]>
Commit | Line | Data |
---|---|---|
85aaf69f SL |
1 | // Copyright 2012-2015 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 | //! Inspection and manipulation of the process's environment. | |
12 | //! | |
13 | //! This module contains methods to inspect various aspects such as | |
c1a9b12d | 14 | //! environment variables, process arguments, the current directory, and various |
85aaf69f SL |
15 | //! other important directories. |
16 | ||
c34b1796 | 17 | #![stable(feature = "env", since = "1.0.0")] |
85aaf69f | 18 | |
85aaf69f | 19 | use error::Error; |
c34b1796 | 20 | use ffi::{OsStr, OsString}; |
85aaf69f | 21 | use fmt; |
c34b1796 AL |
22 | use io; |
23 | use path::{Path, PathBuf}; | |
85aaf69f SL |
24 | use sys::os as os_imp; |
25 | ||
d9579d0f | 26 | /// Returns the current working directory as a `PathBuf`. |
85aaf69f SL |
27 | /// |
28 | /// # Errors | |
29 | /// | |
30 | /// Returns an `Err` if the current working directory value is invalid. | |
31 | /// Possible cases: | |
32 | /// | |
33 | /// * Current directory does not exist. | |
34 | /// * There are insufficient permissions to access the current directory. | |
85aaf69f | 35 | /// |
c34b1796 | 36 | /// # Examples |
85aaf69f | 37 | /// |
c34b1796 | 38 | /// ``` |
85aaf69f SL |
39 | /// use std::env; |
40 | /// | |
41 | /// // We assume that we are in a valid directory. | |
42 | /// let p = env::current_dir().unwrap(); | |
43 | /// println!("The current directory is {}", p.display()); | |
44 | /// ``` | |
c34b1796 AL |
45 | #[stable(feature = "env", since = "1.0.0")] |
46 | pub fn current_dir() -> io::Result<PathBuf> { | |
85aaf69f SL |
47 | os_imp::getcwd() |
48 | } | |
49 | ||
50 | /// Changes the current working directory to the specified path, returning | |
51 | /// whether the change was completed successfully or not. | |
52 | /// | |
c34b1796 | 53 | /// # Examples |
85aaf69f | 54 | /// |
c34b1796 | 55 | /// ``` |
85aaf69f | 56 | /// use std::env; |
c34b1796 | 57 | /// use std::path::Path; |
85aaf69f SL |
58 | /// |
59 | /// let root = Path::new("/"); | |
60 | /// assert!(env::set_current_dir(&root).is_ok()); | |
61 | /// println!("Successfully changed working directory to {}!", root.display()); | |
62 | /// ``` | |
c34b1796 | 63 | #[stable(feature = "env", since = "1.0.0")] |
d9579d0f | 64 | pub fn set_current_dir<P: AsRef<Path>>(p: P) -> io::Result<()> { |
c34b1796 | 65 | os_imp::chdir(p.as_ref()) |
85aaf69f SL |
66 | } |
67 | ||
85aaf69f SL |
68 | /// An iterator over a snapshot of the environment variables of this process. |
69 | /// | |
70 | /// This iterator is created through `std::env::vars()` and yields `(String, | |
71 | /// String)` pairs. | |
c34b1796 | 72 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
73 | pub struct Vars { inner: VarsOs } |
74 | ||
75 | /// An iterator over a snapshot of the environment variables of this process. | |
76 | /// | |
77 | /// This iterator is created through `std::env::vars_os()` and yields | |
78 | /// `(OsString, OsString)` pairs. | |
c34b1796 | 79 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
80 | pub struct VarsOs { inner: os_imp::Env } |
81 | ||
82 | /// Returns an iterator of (variable, value) pairs of strings, for all the | |
83 | /// environment variables of the current process. | |
84 | /// | |
85 | /// The returned iterator contains a snapshot of the process's environment | |
9e0c209e | 86 | /// variables at the time of this invocation. Modifications to environment |
85aaf69f SL |
87 | /// variables afterwards will not be reflected in the returned iterator. |
88 | /// | |
89 | /// # Panics | |
90 | /// | |
91 | /// While iterating, the returned iterator will panic if any key or value in the | |
92 | /// environment is not valid unicode. If this is not desired, consider using the | |
93 | /// `env::vars_os` function. | |
94 | /// | |
c34b1796 | 95 | /// # Examples |
85aaf69f | 96 | /// |
c34b1796 | 97 | /// ``` |
85aaf69f SL |
98 | /// use std::env; |
99 | /// | |
100 | /// // We will iterate through the references to the element returned by | |
101 | /// // env::vars(); | |
102 | /// for (key, value) in env::vars() { | |
103 | /// println!("{}: {}", key, value); | |
104 | /// } | |
105 | /// ``` | |
c34b1796 | 106 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
107 | pub fn vars() -> Vars { |
108 | Vars { inner: vars_os() } | |
109 | } | |
110 | ||
111 | /// Returns an iterator of (variable, value) pairs of OS strings, for all the | |
112 | /// environment variables of the current process. | |
113 | /// | |
114 | /// The returned iterator contains a snapshot of the process's environment | |
9e0c209e | 115 | /// variables at the time of this invocation. Modifications to environment |
85aaf69f SL |
116 | /// variables afterwards will not be reflected in the returned iterator. |
117 | /// | |
c34b1796 | 118 | /// # Examples |
85aaf69f | 119 | /// |
c34b1796 | 120 | /// ``` |
85aaf69f SL |
121 | /// use std::env; |
122 | /// | |
123 | /// // We will iterate through the references to the element returned by | |
124 | /// // env::vars_os(); | |
125 | /// for (key, value) in env::vars_os() { | |
126 | /// println!("{:?}: {:?}", key, value); | |
127 | /// } | |
128 | /// ``` | |
c34b1796 | 129 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f | 130 | pub fn vars_os() -> VarsOs { |
85aaf69f SL |
131 | VarsOs { inner: os_imp::env() } |
132 | } | |
133 | ||
c34b1796 | 134 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
135 | impl Iterator for Vars { |
136 | type Item = (String, String); | |
137 | fn next(&mut self) -> Option<(String, String)> { | |
138 | self.inner.next().map(|(a, b)| { | |
139 | (a.into_string().unwrap(), b.into_string().unwrap()) | |
140 | }) | |
141 | } | |
142 | fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } | |
143 | } | |
144 | ||
c34b1796 | 145 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
146 | impl Iterator for VarsOs { |
147 | type Item = (OsString, OsString); | |
148 | fn next(&mut self) -> Option<(OsString, OsString)> { self.inner.next() } | |
149 | fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } | |
150 | } | |
151 | ||
152 | /// Fetches the environment variable `key` from the current process. | |
153 | /// | |
154 | /// The returned result is `Ok(s)` if the environment variable is present and is | |
155 | /// valid unicode. If the environment variable is not present, or it is not | |
156 | /// valid unicode, then `Err` will be returned. | |
157 | /// | |
c34b1796 | 158 | /// # Examples |
85aaf69f | 159 | /// |
c34b1796 | 160 | /// ``` |
85aaf69f SL |
161 | /// use std::env; |
162 | /// | |
163 | /// let key = "HOME"; | |
164 | /// match env::var(key) { | |
165 | /// Ok(val) => println!("{}: {:?}", key, val), | |
166 | /// Err(e) => println!("couldn't interpret {}: {}", key, e), | |
167 | /// } | |
168 | /// ``` | |
c34b1796 | 169 | #[stable(feature = "env", since = "1.0.0")] |
d9579d0f | 170 | pub fn var<K: AsRef<OsStr>>(key: K) -> Result<String, VarError> { |
e9174d1e SL |
171 | _var(key.as_ref()) |
172 | } | |
173 | ||
174 | fn _var(key: &OsStr) -> Result<String, VarError> { | |
85aaf69f SL |
175 | match var_os(key) { |
176 | Some(s) => s.into_string().map_err(VarError::NotUnicode), | |
177 | None => Err(VarError::NotPresent) | |
178 | } | |
179 | } | |
180 | ||
181 | /// Fetches the environment variable `key` from the current process, returning | |
54a0048b | 182 | /// `None` if the variable isn't set. |
85aaf69f | 183 | /// |
c34b1796 | 184 | /// # Examples |
85aaf69f | 185 | /// |
c34b1796 | 186 | /// ``` |
85aaf69f SL |
187 | /// use std::env; |
188 | /// | |
189 | /// let key = "HOME"; | |
190 | /// match env::var_os(key) { | |
191 | /// Some(val) => println!("{}: {:?}", key, val), | |
192 | /// None => println!("{} is not defined in the environment.", key) | |
193 | /// } | |
194 | /// ``` | |
c34b1796 | 195 | #[stable(feature = "env", since = "1.0.0")] |
d9579d0f | 196 | pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> { |
e9174d1e SL |
197 | _var_os(key.as_ref()) |
198 | } | |
199 | ||
200 | fn _var_os(key: &OsStr) -> Option<OsString> { | |
92a42be0 SL |
201 | os_imp::getenv(key).unwrap_or_else(|e| { |
202 | panic!("failed to get environment variable `{:?}`: {}", key, e) | |
203 | }) | |
85aaf69f SL |
204 | } |
205 | ||
206 | /// Possible errors from the `env::var` method. | |
207 | #[derive(Debug, PartialEq, Eq, Clone)] | |
c34b1796 | 208 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
209 | pub enum VarError { |
210 | /// The specified environment variable was not present in the current | |
211 | /// process's environment. | |
c34b1796 | 212 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
213 | NotPresent, |
214 | ||
215 | /// The specified environment variable was found, but it did not contain | |
216 | /// valid unicode data. The found data is returned as a payload of this | |
217 | /// variant. | |
c34b1796 | 218 | #[stable(feature = "env", since = "1.0.0")] |
7453a54e | 219 | NotUnicode(#[stable(feature = "env", since = "1.0.0")] OsString), |
85aaf69f SL |
220 | } |
221 | ||
c34b1796 | 222 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
223 | impl fmt::Display for VarError { |
224 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
225 | match *self { | |
226 | VarError::NotPresent => write!(f, "environment variable not found"), | |
227 | VarError::NotUnicode(ref s) => { | |
228 | write!(f, "environment variable was not valid unicode: {:?}", s) | |
229 | } | |
230 | } | |
231 | } | |
232 | } | |
233 | ||
c34b1796 | 234 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
235 | impl Error for VarError { |
236 | fn description(&self) -> &str { | |
237 | match *self { | |
238 | VarError::NotPresent => "environment variable not found", | |
239 | VarError::NotUnicode(..) => "environment variable was not valid unicode", | |
240 | } | |
241 | } | |
242 | } | |
243 | ||
244 | /// Sets the environment variable `k` to the value `v` for the currently running | |
245 | /// process. | |
246 | /// | |
d9579d0f AL |
247 | /// Note that while concurrent access to environment variables is safe in Rust, |
248 | /// some platforms only expose inherently unsafe non-threadsafe APIs for | |
249 | /// inspecting the environment. As a result extra care needs to be taken when | |
250 | /// auditing calls to unsafe external FFI functions to ensure that any external | |
251 | /// environment accesses are properly synchronized with accesses in Rust. | |
252 | /// | |
253 | /// Discussion of this unsafety on Unix may be found in: | |
254 | /// | |
255 | /// - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188) | |
256 | /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2) | |
257 | /// | |
b039eaaf SL |
258 | /// # Panics |
259 | /// | |
260 | /// This function may panic if `key` is empty, contains an ASCII equals sign | |
261 | /// `'='` or the NUL character `'\0'`, or when the value contains the NUL | |
262 | /// character. | |
263 | /// | |
c34b1796 | 264 | /// # Examples |
85aaf69f | 265 | /// |
c34b1796 | 266 | /// ``` |
85aaf69f SL |
267 | /// use std::env; |
268 | /// | |
269 | /// let key = "KEY"; | |
270 | /// env::set_var(key, "VALUE"); | |
271 | /// assert_eq!(env::var(key), Ok("VALUE".to_string())); | |
272 | /// ``` | |
c34b1796 | 273 | #[stable(feature = "env", since = "1.0.0")] |
d9579d0f | 274 | pub fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(k: K, v: V) { |
e9174d1e SL |
275 | _set_var(k.as_ref(), v.as_ref()) |
276 | } | |
277 | ||
278 | fn _set_var(k: &OsStr, v: &OsStr) { | |
92a42be0 SL |
279 | os_imp::setenv(k, v).unwrap_or_else(|e| { |
280 | panic!("failed to set environment variable `{:?}` to `{:?}`: {}", | |
281 | k, v, e) | |
282 | }) | |
85aaf69f SL |
283 | } |
284 | ||
9346a6ac | 285 | /// Removes an environment variable from the environment of the currently running process. |
c34b1796 | 286 | /// |
d9579d0f AL |
287 | /// Note that while concurrent access to environment variables is safe in Rust, |
288 | /// some platforms only expose inherently unsafe non-threadsafe APIs for | |
289 | /// inspecting the environment. As a result extra care needs to be taken when | |
290 | /// auditing calls to unsafe external FFI functions to ensure that any external | |
291 | /// environment accesses are properly synchronized with accesses in Rust. | |
292 | /// | |
293 | /// Discussion of this unsafety on Unix may be found in: | |
294 | /// | |
295 | /// - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188) | |
296 | /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2) | |
297 | /// | |
b039eaaf SL |
298 | /// # Panics |
299 | /// | |
300 | /// This function may panic if `key` is empty, contains an ASCII equals sign | |
301 | /// `'='` or the NUL character `'\0'`, or when the value contains the NUL | |
302 | /// character. | |
303 | /// | |
c34b1796 AL |
304 | /// # Examples |
305 | /// | |
306 | /// ``` | |
307 | /// use std::env; | |
308 | /// | |
309 | /// let key = "KEY"; | |
310 | /// env::set_var(key, "VALUE"); | |
311 | /// assert_eq!(env::var(key), Ok("VALUE".to_string())); | |
312 | /// | |
313 | /// env::remove_var(key); | |
314 | /// assert!(env::var(key).is_err()); | |
315 | /// ``` | |
316 | #[stable(feature = "env", since = "1.0.0")] | |
d9579d0f | 317 | pub fn remove_var<K: AsRef<OsStr>>(k: K) { |
e9174d1e SL |
318 | _remove_var(k.as_ref()) |
319 | } | |
320 | ||
321 | fn _remove_var(k: &OsStr) { | |
92a42be0 SL |
322 | os_imp::unsetenv(k).unwrap_or_else(|e| { |
323 | panic!("failed to remove environment variable `{:?}`: {}", k, e) | |
324 | }) | |
85aaf69f SL |
325 | } |
326 | ||
92a42be0 | 327 | /// An iterator over `PathBuf` instances for parsing an environment variable |
85aaf69f SL |
328 | /// according to platform-specific conventions. |
329 | /// | |
330 | /// This structure is returned from `std::env::split_paths`. | |
c34b1796 | 331 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
332 | pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> } |
333 | ||
334 | /// Parses input according to platform conventions for the `PATH` | |
335 | /// environment variable. | |
336 | /// | |
337 | /// Returns an iterator over the paths contained in `unparsed`. | |
338 | /// | |
c34b1796 | 339 | /// # Examples |
85aaf69f | 340 | /// |
c34b1796 | 341 | /// ``` |
85aaf69f SL |
342 | /// use std::env; |
343 | /// | |
344 | /// let key = "PATH"; | |
345 | /// match env::var_os(key) { | |
346 | /// Some(paths) => { | |
347 | /// for path in env::split_paths(&paths) { | |
348 | /// println!("'{}'", path.display()); | |
349 | /// } | |
350 | /// } | |
351 | /// None => println!("{} is not defined in the environment.", key) | |
352 | /// } | |
353 | /// ``` | |
c34b1796 AL |
354 | #[stable(feature = "env", since = "1.0.0")] |
355 | pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths { | |
356 | SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) } | |
85aaf69f SL |
357 | } |
358 | ||
c34b1796 | 359 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f | 360 | impl<'a> Iterator for SplitPaths<'a> { |
c34b1796 AL |
361 | type Item = PathBuf; |
362 | fn next(&mut self) -> Option<PathBuf> { self.inner.next() } | |
85aaf69f SL |
363 | fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } |
364 | } | |
365 | ||
366 | /// Error type returned from `std::env::join_paths` when paths fail to be | |
367 | /// joined. | |
368 | #[derive(Debug)] | |
c34b1796 | 369 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
370 | pub struct JoinPathsError { |
371 | inner: os_imp::JoinPathsError | |
372 | } | |
373 | ||
374 | /// Joins a collection of `Path`s appropriately for the `PATH` | |
375 | /// environment variable. | |
376 | /// | |
377 | /// Returns an `OsString` on success. | |
378 | /// | |
379 | /// Returns an `Err` (containing an error message) if one of the input | |
380 | /// `Path`s contains an invalid character for constructing the `PATH` | |
381 | /// variable (a double quote on Windows or a colon on Unix). | |
382 | /// | |
c34b1796 | 383 | /// # Examples |
85aaf69f | 384 | /// |
c34b1796 | 385 | /// ``` |
85aaf69f | 386 | /// use std::env; |
c34b1796 | 387 | /// use std::path::PathBuf; |
85aaf69f SL |
388 | /// |
389 | /// if let Some(path) = env::var_os("PATH") { | |
390 | /// let mut paths = env::split_paths(&path).collect::<Vec<_>>(); | |
c34b1796 | 391 | /// paths.push(PathBuf::from("/home/xyz/bin")); |
62682a34 | 392 | /// let new_path = env::join_paths(paths).unwrap(); |
85aaf69f SL |
393 | /// env::set_var("PATH", &new_path); |
394 | /// } | |
395 | /// ``` | |
c34b1796 | 396 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f | 397 | pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError> |
c34b1796 | 398 | where I: IntoIterator<Item=T>, T: AsRef<OsStr> |
85aaf69f | 399 | { |
c34b1796 | 400 | os_imp::join_paths(paths.into_iter()).map_err(|e| { |
85aaf69f SL |
401 | JoinPathsError { inner: e } |
402 | }) | |
403 | } | |
404 | ||
c34b1796 | 405 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
406 | impl fmt::Display for JoinPathsError { |
407 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
408 | self.inner.fmt(f) | |
409 | } | |
410 | } | |
411 | ||
c34b1796 | 412 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
413 | impl Error for JoinPathsError { |
414 | fn description(&self) -> &str { self.inner.description() } | |
415 | } | |
416 | ||
54a0048b | 417 | /// Returns the path of the current user's home directory if known. |
85aaf69f SL |
418 | /// |
419 | /// # Unix | |
420 | /// | |
421 | /// Returns the value of the 'HOME' environment variable if it is set | |
92a42be0 SL |
422 | /// and not equal to the empty string. Otherwise, it tries to determine the |
423 | /// home directory by invoking the `getpwuid_r` function on the UID of the | |
424 | /// current user. | |
85aaf69f SL |
425 | /// |
426 | /// # Windows | |
427 | /// | |
428 | /// Returns the value of the 'HOME' environment variable if it is | |
429 | /// set and not equal to the empty string. Otherwise, returns the value of the | |
430 | /// 'USERPROFILE' environment variable if it is set and not equal to the empty | |
b039eaaf SL |
431 | /// string. If both do not exist, [`GetUserProfileDirectory`][msdn] is used to |
432 | /// return the appropriate path. | |
433 | /// | |
434 | /// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/bb762280(v=vs.85).aspx | |
85aaf69f | 435 | /// |
c34b1796 | 436 | /// # Examples |
85aaf69f | 437 | /// |
c34b1796 | 438 | /// ``` |
85aaf69f SL |
439 | /// use std::env; |
440 | /// | |
441 | /// match env::home_dir() { | |
7453a54e SL |
442 | /// Some(path) => println!("{}", path.display()), |
443 | /// None => println!("Impossible to get your home dir!"), | |
85aaf69f SL |
444 | /// } |
445 | /// ``` | |
c34b1796 AL |
446 | #[stable(feature = "env", since = "1.0.0")] |
447 | pub fn home_dir() -> Option<PathBuf> { | |
85aaf69f SL |
448 | os_imp::home_dir() |
449 | } | |
450 | ||
54a0048b | 451 | /// Returns the path of a temporary directory. |
85aaf69f | 452 | /// |
a7813a04 XL |
453 | /// On Unix, returns the value of the `TMPDIR` environment variable if it is |
454 | /// set, otherwise for non-Android it returns `/tmp`. If Android, since there | |
455 | /// is no global temporary folder (it is usually allocated per-app), it returns | |
456 | /// `/data/local/tmp`. | |
457 | /// | |
458 | /// On Windows, returns the value of, in order, the `TMP`, `TEMP`, | |
459 | /// `USERPROFILE` environment variable if any are set and not the empty | |
460 | /// string. Otherwise, `temp_dir` returns the path of the Windows directory. | |
461 | /// This behavior is identical to that of [`GetTempPath`][msdn], which this | |
462 | /// function uses internally. | |
b039eaaf SL |
463 | /// |
464 | /// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992(v=vs.85).aspx | |
c34b1796 AL |
465 | /// |
466 | /// ``` | |
467 | /// use std::env; | |
468 | /// use std::fs::File; | |
469 | /// | |
470 | /// # fn foo() -> std::io::Result<()> { | |
471 | /// let mut dir = env::temp_dir(); | |
472 | /// dir.push("foo.txt"); | |
473 | /// | |
474 | /// let f = try!(File::create(dir)); | |
475 | /// # Ok(()) | |
476 | /// # } | |
477 | /// ``` | |
478 | #[stable(feature = "env", since = "1.0.0")] | |
479 | pub fn temp_dir() -> PathBuf { | |
85aaf69f SL |
480 | os_imp::temp_dir() |
481 | } | |
482 | ||
54a0048b | 483 | /// Returns the full filesystem path of the current running executable. |
85aaf69f | 484 | /// |
54a0048b | 485 | /// The path returned is not necessarily a "real path" of the executable as |
85aaf69f SL |
486 | /// there may be intermediate symlinks. |
487 | /// | |
488 | /// # Errors | |
489 | /// | |
54a0048b | 490 | /// Acquiring the path of the current executable is a platform-specific operation |
85aaf69f | 491 | /// that can fail for a good number of reasons. Some errors can include, but not |
7453a54e | 492 | /// be limited to, filesystem operations failing or general syscall failures. |
85aaf69f | 493 | /// |
5bcae85e SL |
494 | /// # Security |
495 | /// | |
496 | /// The output of this function should not be used in anything that might have | |
497 | /// security implications. For example: | |
498 | /// | |
499 | /// ``` | |
500 | /// fn main() { | |
501 | /// println!("{:?}", std::env::current_exe()); | |
502 | /// } | |
503 | /// ``` | |
504 | /// | |
505 | /// On Linux systems, if this is compiled as `foo`: | |
506 | /// | |
507 | /// ```bash | |
508 | /// $ rustc foo.rs | |
509 | /// $ ./foo | |
510 | /// Ok("/home/alex/foo") | |
511 | /// ``` | |
512 | /// | |
513 | /// And you make a symbolic link of the program: | |
514 | /// | |
515 | /// ```bash | |
516 | /// $ ln foo bar | |
517 | /// ``` | |
518 | /// | |
519 | /// When you run it, you won't get the original executable, you'll get the | |
520 | /// symlink: | |
521 | /// | |
522 | /// ```bash | |
523 | /// $ ./bar | |
524 | /// Ok("/home/alex/bar") | |
525 | /// ``` | |
526 | /// | |
527 | /// This sort of behavior has been known to [lead to privilege escalation] when | |
528 | /// used incorrectly, for example. | |
529 | /// | |
530 | /// [lead to privilege escalation]: http://securityvulns.com/Wdocument183.html | |
531 | /// | |
85aaf69f SL |
532 | /// # Examples |
533 | /// | |
c34b1796 | 534 | /// ``` |
85aaf69f SL |
535 | /// use std::env; |
536 | /// | |
537 | /// match env::current_exe() { | |
538 | /// Ok(exe_path) => println!("Path of this executable is: {}", | |
539 | /// exe_path.display()), | |
540 | /// Err(e) => println!("failed to get current exe path: {}", e), | |
541 | /// }; | |
542 | /// ``` | |
c34b1796 AL |
543 | #[stable(feature = "env", since = "1.0.0")] |
544 | pub fn current_exe() -> io::Result<PathBuf> { | |
85aaf69f SL |
545 | os_imp::current_exe() |
546 | } | |
547 | ||
c34b1796 | 548 | /// An iterator over the arguments of a process, yielding a `String` value |
85aaf69f SL |
549 | /// for each argument. |
550 | /// | |
551 | /// This structure is created through the `std::env::args` method. | |
c34b1796 | 552 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
553 | pub struct Args { inner: ArgsOs } |
554 | ||
555 | /// An iterator over the arguments of a process, yielding an `OsString` value | |
556 | /// for each argument. | |
557 | /// | |
558 | /// This structure is created through the `std::env::args_os` method. | |
c34b1796 | 559 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
560 | pub struct ArgsOs { inner: os_imp::Args } |
561 | ||
562 | /// Returns the arguments which this program was started with (normally passed | |
563 | /// via the command line). | |
564 | /// | |
54a0048b | 565 | /// The first element is traditionally the path of the executable, but it can be |
7453a54e | 566 | /// set to arbitrary text, and may not even exist. This means this property should |
85aaf69f SL |
567 | /// not be relied upon for security purposes. |
568 | /// | |
569 | /// # Panics | |
570 | /// | |
571 | /// The returned iterator will panic during iteration if any argument to the | |
7453a54e | 572 | /// process is not valid unicode. If this is not desired, |
85aaf69f SL |
573 | /// use the `args_os` function instead. |
574 | /// | |
c34b1796 | 575 | /// # Examples |
85aaf69f | 576 | /// |
c34b1796 | 577 | /// ``` |
85aaf69f SL |
578 | /// use std::env; |
579 | /// | |
580 | /// // Prints each argument on a separate line | |
581 | /// for argument in env::args() { | |
582 | /// println!("{}", argument); | |
583 | /// } | |
584 | /// ``` | |
c34b1796 | 585 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
586 | pub fn args() -> Args { |
587 | Args { inner: args_os() } | |
588 | } | |
589 | ||
590 | /// Returns the arguments which this program was started with (normally passed | |
591 | /// via the command line). | |
592 | /// | |
54a0048b | 593 | /// The first element is traditionally the path of the executable, but it can be |
85aaf69f SL |
594 | /// set to arbitrary text, and it may not even exist, so this property should |
595 | /// not be relied upon for security purposes. | |
596 | /// | |
c34b1796 | 597 | /// # Examples |
85aaf69f | 598 | /// |
c34b1796 | 599 | /// ``` |
85aaf69f SL |
600 | /// use std::env; |
601 | /// | |
602 | /// // Prints each argument on a separate line | |
603 | /// for argument in env::args_os() { | |
604 | /// println!("{:?}", argument); | |
605 | /// } | |
606 | /// ``` | |
c34b1796 | 607 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
608 | pub fn args_os() -> ArgsOs { |
609 | ArgsOs { inner: os_imp::args() } | |
610 | } | |
611 | ||
c34b1796 | 612 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
613 | impl Iterator for Args { |
614 | type Item = String; | |
615 | fn next(&mut self) -> Option<String> { | |
616 | self.inner.next().map(|s| s.into_string().unwrap()) | |
617 | } | |
618 | fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } | |
619 | } | |
620 | ||
c34b1796 | 621 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
622 | impl ExactSizeIterator for Args { |
623 | fn len(&self) -> usize { self.inner.len() } | |
624 | } | |
625 | ||
5bcae85e SL |
626 | #[stable(feature = "env_iterators", since = "1.11.0")] |
627 | impl DoubleEndedIterator for Args { | |
628 | fn next_back(&mut self) -> Option<String> { | |
629 | self.inner.next_back().map(|s| s.into_string().unwrap()) | |
630 | } | |
631 | } | |
632 | ||
c34b1796 | 633 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
634 | impl Iterator for ArgsOs { |
635 | type Item = OsString; | |
636 | fn next(&mut self) -> Option<OsString> { self.inner.next() } | |
637 | fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } | |
638 | } | |
639 | ||
c34b1796 | 640 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f SL |
641 | impl ExactSizeIterator for ArgsOs { |
642 | fn len(&self) -> usize { self.inner.len() } | |
643 | } | |
644 | ||
5bcae85e SL |
645 | #[stable(feature = "env_iterators", since = "1.11.0")] |
646 | impl DoubleEndedIterator for ArgsOs { | |
647 | fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() } | |
648 | } | |
85aaf69f | 649 | /// Constants associated with the current target |
c34b1796 | 650 | #[stable(feature = "env", since = "1.0.0")] |
85aaf69f | 651 | pub mod consts { |
7453a54e | 652 | /// A string describing the architecture of the CPU that is currently |
c34b1796 | 653 | /// in use. |
62682a34 SL |
654 | /// |
655 | /// Some possible values: | |
656 | /// | |
657 | /// - x86 | |
658 | /// - x86_64 | |
659 | /// - arm | |
660 | /// - aarch64 | |
661 | /// - mips | |
9e0c209e | 662 | /// - mips64 |
62682a34 | 663 | /// - powerpc |
9cc50fc6 | 664 | /// - powerpc64 |
9e0c209e | 665 | /// - s390x |
c34b1796 AL |
666 | #[stable(feature = "env", since = "1.0.0")] |
667 | pub const ARCH: &'static str = super::arch::ARCH; | |
85aaf69f | 668 | |
54a0048b | 669 | /// The family of the operating system. Example value is `unix`. |
62682a34 SL |
670 | /// |
671 | /// Some possible values: | |
672 | /// | |
673 | /// - unix | |
674 | /// - windows | |
c34b1796 AL |
675 | #[stable(feature = "env", since = "1.0.0")] |
676 | pub const FAMILY: &'static str = super::os::FAMILY; | |
85aaf69f | 677 | |
54a0048b SL |
678 | /// A string describing the specific operating system in use. |
679 | /// Example value is `linux`. | |
62682a34 SL |
680 | /// |
681 | /// Some possible values: | |
682 | /// | |
683 | /// - linux | |
684 | /// - macos | |
685 | /// - ios | |
686 | /// - freebsd | |
687 | /// - dragonfly | |
688 | /// - bitrig | |
c1a9b12d | 689 | /// - netbsd |
62682a34 | 690 | /// - openbsd |
7453a54e | 691 | /// - solaris |
62682a34 SL |
692 | /// - android |
693 | /// - windows | |
c34b1796 AL |
694 | #[stable(feature = "env", since = "1.0.0")] |
695 | pub const OS: &'static str = super::os::OS; | |
85aaf69f SL |
696 | |
697 | /// Specifies the filename prefix used for shared libraries on this | |
54a0048b | 698 | /// platform. Example value is `lib`. |
62682a34 SL |
699 | /// |
700 | /// Some possible values: | |
701 | /// | |
702 | /// - lib | |
703 | /// - `""` (an empty string) | |
c34b1796 AL |
704 | #[stable(feature = "env", since = "1.0.0")] |
705 | pub const DLL_PREFIX: &'static str = super::os::DLL_PREFIX; | |
85aaf69f SL |
706 | |
707 | /// Specifies the filename suffix used for shared libraries on this | |
54a0048b | 708 | /// platform. Example value is `.so`. |
62682a34 SL |
709 | /// |
710 | /// Some possible values: | |
711 | /// | |
712 | /// - .so | |
713 | /// - .dylib | |
714 | /// - .dll | |
c34b1796 AL |
715 | #[stable(feature = "env", since = "1.0.0")] |
716 | pub const DLL_SUFFIX: &'static str = super::os::DLL_SUFFIX; | |
85aaf69f SL |
717 | |
718 | /// Specifies the file extension used for shared libraries on this | |
54a0048b | 719 | /// platform that goes after the dot. Example value is `so`. |
62682a34 SL |
720 | /// |
721 | /// Some possible values: | |
722 | /// | |
92a42be0 SL |
723 | /// - so |
724 | /// - dylib | |
725 | /// - dll | |
c34b1796 AL |
726 | #[stable(feature = "env", since = "1.0.0")] |
727 | pub const DLL_EXTENSION: &'static str = super::os::DLL_EXTENSION; | |
85aaf69f SL |
728 | |
729 | /// Specifies the filename suffix used for executable binaries on this | |
54a0048b | 730 | /// platform. Example value is `.exe`. |
62682a34 SL |
731 | /// |
732 | /// Some possible values: | |
733 | /// | |
92a42be0 SL |
734 | /// - .exe |
735 | /// - .nexe | |
736 | /// - .pexe | |
62682a34 | 737 | /// - `""` (an empty string) |
c34b1796 AL |
738 | #[stable(feature = "env", since = "1.0.0")] |
739 | pub const EXE_SUFFIX: &'static str = super::os::EXE_SUFFIX; | |
85aaf69f SL |
740 | |
741 | /// Specifies the file extension, if any, used for executable binaries | |
54a0048b | 742 | /// on this platform. Example value is `exe`. |
62682a34 SL |
743 | /// |
744 | /// Some possible values: | |
745 | /// | |
746 | /// - exe | |
747 | /// - `""` (an empty string) | |
c34b1796 AL |
748 | #[stable(feature = "env", since = "1.0.0")] |
749 | pub const EXE_EXTENSION: &'static str = super::os::EXE_EXTENSION; | |
750 | ||
751 | } | |
752 | ||
753 | #[cfg(target_os = "linux")] | |
754 | mod os { | |
755 | pub const FAMILY: &'static str = "unix"; | |
756 | pub const OS: &'static str = "linux"; | |
757 | pub const DLL_PREFIX: &'static str = "lib"; | |
758 | pub const DLL_SUFFIX: &'static str = ".so"; | |
759 | pub const DLL_EXTENSION: &'static str = "so"; | |
760 | pub const EXE_SUFFIX: &'static str = ""; | |
85aaf69f SL |
761 | pub const EXE_EXTENSION: &'static str = ""; |
762 | } | |
763 | ||
85aaf69f | 764 | #[cfg(target_os = "macos")] |
c34b1796 | 765 | mod os { |
85aaf69f | 766 | pub const FAMILY: &'static str = "unix"; |
85aaf69f | 767 | pub const OS: &'static str = "macos"; |
85aaf69f | 768 | pub const DLL_PREFIX: &'static str = "lib"; |
85aaf69f | 769 | pub const DLL_SUFFIX: &'static str = ".dylib"; |
85aaf69f | 770 | pub const DLL_EXTENSION: &'static str = "dylib"; |
85aaf69f | 771 | pub const EXE_SUFFIX: &'static str = ""; |
85aaf69f SL |
772 | pub const EXE_EXTENSION: &'static str = ""; |
773 | } | |
774 | ||
85aaf69f | 775 | #[cfg(target_os = "ios")] |
c34b1796 | 776 | mod os { |
85aaf69f | 777 | pub const FAMILY: &'static str = "unix"; |
85aaf69f | 778 | pub const OS: &'static str = "ios"; |
c34b1796 AL |
779 | pub const DLL_PREFIX: &'static str = "lib"; |
780 | pub const DLL_SUFFIX: &'static str = ".dylib"; | |
781 | pub const DLL_EXTENSION: &'static str = "dylib"; | |
85aaf69f | 782 | pub const EXE_SUFFIX: &'static str = ""; |
85aaf69f SL |
783 | pub const EXE_EXTENSION: &'static str = ""; |
784 | } | |
785 | ||
85aaf69f | 786 | #[cfg(target_os = "freebsd")] |
c34b1796 | 787 | mod os { |
85aaf69f | 788 | pub const FAMILY: &'static str = "unix"; |
85aaf69f | 789 | pub const OS: &'static str = "freebsd"; |
85aaf69f | 790 | pub const DLL_PREFIX: &'static str = "lib"; |
85aaf69f | 791 | pub const DLL_SUFFIX: &'static str = ".so"; |
85aaf69f | 792 | pub const DLL_EXTENSION: &'static str = "so"; |
85aaf69f | 793 | pub const EXE_SUFFIX: &'static str = ""; |
85aaf69f SL |
794 | pub const EXE_EXTENSION: &'static str = ""; |
795 | } | |
796 | ||
85aaf69f | 797 | #[cfg(target_os = "dragonfly")] |
c34b1796 | 798 | mod os { |
85aaf69f | 799 | pub const FAMILY: &'static str = "unix"; |
85aaf69f | 800 | pub const OS: &'static str = "dragonfly"; |
85aaf69f | 801 | pub const DLL_PREFIX: &'static str = "lib"; |
85aaf69f | 802 | pub const DLL_SUFFIX: &'static str = ".so"; |
85aaf69f | 803 | pub const DLL_EXTENSION: &'static str = "so"; |
85aaf69f | 804 | pub const EXE_SUFFIX: &'static str = ""; |
c34b1796 AL |
805 | pub const EXE_EXTENSION: &'static str = ""; |
806 | } | |
85aaf69f | 807 | |
c34b1796 AL |
808 | #[cfg(target_os = "bitrig")] |
809 | mod os { | |
810 | pub const FAMILY: &'static str = "unix"; | |
811 | pub const OS: &'static str = "bitrig"; | |
812 | pub const DLL_PREFIX: &'static str = "lib"; | |
813 | pub const DLL_SUFFIX: &'static str = ".so"; | |
814 | pub const DLL_EXTENSION: &'static str = "so"; | |
815 | pub const EXE_SUFFIX: &'static str = ""; | |
85aaf69f SL |
816 | pub const EXE_EXTENSION: &'static str = ""; |
817 | } | |
818 | ||
c1a9b12d SL |
819 | #[cfg(target_os = "netbsd")] |
820 | mod os { | |
821 | pub const FAMILY: &'static str = "unix"; | |
822 | pub const OS: &'static str = "netbsd"; | |
823 | pub const DLL_PREFIX: &'static str = "lib"; | |
824 | pub const DLL_SUFFIX: &'static str = ".so"; | |
825 | pub const DLL_EXTENSION: &'static str = "so"; | |
826 | pub const EXE_SUFFIX: &'static str = ""; | |
827 | pub const EXE_EXTENSION: &'static str = ""; | |
828 | } | |
829 | ||
85aaf69f | 830 | #[cfg(target_os = "openbsd")] |
c34b1796 | 831 | mod os { |
85aaf69f | 832 | pub const FAMILY: &'static str = "unix"; |
85aaf69f | 833 | pub const OS: &'static str = "openbsd"; |
85aaf69f | 834 | pub const DLL_PREFIX: &'static str = "lib"; |
85aaf69f | 835 | pub const DLL_SUFFIX: &'static str = ".so"; |
85aaf69f | 836 | pub const DLL_EXTENSION: &'static str = "so"; |
85aaf69f | 837 | pub const EXE_SUFFIX: &'static str = ""; |
85aaf69f SL |
838 | pub const EXE_EXTENSION: &'static str = ""; |
839 | } | |
840 | ||
85aaf69f | 841 | #[cfg(target_os = "android")] |
c34b1796 | 842 | mod os { |
85aaf69f | 843 | pub const FAMILY: &'static str = "unix"; |
85aaf69f | 844 | pub const OS: &'static str = "android"; |
85aaf69f | 845 | pub const DLL_PREFIX: &'static str = "lib"; |
85aaf69f | 846 | pub const DLL_SUFFIX: &'static str = ".so"; |
85aaf69f | 847 | pub const DLL_EXTENSION: &'static str = "so"; |
85aaf69f | 848 | pub const EXE_SUFFIX: &'static str = ""; |
85aaf69f SL |
849 | pub const EXE_EXTENSION: &'static str = ""; |
850 | } | |
851 | ||
7453a54e SL |
852 | #[cfg(target_os = "solaris")] |
853 | mod os { | |
854 | pub const FAMILY: &'static str = "unix"; | |
855 | pub const OS: &'static str = "solaris"; | |
856 | pub const DLL_PREFIX: &'static str = "lib"; | |
857 | pub const DLL_SUFFIX: &'static str = ".so"; | |
858 | pub const DLL_EXTENSION: &'static str = "so"; | |
859 | pub const EXE_SUFFIX: &'static str = ""; | |
860 | pub const EXE_EXTENSION: &'static str = ""; | |
861 | } | |
862 | ||
85aaf69f | 863 | #[cfg(target_os = "windows")] |
c34b1796 | 864 | mod os { |
85aaf69f | 865 | pub const FAMILY: &'static str = "windows"; |
85aaf69f | 866 | pub const OS: &'static str = "windows"; |
85aaf69f | 867 | pub const DLL_PREFIX: &'static str = ""; |
85aaf69f | 868 | pub const DLL_SUFFIX: &'static str = ".dll"; |
85aaf69f | 869 | pub const DLL_EXTENSION: &'static str = "dll"; |
85aaf69f | 870 | pub const EXE_SUFFIX: &'static str = ".exe"; |
85aaf69f SL |
871 | pub const EXE_EXTENSION: &'static str = "exe"; |
872 | } | |
873 | ||
92a42be0 SL |
874 | #[cfg(all(target_os = "nacl", not(target_arch = "le32")))] |
875 | mod os { | |
876 | pub const FAMILY: &'static str = "unix"; | |
877 | pub const OS: &'static str = "nacl"; | |
878 | pub const DLL_PREFIX: &'static str = "lib"; | |
879 | pub const DLL_SUFFIX: &'static str = ".so"; | |
880 | pub const DLL_EXTENSION: &'static str = "so"; | |
881 | pub const EXE_SUFFIX: &'static str = ".nexe"; | |
882 | pub const EXE_EXTENSION: &'static str = "nexe"; | |
883 | } | |
884 | #[cfg(all(target_os = "nacl", target_arch = "le32"))] | |
885 | mod os { | |
886 | pub const FAMILY: &'static str = "unix"; | |
887 | pub const OS: &'static str = "pnacl"; | |
888 | pub const DLL_PREFIX: &'static str = "lib"; | |
889 | pub const DLL_SUFFIX: &'static str = ".pso"; | |
890 | pub const DLL_EXTENSION: &'static str = "pso"; | |
891 | pub const EXE_SUFFIX: &'static str = ".pexe"; | |
892 | pub const EXE_EXTENSION: &'static str = "pexe"; | |
893 | } | |
894 | ||
7453a54e SL |
895 | #[cfg(target_os = "emscripten")] |
896 | mod os { | |
897 | pub const FAMILY: &'static str = "unix"; | |
898 | pub const OS: &'static str = "emscripten"; | |
899 | pub const DLL_PREFIX: &'static str = "lib"; | |
900 | pub const DLL_SUFFIX: &'static str = ".so"; | |
901 | pub const DLL_EXTENSION: &'static str = "so"; | |
902 | pub const EXE_SUFFIX: &'static str = ".js"; | |
903 | pub const EXE_EXTENSION: &'static str = "js"; | |
904 | } | |
905 | ||
9e0c209e SL |
906 | #[cfg(target_os = "haiku")] |
907 | mod os { | |
908 | pub const FAMILY: &'static str = "unix"; | |
909 | pub const OS: &'static str = "haiku"; | |
910 | pub const DLL_PREFIX: &'static str = "lib"; | |
911 | pub const DLL_SUFFIX: &'static str = ".so"; | |
912 | pub const DLL_EXTENSION: &'static str = "so"; | |
913 | pub const EXE_SUFFIX: &'static str = ""; | |
914 | pub const EXE_EXTENSION: &'static str = ""; | |
915 | } | |
916 | ||
85aaf69f | 917 | #[cfg(target_arch = "x86")] |
c34b1796 | 918 | mod arch { |
85aaf69f SL |
919 | pub const ARCH: &'static str = "x86"; |
920 | } | |
921 | ||
922 | #[cfg(target_arch = "x86_64")] | |
c34b1796 | 923 | mod arch { |
85aaf69f SL |
924 | pub const ARCH: &'static str = "x86_64"; |
925 | } | |
926 | ||
927 | #[cfg(target_arch = "arm")] | |
c34b1796 | 928 | mod arch { |
85aaf69f SL |
929 | pub const ARCH: &'static str = "arm"; |
930 | } | |
931 | ||
932 | #[cfg(target_arch = "aarch64")] | |
c34b1796 | 933 | mod arch { |
85aaf69f SL |
934 | pub const ARCH: &'static str = "aarch64"; |
935 | } | |
936 | ||
937 | #[cfg(target_arch = "mips")] | |
c34b1796 | 938 | mod arch { |
85aaf69f SL |
939 | pub const ARCH: &'static str = "mips"; |
940 | } | |
941 | ||
9e0c209e SL |
942 | #[cfg(target_arch = "mips64")] |
943 | mod arch { | |
944 | pub const ARCH: &'static str = "mips64"; | |
945 | } | |
946 | ||
85aaf69f | 947 | #[cfg(target_arch = "powerpc")] |
c34b1796 | 948 | mod arch { |
85aaf69f SL |
949 | pub const ARCH: &'static str = "powerpc"; |
950 | } | |
951 | ||
9cc50fc6 SL |
952 | #[cfg(target_arch = "powerpc64")] |
953 | mod arch { | |
954 | pub const ARCH: &'static str = "powerpc64"; | |
955 | } | |
956 | ||
9e0c209e SL |
957 | #[cfg(target_arch = "s390x")] |
958 | mod arch { | |
959 | pub const ARCH: &'static str = "s390x"; | |
960 | } | |
961 | ||
7453a54e | 962 | #[cfg(target_arch = "le32")] |
9cc50fc6 | 963 | mod arch { |
7453a54e | 964 | pub const ARCH: &'static str = "le32"; |
9cc50fc6 SL |
965 | } |
966 | ||
7453a54e | 967 | #[cfg(target_arch = "asmjs")] |
92a42be0 | 968 | mod arch { |
7453a54e | 969 | pub const ARCH: &'static str = "asmjs"; |
92a42be0 SL |
970 | } |
971 | ||
85aaf69f SL |
972 | #[cfg(test)] |
973 | mod tests { | |
85aaf69f | 974 | use super::*; |
c34b1796 | 975 | |
85aaf69f SL |
976 | use iter::repeat; |
977 | use rand::{self, Rng}; | |
978 | use ffi::{OsString, OsStr}; | |
c34b1796 | 979 | use path::{Path, PathBuf}; |
85aaf69f SL |
980 | |
981 | fn make_rand_name() -> OsString { | |
982 | let mut rng = rand::thread_rng(); | |
983 | let n = format!("TEST{}", rng.gen_ascii_chars().take(10) | |
984 | .collect::<String>()); | |
c34b1796 | 985 | let n = OsString::from(n); |
85aaf69f SL |
986 | assert!(var_os(&n).is_none()); |
987 | n | |
988 | } | |
989 | ||
990 | fn eq(a: Option<OsString>, b: Option<&str>) { | |
9346a6ac | 991 | assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s)); |
85aaf69f SL |
992 | } |
993 | ||
994 | #[test] | |
995 | fn test_set_var() { | |
996 | let n = make_rand_name(); | |
997 | set_var(&n, "VALUE"); | |
998 | eq(var_os(&n), Some("VALUE")); | |
999 | } | |
1000 | ||
1001 | #[test] | |
1002 | fn test_remove_var() { | |
1003 | let n = make_rand_name(); | |
1004 | set_var(&n, "VALUE"); | |
1005 | remove_var(&n); | |
1006 | eq(var_os(&n), None); | |
1007 | } | |
1008 | ||
1009 | #[test] | |
1010 | fn test_set_var_overwrite() { | |
1011 | let n = make_rand_name(); | |
1012 | set_var(&n, "1"); | |
1013 | set_var(&n, "2"); | |
1014 | eq(var_os(&n), Some("2")); | |
1015 | set_var(&n, ""); | |
1016 | eq(var_os(&n), Some("")); | |
1017 | } | |
1018 | ||
1019 | #[test] | |
1020 | fn test_var_big() { | |
1021 | let mut s = "".to_string(); | |
1022 | let mut i = 0; | |
1023 | while i < 100 { | |
1024 | s.push_str("aaaaaaaaaa"); | |
1025 | i += 1; | |
1026 | } | |
1027 | let n = make_rand_name(); | |
c34b1796 AL |
1028 | set_var(&n, &s); |
1029 | eq(var_os(&n), Some(&s)); | |
85aaf69f SL |
1030 | } |
1031 | ||
1032 | #[test] | |
1033 | fn test_self_exe_path() { | |
1034 | let path = current_exe(); | |
1035 | assert!(path.is_ok()); | |
1036 | let path = path.unwrap(); | |
1037 | ||
1038 | // Hard to test this function | |
1039 | assert!(path.is_absolute()); | |
1040 | } | |
1041 | ||
1042 | #[test] | |
1043 | fn test_env_set_get_huge() { | |
1044 | let n = make_rand_name(); | |
1045 | let s = repeat("x").take(10000).collect::<String>(); | |
1046 | set_var(&n, &s); | |
c34b1796 | 1047 | eq(var_os(&n), Some(&s)); |
85aaf69f SL |
1048 | remove_var(&n); |
1049 | eq(var_os(&n), None); | |
1050 | } | |
1051 | ||
1052 | #[test] | |
1053 | fn test_env_set_var() { | |
1054 | let n = make_rand_name(); | |
1055 | ||
1056 | let mut e = vars_os(); | |
1057 | set_var(&n, "VALUE"); | |
1058 | assert!(!e.any(|(k, v)| { | |
1059 | &*k == &*n && &*v == "VALUE" | |
1060 | })); | |
1061 | ||
1062 | assert!(vars_os().any(|(k, v)| { | |
1063 | &*k == &*n && &*v == "VALUE" | |
1064 | })); | |
1065 | } | |
1066 | ||
1067 | #[test] | |
1068 | fn test() { | |
1069 | assert!((!Path::new("test-path").is_absolute())); | |
1070 | ||
1071 | current_dir().unwrap(); | |
1072 | } | |
1073 | ||
1074 | #[test] | |
1075 | #[cfg(windows)] | |
1076 | fn split_paths_windows() { | |
1077 | fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { | |
1078 | split_paths(unparsed).collect::<Vec<_>>() == | |
c34b1796 | 1079 | parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>() |
85aaf69f SL |
1080 | } |
1081 | ||
1082 | assert!(check_parse("", &mut [""])); | |
1083 | assert!(check_parse(r#""""#, &mut [""])); | |
1084 | assert!(check_parse(";;", &mut ["", "", ""])); | |
1085 | assert!(check_parse(r"c:\", &mut [r"c:\"])); | |
1086 | assert!(check_parse(r"c:\;", &mut [r"c:\", ""])); | |
1087 | assert!(check_parse(r"c:\;c:\Program Files\", | |
1088 | &mut [r"c:\", r"c:\Program Files\"])); | |
1089 | assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"])); | |
1090 | assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#, | |
1091 | &mut [r"c:\", r"c:\foo;bar\", r"c:\baz"])); | |
1092 | } | |
1093 | ||
1094 | #[test] | |
1095 | #[cfg(unix)] | |
1096 | fn split_paths_unix() { | |
1097 | fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { | |
1098 | split_paths(unparsed).collect::<Vec<_>>() == | |
c34b1796 | 1099 | parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>() |
85aaf69f SL |
1100 | } |
1101 | ||
1102 | assert!(check_parse("", &mut [""])); | |
1103 | assert!(check_parse("::", &mut ["", "", ""])); | |
1104 | assert!(check_parse("/", &mut ["/"])); | |
1105 | assert!(check_parse("/:", &mut ["/", ""])); | |
1106 | assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"])); | |
1107 | } | |
1108 | ||
1109 | #[test] | |
1110 | #[cfg(unix)] | |
1111 | fn join_paths_unix() { | |
1112 | fn test_eq(input: &[&str], output: &str) -> bool { | |
1113 | &*join_paths(input.iter().cloned()).unwrap() == | |
9346a6ac | 1114 | OsStr::new(output) |
85aaf69f SL |
1115 | } |
1116 | ||
1117 | assert!(test_eq(&[], "")); | |
1118 | assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"], | |
1119 | "/bin:/usr/bin:/usr/local/bin")); | |
1120 | assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""], | |
1121 | ":/bin:::/usr/bin:")); | |
1122 | assert!(join_paths(["/te:st"].iter().cloned()).is_err()); | |
1123 | } | |
1124 | ||
1125 | #[test] | |
1126 | #[cfg(windows)] | |
1127 | fn join_paths_windows() { | |
1128 | fn test_eq(input: &[&str], output: &str) -> bool { | |
1129 | &*join_paths(input.iter().cloned()).unwrap() == | |
9346a6ac | 1130 | OsStr::new(output) |
85aaf69f SL |
1131 | } |
1132 | ||
1133 | assert!(test_eq(&[], "")); | |
1134 | assert!(test_eq(&[r"c:\windows", r"c:\"], | |
1135 | r"c:\windows;c:\")); | |
1136 | assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""], | |
1137 | r";c:\windows;;;c:\;")); | |
1138 | assert!(test_eq(&[r"c:\te;st", r"c:\"], | |
1139 | r#""c:\te;st";c:\"#)); | |
1140 | assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err()); | |
1141 | } | |
1142 | } |