]> git.proxmox.com Git - rustc.git/blame - src/libstd/env.rs
New upstream version 1.13.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 18
85aaf69f 19use error::Error;
c34b1796 20use ffi::{OsStr, OsString};
85aaf69f 21use fmt;
c34b1796
AL
22use io;
23use path::{Path, PathBuf};
85aaf69f
SL
24use sys::os as os_imp;
25
d9579d0f 26/// Returns the current working directory as a `PathBuf`.
85aaf69f
SL
27///
28/// # Errors
29///
30/// Returns an `Err` if the current working directory value is invalid.
31/// Possible cases:
32///
33/// * Current directory does not exist.
34/// * There are insufficient permissions to access the current directory.
85aaf69f 35///
c34b1796 36/// # Examples
85aaf69f 37///
c34b1796 38/// ```
85aaf69f
SL
39/// use std::env;
40///
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());
44/// ```
c34b1796
AL
45#[stable(feature = "env", since = "1.0.0")]
46pub fn current_dir() -> io::Result<PathBuf> {
85aaf69f
SL
47 os_imp::getcwd()
48}
49
50/// Changes the current working directory to the specified path, returning
51/// whether the change was completed successfully or not.
52///
c34b1796 53/// # Examples
85aaf69f 54///
c34b1796 55/// ```
85aaf69f 56/// use std::env;
c34b1796 57/// use std::path::Path;
85aaf69f
SL
58///
59/// let root = Path::new("/");
60/// assert!(env::set_current_dir(&root).is_ok());
61/// println!("Successfully changed working directory to {}!", root.display());
62/// ```
c34b1796 63#[stable(feature = "env", since = "1.0.0")]
d9579d0f 64pub fn set_current_dir<P: AsRef<Path>>(p: P) -> io::Result<()> {
c34b1796 65 os_imp::chdir(p.as_ref())
85aaf69f
SL
66}
67
85aaf69f
SL
68/// An iterator over a snapshot of the environment variables of this process.
69///
70/// This iterator is created through `std::env::vars()` and yields `(String,
71/// String)` pairs.
c34b1796 72#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
73pub struct Vars { inner: VarsOs }
74
75/// An iterator over a snapshot of the environment variables of this process.
76///
77/// This iterator is created through `std::env::vars_os()` and yields
78/// `(OsString, OsString)` pairs.
c34b1796 79#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
80pub struct VarsOs { inner: os_imp::Env }
81
82/// Returns an iterator of (variable, value) pairs of strings, for all the
83/// environment variables of the current process.
84///
85/// The returned iterator contains a snapshot of the process's environment
9e0c209e 86/// variables at the time of this invocation. Modifications to environment
85aaf69f
SL
87/// variables afterwards will not be reflected in the returned iterator.
88///
89/// # Panics
90///
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.
94///
c34b1796 95/// # Examples
85aaf69f 96///
c34b1796 97/// ```
85aaf69f
SL
98/// use std::env;
99///
100/// // We will iterate through the references to the element returned by
101/// // env::vars();
102/// for (key, value) in env::vars() {
103/// println!("{}: {}", key, value);
104/// }
105/// ```
c34b1796 106#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
107pub fn vars() -> Vars {
108 Vars { inner: vars_os() }
109}
110
111/// Returns an iterator of (variable, value) pairs of OS strings, for all the
112/// environment variables of the current process.
113///
114/// The returned iterator contains a snapshot of the process's environment
9e0c209e 115/// variables at the time of this invocation. Modifications to environment
85aaf69f
SL
116/// variables afterwards will not be reflected in the returned iterator.
117///
c34b1796 118/// # Examples
85aaf69f 119///
c34b1796 120/// ```
85aaf69f
SL
121/// use std::env;
122///
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);
127/// }
128/// ```
c34b1796 129#[stable(feature = "env", since = "1.0.0")]
85aaf69f 130pub fn vars_os() -> VarsOs {
85aaf69f
SL
131 VarsOs { inner: os_imp::env() }
132}
133
c34b1796 134#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
135impl 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())
140 })
141 }
142 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
143}
144
c34b1796 145#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
146impl 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() }
150}
151
152/// Fetches the environment variable `key` from the current process.
153///
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.
157///
c34b1796 158/// # Examples
85aaf69f 159///
c34b1796 160/// ```
85aaf69f
SL
161/// use std::env;
162///
163/// let key = "HOME";
164/// match env::var(key) {
165/// Ok(val) => println!("{}: {:?}", key, val),
166/// Err(e) => println!("couldn't interpret {}: {}", key, e),
167/// }
168/// ```
c34b1796 169#[stable(feature = "env", since = "1.0.0")]
d9579d0f 170pub fn var<K: AsRef<OsStr>>(key: K) -> Result<String, VarError> {
e9174d1e
SL
171 _var(key.as_ref())
172}
173
174fn _var(key: &OsStr) -> Result<String, VarError> {
85aaf69f
SL
175 match var_os(key) {
176 Some(s) => s.into_string().map_err(VarError::NotUnicode),
177 None => Err(VarError::NotPresent)
178 }
179}
180
181/// Fetches the environment variable `key` from the current process, returning
54a0048b 182/// `None` if the variable isn't set.
85aaf69f 183///
c34b1796 184/// # Examples
85aaf69f 185///
c34b1796 186/// ```
85aaf69f
SL
187/// use std::env;
188///
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)
193/// }
194/// ```
c34b1796 195#[stable(feature = "env", since = "1.0.0")]
d9579d0f 196pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
e9174d1e
SL
197 _var_os(key.as_ref())
198}
199
200fn _var_os(key: &OsStr) -> Option<OsString> {
92a42be0
SL
201 os_imp::getenv(key).unwrap_or_else(|e| {
202 panic!("failed to get environment variable `{:?}`: {}", key, e)
203 })
85aaf69f
SL
204}
205
206/// Possible errors from the `env::var` method.
207#[derive(Debug, PartialEq, Eq, Clone)]
c34b1796 208#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
209pub enum VarError {
210 /// The specified environment variable was not present in the current
211 /// process's environment.
c34b1796 212 #[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
213 NotPresent,
214
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
217 /// variant.
c34b1796 218 #[stable(feature = "env", since = "1.0.0")]
7453a54e 219 NotUnicode(#[stable(feature = "env", since = "1.0.0")] OsString),
85aaf69f
SL
220}
221
c34b1796 222#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
223impl fmt::Display for VarError {
224 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
225 match *self {
226 VarError::NotPresent => write!(f, "environment variable not found"),
227 VarError::NotUnicode(ref s) => {
228 write!(f, "environment variable was not valid unicode: {:?}", s)
229 }
230 }
231 }
232}
233
c34b1796 234#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
235impl Error for VarError {
236 fn description(&self) -> &str {
237 match *self {
238 VarError::NotPresent => "environment variable not found",
239 VarError::NotUnicode(..) => "environment variable was not valid unicode",
240 }
241 }
242}
243
244/// Sets the environment variable `k` to the value `v` for the currently running
245/// process.
246///
d9579d0f
AL
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.
252///
253/// Discussion of this unsafety on Unix may be found in:
254///
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)
257///
b039eaaf
SL
258/// # Panics
259///
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
262/// character.
263///
c34b1796 264/// # Examples
85aaf69f 265///
c34b1796 266/// ```
85aaf69f
SL
267/// use std::env;
268///
269/// let key = "KEY";
270/// env::set_var(key, "VALUE");
271/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
272/// ```
c34b1796 273#[stable(feature = "env", since = "1.0.0")]
d9579d0f 274pub fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(k: K, v: V) {
e9174d1e
SL
275 _set_var(k.as_ref(), v.as_ref())
276}
277
278fn _set_var(k: &OsStr, v: &OsStr) {
92a42be0
SL
279 os_imp::setenv(k, v).unwrap_or_else(|e| {
280 panic!("failed to set environment variable `{:?}` to `{:?}`: {}",
281 k, v, e)
282 })
85aaf69f
SL
283}
284
9346a6ac 285/// Removes an environment variable from the environment of the currently running process.
c34b1796 286///
d9579d0f
AL
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.
292///
293/// Discussion of this unsafety on Unix may be found in:
294///
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)
297///
b039eaaf
SL
298/// # Panics
299///
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
302/// character.
303///
c34b1796
AL
304/// # Examples
305///
306/// ```
307/// use std::env;
308///
309/// let key = "KEY";
310/// env::set_var(key, "VALUE");
311/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
312///
313/// env::remove_var(key);
314/// assert!(env::var(key).is_err());
315/// ```
316#[stable(feature = "env", since = "1.0.0")]
d9579d0f 317pub fn remove_var<K: AsRef<OsStr>>(k: K) {
e9174d1e
SL
318 _remove_var(k.as_ref())
319}
320
321fn _remove_var(k: &OsStr) {
92a42be0
SL
322 os_imp::unsetenv(k).unwrap_or_else(|e| {
323 panic!("failed to remove environment variable `{:?}`: {}", k, e)
324 })
85aaf69f
SL
325}
326
92a42be0 327/// An iterator over `PathBuf` instances for parsing an environment variable
85aaf69f
SL
328/// according to platform-specific conventions.
329///
330/// This structure is returned from `std::env::split_paths`.
c34b1796 331#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
332pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> }
333
334/// Parses input according to platform conventions for the `PATH`
335/// environment variable.
336///
337/// Returns an iterator over the paths contained in `unparsed`.
338///
c34b1796 339/// # Examples
85aaf69f 340///
c34b1796 341/// ```
85aaf69f
SL
342/// use std::env;
343///
344/// let key = "PATH";
345/// match env::var_os(key) {
346/// Some(paths) => {
347/// for path in env::split_paths(&paths) {
348/// println!("'{}'", path.display());
349/// }
350/// }
351/// None => println!("{} is not defined in the environment.", key)
352/// }
353/// ```
c34b1796
AL
354#[stable(feature = "env", since = "1.0.0")]
355pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths {
356 SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) }
85aaf69f
SL
357}
358
c34b1796 359#[stable(feature = "env", since = "1.0.0")]
85aaf69f 360impl<'a> Iterator for SplitPaths<'a> {
c34b1796
AL
361 type Item = PathBuf;
362 fn next(&mut self) -> Option<PathBuf> { self.inner.next() }
85aaf69f
SL
363 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
364}
365
366/// Error type returned from `std::env::join_paths` when paths fail to be
367/// joined.
368#[derive(Debug)]
c34b1796 369#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
370pub struct JoinPathsError {
371 inner: os_imp::JoinPathsError
372}
373
374/// Joins a collection of `Path`s appropriately for the `PATH`
375/// environment variable.
376///
377/// Returns an `OsString` on success.
378///
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).
382///
c34b1796 383/// # Examples
85aaf69f 384///
c34b1796 385/// ```
85aaf69f 386/// use std::env;
c34b1796 387/// use std::path::PathBuf;
85aaf69f
SL
388///
389/// if let Some(path) = env::var_os("PATH") {
390/// let mut paths = env::split_paths(&path).collect::<Vec<_>>();
c34b1796 391/// paths.push(PathBuf::from("/home/xyz/bin"));
62682a34 392/// let new_path = env::join_paths(paths).unwrap();
85aaf69f
SL
393/// env::set_var("PATH", &new_path);
394/// }
395/// ```
c34b1796 396#[stable(feature = "env", since = "1.0.0")]
85aaf69f 397pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
c34b1796 398 where I: IntoIterator<Item=T>, T: AsRef<OsStr>
85aaf69f 399{
c34b1796 400 os_imp::join_paths(paths.into_iter()).map_err(|e| {
85aaf69f
SL
401 JoinPathsError { inner: e }
402 })
403}
404
c34b1796 405#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
406impl fmt::Display for JoinPathsError {
407 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
408 self.inner.fmt(f)
409 }
410}
411
c34b1796 412#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
413impl Error for JoinPathsError {
414 fn description(&self) -> &str { self.inner.description() }
415}
416
54a0048b 417/// Returns the path of the current user's home directory if known.
85aaf69f
SL
418///
419/// # Unix
420///
421/// Returns the value of the 'HOME' environment variable if it is set
92a42be0
SL
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
424/// current user.
85aaf69f
SL
425///
426/// # Windows
427///
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
b039eaaf
SL
431/// string. If both do not exist, [`GetUserProfileDirectory`][msdn] is used to
432/// return the appropriate path.
433///
434/// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/bb762280(v=vs.85).aspx
85aaf69f 435///
c34b1796 436/// # Examples
85aaf69f 437///
c34b1796 438/// ```
85aaf69f
SL
439/// use std::env;
440///
441/// match env::home_dir() {
7453a54e
SL
442/// Some(path) => println!("{}", path.display()),
443/// None => println!("Impossible to get your home dir!"),
85aaf69f
SL
444/// }
445/// ```
c34b1796
AL
446#[stable(feature = "env", since = "1.0.0")]
447pub fn home_dir() -> Option<PathBuf> {
85aaf69f
SL
448 os_imp::home_dir()
449}
450
54a0048b 451/// Returns the path of a temporary directory.
85aaf69f 452///
a7813a04
XL
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`.
457///
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.
b039eaaf
SL
463///
464/// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992(v=vs.85).aspx
c34b1796
AL
465///
466/// ```
467/// use std::env;
468/// use std::fs::File;
469///
470/// # fn foo() -> std::io::Result<()> {
471/// let mut dir = env::temp_dir();
472/// dir.push("foo.txt");
473///
474/// let f = try!(File::create(dir));
475/// # Ok(())
476/// # }
477/// ```
478#[stable(feature = "env", since = "1.0.0")]
479pub fn temp_dir() -> PathBuf {
85aaf69f
SL
480 os_imp::temp_dir()
481}
482
54a0048b 483/// Returns the full filesystem path of the current running executable.
85aaf69f 484///
54a0048b 485/// The path returned is not necessarily a "real path" of the executable as
85aaf69f
SL
486/// there may be intermediate symlinks.
487///
488/// # Errors
489///
54a0048b 490/// Acquiring the path of the current executable is a platform-specific operation
85aaf69f 491/// that can fail for a good number of reasons. Some errors can include, but not
7453a54e 492/// be limited to, filesystem operations failing or general syscall failures.
85aaf69f 493///
5bcae85e
SL
494/// # Security
495///
496/// The output of this function should not be used in anything that might have
497/// security implications. For example:
498///
499/// ```
500/// fn main() {
501/// println!("{:?}", std::env::current_exe());
502/// }
503/// ```
504///
505/// On Linux systems, if this is compiled as `foo`:
506///
507/// ```bash
508/// $ rustc foo.rs
509/// $ ./foo
510/// Ok("/home/alex/foo")
511/// ```
512///
513/// And you make a symbolic link of the program:
514///
515/// ```bash
516/// $ ln foo bar
517/// ```
518///
519/// When you run it, you won't get the original executable, you'll get the
520/// symlink:
521///
522/// ```bash
523/// $ ./bar
524/// Ok("/home/alex/bar")
525/// ```
526///
527/// This sort of behavior has been known to [lead to privilege escalation] when
528/// used incorrectly, for example.
529///
530/// [lead to privilege escalation]: http://securityvulns.com/Wdocument183.html
531///
85aaf69f
SL
532/// # Examples
533///
c34b1796 534/// ```
85aaf69f
SL
535/// use std::env;
536///
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),
541/// };
542/// ```
c34b1796
AL
543#[stable(feature = "env", since = "1.0.0")]
544pub fn current_exe() -> io::Result<PathBuf> {
85aaf69f
SL
545 os_imp::current_exe()
546}
547
c34b1796 548/// An iterator over the arguments of a process, yielding a `String` value
85aaf69f
SL
549/// for each argument.
550///
551/// This structure is created through the `std::env::args` method.
c34b1796 552#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
553pub struct Args { inner: ArgsOs }
554
555/// An iterator over the arguments of a process, yielding an `OsString` value
556/// for each argument.
557///
558/// This structure is created through the `std::env::args_os` method.
c34b1796 559#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
560pub struct ArgsOs { inner: os_imp::Args }
561
562/// Returns the arguments which this program was started with (normally passed
563/// via the command line).
564///
54a0048b 565/// The first element is traditionally the path of the executable, but it can be
7453a54e 566/// set to arbitrary text, and may not even exist. This means this property should
85aaf69f
SL
567/// not be relied upon for security purposes.
568///
569/// # Panics
570///
571/// The returned iterator will panic during iteration if any argument to the
7453a54e 572/// process is not valid unicode. If this is not desired,
85aaf69f
SL
573/// use the `args_os` function instead.
574///
c34b1796 575/// # Examples
85aaf69f 576///
c34b1796 577/// ```
85aaf69f
SL
578/// use std::env;
579///
580/// // Prints each argument on a separate line
581/// for argument in env::args() {
582/// println!("{}", argument);
583/// }
584/// ```
c34b1796 585#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
586pub fn args() -> Args {
587 Args { inner: args_os() }
588}
589
590/// Returns the arguments which this program was started with (normally passed
591/// via the command line).
592///
54a0048b 593/// The first element is traditionally the path of the executable, but it can be
85aaf69f
SL
594/// set to arbitrary text, and it may not even exist, so this property should
595/// not be relied upon for security purposes.
596///
c34b1796 597/// # Examples
85aaf69f 598///
c34b1796 599/// ```
85aaf69f
SL
600/// use std::env;
601///
602/// // Prints each argument on a separate line
603/// for argument in env::args_os() {
604/// println!("{:?}", argument);
605/// }
606/// ```
c34b1796 607#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
608pub fn args_os() -> ArgsOs {
609 ArgsOs { inner: os_imp::args() }
610}
611
c34b1796 612#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
613impl Iterator for Args {
614 type Item = String;
615 fn next(&mut self) -> Option<String> {
616 self.inner.next().map(|s| s.into_string().unwrap())
617 }
618 fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
619}
620
c34b1796 621#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
622impl ExactSizeIterator for Args {
623 fn len(&self) -> usize { self.inner.len() }
624}
625
5bcae85e
SL
626#[stable(feature = "env_iterators", since = "1.11.0")]
627impl DoubleEndedIterator for Args {
628 fn next_back(&mut self) -> Option<String> {
629 self.inner.next_back().map(|s| s.into_string().unwrap())
630 }
631}
632
c34b1796 633#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
634impl 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() }
638}
639
c34b1796 640#[stable(feature = "env", since = "1.0.0")]
85aaf69f
SL
641impl ExactSizeIterator for ArgsOs {
642 fn len(&self) -> usize { self.inner.len() }
643}
644
5bcae85e
SL
645#[stable(feature = "env_iterators", since = "1.11.0")]
646impl DoubleEndedIterator for ArgsOs {
647 fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() }
648}
85aaf69f 649/// Constants associated with the current target
c34b1796 650#[stable(feature = "env", since = "1.0.0")]
85aaf69f 651pub mod consts {
7453a54e 652 /// A string describing the architecture of the CPU that is currently
c34b1796 653 /// in use.
62682a34
SL
654 ///
655 /// Some possible values:
656 ///
657 /// - x86
658 /// - x86_64
659 /// - arm
660 /// - aarch64
661 /// - mips
9e0c209e 662 /// - mips64
62682a34 663 /// - powerpc
9cc50fc6 664 /// - powerpc64
9e0c209e 665 /// - s390x
c34b1796
AL
666 #[stable(feature = "env", since = "1.0.0")]
667 pub const ARCH: &'static str = super::arch::ARCH;
85aaf69f 668
54a0048b 669 /// The family of the operating system. Example value is `unix`.
62682a34
SL
670 ///
671 /// Some possible values:
672 ///
673 /// - unix
674 /// - windows
c34b1796
AL
675 #[stable(feature = "env", since = "1.0.0")]
676 pub const FAMILY: &'static str = super::os::FAMILY;
85aaf69f 677
54a0048b
SL
678 /// A string describing the specific operating system in use.
679 /// Example value is `linux`.
62682a34
SL
680 ///
681 /// Some possible values:
682 ///
683 /// - linux
684 /// - macos
685 /// - ios
686 /// - freebsd
687 /// - dragonfly
688 /// - bitrig
c1a9b12d 689 /// - netbsd
62682a34 690 /// - openbsd
7453a54e 691 /// - solaris
62682a34
SL
692 /// - android
693 /// - windows
c34b1796
AL
694 #[stable(feature = "env", since = "1.0.0")]
695 pub const OS: &'static str = super::os::OS;
85aaf69f
SL
696
697 /// Specifies the filename prefix used for shared libraries on this
54a0048b 698 /// platform. Example value is `lib`.
62682a34
SL
699 ///
700 /// Some possible values:
701 ///
702 /// - lib
703 /// - `""` (an empty string)
c34b1796
AL
704 #[stable(feature = "env", since = "1.0.0")]
705 pub const DLL_PREFIX: &'static str = super::os::DLL_PREFIX;
85aaf69f
SL
706
707 /// Specifies the filename suffix used for shared libraries on this
54a0048b 708 /// platform. Example value is `.so`.
62682a34
SL
709 ///
710 /// Some possible values:
711 ///
712 /// - .so
713 /// - .dylib
714 /// - .dll
c34b1796
AL
715 #[stable(feature = "env", since = "1.0.0")]
716 pub const DLL_SUFFIX: &'static str = super::os::DLL_SUFFIX;
85aaf69f
SL
717
718 /// Specifies the file extension used for shared libraries on this
54a0048b 719 /// platform that goes after the dot. Example value is `so`.
62682a34
SL
720 ///
721 /// Some possible values:
722 ///
92a42be0
SL
723 /// - so
724 /// - dylib
725 /// - dll
c34b1796
AL
726 #[stable(feature = "env", since = "1.0.0")]
727 pub const DLL_EXTENSION: &'static str = super::os::DLL_EXTENSION;
85aaf69f
SL
728
729 /// Specifies the filename suffix used for executable binaries on this
54a0048b 730 /// platform. Example value is `.exe`.
62682a34
SL
731 ///
732 /// Some possible values:
733 ///
92a42be0
SL
734 /// - .exe
735 /// - .nexe
736 /// - .pexe
62682a34 737 /// - `""` (an empty string)
c34b1796
AL
738 #[stable(feature = "env", since = "1.0.0")]
739 pub const EXE_SUFFIX: &'static str = super::os::EXE_SUFFIX;
85aaf69f
SL
740
741 /// Specifies the file extension, if any, used for executable binaries
54a0048b 742 /// on this platform. Example value is `exe`.
62682a34
SL
743 ///
744 /// Some possible values:
745 ///
746 /// - exe
747 /// - `""` (an empty string)
c34b1796
AL
748 #[stable(feature = "env", since = "1.0.0")]
749 pub const EXE_EXTENSION: &'static str = super::os::EXE_EXTENSION;
750
751}
752
753#[cfg(target_os = "linux")]
754mod os {
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 = "";
85aaf69f
SL
761 pub const EXE_EXTENSION: &'static str = "";
762}
763
85aaf69f 764#[cfg(target_os = "macos")]
c34b1796 765mod os {
85aaf69f 766 pub const FAMILY: &'static str = "unix";
85aaf69f 767 pub const OS: &'static str = "macos";
85aaf69f 768 pub const DLL_PREFIX: &'static str = "lib";
85aaf69f 769 pub const DLL_SUFFIX: &'static str = ".dylib";
85aaf69f 770 pub const DLL_EXTENSION: &'static str = "dylib";
85aaf69f 771 pub const EXE_SUFFIX: &'static str = "";
85aaf69f
SL
772 pub const EXE_EXTENSION: &'static str = "";
773}
774
85aaf69f 775#[cfg(target_os = "ios")]
c34b1796 776mod os {
85aaf69f 777 pub const FAMILY: &'static str = "unix";
85aaf69f 778 pub const OS: &'static str = "ios";
c34b1796
AL
779 pub const DLL_PREFIX: &'static str = "lib";
780 pub const DLL_SUFFIX: &'static str = ".dylib";
781 pub const DLL_EXTENSION: &'static str = "dylib";
85aaf69f 782 pub const EXE_SUFFIX: &'static str = "";
85aaf69f
SL
783 pub const EXE_EXTENSION: &'static str = "";
784}
785
85aaf69f 786#[cfg(target_os = "freebsd")]
c34b1796 787mod os {
85aaf69f 788 pub const FAMILY: &'static str = "unix";
85aaf69f 789 pub const OS: &'static str = "freebsd";
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 = "dragonfly")]
c34b1796 798mod os {
85aaf69f 799 pub const FAMILY: &'static str = "unix";
85aaf69f 800 pub const OS: &'static str = "dragonfly";
85aaf69f 801 pub const DLL_PREFIX: &'static str = "lib";
85aaf69f 802 pub const DLL_SUFFIX: &'static str = ".so";
85aaf69f 803 pub const DLL_EXTENSION: &'static str = "so";
85aaf69f 804 pub const EXE_SUFFIX: &'static str = "";
c34b1796
AL
805 pub const EXE_EXTENSION: &'static str = "";
806}
85aaf69f 807
c34b1796
AL
808#[cfg(target_os = "bitrig")]
809mod os {
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 = "";
85aaf69f
SL
816 pub const EXE_EXTENSION: &'static str = "";
817}
818
c1a9b12d
SL
819#[cfg(target_os = "netbsd")]
820mod os {
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 = "";
828}
829
85aaf69f 830#[cfg(target_os = "openbsd")]
c34b1796 831mod os {
85aaf69f 832 pub const FAMILY: &'static str = "unix";
85aaf69f 833 pub const OS: &'static str = "openbsd";
85aaf69f 834 pub const DLL_PREFIX: &'static str = "lib";
85aaf69f 835 pub const DLL_SUFFIX: &'static str = ".so";
85aaf69f 836 pub const DLL_EXTENSION: &'static str = "so";
85aaf69f 837 pub const EXE_SUFFIX: &'static str = "";
85aaf69f
SL
838 pub const EXE_EXTENSION: &'static str = "";
839}
840
85aaf69f 841#[cfg(target_os = "android")]
c34b1796 842mod os {
85aaf69f 843 pub const FAMILY: &'static str = "unix";
85aaf69f 844 pub const OS: &'static str = "android";
85aaf69f 845 pub const DLL_PREFIX: &'static str = "lib";
85aaf69f 846 pub const DLL_SUFFIX: &'static str = ".so";
85aaf69f 847 pub const DLL_EXTENSION: &'static str = "so";
85aaf69f 848 pub const EXE_SUFFIX: &'static str = "";
85aaf69f
SL
849 pub const EXE_EXTENSION: &'static str = "";
850}
851
7453a54e
SL
852#[cfg(target_os = "solaris")]
853mod os {
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 = "";
861}
862
85aaf69f 863#[cfg(target_os = "windows")]
c34b1796 864mod os {
85aaf69f 865 pub const FAMILY: &'static str = "windows";
85aaf69f 866 pub const OS: &'static str = "windows";
85aaf69f 867 pub const DLL_PREFIX: &'static str = "";
85aaf69f 868 pub const DLL_SUFFIX: &'static str = ".dll";
85aaf69f 869 pub const DLL_EXTENSION: &'static str = "dll";
85aaf69f 870 pub const EXE_SUFFIX: &'static str = ".exe";
85aaf69f
SL
871 pub const EXE_EXTENSION: &'static str = "exe";
872}
873
92a42be0
SL
874#[cfg(all(target_os = "nacl", not(target_arch = "le32")))]
875mod os {
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";
883}
884#[cfg(all(target_os = "nacl", target_arch = "le32"))]
885mod os {
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";
893}
894
7453a54e
SL
895#[cfg(target_os = "emscripten")]
896mod os {
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";
904}
905
9e0c209e
SL
906#[cfg(target_os = "haiku")]
907mod os {
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 = "";
915}
916
85aaf69f 917#[cfg(target_arch = "x86")]
c34b1796 918mod arch {
85aaf69f
SL
919 pub const ARCH: &'static str = "x86";
920}
921
922#[cfg(target_arch = "x86_64")]
c34b1796 923mod arch {
85aaf69f
SL
924 pub const ARCH: &'static str = "x86_64";
925}
926
927#[cfg(target_arch = "arm")]
c34b1796 928mod arch {
85aaf69f
SL
929 pub const ARCH: &'static str = "arm";
930}
931
932#[cfg(target_arch = "aarch64")]
c34b1796 933mod arch {
85aaf69f
SL
934 pub const ARCH: &'static str = "aarch64";
935}
936
937#[cfg(target_arch = "mips")]
c34b1796 938mod arch {
85aaf69f
SL
939 pub const ARCH: &'static str = "mips";
940}
941
9e0c209e
SL
942#[cfg(target_arch = "mips64")]
943mod arch {
944 pub const ARCH: &'static str = "mips64";
945}
946
85aaf69f 947#[cfg(target_arch = "powerpc")]
c34b1796 948mod arch {
85aaf69f
SL
949 pub const ARCH: &'static str = "powerpc";
950}
951
9cc50fc6
SL
952#[cfg(target_arch = "powerpc64")]
953mod arch {
954 pub const ARCH: &'static str = "powerpc64";
955}
956
9e0c209e
SL
957#[cfg(target_arch = "s390x")]
958mod arch {
959 pub const ARCH: &'static str = "s390x";
960}
961
7453a54e 962#[cfg(target_arch = "le32")]
9cc50fc6 963mod arch {
7453a54e 964 pub const ARCH: &'static str = "le32";
9cc50fc6
SL
965}
966
7453a54e 967#[cfg(target_arch = "asmjs")]
92a42be0 968mod arch {
7453a54e 969 pub const ARCH: &'static str = "asmjs";
92a42be0
SL
970}
971
85aaf69f
SL
972#[cfg(test)]
973mod tests {
85aaf69f 974 use super::*;
c34b1796 975
85aaf69f
SL
976 use iter::repeat;
977 use rand::{self, Rng};
978 use ffi::{OsString, OsStr};
c34b1796 979 use path::{Path, PathBuf};
85aaf69f
SL
980
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>());
c34b1796 985 let n = OsString::from(n);
85aaf69f
SL
986 assert!(var_os(&n).is_none());
987 n
988 }
989
990 fn eq(a: Option<OsString>, b: Option<&str>) {
9346a6ac 991 assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
85aaf69f
SL
992 }
993
994 #[test]
995 fn test_set_var() {
996 let n = make_rand_name();
997 set_var(&n, "VALUE");
998 eq(var_os(&n), Some("VALUE"));
999 }
1000
1001 #[test]
1002 fn test_remove_var() {
1003 let n = make_rand_name();
1004 set_var(&n, "VALUE");
1005 remove_var(&n);
1006 eq(var_os(&n), None);
1007 }
1008
1009 #[test]
1010 fn test_set_var_overwrite() {
1011 let n = make_rand_name();
1012 set_var(&n, "1");
1013 set_var(&n, "2");
1014 eq(var_os(&n), Some("2"));
1015 set_var(&n, "");
1016 eq(var_os(&n), Some(""));
1017 }
1018
1019 #[test]
1020 fn test_var_big() {
1021 let mut s = "".to_string();
1022 let mut i = 0;
1023 while i < 100 {
1024 s.push_str("aaaaaaaaaa");
1025 i += 1;
1026 }
1027 let n = make_rand_name();
c34b1796
AL
1028 set_var(&n, &s);
1029 eq(var_os(&n), Some(&s));
85aaf69f
SL
1030 }
1031
1032 #[test]
1033 fn test_self_exe_path() {
1034 let path = current_exe();
1035 assert!(path.is_ok());
1036 let path = path.unwrap();
1037
1038 // Hard to test this function
1039 assert!(path.is_absolute());
1040 }
1041
1042 #[test]
1043 fn test_env_set_get_huge() {
1044 let n = make_rand_name();
1045 let s = repeat("x").take(10000).collect::<String>();
1046 set_var(&n, &s);
c34b1796 1047 eq(var_os(&n), Some(&s));
85aaf69f
SL
1048 remove_var(&n);
1049 eq(var_os(&n), None);
1050 }
1051
1052 #[test]
1053 fn test_env_set_var() {
1054 let n = make_rand_name();
1055
1056 let mut e = vars_os();
1057 set_var(&n, "VALUE");
1058 assert!(!e.any(|(k, v)| {
1059 &*k == &*n && &*v == "VALUE"
1060 }));
1061
1062 assert!(vars_os().any(|(k, v)| {
1063 &*k == &*n && &*v == "VALUE"
1064 }));
1065 }
1066
1067 #[test]
1068 fn test() {
1069 assert!((!Path::new("test-path").is_absolute()));
1070
1071 current_dir().unwrap();
1072 }
1073
1074 #[test]
1075 #[cfg(windows)]
1076 fn split_paths_windows() {
1077 fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
1078 split_paths(unparsed).collect::<Vec<_>>() ==
c34b1796 1079 parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
85aaf69f
SL
1080 }
1081
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"]));
1092 }
1093
1094 #[test]
1095 #[cfg(unix)]
1096 fn split_paths_unix() {
1097 fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
1098 split_paths(unparsed).collect::<Vec<_>>() ==
c34b1796 1099 parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
85aaf69f
SL
1100 }
1101
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"]));
1107 }
1108
1109 #[test]
1110 #[cfg(unix)]
1111 fn join_paths_unix() {
1112 fn test_eq(input: &[&str], output: &str) -> bool {
1113 &*join_paths(input.iter().cloned()).unwrap() ==
9346a6ac 1114 OsStr::new(output)
85aaf69f
SL
1115 }
1116
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());
1123 }
1124
1125 #[test]
1126 #[cfg(windows)]
1127 fn join_paths_windows() {
1128 fn test_eq(input: &[&str], output: &str) -> bool {
1129 &*join_paths(input.iter().cloned()).unwrap() ==
9346a6ac 1130 OsStr::new(output)
85aaf69f
SL
1131 }
1132
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());
1141 }
1142 }