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