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")]
20 use ffi::{OsStr, OsString};
23 use path::{Path, PathBuf};
24 use sys::os as os_imp;
26 /// Returns the current working directory as a `PathBuf`.
30 /// Returns an `Err` if the current working directory value is invalid.
33 /// * Current directory does not exist.
34 /// * There are insufficient permissions to access the current directory.
41 /// // We assume that we are in a valid directory.
42 /// let p = env::current_dir().unwrap();
43 /// println!("The current directory is {}", p.display());
45 #[stable(feature = "env", since = "1.0.0")]
46 pub fn current_dir() -> io::Result<PathBuf> {
50 /// Changes the current working directory to the specified path, returning
51 /// whether the change was completed successfully or not.
57 /// use std::path::Path;
59 /// let root = Path::new("/");
60 /// assert!(env::set_current_dir(&root).is_ok());
61 /// println!("Successfully changed working directory to {}!", root.display());
63 #[stable(feature = "env", since = "1.0.0")]
64 pub fn set_current_dir<P: AsRef<Path>>(p: P) -> io::Result<()> {
65 os_imp::chdir(p.as_ref())
68 /// An iterator over a snapshot of the environment variables of this process.
70 /// This iterator is created through `std::env::vars()` and yields `(String,
72 #[stable(feature = "env", since = "1.0.0")]
73 pub struct Vars { inner: VarsOs }
75 /// An iterator over a snapshot of the environment variables of this process.
77 /// This iterator is created through `std::env::vars_os()` and yields
78 /// `(OsString, OsString)` pairs.
79 #[stable(feature = "env", since = "1.0.0")]
80 pub struct VarsOs { inner: os_imp::Env }
82 /// Returns an iterator of (variable, value) pairs of strings, for all the
83 /// environment variables of the current process.
85 /// The returned iterator contains a snapshot of the process's environment
86 /// variables at the time of this invocation. Modifications to environment
87 /// variables afterwards will not be reflected in the returned iterator.
91 /// While iterating, the returned iterator will panic if any key or value in the
92 /// environment is not valid unicode. If this is not desired, consider using the
93 /// `env::vars_os` function.
100 /// // We will iterate through the references to the element returned by
102 /// for (key, value) in env::vars() {
103 /// println!("{}: {}", key, value);
106 #[stable(feature = "env", since = "1.0.0")]
107 pub fn vars() -> Vars {
108 Vars { inner: vars_os() }
111 /// Returns an iterator of (variable, value) pairs of OS strings, for all the
112 /// environment variables of the current process.
114 /// The returned iterator contains a snapshot of the process's environment
115 /// variables at the time of this invocation. Modifications to environment
116 /// variables afterwards will not be reflected in the returned iterator.
123 /// // We will iterate through the references to the element returned by
124 /// // env::vars_os();
125 /// for (key, value) in env::vars_os() {
126 /// println!("{:?}: {:?}", key, value);
129 #[stable(feature = "env", since = "1.0.0")]
130 pub fn vars_os() -> VarsOs {
131 VarsOs { inner: os_imp::env() }
134 #[stable(feature = "env", since = "1.0.0")]
135 impl Iterator for Vars {
136 type Item = (String, String);
137 fn next(&mut self) -> Option<(String, String)> {
138 self.inner.next().map(|(a, b)| {
139 (a.into_string().unwrap(), b.into_string().unwrap())
142 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
145 #[stable(feature = "env", since = "1.0.0")]
146 impl Iterator for VarsOs {
147 type Item = (OsString, OsString);
148 fn next(&mut self) -> Option<(OsString, OsString)> { self.inner.next() }
149 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
152 /// Fetches the environment variable `key` from the current process.
154 /// The returned result is `Ok(s)` if the environment variable is present and is
155 /// valid unicode. If the environment variable is not present, or it is not
156 /// valid unicode, then `Err` will be returned.
163 /// let key = "HOME";
164 /// match env::var(key) {
165 /// Ok(val) => println!("{}: {:?}", key, val),
166 /// Err(e) => println!("couldn't interpret {}: {}", key, e),
169 #[stable(feature = "env", since = "1.0.0")]
170 pub fn var<K: AsRef<OsStr>>(key: K) -> Result<String, VarError> {
174 fn _var(key: &OsStr) -> Result<String, VarError> {
176 Some(s) => s.into_string().map_err(VarError::NotUnicode),
177 None => Err(VarError::NotPresent)
181 /// Fetches the environment variable `key` from the current process, returning
182 /// `None` if the variable isn't set.
189 /// let key = "HOME";
190 /// match env::var_os(key) {
191 /// Some(val) => println!("{}: {:?}", key, val),
192 /// None => println!("{} is not defined in the environment.", key)
195 #[stable(feature = "env", since = "1.0.0")]
196 pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
197 _var_os(key.as_ref())
200 fn _var_os(key: &OsStr) -> Option<OsString> {
201 os_imp::getenv(key).unwrap_or_else(|e| {
202 panic!("failed to get environment variable `{:?}`: {}", key, e)
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(#[stable(feature = "env", since = "1.0.0")] 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
247 /// Note that while concurrent access to environment variables is safe in Rust,
248 /// some platforms only expose inherently unsafe non-threadsafe APIs for
249 /// inspecting the environment. As a result extra care needs to be taken when
250 /// auditing calls to unsafe external FFI functions to ensure that any external
251 /// environment accesses are properly synchronized with accesses in Rust.
253 /// Discussion of this unsafety on Unix may be found in:
255 /// - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188)
256 /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
260 /// This function may panic if `key` is empty, contains an ASCII equals sign
261 /// `'='` or the NUL character `'\0'`, or when the value contains the NUL
270 /// env::set_var(key, "VALUE");
271 /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
273 #[stable(feature = "env", since = "1.0.0")]
274 pub fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(k: K, v: V) {
275 _set_var(k.as_ref(), v.as_ref())
278 fn _set_var(k: &OsStr, v: &OsStr) {
279 os_imp::setenv(k, v).unwrap_or_else(|e| {
280 panic!("failed to set environment variable `{:?}` to `{:?}`: {}",
285 /// Removes an environment variable from the environment of the currently running process.
287 /// Note that while concurrent access to environment variables is safe in Rust,
288 /// some platforms only expose inherently unsafe non-threadsafe APIs for
289 /// inspecting the environment. As a result extra care needs to be taken when
290 /// auditing calls to unsafe external FFI functions to ensure that any external
291 /// environment accesses are properly synchronized with accesses in Rust.
293 /// Discussion of this unsafety on Unix may be found in:
295 /// - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188)
296 /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
300 /// This function may panic if `key` is empty, contains an ASCII equals sign
301 /// `'='` or the NUL character `'\0'`, or when the value contains the NUL
310 /// env::set_var(key, "VALUE");
311 /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
313 /// env::remove_var(key);
314 /// assert!(env::var(key).is_err());
316 #[stable(feature = "env", since = "1.0.0")]
317 pub fn remove_var<K: AsRef<OsStr>>(k: K) {
318 _remove_var(k.as_ref())
321 fn _remove_var(k: &OsStr) {
322 os_imp::unsetenv(k).unwrap_or_else(|e| {
323 panic!("failed to remove environment variable `{:?}`: {}", k, e)
327 /// An iterator over `PathBuf` instances for parsing an environment variable
328 /// according to platform-specific conventions.
330 /// This structure is returned from `std::env::split_paths`.
331 #[stable(feature = "env", since = "1.0.0")]
332 pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> }
334 /// Parses input according to platform conventions for the `PATH`
335 /// environment variable.
337 /// Returns an iterator over the paths contained in `unparsed`.
344 /// let key = "PATH";
345 /// match env::var_os(key) {
347 /// for path in env::split_paths(&paths) {
348 /// println!("'{}'", path.display());
351 /// None => println!("{} is not defined in the environment.", key)
354 #[stable(feature = "env", since = "1.0.0")]
355 pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths {
356 SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) }
359 #[stable(feature = "env", since = "1.0.0")]
360 impl<'a> Iterator for SplitPaths<'a> {
362 fn next(&mut self) -> Option<PathBuf> { self.inner.next() }
363 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
366 /// Error type returned from `std::env::join_paths` when paths fail to be
369 #[stable(feature = "env", since = "1.0.0")]
370 pub struct JoinPathsError {
371 inner: os_imp::JoinPathsError
374 /// Joins a collection of `Path`s appropriately for the `PATH`
375 /// environment variable.
377 /// Returns an `OsString` on success.
379 /// Returns an `Err` (containing an error message) if one of the input
380 /// `Path`s contains an invalid character for constructing the `PATH`
381 /// variable (a double quote on Windows or a colon on Unix).
387 /// use std::path::PathBuf;
389 /// if let Some(path) = env::var_os("PATH") {
390 /// let mut paths = env::split_paths(&path).collect::<Vec<_>>();
391 /// paths.push(PathBuf::from("/home/xyz/bin"));
392 /// let new_path = env::join_paths(paths).unwrap();
393 /// env::set_var("PATH", &new_path);
396 #[stable(feature = "env", since = "1.0.0")]
397 pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
398 where I: IntoIterator<Item=T>, T: AsRef<OsStr>
400 os_imp::join_paths(paths.into_iter()).map_err(|e| {
401 JoinPathsError { inner: e }
405 #[stable(feature = "env", since = "1.0.0")]
406 impl fmt::Display for JoinPathsError {
407 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
412 #[stable(feature = "env", since = "1.0.0")]
413 impl Error for JoinPathsError {
414 fn description(&self) -> &str { self.inner.description() }
417 /// Returns the path of the current user's home directory if known.
421 /// Returns the value of the 'HOME' environment variable if it is set
422 /// and not equal to the empty string. Otherwise, it tries to determine the
423 /// home directory by invoking the `getpwuid_r` function on the UID of the
428 /// Returns the value of the 'HOME' environment variable if it is
429 /// set and not equal to the empty string. Otherwise, returns the value of the
430 /// 'USERPROFILE' environment variable if it is set and not equal to the empty
431 /// string. If both do not exist, [`GetUserProfileDirectory`][msdn] is used to
432 /// return the appropriate path.
434 /// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/bb762280(v=vs.85).aspx
441 /// match env::home_dir() {
442 /// Some(path) => println!("{}", path.display()),
443 /// None => println!("Impossible to get your home dir!"),
446 #[stable(feature = "env", since = "1.0.0")]
447 pub fn home_dir() -> Option<PathBuf> {
451 /// Returns the path of a temporary directory.
453 /// On Unix, returns the value of the `TMPDIR` environment variable if it is
454 /// set, otherwise for non-Android it returns `/tmp`. If Android, since there
455 /// is no global temporary folder (it is usually allocated per-app), it returns
456 /// `/data/local/tmp`.
458 /// On Windows, returns the value of, in order, the `TMP`, `TEMP`,
459 /// `USERPROFILE` environment variable if any are set and not the empty
460 /// string. Otherwise, `temp_dir` returns the path of the Windows directory.
461 /// This behavior is identical to that of [`GetTempPath`][msdn], which this
462 /// function uses internally.
464 /// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992(v=vs.85).aspx
468 /// use std::fs::File;
470 /// # fn foo() -> std::io::Result<()> {
471 /// let mut dir = env::temp_dir();
472 /// dir.push("foo.txt");
474 /// let f = try!(File::create(dir));
478 #[stable(feature = "env", since = "1.0.0")]
479 pub fn temp_dir() -> PathBuf {
483 /// Returns the full filesystem path of the current running executable.
485 /// The path returned is not necessarily a "real path" of the executable as
486 /// there may be intermediate symlinks.
490 /// Acquiring the path of the current executable is a platform-specific operation
491 /// that can fail for a good number of reasons. Some errors can include, but not
492 /// be limited to, filesystem operations failing or general syscall failures.
496 /// The output of this function should not be used in anything that might have
497 /// security implications. For example:
501 /// println!("{:?}", std::env::current_exe());
505 /// On Linux systems, if this is compiled as `foo`:
510 /// Ok("/home/alex/foo")
513 /// And you make a symbolic link of the program:
519 /// When you run it, you won't get the original executable, you'll get the
524 /// Ok("/home/alex/bar")
527 /// This sort of behavior has been known to [lead to privilege escalation] when
528 /// used incorrectly, for example.
530 /// [lead to privilege escalation]: http://securityvulns.com/Wdocument183.html
537 /// match env::current_exe() {
538 /// Ok(exe_path) => println!("Path of this executable is: {}",
539 /// exe_path.display()),
540 /// Err(e) => println!("failed to get current exe path: {}", e),
543 #[stable(feature = "env", since = "1.0.0")]
544 pub fn current_exe() -> io::Result<PathBuf> {
545 os_imp::current_exe()
548 /// An iterator over the arguments of a process, yielding a `String` value
549 /// for each argument.
551 /// This structure is created through the `std::env::args` method.
552 #[stable(feature = "env", since = "1.0.0")]
553 pub struct Args { inner: ArgsOs }
555 /// An iterator over the arguments of a process, yielding an `OsString` value
556 /// for each argument.
558 /// This structure is created through the `std::env::args_os` method.
559 #[stable(feature = "env", since = "1.0.0")]
560 pub struct ArgsOs { inner: os_imp::Args }
562 /// Returns the arguments which this program was started with (normally passed
563 /// via the command line).
565 /// The first element is traditionally the path of the executable, but it can be
566 /// set to arbitrary text, and may not even exist. This means this property should
567 /// not be relied upon for security purposes.
571 /// The returned iterator will panic during iteration if any argument to the
572 /// process is not valid unicode. If this is not desired,
573 /// use the `args_os` function instead.
580 /// // Prints each argument on a separate line
581 /// for argument in env::args() {
582 /// println!("{}", argument);
585 #[stable(feature = "env", since = "1.0.0")]
586 pub fn args() -> Args {
587 Args { inner: args_os() }
590 /// Returns the arguments which this program was started with (normally passed
591 /// via the command line).
593 /// The first element is traditionally the path of the executable, but it can be
594 /// set to arbitrary text, and it may not even exist, so this property should
595 /// not be relied upon for security purposes.
602 /// // Prints each argument on a separate line
603 /// for argument in env::args_os() {
604 /// println!("{:?}", argument);
607 #[stable(feature = "env", since = "1.0.0")]
608 pub fn args_os() -> ArgsOs {
609 ArgsOs { inner: os_imp::args() }
612 #[stable(feature = "env", since = "1.0.0")]
613 impl Iterator for Args {
615 fn next(&mut self) -> Option<String> {
616 self.inner.next().map(|s| s.into_string().unwrap())
618 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
621 #[stable(feature = "env", since = "1.0.0")]
622 impl ExactSizeIterator for Args {
623 fn len(&self) -> usize { self.inner.len() }
626 #[stable(feature = "env_iterators", since = "1.11.0")]
627 impl DoubleEndedIterator for Args {
628 fn next_back(&mut self) -> Option<String> {
629 self.inner.next_back().map(|s| s.into_string().unwrap())
633 #[stable(feature = "env", since = "1.0.0")]
634 impl Iterator for ArgsOs {
635 type Item = OsString;
636 fn next(&mut self) -> Option<OsString> { self.inner.next() }
637 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
640 #[stable(feature = "env", since = "1.0.0")]
641 impl ExactSizeIterator for ArgsOs {
642 fn len(&self) -> usize { self.inner.len() }
645 #[stable(feature = "env_iterators", since = "1.11.0")]
646 impl DoubleEndedIterator for ArgsOs {
647 fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() }
649 /// Constants associated with the current target
650 #[stable(feature = "env", since = "1.0.0")]
652 /// A string describing the architecture of the CPU that is currently
655 /// Some possible values:
666 #[stable(feature = "env", since = "1.0.0")]
667 pub const ARCH: &'static str = super::arch::ARCH;
669 /// The family of the operating system. Example value is `unix`.
671 /// Some possible values:
675 #[stable(feature = "env", since = "1.0.0")]
676 pub const FAMILY: &'static str = super::os::FAMILY;
678 /// A string describing the specific operating system in use.
679 /// Example value is `linux`.
681 /// Some possible values:
694 #[stable(feature = "env", since = "1.0.0")]
695 pub const OS: &'static str = super::os::OS;
697 /// Specifies the filename prefix used for shared libraries on this
698 /// platform. Example value is `lib`.
700 /// Some possible values:
703 /// - `""` (an empty string)
704 #[stable(feature = "env", since = "1.0.0")]
705 pub const DLL_PREFIX: &'static str = super::os::DLL_PREFIX;
707 /// Specifies the filename suffix used for shared libraries on this
708 /// platform. Example value is `.so`.
710 /// Some possible values:
715 #[stable(feature = "env", since = "1.0.0")]
716 pub const DLL_SUFFIX: &'static str = super::os::DLL_SUFFIX;
718 /// Specifies the file extension used for shared libraries on this
719 /// platform that goes after the dot. Example value is `so`.
721 /// Some possible values:
726 #[stable(feature = "env", since = "1.0.0")]
727 pub const DLL_EXTENSION: &'static str = super::os::DLL_EXTENSION;
729 /// Specifies the filename suffix used for executable binaries on this
730 /// platform. Example value is `.exe`.
732 /// Some possible values:
737 /// - `""` (an empty string)
738 #[stable(feature = "env", since = "1.0.0")]
739 pub const EXE_SUFFIX: &'static str = super::os::EXE_SUFFIX;
741 /// Specifies the file extension, if any, used for executable binaries
742 /// on this platform. Example value is `exe`.
744 /// Some possible values:
747 /// - `""` (an empty string)
748 #[stable(feature = "env", since = "1.0.0")]
749 pub const EXE_EXTENSION: &'static str = super::os::EXE_EXTENSION;
753 #[cfg(target_os = "linux")]
755 pub const FAMILY: &'static str = "unix";
756 pub const OS: &'static str = "linux";
757 pub const DLL_PREFIX: &'static str = "lib";
758 pub const DLL_SUFFIX: &'static str = ".so";
759 pub const DLL_EXTENSION: &'static str = "so";
760 pub const EXE_SUFFIX: &'static str = "";
761 pub const EXE_EXTENSION: &'static str = "";
764 #[cfg(target_os = "macos")]
766 pub const FAMILY: &'static str = "unix";
767 pub const OS: &'static str = "macos";
768 pub const DLL_PREFIX: &'static str = "lib";
769 pub const DLL_SUFFIX: &'static str = ".dylib";
770 pub const DLL_EXTENSION: &'static str = "dylib";
771 pub const EXE_SUFFIX: &'static str = "";
772 pub const EXE_EXTENSION: &'static str = "";
775 #[cfg(target_os = "ios")]
777 pub const FAMILY: &'static str = "unix";
778 pub const OS: &'static str = "ios";
779 pub const DLL_PREFIX: &'static str = "lib";
780 pub const DLL_SUFFIX: &'static str = ".dylib";
781 pub const DLL_EXTENSION: &'static str = "dylib";
782 pub const EXE_SUFFIX: &'static str = "";
783 pub const EXE_EXTENSION: &'static str = "";
786 #[cfg(target_os = "freebsd")]
788 pub const FAMILY: &'static str = "unix";
789 pub const OS: &'static str = "freebsd";
790 pub const DLL_PREFIX: &'static str = "lib";
791 pub const DLL_SUFFIX: &'static str = ".so";
792 pub const DLL_EXTENSION: &'static str = "so";
793 pub const EXE_SUFFIX: &'static str = "";
794 pub const EXE_EXTENSION: &'static str = "";
797 #[cfg(target_os = "dragonfly")]
799 pub const FAMILY: &'static str = "unix";
800 pub const OS: &'static str = "dragonfly";
801 pub const DLL_PREFIX: &'static str = "lib";
802 pub const DLL_SUFFIX: &'static str = ".so";
803 pub const DLL_EXTENSION: &'static str = "so";
804 pub const EXE_SUFFIX: &'static str = "";
805 pub const EXE_EXTENSION: &'static str = "";
808 #[cfg(target_os = "bitrig")]
810 pub const FAMILY: &'static str = "unix";
811 pub const OS: &'static str = "bitrig";
812 pub const DLL_PREFIX: &'static str = "lib";
813 pub const DLL_SUFFIX: &'static str = ".so";
814 pub const DLL_EXTENSION: &'static str = "so";
815 pub const EXE_SUFFIX: &'static str = "";
816 pub const EXE_EXTENSION: &'static str = "";
819 #[cfg(target_os = "netbsd")]
821 pub const FAMILY: &'static str = "unix";
822 pub const OS: &'static str = "netbsd";
823 pub const DLL_PREFIX: &'static str = "lib";
824 pub const DLL_SUFFIX: &'static str = ".so";
825 pub const DLL_EXTENSION: &'static str = "so";
826 pub const EXE_SUFFIX: &'static str = "";
827 pub const EXE_EXTENSION: &'static str = "";
830 #[cfg(target_os = "openbsd")]
832 pub const FAMILY: &'static str = "unix";
833 pub const OS: &'static str = "openbsd";
834 pub const DLL_PREFIX: &'static str = "lib";
835 pub const DLL_SUFFIX: &'static str = ".so";
836 pub const DLL_EXTENSION: &'static str = "so";
837 pub const EXE_SUFFIX: &'static str = "";
838 pub const EXE_EXTENSION: &'static str = "";
841 #[cfg(target_os = "android")]
843 pub const FAMILY: &'static str = "unix";
844 pub const OS: &'static str = "android";
845 pub const DLL_PREFIX: &'static str = "lib";
846 pub const DLL_SUFFIX: &'static str = ".so";
847 pub const DLL_EXTENSION: &'static str = "so";
848 pub const EXE_SUFFIX: &'static str = "";
849 pub const EXE_EXTENSION: &'static str = "";
852 #[cfg(target_os = "solaris")]
854 pub const FAMILY: &'static str = "unix";
855 pub const OS: &'static str = "solaris";
856 pub const DLL_PREFIX: &'static str = "lib";
857 pub const DLL_SUFFIX: &'static str = ".so";
858 pub const DLL_EXTENSION: &'static str = "so";
859 pub const EXE_SUFFIX: &'static str = "";
860 pub const EXE_EXTENSION: &'static str = "";
863 #[cfg(target_os = "windows")]
865 pub const FAMILY: &'static str = "windows";
866 pub const OS: &'static str = "windows";
867 pub const DLL_PREFIX: &'static str = "";
868 pub const DLL_SUFFIX: &'static str = ".dll";
869 pub const DLL_EXTENSION: &'static str = "dll";
870 pub const EXE_SUFFIX: &'static str = ".exe";
871 pub const EXE_EXTENSION: &'static str = "exe";
874 #[cfg(all(target_os = "nacl", not(target_arch = "le32")))]
876 pub const FAMILY: &'static str = "unix";
877 pub const OS: &'static str = "nacl";
878 pub const DLL_PREFIX: &'static str = "lib";
879 pub const DLL_SUFFIX: &'static str = ".so";
880 pub const DLL_EXTENSION: &'static str = "so";
881 pub const EXE_SUFFIX: &'static str = ".nexe";
882 pub const EXE_EXTENSION: &'static str = "nexe";
884 #[cfg(all(target_os = "nacl", target_arch = "le32"))]
886 pub const FAMILY: &'static str = "unix";
887 pub const OS: &'static str = "pnacl";
888 pub const DLL_PREFIX: &'static str = "lib";
889 pub const DLL_SUFFIX: &'static str = ".pso";
890 pub const DLL_EXTENSION: &'static str = "pso";
891 pub const EXE_SUFFIX: &'static str = ".pexe";
892 pub const EXE_EXTENSION: &'static str = "pexe";
895 #[cfg(target_os = "emscripten")]
897 pub const FAMILY: &'static str = "unix";
898 pub const OS: &'static str = "emscripten";
899 pub const DLL_PREFIX: &'static str = "lib";
900 pub const DLL_SUFFIX: &'static str = ".so";
901 pub const DLL_EXTENSION: &'static str = "so";
902 pub const EXE_SUFFIX: &'static str = ".js";
903 pub const EXE_EXTENSION: &'static str = "js";
906 #[cfg(target_os = "haiku")]
908 pub const FAMILY: &'static str = "unix";
909 pub const OS: &'static str = "haiku";
910 pub const DLL_PREFIX: &'static str = "lib";
911 pub const DLL_SUFFIX: &'static str = ".so";
912 pub const DLL_EXTENSION: &'static str = "so";
913 pub const EXE_SUFFIX: &'static str = "";
914 pub const EXE_EXTENSION: &'static str = "";
917 #[cfg(target_arch = "x86")]
919 pub const ARCH: &'static str = "x86";
922 #[cfg(target_arch = "x86_64")]
924 pub const ARCH: &'static str = "x86_64";
927 #[cfg(target_arch = "arm")]
929 pub const ARCH: &'static str = "arm";
932 #[cfg(target_arch = "aarch64")]
934 pub const ARCH: &'static str = "aarch64";
937 #[cfg(target_arch = "mips")]
939 pub const ARCH: &'static str = "mips";
942 #[cfg(target_arch = "mips64")]
944 pub const ARCH: &'static str = "mips64";
947 #[cfg(target_arch = "powerpc")]
949 pub const ARCH: &'static str = "powerpc";
952 #[cfg(target_arch = "powerpc64")]
954 pub const ARCH: &'static str = "powerpc64";
957 #[cfg(target_arch = "s390x")]
959 pub const ARCH: &'static str = "s390x";
962 #[cfg(target_arch = "le32")]
964 pub const ARCH: &'static str = "le32";
967 #[cfg(target_arch = "asmjs")]
969 pub const ARCH: &'static str = "asmjs";
977 use rand::{self, Rng};
978 use ffi::{OsString, OsStr};
979 use path::{Path, PathBuf};
981 fn make_rand_name() -> OsString {
982 let mut rng = rand::thread_rng();
983 let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
984 .collect::<String>());
985 let n = OsString::from(n);
986 assert!(var_os(&n).is_none());
990 fn eq(a: Option<OsString>, b: Option<&str>) {
991 assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
996 let n = make_rand_name();
997 set_var(&n, "VALUE");
998 eq(var_os(&n), Some("VALUE"));
1002 fn test_remove_var() {
1003 let n = make_rand_name();
1004 set_var(&n, "VALUE");
1006 eq(var_os(&n), None);
1010 fn test_set_var_overwrite() {
1011 let n = make_rand_name();
1014 eq(var_os(&n), Some("2"));
1016 eq(var_os(&n), Some(""));
1021 let mut s = "".to_string();
1024 s.push_str("aaaaaaaaaa");
1027 let n = make_rand_name();
1029 eq(var_os(&n), Some(&s));
1033 fn test_self_exe_path() {
1034 let path = current_exe();
1035 assert!(path.is_ok());
1036 let path = path.unwrap();
1038 // Hard to test this function
1039 assert!(path.is_absolute());
1043 fn test_env_set_get_huge() {
1044 let n = make_rand_name();
1045 let s = repeat("x").take(10000).collect::<String>();
1047 eq(var_os(&n), Some(&s));
1049 eq(var_os(&n), None);
1053 fn test_env_set_var() {
1054 let n = make_rand_name();
1056 let mut e = vars_os();
1057 set_var(&n, "VALUE");
1058 assert!(!e.any(|(k, v)| {
1059 &*k == &*n && &*v == "VALUE"
1062 assert!(vars_os().any(|(k, v)| {
1063 &*k == &*n && &*v == "VALUE"
1069 assert!((!Path::new("test-path").is_absolute()));
1071 current_dir().unwrap();
1076 fn split_paths_windows() {
1077 fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
1078 split_paths(unparsed).collect::<Vec<_>>() ==
1079 parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
1082 assert!(check_parse("", &mut [""]));
1083 assert!(check_parse(r#""""#, &mut [""]));
1084 assert!(check_parse(";;", &mut ["", "", ""]));
1085 assert!(check_parse(r"c:\", &mut [r"c:\"]));
1086 assert!(check_parse(r"c:\;", &mut [r"c:\", ""]));
1087 assert!(check_parse(r"c:\;c:\Program Files\",
1088 &mut [r"c:\", r"c:\Program Files\"]));
1089 assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"]));
1090 assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#,
1091 &mut [r"c:\", r"c:\foo;bar\", r"c:\baz"]));
1096 fn split_paths_unix() {
1097 fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
1098 split_paths(unparsed).collect::<Vec<_>>() ==
1099 parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
1102 assert!(check_parse("", &mut [""]));
1103 assert!(check_parse("::", &mut ["", "", ""]));
1104 assert!(check_parse("/", &mut ["/"]));
1105 assert!(check_parse("/:", &mut ["/", ""]));
1106 assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"]));
1111 fn join_paths_unix() {
1112 fn test_eq(input: &[&str], output: &str) -> bool {
1113 &*join_paths(input.iter().cloned()).unwrap() ==
1117 assert!(test_eq(&[], ""));
1118 assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"],
1119 "/bin:/usr/bin:/usr/local/bin"));
1120 assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""],
1121 ":/bin:::/usr/bin:"));
1122 assert!(join_paths(["/te:st"].iter().cloned()).is_err());
1127 fn join_paths_windows() {
1128 fn test_eq(input: &[&str], output: &str) -> bool {
1129 &*join_paths(input.iter().cloned()).unwrap() ==
1133 assert!(test_eq(&[], ""));
1134 assert!(test_eq(&[r"c:\windows", r"c:\"],
1135 r"c:\windows;c:\"));
1136 assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""],
1137 r";c:\windows;;;c:\;"));
1138 assert!(test_eq(&[r"c:\te;st", r"c:\"],
1139 r#""c:\te;st";c:\"#));
1140 assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err());