]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/redox/os.rs
e38b7b29f4837e1de389bb51722d245ba78c62c7
[rust.git] / src / libstd / sys / redox / os.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Implementation of `std::os` functionality for unix systems
12
13 #![allow(unused_imports)] // lots of cfg code here
14
15 use os::unix::prelude::*;
16
17 use error::Error as StdError;
18 use ffi::{OsString, OsStr};
19 use fmt;
20 use io::{self, Read, Write};
21 use iter;
22 use marker::PhantomData;
23 use mem;
24 use memchr;
25 use path::{self, PathBuf};
26 use ptr;
27 use slice;
28 use str;
29 use sys_common::mutex::Mutex;
30 use sys::{cvt, fd, syscall};
31 use vec;
32
33 const TMPBUF_SZ: usize = 128;
34 static ENV_LOCK: Mutex = Mutex::new();
35
36 extern {
37     #[link_name = "__errno_location"]
38     fn errno_location() -> *mut i32;
39 }
40
41 /// Returns the platform-specific value of errno
42 pub fn errno() -> i32 {
43     unsafe {
44         (*errno_location())
45     }
46 }
47
48 /// Gets a detailed string description for the given error number.
49 pub fn error_string(errno: i32) -> String {
50     if let Some(string) = syscall::STR_ERROR.get(errno as usize) {
51         string.to_string()
52     } else {
53         "unknown error".to_string()
54     }
55 }
56
57 pub fn getcwd() -> io::Result<PathBuf> {
58     let mut buf = [0; 4096];
59     let count = cvt(syscall::getcwd(&mut buf))?;
60     Ok(PathBuf::from(OsString::from_vec(buf[.. count].to_vec())))
61 }
62
63 pub fn chdir(p: &path::Path) -> io::Result<()> {
64     cvt(syscall::chdir(p.to_str().unwrap())).and(Ok(()))
65 }
66
67 pub struct SplitPaths<'a> {
68     iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>,
69                     fn(&'a [u8]) -> PathBuf>,
70 }
71
72 pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
73     fn bytes_to_path(b: &[u8]) -> PathBuf {
74         PathBuf::from(<OsStr as OsStrExt>::from_bytes(b))
75     }
76     fn is_colon(b: &u8) -> bool { *b == b':' }
77     let unparsed = unparsed.as_bytes();
78     SplitPaths {
79         iter: unparsed.split(is_colon as fn(&u8) -> bool)
80                       .map(bytes_to_path as fn(&[u8]) -> PathBuf)
81     }
82 }
83
84 impl<'a> Iterator for SplitPaths<'a> {
85     type Item = PathBuf;
86     fn next(&mut self) -> Option<PathBuf> { self.iter.next() }
87     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
88 }
89
90 #[derive(Debug)]
91 pub struct JoinPathsError;
92
93 pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
94     where I: Iterator<Item=T>, T: AsRef<OsStr>
95 {
96     let mut joined = Vec::new();
97     let sep = b':';
98
99     for (i, path) in paths.enumerate() {
100         let path = path.as_ref().as_bytes();
101         if i > 0 { joined.push(sep) }
102         if path.contains(&sep) {
103             return Err(JoinPathsError)
104         }
105         joined.extend_from_slice(path);
106     }
107     Ok(OsStringExt::from_vec(joined))
108 }
109
110 impl fmt::Display for JoinPathsError {
111     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112         "path segment contains separator `:`".fmt(f)
113     }
114 }
115
116 impl StdError for JoinPathsError {
117     fn description(&self) -> &str { "failed to join paths" }
118 }
119
120 pub fn current_exe() -> io::Result<PathBuf> {
121     use fs::File;
122
123     let mut file = File::open("sys:exe")?;
124
125     let mut path = String::new();
126     file.read_to_string(&mut path)?;
127
128     if path.ends_with('\n') {
129         path.pop();
130     }
131
132     Ok(PathBuf::from(path))
133 }
134
135 pub struct Env {
136     iter: vec::IntoIter<(OsString, OsString)>,
137     _dont_send_or_sync_me: PhantomData<*mut ()>,
138 }
139
140 impl Iterator for Env {
141     type Item = (OsString, OsString);
142     fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() }
143     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
144 }
145
146 /// Returns a vector of (variable, value) byte-vector pairs for all the
147 /// environment variables of the current process.
148 pub fn env() -> Env {
149     let mut variables: Vec<(OsString, OsString)> = Vec::new();
150     if let Ok(mut file) = ::fs::File::open("env:") {
151         let mut string = String::new();
152         if file.read_to_string(&mut string).is_ok() {
153             for line in string.lines() {
154                 let mut parts = line.splitn(2, '=');
155                 if let Some(name) = parts.next() {
156                     let value = parts.next().unwrap_or("");
157                     variables.push((OsString::from(name.to_string()),
158                                     OsString::from(value.to_string())));
159                 }
160             }
161         }
162     }
163     Env { iter: variables.into_iter(), _dont_send_or_sync_me: PhantomData }
164 }
165
166 pub fn getenv(key: &OsStr) -> io::Result<Option<OsString>> {
167     if ! key.is_empty() {
168         if let Ok(mut file) = ::fs::File::open(&("env:".to_owned() + key.to_str().unwrap())) {
169             let mut string = String::new();
170             file.read_to_string(&mut string)?;
171             Ok(Some(OsString::from(string)))
172         } else {
173             Ok(None)
174         }
175     } else {
176         Ok(None)
177     }
178 }
179
180 pub fn setenv(key: &OsStr, value: &OsStr) -> io::Result<()> {
181     if ! key.is_empty() {
182         let mut file = ::fs::File::create(&("env:".to_owned() + key.to_str().unwrap()))?;
183         file.write_all(value.as_bytes())?;
184         file.set_len(value.len() as u64)?;
185     }
186     Ok(())
187 }
188
189 pub fn unsetenv(key: &OsStr) -> io::Result<()> {
190     ::fs::remove_file(&("env:".to_owned() + key.to_str().unwrap()))?;
191     Ok(())
192 }
193
194 pub fn page_size() -> usize {
195     4096
196 }
197
198 pub fn temp_dir() -> PathBuf {
199     ::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| {
200         PathBuf::from("/tmp")
201     })
202 }
203
204 pub fn home_dir() -> Option<PathBuf> {
205     return ::env::var_os("HOME").map(PathBuf::from);
206 }
207
208 pub fn exit(code: i32) -> ! {
209     let _ = syscall::exit(code as usize);
210     unreachable!();
211 }