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.
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.
11 //! Inspection and manipulation of the process's environment.
13 //! This module contains methods to inspect various aspects such as
14 //! environment variables, process arguments, the current directory, and various
15 //! other important directories.
17 #![stable(feature = "env", since = "1.0.0")]
22 use ffi::{OsStr, OsString};
25 use path::{Path, PathBuf};
26 use sync::StaticMutex;
27 use sys::os as os_imp;
29 /// Returns the current working directory as a `PathBuf`.
33 /// Returns an `Err` if the current working directory value is invalid.
36 /// * Current directory does not exist.
37 /// * There are insufficient permissions to access the current directory.
44 /// // We assume that we are in a valid directory.
45 /// let p = env::current_dir().unwrap();
46 /// println!("The current directory is {}", p.display());
48 #[stable(feature = "env", since = "1.0.0")]
49 pub fn current_dir() -> io::Result<PathBuf> {
53 /// Changes the current working directory to the specified path, returning
54 /// whether the change was completed successfully or not.
60 /// use std::path::Path;
62 /// let root = Path::new("/");
63 /// assert!(env::set_current_dir(&root).is_ok());
64 /// println!("Successfully changed working directory to {}!", root.display());
66 #[stable(feature = "env", since = "1.0.0")]
67 pub fn set_current_dir<P: AsRef<Path>>(p: P) -> io::Result<()> {
68 os_imp::chdir(p.as_ref())
71 static ENV_LOCK: StaticMutex = StaticMutex::new();
73 /// An iterator over a snapshot of the environment variables of this process.
75 /// This iterator is created through `std::env::vars()` and yields `(String,
77 #[stable(feature = "env", since = "1.0.0")]
78 pub struct Vars { inner: VarsOs }
80 /// An iterator over a snapshot of the environment variables of this process.
82 /// This iterator is created through `std::env::vars_os()` and yields
83 /// `(OsString, OsString)` pairs.
84 #[stable(feature = "env", since = "1.0.0")]
85 pub struct VarsOs { inner: os_imp::Env }
87 /// Returns an iterator of (variable, value) pairs of strings, for all the
88 /// environment variables of the current process.
90 /// The returned iterator contains a snapshot of the process's environment
91 /// variables at the time of this invocation, modifications to environment
92 /// variables afterwards will not be reflected in the returned iterator.
96 /// While iterating, the returned iterator will panic if any key or value in the
97 /// environment is not valid unicode. If this is not desired, consider using the
98 /// `env::vars_os` function.
105 /// // We will iterate through the references to the element returned by
107 /// for (key, value) in env::vars() {
108 /// println!("{}: {}", key, value);
111 #[stable(feature = "env", since = "1.0.0")]
112 pub fn vars() -> Vars {
113 Vars { inner: vars_os() }
116 /// Returns an iterator of (variable, value) pairs of OS strings, for all the
117 /// environment variables of the current process.
119 /// The returned iterator contains a snapshot of the process's environment
120 /// variables at the time of this invocation, modifications to environment
121 /// variables afterwards will not be reflected in the returned iterator.
128 /// // We will iterate through the references to the element returned by
129 /// // env::vars_os();
130 /// for (key, value) in env::vars_os() {
131 /// println!("{:?}: {:?}", key, value);
134 #[stable(feature = "env", since = "1.0.0")]
135 pub fn vars_os() -> VarsOs {
136 let _g = ENV_LOCK.lock();
137 VarsOs { inner: os_imp::env() }
140 #[stable(feature = "env", since = "1.0.0")]
141 impl Iterator for Vars {
142 type Item = (String, String);
143 fn next(&mut self) -> Option<(String, String)> {
144 self.inner.next().map(|(a, b)| {
145 (a.into_string().unwrap(), b.into_string().unwrap())
148 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
151 #[stable(feature = "env", since = "1.0.0")]
152 impl Iterator for VarsOs {
153 type Item = (OsString, OsString);
154 fn next(&mut self) -> Option<(OsString, OsString)> { self.inner.next() }
155 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
158 /// Fetches the environment variable `key` from the current process.
160 /// The returned result is `Ok(s)` if the environment variable is present and is
161 /// valid unicode. If the environment variable is not present, or it is not
162 /// valid unicode, then `Err` will be returned.
169 /// let key = "HOME";
170 /// match env::var(key) {
171 /// Ok(val) => println!("{}: {:?}", key, val),
172 /// Err(e) => println!("couldn't interpret {}: {}", key, e),
175 #[stable(feature = "env", since = "1.0.0")]
176 pub fn var<K: AsRef<OsStr>>(key: K) -> Result<String, VarError> {
178 Some(s) => s.into_string().map_err(VarError::NotUnicode),
179 None => Err(VarError::NotPresent)
183 /// Fetches the environment variable `key` from the current process, returning
184 /// None if the variable isn't set.
191 /// let key = "HOME";
192 /// match env::var_os(key) {
193 /// Some(val) => println!("{}: {:?}", key, val),
194 /// None => println!("{} is not defined in the environment.", key)
197 #[stable(feature = "env", since = "1.0.0")]
198 pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
199 let _g = ENV_LOCK.lock();
200 os_imp::getenv(key.as_ref())
203 /// Possible errors from the `env::var` method.
204 #[derive(Debug, PartialEq, Eq, Clone)]
205 #[stable(feature = "env", since = "1.0.0")]
207 /// The specified environment variable was not present in the current
208 /// process's environment.
209 #[stable(feature = "env", since = "1.0.0")]
212 /// The specified environment variable was found, but it did not contain
213 /// valid unicode data. The found data is returned as a payload of this
215 #[stable(feature = "env", since = "1.0.0")]
216 NotUnicode(OsString),
219 #[stable(feature = "env", since = "1.0.0")]
220 impl fmt::Display for VarError {
221 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
223 VarError::NotPresent => write!(f, "environment variable not found"),
224 VarError::NotUnicode(ref s) => {
225 write!(f, "environment variable was not valid unicode: {:?}", s)
231 #[stable(feature = "env", since = "1.0.0")]
232 impl Error for VarError {
233 fn description(&self) -> &str {
235 VarError::NotPresent => "environment variable not found",
236 VarError::NotUnicode(..) => "environment variable was not valid unicode",
241 /// Sets the environment variable `k` to the value `v` for the currently running
244 /// Note that while concurrent access to environment variables is safe in Rust,
245 /// some platforms only expose inherently unsafe non-threadsafe APIs for
246 /// inspecting the environment. As a result extra care needs to be taken when
247 /// auditing calls to unsafe external FFI functions to ensure that any external
248 /// environment accesses are properly synchronized with accesses in Rust.
250 /// Discussion of this unsafety on Unix may be found in:
252 /// - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188)
253 /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
261 /// env::set_var(key, "VALUE");
262 /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
264 #[stable(feature = "env", since = "1.0.0")]
265 pub fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(k: K, v: V) {
266 let _g = ENV_LOCK.lock();
267 os_imp::setenv(k.as_ref(), v.as_ref())
270 /// Removes an environment variable from the environment of the currently running process.
272 /// Note that while concurrent access to environment variables is safe in Rust,
273 /// some platforms only expose inherently unsafe non-threadsafe APIs for
274 /// inspecting the environment. As a result extra care needs to be taken when
275 /// auditing calls to unsafe external FFI functions to ensure that any external
276 /// environment accesses are properly synchronized with accesses in Rust.
278 /// Discussion of this unsafety on Unix may be found in:
280 /// - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188)
281 /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
289 /// env::set_var(key, "VALUE");
290 /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
292 /// env::remove_var(key);
293 /// assert!(env::var(key).is_err());
295 #[stable(feature = "env", since = "1.0.0")]
296 pub fn remove_var<K: AsRef<OsStr>>(k: K) {
297 let _g = ENV_LOCK.lock();
298 os_imp::unsetenv(k.as_ref())
301 /// An iterator over `Path` instances for parsing an environment variable
302 /// according to platform-specific conventions.
304 /// This structure is returned from `std::env::split_paths`.
305 #[stable(feature = "env", since = "1.0.0")]
306 pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> }
308 /// Parses input according to platform conventions for the `PATH`
309 /// environment variable.
311 /// Returns an iterator over the paths contained in `unparsed`.
318 /// let key = "PATH";
319 /// match env::var_os(key) {
321 /// for path in env::split_paths(&paths) {
322 /// println!("'{}'", path.display());
325 /// None => println!("{} is not defined in the environment.", key)
328 #[stable(feature = "env", since = "1.0.0")]
329 pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths {
330 SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) }
333 #[stable(feature = "env", since = "1.0.0")]
334 impl<'a> Iterator for SplitPaths<'a> {
336 fn next(&mut self) -> Option<PathBuf> { self.inner.next() }
337 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
340 /// Error type returned from `std::env::join_paths` when paths fail to be
343 #[stable(feature = "env", since = "1.0.0")]
344 pub struct JoinPathsError {
345 inner: os_imp::JoinPathsError
348 /// Joins a collection of `Path`s appropriately for the `PATH`
349 /// environment variable.
351 /// Returns an `OsString` on success.
353 /// Returns an `Err` (containing an error message) if one of the input
354 /// `Path`s contains an invalid character for constructing the `PATH`
355 /// variable (a double quote on Windows or a colon on Unix).
361 /// use std::path::PathBuf;
363 /// if let Some(path) = env::var_os("PATH") {
364 /// let mut paths = env::split_paths(&path).collect::<Vec<_>>();
365 /// paths.push(PathBuf::from("/home/xyz/bin"));
366 /// let new_path = env::join_paths(paths).unwrap();
367 /// env::set_var("PATH", &new_path);
370 #[stable(feature = "env", since = "1.0.0")]
371 pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
372 where I: IntoIterator<Item=T>, T: AsRef<OsStr>
374 os_imp::join_paths(paths.into_iter()).map_err(|e| {
375 JoinPathsError { inner: e }
379 #[stable(feature = "env", since = "1.0.0")]
380 impl fmt::Display for JoinPathsError {
381 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
386 #[stable(feature = "env", since = "1.0.0")]
387 impl Error for JoinPathsError {
388 fn description(&self) -> &str { self.inner.description() }
391 /// Optionally returns the path to the current user's home directory if known.
395 /// Returns the value of the 'HOME' environment variable if it is set
396 /// and not equal to the empty string.
400 /// Returns the value of the 'HOME' environment variable if it is
401 /// set and not equal to the empty string. Otherwise, returns the value of the
402 /// 'USERPROFILE' environment variable if it is set and not equal to the empty
410 /// match env::home_dir() {
411 /// Some(ref p) => println!("{}", p.display()),
412 /// None => println!("Impossible to get your home dir!")
415 #[stable(feature = "env", since = "1.0.0")]
416 pub fn home_dir() -> Option<PathBuf> {
420 /// Returns the path to a temporary directory.
422 /// On Unix, returns the value of the 'TMPDIR' environment variable if it is
423 /// set, otherwise for non-Android it returns '/tmp'. If Android, since there
424 /// is no global temporary folder (it is usually allocated per-app), we return
425 /// '/data/local/tmp'.
427 /// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
428 /// 'USERPROFILE' environment variable if any are set and not the empty
429 /// string. Otherwise, tmpdir returns the path to the Windows directory.
433 /// use std::fs::File;
435 /// # fn foo() -> std::io::Result<()> {
436 /// let mut dir = env::temp_dir();
437 /// dir.push("foo.txt");
439 /// let f = try!(File::create(dir));
443 #[stable(feature = "env", since = "1.0.0")]
444 pub fn temp_dir() -> PathBuf {
448 /// Optionally returns the filesystem path to the current executable which is
449 /// running but with the executable name.
451 /// The path returned is not necessarily a "real path" to the executable as
452 /// there may be intermediate symlinks.
456 /// Acquiring the path to the current executable is a platform-specific operation
457 /// that can fail for a good number of reasons. Some errors can include, but not
458 /// be limited to filesystem operations failing or general syscall failures.
465 /// match env::current_exe() {
466 /// Ok(exe_path) => println!("Path of this executable is: {}",
467 /// exe_path.display()),
468 /// Err(e) => println!("failed to get current exe path: {}", e),
471 #[stable(feature = "env", since = "1.0.0")]
472 pub fn current_exe() -> io::Result<PathBuf> {
473 os_imp::current_exe()
476 /// An iterator over the arguments of a process, yielding a `String` value
477 /// for each argument.
479 /// This structure is created through the `std::env::args` method.
480 #[stable(feature = "env", since = "1.0.0")]
481 pub struct Args { inner: ArgsOs }
483 /// An iterator over the arguments of a process, yielding an `OsString` value
484 /// for each argument.
486 /// This structure is created through the `std::env::args_os` method.
487 #[stable(feature = "env", since = "1.0.0")]
488 pub struct ArgsOs { inner: os_imp::Args }
490 /// Returns the arguments which this program was started with (normally passed
491 /// via the command line).
493 /// The first element is traditionally the path to the executable, but it can be
494 /// set to arbitrary text, and it may not even exist, so this property should
495 /// not be relied upon for security purposes.
499 /// The returned iterator will panic during iteration if any argument to the
500 /// process is not valid unicode. If this is not desired it is recommended to
501 /// use the `args_os` function instead.
508 /// // Prints each argument on a separate line
509 /// for argument in env::args() {
510 /// println!("{}", argument);
513 #[stable(feature = "env", since = "1.0.0")]
514 pub fn args() -> Args {
515 Args { inner: args_os() }
518 /// Returns the arguments which this program was started with (normally passed
519 /// via the command line).
521 /// The first element is traditionally the path to the executable, but it can be
522 /// set to arbitrary text, and it may not even exist, so this property should
523 /// not be relied upon for security purposes.
530 /// // Prints each argument on a separate line
531 /// for argument in env::args_os() {
532 /// println!("{:?}", argument);
535 #[stable(feature = "env", since = "1.0.0")]
536 pub fn args_os() -> ArgsOs {
537 ArgsOs { inner: os_imp::args() }
540 #[stable(feature = "env", since = "1.0.0")]
541 impl Iterator for Args {
543 fn next(&mut self) -> Option<String> {
544 self.inner.next().map(|s| s.into_string().unwrap())
546 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
549 #[stable(feature = "env", since = "1.0.0")]
550 impl ExactSizeIterator for Args {
551 fn len(&self) -> usize { self.inner.len() }
554 #[stable(feature = "env", since = "1.0.0")]
555 impl Iterator for ArgsOs {
556 type Item = OsString;
557 fn next(&mut self) -> Option<OsString> { self.inner.next() }
558 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
561 #[stable(feature = "env", since = "1.0.0")]
562 impl ExactSizeIterator for ArgsOs {
563 fn len(&self) -> usize { self.inner.len() }
566 /// Constants associated with the current target
567 #[stable(feature = "env", since = "1.0.0")]
569 /// A string describing the architecture of the CPU that this is currently
572 /// Some possible values:
581 #[stable(feature = "env", since = "1.0.0")]
582 pub const ARCH: &'static str = super::arch::ARCH;
584 /// The family of the operating system. In this case, `unix`.
586 /// Some possible values:
590 #[stable(feature = "env", since = "1.0.0")]
591 pub const FAMILY: &'static str = super::os::FAMILY;
593 /// A string describing the specific operating system in use: in this
596 /// Some possible values:
608 #[stable(feature = "env", since = "1.0.0")]
609 pub const OS: &'static str = super::os::OS;
611 /// Specifies the filename prefix used for shared libraries on this
612 /// platform: in this case, `lib`.
614 /// Some possible values:
617 /// - `""` (an empty string)
618 #[stable(feature = "env", since = "1.0.0")]
619 pub const DLL_PREFIX: &'static str = super::os::DLL_PREFIX;
621 /// Specifies the filename suffix used for shared libraries on this
622 /// platform: in this case, `.so`.
624 /// Some possible values:
629 #[stable(feature = "env", since = "1.0.0")]
630 pub const DLL_SUFFIX: &'static str = super::os::DLL_SUFFIX;
632 /// Specifies the file extension used for shared libraries on this
633 /// platform that goes after the dot: in this case, `so`.
635 /// Some possible values:
640 #[stable(feature = "env", since = "1.0.0")]
641 pub const DLL_EXTENSION: &'static str = super::os::DLL_EXTENSION;
643 /// Specifies the filename suffix used for executable binaries on this
644 /// platform: in this case, the empty string.
646 /// Some possible values:
649 /// - `""` (an empty string)
650 #[stable(feature = "env", since = "1.0.0")]
651 pub const EXE_SUFFIX: &'static str = super::os::EXE_SUFFIX;
653 /// Specifies the file extension, if any, used for executable binaries
654 /// on this platform: in this case, the empty string.
656 /// Some possible values:
659 /// - `""` (an empty string)
660 #[stable(feature = "env", since = "1.0.0")]
661 pub const EXE_EXTENSION: &'static str = super::os::EXE_EXTENSION;
665 #[cfg(target_os = "linux")]
667 pub const FAMILY: &'static str = "unix";
668 pub const OS: &'static str = "linux";
669 pub const DLL_PREFIX: &'static str = "lib";
670 pub const DLL_SUFFIX: &'static str = ".so";
671 pub const DLL_EXTENSION: &'static str = "so";
672 pub const EXE_SUFFIX: &'static str = "";
673 pub const EXE_EXTENSION: &'static str = "";
676 #[cfg(target_os = "macos")]
678 pub const FAMILY: &'static str = "unix";
679 pub const OS: &'static str = "macos";
680 pub const DLL_PREFIX: &'static str = "lib";
681 pub const DLL_SUFFIX: &'static str = ".dylib";
682 pub const DLL_EXTENSION: &'static str = "dylib";
683 pub const EXE_SUFFIX: &'static str = "";
684 pub const EXE_EXTENSION: &'static str = "";
687 #[cfg(target_os = "ios")]
689 pub const FAMILY: &'static str = "unix";
690 pub const OS: &'static str = "ios";
691 pub const DLL_PREFIX: &'static str = "lib";
692 pub const DLL_SUFFIX: &'static str = ".dylib";
693 pub const DLL_EXTENSION: &'static str = "dylib";
694 pub const EXE_SUFFIX: &'static str = "";
695 pub const EXE_EXTENSION: &'static str = "";
698 #[cfg(target_os = "freebsd")]
700 pub const FAMILY: &'static str = "unix";
701 pub const OS: &'static str = "freebsd";
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 = "";
706 pub const EXE_EXTENSION: &'static str = "";
709 #[cfg(target_os = "dragonfly")]
711 pub const FAMILY: &'static str = "unix";
712 pub const OS: &'static str = "dragonfly";
713 pub const DLL_PREFIX: &'static str = "lib";
714 pub const DLL_SUFFIX: &'static str = ".so";
715 pub const DLL_EXTENSION: &'static str = "so";
716 pub const EXE_SUFFIX: &'static str = "";
717 pub const EXE_EXTENSION: &'static str = "";
720 #[cfg(target_os = "bitrig")]
722 pub const FAMILY: &'static str = "unix";
723 pub const OS: &'static str = "bitrig";
724 pub const DLL_PREFIX: &'static str = "lib";
725 pub const DLL_SUFFIX: &'static str = ".so";
726 pub const DLL_EXTENSION: &'static str = "so";
727 pub const EXE_SUFFIX: &'static str = "";
728 pub const EXE_EXTENSION: &'static str = "";
731 #[cfg(target_os = "netbsd")]
733 pub const FAMILY: &'static str = "unix";
734 pub const OS: &'static str = "netbsd";
735 pub const DLL_PREFIX: &'static str = "lib";
736 pub const DLL_SUFFIX: &'static str = ".so";
737 pub const DLL_EXTENSION: &'static str = "so";
738 pub const EXE_SUFFIX: &'static str = "";
739 pub const EXE_EXTENSION: &'static str = "";
742 #[cfg(target_os = "openbsd")]
744 pub const FAMILY: &'static str = "unix";
745 pub const OS: &'static str = "openbsd";
746 pub const DLL_PREFIX: &'static str = "lib";
747 pub const DLL_SUFFIX: &'static str = ".so";
748 pub const DLL_EXTENSION: &'static str = "so";
749 pub const EXE_SUFFIX: &'static str = "";
750 pub const EXE_EXTENSION: &'static str = "";
753 #[cfg(target_os = "android")]
755 pub const FAMILY: &'static str = "unix";
756 pub const OS: &'static str = "android";
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 = "";
761 pub const EXE_EXTENSION: &'static str = "";
764 #[cfg(target_os = "windows")]
766 pub const FAMILY: &'static str = "windows";
767 pub const OS: &'static str = "windows";
768 pub const DLL_PREFIX: &'static str = "";
769 pub const DLL_SUFFIX: &'static str = ".dll";
770 pub const DLL_EXTENSION: &'static str = "dll";
771 pub const EXE_SUFFIX: &'static str = ".exe";
772 pub const EXE_EXTENSION: &'static str = "exe";
775 #[cfg(target_arch = "x86")]
777 pub const ARCH: &'static str = "x86";
780 #[cfg(target_arch = "x86_64")]
782 pub const ARCH: &'static str = "x86_64";
785 #[cfg(target_arch = "arm")]
787 pub const ARCH: &'static str = "arm";
790 #[cfg(target_arch = "aarch64")]
792 pub const ARCH: &'static str = "aarch64";
795 #[cfg(target_arch = "mips")]
797 pub const ARCH: &'static str = "mips";
800 #[cfg(target_arch = "mipsel")]
802 pub const ARCH: &'static str = "mipsel";
805 #[cfg(target_arch = "powerpc")]
807 pub const ARCH: &'static str = "powerpc";
816 use rand::{self, Rng};
817 use ffi::{OsString, OsStr};
818 use path::{Path, PathBuf};
820 fn make_rand_name() -> OsString {
821 let mut rng = rand::thread_rng();
822 let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
823 .collect::<String>());
824 let n = OsString::from(n);
825 assert!(var_os(&n).is_none());
829 fn eq(a: Option<OsString>, b: Option<&str>) {
830 assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
835 let n = make_rand_name();
836 set_var(&n, "VALUE");
837 eq(var_os(&n), Some("VALUE"));
841 fn test_remove_var() {
842 let n = make_rand_name();
843 set_var(&n, "VALUE");
845 eq(var_os(&n), None);
849 fn test_set_var_overwrite() {
850 let n = make_rand_name();
853 eq(var_os(&n), Some("2"));
855 eq(var_os(&n), Some(""));
860 let mut s = "".to_string();
863 s.push_str("aaaaaaaaaa");
866 let n = make_rand_name();
868 eq(var_os(&n), Some(&s));
872 fn test_self_exe_path() {
873 let path = current_exe();
874 assert!(path.is_ok());
875 let path = path.unwrap();
877 // Hard to test this function
878 assert!(path.is_absolute());
882 fn test_env_set_get_huge() {
883 let n = make_rand_name();
884 let s = repeat("x").take(10000).collect::<String>();
886 eq(var_os(&n), Some(&s));
888 eq(var_os(&n), None);
892 fn test_env_set_var() {
893 let n = make_rand_name();
895 let mut e = vars_os();
896 set_var(&n, "VALUE");
897 assert!(!e.any(|(k, v)| {
898 &*k == &*n && &*v == "VALUE"
901 assert!(vars_os().any(|(k, v)| {
902 &*k == &*n && &*v == "VALUE"
908 assert!((!Path::new("test-path").is_absolute()));
910 current_dir().unwrap();
915 fn split_paths_windows() {
916 fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
917 split_paths(unparsed).collect::<Vec<_>>() ==
918 parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
921 assert!(check_parse("", &mut [""]));
922 assert!(check_parse(r#""""#, &mut [""]));
923 assert!(check_parse(";;", &mut ["", "", ""]));
924 assert!(check_parse(r"c:\", &mut [r"c:\"]));
925 assert!(check_parse(r"c:\;", &mut [r"c:\", ""]));
926 assert!(check_parse(r"c:\;c:\Program Files\",
927 &mut [r"c:\", r"c:\Program Files\"]));
928 assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"]));
929 assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#,
930 &mut [r"c:\", r"c:\foo;bar\", r"c:\baz"]));
935 fn split_paths_unix() {
936 fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
937 split_paths(unparsed).collect::<Vec<_>>() ==
938 parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
941 assert!(check_parse("", &mut [""]));
942 assert!(check_parse("::", &mut ["", "", ""]));
943 assert!(check_parse("/", &mut ["/"]));
944 assert!(check_parse("/:", &mut ["/", ""]));
945 assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"]));
950 fn join_paths_unix() {
951 fn test_eq(input: &[&str], output: &str) -> bool {
952 &*join_paths(input.iter().cloned()).unwrap() ==
956 assert!(test_eq(&[], ""));
957 assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"],
958 "/bin:/usr/bin:/usr/local/bin"));
959 assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""],
960 ":/bin:::/usr/bin:"));
961 assert!(join_paths(["/te:st"].iter().cloned()).is_err());
966 fn join_paths_windows() {
967 fn test_eq(input: &[&str], output: &str) -> bool {
968 &*join_paths(input.iter().cloned()).unwrap() ==
972 assert!(test_eq(&[], ""));
973 assert!(test_eq(&[r"c:\windows", r"c:\"],
975 assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""],
976 r";c:\windows;;;c:\;"));
977 assert!(test_eq(&[r"c:\te;st", r"c:\"],
978 r#""c:\te;st";c:\"#));
979 assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err());