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 varibles, process arguments, the current directory, and various
15 //! other important directories.
17 #![stable(feature = "env", since = "1.0.0")]
21 use iter::IntoIterator;
23 use ffi::{OsString, AsOsStr};
26 use path::{Path, PathBuf};
27 use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
28 use sync::{StaticMutex, MUTEX_INIT};
29 use sys::os as os_imp;
31 /// Returns the current working directory as a `Path`.
35 /// Returns an `Err` if the current working directory value is invalid.
38 /// * Current directory does not exist.
39 /// * There are insufficient permissions to access the current directory.
40 /// * The internal buffer is not large enough to hold the path.
47 /// // We assume that we are in a valid directory.
48 /// let p = env::current_dir().unwrap();
49 /// println!("The current directory is {}", p.display());
51 #[stable(feature = "env", since = "1.0.0")]
52 pub fn current_dir() -> io::Result<PathBuf> {
56 /// Changes the current working directory to the specified path, returning
57 /// whether the change was completed successfully or not.
63 /// use std::path::Path;
65 /// let root = Path::new("/");
66 /// assert!(env::set_current_dir(&root).is_ok());
67 /// println!("Successfully changed working directory to {}!", root.display());
69 #[stable(feature = "env", since = "1.0.0")]
70 pub fn set_current_dir<P: AsRef<Path> + ?Sized>(p: &P) -> io::Result<()> {
71 os_imp::chdir(p.as_ref())
74 static ENV_LOCK: StaticMutex = MUTEX_INIT;
76 /// An iterator over a snapshot of the environment variables of this process.
78 /// This iterator is created through `std::env::vars()` and yields `(String,
80 #[stable(feature = "env", since = "1.0.0")]
81 pub struct Vars { inner: VarsOs }
83 /// An iterator over a snapshot of the environment variables of this process.
85 /// This iterator is created through `std::env::vars_os()` and yields
86 /// `(OsString, OsString)` pairs.
87 #[stable(feature = "env", since = "1.0.0")]
88 pub struct VarsOs { inner: os_imp::Env }
90 /// Returns an iterator of (variable, value) pairs of strings, for all the
91 /// environment variables of the current process.
93 /// The returned iterator contains a snapshot of the process's environment
94 /// variables at the time of this invocation, modifications to environment
95 /// variables afterwards will not be reflected in the returned iterator.
99 /// While iterating, the returned iterator will panic if any key or value in the
100 /// environment is not valid unicode. If this is not desired, consider using the
101 /// `env::vars_os` function.
108 /// // We will iterate through the references to the element returned by
110 /// for (key, value) in env::vars() {
111 /// println!("{}: {}", key, value);
114 #[stable(feature = "env", since = "1.0.0")]
115 pub fn vars() -> Vars {
116 Vars { inner: vars_os() }
119 /// Returns an iterator of (variable, value) pairs of OS strings, for all the
120 /// environment variables of the current process.
122 /// The returned iterator contains a snapshot of the process's environment
123 /// variables at the time of this invocation, modifications to environment
124 /// variables afterwards will not be reflected in the returned iterator.
131 /// // We will iterate through the references to the element returned by
132 /// // env::vars_os();
133 /// for (key, value) in env::vars_os() {
134 /// println!("{:?}: {:?}", key, value);
137 #[stable(feature = "env", since = "1.0.0")]
138 pub fn vars_os() -> VarsOs {
139 let _g = ENV_LOCK.lock();
140 VarsOs { inner: os_imp::env() }
143 #[stable(feature = "env", since = "1.0.0")]
144 impl Iterator for Vars {
145 type Item = (String, String);
146 fn next(&mut self) -> Option<(String, String)> {
147 self.inner.next().map(|(a, b)| {
148 (a.into_string().unwrap(), b.into_string().unwrap())
151 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
154 #[stable(feature = "env", since = "1.0.0")]
155 impl Iterator for VarsOs {
156 type Item = (OsString, OsString);
157 fn next(&mut self) -> Option<(OsString, OsString)> { self.inner.next() }
158 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
161 /// Fetches the environment variable `key` from the current process.
163 /// The returned result is `Ok(s)` if the environment variable is present and is
164 /// valid unicode. If the environment variable is not present, or it is not
165 /// valid unicode, then `Err` will be returned.
172 /// let key = "HOME";
173 /// match env::var(key) {
174 /// Ok(val) => println!("{}: {:?}", key, val),
175 /// Err(e) => println!("couldn't interpret {}: {}", key, e),
178 #[stable(feature = "env", since = "1.0.0")]
179 pub fn var<K: ?Sized>(key: &K) -> Result<String, VarError> where K: AsOsStr {
181 Some(s) => s.into_string().map_err(VarError::NotUnicode),
182 None => Err(VarError::NotPresent)
186 /// Fetches the environment variable `key` from the current process, returning
187 /// None if the variable isn't set.
194 /// let key = "HOME";
195 /// match env::var_os(key) {
196 /// Some(val) => println!("{}: {:?}", key, val),
197 /// None => println!("{} is not defined in the environment.", key)
200 #[stable(feature = "env", since = "1.0.0")]
201 pub fn var_os<K: ?Sized>(key: &K) -> Option<OsString> where K: AsOsStr {
202 let _g = ENV_LOCK.lock();
203 os_imp::getenv(key.as_os_str())
206 /// Possible errors from the `env::var` method.
207 #[derive(Debug, PartialEq, Eq, Clone)]
208 #[stable(feature = "env", since = "1.0.0")]
210 /// The specified environment variable was not present in the current
211 /// process's environment.
212 #[stable(feature = "env", since = "1.0.0")]
215 /// The specified environment variable was found, but it did not contain
216 /// valid unicode data. The found data is returned as a payload of this
218 #[stable(feature = "env", since = "1.0.0")]
219 NotUnicode(OsString),
222 #[stable(feature = "env", since = "1.0.0")]
223 impl fmt::Display for VarError {
224 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
226 VarError::NotPresent => write!(f, "environment variable not found"),
227 VarError::NotUnicode(ref s) => {
228 write!(f, "environment variable was not valid unicode: {:?}", s)
234 #[stable(feature = "env", since = "1.0.0")]
235 impl Error for VarError {
236 fn description(&self) -> &str {
238 VarError::NotPresent => "environment variable not found",
239 VarError::NotUnicode(..) => "environment variable was not valid unicode",
244 /// Sets the environment variable `k` to the value `v` for the currently running
253 /// env::set_var(key, "VALUE");
254 /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
256 #[stable(feature = "env", since = "1.0.0")]
257 pub fn set_var<K: ?Sized, V: ?Sized>(k: &K, v: &V)
258 where K: AsOsStr, V: AsOsStr
260 let _g = ENV_LOCK.lock();
261 os_imp::setenv(k.as_os_str(), v.as_os_str())
264 /// Remove a variable from the environment entirely.
265 #[stable(feature = "env", since = "1.0.0")]
266 pub fn remove_var<K: ?Sized>(k: &K) where K: AsOsStr {
267 let _g = ENV_LOCK.lock();
268 os_imp::unsetenv(k.as_os_str())
271 /// An iterator over `Path` instances for parsing an environment variable
272 /// according to platform-specific conventions.
274 /// This structure is returned from `std::env::split_paths`.
275 #[stable(feature = "env", since = "1.0.0")]
276 pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> }
278 /// Parses input according to platform conventions for the `PATH`
279 /// environment variable.
281 /// Returns an iterator over the paths contained in `unparsed`.
288 /// let key = "PATH";
289 /// match env::var_os(key) {
291 /// for path in env::split_paths(&paths) {
292 /// println!("'{}'", path.display());
295 /// None => println!("{} is not defined in the environment.", key)
298 #[stable(feature = "env", since = "1.0.0")]
299 pub fn split_paths<T: AsOsStr + ?Sized>(unparsed: &T) -> SplitPaths {
300 SplitPaths { inner: os_imp::split_paths(unparsed.as_os_str()) }
303 #[stable(feature = "env", since = "1.0.0")]
304 impl<'a> Iterator for SplitPaths<'a> {
306 fn next(&mut self) -> Option<PathBuf> { self.inner.next() }
307 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
310 /// Error type returned from `std::env::join_paths` when paths fail to be
313 #[stable(feature = "env", since = "1.0.0")]
314 pub struct JoinPathsError {
315 inner: os_imp::JoinPathsError
318 /// Joins a collection of `Path`s appropriately for the `PATH`
319 /// environment variable.
321 /// Returns an `OsString` on success.
323 /// Returns an `Err` (containing an error message) if one of the input
324 /// `Path`s contains an invalid character for constructing the `PATH`
325 /// variable (a double quote on Windows or a colon on Unix).
331 /// use std::path::PathBuf;
333 /// if let Some(path) = env::var_os("PATH") {
334 /// let mut paths = env::split_paths(&path).collect::<Vec<_>>();
335 /// paths.push(PathBuf::new("/home/xyz/bin"));
336 /// let new_path = env::join_paths(paths.iter()).unwrap();
337 /// env::set_var("PATH", &new_path);
340 #[stable(feature = "env", since = "1.0.0")]
341 pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
342 where I: IntoIterator<Item=T>, T: AsOsStr
344 os_imp::join_paths(paths.into_iter()).map_err(|e| {
345 JoinPathsError { inner: e }
349 #[stable(feature = "env", since = "1.0.0")]
350 impl fmt::Display for JoinPathsError {
351 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
356 #[stable(feature = "env", since = "1.0.0")]
357 impl Error for JoinPathsError {
358 fn description(&self) -> &str { self.inner.description() }
361 /// Optionally returns the path to the current user's home directory if known.
365 /// Returns the value of the 'HOME' environment variable if it is set
366 /// and not equal to the empty string.
370 /// Returns the value of the 'HOME' environment variable if it is
371 /// set and not equal to the empty string. Otherwise, returns the value of the
372 /// 'USERPROFILE' environment variable if it is set and not equal to the empty
380 /// match env::home_dir() {
381 /// Some(ref p) => println!("{}", p.display()),
382 /// None => println!("Impossible to get your home dir!")
385 #[stable(feature = "env", since = "1.0.0")]
386 pub fn home_dir() -> Option<PathBuf> {
390 /// Returns the path to a temporary directory.
392 /// On Unix, returns the value of the 'TMPDIR' environment variable if it is
393 /// set, otherwise for non-Android it returns '/tmp'. If Android, since there
394 /// is no global temporary folder (it is usually allocated per-app), we return
395 /// '/data/local/tmp'.
397 /// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
398 /// 'USERPROFILE' environment variable if any are set and not the empty
399 /// string. Otherwise, tmpdir returns the path to the Windows directory.
400 #[stable(feature = "env", since = "1.0.0")]
401 pub fn temp_dir() -> PathBuf {
405 /// Optionally returns the filesystem path to the current executable which is
406 /// running but with the executable name.
408 /// The path returned is not necessarily a "real path" to the executable as
409 /// there may be intermediate symlinks.
413 /// Acquiring the path to the current executable is a platform-specific operation
414 /// that can fail for a good number of reasons. Some errors can include, but not
415 /// be limited to filesystem operations failing or general syscall failures.
422 /// match env::current_exe() {
423 /// Ok(exe_path) => println!("Path of this executable is: {}",
424 /// exe_path.display()),
425 /// Err(e) => println!("failed to get current exe path: {}", e),
428 #[stable(feature = "env", since = "1.0.0")]
429 pub fn current_exe() -> io::Result<PathBuf> {
430 os_imp::current_exe()
433 static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
435 /// Sets the process exit code
437 /// Sets the exit code returned by the process if all supervised tasks
438 /// terminate successfully (without panicking). If the current root task panics
439 /// and is supervised by the scheduler then any user-specified exit status is
440 /// ignored and the process exits with the default panic status.
442 /// Note that this is not synchronized against modifications of other threads.
443 #[unstable(feature = "exit_status", reason = "managing the exit status may change")]
444 pub fn set_exit_status(code: i32) {
445 EXIT_STATUS.store(code as isize, Ordering::SeqCst)
448 /// Fetches the process's current exit code. This defaults to 0 and can change
449 /// by calling `set_exit_status`.
450 #[unstable(feature = "exit_status", reason = "managing the exit status may change")]
451 pub fn get_exit_status() -> i32 {
452 EXIT_STATUS.load(Ordering::SeqCst) as i32
455 /// An iterator over the arguments of a process, yielding a `String` value
456 /// for each argument.
458 /// This structure is created through the `std::env::args` method.
459 #[stable(feature = "env", since = "1.0.0")]
460 pub struct Args { inner: ArgsOs }
462 /// An iterator over the arguments of a process, yielding an `OsString` value
463 /// for each argument.
465 /// This structure is created through the `std::env::args_os` method.
466 #[stable(feature = "env", since = "1.0.0")]
467 pub struct ArgsOs { inner: os_imp::Args }
469 /// Returns the arguments which this program was started with (normally passed
470 /// via the command line).
472 /// The first element is traditionally the path to the executable, but it can be
473 /// set to arbitrary text, and it may not even exist, so this property should
474 /// not be relied upon for security purposes.
478 /// The returned iterator will panic during iteration if any argument to the
479 /// process is not valid unicode. If this is not desired it is recommended to
480 /// use the `args_os` function instead.
487 /// // Prints each argument on a separate line
488 /// for argument in env::args() {
489 /// println!("{}", argument);
492 #[stable(feature = "env", since = "1.0.0")]
493 pub fn args() -> Args {
494 Args { inner: args_os() }
497 /// Returns the arguments which this program was started with (normally passed
498 /// via the command line).
500 /// The first element is traditionally the path to the executable, but it can be
501 /// set to arbitrary text, and it may not even exist, so this property should
502 /// not be relied upon for security purposes.
509 /// // Prints each argument on a separate line
510 /// for argument in env::args_os() {
511 /// println!("{:?}", argument);
514 #[stable(feature = "env", since = "1.0.0")]
515 pub fn args_os() -> ArgsOs {
516 ArgsOs { inner: os_imp::args() }
519 #[stable(feature = "env", since = "1.0.0")]
520 impl Iterator for Args {
522 fn next(&mut self) -> Option<String> {
523 self.inner.next().map(|s| s.into_string().unwrap())
525 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
528 #[stable(feature = "env", since = "1.0.0")]
529 impl ExactSizeIterator for Args {
530 fn len(&self) -> usize { self.inner.len() }
533 #[stable(feature = "env", since = "1.0.0")]
534 impl Iterator for ArgsOs {
535 type Item = OsString;
536 fn next(&mut self) -> Option<OsString> { self.inner.next() }
537 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
540 #[stable(feature = "env", since = "1.0.0")]
541 impl ExactSizeIterator for ArgsOs {
542 fn len(&self) -> usize { self.inner.len() }
545 /// Returns the page size of the current architecture in bytes.
546 #[unstable(feature = "page_size", reason = "naming and/or location may change")]
547 pub fn page_size() -> usize {
551 /// Constants associated with the current target
552 #[stable(feature = "env", since = "1.0.0")]
554 /// A string describing the architecture of the CPU that this is currently
556 #[stable(feature = "env", since = "1.0.0")]
557 pub const ARCH: &'static str = super::arch::ARCH;
559 #[stable(feature = "env", since = "1.0.0")]
560 pub const FAMILY: &'static str = super::os::FAMILY;
562 /// A string describing the specific operating system in use: in this
564 #[stable(feature = "env", since = "1.0.0")]
565 pub const OS: &'static str = super::os::OS;
567 /// Specifies the filename prefix used for shared libraries on this
568 /// platform: in this case, `lib`.
569 #[stable(feature = "env", since = "1.0.0")]
570 pub const DLL_PREFIX: &'static str = super::os::DLL_PREFIX;
572 /// Specifies the filename suffix used for shared libraries on this
573 /// platform: in this case, `.so`.
574 #[stable(feature = "env", since = "1.0.0")]
575 pub const DLL_SUFFIX: &'static str = super::os::DLL_SUFFIX;
577 /// Specifies the file extension used for shared libraries on this
578 /// platform that goes after the dot: in this case, `so`.
579 #[stable(feature = "env", since = "1.0.0")]
580 pub const DLL_EXTENSION: &'static str = super::os::DLL_EXTENSION;
582 /// Specifies the filename suffix used for executable binaries on this
583 /// platform: in this case, the empty string.
584 #[stable(feature = "env", since = "1.0.0")]
585 pub const EXE_SUFFIX: &'static str = super::os::EXE_SUFFIX;
587 /// Specifies the file extension, if any, used for executable binaries
588 /// on this platform: in this case, the empty string.
589 #[stable(feature = "env", since = "1.0.0")]
590 pub const EXE_EXTENSION: &'static str = super::os::EXE_EXTENSION;
594 #[cfg(target_os = "linux")]
596 pub const FAMILY: &'static str = "unix";
597 pub const OS: &'static str = "linux";
598 pub const DLL_PREFIX: &'static str = "lib";
599 pub const DLL_SUFFIX: &'static str = ".so";
600 pub const DLL_EXTENSION: &'static str = "so";
601 pub const EXE_SUFFIX: &'static str = "";
602 pub const EXE_EXTENSION: &'static str = "";
605 #[cfg(target_os = "macos")]
607 pub const FAMILY: &'static str = "unix";
608 pub const OS: &'static str = "macos";
609 pub const DLL_PREFIX: &'static str = "lib";
610 pub const DLL_SUFFIX: &'static str = ".dylib";
611 pub const DLL_EXTENSION: &'static str = "dylib";
612 pub const EXE_SUFFIX: &'static str = "";
613 pub const EXE_EXTENSION: &'static str = "";
616 #[cfg(target_os = "ios")]
618 pub const FAMILY: &'static str = "unix";
619 pub const OS: &'static str = "ios";
620 pub const DLL_PREFIX: &'static str = "lib";
621 pub const DLL_SUFFIX: &'static str = ".dylib";
622 pub const DLL_EXTENSION: &'static str = "dylib";
623 pub const EXE_SUFFIX: &'static str = "";
624 pub const EXE_EXTENSION: &'static str = "";
627 #[cfg(target_os = "freebsd")]
629 pub const FAMILY: &'static str = "unix";
630 pub const OS: &'static str = "freebsd";
631 pub const DLL_PREFIX: &'static str = "lib";
632 pub const DLL_SUFFIX: &'static str = ".so";
633 pub const DLL_EXTENSION: &'static str = "so";
634 pub const EXE_SUFFIX: &'static str = "";
635 pub const EXE_EXTENSION: &'static str = "";
638 #[cfg(target_os = "dragonfly")]
640 pub const FAMILY: &'static str = "unix";
641 pub const OS: &'static str = "dragonfly";
642 pub const DLL_PREFIX: &'static str = "lib";
643 pub const DLL_SUFFIX: &'static str = ".so";
644 pub const DLL_EXTENSION: &'static str = "so";
645 pub const EXE_SUFFIX: &'static str = "";
646 pub const EXE_EXTENSION: &'static str = "";
649 #[cfg(target_os = "bitrig")]
651 pub const FAMILY: &'static str = "unix";
652 pub const OS: &'static str = "bitrig";
653 pub const DLL_PREFIX: &'static str = "lib";
654 pub const DLL_SUFFIX: &'static str = ".so";
655 pub const DLL_EXTENSION: &'static str = "so";
656 pub const EXE_SUFFIX: &'static str = "";
657 pub const EXE_EXTENSION: &'static str = "";
660 #[cfg(target_os = "openbsd")]
662 pub const FAMILY: &'static str = "unix";
663 pub const OS: &'static str = "openbsd";
664 pub const DLL_PREFIX: &'static str = "lib";
665 pub const DLL_SUFFIX: &'static str = ".so";
666 pub const DLL_EXTENSION: &'static str = "so";
667 pub const EXE_SUFFIX: &'static str = "";
668 pub const EXE_EXTENSION: &'static str = "";
671 #[cfg(target_os = "android")]
673 pub const FAMILY: &'static str = "unix";
674 pub const OS: &'static str = "android";
675 pub const DLL_PREFIX: &'static str = "lib";
676 pub const DLL_SUFFIX: &'static str = ".so";
677 pub const DLL_EXTENSION: &'static str = "so";
678 pub const EXE_SUFFIX: &'static str = "";
679 pub const EXE_EXTENSION: &'static str = "";
682 #[cfg(target_os = "windows")]
684 pub const FAMILY: &'static str = "windows";
685 pub const OS: &'static str = "windows";
686 pub const DLL_PREFIX: &'static str = "";
687 pub const DLL_SUFFIX: &'static str = ".dll";
688 pub const DLL_EXTENSION: &'static str = "dll";
689 pub const EXE_SUFFIX: &'static str = ".exe";
690 pub const EXE_EXTENSION: &'static str = "exe";
693 #[cfg(target_arch = "x86")]
695 pub const ARCH: &'static str = "x86";
698 #[cfg(target_arch = "x86_64")]
700 pub const ARCH: &'static str = "x86_64";
703 #[cfg(target_arch = "arm")]
705 pub const ARCH: &'static str = "arm";
708 #[cfg(target_arch = "aarch64")]
710 pub const ARCH: &'static str = "aarch64";
713 #[cfg(target_arch = "mips")]
715 pub const ARCH: &'static str = "mips";
718 #[cfg(target_arch = "mipsel")]
720 pub const ARCH: &'static str = "mipsel";
723 #[cfg(target_arch = "powerpc")]
725 pub const ARCH: &'static str = "powerpc";
734 use rand::{self, Rng};
735 use ffi::{OsString, OsStr};
736 use path::{Path, PathBuf};
738 fn make_rand_name() -> OsString {
739 let mut rng = rand::thread_rng();
740 let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
741 .collect::<String>());
742 let n = OsString::from_string(n);
743 assert!(var_os(&n).is_none());
747 fn eq(a: Option<OsString>, b: Option<&str>) {
748 assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::from_str).map(|s| &*s));
753 let n = make_rand_name();
754 set_var(&n, "VALUE");
755 eq(var_os(&n), Some("VALUE"));
759 fn test_remove_var() {
760 let n = make_rand_name();
761 set_var(&n, "VALUE");
763 eq(var_os(&n), None);
767 fn test_set_var_overwrite() {
768 let n = make_rand_name();
771 eq(var_os(&n), Some("2"));
773 eq(var_os(&n), Some(""));
778 let mut s = "".to_string();
781 s.push_str("aaaaaaaaaa");
784 let n = make_rand_name();
786 eq(var_os(&n), Some(&s));
790 fn test_self_exe_path() {
791 let path = current_exe();
792 assert!(path.is_ok());
793 let path = path.unwrap();
795 // Hard to test this function
796 assert!(path.is_absolute());
800 fn test_env_set_get_huge() {
801 let n = make_rand_name();
802 let s = repeat("x").take(10000).collect::<String>();
804 eq(var_os(&n), Some(&s));
806 eq(var_os(&n), None);
810 fn test_env_set_var() {
811 let n = make_rand_name();
813 let mut e = vars_os();
814 set_var(&n, "VALUE");
815 assert!(!e.any(|(k, v)| {
816 &*k == &*n && &*v == "VALUE"
819 assert!(vars_os().any(|(k, v)| {
820 &*k == &*n && &*v == "VALUE"
826 assert!((!Path::new("test-path").is_absolute()));
828 current_dir().unwrap();
833 fn split_paths_windows() {
834 fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
835 split_paths(unparsed).collect::<Vec<_>>() ==
836 parsed.iter().map(|s| PathBuf::new(*s)).collect::<Vec<_>>()
839 assert!(check_parse("", &mut [""]));
840 assert!(check_parse(r#""""#, &mut [""]));
841 assert!(check_parse(";;", &mut ["", "", ""]));
842 assert!(check_parse(r"c:\", &mut [r"c:\"]));
843 assert!(check_parse(r"c:\;", &mut [r"c:\", ""]));
844 assert!(check_parse(r"c:\;c:\Program Files\",
845 &mut [r"c:\", r"c:\Program Files\"]));
846 assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"]));
847 assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#,
848 &mut [r"c:\", r"c:\foo;bar\", r"c:\baz"]));
853 fn split_paths_unix() {
854 fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
855 split_paths(unparsed).collect::<Vec<_>>() ==
856 parsed.iter().map(|s| PathBuf::new(*s)).collect::<Vec<_>>()
859 assert!(check_parse("", &mut [""]));
860 assert!(check_parse("::", &mut ["", "", ""]));
861 assert!(check_parse("/", &mut ["/"]));
862 assert!(check_parse("/:", &mut ["/", ""]));
863 assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"]));
868 fn join_paths_unix() {
869 fn test_eq(input: &[&str], output: &str) -> bool {
870 &*join_paths(input.iter().cloned()).unwrap() ==
871 OsStr::from_str(output)
874 assert!(test_eq(&[], ""));
875 assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"],
876 "/bin:/usr/bin:/usr/local/bin"));
877 assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""],
878 ":/bin:::/usr/bin:"));
879 assert!(join_paths(["/te:st"].iter().cloned()).is_err());
884 fn join_paths_windows() {
885 fn test_eq(input: &[&str], output: &str) -> bool {
886 &*join_paths(input.iter().cloned()).unwrap() ==
887 OsStr::from_str(output)
890 assert!(test_eq(&[], ""));
891 assert!(test_eq(&[r"c:\windows", r"c:\"],
893 assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""],
894 r";c:\windows;;;c:\;"));
895 assert!(test_eq(&[r"c:\te;st", r"c:\"],
896 r#""c:\te;st";c:\"#));
897 assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err());