diff options
| author | Jeremy Soller <jackpot51@gmail.com> | 2016-10-28 14:17:34 -0600 |
|---|---|---|
| committer | Jeremy Soller <jackpot51@gmail.com> | 2016-10-28 14:17:34 -0600 |
| commit | a5de9bb591c9752d39c87339fd8f5ff49ea4b2da (patch) | |
| tree | 69c296d20f5fe58d0bbd2b603bd4143430a5d6a2 /src/libstd | |
| parent | 8b09e01fef9912e7c3eef997c40f9f4f91d09e4c (diff) | |
| download | rust-a5de9bb591c9752d39c87339fd8f5ff49ea4b2da.tar.gz rust-a5de9bb591c9752d39c87339fd8f5ff49ea4b2da.zip | |
Remove unsafe libc layer
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/fs.rs | 10 | ||||
| -rw-r--r-- | src/libstd/sys/redox/ext/io.rs | 3 | ||||
| -rw-r--r-- | src/libstd/sys/redox/fd.rs | 32 | ||||
| -rw-r--r-- | src/libstd/sys/redox/fs.rs | 186 | ||||
| -rw-r--r-- | src/libstd/sys/redox/mod.rs | 39 | ||||
| -rw-r--r-- | src/libstd/sys/redox/os.rs | 102 | ||||
| -rw-r--r-- | src/libstd/sys/redox/pipe.rs | 6 | ||||
| -rw-r--r-- | src/libstd/sys/redox/process.rs | 137 | ||||
| -rw-r--r-- | src/libstd/sys/redox/thread.rs | 29 | ||||
| -rw-r--r-- | src/libstd/sys/redox/time.rs | 286 |
10 files changed, 193 insertions, 637 deletions
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index df5741d00a2..5845963d31a 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -348,6 +348,16 @@ impl File { inner: self.inner.duplicate()? }) } + + /// Get the path that this file points to. + /// + /// This function is only implemented on Redox, but could be + /// implemented on other operating systems using readlink + #[cfg(redox)] + #[stable(feature = "rust1", since = "1.14.0")] + pub fn path(&self) -> io::Result<PathBuf> { + self.inner.path() + } } impl AsInner<fs_imp::File> for File { diff --git a/src/libstd/sys/redox/ext/io.rs b/src/libstd/sys/redox/ext/io.rs index bffd4f66a28..4f39f3b4f33 100644 --- a/src/libstd/sys/redox/ext/io.rs +++ b/src/libstd/sys/redox/ext/io.rs @@ -13,13 +13,12 @@ #![stable(feature = "rust1", since = "1.0.0")] use fs; -use os::raw; use sys; use sys_common::{AsInner, FromInner, IntoInner}; /// Raw file descriptors. #[stable(feature = "rust1", since = "1.0.0")] -pub type RawFd = raw::c_int; +pub type RawFd = usize; /// A trait to extract the raw unix file descriptor from an underlying /// object. diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs index 99ae089b5c0..4c4dae7cd41 100644 --- a/src/libstd/sys/redox/fd.rs +++ b/src/libstd/sys/redox/fd.rs @@ -11,37 +11,32 @@ #![unstable(reason = "not public", issue = "0", feature = "fd")] use io::{self, Read}; -use libc::{self, c_int, c_void}; +use libc; use mem; use sys::cvt; use sys_common::AsInner; use sys_common::io::read_to_end_uninitialized; pub struct FileDesc { - fd: c_int, + fd: usize, } impl FileDesc { - pub fn new(fd: c_int) -> FileDesc { + pub fn new(fd: usize) -> FileDesc { FileDesc { fd: fd } } - pub fn raw(&self) -> c_int { self.fd } + pub fn raw(&self) -> usize { self.fd } /// Extracts the actual filedescriptor without closing it. - pub fn into_raw(self) -> c_int { + pub fn into_raw(self) -> usize { let fd = self.fd; mem::forget(self); fd } pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { - let ret = cvt(unsafe { - libc::read(self.fd, - buf.as_mut_ptr() as *mut c_void, - buf.len()) - })?; - Ok(ret as usize) + cvt(libc::read(self.fd, buf)) } pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { @@ -50,12 +45,7 @@ impl FileDesc { } pub fn write(&self, buf: &[u8]) -> io::Result<usize> { - let ret = cvt(unsafe { - libc::write(self.fd, - buf.as_ptr() as *const c_void, - buf.len()) - })?; - Ok(ret as usize) + cvt(libc::write(self.fd, buf)) } pub fn set_cloexec(&self) -> io::Result<()> { @@ -86,7 +76,7 @@ impl FileDesc { } pub fn duplicate(&self) -> io::Result<FileDesc> { - let new_fd = cvt(unsafe { libc::dup(self.fd) })?; + let new_fd = cvt(libc::dup(self.fd, &[]))?; Ok(FileDesc::new(new_fd)) } } @@ -101,8 +91,8 @@ impl<'a> Read for &'a FileDesc { } } -impl AsInner<c_int> for FileDesc { - fn as_inner(&self) -> &c_int { &self.fd } +impl AsInner<usize> for FileDesc { + fn as_inner(&self) -> &usize { &self.fd } } impl Drop for FileDesc { @@ -112,6 +102,6 @@ impl Drop for FileDesc { // the file descriptor was closed or not, and if we retried (for // something like EINTR), we might close another valid file descriptor // (opened after we closed ours. - let _ = unsafe { libc::close(self.fd) }; + let _ = libc::close(self.fd); } } diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index 56b1bf95ae8..ca1a7963f8e 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -10,26 +10,24 @@ use os::unix::prelude::*; -use ffi::{CString, CStr, OsString, OsStr}; +use ffi::{OsString, OsStr}; use fmt; use io::{self, Error, ErrorKind, SeekFrom}; use libc::{self, c_int, mode_t}; -use mem; use path::{Path, PathBuf}; use sync::Arc; use sys::fd::FileDesc; use sys::time::SystemTime; -use sys::{cvt, cvt_r}; +use sys::cvt; use sys_common::{AsInner, FromInner}; -use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, off_t as off64_t, - ftruncate as ftruncate64, lseek as lseek64, open as open64}; +use libc::{stat, fstat, fsync, ftruncate, lseek, open}; pub struct File(FileDesc); #[derive(Clone)] pub struct FileAttr { - stat: stat64, + stat: stat, } pub struct ReadDir { @@ -104,8 +102,8 @@ impl FileAttr { } } -impl AsInner<stat64> for FileAttr { - fn as_inner(&self) -> &stat64 { &self.stat } +impl AsInner<stat> for FileAttr { + fn as_inner(&self) -> &stat { &self.stat } } impl FilePermissions { @@ -254,60 +252,32 @@ impl OpenOptions { impl File { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> { - let path = cstr(path)?; - File::open_c(&path, opts) - } - - pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> { - let flags = libc::O_CLOEXEC as i32 | - opts.get_access_mode()? | - opts.get_creation_mode()? | - (opts.custom_flags as usize & !libc::O_ACCMODE) as i32; - let fd = cvt_r(|| unsafe { - open64(path.as_ptr(), flags, opts.mode as mode_t) - })?; - let fd = FileDesc::new(fd); - - Ok(File(fd)) + let flags = libc::O_CLOEXEC | + opts.get_access_mode()? as usize | + opts.get_creation_mode()? as usize | + (opts.custom_flags as usize & !libc::O_ACCMODE); + let fd = cvt(open(path.to_str().unwrap(), flags | opts.mode as usize))?; + Ok(File(FileDesc::new(fd))) } pub fn file_attr(&self) -> io::Result<FileAttr> { - let mut stat: stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { - fstat64(self.0.raw(), &mut stat) - })?; + let mut stat: stat = stat::default(); + cvt(fstat(self.0.raw(), &mut stat))?; Ok(FileAttr { stat: stat }) } pub fn fsync(&self) -> io::Result<()> { - cvt_r(|| unsafe { libc::fsync(self.0.raw()) })?; + cvt(fsync(self.0.raw()))?; Ok(()) } pub fn datasync(&self) -> io::Result<()> { - cvt_r(|| unsafe { os_datasync(self.0.raw()) })?; - return Ok(()); - - #[cfg(any(target_os = "macos", target_os = "ios"))] - unsafe fn os_datasync(fd: c_int) -> c_int { - libc::fcntl(fd, libc::F_FULLFSYNC) - } - #[cfg(target_os = "linux")] - unsafe fn os_datasync(fd: c_int) -> c_int { libc::fdatasync(fd) } - #[cfg(not(any(target_os = "macos", - target_os = "ios", - target_os = "linux")))] - unsafe fn os_datasync(fd: c_int) -> c_int { libc::fsync(fd) } + self.fsync() } pub fn truncate(&self, size: u64) -> io::Result<()> { - #[cfg(target_os = "android")] - return ::sys::android::ftruncate64(self.0.raw(), size); - - #[cfg(not(target_os = "android"))] - return cvt_r(|| unsafe { - ftruncate64(self.0.raw(), size as off64_t) - }).map(|_| ()); + cvt(ftruncate(self.0.raw(), size as usize))?; + Ok(()) } pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { @@ -332,7 +302,7 @@ impl File { SeekFrom::End(off) => (libc::SEEK_END, off), SeekFrom::Current(off) => (libc::SEEK_CUR, off), }; - let n = cvt(unsafe { lseek64(self.0.raw(), pos as usize, whence) } as isize)?; + let n = cvt(lseek(self.0.raw(), pos as isize, whence))?; Ok(n as u64) } @@ -341,9 +311,8 @@ impl File { } pub fn dup(&self, buf: &[u8]) -> io::Result<File> { - libc::dup_extra(*self.fd().as_inner() as usize, buf) - .map(|fd| File(FileDesc::new(fd as i32))) - .map_err(|err| Error::from_raw_os_error(err.errno)) + let fd = cvt(libc::dup(*self.fd().as_inner() as usize, buf))?; + Ok(File(FileDesc::new(fd))) } pub fn path(&self) -> io::Result<PathBuf> { @@ -365,8 +334,7 @@ impl DirBuilder { } pub fn mkdir(&self, p: &Path) -> io::Result<()> { - let p = cstr(p)?; - cvt(unsafe { libc::mkdir(p.as_ptr(), self.mode) })?; + cvt(libc::mkdir(p.to_str().unwrap(), self.mode))?; Ok(()) } @@ -375,96 +343,39 @@ impl DirBuilder { } } -fn cstr(path: &Path) -> io::Result<CString> { - Ok(CString::new(path.as_os_str().as_bytes())?) -} - -impl FromInner<c_int> for File { - fn from_inner(fd: c_int) -> File { +impl FromInner<usize> for File { + fn from_inner(fd: usize) -> File { File(FileDesc::new(fd)) } } impl fmt::Debug for File { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - #[cfg(target_os = "linux")] - fn get_path(fd: c_int) -> Option<PathBuf> { - let mut p = PathBuf::from("/proc/self/fd"); - p.push(&fd.to_string()); - readlink(&p).ok() - } - - #[cfg(target_os = "macos")] - fn get_path(fd: c_int) -> Option<PathBuf> { - // FIXME: The use of PATH_MAX is generally not encouraged, but it - // is inevitable in this case because OS X defines `fcntl` with - // `F_GETPATH` in terms of `MAXPATHLEN`, and there are no - // alternatives. If a better method is invented, it should be used - // instead. - let mut buf = vec![0;libc::PATH_MAX as usize]; - let n = unsafe { libc::fcntl(fd, libc::F_GETPATH, buf.as_ptr()) }; - if n == -1 { - return None; - } - let l = buf.iter().position(|&c| c == 0).unwrap(); - buf.truncate(l as usize); - buf.shrink_to_fit(); - Some(PathBuf::from(OsString::from_vec(buf))) - } - - #[cfg(not(any(target_os = "linux", target_os = "macos")))] - fn get_path(_fd: c_int) -> Option<PathBuf> { - // FIXME(#24570): implement this for other Unix platforms - None - } - - #[cfg(any(target_os = "linux", target_os = "macos"))] - fn get_mode(fd: c_int) -> Option<(bool, bool)> { - let mode = unsafe { libc::fcntl(fd, libc::F_GETFL) }; - if mode == -1 { - return None; - } - match mode & libc::O_ACCMODE { - libc::O_RDONLY => Some((true, false)), - libc::O_RDWR => Some((true, true)), - libc::O_WRONLY => Some((false, true)), - _ => None - } - } - - #[cfg(not(any(target_os = "linux", target_os = "macos")))] - fn get_mode(_fd: c_int) -> Option<(bool, bool)> { - // FIXME(#24570): implement this for other Unix platforms - None - } - - let fd = self.0.raw(); let mut b = f.debug_struct("File"); - b.field("fd", &fd); - if let Some(path) = get_path(fd) { + b.field("fd", &self.0.raw()); + if let Ok(path) = self.path() { b.field("path", &path); } + /* if let Some((read, write)) = get_mode(fd) { b.field("read", &read).field("write", &write); } + */ b.finish() } } pub fn readdir(p: &Path) -> io::Result<ReadDir> { let root = Arc::new(p.to_path_buf()); - let p = cstr(p)?; - unsafe { - let fd = FileDesc::new(cvt(libc::open(p.as_ptr(), 0, 0))?); - let mut data = Vec::new(); - fd.read_to_end(&mut data)?; - Ok(ReadDir { data: data, i: 0, root: root }) - } + let options = OpenOptions::new(); + let fd = File::open(p, &options)?; + let mut data = Vec::new(); + fd.read_to_end(&mut data)?; + Ok(ReadDir { data: data, i: 0, root: root }) } pub fn unlink(p: &Path) -> io::Result<()> { - let p = cstr(p)?; - cvt(unsafe { libc::unlink(p.as_ptr()) })?; + cvt(libc::unlink(p.to_str().unwrap()))?; Ok(()) } @@ -477,8 +388,7 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { } pub fn rmdir(p: &Path) -> io::Result<()> { - let p = cstr(p)?; - cvt(unsafe { libc::rmdir(p.as_ptr()) })?; + cvt(libc::rmdir(p.to_str().unwrap()))?; Ok(()) } @@ -503,8 +413,8 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { rmdir(path) } -pub fn readlink(_p: &Path) -> io::Result<PathBuf> { - unimplemented!(); +pub fn readlink(p: &Path) -> io::Result<PathBuf> { + canonicalize(p) } pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> { @@ -516,25 +426,21 @@ pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { } pub fn stat(p: &Path) -> io::Result<FileAttr> { - let p = cstr(p)?; - let mut stat: stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { - stat64(p.as_ptr(), &mut stat as *mut _ as *mut _) - })?; + let mut stat: stat = stat::default(); + let options = OpenOptions::new(); + let file = File::open(p, &options)?; + cvt(fstat(file.0.raw(), &mut stat))?; Ok(FileAttr { stat: stat }) } pub fn lstat(p: &Path) -> io::Result<FileAttr> { - let p = cstr(p)?; - let mut stat: stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { - lstat64(p.as_ptr(), &mut stat as *mut _ as *mut _) - })?; - Ok(FileAttr { stat: stat }) + stat(p) } -pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> { - unimplemented!(); +pub fn canonicalize(p: &Path) -> io::Result<PathBuf> { + let options = OpenOptions::new(); + let file = File::open(p, &options)?; + file.path() } pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index 108ebb0800e..f7465d01fad 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -41,9 +41,7 @@ pub fn init() { use intrinsics; let msg = "fatal runtime error: out of memory\n"; unsafe { - libc::write(libc::STDERR_FILENO, - msg.as_ptr() as *const libc::c_void, - msg.len()); + let _ = libc::write(libc::STDERR_FILENO, msg.as_bytes()); intrinsics::abort(); } } @@ -75,37 +73,6 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { } } -#[doc(hidden)] -pub trait IsMinusOne { - fn is_minus_one(&self) -> bool; -} - -macro_rules! impl_is_minus_one { - ($($t:ident)*) => ($(impl IsMinusOne for $t { - fn is_minus_one(&self) -> bool { - *self == -1 - } - })*) -} - -impl_is_minus_one! { i8 i16 i32 i64 isize } - -pub fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> { - if t.is_minus_one() { - Err(io::Error::last_os_error()) - } else { - Ok(t) - } -} - -pub fn cvt_r<T, F>(mut f: F) -> io::Result<T> - where T: IsMinusOne, - F: FnMut() -> T -{ - loop { - match cvt(f()) { - Err(ref e) if e.kind() == ErrorKind::Interrupted => {} - other => return other, - } - } +pub fn cvt(result: Result<usize, libc::Error>) -> io::Result<usize> { + result.map_err(|err| io::Error::from_raw_os_error(err.errno as i32)) } diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs index a2262369e92..c2e419aeaaa 100644 --- a/src/libstd/sys/redox/os.rs +++ b/src/libstd/sys/redox/os.rs @@ -35,109 +35,28 @@ use vec; const TMPBUF_SZ: usize = 128; static ENV_LOCK: Mutex = Mutex::new(); - -extern { - #[cfg(not(target_os = "dragonfly"))] - #[cfg_attr(any(target_os = "linux", target_os = "emscripten", target_os = "fuchsia"), - link_name = "__errno_location")] - #[cfg_attr(any(target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd", - target_os = "android", - target_env = "newlib"), - link_name = "__errno")] - #[cfg_attr(target_os = "solaris", link_name = "___errno")] - #[cfg_attr(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd"), - link_name = "__error")] - #[cfg_attr(target_os = "haiku", link_name = "_errnop")] - fn errno_location() -> *mut c_int; -} - /// Returns the platform-specific value of errno -#[cfg(not(target_os = "dragonfly"))] pub fn errno() -> i32 { - unsafe { - (*errno_location()) as i32 - } -} - -/// Sets the platform-specific value of errno -#[cfg(target_os = "solaris")] // only needed for readdir so far -pub fn set_errno(e: i32) { - unsafe { - *errno_location() = e as c_int - } -} - -#[cfg(target_os = "dragonfly")] -pub fn errno() -> i32 { - extern { - #[thread_local] - static errno: c_int; - } - - errno as i32 + 0 } /// Gets a detailed string description for the given error number. pub fn error_string(errno: i32) -> String { - 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; - } - - let mut buf = [0 as c_char; TMPBUF_SZ]; - - let p = buf.as_mut_ptr(); - unsafe { - if strerror_r(errno as c_int, p, buf.len()) < 0 { - panic!("strerror_r failure"); - } - - let p = p as *const _; - str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned() + if let Some(string) = libc::STR_ERROR.get(errno as usize) { + string.to_string() + } else { + "unknown error".to_string() } } pub fn getcwd() -> io::Result<PathBuf> { - let mut buf = Vec::with_capacity(512); - loop { - unsafe { - let ptr = buf.as_mut_ptr() as *mut libc::c_char; - if !libc::getcwd(ptr, buf.capacity()).is_null() { - let len = CStr::from_ptr(buf.as_ptr() as *const libc::c_char).to_bytes().len(); - buf.set_len(len); - buf.shrink_to_fit(); - return Ok(PathBuf::from(OsString::from_vec(buf))); - } else { - let error = io::Error::last_os_error(); - if error.raw_os_error() != Some(libc::ERANGE) { - return Err(error); - } - } - - // Trigger the internal buffer resizing logic of `Vec` by requiring - // more space than the current capacity. - let cap = buf.capacity(); - buf.set_len(cap); - buf.reserve(1); - } - } + let mut buf = [0; 4096]; + let count = cvt(libc::getcwd(&mut buf))?; + Ok(PathBuf::from(OsString::from_vec(buf[.. count].to_vec()))) } pub fn chdir(p: &path::Path) -> io::Result<()> { - let p: &OsStr = p.as_ref(); - let p = CString::new(p.as_bytes())?; - unsafe { - match libc::chdir(p.as_ptr()) == (0 as c_int) { - true => Ok(()), - false => Err(io::Error::last_os_error()), - } - } + cvt(libc::chdir(p.to_str().unwrap())).and(Ok(())) } pub struct SplitPaths<'a> { @@ -242,5 +161,6 @@ pub fn home_dir() -> Option<PathBuf> { } pub fn exit(code: i32) -> ! { - unsafe { libc::exit(code as c_int) } + let _ = libc::exit(code as usize); + unreachable!(); } diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs index f77f1e0dc68..5902ba128e8 100644 --- a/src/libstd/sys/redox/pipe.rs +++ b/src/libstd/sys/redox/pipe.rs @@ -9,7 +9,7 @@ // except according to those terms. use io; -use libc::{self, c_int}; +use libc; use sys::fd::FileDesc; //////////////////////////////////////////////////////////////////////////////// @@ -23,8 +23,8 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { libc::pipe2(&mut fds, libc::O_CLOEXEC).map_err(|err| io::Error::from_raw_os_error(err.errno))?; - let fd0 = FileDesc::new(fds[0] as c_int); - let fd1 = FileDesc::new(fds[1] as c_int); + let fd0 = FileDesc::new(fds[0]); + let fd1 = FileDesc::new(fds[1]); Ok((AnonPipe::from_fd(fd0)?, AnonPipe::from_fd(fd1)?)) } diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index b025623fc9f..921e3f056da 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -12,14 +12,15 @@ use os::unix::prelude::*; use collections::hash_map::HashMap; use env; -use ffi::{OsStr, CString, CStr}; +use ffi::{OsStr, CString}; use fmt; use io::{self, Error, ErrorKind}; use libc::{self, pid_t, c_int, gid_t, uid_t}; +use path::Path; use sys::fd::FileDesc; use sys::fs::{File, OpenOptions}; use sys::pipe::{self, AnonPipe}; -use sys::{self, cvt, cvt_r}; +use sys::{self, cvt}; //////////////////////////////////////////////////////////////////////////////// // Command @@ -47,7 +48,7 @@ pub struct Command { args: Vec<String>, env: HashMap<String, String>, - cwd: Option<CString>, + cwd: Option<String>, uid: Option<uid_t>, gid: Option<gid_t>, saw_nul: bool, @@ -75,7 +76,7 @@ struct ChildPipes { enum ChildStdio { Inherit, - Explicit(c_int), + Explicit(usize), Owned(FileDesc), } @@ -120,7 +121,7 @@ impl Command { } pub fn cwd(&mut self, dir: &OsStr) { - self.cwd = Some(os2c(dir, &mut self.saw_nul)); + self.cwd = Some(dir.to_str().unwrap().to_owned()); } pub fn uid(&mut self, id: uid_t) { self.uid = Some(id); @@ -157,7 +158,7 @@ impl Command { let (input, output) = sys::pipe::anon_pipe()?; let pid = unsafe { - match cvt(libc::fork() as isize)? { + match cvt(libc::clone(0))? { 0 => { drop(input); let err = self.do_exec(theirs); @@ -174,7 +175,8 @@ impl Command { // we want to be sure we *don't* run at_exit destructors as // we're being torn down regardless assert!(output.write(&bytes).is_ok()); - libc::_exit(1) + let _ = libc::exit(1); + unreachable!(); } n => n as pid_t, } @@ -271,29 +273,29 @@ impl Command { } if let Some(fd) = stdio.stderr.fd() { - libc::close(libc::STDERR_FILENO); - t!(cvt(libc::dup(fd))); - libc::close(fd); + let _ = libc::close(libc::STDERR_FILENO); + t!(cvt(libc::dup(fd, &[]))); + let _ = libc::close(fd); } if let Some(fd) = stdio.stdout.fd() { - libc::close(libc::STDOUT_FILENO); - t!(cvt(libc::dup(fd))); - libc::close(fd); + let _ = libc::close(libc::STDOUT_FILENO); + t!(cvt(libc::dup(fd, &[]))); + let _ = libc::close(fd); } if let Some(fd) = stdio.stdin.fd() { - libc::close(libc::STDIN_FILENO); - t!(cvt(libc::dup(fd))); - libc::close(fd); + let _ = libc::close(libc::STDIN_FILENO); + t!(cvt(libc::dup(fd, &[]))); + let _ = libc::close(fd); } - if let Some(u) = self.gid { - t!(cvt(libc::setgid(u as gid_t))); + if let Some(g) = self.gid { + t!(cvt(libc::setgid(g))); } if let Some(u) = self.uid { - t!(cvt(libc::setuid(u as uid_t))); + t!(cvt(libc::setuid(u))); } if let Some(ref cwd) = self.cwd { - t!(cvt(libc::chdir(cwd.as_ptr()))); + t!(cvt(libc::chdir(cwd))); } for callback in self.closures.iter_mut() { @@ -363,7 +365,7 @@ impl Stdio { // stderr. No matter which we dup first, the second will get // overwritten prematurely. Stdio::Fd(ref fd) => { - if fd.raw() >= 0 && fd.raw() <= libc::STDERR_FILENO { + if fd.raw() <= libc::STDERR_FILENO { Ok((ChildStdio::Owned(fd.duplicate()?), None)) } else { Ok((ChildStdio::Explicit(fd.raw()), None)) @@ -384,10 +386,7 @@ impl Stdio { let mut opts = OpenOptions::new(); opts.read(readable); opts.write(!readable); - let path = unsafe { - CStr::from_ptr("/dev/null\0".as_ptr() as *const _) - }; - let fd = File::open_c(&path, &opts)?; + let fd = File::open(&Path::new("null:"), &opts)?; Ok((ChildStdio::Owned(fd.into_fd()), None)) } } @@ -395,7 +394,7 @@ impl Stdio { } impl ChildStdio { - fn fd(&self) -> Option<c_int> { + fn fd(&self) -> Option<usize> { match *self { ChildStdio::Inherit => None, ChildStdio::Explicit(fd) => Some(fd), @@ -496,7 +495,8 @@ impl Process { Err(Error::new(ErrorKind::InvalidInput, "invalid argument: can't kill an exited process")) } else { - cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(|_| ()) + cvt(libc::kill(self.pid, libc::SIGKILL))?; + Ok(()) } } @@ -505,89 +505,8 @@ impl Process { return Ok(status) } let mut status = 0; - cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })?; + cvt(libc::waitpid(self.pid, &mut status, 0))?; self.status = Some(ExitStatus(status as i32)); Ok(ExitStatus(status as i32)) } } - -#[cfg(all(test, not(target_os = "emscripten")))] -mod tests { - use super::*; - - use ffi::OsStr; - use mem; - use ptr; - use libc; - use sys::cvt; - - macro_rules! t { - ($e:expr) => { - match $e { - Ok(t) => t, - Err(e) => panic!("received error for `{}`: {}", stringify!($e), e), - } - } - } - - #[cfg(not(target_os = "android"))] - extern { - #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")] - fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int; - } - - #[cfg(target_os = "android")] - unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int { - use slice; - - let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::<libc::sigset_t>()); - let bit = (signum - 1) as usize; - raw[bit / 8] |= 1 << (bit % 8); - return 0; - } - - // See #14232 for more information, but it appears that signal delivery to a - // newly spawned process may just be raced in the OSX, so to prevent this - // test from being flaky we ignore it on OSX. - #[test] - #[cfg_attr(target_os = "macos", ignore)] - #[cfg_attr(target_os = "nacl", ignore)] // no signals on NaCl. - fn test_process_mask() { - unsafe { - // Test to make sure that a signal mask does not get inherited. - let mut cmd = Command::new(OsStr::new("cat")); - - let mut set: libc::sigset_t = mem::uninitialized(); - let mut old_set: libc::sigset_t = mem::uninitialized(); - t!(cvt(libc::sigemptyset(&mut set))); - t!(cvt(sigaddset(&mut set, libc::SIGINT))); - t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut old_set))); - - cmd.stdin(Stdio::MakePipe); - cmd.stdout(Stdio::MakePipe); - - let (mut cat, mut pipes) = t!(cmd.spawn(Stdio::Null, true)); - let stdin_write = pipes.stdin.take().unwrap(); - let stdout_read = pipes.stdout.take().unwrap(); - - t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &old_set, - ptr::null_mut()))); - - t!(cvt(libc::kill(cat.id() as libc::pid_t, libc::SIGINT))); - // We need to wait until SIGINT is definitely delivered. The - // easiest way is to write something to cat, and try to read it - // back: if SIGINT is unmasked, it'll get delivered when cat is - // next scheduled. - let _ = stdin_write.write(b"Hello"); - drop(stdin_write); - - // Either EOF or failure (EPIPE) is okay. - let mut buf = [0; 5]; - if let Ok(ret) = stdout_read.read(&mut buf) { - assert!(ret == 0); - } - - t!(cat.wait()); - } - } -} diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index eaf908dc53e..616da662d9a 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -14,7 +14,6 @@ use ffi::CStr; use io; use libc; use mem; -use sys::os; use sys_common::thread::start_thread; use time::Duration; @@ -42,7 +41,7 @@ impl Thread { } pub fn set_name(_name: &CStr) { - + unimplemented!(); } pub fn sleep(dur: Duration) { @@ -51,20 +50,18 @@ impl Thread { // If we're awoken with a signal then the return value will be -1 and // nanosleep will fill in `ts` with the remaining time. - unsafe { - while secs > 0 || nsecs > 0 { - let mut ts = libc::timespec { - tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t, - tv_nsec: nsecs, - }; - secs -= ts.tv_sec as u64; - if libc::nanosleep(&ts, &mut ts) == -1 { - assert_eq!(os::errno(), libc::EINTR); - secs += ts.tv_sec as u64; - nsecs = ts.tv_nsec; - } else { - nsecs = 0; - } + while secs > 0 || nsecs > 0 { + let req = libc::timespec { + tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t, + tv_nsec: nsecs, + }; + secs -= req.tv_sec as u64; + let mut rem = libc::timespec::default(); + if libc::nanosleep(&req, &mut rem).is_err() { + secs += rem.tv_sec as u64; + nsecs = rem.tv_nsec; + } else { + nsecs = 0; } } } diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs index 5caaf20fdf8..4e1a82bcc9a 100644 --- a/src/libstd/sys/redox/time.rs +++ b/src/libstd/sys/redox/time.rs @@ -9,11 +9,11 @@ // except according to those terms. use cmp::Ordering; +use fmt; use libc; +use sys::cvt; use time::Duration; -pub use self::inner::{Instant, SystemTime, UNIX_EPOCH}; - const NSEC_PER_SEC: u64 = 1_000_000_000; #[derive(Copy, Clone)] @@ -103,249 +103,97 @@ impl Ord for Timespec { } } -#[cfg(any(target_os = "macos", target_os = "ios"))] -mod inner { - use fmt; - use libc; - use sync::Once; - use sys::cvt; - use sys_common::mul_div_u64; - use time::Duration; - - use super::NSEC_PER_SEC; - use super::Timespec; - - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] - pub struct Instant { - t: u64 - } +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct Instant { + t: Timespec, +} - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] - pub struct SystemTime { - t: Timespec, - } +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct SystemTime { + t: Timespec, +} - pub const UNIX_EPOCH: SystemTime = SystemTime { - t: Timespec { - t: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - }, +pub const UNIX_EPOCH: SystemTime = SystemTime { + t: Timespec { + t: libc::timespec { + tv_sec: 0, + tv_nsec: 0, }, - }; + }, +}; - impl Instant { - pub fn now() -> Instant { - Instant { t: unsafe { libc::mach_absolute_time() } } - } - - pub fn sub_instant(&self, other: &Instant) -> Duration { - let info = info(); - let diff = self.t.checked_sub(other.t) - .expect("second instant is later than self"); - let nanos = mul_div_u64(diff, info.numer as u64, info.denom as u64); - Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32) - } - - pub fn add_duration(&self, other: &Duration) -> Instant { - Instant { - t: self.t.checked_add(dur2intervals(other)) - .expect("overflow when adding duration to instant"), - } - } - - pub fn sub_duration(&self, other: &Duration) -> Instant { - Instant { - t: self.t.checked_sub(dur2intervals(other)) - .expect("overflow when adding duration to instant"), - } - } +impl Instant { + pub fn now() -> Instant { + Instant { t: now(libc::CLOCK_MONOTONIC) } } - impl SystemTime { - pub fn now() -> SystemTime { - use ptr; - - let mut s = libc::timeval { - tv_sec: 0, - tv_usec: 0, - }; - cvt(unsafe { - libc::gettimeofday(&mut s, ptr::null_mut()) - }).unwrap(); - return SystemTime::from(s) - } - - pub fn sub_time(&self, other: &SystemTime) - -> Result<Duration, Duration> { - self.t.sub_timespec(&other.t) - } - - pub fn add_duration(&self, other: &Duration) -> SystemTime { - SystemTime { t: self.t.add_duration(other) } - } - - pub fn sub_duration(&self, other: &Duration) -> SystemTime { - SystemTime { t: self.t.sub_duration(other) } - } - } - - impl From<libc::timeval> for SystemTime { - fn from(t: libc::timeval) -> SystemTime { - SystemTime::from(libc::timespec { - tv_sec: t.tv_sec, - tv_nsec: (t.tv_usec * 1000) as libc::c_long, - }) - } + pub fn sub_instant(&self, other: &Instant) -> Duration { + self.t.sub_timespec(&other.t).unwrap_or_else(|_| { + panic!("other was less than the current instant") + }) } - impl From<libc::timespec> for SystemTime { - fn from(t: libc::timespec) -> SystemTime { - SystemTime { t: Timespec { t: t } } - } + pub fn add_duration(&self, other: &Duration) -> Instant { + Instant { t: self.t.add_duration(other) } } - impl fmt::Debug for SystemTime { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("SystemTime") - .field("tv_sec", &self.t.t.tv_sec) - .field("tv_nsec", &self.t.t.tv_nsec) - .finish() - } - } - - fn dur2intervals(dur: &Duration) -> u64 { - let info = info(); - let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| { - nanos.checked_add(dur.subsec_nanos() as u64) - }).expect("overflow converting duration to nanoseconds"); - mul_div_u64(nanos, info.denom as u64, info.numer as u64) - } - - fn info() -> &'static libc::mach_timebase_info { - static mut INFO: libc::mach_timebase_info = libc::mach_timebase_info { - numer: 0, - denom: 0, - }; - static ONCE: Once = Once::new(); - - unsafe { - ONCE.call_once(|| { - libc::mach_timebase_info(&mut INFO); - }); - &INFO - } + pub fn sub_duration(&self, other: &Duration) -> Instant { + Instant { t: self.t.sub_duration(other) } } } -#[cfg(not(any(target_os = "macos", target_os = "ios")))] -mod inner { - use fmt; - use libc; - use sys::cvt; - use time::Duration; - - use super::Timespec; - - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] - pub struct Instant { - t: Timespec, +impl fmt::Debug for Instant { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Instant") + .field("tv_sec", &self.t.t.tv_sec) + .field("tv_nsec", &self.t.t.tv_nsec) + .finish() } +} - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] - pub struct SystemTime { - t: Timespec, +impl SystemTime { + pub fn now() -> SystemTime { + SystemTime { t: now(libc::CLOCK_REALTIME) } } - pub const UNIX_EPOCH: SystemTime = SystemTime { - t: Timespec { - t: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - }, - }, - }; - - impl Instant { - pub fn now() -> Instant { - Instant { t: now(libc::CLOCK_MONOTONIC) } - } - - pub fn sub_instant(&self, other: &Instant) -> Duration { - self.t.sub_timespec(&other.t).unwrap_or_else(|_| { - panic!("other was less than the current instant") - }) - } - - pub fn add_duration(&self, other: &Duration) -> Instant { - Instant { t: self.t.add_duration(other) } - } - - pub fn sub_duration(&self, other: &Duration) -> Instant { - Instant { t: self.t.sub_duration(other) } - } + pub fn sub_time(&self, other: &SystemTime) + -> Result<Duration, Duration> { + self.t.sub_timespec(&other.t) } - impl fmt::Debug for Instant { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Instant") - .field("tv_sec", &self.t.t.tv_sec) - .field("tv_nsec", &self.t.t.tv_nsec) - .finish() - } + pub fn add_duration(&self, other: &Duration) -> SystemTime { + SystemTime { t: self.t.add_duration(other) } } - impl SystemTime { - pub fn now() -> SystemTime { - SystemTime { t: now(libc::CLOCK_REALTIME) } - } - - pub fn sub_time(&self, other: &SystemTime) - -> Result<Duration, Duration> { - self.t.sub_timespec(&other.t) - } - - pub fn add_duration(&self, other: &Duration) -> SystemTime { - SystemTime { t: self.t.add_duration(other) } - } - - pub fn sub_duration(&self, other: &Duration) -> SystemTime { - SystemTime { t: self.t.sub_duration(other) } - } + pub fn sub_duration(&self, other: &Duration) -> SystemTime { + SystemTime { t: self.t.sub_duration(other) } } +} - impl From<libc::timespec> for SystemTime { - fn from(t: libc::timespec) -> SystemTime { - SystemTime { t: Timespec { t: t } } - } +impl From<libc::timespec> for SystemTime { + fn from(t: libc::timespec) -> SystemTime { + SystemTime { t: Timespec { t: t } } } +} - impl fmt::Debug for SystemTime { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("SystemTime") - .field("tv_sec", &self.t.t.tv_sec) - .field("tv_nsec", &self.t.t.tv_nsec) - .finish() - } +impl fmt::Debug for SystemTime { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("SystemTime") + .field("tv_sec", &self.t.t.tv_sec) + .field("tv_nsec", &self.t.t.tv_nsec) + .finish() } +} - #[cfg(not(any(target_os = "dragonfly", target_os = "redox")))] - pub type clock_t = libc::c_int; - #[cfg(target_os = "dragonfly")] - pub type clock_t = libc::c_ulong; - #[cfg(target_os = "redox")] - pub type clock_t = usize; +pub type clock_t = usize; - fn now(clock: clock_t) -> Timespec { - let mut t = Timespec { - t: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - } - }; - cvt(unsafe { - libc::clock_gettime(clock, &mut t.t) - }).unwrap(); - t - } +fn now(clock: clock_t) -> Timespec { + let mut t = Timespec { + t: libc::timespec { + tv_sec: 0, + tv_nsec: 0, + } + }; + cvt(libc::clock_gettime(clock, &mut t.t)).unwrap(); + t } |
