diff options
Diffstat (limited to 'src/libstd/sys/unix/os.rs')
| -rw-r--r-- | src/libstd/sys/unix/os.rs | 116 |
1 files changed, 53 insertions, 63 deletions
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 59b385b9481..3c53db53f85 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -26,38 +26,25 @@ use path::{self, PathBuf}; use ptr; use slice; use str; -use sys::c; +use sync::StaticMutex; +use sys::cvt; use sys::fd; use vec; const TMPBUF_SZ: usize = 128; +static ENV_LOCK: StaticMutex = StaticMutex::new(); /// Returns the platform-specific value of errno pub fn errno() -> i32 { - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd"))] - unsafe fn errno_location() -> *const c_int { - extern { fn __error() -> *const c_int; } - __error() - } - - #[cfg(target_os = "dragonfly")] - unsafe fn errno_location() -> *const c_int { - extern { fn __dfly_error() -> *const c_int; } - __dfly_error() - } - - #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))] - unsafe fn errno_location() -> *const c_int { - extern { fn __errno() -> *const c_int; } - __errno() - } - - #[cfg(any(target_os = "linux", target_os = "android"))] - unsafe fn errno_location() -> *const c_int { - extern { fn __errno_location() -> *const c_int; } - __errno_location() + extern { + #[cfg_attr(any(target_os = "linux", target_os = "android"), link_name = "__errno_location")] + #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd", + target_env = "newlib"), + link_name = "__errno")] + #[cfg_attr(target_os = "dragonfly", link_name = "__dfly_error")] + #[cfg_attr(any(target_os = "macos", target_os = "ios", target_os = "freebsd"), + link_name = "__error")] + fn errno_location() -> *const c_int; } unsafe { @@ -67,14 +54,9 @@ pub fn errno() -> i32 { /// Gets a detailed string description for the given error number. pub fn error_string(errno: i32) -> String { - #[cfg(target_os = "linux")] - extern { - #[link_name = "__xpg_strerror_r"] - fn strerror_r(errnum: c_int, buf: *mut c_char, - buflen: libc::size_t) -> c_int; - } - #[cfg(not(target_os = "linux"))] extern { + #[cfg_attr(any(target_os = "linux", target_env = "newlib"), + link_name = "__xpg_strerror_r")] fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) -> c_int; } @@ -247,8 +229,11 @@ pub fn current_exe() -> io::Result<PathBuf> { #[cfg(any(target_os = "macos", target_os = "ios"))] pub fn current_exe() -> io::Result<PathBuf> { + extern { + fn _NSGetExecutablePath(buf: *mut libc::c_char, + bufsize: *mut u32) -> libc::c_int; + } unsafe { - use libc::funcs::extra::_NSGetExecutablePath; let mut sz: u32 = 0; _NSGetExecutablePath(ptr::null_mut(), &mut sz); if sz == 0 { return Err(io::Error::last_os_error()); } @@ -361,7 +346,8 @@ pub fn args() -> Args { target_os = "dragonfly", target_os = "bitrig", target_os = "netbsd", - target_os = "openbsd"))] + target_os = "openbsd", + target_os = "nacl"))] pub fn args() -> Args { use sys_common; let bytes = sys_common::args::clone().unwrap_or(Vec::new()); @@ -397,6 +383,7 @@ pub unsafe fn environ() -> *mut *const *const c_char { /// Returns a vector of (variable, value) byte-vector pairs for all the /// environment variables of the current process. pub fn env() -> Env { + let _g = ENV_LOCK.lock(); return unsafe { let mut environ = *environ(); if environ as usize == 0 { @@ -420,35 +407,36 @@ pub fn env() -> Env { } } -pub fn getenv(k: &OsStr) -> Option<OsString> { - unsafe { - let s = k.to_cstring().unwrap(); - let s = libc::getenv(s.as_ptr()) as *const _; +pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> { + // environment variables with a nul byte can't be set, so their value is + // always None as well + let k = try!(CString::new(k.as_bytes())); + let _g = ENV_LOCK.lock(); + Ok(unsafe { + let s = libc::getenv(k.as_ptr()) as *const _; if s.is_null() { None } else { Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec())) } - } + }) } -pub fn setenv(k: &OsStr, v: &OsStr) { - unsafe { - let k = k.to_cstring().unwrap(); - let v = v.to_cstring().unwrap(); - if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 { - panic!("failed setenv: {}", io::Error::last_os_error()); - } - } +pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + let k = try!(CString::new(k.as_bytes())); + let v = try!(CString::new(v.as_bytes())); + let _g = ENV_LOCK.lock(); + cvt(unsafe { + libc::setenv(k.as_ptr(), v.as_ptr(), 1) + }).map(|_| ()) } -pub fn unsetenv(n: &OsStr) { - unsafe { - let nbuf = n.to_cstring().unwrap(); - if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 { - panic!("failed unsetenv: {}", io::Error::last_os_error()); - } - } +pub fn unsetenv(n: &OsStr) -> io::Result<()> { + let nbuf = try!(CString::new(n.as_bytes())); + let _g = ENV_LOCK.lock(); + cvt(unsafe { + libc::unsetenv(nbuf.as_ptr()) + }).map(|_| ()) } pub fn page_size() -> usize { @@ -458,7 +446,7 @@ pub fn page_size() -> usize { } pub fn temp_dir() -> PathBuf { - getenv("TMPDIR".as_ref()).map(PathBuf::from).unwrap_or_else(|| { + ::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| { if cfg!(target_os = "android") { PathBuf::from("/data/local/tmp") } else { @@ -468,28 +456,30 @@ pub fn temp_dir() -> PathBuf { } pub fn home_dir() -> Option<PathBuf> { - return getenv("HOME".as_ref()).or_else(|| unsafe { + return ::env::var_os("HOME").or_else(|| unsafe { fallback() }).map(PathBuf::from); #[cfg(any(target_os = "android", - target_os = "ios"))] + target_os = "ios", + target_os = "nacl"))] unsafe fn fallback() -> Option<OsString> { None } #[cfg(not(any(target_os = "android", - target_os = "ios")))] + target_os = "ios", + target_os = "nacl")))] unsafe fn fallback() -> Option<OsString> { - let amt = match libc::sysconf(c::_SC_GETPW_R_SIZE_MAX) { + let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) { n if n < 0 => 512 as usize, n => n as usize, }; let me = libc::getuid(); loop { let mut buf = Vec::with_capacity(amt); - let mut passwd: c::passwd = mem::zeroed(); + let mut passwd: libc::passwd = mem::zeroed(); let mut result = ptr::null_mut(); - match c::getpwuid_r(me, &mut passwd, buf.as_mut_ptr(), - buf.capacity() as libc::size_t, - &mut result) { + match libc::getpwuid_r(me, &mut passwd, buf.as_mut_ptr(), + buf.capacity() as libc::size_t, + &mut result) { 0 if !result.is_null() => {} _ => return None } |
