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