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