Remove unsafe libc layer
This commit is contained in:
parent
8b09e01fef
commit
a5de9bb591
10 changed files with 207 additions and 651 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)?))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Instant {
|
||||
t: Timespec,
|
||||
}
|
||||
|
||||
use super::NSEC_PER_SEC;
|
||||
use super::Timespec;
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct SystemTime {
|
||||
t: Timespec,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
pub struct Instant {
|
||||
t: u64
|
||||
}
|
||||
|
||||
#[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) }
|
||||
}
|
||||
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::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 add_duration(&self, other: &Duration) -> Instant {
|
||||
Instant { t: self.t.add_duration(other) }
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
#[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,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
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) }
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
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) }
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
#[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;
|
||||
|
||||
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
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
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) }
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
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(libc::clock_gettime(clock, &mut t.t)).unwrap();
|
||||
t
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue