]> git.proxmox.com Git - rustc.git/blob - src/libstd/sys/redox/os.rs
New upstream version 1.23.0+dfsg1
[rustc.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_semicolon(b: &u8) -> bool { *b == b';' }
77 let unparsed = unparsed.as_bytes();
78 SplitPaths {
79 iter: unparsed.split(is_semicolon 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 }
212
213 pub fn getpid() -> u32 {
214 syscall::getpid().unwrap() as u32
215 }