From 8b09e01fef9912e7c3eef997c40f9f4f91d09e4c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 27 Oct 2016 20:57:49 -0600 Subject: Add redox system --- src/libstd/sys/common/mod.rs | 7 +- src/libstd/sys/common/util.rs | 6 + src/libstd/sys/redox/args.rs | 105 ++++++ src/libstd/sys/redox/backtrace.rs | 8 + src/libstd/sys/redox/condvar.rs | 88 +++++ src/libstd/sys/redox/env.rs | 19 ++ src/libstd/sys/redox/ext/ffi.rs | 61 ++++ src/libstd/sys/redox/ext/fs.rs | 300 +++++++++++++++++ src/libstd/sys/redox/ext/io.rs | 147 ++++++++ src/libstd/sys/redox/ext/mod.rs | 50 +++ src/libstd/sys/redox/ext/process.rs | 183 ++++++++++ src/libstd/sys/redox/fd.rs | 117 +++++++ src/libstd/sys/redox/fs.rs | 554 ++++++++++++++++++++++++++++++ src/libstd/sys/redox/memchr.rs | 14 + src/libstd/sys/redox/mod.rs | 111 ++++++ src/libstd/sys/redox/mutex.rs | 125 +++++++ src/libstd/sys/redox/net/dns/answer.rs | 12 + src/libstd/sys/redox/net/dns/mod.rs | 207 ++++++++++++ src/libstd/sys/redox/net/dns/query.rs | 8 + src/libstd/sys/redox/net/mod.rs | 91 +++++ src/libstd/sys/redox/net/tcp.rs | 160 +++++++++ src/libstd/sys/redox/net/udp.rs | 163 +++++++++ src/libstd/sys/redox/os.rs | 246 ++++++++++++++ src/libstd/sys/redox/os_str.rs | 119 +++++++ src/libstd/sys/redox/path.rs | 29 ++ src/libstd/sys/redox/pipe.rs | 105 ++++++ src/libstd/sys/redox/process.rs | 593 +++++++++++++++++++++++++++++++++ src/libstd/sys/redox/rand.rs | 40 +++ src/libstd/sys/redox/rwlock.rs | 55 +++ src/libstd/sys/redox/stack_overflow.rs | 27 ++ src/libstd/sys/redox/stdio.rs | 69 ++++ src/libstd/sys/redox/thread.rs | 94 ++++++ src/libstd/sys/redox/thread_local.rs | 41 +++ src/libstd/sys/redox/time.rs | 351 +++++++++++++++++++ 34 files changed, 4304 insertions(+), 1 deletion(-) create mode 100644 src/libstd/sys/redox/args.rs create mode 100644 src/libstd/sys/redox/backtrace.rs create mode 100644 src/libstd/sys/redox/condvar.rs create mode 100644 src/libstd/sys/redox/env.rs create mode 100644 src/libstd/sys/redox/ext/ffi.rs create mode 100644 src/libstd/sys/redox/ext/fs.rs create mode 100644 src/libstd/sys/redox/ext/io.rs create mode 100644 src/libstd/sys/redox/ext/mod.rs create mode 100644 src/libstd/sys/redox/ext/process.rs create mode 100644 src/libstd/sys/redox/fd.rs create mode 100644 src/libstd/sys/redox/fs.rs create mode 100644 src/libstd/sys/redox/memchr.rs create mode 100644 src/libstd/sys/redox/mod.rs create mode 100644 src/libstd/sys/redox/mutex.rs create mode 100644 src/libstd/sys/redox/net/dns/answer.rs create mode 100644 src/libstd/sys/redox/net/dns/mod.rs create mode 100644 src/libstd/sys/redox/net/dns/query.rs create mode 100644 src/libstd/sys/redox/net/mod.rs create mode 100644 src/libstd/sys/redox/net/tcp.rs create mode 100644 src/libstd/sys/redox/net/udp.rs create mode 100644 src/libstd/sys/redox/os.rs create mode 100644 src/libstd/sys/redox/os_str.rs create mode 100644 src/libstd/sys/redox/path.rs create mode 100644 src/libstd/sys/redox/pipe.rs create mode 100644 src/libstd/sys/redox/process.rs create mode 100644 src/libstd/sys/redox/rand.rs create mode 100644 src/libstd/sys/redox/rwlock.rs create mode 100644 src/libstd/sys/redox/stack_overflow.rs create mode 100644 src/libstd/sys/redox/stdio.rs create mode 100644 src/libstd/sys/redox/thread.rs create mode 100644 src/libstd/sys/redox/thread_local.rs create mode 100644 src/libstd/sys/redox/time.rs (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs index 2845f895f18..274f3c10d9c 100644 --- a/src/libstd/sys/common/mod.rs +++ b/src/libstd/sys/common/mod.rs @@ -32,7 +32,6 @@ pub mod condvar; pub mod io; pub mod memchr; pub mod mutex; -pub mod net; pub mod poison; pub mod remutex; pub mod rwlock; @@ -42,6 +41,12 @@ pub mod thread_local; pub mod util; pub mod wtf8; +#[cfg(redox)] +pub use sys::net; + +#[cfg(not(redox))] +pub mod net; + #[cfg(any(not(cargobuild), feature = "backtrace"))] #[cfg(any(all(unix, not(any(target_os = "macos", target_os = "ios", target_os = "emscripten"))), all(windows, target_env = "gnu")))] diff --git a/src/libstd/sys/common/util.rs b/src/libstd/sys/common/util.rs index b5d03576338..dda0abb4c0c 100644 --- a/src/libstd/sys/common/util.rs +++ b/src/libstd/sys/common/util.rs @@ -33,6 +33,12 @@ pub fn dumb_print(args: fmt::Arguments) { let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args)); } +// On Redox, use an illegal instruction +#[cfg(redox)] +unsafe fn abort_internal() -> ! { + ::intrinsics::abort() +} + // On Unix-like platforms, libc::abort will unregister signal handlers // including the SIGABRT handler, preventing the abort from being blocked, and // fclose streams, with the side effect of flushing them so libc bufferred diff --git a/src/libstd/sys/redox/args.rs b/src/libstd/sys/redox/args.rs new file mode 100644 index 00000000000..91233645989 --- /dev/null +++ b/src/libstd/sys/redox/args.rs @@ -0,0 +1,105 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Global initialization and retreival of command line arguments. +//! +//! On some platforms these are stored during runtime startup, +//! and on some they are retrieved from the system on demand. + +#![allow(dead_code)] // runtime init functions not used during testing + +use ffi::OsString; +use marker::PhantomData; +use vec; + +/// One-time global initialization. +pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) } + +/// One-time global cleanup. +pub unsafe fn cleanup() { imp::cleanup() } + +/// Returns the command line arguments +pub fn args() -> Args { + imp::args() +} + +pub struct Args { + iter: vec::IntoIter, + _dont_send_or_sync_me: PhantomData<*mut ()>, +} + +impl Iterator for Args { + type Item = OsString; + fn next(&mut self) -> Option { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} + +impl ExactSizeIterator for Args { + fn len(&self) -> usize { self.iter.len() } +} + +impl DoubleEndedIterator for Args { + fn next_back(&mut self) -> Option { self.iter.next_back() } +} + +mod imp { + use os::unix::prelude::*; + use mem; + use ffi::{CStr, OsString}; + use marker::PhantomData; + use libc; + use super::Args; + + use sys_common::mutex::Mutex; + + static mut GLOBAL_ARGS_PTR: usize = 0; + static LOCK: Mutex = Mutex::new(); + + pub unsafe fn init(argc: isize, argv: *const *const u8) { + let args = (0..argc).map(|i| { + CStr::from_ptr(*argv.offset(i) as *const libc::c_char).to_bytes().to_vec() + }).collect(); + + LOCK.lock(); + let ptr = get_global_ptr(); + assert!((*ptr).is_none()); + (*ptr) = Some(box args); + LOCK.unlock(); + } + + pub unsafe fn cleanup() { + LOCK.lock(); + *get_global_ptr() = None; + LOCK.unlock(); + } + + pub fn args() -> Args { + let bytes = clone().unwrap_or(Vec::new()); + let v: Vec = bytes.into_iter().map(|v| { + OsStringExt::from_vec(v) + }).collect(); + Args { iter: v.into_iter(), _dont_send_or_sync_me: PhantomData } + } + + fn clone() -> Option>> { + unsafe { + LOCK.lock(); + let ptr = get_global_ptr(); + let ret = (*ptr).as_ref().map(|s| (**s).clone()); + LOCK.unlock(); + return ret + } + } + + fn get_global_ptr() -> *mut Option>>> { + unsafe { mem::transmute(&GLOBAL_ARGS_PTR) } + } + +} diff --git a/src/libstd/sys/redox/backtrace.rs b/src/libstd/sys/redox/backtrace.rs new file mode 100644 index 00000000000..63e427694ae --- /dev/null +++ b/src/libstd/sys/redox/backtrace.rs @@ -0,0 +1,8 @@ +use libc; +use io; +use sys_common::backtrace::output; + +#[inline(never)] +pub fn write(w: &mut io::Write) -> io::Result<()> { + output(w, 0, 0 as *mut libc::c_void, None) +} diff --git a/src/libstd/sys/redox/condvar.rs b/src/libstd/sys/redox/condvar.rs new file mode 100644 index 00000000000..2a6685bc122 --- /dev/null +++ b/src/libstd/sys/redox/condvar.rs @@ -0,0 +1,88 @@ +use cell::UnsafeCell; +use intrinsics::{atomic_cxchg, atomic_xadd, atomic_xchg}; +use ptr; +use time::Duration; + +use super::mutex::{mutex_lock, mutex_unlock, Mutex}; + +use libc::{futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE}; + +pub struct Condvar { + lock: UnsafeCell<*mut i32>, + seq: UnsafeCell +} + +impl Condvar { + pub const fn new() -> Condvar { + Condvar { + lock: UnsafeCell::new(ptr::null_mut()), + seq: UnsafeCell::new(0) + } + } + + pub unsafe fn init(&self) { + + } + + pub fn notify_one(&self) { + unsafe { + let seq = self.seq.get(); + + atomic_xadd(seq, 1); + + let _ = futex(seq, FUTEX_WAKE, 1, 0, ptr::null_mut()); + } + } + + pub fn notify_all(&self) { + unsafe { + let lock = self.lock.get(); + let seq = self.seq.get(); + + if *lock == ptr::null_mut() { + return; + } + + atomic_xadd(seq, 1); + + let _ = futex(seq, FUTEX_REQUEUE, 1, ::usize::MAX, *lock); + } + } + + pub fn wait(&self, mutex: &Mutex) { + unsafe { + let lock = self.lock.get(); + let seq = self.seq.get(); + + if *lock != mutex.lock.get() { + if *lock != ptr::null_mut() { + panic!("Condvar used with more than one Mutex"); + } + + atomic_cxchg(lock as *mut usize, 0, mutex.lock.get() as usize); + } + + mutex_unlock(*lock); + + let _ = futex(seq, FUTEX_WAIT, *seq, 0, ptr::null_mut()); + + while atomic_xchg(*lock, 2) != 0 { + let _ = futex(*lock, FUTEX_WAIT, 2, 0, ptr::null_mut()); + } + + mutex_lock(*lock); + } + } + + pub fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { + unimplemented!(); + } + + pub unsafe fn destroy(&self) { + + } +} + +unsafe impl Send for Condvar {} + +unsafe impl Sync for Condvar {} diff --git a/src/libstd/sys/redox/env.rs b/src/libstd/sys/redox/env.rs new file mode 100644 index 00000000000..51fd2d07973 --- /dev/null +++ b/src/libstd/sys/redox/env.rs @@ -0,0 +1,19 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub mod os { + pub const FAMILY: &'static str = "redox"; + pub const OS: &'static str = "redox"; + pub const DLL_PREFIX: &'static str = "lib"; + pub const DLL_SUFFIX: &'static str = ".so"; + pub const DLL_EXTENSION: &'static str = "so"; + pub const EXE_SUFFIX: &'static str = ""; + pub const EXE_EXTENSION: &'static str = ""; +} diff --git a/src/libstd/sys/redox/ext/ffi.rs b/src/libstd/sys/redox/ext/ffi.rs new file mode 100644 index 00000000000..d59b4fc0b70 --- /dev/null +++ b/src/libstd/sys/redox/ext/ffi.rs @@ -0,0 +1,61 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Unix-specific extension to the primitives in the `std::ffi` module + +#![stable(feature = "rust1", since = "1.0.0")] + +use ffi::{OsStr, OsString}; +use mem; +use sys::os_str::Buf; +use sys_common::{FromInner, IntoInner, AsInner}; + +/// Unix-specific extensions to `OsString`. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait OsStringExt { + /// Creates an `OsString` from a byte vector. + #[stable(feature = "rust1", since = "1.0.0")] + fn from_vec(vec: Vec) -> Self; + + /// Yields the underlying byte vector of this `OsString`. + #[stable(feature = "rust1", since = "1.0.0")] + fn into_vec(self) -> Vec; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl OsStringExt for OsString { + fn from_vec(vec: Vec) -> OsString { + FromInner::from_inner(Buf { inner: vec }) + } + fn into_vec(self) -> Vec { + self.into_inner().inner + } +} + +/// Unix-specific extensions to `OsStr`. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait OsStrExt { + #[stable(feature = "rust1", since = "1.0.0")] + fn from_bytes(slice: &[u8]) -> &Self; + + /// Gets the underlying byte view of the `OsStr` slice. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_bytes(&self) -> &[u8]; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl OsStrExt for OsStr { + fn from_bytes(slice: &[u8]) -> &OsStr { + unsafe { mem::transmute(slice) } + } + fn as_bytes(&self) -> &[u8] { + &self.as_inner().inner + } +} diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs new file mode 100644 index 00000000000..45ad7c092de --- /dev/null +++ b/src/libstd/sys/redox/ext/fs.rs @@ -0,0 +1,300 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Unix-specific extensions to primitives in the `std::fs` module. + +#![stable(feature = "rust1", since = "1.0.0")] + +use fs::{self, Permissions, OpenOptions}; +use io; +use path::Path; +use sys; +use sys_common::{FromInner, AsInner, AsInnerMut}; + +/// Unix-specific extensions to `Permissions` +#[stable(feature = "fs_ext", since = "1.1.0")] +pub trait PermissionsExt { + /// Returns the underlying raw `mode_t` bits that are the standard Unix + /// permissions for this file. + /// + /// # Examples + /// + /// ```rust,ignore + /// use std::fs::File; + /// use std::os::unix::fs::PermissionsExt; + /// + /// let f = try!(File::create("foo.txt")); + /// let metadata = try!(f.metadata()); + /// let permissions = metadata.permissions(); + /// + /// println!("permissions: {}", permissions.mode()); + /// ``` + #[stable(feature = "fs_ext", since = "1.1.0")] + fn mode(&self) -> u32; + + /// Sets the underlying raw bits for this set of permissions. + /// + /// # Examples + /// + /// ```rust,ignore + /// use std::fs::File; + /// use std::os::unix::fs::PermissionsExt; + /// + /// let f = try!(File::create("foo.txt")); + /// let metadata = try!(f.metadata()); + /// let mut permissions = metadata.permissions(); + /// + /// permissions.set_mode(0o644); // Read/write for owner and read for others. + /// assert_eq!(permissions.mode(), 0o644); + /// ``` + #[stable(feature = "fs_ext", since = "1.1.0")] + fn set_mode(&mut self, mode: u32); + + /// Creates a new instance of `Permissions` from the given set of Unix + /// permission bits. + /// + /// # Examples + /// + /// ```rust,ignore + /// use std::fs::Permissions; + /// use std::os::unix::fs::PermissionsExt; + /// + /// // Read/write for owner and read for others. + /// let permissions = Permissions::from_mode(0o644); + /// assert_eq!(permissions.mode(), 0o644); + /// ``` + #[stable(feature = "fs_ext", since = "1.1.0")] + fn from_mode(mode: u32) -> Self; +} + +#[stable(feature = "fs_ext", since = "1.1.0")] +impl PermissionsExt for Permissions { + fn mode(&self) -> u32 { + self.as_inner().mode() + } + + fn set_mode(&mut self, mode: u32) { + *self = Permissions::from_inner(FromInner::from_inner(mode)); + } + + fn from_mode(mode: u32) -> Permissions { + Permissions::from_inner(FromInner::from_inner(mode)) + } +} + +/// Unix-specific extensions to `OpenOptions` +#[stable(feature = "fs_ext", since = "1.1.0")] +pub trait OpenOptionsExt { + /// Sets the mode bits that a new file will be created with. + /// + /// If a new file is created as part of a `File::open_opts` call then this + /// specified `mode` will be used as the permission bits for the new file. + /// If no `mode` is set, the default of `0o666` will be used. + /// The operating system masks out bits with the systems `umask`, to produce + /// the final permissions. + /// + /// # Examples + /// + /// ```rust,ignore + /// extern crate libc; + /// use std::fs::OpenOptions; + /// use std::os::unix::fs::OpenOptionsExt; + /// + /// let mut options = OpenOptions::new(); + /// options.mode(0o644); // Give read/write for owner and read for others. + /// let file = options.open("foo.txt"); + /// ``` + #[stable(feature = "fs_ext", since = "1.1.0")] + fn mode(&mut self, mode: u32) -> &mut Self; + + /// Pass custom flags to the `flags` agument of `open`. + /// + /// The bits that define the access mode are masked out with `O_ACCMODE`, to + /// ensure they do not interfere with the access mode set by Rusts options. + /// + /// Custom flags can only set flags, not remove flags set by Rusts options. + /// This options overwrites any previously set custom flags. + /// + /// # Examples + /// + /// ```rust,ignore + /// extern crate libc; + /// use std::fs::OpenOptions; + /// use std::os::unix::fs::OpenOptionsExt; + /// + /// let mut options = OpenOptions::new(); + /// options.write(true); + /// if cfg!(unix) { + /// options.custom_flags(libc::O_NOFOLLOW); + /// } + /// let file = options.open("foo.txt"); + /// ``` + #[stable(feature = "open_options_ext", since = "1.10.0")] + fn custom_flags(&mut self, flags: i32) -> &mut Self; +} + +#[stable(feature = "fs_ext", since = "1.1.0")] +impl OpenOptionsExt for OpenOptions { + fn mode(&mut self, mode: u32) -> &mut OpenOptions { + self.as_inner_mut().mode(mode); self + } + + fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions { + self.as_inner_mut().custom_flags(flags); self + } +} + +// Hm, why are there casts here to the returned type, shouldn't the types always +// be the same? Right you are! Turns out, however, on android at least the types +// in the raw `stat` structure are not the same as the types being returned. Who +// knew! +// +// As a result to make sure this compiles for all platforms we do the manual +// casts and rely on manual lowering to `stat` if the raw type is desired. +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn mode(&self) -> u32; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn uid(&self) -> u32; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn gid(&self) -> u32; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn size(&self) -> u64; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn atime(&self) -> i64; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn atime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn mtime(&self) -> i64; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn mtime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn ctime(&self) -> i64; + #[stable(feature = "metadata_ext", since = "1.1.0")] + fn ctime_nsec(&self) -> i64; +} + +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for fs::Metadata { + fn mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + fn uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + fn gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + fn size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + fn atime(&self) -> i64 { + self.as_inner().as_inner().st_atime as i64 + } + fn atime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_atime_nsec as i64 + } + fn mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtime as i64 + } + fn mtime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_mtime_nsec as i64 + } + fn ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctime as i64 + } + fn ctime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_ctime_nsec as i64 + } +} + +/* +/// Add special unix types (block/char device, fifo and socket) +#[stable(feature = "file_type_ext", since = "1.5.0")] +pub trait FileTypeExt { + /// Returns whether this file type is a block device. + #[stable(feature = "file_type_ext", since = "1.5.0")] + fn is_block_device(&self) -> bool; + /// Returns whether this file type is a char device. + #[stable(feature = "file_type_ext", since = "1.5.0")] + fn is_char_device(&self) -> bool; + /// Returns whether this file type is a fifo. + #[stable(feature = "file_type_ext", since = "1.5.0")] + fn is_fifo(&self) -> bool; + /// Returns whether this file type is a socket. + #[stable(feature = "file_type_ext", since = "1.5.0")] + fn is_socket(&self) -> bool; +} + +#[stable(feature = "file_type_ext", since = "1.5.0")] +impl FileTypeExt for fs::FileType { + fn is_block_device(&self) -> bool { self.as_inner().is(libc::S_IFBLK) } + fn is_char_device(&self) -> bool { self.as_inner().is(libc::S_IFCHR) } + fn is_fifo(&self) -> bool { self.as_inner().is(libc::S_IFIFO) } + fn is_socket(&self) -> bool { self.as_inner().is(libc::S_IFSOCK) } +} +*/ + +/// Creates a new symbolic link on the filesystem. +/// +/// The `dst` path will be a symbolic link pointing to the `src` path. +/// +/// # Note +/// +/// On Windows, you must specify whether a symbolic link points to a file +/// or directory. Use `os::windows::fs::symlink_file` to create a +/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a +/// symbolic link to a directory. Additionally, the process must have +/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a +/// symbolic link. +/// +/// # Examples +/// +/// ``` +/// use std::os::unix::fs; +/// +/// # fn foo() -> std::io::Result<()> { +/// try!(fs::symlink("a.txt", "b.txt")); +/// # Ok(()) +/// # } +/// ``` +#[stable(feature = "symlink", since = "1.1.0")] +pub fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> +{ + sys::fs::symlink(src.as_ref(), dst.as_ref()) +} + +#[stable(feature = "dir_builder", since = "1.6.0")] +/// An extension trait for `fs::DirBuilder` for unix-specific options. +pub trait DirBuilderExt { + /// Sets the mode to create new directories with. This option defaults to + /// 0o777. + /// + /// # Examples + /// + /// ```ignore + /// use std::fs::DirBuilder; + /// use std::os::unix::fs::DirBuilderExt; + /// + /// let mut builder = DirBuilder::new(); + /// builder.mode(0o755); + /// ``` + #[stable(feature = "dir_builder", since = "1.6.0")] + fn mode(&mut self, mode: u32) -> &mut Self; +} + +#[stable(feature = "dir_builder", since = "1.6.0")] +impl DirBuilderExt for fs::DirBuilder { + fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder { + self.as_inner_mut().set_mode(mode); + self + } +} diff --git a/src/libstd/sys/redox/ext/io.rs b/src/libstd/sys/redox/ext/io.rs new file mode 100644 index 00000000000..bffd4f66a28 --- /dev/null +++ b/src/libstd/sys/redox/ext/io.rs @@ -0,0 +1,147 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Unix-specific extensions to general I/O primitives + +#![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; + +/// A trait to extract the raw unix file descriptor from an underlying +/// object. +/// +/// This is only available on unix platforms and must be imported in order +/// to call the method. Windows platforms have a corresponding `AsRawHandle` +/// and `AsRawSocket` set of traits. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait AsRawFd { + /// Extracts the raw file descriptor. + /// + /// This method does **not** pass ownership of the raw file descriptor + /// to the caller. The descriptor is only guaranteed to be valid while + /// the original object has not yet been destroyed. + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_fd(&self) -> RawFd; +} + +/// A trait to express the ability to construct an object from a raw file +/// descriptor. +#[stable(feature = "from_raw_os", since = "1.1.0")] +pub trait FromRawFd { + /// Constructs a new instances of `Self` from the given raw file + /// descriptor. + /// + /// This function **consumes ownership** of the specified file + /// descriptor. The returned object will take responsibility for closing + /// it when the object goes out of scope. + /// + /// This function is also unsafe as the primitives currently returned + /// have the contract that they are the sole owner of the file + /// descriptor they are wrapping. Usage of this function could + /// accidentally allow violating this contract which can cause memory + /// unsafety in code that relies on it being true. + #[stable(feature = "from_raw_os", since = "1.1.0")] + unsafe fn from_raw_fd(fd: RawFd) -> Self; +} + +/// A trait to express the ability to consume an object and acquire ownership of +/// its raw file descriptor. +#[stable(feature = "into_raw_os", since = "1.4.0")] +pub trait IntoRawFd { + /// Consumes this object, returning the raw underlying file descriptor. + /// + /// This function **transfers ownership** of the underlying file descriptor + /// to the caller. Callers are then the unique owners of the file descriptor + /// and must close the descriptor once it's no longer needed. + #[stable(feature = "into_raw_os", since = "1.4.0")] + fn into_raw_fd(self) -> RawFd; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawFd for fs::File { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd().raw() + } +} +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawFd for fs::File { + unsafe fn from_raw_fd(fd: RawFd) -> fs::File { + fs::File::from_inner(sys::fs::File::from_inner(fd)) + } +} +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for fs::File { + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_fd().into_raw() + } +} + +/* +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawFd for net::TcpStream { + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawFd for net::TcpListener { + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawFd for net::UdpSocket { + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } +} + +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawFd for net::TcpStream { + unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { + let socket = sys::net::Socket::from_inner(fd); + net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket)) + } +} +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawFd for net::TcpListener { + unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener { + let socket = sys::net::Socket::from_inner(fd); + net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket)) + } +} +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawFd for net::UdpSocket { + unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket { + let socket = sys::net::Socket::from_inner(fd); + net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket)) + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for net::TcpStream { + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_socket().into_inner() + } +} +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for net::TcpListener { + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_socket().into_inner() + } +} +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for net::UdpSocket { + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_socket().into_inner() + } +} +*/ diff --git a/src/libstd/sys/redox/ext/mod.rs b/src/libstd/sys/redox/ext/mod.rs new file mode 100644 index 00000000000..7ba166e8932 --- /dev/null +++ b/src/libstd/sys/redox/ext/mod.rs @@ -0,0 +1,50 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Experimental extensions to `std` for Unix platforms. +//! +//! For now, this module is limited to extracting file descriptors, +//! but its functionality will grow over time. +//! +//! # Example +//! +//! ```no_run +//! use std::fs::File; +//! use std::os::unix::prelude::*; +//! +//! fn main() { +//! let f = File::create("foo.txt").unwrap(); +//! let fd = f.as_raw_fd(); +//! +//! // use fd with native unix bindings +//! } +//! ``` + +#![stable(feature = "rust1", since = "1.0.0")] + +pub mod ffi; +pub mod fs; +pub mod io; +pub mod process; + +/// A prelude for conveniently writing platform-specific code. +/// +/// Includes all extension traits, and some important type definitions. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod prelude { + #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] + pub use super::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; + #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] + pub use super::ffi::{OsStrExt, OsStringExt}; + #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] + pub use super::fs::{PermissionsExt, OpenOptionsExt, MetadataExt}; + #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] + pub use super::process::{CommandExt, ExitStatusExt}; +} diff --git a/src/libstd/sys/redox/ext/process.rs b/src/libstd/sys/redox/ext/process.rs new file mode 100644 index 00000000000..f8e6b2cf470 --- /dev/null +++ b/src/libstd/sys/redox/ext/process.rs @@ -0,0 +1,183 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Unix-specific extensions to primitives in the `std::process` module. + +#![stable(feature = "rust1", since = "1.0.0")] + +use io; +use os::unix::io::{FromRawFd, RawFd, AsRawFd, IntoRawFd}; +use process; +use sys; +use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner}; + +/// Unix-specific extensions to the `std::process::Command` builder +#[stable(feature = "rust1", since = "1.0.0")] +pub trait CommandExt { + /// Sets the child process's user id. This translates to a + /// `setuid` call in the child process. Failure in the `setuid` + /// call will cause the spawn to fail. + #[stable(feature = "rust1", since = "1.0.0")] + fn uid(&mut self, id: u32) -> &mut process::Command; + + /// Similar to `uid`, but sets the group id of the child process. This has + /// the same semantics as the `uid` field. + #[stable(feature = "rust1", since = "1.0.0")] + fn gid(&mut self, id: u32) -> &mut process::Command; + + /// Schedules a closure to be run just before the `exec` function is + /// invoked. + /// + /// The closure is allowed to return an I/O error whose OS error code will + /// be communicated back to the parent and returned as an error from when + /// the spawn was requested. + /// + /// Multiple closures can be registered and they will be called in order of + /// their registration. If a closure returns `Err` then no further closures + /// will be called and the spawn operation will immediately return with a + /// failure. + /// + /// # Notes + /// + /// This closure will be run in the context of the child process after a + /// `fork`. This primarily means that any modificatons made to memory on + /// behalf of this closure will **not** be visible to the parent process. + /// This is often a very constrained environment where normal operations + /// like `malloc` or acquiring a mutex are not guaranteed to work (due to + /// other threads perhaps still running when the `fork` was run). + /// + /// When this closure is run, aspects such as the stdio file descriptors and + /// working directory have successfully been changed, so output to these + /// locations may not appear where intended. + #[unstable(feature = "process_exec", issue = "31398")] + fn before_exec(&mut self, f: F) -> &mut process::Command + where F: FnMut() -> io::Result<()> + Send + Sync + 'static; + + /// Performs all the required setup by this `Command`, followed by calling + /// the `execvp` syscall. + /// + /// On success this function will not return, and otherwise it will return + /// an error indicating why the exec (or another part of the setup of the + /// `Command`) failed. + /// + /// This function, unlike `spawn`, will **not** `fork` the process to create + /// a new child. Like spawn, however, the default behavior for the stdio + /// descriptors will be to inherited from the current process. + /// + /// # Notes + /// + /// The process may be in a "broken state" if this function returns in + /// error. For example the working directory, environment variables, signal + /// handling settings, various user/group information, or aspects of stdio + /// file descriptors may have changed. If a "transactional spawn" is + /// required to gracefully handle errors it is recommended to use the + /// cross-platform `spawn` instead. + #[stable(feature = "process_exec2", since = "1.9.0")] + fn exec(&mut self) -> io::Error; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl CommandExt for process::Command { + fn uid(&mut self, id: u32) -> &mut process::Command { + self.as_inner_mut().uid(id as usize); + self + } + + fn gid(&mut self, id: u32) -> &mut process::Command { + self.as_inner_mut().gid(id as usize); + self + } + + fn before_exec(&mut self, f: F) -> &mut process::Command + where F: FnMut() -> io::Result<()> + Send + Sync + 'static + { + self.as_inner_mut().before_exec(Box::new(f)); + self + } + + fn exec(&mut self) -> io::Error { + self.as_inner_mut().exec(sys::process::Stdio::Inherit) + } +} + +/// Unix-specific extensions to `std::process::ExitStatus` +#[stable(feature = "rust1", since = "1.0.0")] +pub trait ExitStatusExt { + /// Creates a new `ExitStatus` from the raw underlying `i32` return value of + /// a process. + #[stable(feature = "exit_status_from", since = "1.12.0")] + fn from_raw(raw: i32) -> Self; + + /// If the process was terminated by a signal, returns that signal. + #[stable(feature = "rust1", since = "1.0.0")] + fn signal(&self) -> Option; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExitStatusExt for process::ExitStatus { + fn from_raw(raw: i32) -> Self { + process::ExitStatus::from_inner(From::from(raw)) + } + + fn signal(&self) -> Option { + self.as_inner().signal() + } +} + +#[stable(feature = "process_extensions", since = "1.2.0")] +impl FromRawFd for process::Stdio { + unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio { + let fd = sys::fd::FileDesc::new(fd); + let io = sys::process::Stdio::Fd(fd); + process::Stdio::from_inner(io) + } +} + +#[stable(feature = "process_extensions", since = "1.2.0")] +impl AsRawFd for process::ChildStdin { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd().raw() + } +} + +#[stable(feature = "process_extensions", since = "1.2.0")] +impl AsRawFd for process::ChildStdout { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd().raw() + } +} + +#[stable(feature = "process_extensions", since = "1.2.0")] +impl AsRawFd for process::ChildStderr { + fn as_raw_fd(&self) -> RawFd { + self.as_inner().fd().raw() + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for process::ChildStdin { + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_fd().into_raw() + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for process::ChildStdout { + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_fd().into_raw() + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for process::ChildStderr { + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_fd().into_raw() + } +} diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs new file mode 100644 index 00000000000..99ae089b5c0 --- /dev/null +++ b/src/libstd/sys/redox/fd.rs @@ -0,0 +1,117 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![unstable(reason = "not public", issue = "0", feature = "fd")] + +use io::{self, Read}; +use libc::{self, c_int, c_void}; +use mem; +use sys::cvt; +use sys_common::AsInner; +use sys_common::io::read_to_end_uninitialized; + +pub struct FileDesc { + fd: c_int, +} + +impl FileDesc { + pub fn new(fd: c_int) -> FileDesc { + FileDesc { fd: fd } + } + + pub fn raw(&self) -> c_int { self.fd } + + /// Extracts the actual filedescriptor without closing it. + pub fn into_raw(self) -> c_int { + let fd = self.fd; + mem::forget(self); + fd + } + + pub fn read(&self, buf: &mut [u8]) -> io::Result { + let ret = cvt(unsafe { + libc::read(self.fd, + buf.as_mut_ptr() as *mut c_void, + buf.len()) + })?; + Ok(ret as usize) + } + + pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { + let mut me = self; + (&mut me).read_to_end(buf) + } + + pub fn write(&self, buf: &[u8]) -> io::Result { + let ret = cvt(unsafe { + libc::write(self.fd, + buf.as_ptr() as *const c_void, + buf.len()) + })?; + Ok(ret as usize) + } + + pub fn set_cloexec(&self) -> io::Result<()> { + unimplemented!(); + /* + unsafe { + let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD, 0))?; + cvt(libc::fcntl(self.fd, libc::F_SETFD, previous | libc::FD_CLOEXEC))?; + Ok(()) + } + */ + } + + pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> { + unimplemented!(); + /* + unsafe { + let previous = cvt(libc::fcntl(self.fd, libc::F_GETFL, 0))?; + let new = if nonblocking { + previous | libc::O_NONBLOCK + } else { + previous & !libc::O_NONBLOCK + }; + cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?; + Ok(()) + } + */ + } + + pub fn duplicate(&self) -> io::Result { + let new_fd = cvt(unsafe { libc::dup(self.fd) })?; + Ok(FileDesc::new(new_fd)) + } +} + +impl<'a> Read for &'a FileDesc { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (**self).read(buf) + } + + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + unsafe { read_to_end_uninitialized(self, buf) } + } +} + +impl AsInner for FileDesc { + fn as_inner(&self) -> &c_int { &self.fd } +} + +impl Drop for FileDesc { + fn drop(&mut self) { + // Note that errors are ignored when closing a file descriptor. The + // reason for this is that if an error occurs we don't actually know if + // 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) }; + } +} diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs new file mode 100644 index 00000000000..56b1bf95ae8 --- /dev/null +++ b/src/libstd/sys/redox/fs.rs @@ -0,0 +1,554 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use os::unix::prelude::*; + +use ffi::{CString, CStr, 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_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}; + +pub struct File(FileDesc); + +#[derive(Clone)] +pub struct FileAttr { + stat: stat64, +} + +pub struct ReadDir { + data: Vec, + i: usize, + root: Arc, +} + +struct Dir(FileDesc); + +unsafe impl Send for Dir {} +unsafe impl Sync for Dir {} + +pub struct DirEntry { + root: Arc, + name: Box<[u8]> +} + +#[derive(Clone)] +pub struct OpenOptions { + // generic + read: bool, + write: bool, + append: bool, + truncate: bool, + create: bool, + create_new: bool, + // system-specific + custom_flags: i32, + mode: mode_t, +} + +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct FilePermissions { mode: mode_t } + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub struct FileType { mode: mode_t } + +pub struct DirBuilder { mode: mode_t } + +impl FileAttr { + pub fn size(&self) -> u64 { self.stat.st_size as u64 } + pub fn perm(&self) -> FilePermissions { + FilePermissions { mode: (self.stat.st_mode as mode_t) & 0o777 } + } + + pub fn file_type(&self) -> FileType { + FileType { mode: self.stat.st_mode as mode_t } + } +} + +impl FileAttr { + pub fn modified(&self) -> io::Result { + Ok(SystemTime::from(libc::timespec { + tv_sec: self.stat.st_mtime as libc::time_t, + tv_nsec: self.stat.st_mtime_nsec as i32, + })) + } + + pub fn accessed(&self) -> io::Result { + Ok(SystemTime::from(libc::timespec { + tv_sec: self.stat.st_atime as libc::time_t, + tv_nsec: self.stat.st_atime_nsec as i32, + })) + } + + pub fn created(&self) -> io::Result { + Ok(SystemTime::from(libc::timespec { + tv_sec: self.stat.st_ctime as libc::time_t, + tv_nsec: self.stat.st_ctime_nsec as i32, + })) + } +} + +impl AsInner for FileAttr { + fn as_inner(&self) -> &stat64 { &self.stat } +} + +impl FilePermissions { + pub fn readonly(&self) -> bool { self.mode & 0o222 == 0 } + pub fn set_readonly(&mut self, readonly: bool) { + if readonly { + self.mode &= !0o222; + } else { + self.mode |= 0o222; + } + } + pub fn mode(&self) -> u32 { self.mode as u32 } +} + +impl FileType { + pub fn is_dir(&self) -> bool { self.is(libc::MODE_DIR) } + pub fn is_file(&self) -> bool { self.is(libc::MODE_FILE) } + pub fn is_symlink(&self) -> bool { false } + + pub fn is(&self, mode: mode_t) -> bool { self.mode & (libc::MODE_DIR | libc::MODE_FILE) == mode } +} + +impl FromInner for FilePermissions { + fn from_inner(mode: u32) -> FilePermissions { + FilePermissions { mode: mode as mode_t } + } +} + +impl fmt::Debug for ReadDir { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame. + // Thus the result will be e g 'ReadDir("/home")' + fmt::Debug::fmt(&*self.root, f) + } +} + +impl Iterator for ReadDir { + type Item = io::Result; + + fn next(&mut self) -> Option> { + loop { + let start = self.i; + while self.i < self.data.len() { + let i = self.i; + self.i += 1; + if self.data[i] == b'\n' { + break; + } + } + if start < self.i { + let ret = DirEntry { + name: self.data[start .. self.i].to_owned().into_boxed_slice(), + root: self.root.clone() + }; + if ret.name_bytes() != b"." && ret.name_bytes() != b".." { + return Some(Ok(ret)) + } + } else { + return None; + } + } + } +} + +impl DirEntry { + pub fn path(&self) -> PathBuf { + self.root.join(OsStr::from_bytes(self.name_bytes())) + } + + pub fn file_name(&self) -> OsString { + OsStr::from_bytes(self.name_bytes()).to_os_string() + } + + pub fn metadata(&self) -> io::Result { + lstat(&self.path()) + } + + pub fn file_type(&self) -> io::Result { + stat(&self.path()).map(|m| m.file_type()) + } + + fn name_bytes(&self) -> &[u8] { + &*self.name + } +} + +impl OpenOptions { + pub fn new() -> OpenOptions { + OpenOptions { + // generic + read: false, + write: false, + append: false, + truncate: false, + create: false, + create_new: false, + // system-specific + custom_flags: 0, + mode: 0o666, + } + } + + pub fn read(&mut self, read: bool) { self.read = read; } + pub fn write(&mut self, write: bool) { self.write = write; } + pub fn append(&mut self, append: bool) { self.append = append; } + pub fn truncate(&mut self, truncate: bool) { self.truncate = truncate; } + pub fn create(&mut self, create: bool) { self.create = create; } + pub fn create_new(&mut self, create_new: bool) { self.create_new = create_new; } + + pub fn custom_flags(&mut self, flags: i32) { self.custom_flags = flags; } + pub fn mode(&mut self, mode: u32) { self.mode = mode as mode_t; } + + fn get_access_mode(&self) -> io::Result { + match (self.read, self.write, self.append) { + (true, false, false) => Ok(libc::O_RDONLY as c_int), + (false, true, false) => Ok(libc::O_WRONLY as c_int), + (true, true, false) => Ok(libc::O_RDWR as c_int), + (false, _, true) => Ok(libc::O_WRONLY as c_int | libc::O_APPEND as c_int), + (true, _, true) => Ok(libc::O_RDWR as c_int | libc::O_APPEND as c_int), + (false, false, false) => Err(Error::from_raw_os_error(libc::EINVAL)), + } + } + + fn get_creation_mode(&self) -> io::Result { + match (self.write, self.append) { + (true, false) => {} + (false, false) => + if self.truncate || self.create || self.create_new { + return Err(Error::from_raw_os_error(libc::EINVAL)); + }, + (_, true) => + if self.truncate && !self.create_new { + return Err(Error::from_raw_os_error(libc::EINVAL)); + }, + } + + Ok(match (self.create, self.truncate, self.create_new) { + (false, false, false) => 0, + (true, false, false) => libc::O_CREAT as c_int, + (false, true, false) => libc::O_TRUNC as c_int, + (true, true, false) => libc::O_CREAT as c_int | libc::O_TRUNC as c_int, + (_, _, true) => libc::O_CREAT as c_int | libc::O_EXCL as c_int, + }) + } +} + +impl File { + pub fn open(path: &Path, opts: &OpenOptions) -> io::Result { + let path = cstr(path)?; + File::open_c(&path, opts) + } + + pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result { + 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)) + } + + pub fn file_attr(&self) -> io::Result { + let mut stat: stat64 = unsafe { mem::zeroed() }; + cvt(unsafe { + fstat64(self.0.raw(), &mut stat) + })?; + Ok(FileAttr { stat: stat }) + } + + pub fn fsync(&self) -> io::Result<()> { + cvt_r(|| unsafe { libc::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) } + } + + 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(|_| ()); + } + + pub fn read(&self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } + + pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { + self.0.read_to_end(buf) + } + + pub fn write(&self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + + pub fn flush(&self) -> io::Result<()> { Ok(()) } + + pub fn seek(&self, pos: SeekFrom) -> io::Result { + let (whence, pos) = match pos { + // Casting to `i64` is fine, too large values will end up as + // negative which will cause an error in `lseek64`. + SeekFrom::Start(off) => (libc::SEEK_SET, off as i64), + 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)?; + Ok(n as u64) + } + + pub fn duplicate(&self) -> io::Result { + self.0.duplicate().map(File) + } + + pub fn dup(&self, buf: &[u8]) -> io::Result { + 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)) + } + + pub fn path(&self) -> io::Result { + let mut buf: [u8; 4096] = [0; 4096]; + match libc::fpath(*self.fd().as_inner() as usize, &mut buf) { + Ok(count) => Ok(PathBuf::from(unsafe { String::from_utf8_unchecked(Vec::from(&buf[0..count])) })), + Err(err) => Err(Error::from_raw_os_error(err.errno)), + } + } + + pub fn fd(&self) -> &FileDesc { &self.0 } + + pub fn into_fd(self) -> FileDesc { self.0 } +} + +impl DirBuilder { + pub fn new() -> DirBuilder { + DirBuilder { mode: 0o777 } + } + + pub fn mkdir(&self, p: &Path) -> io::Result<()> { + let p = cstr(p)?; + cvt(unsafe { libc::mkdir(p.as_ptr(), self.mode) })?; + Ok(()) + } + + pub fn set_mode(&mut self, mode: u32) { + self.mode = mode as mode_t; + } +} + +fn cstr(path: &Path) -> io::Result { + Ok(CString::new(path.as_os_str().as_bytes())?) +} + +impl FromInner for File { + fn from_inner(fd: c_int) -> 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 { + 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 { + // 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 { + // 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("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 { + 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 }) + } +} + +pub fn unlink(p: &Path) -> io::Result<()> { + let p = cstr(p)?; + cvt(unsafe { libc::unlink(p.as_ptr()) })?; + Ok(()) +} + +pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { + unimplemented!(); +} + +pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { + unimplemented!(); +} + +pub fn rmdir(p: &Path) -> io::Result<()> { + let p = cstr(p)?; + cvt(unsafe { libc::rmdir(p.as_ptr()) })?; + Ok(()) +} + +pub fn remove_dir_all(path: &Path) -> io::Result<()> { + let filetype = lstat(path)?.file_type(); + if filetype.is_symlink() { + unlink(path) + } else { + remove_dir_all_recursive(path) + } +} + +fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { + for child in readdir(path)? { + let child = child?; + if child.file_type()?.is_dir() { + remove_dir_all_recursive(&child.path())?; + } else { + unlink(&child.path())?; + } + } + rmdir(path) +} + +pub fn readlink(_p: &Path) -> io::Result { + unimplemented!(); +} + +pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> { + unimplemented!(); +} + +pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { + unimplemented!(); +} + +pub fn stat(p: &Path) -> io::Result { + let p = cstr(p)?; + let mut stat: stat64 = unsafe { mem::zeroed() }; + cvt(unsafe { + stat64(p.as_ptr(), &mut stat as *mut _ as *mut _) + })?; + Ok(FileAttr { stat: stat }) +} + +pub fn lstat(p: &Path) -> io::Result { + 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 }) +} + +pub fn canonicalize(_p: &Path) -> io::Result { + unimplemented!(); +} + +pub fn copy(from: &Path, to: &Path) -> io::Result { + use fs::{File, set_permissions}; + if !from.is_file() { + return Err(Error::new(ErrorKind::InvalidInput, + "the source path is not an existing regular file")) + } + + let mut reader = File::open(from)?; + let mut writer = File::create(to)?; + let perm = reader.metadata()?.permissions(); + + let ret = io::copy(&mut reader, &mut writer)?; + set_permissions(to, perm)?; + Ok(ret) +} diff --git a/src/libstd/sys/redox/memchr.rs b/src/libstd/sys/redox/memchr.rs new file mode 100644 index 00000000000..4c314b7a472 --- /dev/null +++ b/src/libstd/sys/redox/memchr.rs @@ -0,0 +1,14 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// Original implementation taken from rust-memchr +// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch + +pub use sys_common::memchr::fallback::{memchr, memrchr}; diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs new file mode 100644 index 00000000000..108ebb0800e --- /dev/null +++ b/src/libstd/sys/redox/mod.rs @@ -0,0 +1,111 @@ +#![allow(dead_code, missing_docs, bad_style)] + +use io::{self, ErrorKind}; +use libc; + +pub mod args; +pub mod backtrace; +pub mod condvar; +pub mod env; +pub mod ext; +pub mod fd; +pub mod fs; +pub mod memchr; +pub mod mutex; +pub mod net; +pub mod os; +pub mod os_str; +pub mod path; +pub mod pipe; +pub mod process; +pub mod rand; +pub mod rwlock; +pub mod stack_overflow; +pub mod stdio; +pub mod thread; +pub mod thread_local; +pub mod time; + +#[cfg(not(test))] +pub fn init() { + use alloc::oom; + + oom::set_oom_handler(oom_handler); + + // A nicer handler for out-of-memory situations than the default one. This + // one prints a message to stderr before aborting. It is critical that this + // code does not allocate any memory since we are in an OOM situation. Any + // errors are ignored while printing since there's nothing we can do about + // them and we are about to exit anyways. + fn oom_handler() -> ! { + 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()); + intrinsics::abort(); + } + } +} + +pub fn decode_error_kind(errno: i32) -> ErrorKind { + match errno as libc::c_int { + libc::ECONNREFUSED => ErrorKind::ConnectionRefused, + libc::ECONNRESET => ErrorKind::ConnectionReset, + libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied, + libc::EPIPE => ErrorKind::BrokenPipe, + libc::ENOTCONN => ErrorKind::NotConnected, + libc::ECONNABORTED => ErrorKind::ConnectionAborted, + libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, + libc::EADDRINUSE => ErrorKind::AddrInUse, + libc::ENOENT => ErrorKind::NotFound, + libc::EINTR => ErrorKind::Interrupted, + libc::EINVAL => ErrorKind::InvalidInput, + libc::ETIMEDOUT => ErrorKind::TimedOut, + libc::EEXIST => ErrorKind::AlreadyExists, + + // These two constants can have the same value on some systems, + // but different values on others, so we can't use a match + // clause + x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => + ErrorKind::WouldBlock, + + _ => ErrorKind::Other, + } +} + +#[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: T) -> io::Result { + if t.is_minus_one() { + Err(io::Error::last_os_error()) + } else { + Ok(t) + } +} + +pub fn cvt_r(mut f: F) -> io::Result + where T: IsMinusOne, + F: FnMut() -> T +{ + loop { + match cvt(f()) { + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + other => return other, + } + } +} diff --git a/src/libstd/sys/redox/mutex.rs b/src/libstd/sys/redox/mutex.rs new file mode 100644 index 00000000000..5723443785a --- /dev/null +++ b/src/libstd/sys/redox/mutex.rs @@ -0,0 +1,125 @@ +use cell::UnsafeCell; +use intrinsics::{atomic_cxchg, atomic_xchg}; +use ptr; + +use libc::{futex, FUTEX_WAIT, FUTEX_WAKE}; + +pub unsafe fn mutex_try_lock(m: *mut i32) -> bool { + atomic_cxchg(m, 0, 1).0 == 0 +} + +pub unsafe fn mutex_lock(m: *mut i32) { + let mut c = 0; + //Set to larger value for longer spin test + for _i in 0..100 { + c = atomic_cxchg(m, 0, 1).0; + if c == 0 { + break; + } + //cpu_relax() + } + if c == 1 { + c = atomic_xchg(m, 2); + } + while c != 0 { + let _ = futex(m, FUTEX_WAIT, 2, 0, ptr::null_mut()); + c = atomic_xchg(m, 2); + } +} + +pub unsafe fn mutex_unlock(m: *mut i32) { + if *m == 2 { + *m = 0; + } else if atomic_xchg(m, 0) == 1 { + return; + } + //Set to larger value for longer spin test + for _i in 0..100 { + if *m != 0 { + if atomic_cxchg(m, 1, 2).0 != 0 { + return; + } + } + //cpu_relax() + } + let _ = futex(m, FUTEX_WAKE, 1, 0, ptr::null_mut()); +} + +pub struct Mutex { + pub lock: UnsafeCell, +} + +impl Mutex { + /// Create a new mutex. + pub const fn new() -> Self { + Mutex { + lock: UnsafeCell::new(0), + } + } + + pub unsafe fn init(&self) { + + } + + /// Try to lock the mutex + pub unsafe fn try_lock(&self) -> bool { + mutex_try_lock(self.lock.get()) + } + + /// Lock the mutex + pub unsafe fn lock(&self) { + mutex_lock(self.lock.get()); + } + + /// Unlock the mutex + pub unsafe fn unlock(&self) { + mutex_unlock(self.lock.get()); + } + + pub unsafe fn destroy(&self) { + + } +} + +unsafe impl Send for Mutex {} + +unsafe impl Sync for Mutex {} + +pub struct ReentrantMutex { + pub lock: UnsafeCell, +} + +impl ReentrantMutex { + pub const fn uninitialized() -> Self { + ReentrantMutex { + lock: UnsafeCell::new(0), + } + } + + pub unsafe fn init(&mut self) { + + } + + /// Try to lock the mutex + pub unsafe fn try_lock(&self) -> bool { + mutex_try_lock(self.lock.get()) + } + + /// Lock the mutex + pub unsafe fn lock(&self) { + mutex_lock(self.lock.get()); + } + + /// Unlock the mutex + pub unsafe fn unlock(&self) { + mutex_unlock(self.lock.get()); + } + + pub unsafe fn destroy(&self) { + + } +} + +unsafe impl Send for ReentrantMutex {} + +unsafe impl Sync for ReentrantMutex {} diff --git a/src/libstd/sys/redox/net/dns/answer.rs b/src/libstd/sys/redox/net/dns/answer.rs new file mode 100644 index 00000000000..c0450c11ed6 --- /dev/null +++ b/src/libstd/sys/redox/net/dns/answer.rs @@ -0,0 +1,12 @@ +use string::String; +use vec::Vec; + +#[derive(Clone, Debug)] +pub struct DnsAnswer { + pub name: String, + pub a_type: u16, + pub a_class: u16, + pub ttl_a: u16, + pub ttl_b: u16, + pub data: Vec +} diff --git a/src/libstd/sys/redox/net/dns/mod.rs b/src/libstd/sys/redox/net/dns/mod.rs new file mode 100644 index 00000000000..4397b71b939 --- /dev/null +++ b/src/libstd/sys/redox/net/dns/mod.rs @@ -0,0 +1,207 @@ +pub use self::answer::DnsAnswer; +pub use self::query::DnsQuery; + +use slice; +use u16; +use string::String; +use vec::Vec; + +mod answer; +mod query; + +#[unstable(feature = "n16", issue="0")] +#[allow(non_camel_case_types)] +#[derive(Copy, Clone, Debug, Default)] +#[repr(packed)] +pub struct n16 { + inner: u16 +} + +impl n16 { + #[unstable(feature = "n16", issue="0")] + pub fn as_bytes(&self) -> &[u8] { + unsafe { slice::from_raw_parts((&self.inner as *const u16) as *const u8, 2) } + } + + #[unstable(feature = "n16", issue="0")] + pub fn from_bytes(bytes: &[u8]) -> Self { + n16 { + inner: unsafe { slice::from_raw_parts(bytes.as_ptr() as *const u16, bytes.len()/2)[0] } + } + } +} + +#[unstable(feature = "n16", issue="0")] +impl From for n16 { + fn from(value: u16) -> Self { + n16 { + inner: value.to_be() + } + } +} + +#[unstable(feature = "n16", issue="0")] +impl From for u16 { + fn from(value: n16) -> Self { + u16::from_be(value.inner) + } +} + +#[derive(Clone, Debug)] +pub struct Dns { + pub transaction_id: u16, + pub flags: u16, + pub queries: Vec, + pub answers: Vec +} + +impl Dns { + pub fn compile(&self) -> Vec { + let mut data = Vec::new(); + + macro_rules! push_u8 { + ($value:expr) => { + data.push($value); + }; + }; + + macro_rules! push_n16 { + ($value:expr) => { + data.extend_from_slice(n16::from($value).as_bytes()); + }; + }; + + push_n16!(self.transaction_id); + push_n16!(self.flags); + push_n16!(self.queries.len() as u16); + push_n16!(self.answers.len() as u16); + push_n16!(0); + push_n16!(0); + + for query in self.queries.iter() { + for part in query.name.split('.') { + push_u8!(part.len() as u8); + data.extend_from_slice(part.as_bytes()); + } + push_u8!(0); + push_n16!(query.q_type); + push_n16!(query.q_class); + } + + data + } + + pub fn parse(data: &[u8]) -> Result { + let mut i = 0; + + macro_rules! pop_u8 { + () => { + { + i += 1; + if i > data.len() { + return Err(format!("{}: {}: pop_u8", file!(), line!())); + } + data[i - 1] + } + }; + }; + + macro_rules! pop_n16 { + () => { + { + i += 2; + if i > data.len() { + return Err(format!("{}: {}: pop_n16", file!(), line!())); + } + u16::from(n16::from_bytes(&data[i - 2 .. i])) + } + }; + }; + + macro_rules! pop_data { + () => { + { + let mut data = Vec::new(); + + let data_len = pop_n16!(); + for _data_i in 0..data_len { + data.push(pop_u8!()); + } + + data + } + }; + }; + + macro_rules! pop_name { + () => { + { + let mut name = String::new(); + + loop { + let name_len = pop_u8!(); + if name_len == 0 { + break; + } + if ! name.is_empty() { + name.push('.'); + } + for _name_i in 0..name_len { + name.push(pop_u8!() as char); + } + } + + name + } + }; + }; + + let transaction_id = pop_n16!(); + let flags = pop_n16!(); + let queries_len = pop_n16!(); + let answers_len = pop_n16!(); + pop_n16!(); + pop_n16!(); + + let mut queries = Vec::new(); + for _query_i in 0..queries_len { + queries.push(DnsQuery { + name: pop_name!(), + q_type: pop_n16!(), + q_class: pop_n16!() + }); + } + + let mut answers = Vec::new(); + for _answer_i in 0..answers_len { + let name_ind = 0b11000000; + let name_test = pop_u8!(); + i -= 1; + + answers.push(DnsAnswer { + name: if name_test & name_ind == name_ind { + let name_off = pop_n16!() - ((name_ind as u16) << 8); + let old_i = i; + i = name_off as usize; + let name = pop_name!(); + i = old_i; + name + } else { + pop_name!() + }, + a_type: pop_n16!(), + a_class: pop_n16!(), + ttl_a: pop_n16!(), + ttl_b: pop_n16!(), + data: pop_data!() + }); + } + + Ok(Dns { + transaction_id: transaction_id, + flags: flags, + queries: queries, + answers: answers, + }) + } +} diff --git a/src/libstd/sys/redox/net/dns/query.rs b/src/libstd/sys/redox/net/dns/query.rs new file mode 100644 index 00000000000..dcb554d82de --- /dev/null +++ b/src/libstd/sys/redox/net/dns/query.rs @@ -0,0 +1,8 @@ +use string::String; + +#[derive(Clone, Debug)] +pub struct DnsQuery { + pub name: String, + pub q_type: u16, + pub q_class: u16 +} diff --git a/src/libstd/sys/redox/net/mod.rs b/src/libstd/sys/redox/net/mod.rs new file mode 100644 index 00000000000..1c8fde546ef --- /dev/null +++ b/src/libstd/sys/redox/net/mod.rs @@ -0,0 +1,91 @@ +use fs::File; +use io::{Error, Result, Read}; +use iter::Iterator; +use net::{Ipv4Addr, SocketAddr, SocketAddrV4}; +use str::FromStr; +use string::{String, ToString}; +use libc::EINVAL; +use time; +use vec::{IntoIter, Vec}; + +use self::dns::{Dns, DnsQuery}; + +pub extern crate libc as netc; +pub use self::tcp::{TcpStream, TcpListener}; +pub use self::udp::UdpSocket; + +mod dns; +mod tcp; +mod udp; + +pub struct LookupHost(IntoIter); + +impl Iterator for LookupHost { + type Item = SocketAddr; + fn next(&mut self) -> Option { + self.0.next() + } +} + +pub fn lookup_host(host: &str) -> Result { + let mut ip_string = String::new(); + File::open("/etc/net/ip")?.read_to_string(&mut ip_string)?; + let ip: Vec = ip_string.trim().split(".").map(|part| part.parse::().unwrap_or(0)).collect(); + + let mut dns_string = String::new(); + File::open("/etc/net/dns")?.read_to_string(&mut dns_string)?; + let dns: Vec = dns_string.trim().split(".").map(|part| part.parse::().unwrap_or(0)).collect(); + + if ip.len() == 4 && dns.len() == 4 { + let tid = (time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap().subsec_nanos() >> 16) as u16; + + let packet = Dns { + transaction_id: tid, + flags: 0x0100, + queries: vec![DnsQuery { + name: host.to_string(), + q_type: 0x0001, + q_class: 0x0001, + }], + answers: vec![] + }; + + let packet_data = packet.compile(); + + let socket = UdpSocket::bind(&SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]), 0)))?; + socket.connect(&SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(dns[0], dns[1], dns[2], dns[3]), 53)))?; + socket.send(&packet_data)?; + + let mut buf = [0; 65536]; + let count = socket.recv(&mut buf)?; + + match Dns::parse(&buf[.. count]) { + Ok(response) => { + let mut addrs = vec![]; + for answer in response.answers.iter() { + if answer.a_type == 0x0001 && answer.a_class == 0x0001 && answer.data.len() == 4 { + addrs.push(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(answer.data[0], answer.data[1], answer.data[2], answer.data[3]), 0))); + } + } + Ok(LookupHost(addrs.into_iter())) + }, + Err(_err) => Err(Error::from_raw_os_error(EINVAL)) + } + } else { + Err(Error::from_raw_os_error(EINVAL)) + } +} + +fn path_to_peer_addr(path_str: &str) -> SocketAddr { + let mut parts = path_str.split('/').next().unwrap_or("").split(':').skip(1); + let host = Ipv4Addr::from_str(parts.next().unwrap_or("")).unwrap_or(Ipv4Addr::new(0, 0, 0, 0)); + let port = parts.next().unwrap_or("").parse::().unwrap_or(0); + SocketAddr::V4(SocketAddrV4::new(host, port)) +} + +fn path_to_local_addr(path_str: &str) -> SocketAddr { + let mut parts = path_str.split('/').nth(1).unwrap_or("").split(':'); + let host = Ipv4Addr::from_str(parts.next().unwrap_or("")).unwrap_or(Ipv4Addr::new(0, 0, 0, 0)); + let port = parts.next().unwrap_or("").parse::().unwrap_or(0); + SocketAddr::V4(SocketAddrV4::new(host, port)) +} diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs new file mode 100644 index 00000000000..351c534c036 --- /dev/null +++ b/src/libstd/sys/redox/net/tcp.rs @@ -0,0 +1,160 @@ +use io::{Error, ErrorKind, Result}; +use net::{SocketAddr, Shutdown}; +use path::Path; +use sys::fs::{File, OpenOptions}; +use time::Duration; +use vec::Vec; + +use super::{path_to_peer_addr, path_to_local_addr}; + +#[derive(Debug)] +pub struct TcpStream(File); + +impl TcpStream { + pub fn connect(addr: &SocketAddr) -> Result { + let path = format!("tcp:{}", addr); + let mut options = OpenOptions::new(); + options.read(true); + options.write(true); + Ok(TcpStream(File::open(&Path::new(path.as_str()), &options)?)) + } + + pub fn duplicate(&self) -> Result { + Ok(TcpStream(self.0.dup(&[])?)) + } + + pub fn read(&self, buf: &mut [u8]) -> Result { + self.0.read(buf) + } + + pub fn read_to_end(&self, buf: &mut Vec) -> Result { + self.0.read_to_end(buf) + } + + pub fn write(&self, buf: &[u8]) -> Result { + self.0.write(buf) + } + + pub fn take_error(&self) -> Result> { + Ok(None) + } + + pub fn peer_addr(&self) -> Result { + let path = self.0.path()?; + Ok(path_to_peer_addr(path.to_str().unwrap_or(""))) + } + + pub fn socket_addr(&self) -> Result { + let path = self.0.path()?; + Ok(path_to_local_addr(path.to_str().unwrap_or(""))) + } + + pub fn shutdown(&self, _how: Shutdown) -> Result<()> { + Err(Error::new(ErrorKind::Other, "TcpStream::shutdown not implemented")) + } + + pub fn nodelay(&self) -> Result { + Err(Error::new(ErrorKind::Other, "TcpStream::nodelay not implemented")) + } + + pub fn nonblocking(&self) -> Result { + Err(Error::new(ErrorKind::Other, "TcpStream::nonblocking not implemented")) + } + + pub fn only_v6(&self) -> Result { + Err(Error::new(ErrorKind::Other, "TcpStream::only_v6 not implemented")) + } + + pub fn ttl(&self) -> Result { + Err(Error::new(ErrorKind::Other, "TcpStream::ttl not implemented")) + } + + pub fn read_timeout(&self) -> Result> { + Err(Error::new(ErrorKind::Other, "TcpStream::read_timeout not implemented")) + } + + pub fn write_timeout(&self) -> Result> { + Err(Error::new(ErrorKind::Other, "TcpStream::write_timeout not implemented")) + } + + pub fn set_nodelay(&self, _nodelay: bool) -> Result<()> { + Err(Error::new(ErrorKind::Other, "TcpStream::set_nodelay not implemented")) + } + + pub fn set_nonblocking(&self, _nonblocking: bool) -> Result<()> { + Err(Error::new(ErrorKind::Other, "TcpStream::set_nonblocking not implemented")) + } + + pub fn set_only_v6(&self, _only_v6: bool) -> Result<()> { + Err(Error::new(ErrorKind::Other, "TcpStream::set_only_v6 not implemented")) + } + + pub fn set_ttl(&self, _ttl: u32) -> Result<()> { + Err(Error::new(ErrorKind::Other, "TcpStream::set_ttl not implemented")) + } + + pub fn set_read_timeout(&self, _dur: Option) -> Result<()> { + Err(Error::new(ErrorKind::Other, "TcpStream::set_read_timeout not implemented")) + } + + pub fn set_write_timeout(&self, _dur: Option) -> Result<()> { + Err(Error::new(ErrorKind::Other, "TcpStream::set_write_timeout not implemented")) + } +} + +#[derive(Debug)] +pub struct TcpListener(File); + +impl TcpListener { + pub fn bind(addr: &SocketAddr) -> Result { + let path = format!("tcp:/{}", addr); + let mut options = OpenOptions::new(); + options.read(true); + options.write(true); + Ok(TcpListener(File::open(&Path::new(path.as_str()), &options)?)) + } + + pub fn accept(&self) -> Result<(TcpStream, SocketAddr)> { + let file = self.0.dup(b"listen")?; + let path = file.path()?; + let peer_addr = path_to_peer_addr(path.to_str().unwrap_or("")); + Ok((TcpStream(file), peer_addr)) + } + + pub fn duplicate(&self) -> Result { + Ok(TcpListener(self.0.dup(&[])?)) + } + + pub fn take_error(&self) -> Result> { + Ok(None) + } + + pub fn socket_addr(&self) -> Result { + let path = self.0.path()?; + Ok(path_to_local_addr(path.to_str().unwrap_or(""))) + } + + pub fn nonblocking(&self) -> Result { + Err(Error::new(ErrorKind::Other, "TcpListener::nonblocking not implemented")) + } + + pub fn only_v6(&self) -> Result { + Err(Error::new(ErrorKind::Other, "TcpListener::only_v6 not implemented")) + } + + pub fn ttl(&self) -> Result { + Err(Error::new(ErrorKind::Other, "TcpListener::ttl not implemented")) + } + + pub fn set_nonblocking(&self, _nonblocking: bool) -> Result<()> { + Err(Error::new(ErrorKind::Other, "TcpListener::set_nonblocking not implemented")) + } + + pub fn set_only_v6(&self, _only_v6: bool) -> Result<()> { + Err(Error::new(ErrorKind::Other, "TcpListener::set_only_v6 not implemented")) + } + + pub fn set_ttl(&self, _ttl: u32) -> Result<()> { + Err(Error::new(ErrorKind::Other, "TcpListener::set_ttl not implemented")) + } +} diff --git a/src/libstd/sys/redox/net/udp.rs b/src/libstd/sys/redox/net/udp.rs new file mode 100644 index 00000000000..a259db6a4c0 --- /dev/null +++ b/src/libstd/sys/redox/net/udp.rs @@ -0,0 +1,163 @@ +use cell::UnsafeCell; +use io::{Error, ErrorKind, Result}; +use net::{SocketAddr, Ipv4Addr, Ipv6Addr}; +use path::Path; +use sys::fs::{File, OpenOptions}; +use time::Duration; + +use super::{path_to_peer_addr, path_to_local_addr}; + +#[derive(Debug)] +pub struct UdpSocket(File, UnsafeCell>); + +impl UdpSocket { + pub fn bind(addr: &SocketAddr) -> Result { + let path = format!("udp:/{}", addr); + let mut options = OpenOptions::new(); + options.read(true); + options.write(true); + Ok(UdpSocket(File::open(&Path::new(path.as_str()), &options)?, UnsafeCell::new(None))) + } + + fn get_conn(&self) -> &mut Option { + unsafe { &mut *(self.1.get()) } + } + + pub fn connect(&self, addr: &SocketAddr) -> Result<()> { + unsafe { *self.1.get() = Some(*addr) }; + Ok(()) + } + + pub fn duplicate(&self) -> Result { + let new_bind = self.0.dup(&[])?; + let new_conn = *self.get_conn(); + Ok(UdpSocket(new_bind, UnsafeCell::new(new_conn))) + } + + pub fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> { + let from = self.0.dup(b"listen")?; + let path = from.path()?; + let peer_addr = path_to_peer_addr(path.to_str().unwrap_or("")); + let count = from.read(buf)?; + Ok((count, peer_addr)) + } + + pub fn recv(&self, buf: &mut [u8]) -> Result { + if let Some(addr) = *self.get_conn() { + let from = self.0.dup(format!("{}", addr).as_bytes())?; + from.read(buf) + } else { + Err(Error::new(ErrorKind::Other, "UdpSocket::recv not connected")) + } + } + + pub fn send_to(&self, buf: &[u8], addr: &SocketAddr) -> Result { + let to = self.0.dup(format!("{}", addr).as_bytes())?; + to.write(buf) + } + + pub fn send(&self, buf: &[u8]) -> Result { + if let Some(addr) = *self.get_conn() { + self.send_to(buf, &addr) + } else { + Err(Error::new(ErrorKind::Other, "UdpSocket::send not connected")) + } + } + + pub fn take_error(&self) -> Result> { + Ok(None) + } + + pub fn socket_addr(&self) -> Result { + let path = self.0.path()?; + Ok(path_to_local_addr(path.to_str().unwrap_or(""))) + } + + pub fn broadcast(&self) -> Result { + Err(Error::new(ErrorKind::Other, "UdpSocket::broadcast not implemented")) + } + + pub fn multicast_loop_v4(&self) -> Result { + Err(Error::new(ErrorKind::Other, "UdpSocket::multicast_loop_v4 not implemented")) + } + + pub fn multicast_loop_v6(&self) -> Result { + Err(Error::new(ErrorKind::Other, "UdpSocket::multicast_loop_v6 not implemented")) + } + + pub fn multicast_ttl_v4(&self) -> Result { + Err(Error::new(ErrorKind::Other, "UdpSocket::multicast_ttl_v4 not implemented")) + } + + pub fn nonblocking(&self) -> Result { + Err(Error::new(ErrorKind::Other, "UdpSocket::nonblocking not implemented")) + } + + pub fn only_v6(&self) -> Result { + Err(Error::new(ErrorKind::Other, "UdpSocket::only_v6 not implemented")) + } + + pub fn ttl(&self) -> Result { + Err(Error::new(ErrorKind::Other, "UdpSocket::ttl not implemented")) + } + + pub fn read_timeout(&self) -> Result> { + Err(Error::new(ErrorKind::Other, "UdpSocket::read_timeout not implemented")) + } + + pub fn write_timeout(&self) -> Result> { + Err(Error::new(ErrorKind::Other, "UdpSocket::write_timeout not implemented")) + } + + pub fn set_broadcast(&self, _broadcast: bool) -> Result<()> { + Err(Error::new(ErrorKind::Other, "UdpSocket::set_broadcast not implemented")) + } + + pub fn set_multicast_loop_v4(&self, _multicast_loop_v4: bool) -> Result<()> { + Err(Error::new(ErrorKind::Other, "UdpSocket::set_multicast_loop_v4 not implemented")) + } + + pub fn set_multicast_loop_v6(&self, _multicast_loop_v6: bool) -> Result<()> { + Err(Error::new(ErrorKind::Other, "UdpSocket::set_multicast_loop_v6 not implemented")) + } + + pub fn set_multicast_ttl_v4(&self, _multicast_ttl_v4: u32) -> Result<()> { + Err(Error::new(ErrorKind::Other, "UdpSocket::set_multicast_ttl_v4 not implemented")) + } + + pub fn set_nonblocking(&self, _nonblocking: bool) -> Result<()> { + Err(Error::new(ErrorKind::Other, "UdpSocket::set_nonblocking not implemented")) + } + + pub fn set_only_v6(&self, _only_v6: bool) -> Result<()> { + Err(Error::new(ErrorKind::Other, "UdpSocket::set_only_v6 not implemented")) + } + + pub fn set_ttl(&self, _ttl: u32) -> Result<()> { + Err(Error::new(ErrorKind::Other, "UdpSocket::set_ttl not implemented")) + } + + pub fn set_read_timeout(&self, _dur: Option) -> Result<()> { + Err(Error::new(ErrorKind::Other, "UdpSocket::set_read_timeout not implemented")) + } + + pub fn set_write_timeout(&self, _dur: Option) -> Result<()> { + Err(Error::new(ErrorKind::Other, "UdpSocket::set_write_timeout not implemented")) + } + + pub fn join_multicast_v4(&self, _multiaddr: &Ipv4Addr, _interface: &Ipv4Addr) -> Result<()> { + Err(Error::new(ErrorKind::Other, "UdpSocket::join_multicast_v4 not implemented")) + } + + pub fn join_multicast_v6(&self, _multiaddr: &Ipv6Addr, _interface: u32) -> Result<()> { + Err(Error::new(ErrorKind::Other, "UdpSocket::join_multicast_v6 not implemented")) + } + + pub fn leave_multicast_v4(&self, _multiaddr: &Ipv4Addr, _interface: &Ipv4Addr) -> Result<()> { + Err(Error::new(ErrorKind::Other, "UdpSocket::leave_multicast_v4 not implemented")) + } + + pub fn leave_multicast_v6(&self, _multiaddr: &Ipv6Addr, _interface: u32) -> Result<()> { + Err(Error::new(ErrorKind::Other, "UdpSocket::leave_multicast_v6 not implemented")) + } +} diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs new file mode 100644 index 00000000000..a2262369e92 --- /dev/null +++ b/src/libstd/sys/redox/os.rs @@ -0,0 +1,246 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Implementation of `std::os` functionality for unix systems + +#![allow(unused_imports)] // lots of cfg code here + +use os::unix::prelude::*; + +use error::Error as StdError; +use ffi::{CString, CStr, OsString, OsStr}; +use fmt; +use io; +use iter; +use libc::{self, c_int, c_char, c_void}; +use marker::PhantomData; +use mem; +use memchr; +use path::{self, PathBuf}; +use ptr; +use slice; +use str; +use sys_common::mutex::Mutex; +use sys::cvt; +use sys::fd; +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 +} + +/// 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() + } +} + +pub fn getcwd() -> io::Result { + 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); + } + } +} + +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()), + } + } +} + +pub struct SplitPaths<'a> { + iter: iter::Map bool>, + fn(&'a [u8]) -> PathBuf>, +} + +pub fn split_paths(unparsed: &OsStr) -> SplitPaths { + fn bytes_to_path(b: &[u8]) -> PathBuf { + PathBuf::from(::from_bytes(b)) + } + fn is_colon(b: &u8) -> bool { *b == b':' } + let unparsed = unparsed.as_bytes(); + SplitPaths { + iter: unparsed.split(is_colon as fn(&u8) -> bool) + .map(bytes_to_path as fn(&[u8]) -> PathBuf) + } +} + +impl<'a> Iterator for SplitPaths<'a> { + type Item = PathBuf; + fn next(&mut self) -> Option { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} + +#[derive(Debug)] +pub struct JoinPathsError; + +pub fn join_paths(paths: I) -> Result + where I: Iterator, T: AsRef +{ + let mut joined = Vec::new(); + let sep = b':'; + + for (i, path) in paths.enumerate() { + let path = path.as_ref().as_bytes(); + if i > 0 { joined.push(sep) } + if path.contains(&sep) { + return Err(JoinPathsError) + } + joined.extend_from_slice(path); + } + Ok(OsStringExt::from_vec(joined)) +} + +impl fmt::Display for JoinPathsError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "path segment contains separator `:`".fmt(f) + } +} + +impl StdError for JoinPathsError { + fn description(&self) -> &str { "failed to join paths" } +} + +pub fn current_exe() -> io::Result { + use io::ErrorKind; + Err(io::Error::new(ErrorKind::Other, "Not yet implemented on redox")) +} + +pub struct Env { + iter: vec::IntoIter<(OsString, OsString)>, + _dont_send_or_sync_me: PhantomData<*mut ()>, +} + +impl Iterator for Env { + type Item = (OsString, OsString); + fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} + +/// Returns a vector of (variable, value) byte-vector pairs for all the +/// environment variables of the current process. +pub fn env() -> Env { + unimplemented!(); +} + +pub fn getenv(_k: &OsStr) -> io::Result> { + unimplemented!(); +} + +pub fn setenv(_k: &OsStr, _v: &OsStr) -> io::Result<()> { + unimplemented!(); +} + +pub fn unsetenv(_n: &OsStr) -> io::Result<()> { + unimplemented!(); +} + +pub fn page_size() -> usize { + 4096 +} + +pub fn temp_dir() -> PathBuf { + ::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| { + PathBuf::from("/tmp") + }) +} + +pub fn home_dir() -> Option { + return ::env::var_os("HOME").map(PathBuf::from); +} + +pub fn exit(code: i32) -> ! { + unsafe { libc::exit(code as c_int) } +} diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs new file mode 100644 index 00000000000..5a733c0cb87 --- /dev/null +++ b/src/libstd/sys/redox/os_str.rs @@ -0,0 +1,119 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// The underlying OsString/OsStr implementation on Unix systems: just +/// a `Vec`/`[u8]`. + +use borrow::Cow; +use fmt::{self, Debug}; +use str; +use mem; +use sys_common::{AsInner, IntoInner}; + +#[derive(Clone, Hash)] +pub struct Buf { + pub inner: Vec +} + +pub struct Slice { + pub inner: [u8] +} + +impl Debug for Slice { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + self.to_string_lossy().fmt(formatter) + } +} + +impl Debug for Buf { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + self.as_slice().fmt(formatter) + } +} + +impl IntoInner> for Buf { + fn into_inner(self) -> Vec { + self.inner + } +} + +impl AsInner<[u8]> for Buf { + fn as_inner(&self) -> &[u8] { + &self.inner + } +} + + +impl Buf { + pub fn from_string(s: String) -> Buf { + Buf { inner: s.into_bytes() } + } + + #[inline] + pub fn with_capacity(capacity: usize) -> Buf { + Buf { + inner: Vec::with_capacity(capacity) + } + } + + #[inline] + pub fn clear(&mut self) { + self.inner.clear() + } + + #[inline] + pub fn capacity(&self) -> usize { + self.inner.capacity() + } + + #[inline] + pub fn reserve(&mut self, additional: usize) { + self.inner.reserve(additional) + } + + #[inline] + pub fn reserve_exact(&mut self, additional: usize) { + self.inner.reserve_exact(additional) + } + + pub fn as_slice(&self) -> &Slice { + unsafe { mem::transmute(&*self.inner) } + } + + pub fn into_string(self) -> Result { + String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } ) + } + + pub fn push_slice(&mut self, s: &Slice) { + self.inner.extend_from_slice(&s.inner) + } +} + +impl Slice { + fn from_u8_slice(s: &[u8]) -> &Slice { + unsafe { mem::transmute(s) } + } + + pub fn from_str(s: &str) -> &Slice { + Slice::from_u8_slice(s.as_bytes()) + } + + pub fn to_str(&self) -> Option<&str> { + str::from_utf8(&self.inner).ok() + } + + pub fn to_string_lossy(&self) -> Cow { + String::from_utf8_lossy(&self.inner) + } + + pub fn to_owned(&self) -> Buf { + Buf { inner: self.inner.to_vec() } + } +} diff --git a/src/libstd/sys/redox/path.rs b/src/libstd/sys/redox/path.rs new file mode 100644 index 00000000000..bf9af7a4353 --- /dev/null +++ b/src/libstd/sys/redox/path.rs @@ -0,0 +1,29 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use path::Prefix; +use ffi::OsStr; + +#[inline] +pub fn is_sep_byte(b: u8) -> bool { + b == b'/' +} + +#[inline] +pub fn is_verbatim_sep(b: u8) -> bool { + b == b'/' +} + +pub fn parse_prefix(_: &OsStr) -> Option { + None +} + +pub const MAIN_SEP_STR: &'static str = "/"; +pub const MAIN_SEP: char = '/'; diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs new file mode 100644 index 00000000000..f77f1e0dc68 --- /dev/null +++ b/src/libstd/sys/redox/pipe.rs @@ -0,0 +1,105 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use io; +use libc::{self, c_int}; +use sys::fd::FileDesc; + +//////////////////////////////////////////////////////////////////////////////// +// Anonymous pipes +//////////////////////////////////////////////////////////////////////////////// + +pub struct AnonPipe(FileDesc); + +pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { + let mut fds = [0; 2]; + + 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); + Ok((AnonPipe::from_fd(fd0)?, AnonPipe::from_fd(fd1)?)) +} + +impl AnonPipe { + pub fn from_fd(fd: FileDesc) -> io::Result { + fd.set_cloexec()?; + Ok(AnonPipe(fd)) + } + + pub fn read(&self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } + + pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { + self.0.read_to_end(buf) + } + + pub fn write(&self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + + pub fn fd(&self) -> &FileDesc { &self.0 } + pub fn into_fd(self) -> FileDesc { self.0 } +} + +pub fn read2(_p1: AnonPipe, + _v1: &mut Vec, + _p2: AnonPipe, + _v2: &mut Vec) -> io::Result<()> { + unimplemented!(); + /* + // Set both pipes into nonblocking mode as we're gonna be reading from both + // in the `select` loop below, and we wouldn't want one to block the other! + let p1 = p1.into_fd(); + let p2 = p2.into_fd(); + p1.set_nonblocking(true)?; + p2.set_nonblocking(true)?; + + let max = cmp::max(p1.raw(), p2.raw()); + loop { + // wait for either pipe to become readable using `select` + cvt_r(|| unsafe { + let mut read: libc::fd_set = mem::zeroed(); + libc::FD_SET(p1.raw(), &mut read); + libc::FD_SET(p2.raw(), &mut read); + libc::select(max + 1, &mut read, ptr::null_mut(), ptr::null_mut(), + ptr::null_mut()) + })?; + + // Read as much as we can from each pipe, ignoring EWOULDBLOCK or + // EAGAIN. If we hit EOF, then this will happen because the underlying + // reader will return Ok(0), in which case we'll see `Ok` ourselves. In + // this case we flip the other fd back into blocking mode and read + // whatever's leftover on that file descriptor. + let read = |fd: &FileDesc, dst: &mut Vec| { + match fd.read_to_end(dst) { + Ok(_) => Ok(true), + Err(e) => { + if e.raw_os_error() == Some(libc::EWOULDBLOCK) || + e.raw_os_error() == Some(libc::EAGAIN) { + Ok(false) + } else { + Err(e) + } + } + } + }; + if read(&p1, v1)? { + p2.set_nonblocking(false)?; + return p2.read_to_end(v2).map(|_| ()); + } + if read(&p2, v2)? { + p1.set_nonblocking(false)?; + return p1.read_to_end(v1).map(|_| ()); + } + } + */ +} diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs new file mode 100644 index 00000000000..b025623fc9f --- /dev/null +++ b/src/libstd/sys/redox/process.rs @@ -0,0 +1,593 @@ +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use os::unix::prelude::*; + +use collections::hash_map::HashMap; +use env; +use ffi::{OsStr, CString, CStr}; +use fmt; +use io::{self, Error, ErrorKind}; +use libc::{self, pid_t, c_int, gid_t, uid_t}; +use sys::fd::FileDesc; +use sys::fs::{File, OpenOptions}; +use sys::pipe::{self, AnonPipe}; +use sys::{self, cvt, cvt_r}; + +//////////////////////////////////////////////////////////////////////////////// +// Command +//////////////////////////////////////////////////////////////////////////////// + +pub struct Command { + // Currently we try hard to ensure that the call to `.exec()` doesn't + // actually allocate any memory. While many platforms try to ensure that + // memory allocation works after a fork in a multithreaded process, it's + // been observed to be buggy and somewhat unreliable, so we do our best to + // just not do it at all! + // + // Along those lines, the `argv` and `envp` raw pointers here are exactly + // what's gonna get passed to `execvp`. The `argv` array starts with the + // `program` and ends with a NULL, and the `envp` pointer, if present, is + // also null-terminated. + // + // Right now we don't support removing arguments, so there's no much fancy + // support there, but we support adding and removing environment variables, + // so a side table is used to track where in the `envp` array each key is + // located. Whenever we add a key we update it in place if it's already + // present, and whenever we remove a key we update the locations of all + // other keys. + program: String, + args: Vec, + env: HashMap, + + cwd: Option, + uid: Option, + gid: Option, + saw_nul: bool, + closures: Vec io::Result<()> + Send + Sync>>, + stdin: Option, + stdout: Option, + stderr: Option, +} + +// passed back to std::process with the pipes connected to the child, if any +// were requested +pub struct StdioPipes { + pub stdin: Option, + pub stdout: Option, + pub stderr: Option, +} + +// passed to do_exec() with configuration of what the child stdio should look +// like +struct ChildPipes { + stdin: ChildStdio, + stdout: ChildStdio, + stderr: ChildStdio, +} + +enum ChildStdio { + Inherit, + Explicit(c_int), + Owned(FileDesc), +} + +pub enum Stdio { + Inherit, + Null, + MakePipe, + Fd(FileDesc), +} + +impl Command { + pub fn new(program: &OsStr) -> Command { + Command { + program: program.to_str().unwrap().to_owned(), + args: Vec::new(), + env: HashMap::new(), + cwd: None, + uid: None, + gid: None, + saw_nul: false, + closures: Vec::new(), + stdin: None, + stdout: None, + stderr: None, + } + } + + pub fn arg(&mut self, arg: &OsStr) { + self.args.push(arg.to_str().unwrap().to_owned()); + } + + pub fn env(&mut self, key: &OsStr, val: &OsStr) { + self.env.insert(key.to_str().unwrap().to_owned(), val.to_str().unwrap().to_owned()); + } + + pub fn env_remove(&mut self, key: &OsStr) { + self.env.remove(key.to_str().unwrap()); + } + + pub fn env_clear(&mut self) { + self.env.clear(); + } + + pub fn cwd(&mut self, dir: &OsStr) { + self.cwd = Some(os2c(dir, &mut self.saw_nul)); + } + pub fn uid(&mut self, id: uid_t) { + self.uid = Some(id); + } + pub fn gid(&mut self, id: gid_t) { + self.gid = Some(id); + } + + pub fn before_exec(&mut self, + f: Box io::Result<()> + Send + Sync>) { + self.closures.push(f); + } + + pub fn stdin(&mut self, stdin: Stdio) { + self.stdin = Some(stdin); + } + pub fn stdout(&mut self, stdout: Stdio) { + self.stdout = Some(stdout); + } + pub fn stderr(&mut self, stderr: Stdio) { + self.stderr = Some(stderr); + } + + pub fn spawn(&mut self, default: Stdio, needs_stdin: bool) + -> io::Result<(Process, StdioPipes)> { + const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX"; + + if self.saw_nul { + return Err(io::Error::new(ErrorKind::InvalidInput, + "nul byte found in provided data")); + } + + let (ours, theirs) = self.setup_io(default, needs_stdin)?; + let (input, output) = sys::pipe::anon_pipe()?; + + let pid = unsafe { + match cvt(libc::fork() as isize)? { + 0 => { + drop(input); + let err = self.do_exec(theirs); + let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32; + let bytes = [ + (errno >> 24) as u8, + (errno >> 16) as u8, + (errno >> 8) as u8, + (errno >> 0) as u8, + CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1], + CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3] + ]; + // pipe I/O up to PIPE_BUF bytes should be atomic, and then + // 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) + } + n => n as pid_t, + } + }; + + let mut p = Process { pid: pid, status: None }; + drop(output); + let mut bytes = [0; 8]; + + // loop to handle EINTR + loop { + match input.read(&mut bytes) { + Ok(0) => return Ok((p, ours)), + Ok(8) => { + assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]), + "Validation on the CLOEXEC pipe failed: {:?}", bytes); + let errno = combine(&bytes[0.. 4]); + assert!(p.wait().is_ok(), + "wait() should either return Ok or panic"); + return Err(Error::from_raw_os_error(errno)) + } + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => { + assert!(p.wait().is_ok(), + "wait() should either return Ok or panic"); + panic!("the CLOEXEC pipe failed: {:?}", e) + }, + Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic + assert!(p.wait().is_ok(), + "wait() should either return Ok or panic"); + panic!("short read on the CLOEXEC pipe") + } + } + } + + fn combine(arr: &[u8]) -> i32 { + let a = arr[0] as u32; + let b = arr[1] as u32; + let c = arr[2] as u32; + let d = arr[3] as u32; + + ((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32 + } + } + + pub fn exec(&mut self, default: Stdio) -> io::Error { + if self.saw_nul { + return io::Error::new(ErrorKind::InvalidInput, + "nul byte found in provided data") + } + + match self.setup_io(default, true) { + Ok((_, theirs)) => unsafe { self.do_exec(theirs) }, + Err(e) => e, + } + } + + // And at this point we've reached a special time in the life of the + // child. The child must now be considered hamstrung and unable to + // do anything other than syscalls really. Consider the following + // scenario: + // + // 1. Thread A of process 1 grabs the malloc() mutex + // 2. Thread B of process 1 forks(), creating thread C + // 3. Thread C of process 2 then attempts to malloc() + // 4. The memory of process 2 is the same as the memory of + // process 1, so the mutex is locked. + // + // This situation looks a lot like deadlock, right? It turns out + // that this is what pthread_atfork() takes care of, which is + // presumably implemented across platforms. The first thing that + // threads to *before* forking is to do things like grab the malloc + // mutex, and then after the fork they unlock it. + // + // Despite this information, libnative's spawn has been witnessed to + // deadlock on both OSX and FreeBSD. I'm not entirely sure why, but + // all collected backtraces point at malloc/free traffic in the + // child spawned process. + // + // For this reason, the block of code below should contain 0 + // invocations of either malloc of free (or their related friends). + // + // As an example of not having malloc/free traffic, we don't close + // this file descriptor by dropping the FileDesc (which contains an + // allocation). Instead we just close it manually. This will never + // have the drop glue anyway because this code never returns (the + // child will either exec() or invoke libc::exit) + unsafe fn do_exec(&mut self, stdio: ChildPipes) -> io::Error { + macro_rules! t { + ($e:expr) => (match $e { + Ok(e) => e, + Err(e) => return e, + }) + } + + if let Some(fd) = stdio.stderr.fd() { + libc::close(libc::STDERR_FILENO); + t!(cvt(libc::dup(fd))); + libc::close(fd); + } + if let Some(fd) = stdio.stdout.fd() { + libc::close(libc::STDOUT_FILENO); + t!(cvt(libc::dup(fd))); + libc::close(fd); + } + if let Some(fd) = stdio.stdin.fd() { + libc::close(libc::STDIN_FILENO); + t!(cvt(libc::dup(fd))); + libc::close(fd); + } + + if let Some(u) = self.gid { + t!(cvt(libc::setgid(u as gid_t))); + } + if let Some(u) = self.uid { + t!(cvt(libc::setuid(u as uid_t))); + } + if let Some(ref cwd) = self.cwd { + t!(cvt(libc::chdir(cwd.as_ptr()))); + } + + for callback in self.closures.iter_mut() { + t!(callback()); + } + + let mut args: Vec<[usize; 2]> = Vec::new(); + args.push([self.program.as_ptr() as usize, self.program.len()]); + for arg in self.args.iter() { + args.push([arg.as_ptr() as usize, arg.len()]); + } + + for (key, val) in self.env.iter() { + env::set_var(key, val); + } + + if let Err(err) = libc::exec(&self.program, &args) { + io::Error::from_raw_os_error(err.errno as i32) + } else { + panic!("return from exec without err"); + } + } + + + fn setup_io(&self, default: Stdio, needs_stdin: bool) + -> io::Result<(StdioPipes, ChildPipes)> { + let null = Stdio::Null; + let default_stdin = if needs_stdin {&default} else {&null}; + let stdin = self.stdin.as_ref().unwrap_or(default_stdin); + let stdout = self.stdout.as_ref().unwrap_or(&default); + let stderr = self.stderr.as_ref().unwrap_or(&default); + let (their_stdin, our_stdin) = stdin.to_child_stdio(true)?; + let (their_stdout, our_stdout) = stdout.to_child_stdio(false)?; + let (their_stderr, our_stderr) = stderr.to_child_stdio(false)?; + let ours = StdioPipes { + stdin: our_stdin, + stdout: our_stdout, + stderr: our_stderr, + }; + let theirs = ChildPipes { + stdin: their_stdin, + stdout: their_stdout, + stderr: their_stderr, + }; + Ok((ours, theirs)) + } +} + +fn os2c(s: &OsStr, saw_nul: &mut bool) -> CString { + CString::new(s.as_bytes()).unwrap_or_else(|_e| { + *saw_nul = true; + CString::new("").unwrap() + }) +} + +impl Stdio { + fn to_child_stdio(&self, readable: bool) + -> io::Result<(ChildStdio, Option)> { + match *self { + Stdio::Inherit => Ok((ChildStdio::Inherit, None)), + + // Make sure that the source descriptors are not an stdio + // descriptor, otherwise the order which we set the child's + // descriptors may blow away a descriptor which we are hoping to + // save. For example, suppose we want the child's stderr to be the + // parent's stdout, and the child's stdout to be the parent's + // 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 { + Ok((ChildStdio::Owned(fd.duplicate()?), None)) + } else { + Ok((ChildStdio::Explicit(fd.raw()), None)) + } + } + + Stdio::MakePipe => { + let (reader, writer) = pipe::anon_pipe()?; + let (ours, theirs) = if readable { + (writer, reader) + } else { + (reader, writer) + }; + Ok((ChildStdio::Owned(theirs.into_fd()), Some(ours))) + } + + Stdio::Null => { + 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)?; + Ok((ChildStdio::Owned(fd.into_fd()), None)) + } + } + } +} + +impl ChildStdio { + fn fd(&self) -> Option { + match *self { + ChildStdio::Inherit => None, + ChildStdio::Explicit(fd) => Some(fd), + ChildStdio::Owned(ref fd) => Some(fd.raw()), + } + } +} + +fn pair_to_key(key: &OsStr, value: &OsStr, saw_nul: &mut bool) -> CString { + let (key, value) = (key.as_bytes(), value.as_bytes()); + let mut v = Vec::with_capacity(key.len() + value.len() + 1); + v.extend(key); + v.push(b'='); + v.extend(value); + CString::new(v).unwrap_or_else(|_e| { + *saw_nul = true; + CString::new("foo=bar").unwrap() + }) +} + +impl fmt::Debug for Command { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.program)?; + for arg in &self.args { + write!(f, " {:?}", arg)?; + } + Ok(()) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Processes +//////////////////////////////////////////////////////////////////////////////// + +/// Unix exit statuses +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitStatus(c_int); + +impl ExitStatus { + fn exited(&self) -> bool { + true + } + + pub fn success(&self) -> bool { + self.code() == Some(0) + } + + pub fn code(&self) -> Option { + if self.exited() { + Some(self.0) + } else { + None + } + } + + pub fn signal(&self) -> Option { + if !self.exited() { + Some(self.0) + } else { + None + } + } +} + +impl From for ExitStatus { + fn from(a: c_int) -> ExitStatus { + ExitStatus(a) + } +} + +impl fmt::Display for ExitStatus { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if let Some(code) = self.code() { + write!(f, "exit code: {}", code) + } else { + let signal = self.signal().unwrap(); + write!(f, "signal: {}", signal) + } + } +} + +/// The unique id of the process (this should never be negative). +pub struct Process { + pid: pid_t, + status: Option, +} + +impl Process { + pub fn id(&self) -> u32 { + self.pid as u32 + } + + pub fn kill(&mut self) -> io::Result<()> { + // If we've already waited on this process then the pid can be recycled + // and used for another process, and we probably shouldn't be killing + // random processes, so just return an error. + if self.status.is_some() { + Err(Error::new(ErrorKind::InvalidInput, + "invalid argument: can't kill an exited process")) + } else { + cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(|_| ()) + } + } + + pub fn wait(&mut self) -> io::Result { + if let Some(status) = self.status { + return Ok(status) + } + let mut status = 0; + cvt_r(|| unsafe { 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::()); + 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/rand.rs b/src/libstd/sys/redox/rand.rs new file mode 100644 index 00000000000..6ea9a3fb105 --- /dev/null +++ b/src/libstd/sys/redox/rand.rs @@ -0,0 +1,40 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use fs::File; +use io; +use rand::Rng; +use rand::reader::ReaderRng; + +pub struct OsRng { + inner: ReaderRng, +} + +impl OsRng { + /// Create a new `OsRng`. + pub fn new() -> io::Result { + let reader = File::open("rand:")?; + let reader_rng = ReaderRng::new(reader); + + Ok(OsRng { inner: reader_rng }) + } +} + +impl Rng for OsRng { + fn next_u32(&mut self) -> u32 { + self.inner.next_u32() + } + fn next_u64(&mut self) -> u64 { + self.inner.next_u64() + } + fn fill_bytes(&mut self, v: &mut [u8]) { + self.inner.fill_bytes(v) + } +} diff --git a/src/libstd/sys/redox/rwlock.rs b/src/libstd/sys/redox/rwlock.rs new file mode 100644 index 00000000000..c2de1d50685 --- /dev/null +++ b/src/libstd/sys/redox/rwlock.rs @@ -0,0 +1,55 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub struct RWLock; + +unsafe impl Send for RWLock {} +unsafe impl Sync for RWLock {} + +impl RWLock { + pub const fn new() -> RWLock { + RWLock + } + + #[inline] + pub unsafe fn read(&self) { + unimplemented!(); + } + + #[inline] + pub unsafe fn try_read(&self) -> bool { + unimplemented!(); + } + + #[inline] + pub unsafe fn write(&self) { + unimplemented!(); + } + + #[inline] + pub unsafe fn try_write(&self) -> bool { + unimplemented!(); + } + + #[inline] + pub unsafe fn read_unlock(&self) { + unimplemented!(); + } + + #[inline] + pub unsafe fn write_unlock(&self) { + unimplemented!(); + } + + #[inline] + pub unsafe fn destroy(&self) { + + } +} diff --git a/src/libstd/sys/redox/stack_overflow.rs b/src/libstd/sys/redox/stack_overflow.rs new file mode 100644 index 00000000000..c8595d38b21 --- /dev/null +++ b/src/libstd/sys/redox/stack_overflow.rs @@ -0,0 +1,27 @@ +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg_attr(test, allow(dead_code))] + +pub struct Handler; + +impl Handler { + pub unsafe fn new() -> Handler { + unimplemented!(); + } +} + +pub unsafe fn init() { + +} + +pub unsafe fn cleanup() { + unimplemented!(); +} diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs new file mode 100644 index 00000000000..0ed9de36c73 --- /dev/null +++ b/src/libstd/sys/redox/stdio.rs @@ -0,0 +1,69 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use io; +use libc; +use sys::fd::FileDesc; + +pub struct Stdin(()); +pub struct Stdout(()); +pub struct Stderr(()); + +impl Stdin { + pub fn new() -> io::Result { Ok(Stdin(())) } + + pub fn read(&self, data: &mut [u8]) -> io::Result { + let fd = FileDesc::new(libc::STDIN_FILENO); + let ret = fd.read(data); + fd.into_raw(); + ret + } + + pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { + let fd = FileDesc::new(libc::STDIN_FILENO); + let ret = fd.read_to_end(buf); + fd.into_raw(); + ret + } +} + +impl Stdout { + pub fn new() -> io::Result { Ok(Stdout(())) } + + pub fn write(&self, data: &[u8]) -> io::Result { + let fd = FileDesc::new(libc::STDOUT_FILENO); + let ret = fd.write(data); + fd.into_raw(); + ret + } +} + +impl Stderr { + pub fn new() -> io::Result { Ok(Stderr(())) } + + pub fn write(&self, data: &[u8]) -> io::Result { + let fd = FileDesc::new(libc::STDERR_FILENO); + let ret = fd.write(data); + fd.into_raw(); + ret + } +} + +// FIXME: right now this raw stderr handle is used in a few places because +// std::io::stderr_raw isn't exposed, but once that's exposed this impl +// should go away +impl io::Write for Stderr { + fn write(&mut self, data: &[u8]) -> io::Result { + Stderr::write(self, data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +pub const EBADF_ERR: i32 = ::libc::EBADF; diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs new file mode 100644 index 00000000000..eaf908dc53e --- /dev/null +++ b/src/libstd/sys/redox/thread.rs @@ -0,0 +1,94 @@ +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use alloc::boxed::FnBox; +use cmp; +use ffi::CStr; +use io; +use libc; +use mem; +use sys::os; +use sys_common::thread::start_thread; +use time::Duration; + +pub struct Thread { + id: libc::pid_t, +} + +// Some platforms may have pthread_t as a pointer in which case we still want +// a thread to be Send/Sync +unsafe impl Send for Thread {} +unsafe impl Sync for Thread {} + +impl Thread { + pub unsafe fn new<'a>(_stack: usize, p: Box) -> io::Result { + let p = box p; + + start_thread(&*p as *const _ as *mut _); + + unimplemented!(); + } + + pub fn yield_now() { + let ret = unsafe { libc::sched_yield() }; + debug_assert_eq!(ret, 0); + } + + pub fn set_name(_name: &CStr) { + + } + + pub fn sleep(dur: Duration) { + let mut secs = dur.as_secs(); + let mut nsecs = dur.subsec_nanos() as i32; + + // 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; + } + } + } + } + + pub fn join(self) { + panic!(); + } + + pub fn id(&self) -> libc::pid_t { self.id } + + pub fn into_id(self) -> libc::pid_t { + let id = self.id; + mem::forget(self); + id + } +} + +impl Drop for Thread { + fn drop(&mut self) { + panic!(); + } +} + +pub mod guard { + pub unsafe fn current() -> Option { None } + pub unsafe fn init() -> Option { None } +} diff --git a/src/libstd/sys/redox/thread_local.rs b/src/libstd/sys/redox/thread_local.rs new file mode 100644 index 00000000000..2639ef013de --- /dev/null +++ b/src/libstd/sys/redox/thread_local.rs @@ -0,0 +1,41 @@ +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] // not used on all platforms + +pub type Key = usize; + +#[inline] +pub unsafe fn create(_dtor: Option) -> Key { + panic!("pthread key create not supported"); + //let mut key = 0; + //assert_eq!(libc::pthread_key_create(&mut key, mem::transmute(dtor)), 0); + //key +} + +#[inline] +pub unsafe fn set(_key: Key, _value: *mut u8) { + panic!("pthread key set not supported"); + //let r = libc::pthread_setspecific(key, value as *mut _); + //debug_assert_eq!(r, 0); +} + +#[inline] +pub unsafe fn get(_key: Key) -> *mut u8 { + panic!("pthread key get not supported"); + //libc::pthread_getspecific(key) as *mut u8 +} + +#[inline] +pub unsafe fn destroy(_key: Key) { + panic!("pthread key destroy not supported"); + //let r = libc::pthread_key_delete(key); + //debug_assert_eq!(r, 0); +} diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs new file mode 100644 index 00000000000..5caaf20fdf8 --- /dev/null +++ b/src/libstd/sys/redox/time.rs @@ -0,0 +1,351 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use cmp::Ordering; +use libc; +use time::Duration; + +pub use self::inner::{Instant, SystemTime, UNIX_EPOCH}; + +const NSEC_PER_SEC: u64 = 1_000_000_000; + +#[derive(Copy, Clone)] +struct Timespec { + t: libc::timespec, +} + +impl Timespec { + fn sub_timespec(&self, other: &Timespec) -> Result { + if self >= other { + Ok(if self.t.tv_nsec >= other.t.tv_nsec { + Duration::new((self.t.tv_sec - other.t.tv_sec) as u64, + (self.t.tv_nsec - other.t.tv_nsec) as u32) + } else { + Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64, + self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - + other.t.tv_nsec as u32) + }) + } else { + match other.sub_timespec(self) { + Ok(d) => Err(d), + Err(d) => Ok(d), + } + } + } + + fn add_duration(&self, other: &Duration) -> Timespec { + let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64); + let mut secs = secs.expect("overflow when adding duration to time"); + + // Nano calculations can't overflow because nanos are <1B which fit + // in a u32. + let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; + if nsec >= NSEC_PER_SEC as u32 { + nsec -= NSEC_PER_SEC as u32; + secs = secs.checked_add(1).expect("overflow when adding \ + duration to time"); + } + Timespec { + t: libc::timespec { + tv_sec: secs as libc::time_t, + tv_nsec: nsec as i32, + }, + } + } + + fn sub_duration(&self, other: &Duration) -> Timespec { + let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64); + let mut secs = secs.expect("overflow when subtracting duration \ + from time"); + + // Similar to above, nanos can't overflow. + let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; + if nsec < 0 { + nsec += NSEC_PER_SEC as i32; + secs = secs.checked_sub(1).expect("overflow when subtracting \ + duration from time"); + } + Timespec { + t: libc::timespec { + tv_sec: secs as libc::time_t, + tv_nsec: nsec as i32, + }, + } + } +} + +impl PartialEq for Timespec { + fn eq(&self, other: &Timespec) -> bool { + self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec + } +} + +impl Eq for Timespec {} + +impl PartialOrd for Timespec { + fn partial_cmp(&self, other: &Timespec) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Timespec { + fn cmp(&self, other: &Timespec) -> Ordering { + let me = (self.t.tv_sec, self.t.tv_nsec); + let other = (other.t.tv_sec, other.t.tv_nsec); + me.cmp(&other) + } +} + +#[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 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: 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 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 { + 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 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, + }) + } + } + + impl From 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 + } + } +} + +#[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 { + 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 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 + } +} -- cgit 1.4.1-3-g733a5 From a5de9bb591c9752d39c87339fd8f5ff49ea4b2da Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 28 Oct 2016 14:17:34 -0600 Subject: Remove unsafe libc layer --- src/libstd/fs.rs | 10 ++ src/libstd/sys/redox/ext/io.rs | 3 +- src/libstd/sys/redox/fd.rs | 32 ++--- src/libstd/sys/redox/fs.rs | 186 +++++++------------------- src/libstd/sys/redox/mod.rs | 39 +----- src/libstd/sys/redox/os.rs | 102 ++------------ src/libstd/sys/redox/pipe.rs | 6 +- src/libstd/sys/redox/process.rs | 137 ++++--------------- src/libstd/sys/redox/thread.rs | 29 ++-- src/libstd/sys/redox/time.rs | 286 ++++++++++------------------------------ 10 files changed, 193 insertions(+), 637 deletions(-) (limited to 'src/libstd/sys') 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 { + self.inner.path() + } } impl AsInner 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 { - 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) -> io::Result { @@ -50,12 +45,7 @@ impl FileDesc { } pub fn write(&self, buf: &[u8]) -> io::Result { - 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 { - 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 for FileDesc { - fn as_inner(&self) -> &c_int { &self.fd } +impl AsInner 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 for FileAttr { - fn as_inner(&self) -> &stat64 { &self.stat } +impl AsInner 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 { - let path = cstr(path)?; - File::open_c(&path, opts) - } - - pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result { - 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 { - 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 { @@ -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 { - 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 { @@ -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 { - Ok(CString::new(path.as_os_str().as_bytes())?) -} - -impl FromInner for File { - fn from_inner(fd: c_int) -> File { +impl FromInner 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 { - 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 { - // 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 { - // 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 { 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 { - unimplemented!(); +pub fn readlink(p: &Path) -> io::Result { + 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 { - 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 { - 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 { - unimplemented!(); +pub fn canonicalize(p: &Path) -> io::Result { + let options = OpenOptions::new(); + let file = File::open(p, &options)?; + file.path() } pub fn copy(from: &Path, to: &Path) -> io::Result { 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: T) -> io::Result { - if t.is_minus_one() { - Err(io::Error::last_os_error()) - } else { - Ok(t) - } -} - -pub fn cvt_r(mut f: F) -> io::Result - 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) -> io::Result { + 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 { - 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 { } 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, env: HashMap, - cwd: Option, + cwd: Option, uid: Option, gid: Option, 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 { + fn fd(&self) -> Option { 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::()); - 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 { - 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 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 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 { + 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 { - 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 for SystemTime { - fn from(t: libc::timespec) -> SystemTime { - SystemTime { t: Timespec { t: t } } - } +impl From 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 } -- cgit 1.4.1-3-g733a5 From b1b35dd1f20b011cb6807ee56c5829753351b977 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 29 Oct 2016 21:15:32 -0600 Subject: Implement env, reentrant mutex, and partially implement scoped thread locals. Better error messages for unsupported features --- src/libstd/sys/redox/condvar.rs | 16 +++++++- src/libstd/sys/redox/fd.rs | 2 + src/libstd/sys/redox/fs.rs | 4 ++ src/libstd/sys/redox/mutex.rs | 69 +++++++++++++++++++++++++++++----- src/libstd/sys/redox/os.rs | 45 ++++++++++++++++++---- src/libstd/sys/redox/pipe.rs | 1 + src/libstd/sys/redox/rwlock.rs | 24 +++++++----- src/libstd/sys/redox/stack_overflow.rs | 4 +- src/libstd/sys/redox/thread.rs | 10 +++-- src/libstd/sys/redox/thread_local.rs | 48 +++++++++++++++-------- 10 files changed, 174 insertions(+), 49 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/condvar.rs b/src/libstd/sys/redox/condvar.rs index 2a6685bc122..b5234be567d 100644 --- a/src/libstd/sys/redox/condvar.rs +++ b/src/libstd/sys/redox/condvar.rs @@ -20,11 +20,15 @@ impl Condvar { } } + #[inline] pub unsafe fn init(&self) { - + *self.lock.get() = ptr::null_mut(); + *self.seq.get() = 0; } + #[inline] pub fn notify_one(&self) { + ::sys_common::util::dumb_print(format_args!("condvar notify_one\n")); unsafe { let seq = self.seq.get(); @@ -34,7 +38,9 @@ impl Condvar { } } + #[inline] pub fn notify_all(&self) { + ::sys_common::util::dumb_print(format_args!("condvar notify_all\n")); unsafe { let lock = self.lock.get(); let seq = self.seq.get(); @@ -49,7 +55,9 @@ impl Condvar { } } + #[inline] pub fn wait(&self, mutex: &Mutex) { + ::sys_common::util::dumb_print(format_args!("condvar wait\n")); unsafe { let lock = self.lock.get(); let seq = self.seq.get(); @@ -74,12 +82,16 @@ impl Condvar { } } + #[inline] pub fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { + ::sys_common::util::dumb_print(format_args!("condvar wait_timeout\n")); unimplemented!(); } + #[inline] pub unsafe fn destroy(&self) { - + *self.lock.get() = ptr::null_mut(); + *self.seq.get() = 0; } } diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs index 4c4dae7cd41..4a3c0fdb37e 100644 --- a/src/libstd/sys/redox/fd.rs +++ b/src/libstd/sys/redox/fd.rs @@ -49,6 +49,7 @@ impl FileDesc { } pub fn set_cloexec(&self) -> io::Result<()> { + ::sys_common::util::dumb_print(format_args!("Set cloexec\n")); unimplemented!(); /* unsafe { @@ -60,6 +61,7 @@ impl FileDesc { } pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> { + ::sys_common::util::dumb_print(format_args!("Set nonblocking\n")); unimplemented!(); /* unsafe { diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index ca1a7963f8e..3779c4c6677 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -380,10 +380,12 @@ pub fn unlink(p: &Path) -> io::Result<()> { } pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { + ::sys_common::util::dumb_print(format_args!("Rename\n")); unimplemented!(); } pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { + ::sys_common::util::dumb_print(format_args!("Set perm\n")); unimplemented!(); } @@ -418,10 +420,12 @@ pub fn readlink(p: &Path) -> io::Result { } pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> { + ::sys_common::util::dumb_print(format_args!("Symlink\n")); unimplemented!(); } pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { + ::sys_common::util::dumb_print(format_args!("Link\n")); unimplemented!(); } diff --git a/src/libstd/sys/redox/mutex.rs b/src/libstd/sys/redox/mutex.rs index 5723443785a..aa808c2f8d4 100644 --- a/src/libstd/sys/redox/mutex.rs +++ b/src/libstd/sys/redox/mutex.rs @@ -2,7 +2,7 @@ use cell::UnsafeCell; use intrinsics::{atomic_cxchg, atomic_xchg}; use ptr; -use libc::{futex, FUTEX_WAIT, FUTEX_WAKE}; +use libc::{futex, getpid, FUTEX_WAIT, FUTEX_WAKE}; pub unsafe fn mutex_try_lock(m: *mut i32) -> bool { atomic_cxchg(m, 0, 1).0 == 0 @@ -57,27 +57,36 @@ impl Mutex { } } + #[inline] pub unsafe fn init(&self) { - + *self.lock.get() = 0; } /// Try to lock the mutex + #[inline] pub unsafe fn try_lock(&self) -> bool { + ::sys_common::util::dumb_print(format_args!("mutex try lock\n")); mutex_try_lock(self.lock.get()) } /// Lock the mutex + #[inline] pub unsafe fn lock(&self) { - mutex_lock(self.lock.get()); + ::sys_common::util::dumb_print(format_args!("mutex lock\n")); + mutex_try_lock(self.lock.get()); + //mutex_lock(self.lock.get()); } /// Unlock the mutex + #[inline] pub unsafe fn unlock(&self) { + ::sys_common::util::dumb_print(format_args!("mutex unlock\n")); mutex_unlock(self.lock.get()); } + #[inline] pub unsafe fn destroy(&self) { - + *self.lock.get() = 0; } } @@ -87,36 +96,78 @@ unsafe impl Sync for Mutex {} pub struct ReentrantMutex { pub lock: UnsafeCell, + pub owner: UnsafeCell, + pub own_count: UnsafeCell, } impl ReentrantMutex { pub const fn uninitialized() -> Self { ReentrantMutex { lock: UnsafeCell::new(0), + owner: UnsafeCell::new(0), + own_count: UnsafeCell::new(0), } } + #[inline] pub unsafe fn init(&mut self) { - + *self.lock.get() = 0; + *self.owner.get() = 0; + *self.own_count.get() = 0; } /// Try to lock the mutex + #[inline] pub unsafe fn try_lock(&self) -> bool { - mutex_try_lock(self.lock.get()) + ::sys_common::util::dumb_print(format_args!("remutex try_lock\n")); + let pid = getpid().unwrap(); + if *self.own_count.get() > 0 && *self.owner.get() == pid { + *self.own_count.get() += 1; + true + } else { + if mutex_try_lock(self.lock.get()) { + *self.owner.get() = pid; + *self.own_count.get() = 1; + true + } else { + false + } + } } /// Lock the mutex + #[inline] pub unsafe fn lock(&self) { - mutex_lock(self.lock.get()); + ::sys_common::util::dumb_print(format_args!("remutex lock\n")); + let pid = getpid().unwrap(); + if *self.own_count.get() > 0 && *self.owner.get() == pid { + *self.own_count.get() += 1; + } else { + mutex_lock(self.lock.get()); + *self.owner.get() = pid; + *self.own_count.get() = 1; + } } /// Unlock the mutex + #[inline] pub unsafe fn unlock(&self) { - mutex_unlock(self.lock.get()); + ::sys_common::util::dumb_print(format_args!("remutex unlock\n")); + let pid = getpid().unwrap(); + if *self.own_count.get() > 0 && *self.owner.get() == pid { + *self.own_count.get() -= 1; + if *self.own_count.get() == 0 { + *self.owner.get() = 0; + mutex_unlock(self.lock.get()); + } + } } + #[inline] pub unsafe fn destroy(&self) { - + *self.lock.get() = 0; + *self.owner.get() = 0; + *self.own_count.get() = 0; } } diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs index c2e419aeaaa..9524f2c28f9 100644 --- a/src/libstd/sys/redox/os.rs +++ b/src/libstd/sys/redox/os.rs @@ -17,7 +17,7 @@ use os::unix::prelude::*; use error::Error as StdError; use ffi::{CString, CStr, OsString, OsStr}; use fmt; -use io; +use io::{self, Read, Write}; use iter; use libc::{self, c_int, c_char, c_void}; use marker::PhantomData; @@ -131,19 +131,48 @@ impl Iterator for Env { /// Returns a vector of (variable, value) byte-vector pairs for all the /// environment variables of the current process. pub fn env() -> Env { - unimplemented!(); + let mut variables: Vec<(OsString, OsString)> = Vec::new(); + if let Ok(mut file) = ::fs::File::open("env:") { + let mut string = String::new(); + if file.read_to_string(&mut string).is_ok() { + for line in string.lines() { + if let Some(equal_sign) = line.chars().position(|c| c == '=') { + let name = line.chars().take(equal_sign).collect::(); + let value = line.chars().skip(equal_sign+1).collect::(); + variables.push((OsString::from(name), OsString::from(value))); + } + } + } + } + Env { iter: variables.into_iter(), _dont_send_or_sync_me: PhantomData } } -pub fn getenv(_k: &OsStr) -> io::Result> { - unimplemented!(); +pub fn getenv(key: &OsStr) -> io::Result> { + if ! key.is_empty() { + if let Ok(mut file) = ::fs::File::open(&("env:".to_owned() + key.to_str().unwrap())) { + let mut string = String::new(); + file.read_to_string(&mut string)?; + Ok(Some(OsString::from(string))) + } else { + Ok(None) + } + } else { + Ok(None) + } } -pub fn setenv(_k: &OsStr, _v: &OsStr) -> io::Result<()> { - unimplemented!(); +pub fn setenv(key: &OsStr, value: &OsStr) -> io::Result<()> { + if ! key.is_empty() { + let mut file = ::fs::File::open(&("env:".to_owned() + key.to_str().unwrap()))?; + file.write_all(value.as_bytes())?; + file.set_len(value.len() as u64)?; + } + Ok(()) } -pub fn unsetenv(_n: &OsStr) -> io::Result<()> { - unimplemented!(); +pub fn unsetenv(key: &OsStr) -> io::Result<()> { + ::fs::remove_file(&("env:".to_owned() + key.to_str().unwrap()))?; + Ok(()) } pub fn page_size() -> usize { diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs index 5902ba128e8..a25ca048942 100644 --- a/src/libstd/sys/redox/pipe.rs +++ b/src/libstd/sys/redox/pipe.rs @@ -54,6 +54,7 @@ pub fn read2(_p1: AnonPipe, _v1: &mut Vec, _p2: AnonPipe, _v2: &mut Vec) -> io::Result<()> { + ::sys_common::util::dumb_print(format_args!("read2\n")); unimplemented!(); /* // Set both pipes into nonblocking mode as we're gonna be reading from both diff --git a/src/libstd/sys/redox/rwlock.rs b/src/libstd/sys/redox/rwlock.rs index c2de1d50685..c752fa50ea9 100644 --- a/src/libstd/sys/redox/rwlock.rs +++ b/src/libstd/sys/redox/rwlock.rs @@ -8,48 +8,54 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub struct RWLock; +use super::mutex::Mutex; + +pub struct RWLock { + mutex: Mutex +} unsafe impl Send for RWLock {} unsafe impl Sync for RWLock {} impl RWLock { pub const fn new() -> RWLock { - RWLock + RWLock { + mutex: Mutex::new() + } } #[inline] pub unsafe fn read(&self) { - unimplemented!(); + self.mutex.lock(); } #[inline] pub unsafe fn try_read(&self) -> bool { - unimplemented!(); + self.mutex.try_lock() } #[inline] pub unsafe fn write(&self) { - unimplemented!(); + self.mutex.lock(); } #[inline] pub unsafe fn try_write(&self) -> bool { - unimplemented!(); + self.mutex.try_lock() } #[inline] pub unsafe fn read_unlock(&self) { - unimplemented!(); + self.mutex.unlock(); } #[inline] pub unsafe fn write_unlock(&self) { - unimplemented!(); + self.mutex.unlock(); } #[inline] pub unsafe fn destroy(&self) { - + self.mutex.destroy(); } } diff --git a/src/libstd/sys/redox/stack_overflow.rs b/src/libstd/sys/redox/stack_overflow.rs index c8595d38b21..92846bfe0c8 100644 --- a/src/libstd/sys/redox/stack_overflow.rs +++ b/src/libstd/sys/redox/stack_overflow.rs @@ -14,7 +14,7 @@ pub struct Handler; impl Handler { pub unsafe fn new() -> Handler { - unimplemented!(); + Handler } } @@ -23,5 +23,5 @@ pub unsafe fn init() { } pub unsafe fn cleanup() { - unimplemented!(); + } diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index 616da662d9a..b6685f14ec7 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -32,6 +32,8 @@ impl Thread { start_thread(&*p as *const _ as *mut _); + ::sys_common::util::dumb_print(format_args!("thread\n")); + unimplemented!(); } @@ -41,7 +43,7 @@ impl Thread { } pub fn set_name(_name: &CStr) { - unimplemented!(); + } pub fn sleep(dur: Duration) { @@ -67,7 +69,8 @@ impl Thread { } pub fn join(self) { - panic!(); + ::sys_common::util::dumb_print(format_args!("Thread::join")); + unimplemented!(); } pub fn id(&self) -> libc::pid_t { self.id } @@ -81,7 +84,8 @@ impl Thread { impl Drop for Thread { fn drop(&mut self) { - panic!(); + ::sys_common::util::dumb_print(format_args!("Thread::drop")); + unimplemented!(); } } diff --git a/src/libstd/sys/redox/thread_local.rs b/src/libstd/sys/redox/thread_local.rs index 2639ef013de..b12ffebbcac 100644 --- a/src/libstd/sys/redox/thread_local.rs +++ b/src/libstd/sys/redox/thread_local.rs @@ -10,32 +10,48 @@ #![allow(dead_code)] // not used on all platforms +use collections::BTreeMap; +use ptr; + pub type Key = usize; +type Dtor = unsafe extern fn(*mut u8); + +//TODO: Implement this properly + +static mut NEXT_KEY: Key = 0; + +static mut LOCALS: *mut BTreeMap)> = ptr::null_mut(); + +unsafe fn locals() -> &'static mut BTreeMap)> { + if LOCALS == ptr::null_mut() { + LOCALS = Box::into_raw(Box::new(BTreeMap::new())); + } + &mut *LOCALS +} + #[inline] -pub unsafe fn create(_dtor: Option) -> Key { - panic!("pthread key create not supported"); - //let mut key = 0; - //assert_eq!(libc::pthread_key_create(&mut key, mem::transmute(dtor)), 0); - //key +pub unsafe fn create(dtor: Option) -> Key { + let key = NEXT_KEY; + NEXT_KEY += 1; + locals().insert(key, (0 as *mut u8, dtor)); + key } #[inline] -pub unsafe fn set(_key: Key, _value: *mut u8) { - panic!("pthread key set not supported"); - //let r = libc::pthread_setspecific(key, value as *mut _); - //debug_assert_eq!(r, 0); +pub unsafe fn set(key: Key, value: *mut u8) { + locals().get_mut(&key).unwrap().0 = value; } #[inline] -pub unsafe fn get(_key: Key) -> *mut u8 { - panic!("pthread key get not supported"); - //libc::pthread_getspecific(key) as *mut u8 +pub unsafe fn get(key: Key) -> *mut u8 { + locals()[&key].0 } #[inline] -pub unsafe fn destroy(_key: Key) { - panic!("pthread key destroy not supported"); - //let r = libc::pthread_key_delete(key); - //debug_assert_eq!(r, 0); +pub unsafe fn destroy(key: Key) { + let (value, dtor) = locals().remove(&key).unwrap(); + if let Some(dtor_fn) = dtor { + dtor_fn(value); + } } -- cgit 1.4.1-3-g733a5 From ea6f5aa1b19655035475c7155441f658eeccdc5a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 29 Oct 2016 21:46:49 -0600 Subject: Implement rand and args, cleanup other modules --- src/libstd/sys/redox/args.rs | 14 +++++++++----- src/libstd/sys/redox/condvar.rs | 3 --- src/libstd/sys/redox/fd.rs | 26 ++++---------------------- src/libstd/sys/redox/mutex.rs | 9 +-------- src/libstd/sys/redox/os.rs | 2 +- src/libstd/sys/redox/process.rs | 23 +---------------------- src/libstd/sys/redox/rand.rs | 26 +++++++++++++------------- 7 files changed, 29 insertions(+), 74 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/args.rs b/src/libstd/sys/redox/args.rs index 91233645989..52ba030e7c6 100644 --- a/src/libstd/sys/redox/args.rs +++ b/src/libstd/sys/redox/args.rs @@ -52,9 +52,10 @@ impl DoubleEndedIterator for Args { mod imp { use os::unix::prelude::*; use mem; - use ffi::{CStr, OsString}; + use ffi::OsString; use marker::PhantomData; - use libc; + use slice; + use str; use super::Args; use sys_common::mutex::Mutex; @@ -63,9 +64,12 @@ mod imp { static LOCK: Mutex = Mutex::new(); pub unsafe fn init(argc: isize, argv: *const *const u8) { - let args = (0..argc).map(|i| { - CStr::from_ptr(*argv.offset(i) as *const libc::c_char).to_bytes().to_vec() - }).collect(); + let mut args: Vec> = Vec::new(); + for i in 0..argc { + let len = *(argv.offset(i * 2)) as usize; + let ptr = *(argv.offset(i * 2 + 1)); + args.push(slice::from_raw_parts(ptr, len).to_vec()); + } LOCK.lock(); let ptr = get_global_ptr(); diff --git a/src/libstd/sys/redox/condvar.rs b/src/libstd/sys/redox/condvar.rs index b5234be567d..f6c8fec545b 100644 --- a/src/libstd/sys/redox/condvar.rs +++ b/src/libstd/sys/redox/condvar.rs @@ -28,7 +28,6 @@ impl Condvar { #[inline] pub fn notify_one(&self) { - ::sys_common::util::dumb_print(format_args!("condvar notify_one\n")); unsafe { let seq = self.seq.get(); @@ -40,7 +39,6 @@ impl Condvar { #[inline] pub fn notify_all(&self) { - ::sys_common::util::dumb_print(format_args!("condvar notify_all\n")); unsafe { let lock = self.lock.get(); let seq = self.seq.get(); @@ -57,7 +55,6 @@ impl Condvar { #[inline] pub fn wait(&self, mutex: &Mutex) { - ::sys_common::util::dumb_print(format_args!("condvar wait\n")); unsafe { let lock = self.lock.get(); let seq = self.seq.get(); diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs index 4a3c0fdb37e..9c50c547965 100644 --- a/src/libstd/sys/redox/fd.rs +++ b/src/libstd/sys/redox/fd.rs @@ -49,32 +49,14 @@ impl FileDesc { } pub fn set_cloexec(&self) -> io::Result<()> { - ::sys_common::util::dumb_print(format_args!("Set cloexec\n")); - unimplemented!(); - /* - unsafe { - let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD, 0))?; - cvt(libc::fcntl(self.fd, libc::F_SETFD, previous | libc::FD_CLOEXEC))?; - Ok(()) - } - */ + ::sys_common::util::dumb_print(format_args!("{}: set cloexec\n", self.fd)); + //unimplemented!(); + Ok(()) } pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> { - ::sys_common::util::dumb_print(format_args!("Set nonblocking\n")); + ::sys_common::util::dumb_print(format_args!("{}: set nonblocking\n", self.fd)); unimplemented!(); - /* - unsafe { - let previous = cvt(libc::fcntl(self.fd, libc::F_GETFL, 0))?; - let new = if nonblocking { - previous | libc::O_NONBLOCK - } else { - previous & !libc::O_NONBLOCK - }; - cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?; - Ok(()) - } - */ } pub fn duplicate(&self) -> io::Result { diff --git a/src/libstd/sys/redox/mutex.rs b/src/libstd/sys/redox/mutex.rs index aa808c2f8d4..4c2b0de8bd9 100644 --- a/src/libstd/sys/redox/mutex.rs +++ b/src/libstd/sys/redox/mutex.rs @@ -65,22 +65,18 @@ impl Mutex { /// Try to lock the mutex #[inline] pub unsafe fn try_lock(&self) -> bool { - ::sys_common::util::dumb_print(format_args!("mutex try lock\n")); mutex_try_lock(self.lock.get()) } /// Lock the mutex #[inline] pub unsafe fn lock(&self) { - ::sys_common::util::dumb_print(format_args!("mutex lock\n")); - mutex_try_lock(self.lock.get()); - //mutex_lock(self.lock.get()); + mutex_lock(self.lock.get()); } /// Unlock the mutex #[inline] pub unsafe fn unlock(&self) { - ::sys_common::util::dumb_print(format_args!("mutex unlock\n")); mutex_unlock(self.lock.get()); } @@ -119,7 +115,6 @@ impl ReentrantMutex { /// Try to lock the mutex #[inline] pub unsafe fn try_lock(&self) -> bool { - ::sys_common::util::dumb_print(format_args!("remutex try_lock\n")); let pid = getpid().unwrap(); if *self.own_count.get() > 0 && *self.owner.get() == pid { *self.own_count.get() += 1; @@ -138,7 +133,6 @@ impl ReentrantMutex { /// Lock the mutex #[inline] pub unsafe fn lock(&self) { - ::sys_common::util::dumb_print(format_args!("remutex lock\n")); let pid = getpid().unwrap(); if *self.own_count.get() > 0 && *self.owner.get() == pid { *self.own_count.get() += 1; @@ -152,7 +146,6 @@ impl ReentrantMutex { /// Unlock the mutex #[inline] pub unsafe fn unlock(&self) { - ::sys_common::util::dumb_print(format_args!("remutex unlock\n")); let pid = getpid().unwrap(); if *self.own_count.get() > 0 && *self.owner.get() == pid { *self.own_count.get() -= 1; diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs index 9524f2c28f9..309201352c4 100644 --- a/src/libstd/sys/redox/os.rs +++ b/src/libstd/sys/redox/os.rs @@ -15,7 +15,7 @@ use os::unix::prelude::*; use error::Error as StdError; -use ffi::{CString, CStr, OsString, OsStr}; +use ffi::{OsString, OsStr}; use fmt; use io::{self, Read, Write}; use iter; diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 921e3f056da..b6968f285d7 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -8,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use os::unix::prelude::*; - use collections::hash_map::HashMap; use env; -use ffi::{OsStr, CString}; +use ffi::OsStr; use fmt; use io::{self, Error, ErrorKind}; use libc::{self, pid_t, c_int, gid_t, uid_t}; @@ -344,13 +342,6 @@ impl Command { } } -fn os2c(s: &OsStr, saw_nul: &mut bool) -> CString { - CString::new(s.as_bytes()).unwrap_or_else(|_e| { - *saw_nul = true; - CString::new("").unwrap() - }) -} - impl Stdio { fn to_child_stdio(&self, readable: bool) -> io::Result<(ChildStdio, Option)> { @@ -403,18 +394,6 @@ impl ChildStdio { } } -fn pair_to_key(key: &OsStr, value: &OsStr, saw_nul: &mut bool) -> CString { - let (key, value) = (key.as_bytes(), value.as_bytes()); - let mut v = Vec::with_capacity(key.len() + value.len() + 1); - v.extend(key); - v.push(b'='); - v.extend(value); - CString::new(v).unwrap_or_else(|_e| { - *saw_nul = true; - CString::new("foo=bar").unwrap() - }) -} - impl fmt::Debug for Command { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", self.program)?; diff --git a/src/libstd/sys/redox/rand.rs b/src/libstd/sys/redox/rand.rs index 6ea9a3fb105..7d2df6bf957 100644 --- a/src/libstd/sys/redox/rand.rs +++ b/src/libstd/sys/redox/rand.rs @@ -8,33 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use fs::File; use io; +use libc; use rand::Rng; -use rand::reader::ReaderRng; -pub struct OsRng { - inner: ReaderRng, -} +pub struct OsRng; impl OsRng { /// Create a new `OsRng`. pub fn new() -> io::Result { - let reader = File::open("rand:")?; - let reader_rng = ReaderRng::new(reader); - - Ok(OsRng { inner: reader_rng }) + Ok(OsRng) } } impl Rng for OsRng { fn next_u32(&mut self) -> u32 { - self.inner.next_u32() + self.next_u64() as u32 } fn next_u64(&mut self) -> u64 { - self.inner.next_u64() + unsafe { libc::random() } } - fn fill_bytes(&mut self, v: &mut [u8]) { - self.inner.fill_bytes(v) + fn fill_bytes(&mut self, buf: &mut [u8]) { + for chunk in buf.chunks_mut(8) { + let mut rand: u64 = self.next_u64(); + for b in chunk.iter_mut() { + *b = rand as u8; + rand = rand >> 8; + } + } } } -- cgit 1.4.1-3-g733a5 From 37bfef023dab045852ea577dbe40693147a810f5 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 30 Oct 2016 09:36:04 -0600 Subject: Implement thread --- src/libstd/sys/redox/thread.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index b6685f14ec7..46bc6346a6a 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -15,6 +15,7 @@ use io; use libc; use mem; use sys_common::thread::start_thread; +use sys::cvt; use time::Duration; pub struct Thread { @@ -30,11 +31,15 @@ impl Thread { pub unsafe fn new<'a>(_stack: usize, p: Box) -> io::Result { let p = box p; - start_thread(&*p as *const _ as *mut _); - - ::sys_common::util::dumb_print(format_args!("thread\n")); - - unimplemented!(); + let id = cvt(libc::clone(libc::CLONE_VM | libc::CLONE_FS | libc::CLONE_FILES))?; + if id == 0 { + start_thread(&*p as *const _ as *mut _); + let _ = libc::exit(0); + panic!("thread failed to exit"); + } else { + mem::forget(p); + Ok(Thread { id: id }) + } } pub fn yield_now() { @@ -69,8 +74,8 @@ impl Thread { } pub fn join(self) { - ::sys_common::util::dumb_print(format_args!("Thread::join")); - unimplemented!(); + let mut status = 0; + libc::waitpid(self.id, &mut status, 0).unwrap(); } pub fn id(&self) -> libc::pid_t { self.id } @@ -82,13 +87,6 @@ impl Thread { } } -impl Drop for Thread { - fn drop(&mut self) { - ::sys_common::util::dumb_print(format_args!("Thread::drop")); - unimplemented!(); - } -} - pub mod guard { pub unsafe fn current() -> Option { None } pub unsafe fn init() -> Option { None } -- cgit 1.4.1-3-g733a5 From 4edcddfb618a6d684d1f3289706ecc7794b30278 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 30 Oct 2016 16:14:47 -0600 Subject: Implement TLS scoped keys, compiler builtins --- src/libstd/lib.rs | 2 +- src/libstd/sys/redox/thread_local.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 219f244be29..82a719693ec 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -322,7 +322,7 @@ extern crate unwind; extern crate alloc_system; // compiler-rt intrinsics -//REDOX TODO extern crate compiler_builtins; +extern crate compiler_builtins; // Make std testable by not duplicating lang items and other globals. See #2912 #[cfg(test)] extern crate std as realstd; diff --git a/src/libstd/sys/redox/thread_local.rs b/src/libstd/sys/redox/thread_local.rs index b12ffebbcac..7958437a30a 100644 --- a/src/libstd/sys/redox/thread_local.rs +++ b/src/libstd/sys/redox/thread_local.rs @@ -17,10 +17,10 @@ pub type Key = usize; type Dtor = unsafe extern fn(*mut u8); -//TODO: Implement this properly - +#[thread_local] static mut NEXT_KEY: Key = 0; +#[thread_local] static mut LOCALS: *mut BTreeMap)> = ptr::null_mut(); unsafe fn locals() -> &'static mut BTreeMap)> { -- cgit 1.4.1-3-g733a5 From c77979b419959dda0d628ffb4af15c5f2a9e8648 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 30 Oct 2016 18:35:19 -0600 Subject: Fix for thread locals --- src/libstd/sys/redox/thread_local.rs | 39 ++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 15 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/thread_local.rs b/src/libstd/sys/redox/thread_local.rs index 7958437a30a..43b0bf09a6f 100644 --- a/src/libstd/sys/redox/thread_local.rs +++ b/src/libstd/sys/redox/thread_local.rs @@ -12,18 +12,27 @@ use collections::BTreeMap; use ptr; +use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; pub type Key = usize; type Dtor = unsafe extern fn(*mut u8); -#[thread_local] -static mut NEXT_KEY: Key = 0; +static NEXT_KEY: AtomicUsize = ATOMIC_USIZE_INIT; + +static mut KEYS: *mut BTreeMap> = ptr::null_mut(); #[thread_local] -static mut LOCALS: *mut BTreeMap)> = ptr::null_mut(); +static mut LOCALS: *mut BTreeMap = ptr::null_mut(); + +unsafe fn keys() -> &'static mut BTreeMap> { + if KEYS == ptr::null_mut() { + KEYS = Box::into_raw(Box::new(BTreeMap::new())); + } + &mut *KEYS +} -unsafe fn locals() -> &'static mut BTreeMap)> { +unsafe fn locals() -> &'static mut BTreeMap { if LOCALS == ptr::null_mut() { LOCALS = Box::into_raw(Box::new(BTreeMap::new())); } @@ -32,26 +41,26 @@ unsafe fn locals() -> &'static mut BTreeMap)> { #[inline] pub unsafe fn create(dtor: Option) -> Key { - let key = NEXT_KEY; - NEXT_KEY += 1; - locals().insert(key, (0 as *mut u8, dtor)); + let key = NEXT_KEY.fetch_add(1, Ordering::SeqCst); + keys().insert(key, dtor); key } #[inline] -pub unsafe fn set(key: Key, value: *mut u8) { - locals().get_mut(&key).unwrap().0 = value; +pub unsafe fn get(key: Key) -> *mut u8 { + if let Some(&entry) = locals().get(&key) { + entry + } else { + ptr::null_mut() + } } #[inline] -pub unsafe fn get(key: Key) -> *mut u8 { - locals()[&key].0 +pub unsafe fn set(key: Key, value: *mut u8) { + locals().insert(key, value); } #[inline] pub unsafe fn destroy(key: Key) { - let (value, dtor) = locals().remove(&key).unwrap(); - if let Some(dtor_fn) = dtor { - dtor_fn(value); - } + keys().remove(&key); } -- cgit 1.4.1-3-g733a5 From 01e837807095e99d68ecf9c0b38527288281dd02 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 3 Nov 2016 08:58:01 -0600 Subject: Update to new sys requirements --- src/libstd/sys/redox/fast_thread_local.rs | 116 ++++++++++++++++++++++++++++++ src/libstd/sys/redox/mod.rs | 6 ++ src/libstd/sys/redox/stdio.rs | 1 + 3 files changed, 123 insertions(+) create mode 100644 src/libstd/sys/redox/fast_thread_local.rs (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs new file mode 100644 index 00000000000..e0a17730846 --- /dev/null +++ b/src/libstd/sys/redox/fast_thread_local.rs @@ -0,0 +1,116 @@ +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg(target_thread_local)] +#![unstable(feature = "thread_local_internals", issue = "0")] + +use cell::{Cell, UnsafeCell}; +use intrinsics; +use ptr; + +pub struct Key { + inner: UnsafeCell>, + + // Metadata to keep track of the state of the destructor. Remember that + // these variables are thread-local, not global. + dtor_registered: Cell, + dtor_running: Cell, +} + +unsafe impl ::marker::Sync for Key { } + +impl Key { + pub const fn new() -> Key { + Key { + inner: UnsafeCell::new(None), + dtor_registered: Cell::new(false), + dtor_running: Cell::new(false) + } + } + + pub fn get(&'static self) -> Option<&'static UnsafeCell>> { + unsafe { + if intrinsics::needs_drop::() && self.dtor_running.get() { + return None + } + self.register_dtor(); + } + Some(&self.inner) + } + + unsafe fn register_dtor(&self) { + if !intrinsics::needs_drop::() || self.dtor_registered.get() { + return + } + + register_dtor(self as *const _ as *mut u8, + destroy_value::); + self.dtor_registered.set(true); + } +} + +unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { + // The fallback implementation uses a vanilla OS-based TLS key to track + // the list of destructors that need to be run for this thread. The key + // then has its own destructor which runs all the other destructors. + // + // The destructor for DTORS is a little special in that it has a `while` + // loop to continuously drain the list of registered destructors. It + // *should* be the case that this loop always terminates because we + // provide the guarantee that a TLS key cannot be set after it is + // flagged for destruction. + use sys_common::thread_local as os; + + static DTORS: os::StaticKey = os::StaticKey::new(Some(run_dtors)); + type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>; + if DTORS.get().is_null() { + let v: Box = box Vec::new(); + DTORS.set(Box::into_raw(v) as *mut u8); + } + let list: &mut List = &mut *(DTORS.get() as *mut List); + list.push((t, dtor)); + + unsafe extern fn run_dtors(mut ptr: *mut u8) { + while !ptr.is_null() { + let list: Box = Box::from_raw(ptr as *mut List); + for &(ptr, dtor) in list.iter() { + dtor(ptr); + } + ptr = DTORS.get(); + DTORS.set(ptr::null_mut()); + } + } +} + +pub unsafe extern fn destroy_value(ptr: *mut u8) { + let ptr = ptr as *mut Key; + // Right before we run the user destructor be sure to flag the + // destructor as running for this thread so calls to `get` will return + // `None`. + (*ptr).dtor_running.set(true); + + // The OSX implementation of TLS apparently had an odd aspect to it + // where the pointer we have may be overwritten while this destructor + // is running. Specifically if a TLS destructor re-accesses TLS it may + // trigger a re-initialization of all TLS variables, paving over at + // least some destroyed ones with initial values. + // + // This means that if we drop a TLS value in place on OSX that we could + // revert the value to its original state halfway through the + // destructor, which would be bad! + // + // Hence, we use `ptr::read` on OSX (to move to a "safe" location) + // instead of drop_in_place. + if cfg!(target_os = "macos") { + ptr::read((*ptr).inner.get()); + } else { + ptr::drop_in_place((*ptr).inner.get()); + } +} diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index f7465d01fad..3f3d8f2c4f4 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -8,6 +8,7 @@ pub mod backtrace; pub mod condvar; pub mod env; pub mod ext; +pub mod fast_thread_local; pub mod fd; pub mod fs; pub mod memchr; @@ -76,3 +77,8 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { pub fn cvt(result: Result) -> io::Result { result.map_err(|err| io::Error::from_raw_os_error(err.errno as i32)) } + +/// On Redox, use an illegal instruction to abort +pub unsafe fn abort_internal() -> ! { + ::core::intrinsics::abort(); +} diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs index 0ed9de36c73..f0a781b4383 100644 --- a/src/libstd/sys/redox/stdio.rs +++ b/src/libstd/sys/redox/stdio.rs @@ -67,3 +67,4 @@ impl io::Write for Stderr { } pub const EBADF_ERR: i32 = ::libc::EBADF; +pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; -- cgit 1.4.1-3-g733a5 From ced32a08f3bf7325bf3fe6488e21b108f996abc5 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 9 Nov 2016 20:52:30 -0700 Subject: Fix exec --- src/libstd/sys/redox/process.rs | 66 +++++++---------------------------------- 1 file changed, 10 insertions(+), 56 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index b6968f285d7..ad50d1de283 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -18,7 +18,7 @@ use path::Path; use sys::fd::FileDesc; use sys::fs::{File, OpenOptions}; use sys::pipe::{self, AnonPipe}; -use sys::{self, cvt}; +use sys::cvt; //////////////////////////////////////////////////////////////////////////////// // Command @@ -145,78 +145,32 @@ impl Command { pub fn spawn(&mut self, default: Stdio, needs_stdin: bool) -> io::Result<(Process, StdioPipes)> { - const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX"; - if self.saw_nul { return Err(io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data")); } let (ours, theirs) = self.setup_io(default, needs_stdin)?; - let (input, output) = sys::pipe::anon_pipe()?; let pid = unsafe { - match cvt(libc::clone(0))? { + match cvt(libc::clone(libc::CLONE_VFORK))? { 0 => { - drop(input); let err = self.do_exec(theirs); - let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32; - let bytes = [ - (errno >> 24) as u8, - (errno >> 16) as u8, - (errno >> 8) as u8, - (errno >> 0) as u8, - CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1], - CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3] - ]; - // pipe I/O up to PIPE_BUF bytes should be atomic, and then - // 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()); - let _ = libc::exit(1); + let _ = libc::exit((-err.raw_os_error().unwrap_or(libc::EINVAL)) as usize); unreachable!(); } n => n as pid_t, } }; - let mut p = Process { pid: pid, status: None }; - drop(output); - let mut bytes = [0; 8]; - - // loop to handle EINTR - loop { - match input.read(&mut bytes) { - Ok(0) => return Ok((p, ours)), - Ok(8) => { - assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]), - "Validation on the CLOEXEC pipe failed: {:?}", bytes); - let errno = combine(&bytes[0.. 4]); - assert!(p.wait().is_ok(), - "wait() should either return Ok or panic"); - return Err(Error::from_raw_os_error(errno)) - } - Err(ref e) if e.kind() == ErrorKind::Interrupted => {} - Err(e) => { - assert!(p.wait().is_ok(), - "wait() should either return Ok or panic"); - panic!("the CLOEXEC pipe failed: {:?}", e) - }, - Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic - assert!(p.wait().is_ok(), - "wait() should either return Ok or panic"); - panic!("short read on the CLOEXEC pipe") - } + let mut status_mux = 0; + if cvt(libc::waitpid(pid, &mut status_mux, libc::WNOHANG))? == pid { + match libc::Error::demux(status_mux) { + Ok(status) => Ok((Process { pid: pid, status: Some(ExitStatus::from(status as c_int)) }, ours)), + Err(err) => Err(io::Error::from_raw_os_error(err.errno)), } - } - - fn combine(arr: &[u8]) -> i32 { - let a = arr[0] as u32; - let b = arr[1] as u32; - let c = arr[2] as u32; - let d = arr[3] as u32; - - ((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32 + } else { + Ok((Process { pid: pid, status: None }, ours)) } } -- cgit 1.4.1-3-g733a5 From a90850995f9f177c910ba548f1a6312353673926 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 10 Nov 2016 19:33:59 -0700 Subject: Fixes for stdio and processes on Redox --- src/libpanic_abort/lib.rs | 4 ++-- src/libpanic_unwind/lib.rs | 1 + src/libstd/io/stdio.rs | 6 ++++++ src/libstd/sys/redox/fd.rs | 3 +-- src/libstd/sys/redox/process.rs | 16 +++++++++++++++- src/libstd/sys/redox/stdio.rs | 14 +++++++++++++- 6 files changed, 38 insertions(+), 6 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index b87160dd75d..26bc46931bd 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -28,7 +28,7 @@ #![panic_runtime] #![feature(panic_runtime)] #![cfg_attr(unix, feature(libc))] -#![cfg_attr(windows, feature(core_intrinsics))] +#![cfg_attr(any(target_os = "redox", windows), feature(core_intrinsics))] // Rust's "try" function, but if we're aborting on panics we just call the // function as there's nothing else we need to do here. @@ -61,7 +61,7 @@ pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 { libc::abort(); } - #[cfg(windows)] + #[cfg(any(target_os = "redox", windows))] unsafe fn abort() -> ! { core::intrinsics::abort(); } diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index ff483fa823e..b75d9ec6520 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -69,6 +69,7 @@ mod imp; // i686-pc-windows-gnu and all others #[cfg(any(all(unix, not(target_os = "emscripten")), + target_os = "redox", all(windows, target_arch = "x86", target_env = "gnu")))] #[path = "gcc.rs"] mod imp; diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 1777b79ea1b..27bc5f0890c 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -81,11 +81,17 @@ impl Read for StdinRaw { } impl Write for StdoutRaw { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } + #[cfg(not(target_os = "redox"))] fn flush(&mut self) -> io::Result<()> { Ok(()) } + #[cfg(target_os = "redox")] + fn flush(&mut self) -> io::Result<()> { self.0.flush() } } impl Write for StderrRaw { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } + #[cfg(not(target_os = "redox"))] fn flush(&mut self) -> io::Result<()> { Ok(()) } + #[cfg(target_os = "redox")] + fn flush(&mut self) -> io::Result<()> { self.0.flush() } } enum Maybe { diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs index 9c50c547965..786d7676612 100644 --- a/src/libstd/sys/redox/fd.rs +++ b/src/libstd/sys/redox/fd.rs @@ -50,8 +50,7 @@ impl FileDesc { pub fn set_cloexec(&self) -> io::Result<()> { ::sys_common::util::dumb_print(format_args!("{}: set cloexec\n", self.fd)); - //unimplemented!(); - Ok(()) + unimplemented!(); } pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> { diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index ad50d1de283..934cf20bf07 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -264,7 +264,21 @@ impl Command { env::set_var(key, val); } - if let Err(err) = libc::exec(&self.program, &args) { + let program = if self.program.contains(':') || self.program.contains('/') { + self.program.to_owned() + } else { + let mut path_env = ::env::var("PATH").unwrap_or(".".to_string()); + + if ! path_env.ends_with('/') { + path_env.push('/'); + } + + path_env.push_str(&self.program); + + path_env + }; + + if let Err(err) = libc::exec(&program, &args) { io::Error::from_raw_os_error(err.errno as i32) } else { panic!("return from exec without err"); diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs index f0a781b4383..50062186903 100644 --- a/src/libstd/sys/redox/stdio.rs +++ b/src/libstd/sys/redox/stdio.rs @@ -10,6 +10,7 @@ use io; use libc; +use sys::cvt; use sys::fd::FileDesc; pub struct Stdin(()); @@ -43,6 +44,10 @@ impl Stdout { fd.into_raw(); ret } + + pub fn flush(&self) -> io::Result<()> { + cvt(libc::fsync(libc::STDOUT_FILENO)).and(Ok(())) + } } impl Stderr { @@ -54,6 +59,10 @@ impl Stderr { fd.into_raw(); ret } + + pub fn flush(&self) -> io::Result<()> { + cvt(libc::fsync(libc::STDERR_FILENO)).and(Ok(())) + } } // FIXME: right now this raw stderr handle is used in a few places because @@ -63,7 +72,10 @@ impl io::Write for Stderr { fn write(&mut self, data: &[u8]) -> io::Result { Stderr::write(self, data) } - fn flush(&mut self) -> io::Result<()> { Ok(()) } + + fn flush(&mut self) -> io::Result<()> { + cvt(libc::fsync(libc::STDERR_FILENO)).and(Ok(())) + } } pub const EBADF_ERR: i32 = ::libc::EBADF; -- cgit 1.4.1-3-g733a5 From 79a8c272fb8ad09600ef58ff223c73eb44343040 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 10 Nov 2016 19:58:19 -0700 Subject: Fix readdir --- src/libstd/sys/redox/fs.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index 3779c4c6677..1a96ac2f2ea 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -146,16 +146,17 @@ impl Iterator for ReadDir { fn next(&mut self) -> Option> { loop { let start = self.i; - while self.i < self.data.len() { - let i = self.i; + let mut i = self.i; + while i < self.data.len() { self.i += 1; if self.data[i] == b'\n' { break; } + i += 1; } if start < self.i { let ret = DirEntry { - name: self.data[start .. self.i].to_owned().into_boxed_slice(), + name: self.data[start .. i].to_owned().into_boxed_slice(), root: self.root.clone() }; if ret.name_bytes() != b"." && ret.name_bytes() != b".." { @@ -182,7 +183,7 @@ impl DirEntry { } pub fn file_type(&self) -> io::Result { - stat(&self.path()).map(|m| m.file_type()) + lstat(&self.path()).map(|m| m.file_type()) } fn name_bytes(&self) -> &[u8] { @@ -367,7 +368,8 @@ impl fmt::Debug for File { pub fn readdir(p: &Path) -> io::Result { let root = Arc::new(p.to_path_buf()); - let options = OpenOptions::new(); + let mut options = OpenOptions::new(); + options.read(true); let fd = File::open(p, &options)?; let mut data = Vec::new(); fd.read_to_end(&mut data)?; @@ -431,7 +433,8 @@ pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { pub fn stat(p: &Path) -> io::Result { let mut stat: stat = stat::default(); - let options = OpenOptions::new(); + let mut options = OpenOptions::new(); + options.read(true); let file = File::open(p, &options)?; cvt(fstat(file.0.raw(), &mut stat))?; Ok(FileAttr { stat: stat }) @@ -442,7 +445,8 @@ pub fn lstat(p: &Path) -> io::Result { } pub fn canonicalize(p: &Path) -> io::Result { - let options = OpenOptions::new(); + let mut options = OpenOptions::new(); + options.read(true); let file = File::open(p, &options)?; file.path() } -- cgit 1.4.1-3-g733a5 From 25e1a4a0084a56807d7a1e4ca676e078c085b3aa Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 10 Nov 2016 20:13:14 -0700 Subject: Use target_os = redox for cfg --- src/libstd/fs.rs | 2 +- src/libstd/os/mod.rs | 5 +---- src/libstd/sys/mod.rs | 2 +- src/libstd/sys_common/mod.rs | 4 ++-- 4 files changed, 5 insertions(+), 8 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 5845963d31a..3fc1267c06e 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -353,7 +353,7 @@ impl File { /// /// This function is only implemented on Redox, but could be /// implemented on other operating systems using readlink - #[cfg(redox)] + #[cfg(target_os = "redox")] #[stable(feature = "rust1", since = "1.14.0")] pub fn path(&self) -> io::Result { self.inner.path() diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index 744ee6c22e5..58f1604de1c 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -13,10 +13,7 @@ #![stable(feature = "os", since = "1.0.0")] #![allow(missing_docs, bad_style)] -#[cfg(redox)] -#[stable(feature = "rust1", since = "1.0.0")] -pub use sys::ext as unix; -#[cfg(unix)] +#[cfg(any(target_os = "redox", unix))] #[stable(feature = "rust1", since = "1.0.0")] pub use sys::ext as unix; #[cfg(windows)] diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index c196bf39432..a237d8a067e 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -32,7 +32,7 @@ pub use self::imp::*; -#[cfg(redox)] +#[cfg(target_os = "redox")] #[path = "redox/mod.rs"] mod imp; diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index bbd2f679bca..5f5ea09c78d 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -43,10 +43,10 @@ pub mod thread_local; pub mod util; pub mod wtf8; -#[cfg(redox)] +#[cfg(target_os = "redox")] pub use sys::net; -#[cfg(not(redox))] +#[cfg(not(target_os = "redox"))] pub mod net; #[cfg(any(not(cargobuild), feature = "backtrace"))] -- cgit 1.4.1-3-g733a5 From a0b5dfef2a36a15f76476a9d6bb7184a701d0d3c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 14 Nov 2016 12:15:11 -0700 Subject: Add fcntl --- src/libstd/sys/redox/fd.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs index 786d7676612..47d2280fe05 100644 --- a/src/libstd/sys/redox/fd.rs +++ b/src/libstd/sys/redox/fd.rs @@ -49,13 +49,19 @@ impl FileDesc { } pub fn set_cloexec(&self) -> io::Result<()> { - ::sys_common::util::dumb_print(format_args!("{}: set cloexec\n", self.fd)); - unimplemented!(); + let mut flags = cvt(libc::fcntl(self.fd, libc::F_GETFL, 0))?; + flags |= libc::O_CLOEXEC; + cvt(libc::fcntl(self.fd, libc::F_SETFL, flags)).and(Ok(())) } - pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> { - ::sys_common::util::dumb_print(format_args!("{}: set nonblocking\n", self.fd)); - unimplemented!(); + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + let mut flags = cvt(libc::fcntl(self.fd, libc::F_GETFL, 0))?; + if nonblocking { + flags |= libc::O_NONBLOCK; + } else { + flags &= !libc::O_NONBLOCK; + } + cvt(libc::fcntl(self.fd, libc::F_SETFL, flags)).and(Ok(())) } pub fn duplicate(&self) -> io::Result { -- cgit 1.4.1-3-g733a5 From 18bf0540bf8a04a5724dd515fec2311d1e4768e4 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 14 Nov 2016 15:02:18 -0700 Subject: Fix redox prefix handling --- src/libstd/path.rs | 9 ++++++++- src/libstd/sys/redox/path.rs | 12 ++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/path.rs b/src/libstd/path.rs index bb6883236e8..3e414a28a30 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -129,7 +129,9 @@ use sys::path::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix}; // Windows Prefixes //////////////////////////////////////////////////////////////////////////////// -/// Path prefixes (Windows only). +/// Path prefixes (Redox and Windows only). +/// +/// Redox uses schemes like `scheme:reference` to identify different I/O systems /// /// Windows uses a variety of path styles, including references to drive /// volumes (like `C:`), network shared folders (like `\\server\share`) and @@ -139,6 +141,10 @@ use sys::path::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix}; #[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub enum Prefix<'a> { + /// Prefix `scheme:`, where `scheme` is the component stored + #[unstable(feature="redox_prefix", issue="0")] + Scheme(&'a OsStr), + /// Prefix `\\?\`, together with the given component immediately following it. #[stable(feature = "rust1", since = "1.0.0")] Verbatim(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr), @@ -178,6 +184,7 @@ impl<'a> Prefix<'a> { os_str_as_u8_slice(s).len() } match *self { + Scheme(x) => os_str_len(x) + 1, Verbatim(x) => 4 + os_str_len(x), VerbatimUNC(x, y) => { 8 + os_str_len(x) + diff --git a/src/libstd/sys/redox/path.rs b/src/libstd/sys/redox/path.rs index bf9af7a4353..4069a0ea726 100644 --- a/src/libstd/sys/redox/path.rs +++ b/src/libstd/sys/redox/path.rs @@ -21,8 +21,16 @@ pub fn is_verbatim_sep(b: u8) -> bool { b == b'/' } -pub fn parse_prefix(_: &OsStr) -> Option { - None +pub fn parse_prefix(path: &OsStr) -> Option { + if let Some(path_str) = path.to_str() { + if let Some(i) = path_str.find(':') { + Some(Prefix::Scheme(OsStr::new(&path_str[..i]))) + } else { + None + } + } else { + None + } } pub const MAIN_SEP_STR: &'static str = "/"; -- cgit 1.4.1-3-g733a5 From de68aced95ab53bc0f69ff4d6867a03d2dd0f8d7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 14 Nov 2016 19:08:48 -0700 Subject: Add current_exe support --- src/libstd/sys/redox/os.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs index 309201352c4..e007e33258f 100644 --- a/src/libstd/sys/redox/os.rs +++ b/src/libstd/sys/redox/os.rs @@ -113,8 +113,18 @@ impl StdError for JoinPathsError { } pub fn current_exe() -> io::Result { - use io::ErrorKind; - Err(io::Error::new(ErrorKind::Other, "Not yet implemented on redox")) + use fs::File; + + let mut file = File::open("sys:exe")?; + + let mut path = String::new(); + file.read_to_string(&mut path)?; + + if path.ends_with('\n') { + path.pop(); + } + + Ok(PathBuf::from(path)) } pub struct Env { -- cgit 1.4.1-3-g733a5 From 73f24d47dee367563019b18ac5089b91eded2753 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 14 Nov 2016 20:56:06 -0700 Subject: Simple implementation of read2 --- src/libstd/sys/redox/pipe.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs index a25ca048942..fff4a10f913 100644 --- a/src/libstd/sys/redox/pipe.rs +++ b/src/libstd/sys/redox/pipe.rs @@ -23,9 +23,7 @@ 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]); - let fd1 = FileDesc::new(fds[1]); - Ok((AnonPipe::from_fd(fd0)?, AnonPipe::from_fd(fd1)?)) + Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1])))) } impl AnonPipe { @@ -50,12 +48,18 @@ impl AnonPipe { pub fn into_fd(self) -> FileDesc { self.0 } } -pub fn read2(_p1: AnonPipe, - _v1: &mut Vec, - _p2: AnonPipe, - _v2: &mut Vec) -> io::Result<()> { - ::sys_common::util::dumb_print(format_args!("read2\n")); - unimplemented!(); +pub fn read2(p1: AnonPipe, + v1: &mut Vec, + p2: AnonPipe, + v2: &mut Vec) -> io::Result<()> { + //TODO: Use event based I/O multiplexing + //unimplemented!() + + p1.read_to_end(v1)?; + p2.read_to_end(v2)?; + + Ok(()) + /* // Set both pipes into nonblocking mode as we're gonna be reading from both // in the `select` loop below, and we wouldn't want one to block the other! @@ -64,7 +68,6 @@ pub fn read2(_p1: AnonPipe, p1.set_nonblocking(true)?; p2.set_nonblocking(true)?; - let max = cmp::max(p1.raw(), p2.raw()); loop { // wait for either pipe to become readable using `select` cvt_r(|| unsafe { -- cgit 1.4.1-3-g733a5 From 2e5c821619c7b62ec46c8a4f90ead4e59fb6c36e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 15 Nov 2016 16:12:30 -0700 Subject: Add set_perm --- src/libstd/sys/redox/ext/fs.rs | 2 +- src/libstd/sys/redox/fs.rs | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index 45ad7c092de..2914fafa94c 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -216,7 +216,7 @@ impl MetadataExt for fs::Metadata { } } -/* +/* TODO /// Add special unix types (block/char device, fifo and socket) #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index 1a96ac2f2ea..df2926565f7 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -386,9 +386,12 @@ pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { unimplemented!(); } -pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { - ::sys_common::util::dumb_print(format_args!("Set perm\n")); - unimplemented!(); +pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { + let mut options = OpenOptions::new(); + options.read(true); + let file = File::open(p, &options)?; + cvt(libc::fcntl(file.0.raw(), libc::F_SETMODE, perm.mode as usize))?; + Ok(()) } pub fn rmdir(p: &Path) -> io::Result<()> { -- cgit 1.4.1-3-g733a5 From 267bc54fbd2cfeadde7a87fc2aa3fb975ff58b6c Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 15 Nov 2016 17:07:55 -0700 Subject: Use chmod instead of fcntl to change file perms --- src/libstd/sys/redox/fs.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index df2926565f7..3a7b8266a63 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -387,10 +387,7 @@ pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { } pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { - let mut options = OpenOptions::new(); - options.read(true); - let file = File::open(p, &options)?; - cvt(libc::fcntl(file.0.raw(), libc::F_SETMODE, perm.mode as usize))?; + cvt(libc::chmod(p.to_str().unwrap(), perm.mode as usize))?; Ok(()) } -- cgit 1.4.1-3-g733a5 From f01add1a3bc3d86ee62f5819fa6ed9f79d453665 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 17 Nov 2016 10:22:07 -0700 Subject: Add signal support, better exec error handling --- src/libstd/sys/redox/process.rs | 114 ++++++++++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 34 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 934cf20bf07..92694e4b222 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -13,7 +13,7 @@ use env; use ffi::OsStr; use fmt; use io::{self, Error, ErrorKind}; -use libc::{self, pid_t, c_int, gid_t, uid_t}; +use libc::{self, pid_t, gid_t, uid_t}; use path::Path; use sys::fd::FileDesc; use sys::fs::{File, OpenOptions}; @@ -145,33 +145,79 @@ impl Command { pub fn spawn(&mut self, default: Stdio, needs_stdin: bool) -> io::Result<(Process, StdioPipes)> { - if self.saw_nul { - return Err(io::Error::new(ErrorKind::InvalidInput, - "nul byte found in provided data")); - } - - let (ours, theirs) = self.setup_io(default, needs_stdin)?; - - let pid = unsafe { - match cvt(libc::clone(libc::CLONE_VFORK))? { - 0 => { - let err = self.do_exec(theirs); - let _ = libc::exit((-err.raw_os_error().unwrap_or(libc::EINVAL)) as usize); - unreachable!(); - } - n => n as pid_t, - } - }; - - let mut status_mux = 0; - if cvt(libc::waitpid(pid, &mut status_mux, libc::WNOHANG))? == pid { - match libc::Error::demux(status_mux) { - Ok(status) => Ok((Process { pid: pid, status: Some(ExitStatus::from(status as c_int)) }, ours)), - Err(err) => Err(io::Error::from_raw_os_error(err.errno)), - } - } else { - Ok((Process { pid: pid, status: None }, ours)) - } + const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX"; + + if self.saw_nul { + return Err(io::Error::new(ErrorKind::InvalidInput, + "nul byte found in provided data")); + } + + let (ours, theirs) = self.setup_io(default, needs_stdin)?; + let (input, output) = pipe::anon_pipe()?; + + let pid = unsafe { + match cvt(libc::clone(0))? { + 0 => { + drop(input); + let err = self.do_exec(theirs); + let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32; + let bytes = [ + (errno >> 24) as u8, + (errno >> 16) as u8, + (errno >> 8) as u8, + (errno >> 0) as u8, + CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1], + CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3] + ]; + // pipe I/O up to PIPE_BUF bytes should be atomic, and then + // 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()); + let _ = libc::exit(1); + panic!("failed to exit"); + } + n => n, + } + }; + + let mut p = Process { pid: pid, status: None }; + drop(output); + let mut bytes = [0; 8]; + + // loop to handle EINTR + loop { + match input.read(&mut bytes) { + Ok(0) => return Ok((p, ours)), + Ok(8) => { + assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]), + "Validation on the CLOEXEC pipe failed: {:?}", bytes); + let errno = combine(&bytes[0.. 4]); + assert!(p.wait().is_ok(), + "wait() should either return Ok or panic"); + return Err(Error::from_raw_os_error(errno)) + } + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => { + assert!(p.wait().is_ok(), + "wait() should either return Ok or panic"); + panic!("the CLOEXEC pipe failed: {:?}", e) + }, + Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic + assert!(p.wait().is_ok(), + "wait() should either return Ok or panic"); + panic!("short read on the CLOEXEC pipe") + } + } + } + + fn combine(arr: &[u8]) -> i32 { + let a = arr[0] as u32; + let b = arr[1] as u32; + let c = arr[2] as u32; + let d = arr[3] as u32; + + ((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32 + } } pub fn exec(&mut self, default: Stdio) -> io::Error { @@ -378,11 +424,11 @@ impl fmt::Debug for Command { /// Unix exit statuses #[derive(PartialEq, Eq, Clone, Copy, Debug)] -pub struct ExitStatus(c_int); +pub struct ExitStatus(i32); impl ExitStatus { fn exited(&self) -> bool { - true + self.0 & 0x7F == 0 } pub fn success(&self) -> bool { @@ -391,7 +437,7 @@ impl ExitStatus { pub fn code(&self) -> Option { if self.exited() { - Some(self.0) + Some((self.0 >> 8) & 0xFF) } else { None } @@ -399,15 +445,15 @@ impl ExitStatus { pub fn signal(&self) -> Option { if !self.exited() { - Some(self.0) + Some(self.0 & 0x7F) } else { None } } } -impl From for ExitStatus { - fn from(a: c_int) -> ExitStatus { +impl From for ExitStatus { + fn from(a: i32) -> ExitStatus { ExitStatus(a) } } -- cgit 1.4.1-3-g733a5 From 2556400a5d4c9b56084332c29b6c91ac5cd3a9fa Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 17 Nov 2016 14:15:58 -0700 Subject: Replace setuid, setgid with setreuid, setregid --- src/libstd/sys/redox/process.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 92694e4b222..269aa6bedac 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -287,10 +287,10 @@ impl Command { } if let Some(g) = self.gid { - t!(cvt(libc::setgid(g))); + t!(cvt(libc::setregid(g, g))); } if let Some(u) = self.uid { - t!(cvt(libc::setuid(u))); + t!(cvt(libc::setreuid(u, u))); } if let Some(ref cwd) = self.cwd { t!(cvt(libc::chdir(cwd))); -- cgit 1.4.1-3-g733a5 From 4a0bc71bb7e32d7f63d10be13055942fb5dc6aca Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 23 Nov 2016 08:24:49 -0700 Subject: Add File set_permissions --- src/libstd/sys/redox/fs.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index 3a7b8266a63..2b0ab361492 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -316,6 +316,10 @@ impl File { Ok(File(FileDesc::new(fd))) } + pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> { + set_perm(&self.path()?, perm) + } + pub fn path(&self) -> io::Result { let mut buf: [u8; 4096] = [0; 4096]; match libc::fpath(*self.fd().as_inner() as usize, &mut buf) { -- cgit 1.4.1-3-g733a5 From 6733074c847767fd3e0425fcefb73226bde1f6a1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 23 Nov 2016 14:22:39 -0700 Subject: Allow setting nonblock on sockets --- src/libstd/sys/redox/fd.rs | 15 ++++++++++----- src/libstd/sys/redox/net/tcp.rs | 6 +++--- src/libstd/sys/redox/net/udp.rs | 6 +++--- 3 files changed, 16 insertions(+), 11 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs index 47d2280fe05..b716965860e 100644 --- a/src/libstd/sys/redox/fd.rs +++ b/src/libstd/sys/redox/fd.rs @@ -48,6 +48,16 @@ impl FileDesc { cvt(libc::write(self.fd, buf)) } + pub fn duplicate(&self) -> io::Result { + let new_fd = cvt(libc::dup(self.fd, &[]))?; + Ok(FileDesc::new(new_fd)) + } + + pub fn nonblocking(&self) -> io::Result { + let flags = cvt(libc::fcntl(self.fd, libc::F_GETFL, 0))?; + Ok(flags & libc::O_NONBLOCK == libc::O_NONBLOCK) + } + pub fn set_cloexec(&self) -> io::Result<()> { let mut flags = cvt(libc::fcntl(self.fd, libc::F_GETFL, 0))?; flags |= libc::O_CLOEXEC; @@ -63,11 +73,6 @@ impl FileDesc { } cvt(libc::fcntl(self.fd, libc::F_SETFL, flags)).and(Ok(())) } - - pub fn duplicate(&self) -> io::Result { - let new_fd = cvt(libc::dup(self.fd, &[]))?; - Ok(FileDesc::new(new_fd)) - } } impl<'a> Read for &'a FileDesc { diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs index 351c534c036..ceaa5df267f 100644 --- a/src/libstd/sys/redox/net/tcp.rs +++ b/src/libstd/sys/redox/net/tcp.rs @@ -58,7 +58,7 @@ impl TcpStream { } pub fn nonblocking(&self) -> Result { - Err(Error::new(ErrorKind::Other, "TcpStream::nonblocking not implemented")) + self.0.fd().nonblocking() } pub fn only_v6(&self) -> Result { @@ -81,8 +81,8 @@ impl TcpStream { Err(Error::new(ErrorKind::Other, "TcpStream::set_nodelay not implemented")) } - pub fn set_nonblocking(&self, _nonblocking: bool) -> Result<()> { - Err(Error::new(ErrorKind::Other, "TcpStream::set_nonblocking not implemented")) + pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()> { + self.0.fd().set_nonblocking(nonblocking) } pub fn set_only_v6(&self, _only_v6: bool) -> Result<()> { diff --git a/src/libstd/sys/redox/net/udp.rs b/src/libstd/sys/redox/net/udp.rs index a259db6a4c0..7856de033eb 100644 --- a/src/libstd/sys/redox/net/udp.rs +++ b/src/libstd/sys/redox/net/udp.rs @@ -90,7 +90,7 @@ impl UdpSocket { } pub fn nonblocking(&self) -> Result { - Err(Error::new(ErrorKind::Other, "UdpSocket::nonblocking not implemented")) + self.0.fd().nonblocking() } pub fn only_v6(&self) -> Result { @@ -125,8 +125,8 @@ impl UdpSocket { Err(Error::new(ErrorKind::Other, "UdpSocket::set_multicast_ttl_v4 not implemented")) } - pub fn set_nonblocking(&self, _nonblocking: bool) -> Result<()> { - Err(Error::new(ErrorKind::Other, "UdpSocket::set_nonblocking not implemented")) + pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()> { + self.0.fd().set_nonblocking(nonblocking) } pub fn set_only_v6(&self, _only_v6: bool) -> Result<()> { -- cgit 1.4.1-3-g733a5 From 3a1bb2ba26a85bbea4c9be813a9a13d48ab448ac Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 25 Nov 2016 18:23:19 -0700 Subject: Use O_DIRECTORY --- src/libstd/sys/redox/fs.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index 2b0ab361492..0e51da711c9 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -339,7 +339,8 @@ impl DirBuilder { } pub fn mkdir(&self, p: &Path) -> io::Result<()> { - cvt(libc::mkdir(p.to_str().unwrap(), self.mode))?; + let fd = cvt(libc::open(p.to_str().unwrap(), libc::O_CREAT | libc::O_DIRECTORY | libc::O_EXCL | (self.mode as usize & 0o777)))?; + let _ = libc::close(fd); Ok(()) } @@ -372,11 +373,12 @@ impl fmt::Debug for File { pub fn readdir(p: &Path) -> io::Result { let root = Arc::new(p.to_path_buf()); - let mut options = OpenOptions::new(); - options.read(true); - let fd = File::open(p, &options)?; + + let fd = cvt(open(p.to_str().unwrap(), libc::O_CLOEXEC | libc::O_RDONLY | libc::O_DIRECTORY))?; + let file = FileDesc::new(fd); let mut data = Vec::new(); - fd.read_to_end(&mut data)?; + file.read_to_end(&mut data)?; + Ok(ReadDir { data: data, i: 0, root: root }) } @@ -437,10 +439,11 @@ pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { pub fn stat(p: &Path) -> io::Result { let mut stat: stat = stat::default(); - let mut options = OpenOptions::new(); - options.read(true); - let file = File::open(p, &options)?; - cvt(fstat(file.0.raw(), &mut stat))?; + + let fd = cvt(open(p.to_str().unwrap(), libc::O_CLOEXEC | libc::O_STAT))?; + cvt(fstat(fd, &mut stat))?; + let _ = libc::close(fd); + Ok(FileAttr { stat: stat }) } -- cgit 1.4.1-3-g733a5 From d73d32f58d477ca1562e3fc0e966efc88e81409e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 25 Nov 2016 19:53:21 -0700 Subject: Fix canonicalize --- src/libstd/sys/redox/fs.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index 0e51da711c9..12aa17becd8 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -452,9 +452,8 @@ pub fn lstat(p: &Path) -> io::Result { } pub fn canonicalize(p: &Path) -> io::Result { - let mut options = OpenOptions::new(); - options.read(true); - let file = File::open(p, &options)?; + let fd = cvt(open(p.to_str().unwrap(), libc::O_CLOEXEC | libc::O_STAT))?; + let file = File(FileDesc::new(fd)); file.path() } -- cgit 1.4.1-3-g733a5 From 746222fd9d6c16d3dc3c44c797dcc868297c133b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 28 Nov 2016 18:07:19 -0700 Subject: Switch to using syscall crate directly - without import --- src/libstd/sys/redox/condvar.rs | 5 +- src/libstd/sys/redox/ext/fs.rs | 10 ++- src/libstd/sys/redox/ext/mod.rs | 2 +- src/libstd/sys/redox/ext/process.rs | 4 +- src/libstd/sys/redox/fd.rs | 29 ++++----- src/libstd/sys/redox/fs.rs | 125 +++++++++++++++++------------------- src/libstd/sys/redox/mod.rs | 39 +++++------ src/libstd/sys/redox/mutex.rs | 2 +- src/libstd/sys/redox/net/mod.rs | 2 +- src/libstd/sys/redox/os.rs | 12 ++-- src/libstd/sys/redox/pipe.rs | 4 +- src/libstd/sys/redox/process.rs | 53 ++++++++------- src/libstd/sys/redox/stdio.rs | 19 +++--- src/libstd/sys/redox/thread.rs | 26 ++++---- src/libstd/sys/redox/time.rs | 27 ++++---- 15 files changed, 171 insertions(+), 188 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/condvar.rs b/src/libstd/sys/redox/condvar.rs index f6c8fec545b..7e26162efbc 100644 --- a/src/libstd/sys/redox/condvar.rs +++ b/src/libstd/sys/redox/condvar.rs @@ -3,9 +3,8 @@ use intrinsics::{atomic_cxchg, atomic_xadd, atomic_xchg}; use ptr; use time::Duration; -use super::mutex::{mutex_lock, mutex_unlock, Mutex}; - -use libc::{futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE}; +use sys::mutex::{mutex_lock, mutex_unlock, Mutex}; +use sys::syscall::{futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE}; pub struct Condvar { lock: UnsafeCell<*mut i32>, diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index 2914fafa94c..d292b438724 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -216,7 +216,6 @@ impl MetadataExt for fs::Metadata { } } -/* TODO /// Add special unix types (block/char device, fifo and socket) #[stable(feature = "file_type_ext", since = "1.5.0")] pub trait FileTypeExt { @@ -236,12 +235,11 @@ pub trait FileTypeExt { #[stable(feature = "file_type_ext", since = "1.5.0")] impl FileTypeExt for fs::FileType { - fn is_block_device(&self) -> bool { self.as_inner().is(libc::S_IFBLK) } - fn is_char_device(&self) -> bool { self.as_inner().is(libc::S_IFCHR) } - fn is_fifo(&self) -> bool { self.as_inner().is(libc::S_IFIFO) } - fn is_socket(&self) -> bool { self.as_inner().is(libc::S_IFSOCK) } + fn is_block_device(&self) -> bool { false /*TODO*/ } + fn is_char_device(&self) -> bool { false /*TODO*/ } + fn is_fifo(&self) -> bool { false /*TODO*/ } + fn is_socket(&self) -> bool { false /*TODO*/ } } -*/ /// Creates a new symbolic link on the filesystem. /// diff --git a/src/libstd/sys/redox/ext/mod.rs b/src/libstd/sys/redox/ext/mod.rs index 7ba166e8932..02edfa84aa0 100644 --- a/src/libstd/sys/redox/ext/mod.rs +++ b/src/libstd/sys/redox/ext/mod.rs @@ -44,7 +44,7 @@ pub mod prelude { #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] - pub use super::fs::{PermissionsExt, OpenOptionsExt, MetadataExt}; + pub use super::fs::{FileTypeExt, PermissionsExt, OpenOptionsExt, MetadataExt}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use super::process::{CommandExt, ExitStatusExt}; } diff --git a/src/libstd/sys/redox/ext/process.rs b/src/libstd/sys/redox/ext/process.rs index f8e6b2cf470..3a7c59d4e6d 100644 --- a/src/libstd/sys/redox/ext/process.rs +++ b/src/libstd/sys/redox/ext/process.rs @@ -86,12 +86,12 @@ pub trait CommandExt { #[stable(feature = "rust1", since = "1.0.0")] impl CommandExt for process::Command { fn uid(&mut self, id: u32) -> &mut process::Command { - self.as_inner_mut().uid(id as usize); + self.as_inner_mut().uid(id); self } fn gid(&mut self, id: u32) -> &mut process::Command { - self.as_inner_mut().gid(id as usize); + self.as_inner_mut().gid(id); self } diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs index b716965860e..4c8e62d1863 100644 --- a/src/libstd/sys/redox/fd.rs +++ b/src/libstd/sys/redox/fd.rs @@ -11,9 +11,8 @@ #![unstable(reason = "not public", issue = "0", feature = "fd")] use io::{self, Read}; -use libc; use mem; -use sys::cvt; +use sys::{cvt, syscall}; use sys_common::AsInner; use sys_common::io::read_to_end_uninitialized; @@ -36,7 +35,7 @@ impl FileDesc { } pub fn read(&self, buf: &mut [u8]) -> io::Result { - cvt(libc::read(self.fd, buf)) + cvt(syscall::read(self.fd, buf)) } pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { @@ -45,33 +44,33 @@ impl FileDesc { } pub fn write(&self, buf: &[u8]) -> io::Result { - cvt(libc::write(self.fd, buf)) + cvt(syscall::write(self.fd, buf)) } pub fn duplicate(&self) -> io::Result { - let new_fd = cvt(libc::dup(self.fd, &[]))?; + let new_fd = cvt(syscall::dup(self.fd, &[]))?; Ok(FileDesc::new(new_fd)) } pub fn nonblocking(&self) -> io::Result { - let flags = cvt(libc::fcntl(self.fd, libc::F_GETFL, 0))?; - Ok(flags & libc::O_NONBLOCK == libc::O_NONBLOCK) + let flags = cvt(syscall::fcntl(self.fd, syscall::F_GETFL, 0))?; + Ok(flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK) } pub fn set_cloexec(&self) -> io::Result<()> { - let mut flags = cvt(libc::fcntl(self.fd, libc::F_GETFL, 0))?; - flags |= libc::O_CLOEXEC; - cvt(libc::fcntl(self.fd, libc::F_SETFL, flags)).and(Ok(())) + let mut flags = cvt(syscall::fcntl(self.fd, syscall::F_GETFL, 0))?; + flags |= syscall::O_CLOEXEC; + cvt(syscall::fcntl(self.fd, syscall::F_SETFL, flags)).and(Ok(())) } pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { - let mut flags = cvt(libc::fcntl(self.fd, libc::F_GETFL, 0))?; + let mut flags = cvt(syscall::fcntl(self.fd, syscall::F_GETFL, 0))?; if nonblocking { - flags |= libc::O_NONBLOCK; + flags |= syscall::O_NONBLOCK; } else { - flags &= !libc::O_NONBLOCK; + flags &= !syscall::O_NONBLOCK; } - cvt(libc::fcntl(self.fd, libc::F_SETFL, flags)).and(Ok(())) + cvt(syscall::fcntl(self.fd, syscall::F_SETFL, flags)).and(Ok(())) } } @@ -96,6 +95,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 _ = libc::close(self.fd); + let _ = syscall::close(self.fd); } } diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index 12aa17becd8..80aec2e978d 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -13,21 +13,18 @@ use os::unix::prelude::*; use ffi::{OsString, OsStr}; use fmt; use io::{self, Error, ErrorKind, SeekFrom}; -use libc::{self, c_int, mode_t}; use path::{Path, PathBuf}; use sync::Arc; use sys::fd::FileDesc; use sys::time::SystemTime; -use sys::cvt; +use sys::{cvt, syscall}; use sys_common::{AsInner, FromInner}; -use libc::{stat, fstat, fsync, ftruncate, lseek, open}; - pub struct File(FileDesc); #[derive(Clone)] pub struct FileAttr { - stat: stat, + stat: syscall::Stat, } pub struct ReadDir { @@ -57,53 +54,53 @@ pub struct OpenOptions { create_new: bool, // system-specific custom_flags: i32, - mode: mode_t, + mode: u16, } #[derive(Clone, PartialEq, Eq, Debug)] -pub struct FilePermissions { mode: mode_t } +pub struct FilePermissions { mode: u16 } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub struct FileType { mode: mode_t } +pub struct FileType { mode: u16 } -pub struct DirBuilder { mode: mode_t } +pub struct DirBuilder { mode: u16 } impl FileAttr { pub fn size(&self) -> u64 { self.stat.st_size as u64 } pub fn perm(&self) -> FilePermissions { - FilePermissions { mode: (self.stat.st_mode as mode_t) & 0o777 } + FilePermissions { mode: (self.stat.st_mode as u16) & 0o777 } } pub fn file_type(&self) -> FileType { - FileType { mode: self.stat.st_mode as mode_t } + FileType { mode: self.stat.st_mode as u16 } } } impl FileAttr { pub fn modified(&self) -> io::Result { - Ok(SystemTime::from(libc::timespec { - tv_sec: self.stat.st_mtime as libc::time_t, + Ok(SystemTime::from(syscall::TimeSpec { + tv_sec: self.stat.st_mtime as i64, tv_nsec: self.stat.st_mtime_nsec as i32, })) } pub fn accessed(&self) -> io::Result { - Ok(SystemTime::from(libc::timespec { - tv_sec: self.stat.st_atime as libc::time_t, + Ok(SystemTime::from(syscall::TimeSpec { + tv_sec: self.stat.st_atime as i64, tv_nsec: self.stat.st_atime_nsec as i32, })) } pub fn created(&self) -> io::Result { - Ok(SystemTime::from(libc::timespec { - tv_sec: self.stat.st_ctime as libc::time_t, + Ok(SystemTime::from(syscall::TimeSpec { + tv_sec: self.stat.st_ctime as i64, tv_nsec: self.stat.st_ctime_nsec as i32, })) } } -impl AsInner for FileAttr { - fn as_inner(&self) -> &stat { &self.stat } +impl AsInner for FileAttr { + fn as_inner(&self) -> &syscall::Stat { &self.stat } } impl FilePermissions { @@ -119,16 +116,16 @@ impl FilePermissions { } impl FileType { - pub fn is_dir(&self) -> bool { self.is(libc::MODE_DIR) } - pub fn is_file(&self) -> bool { self.is(libc::MODE_FILE) } + pub fn is_dir(&self) -> bool { self.is(syscall::MODE_DIR) } + pub fn is_file(&self) -> bool { self.is(syscall::MODE_FILE) } pub fn is_symlink(&self) -> bool { false } - pub fn is(&self, mode: mode_t) -> bool { self.mode & (libc::MODE_DIR | libc::MODE_FILE) == mode } + pub fn is(&self, mode: u16) -> bool { self.mode & (syscall::MODE_DIR | syscall::MODE_FILE) == mode } } impl FromInner for FilePermissions { fn from_inner(mode: u32) -> FilePermissions { - FilePermissions { mode: mode as mode_t } + FilePermissions { mode: mode as u16 } } } @@ -215,60 +212,60 @@ impl OpenOptions { pub fn create_new(&mut self, create_new: bool) { self.create_new = create_new; } pub fn custom_flags(&mut self, flags: i32) { self.custom_flags = flags; } - pub fn mode(&mut self, mode: u32) { self.mode = mode as mode_t; } + pub fn mode(&mut self, mode: u32) { self.mode = mode as u16; } - fn get_access_mode(&self) -> io::Result { + fn get_access_mode(&self) -> io::Result { match (self.read, self.write, self.append) { - (true, false, false) => Ok(libc::O_RDONLY as c_int), - (false, true, false) => Ok(libc::O_WRONLY as c_int), - (true, true, false) => Ok(libc::O_RDWR as c_int), - (false, _, true) => Ok(libc::O_WRONLY as c_int | libc::O_APPEND as c_int), - (true, _, true) => Ok(libc::O_RDWR as c_int | libc::O_APPEND as c_int), - (false, false, false) => Err(Error::from_raw_os_error(libc::EINVAL)), + (true, false, false) => Ok(syscall::O_RDONLY), + (false, true, false) => Ok(syscall::O_WRONLY), + (true, true, false) => Ok(syscall::O_RDWR), + (false, _, true) => Ok(syscall::O_WRONLY | syscall::O_APPEND), + (true, _, true) => Ok(syscall::O_RDWR | syscall::O_APPEND), + (false, false, false) => Err(Error::from_raw_os_error(syscall::EINVAL)), } } - fn get_creation_mode(&self) -> io::Result { + fn get_creation_mode(&self) -> io::Result { match (self.write, self.append) { (true, false) => {} (false, false) => if self.truncate || self.create || self.create_new { - return Err(Error::from_raw_os_error(libc::EINVAL)); + return Err(Error::from_raw_os_error(syscall::EINVAL)); }, (_, true) => if self.truncate && !self.create_new { - return Err(Error::from_raw_os_error(libc::EINVAL)); + return Err(Error::from_raw_os_error(syscall::EINVAL)); }, } Ok(match (self.create, self.truncate, self.create_new) { (false, false, false) => 0, - (true, false, false) => libc::O_CREAT as c_int, - (false, true, false) => libc::O_TRUNC as c_int, - (true, true, false) => libc::O_CREAT as c_int | libc::O_TRUNC as c_int, - (_, _, true) => libc::O_CREAT as c_int | libc::O_EXCL as c_int, + (true, false, false) => syscall::O_CREAT, + (false, true, false) => syscall::O_TRUNC, + (true, true, false) => syscall::O_CREAT | syscall::O_TRUNC, + (_, _, true) => syscall::O_CREAT | syscall::O_EXCL, }) } } impl File { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result { - let flags = libc::O_CLOEXEC | + let flags = syscall::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))?; + (opts.custom_flags as usize & !syscall::O_ACCMODE); + let fd = cvt(syscall::open(path.to_str().unwrap(), flags | opts.mode as usize))?; Ok(File(FileDesc::new(fd))) } pub fn file_attr(&self) -> io::Result { - let mut stat: stat = stat::default(); - cvt(fstat(self.0.raw(), &mut stat))?; + let mut stat = syscall::Stat::default(); + cvt(syscall::fstat(self.0.raw(), &mut stat))?; Ok(FileAttr { stat: stat }) } pub fn fsync(&self) -> io::Result<()> { - cvt(fsync(self.0.raw()))?; + cvt(syscall::fsync(self.0.raw()))?; Ok(()) } @@ -277,7 +274,7 @@ impl File { } pub fn truncate(&self, size: u64) -> io::Result<()> { - cvt(ftruncate(self.0.raw(), size as usize))?; + cvt(syscall::ftruncate(self.0.raw(), size as usize))?; Ok(()) } @@ -299,11 +296,11 @@ impl File { let (whence, pos) = match pos { // Casting to `i64` is fine, too large values will end up as // negative which will cause an error in `lseek64`. - SeekFrom::Start(off) => (libc::SEEK_SET, off as i64), - SeekFrom::End(off) => (libc::SEEK_END, off), - SeekFrom::Current(off) => (libc::SEEK_CUR, off), + SeekFrom::Start(off) => (syscall::SEEK_SET, off as i64), + SeekFrom::End(off) => (syscall::SEEK_END, off), + SeekFrom::Current(off) => (syscall::SEEK_CUR, off), }; - let n = cvt(lseek(self.0.raw(), pos as isize, whence))?; + let n = cvt(syscall::lseek(self.0.raw(), pos as isize, whence))?; Ok(n as u64) } @@ -312,7 +309,7 @@ impl File { } pub fn dup(&self, buf: &[u8]) -> io::Result { - let fd = cvt(libc::dup(*self.fd().as_inner() as usize, buf))?; + let fd = cvt(syscall::dup(*self.fd().as_inner() as usize, buf))?; Ok(File(FileDesc::new(fd))) } @@ -322,7 +319,7 @@ impl File { pub fn path(&self) -> io::Result { let mut buf: [u8; 4096] = [0; 4096]; - match libc::fpath(*self.fd().as_inner() as usize, &mut buf) { + match syscall::fpath(*self.fd().as_inner() as usize, &mut buf) { Ok(count) => Ok(PathBuf::from(unsafe { String::from_utf8_unchecked(Vec::from(&buf[0..count])) })), Err(err) => Err(Error::from_raw_os_error(err.errno)), } @@ -339,13 +336,13 @@ impl DirBuilder { } pub fn mkdir(&self, p: &Path) -> io::Result<()> { - let fd = cvt(libc::open(p.to_str().unwrap(), libc::O_CREAT | libc::O_DIRECTORY | libc::O_EXCL | (self.mode as usize & 0o777)))?; - let _ = libc::close(fd); + let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_CREAT | syscall::O_DIRECTORY | syscall::O_EXCL | (self.mode as usize & 0o777)))?; + let _ = syscall::close(fd); Ok(()) } pub fn set_mode(&mut self, mode: u32) { - self.mode = mode as mode_t; + self.mode = mode as u16; } } @@ -374,7 +371,7 @@ impl fmt::Debug for File { pub fn readdir(p: &Path) -> io::Result { let root = Arc::new(p.to_path_buf()); - let fd = cvt(open(p.to_str().unwrap(), libc::O_CLOEXEC | libc::O_RDONLY | libc::O_DIRECTORY))?; + let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_CLOEXEC | syscall::O_RDONLY | syscall::O_DIRECTORY))?; let file = FileDesc::new(fd); let mut data = Vec::new(); file.read_to_end(&mut data)?; @@ -383,7 +380,7 @@ pub fn readdir(p: &Path) -> io::Result { } pub fn unlink(p: &Path) -> io::Result<()> { - cvt(libc::unlink(p.to_str().unwrap()))?; + cvt(syscall::unlink(p.to_str().unwrap()))?; Ok(()) } @@ -393,12 +390,12 @@ pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { } pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { - cvt(libc::chmod(p.to_str().unwrap(), perm.mode as usize))?; + cvt(syscall::chmod(p.to_str().unwrap(), perm.mode as usize))?; Ok(()) } pub fn rmdir(p: &Path) -> io::Result<()> { - cvt(libc::rmdir(p.to_str().unwrap()))?; + cvt(syscall::rmdir(p.to_str().unwrap()))?; Ok(()) } @@ -438,13 +435,9 @@ pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { } pub fn stat(p: &Path) -> io::Result { - let mut stat: stat = stat::default(); - - let fd = cvt(open(p.to_str().unwrap(), libc::O_CLOEXEC | libc::O_STAT))?; - cvt(fstat(fd, &mut stat))?; - let _ = libc::close(fd); - - Ok(FileAttr { stat: stat }) + let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_CLOEXEC | syscall::O_STAT))?; + let file = File(FileDesc::new(fd)); + file.file_attr() } pub fn lstat(p: &Path) -> io::Result { @@ -452,7 +445,7 @@ pub fn lstat(p: &Path) -> io::Result { } pub fn canonicalize(p: &Path) -> io::Result { - let fd = cvt(open(p.to_str().unwrap(), libc::O_CLOEXEC | libc::O_STAT))?; + let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_CLOEXEC | syscall::O_STAT))?; let file = File(FileDesc::new(fd)); file.path() } diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index 3f3d8f2c4f4..07ead22b7a8 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -1,7 +1,8 @@ #![allow(dead_code, missing_docs, bad_style)] +pub extern crate syscall; + use io::{self, ErrorKind}; -use libc; pub mod args; pub mod backtrace; @@ -42,40 +43,40 @@ pub fn init() { use intrinsics; let msg = "fatal runtime error: out of memory\n"; unsafe { - let _ = libc::write(libc::STDERR_FILENO, msg.as_bytes()); + let _ = syscall::write(2, msg.as_bytes()); intrinsics::abort(); } } } pub fn decode_error_kind(errno: i32) -> ErrorKind { - match errno as libc::c_int { - libc::ECONNREFUSED => ErrorKind::ConnectionRefused, - libc::ECONNRESET => ErrorKind::ConnectionReset, - libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied, - libc::EPIPE => ErrorKind::BrokenPipe, - libc::ENOTCONN => ErrorKind::NotConnected, - libc::ECONNABORTED => ErrorKind::ConnectionAborted, - libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, - libc::EADDRINUSE => ErrorKind::AddrInUse, - libc::ENOENT => ErrorKind::NotFound, - libc::EINTR => ErrorKind::Interrupted, - libc::EINVAL => ErrorKind::InvalidInput, - libc::ETIMEDOUT => ErrorKind::TimedOut, - libc::EEXIST => ErrorKind::AlreadyExists, + match errno { + syscall::ECONNREFUSED => ErrorKind::ConnectionRefused, + syscall::ECONNRESET => ErrorKind::ConnectionReset, + syscall::EPERM | syscall::EACCES => ErrorKind::PermissionDenied, + syscall::EPIPE => ErrorKind::BrokenPipe, + syscall::ENOTCONN => ErrorKind::NotConnected, + syscall::ECONNABORTED => ErrorKind::ConnectionAborted, + syscall::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, + syscall::EADDRINUSE => ErrorKind::AddrInUse, + syscall::ENOENT => ErrorKind::NotFound, + syscall::EINTR => ErrorKind::Interrupted, + syscall::EINVAL => ErrorKind::InvalidInput, + syscall::ETIMEDOUT => ErrorKind::TimedOut, + syscall::EEXIST => ErrorKind::AlreadyExists, // These two constants can have the same value on some systems, // but different values on others, so we can't use a match // clause - x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => + x if x == syscall::EAGAIN || x == syscall::EWOULDBLOCK => ErrorKind::WouldBlock, _ => ErrorKind::Other, } } -pub fn cvt(result: Result) -> io::Result { - result.map_err(|err| io::Error::from_raw_os_error(err.errno as i32)) +pub fn cvt(result: Result) -> io::Result { + result.map_err(|err| io::Error::from_raw_os_error(err.errno)) } /// On Redox, use an illegal instruction to abort diff --git a/src/libstd/sys/redox/mutex.rs b/src/libstd/sys/redox/mutex.rs index 4c2b0de8bd9..42424da858f 100644 --- a/src/libstd/sys/redox/mutex.rs +++ b/src/libstd/sys/redox/mutex.rs @@ -2,7 +2,7 @@ use cell::UnsafeCell; use intrinsics::{atomic_cxchg, atomic_xchg}; use ptr; -use libc::{futex, getpid, FUTEX_WAIT, FUTEX_WAKE}; +use sys::syscall::{futex, getpid, FUTEX_WAIT, FUTEX_WAKE}; pub unsafe fn mutex_try_lock(m: *mut i32) -> bool { atomic_cxchg(m, 0, 1).0 == 0 diff --git a/src/libstd/sys/redox/net/mod.rs b/src/libstd/sys/redox/net/mod.rs index 1c8fde546ef..92c7d72887b 100644 --- a/src/libstd/sys/redox/net/mod.rs +++ b/src/libstd/sys/redox/net/mod.rs @@ -4,7 +4,7 @@ use iter::Iterator; use net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use str::FromStr; use string::{String, ToString}; -use libc::EINVAL; +use sys::syscall::EINVAL; use time; use vec::{IntoIter, Vec}; diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs index e007e33258f..9ebbae4199b 100644 --- a/src/libstd/sys/redox/os.rs +++ b/src/libstd/sys/redox/os.rs @@ -19,7 +19,6 @@ use ffi::{OsString, OsStr}; use fmt; use io::{self, Read, Write}; use iter; -use libc::{self, c_int, c_char, c_void}; use marker::PhantomData; use mem; use memchr; @@ -28,8 +27,7 @@ use ptr; use slice; use str; use sys_common::mutex::Mutex; -use sys::cvt; -use sys::fd; +use sys::{cvt, fd, syscall}; use vec; const TMPBUF_SZ: usize = 128; @@ -42,7 +40,7 @@ pub fn errno() -> i32 { /// Gets a detailed string description for the given error number. pub fn error_string(errno: i32) -> String { - if let Some(string) = libc::STR_ERROR.get(errno as usize) { + if let Some(string) = syscall::STR_ERROR.get(errno as usize) { string.to_string() } else { "unknown error".to_string() @@ -51,12 +49,12 @@ pub fn error_string(errno: i32) -> String { pub fn getcwd() -> io::Result { let mut buf = [0; 4096]; - let count = cvt(libc::getcwd(&mut buf))?; + let count = cvt(syscall::getcwd(&mut buf))?; Ok(PathBuf::from(OsString::from_vec(buf[.. count].to_vec()))) } pub fn chdir(p: &path::Path) -> io::Result<()> { - cvt(libc::chdir(p.to_str().unwrap())).and(Ok(())) + cvt(syscall::chdir(p.to_str().unwrap())).and(Ok(())) } pub struct SplitPaths<'a> { @@ -200,6 +198,6 @@ pub fn home_dir() -> Option { } pub fn exit(code: i32) -> ! { - let _ = libc::exit(code as usize); + let _ = syscall::exit(code as usize); unreachable!(); } diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs index fff4a10f913..7f192bef495 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; +use sys::syscall; use sys::fd::FileDesc; //////////////////////////////////////////////////////////////////////////////// @@ -21,7 +21,7 @@ pub struct AnonPipe(FileDesc); pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { let mut fds = [0; 2]; - libc::pipe2(&mut fds, libc::O_CLOEXEC).map_err(|err| io::Error::from_raw_os_error(err.errno))?; + syscall::pipe2(&mut fds, syscall::O_CLOEXEC).map_err(|err| io::Error::from_raw_os_error(err.errno))?; Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1])))) } diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 269aa6bedac..3c0d9691328 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -13,12 +13,11 @@ use env; use ffi::OsStr; use fmt; use io::{self, Error, ErrorKind}; -use libc::{self, pid_t, gid_t, uid_t}; use path::Path; use sys::fd::FileDesc; use sys::fs::{File, OpenOptions}; use sys::pipe::{self, AnonPipe}; -use sys::cvt; +use sys::{cvt, syscall}; //////////////////////////////////////////////////////////////////////////////// // Command @@ -47,8 +46,8 @@ pub struct Command { env: HashMap, cwd: Option, - uid: Option, - gid: Option, + uid: Option, + gid: Option, saw_nul: bool, closures: Vec io::Result<()> + Send + Sync>>, stdin: Option, @@ -121,10 +120,10 @@ impl Command { pub fn cwd(&mut self, dir: &OsStr) { self.cwd = Some(dir.to_str().unwrap().to_owned()); } - pub fn uid(&mut self, id: uid_t) { + pub fn uid(&mut self, id: u32) { self.uid = Some(id); } - pub fn gid(&mut self, id: gid_t) { + pub fn gid(&mut self, id: u32) { self.gid = Some(id); } @@ -156,11 +155,11 @@ impl Command { let (input, output) = pipe::anon_pipe()?; let pid = unsafe { - match cvt(libc::clone(0))? { + match cvt(syscall::clone(0))? { 0 => { drop(input); let err = self.do_exec(theirs); - let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32; + let errno = err.raw_os_error().unwrap_or(syscall::EINVAL) as u32; let bytes = [ (errno >> 24) as u8, (errno >> 16) as u8, @@ -173,7 +172,7 @@ 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()); - let _ = libc::exit(1); + let _ = syscall::exit(1); panic!("failed to exit"); } n => n, @@ -261,7 +260,7 @@ impl Command { // this file descriptor by dropping the FileDesc (which contains an // allocation). Instead we just close it manually. This will never // have the drop glue anyway because this code never returns (the - // child will either exec() or invoke libc::exit) + // child will either exec() or invoke syscall::exit) unsafe fn do_exec(&mut self, stdio: ChildPipes) -> io::Error { macro_rules! t { ($e:expr) => (match $e { @@ -271,29 +270,29 @@ impl Command { } if let Some(fd) = stdio.stderr.fd() { - let _ = libc::close(libc::STDERR_FILENO); - t!(cvt(libc::dup(fd, &[]))); - let _ = libc::close(fd); + let _ = syscall::close(2); + t!(cvt(syscall::dup(fd, &[]))); + let _ = syscall::close(fd); } if let Some(fd) = stdio.stdout.fd() { - let _ = libc::close(libc::STDOUT_FILENO); - t!(cvt(libc::dup(fd, &[]))); - let _ = libc::close(fd); + let _ = syscall::close(1); + t!(cvt(syscall::dup(fd, &[]))); + let _ = syscall::close(fd); } if let Some(fd) = stdio.stdin.fd() { - let _ = libc::close(libc::STDIN_FILENO); - t!(cvt(libc::dup(fd, &[]))); - let _ = libc::close(fd); + let _ = syscall::close(0); + t!(cvt(syscall::dup(fd, &[]))); + let _ = syscall::close(fd); } if let Some(g) = self.gid { - t!(cvt(libc::setregid(g, g))); + t!(cvt(syscall::setregid(g as usize, g as usize))); } if let Some(u) = self.uid { - t!(cvt(libc::setreuid(u, u))); + t!(cvt(syscall::setreuid(u as usize, u as usize))); } if let Some(ref cwd) = self.cwd { - t!(cvt(libc::chdir(cwd))); + t!(cvt(syscall::chdir(cwd))); } for callback in self.closures.iter_mut() { @@ -324,7 +323,7 @@ impl Command { path_env }; - if let Err(err) = libc::exec(&program, &args) { + if let Err(err) = syscall::execve(&program, &args) { io::Error::from_raw_os_error(err.errno as i32) } else { panic!("return from exec without err"); @@ -370,7 +369,7 @@ impl Stdio { // stderr. No matter which we dup first, the second will get // overwritten prematurely. Stdio::Fd(ref fd) => { - if fd.raw() <= libc::STDERR_FILENO { + if fd.raw() <= 2 { Ok((ChildStdio::Owned(fd.duplicate()?), None)) } else { Ok((ChildStdio::Explicit(fd.raw()), None)) @@ -471,7 +470,7 @@ impl fmt::Display for ExitStatus { /// The unique id of the process (this should never be negative). pub struct Process { - pid: pid_t, + pid: usize, status: Option, } @@ -488,7 +487,7 @@ impl Process { Err(Error::new(ErrorKind::InvalidInput, "invalid argument: can't kill an exited process")) } else { - cvt(libc::kill(self.pid, libc::SIGKILL))?; + cvt(syscall::kill(self.pid, syscall::SIGKILL))?; Ok(()) } } @@ -498,7 +497,7 @@ impl Process { return Ok(status) } let mut status = 0; - cvt(libc::waitpid(self.pid, &mut status, 0))?; + cvt(syscall::waitpid(self.pid, &mut status, 0))?; self.status = Some(ExitStatus(status as i32)); Ok(ExitStatus(status as i32)) } diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs index 50062186903..1fe7e33a35e 100644 --- a/src/libstd/sys/redox/stdio.rs +++ b/src/libstd/sys/redox/stdio.rs @@ -9,8 +9,7 @@ // except according to those terms. use io; -use libc; -use sys::cvt; +use sys::{cvt, syscall}; use sys::fd::FileDesc; pub struct Stdin(()); @@ -21,14 +20,14 @@ impl Stdin { pub fn new() -> io::Result { Ok(Stdin(())) } pub fn read(&self, data: &mut [u8]) -> io::Result { - let fd = FileDesc::new(libc::STDIN_FILENO); + let fd = FileDesc::new(0); let ret = fd.read(data); fd.into_raw(); ret } pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - let fd = FileDesc::new(libc::STDIN_FILENO); + let fd = FileDesc::new(0); let ret = fd.read_to_end(buf); fd.into_raw(); ret @@ -39,14 +38,14 @@ impl Stdout { pub fn new() -> io::Result { Ok(Stdout(())) } pub fn write(&self, data: &[u8]) -> io::Result { - let fd = FileDesc::new(libc::STDOUT_FILENO); + let fd = FileDesc::new(1); let ret = fd.write(data); fd.into_raw(); ret } pub fn flush(&self) -> io::Result<()> { - cvt(libc::fsync(libc::STDOUT_FILENO)).and(Ok(())) + cvt(syscall::fsync(1)).and(Ok(())) } } @@ -54,14 +53,14 @@ impl Stderr { pub fn new() -> io::Result { Ok(Stderr(())) } pub fn write(&self, data: &[u8]) -> io::Result { - let fd = FileDesc::new(libc::STDERR_FILENO); + let fd = FileDesc::new(2); let ret = fd.write(data); fd.into_raw(); ret } pub fn flush(&self) -> io::Result<()> { - cvt(libc::fsync(libc::STDERR_FILENO)).and(Ok(())) + cvt(syscall::fsync(2)).and(Ok(())) } } @@ -74,9 +73,9 @@ impl io::Write for Stderr { } fn flush(&mut self) -> io::Result<()> { - cvt(libc::fsync(libc::STDERR_FILENO)).and(Ok(())) + cvt(syscall::fsync(2)).and(Ok(())) } } -pub const EBADF_ERR: i32 = ::libc::EBADF; +pub const EBADF_ERR: i32 = ::sys::syscall::EBADF; pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index 46bc6346a6a..0e7b27d3961 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -9,17 +9,15 @@ // except according to those terms. use alloc::boxed::FnBox; -use cmp; use ffi::CStr; use io; -use libc; use mem; use sys_common::thread::start_thread; -use sys::cvt; +use sys::{cvt, syscall}; use time::Duration; pub struct Thread { - id: libc::pid_t, + id: usize, } // Some platforms may have pthread_t as a pointer in which case we still want @@ -31,10 +29,10 @@ impl Thread { pub unsafe fn new<'a>(_stack: usize, p: Box) -> io::Result { let p = box p; - let id = cvt(libc::clone(libc::CLONE_VM | libc::CLONE_FS | libc::CLONE_FILES))?; + let id = cvt(syscall::clone(syscall::CLONE_VM | syscall::CLONE_FS | syscall::CLONE_FILES))?; if id == 0 { start_thread(&*p as *const _ as *mut _); - let _ = libc::exit(0); + let _ = syscall::exit(0); panic!("thread failed to exit"); } else { mem::forget(p); @@ -43,7 +41,7 @@ impl Thread { } pub fn yield_now() { - let ret = unsafe { libc::sched_yield() }; + let ret = syscall::sched_yield().expect("failed to sched_yield"); debug_assert_eq!(ret, 0); } @@ -58,13 +56,13 @@ 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. 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, + let req = syscall::TimeSpec { + tv_sec: secs as i64, tv_nsec: nsecs, }; secs -= req.tv_sec as u64; - let mut rem = libc::timespec::default(); - if libc::nanosleep(&req, &mut rem).is_err() { + let mut rem = syscall::TimeSpec::default(); + if syscall::nanosleep(&req, &mut rem).is_err() { secs += rem.tv_sec as u64; nsecs = rem.tv_nsec; } else { @@ -75,12 +73,12 @@ impl Thread { pub fn join(self) { let mut status = 0; - libc::waitpid(self.id, &mut status, 0).unwrap(); + syscall::waitpid(self.id, &mut status, 0).unwrap(); } - pub fn id(&self) -> libc::pid_t { self.id } + pub fn id(&self) -> usize { self.id } - pub fn into_id(self) -> libc::pid_t { + pub fn into_id(self) -> usize { let id = self.id; mem::forget(self); id diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs index 4e1a82bcc9a..8f05e3bcfe7 100644 --- a/src/libstd/sys/redox/time.rs +++ b/src/libstd/sys/redox/time.rs @@ -10,15 +10,14 @@ use cmp::Ordering; use fmt; -use libc; -use sys::cvt; +use sys::{cvt, syscall}; use time::Duration; const NSEC_PER_SEC: u64 = 1_000_000_000; #[derive(Copy, Clone)] struct Timespec { - t: libc::timespec, + t: syscall::TimeSpec, } impl Timespec { @@ -53,8 +52,8 @@ impl Timespec { duration to time"); } Timespec { - t: libc::timespec { - tv_sec: secs as libc::time_t, + t: syscall::TimeSpec { + tv_sec: secs as i64, tv_nsec: nsec as i32, }, } @@ -73,8 +72,8 @@ impl Timespec { duration from time"); } Timespec { - t: libc::timespec { - tv_sec: secs as libc::time_t, + t: syscall::TimeSpec { + tv_sec: secs as i64, tv_nsec: nsec as i32, }, } @@ -115,7 +114,7 @@ pub struct SystemTime { pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec { - t: libc::timespec { + t: syscall::TimeSpec { tv_sec: 0, tv_nsec: 0, }, @@ -124,7 +123,7 @@ pub const UNIX_EPOCH: SystemTime = SystemTime { impl Instant { pub fn now() -> Instant { - Instant { t: now(libc::CLOCK_MONOTONIC) } + Instant { t: now(syscall::CLOCK_MONOTONIC) } } pub fn sub_instant(&self, other: &Instant) -> Duration { @@ -153,7 +152,7 @@ impl fmt::Debug for Instant { impl SystemTime { pub fn now() -> SystemTime { - SystemTime { t: now(libc::CLOCK_REALTIME) } + SystemTime { t: now(syscall::CLOCK_REALTIME) } } pub fn sub_time(&self, other: &SystemTime) @@ -170,8 +169,8 @@ impl SystemTime { } } -impl From for SystemTime { - fn from(t: libc::timespec) -> SystemTime { +impl From for SystemTime { + fn from(t: syscall::TimeSpec) -> SystemTime { SystemTime { t: Timespec { t: t } } } } @@ -189,11 +188,11 @@ pub type clock_t = usize; fn now(clock: clock_t) -> Timespec { let mut t = Timespec { - t: libc::timespec { + t: syscall::TimeSpec { tv_sec: 0, tv_nsec: 0, } }; - cvt(libc::clock_gettime(clock, &mut t.t)).unwrap(); + cvt(syscall::clock_gettime(clock, &mut t.t)).unwrap(); t } -- cgit 1.4.1-3-g733a5 From 2ec21327f25e4646ce64a2e331bb4702cf96dc99 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 28 Nov 2016 18:19:17 -0700 Subject: Switch to using Prefix::Verbatim --- src/libstd/path.rs | 8 +++----- src/libstd/sys/redox/path.rs | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 8bf9bbb1320..e38cff179c3 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -148,10 +148,6 @@ use sys::path::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix}; #[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub enum Prefix<'a> { - /// Prefix `scheme:`, where `scheme` is the component stored - #[unstable(feature="redox_prefix", issue="0")] - Scheme(&'a OsStr), - /// Prefix `\\?\`, together with the given component immediately following it. #[stable(feature = "rust1", since = "1.0.0")] Verbatim(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr), @@ -191,7 +187,9 @@ impl<'a> Prefix<'a> { os_str_as_u8_slice(s).len() } match *self { - Scheme(x) => os_str_len(x) + 1, + #[cfg(target_os = "redox")] + Verbatim(x) => 1 + os_str_len(x), + #[cfg(not(target_os = "redox"))] Verbatim(x) => 4 + os_str_len(x), VerbatimUNC(x, y) => { 8 + os_str_len(x) + diff --git a/src/libstd/sys/redox/path.rs b/src/libstd/sys/redox/path.rs index 4069a0ea726..e609f83bc07 100644 --- a/src/libstd/sys/redox/path.rs +++ b/src/libstd/sys/redox/path.rs @@ -24,7 +24,7 @@ pub fn is_verbatim_sep(b: u8) -> bool { pub fn parse_prefix(path: &OsStr) -> Option { if let Some(path_str) = path.to_str() { if let Some(i) = path_str.find(':') { - Some(Prefix::Scheme(OsStr::new(&path_str[..i]))) + Some(Prefix::Verbatim(OsStr::new(&path_str[..i]))) } else { None } -- cgit 1.4.1-3-g733a5 From 1d0bba8224686d054378bcc4e853798d56fdfecf Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 28 Nov 2016 18:25:47 -0700 Subject: Move stdout/err flush into sys --- src/libstd/io/stdio.rs | 6 ------ src/libstd/sys/redox/stdio.rs | 2 +- src/libstd/sys/unix/stdio.rs | 13 ++++++++++++- src/libstd/sys/windows/stdio.rs | 13 ++++++++++++- 4 files changed, 25 insertions(+), 9 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index f6ee0be47fa..6419a9ff683 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -81,16 +81,10 @@ impl Read for StdinRaw { } impl Write for StdoutRaw { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } - #[cfg(not(target_os = "redox"))] - fn flush(&mut self) -> io::Result<()> { Ok(()) } - #[cfg(target_os = "redox")] fn flush(&mut self) -> io::Result<()> { self.0.flush() } } impl Write for StderrRaw { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } - #[cfg(not(target_os = "redox"))] - fn flush(&mut self) -> io::Result<()> { Ok(()) } - #[cfg(target_os = "redox")] fn flush(&mut self) -> io::Result<()> { self.0.flush() } } diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs index 1fe7e33a35e..aa8329bc283 100644 --- a/src/libstd/sys/redox/stdio.rs +++ b/src/libstd/sys/redox/stdio.rs @@ -73,7 +73,7 @@ impl io::Write for Stderr { } fn flush(&mut self) -> io::Result<()> { - cvt(syscall::fsync(2)).and(Ok(())) + Stderr::flush(self) } } diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs index 273341b1918..1002c60d303 100644 --- a/src/libstd/sys/unix/stdio.rs +++ b/src/libstd/sys/unix/stdio.rs @@ -43,6 +43,10 @@ impl Stdout { fd.into_raw(); ret } + + pub fn flush(&self) -> io::Result<()> { + Ok(()) + } } impl Stderr { @@ -54,6 +58,10 @@ impl Stderr { fd.into_raw(); ret } + + pub fn flush(&self) -> io::Result<()> { + Ok(()) + } } // FIXME: right now this raw stderr handle is used in a few places because @@ -63,7 +71,10 @@ impl io::Write for Stderr { fn write(&mut self, data: &[u8]) -> io::Result { Stderr::write(self, data) } - fn flush(&mut self) -> io::Result<()> { Ok(()) } + + fn flush(&mut self) -> io::Result<()> { + Stderr::flush(self) + } } pub const EBADF_ERR: i32 = ::libc::EBADF as i32; diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index 72788776ded..0d58da29323 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -156,6 +156,10 @@ impl Stdout { pub fn write(&self, data: &[u8]) -> io::Result { write(&self.0, data) } + + pub fn flush(&self) -> io::Result<()> { + Ok(()) + } } impl Stderr { @@ -166,6 +170,10 @@ impl Stderr { pub fn write(&self, data: &[u8]) -> io::Result { write(&self.0, data) } + + pub fn flush(&self) -> io::Result<()> { + Ok(()) + } } // FIXME: right now this raw stderr handle is used in a few places because @@ -175,7 +183,10 @@ impl io::Write for Stderr { fn write(&mut self, data: &[u8]) -> io::Result { Stderr::write(self, data) } - fn flush(&mut self) -> io::Result<()> { Ok(()) } + + fn flush(&mut self) -> io::Result<()> { + Stderr::flush(self) + } } impl NoClose { -- cgit 1.4.1-3-g733a5 From 6378c77716aa66a12af0fb41abf3dc000b81c2c7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 28 Nov 2016 20:21:19 -0700 Subject: Remove file path from std::fs::File --- src/libstd/fs.rs | 10 ---------- src/libstd/sys/redox/fs.rs | 6 ++---- 2 files changed, 2 insertions(+), 14 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 0cb9a49ad67..e91e808c548 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -383,16 +383,6 @@ impl File { pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> { self.inner.set_permissions(perm.0) } - - /// 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(target_os = "redox")] - #[unstable(feature = "file_path", issue="0")] - pub fn path(&self) -> io::Result { - self.inner.path() - } } impl AsInner for File { diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index 80aec2e978d..9d5d2f5d921 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -319,10 +319,8 @@ impl File { pub fn path(&self) -> io::Result { let mut buf: [u8; 4096] = [0; 4096]; - match syscall::fpath(*self.fd().as_inner() as usize, &mut buf) { - Ok(count) => Ok(PathBuf::from(unsafe { String::from_utf8_unchecked(Vec::from(&buf[0..count])) })), - Err(err) => Err(Error::from_raw_os_error(err.errno)), - } + let count = cvt(syscall::fpath(*self.fd().as_inner() as usize, &mut buf))?; + Ok(PathBuf::from(unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) })) } pub fn fd(&self) -> &FileDesc { &self.0 } -- cgit 1.4.1-3-g733a5 From e68393397a10255ed645cb70bcedd20e5cba691d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 28 Nov 2016 21:06:42 -0700 Subject: Commit to fix make tidy --- src/libstd/sys/redox/args.rs | 2 +- src/libstd/sys/redox/backtrace.rs | 10 +++++++++ src/libstd/sys/redox/condvar.rs | 10 +++++++++ src/libstd/sys/redox/env.rs | 2 +- src/libstd/sys/redox/ext/fs.rs | 10 ++++----- src/libstd/sys/redox/ext/io.rs | 2 +- src/libstd/sys/redox/ext/mod.rs | 2 +- src/libstd/sys/redox/ext/process.rs | 2 +- src/libstd/sys/redox/fast_thread_local.rs | 2 +- src/libstd/sys/redox/fd.rs | 2 +- src/libstd/sys/redox/fs.rs | 14 ++++++++----- src/libstd/sys/redox/mod.rs | 10 +++++++++ src/libstd/sys/redox/mutex.rs | 10 +++++++++ src/libstd/sys/redox/net/dns/answer.rs | 10 +++++++++ src/libstd/sys/redox/net/dns/mod.rs | 10 +++++++++ src/libstd/sys/redox/net/dns/query.rs | 10 +++++++++ src/libstd/sys/redox/net/mod.rs | 35 ++++++++++++++++++++++++------- src/libstd/sys/redox/net/tcp.rs | 10 +++++++++ src/libstd/sys/redox/net/udp.rs | 10 +++++++++ src/libstd/sys/redox/os.rs | 2 +- src/libstd/sys/redox/os_str.rs | 2 +- src/libstd/sys/redox/path.rs | 2 +- src/libstd/sys/redox/pipe.rs | 10 ++++----- src/libstd/sys/redox/process.rs | 2 +- src/libstd/sys/redox/rand.rs | 2 +- src/libstd/sys/redox/rwlock.rs | 2 +- src/libstd/sys/redox/stack_overflow.rs | 4 ++-- src/libstd/sys/redox/stdio.rs | 2 +- src/libstd/sys/redox/thread.rs | 2 +- src/libstd/sys/redox/thread_local.rs | 2 +- src/libstd/sys/redox/time.rs | 2 +- src/libstd/sys/unix/stdio.rs | 2 +- src/libstd/sys/windows/stdio.rs | 2 +- 33 files changed, 157 insertions(+), 44 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/args.rs b/src/libstd/sys/redox/args.rs index 52ba030e7c6..f6fea2f1076 100644 --- a/src/libstd/sys/redox/args.rs +++ b/src/libstd/sys/redox/args.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/backtrace.rs b/src/libstd/sys/redox/backtrace.rs index 63e427694ae..6f53841502a 100644 --- a/src/libstd/sys/redox/backtrace.rs +++ b/src/libstd/sys/redox/backtrace.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use libc; use io; use sys_common::backtrace::output; diff --git a/src/libstd/sys/redox/condvar.rs b/src/libstd/sys/redox/condvar.rs index 7e26162efbc..0ca0987b245 100644 --- a/src/libstd/sys/redox/condvar.rs +++ b/src/libstd/sys/redox/condvar.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use cell::UnsafeCell; use intrinsics::{atomic_cxchg, atomic_xadd, atomic_xchg}; use ptr; diff --git a/src/libstd/sys/redox/env.rs b/src/libstd/sys/redox/env.rs index 51fd2d07973..669b7520df8 100644 --- a/src/libstd/sys/redox/env.rs +++ b/src/libstd/sys/redox/env.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs index d292b438724..b4e220971fd 100644 --- a/src/libstd/sys/redox/ext/fs.rs +++ b/src/libstd/sys/redox/ext/fs.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -235,10 +235,10 @@ pub trait FileTypeExt { #[stable(feature = "file_type_ext", since = "1.5.0")] impl FileTypeExt for fs::FileType { - fn is_block_device(&self) -> bool { false /*TODO*/ } - fn is_char_device(&self) -> bool { false /*TODO*/ } - fn is_fifo(&self) -> bool { false /*TODO*/ } - fn is_socket(&self) -> bool { false /*TODO*/ } + fn is_block_device(&self) -> bool { false /*FIXME: Implement block device mode*/ } + fn is_char_device(&self) -> bool { false /*FIXME: Implement char device mode*/ } + fn is_fifo(&self) -> bool { false /*FIXME: Implement fifo mode*/ } + fn is_socket(&self) -> bool { false /*FIXME: Implement socket mode*/ } } /// Creates a new symbolic link on the filesystem. diff --git a/src/libstd/sys/redox/ext/io.rs b/src/libstd/sys/redox/ext/io.rs index 4f39f3b4f33..135e31fae1e 100644 --- a/src/libstd/sys/redox/ext/io.rs +++ b/src/libstd/sys/redox/ext/io.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/ext/mod.rs b/src/libstd/sys/redox/ext/mod.rs index 02edfa84aa0..513ef272e97 100644 --- a/src/libstd/sys/redox/ext/mod.rs +++ b/src/libstd/sys/redox/ext/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/ext/process.rs b/src/libstd/sys/redox/ext/process.rs index 3a7c59d4e6d..1472242d3db 100644 --- a/src/libstd/sys/redox/ext/process.rs +++ b/src/libstd/sys/redox/ext/process.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs index e0a17730846..6eeae2d90ea 100644 --- a/src/libstd/sys/redox/fast_thread_local.rs +++ b/src/libstd/sys/redox/fast_thread_local.rs @@ -1,4 +1,4 @@ -// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs index 4c8e62d1863..b6de68a9dc1 100644 --- a/src/libstd/sys/redox/fd.rs +++ b/src/libstd/sys/redox/fd.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index 9d5d2f5d921..e3bd77f4009 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -1,4 +1,4 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -118,9 +118,11 @@ impl FilePermissions { impl FileType { pub fn is_dir(&self) -> bool { self.is(syscall::MODE_DIR) } pub fn is_file(&self) -> bool { self.is(syscall::MODE_FILE) } - pub fn is_symlink(&self) -> bool { false } + pub fn is_symlink(&self) -> bool { false /*FIXME: Implement symlink mode*/ } - pub fn is(&self, mode: u16) -> bool { self.mode & (syscall::MODE_DIR | syscall::MODE_FILE) == mode } + pub fn is(&self, mode: u16) -> bool { + self.mode & (syscall::MODE_DIR | syscall::MODE_FILE) == mode + } } impl FromInner for FilePermissions { @@ -334,7 +336,8 @@ impl DirBuilder { } pub fn mkdir(&self, p: &Path) -> io::Result<()> { - let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_CREAT | syscall::O_DIRECTORY | syscall::O_EXCL | (self.mode as usize & 0o777)))?; + let flags = syscall::O_CREAT | syscall::O_DIRECTORY | syscall::O_EXCL; + let fd = cvt(syscall::open(p.to_str().unwrap(), flags | (self.mode as usize & 0o777)))?; let _ = syscall::close(fd); Ok(()) } @@ -369,7 +372,8 @@ impl fmt::Debug for File { pub fn readdir(p: &Path) -> io::Result { let root = Arc::new(p.to_path_buf()); - let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_CLOEXEC | syscall::O_RDONLY | syscall::O_DIRECTORY))?; + let flags = syscall::O_CLOEXEC | syscall::O_RDONLY | syscall::O_DIRECTORY; + let fd = cvt(syscall::open(p.to_str().unwrap(), flags))?; let file = FileDesc::new(fd); let mut data = Vec::new(); file.read_to_end(&mut data)?; diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index 07ead22b7a8..96efa27c0d3 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #![allow(dead_code, missing_docs, bad_style)] pub extern crate syscall; diff --git a/src/libstd/sys/redox/mutex.rs b/src/libstd/sys/redox/mutex.rs index 42424da858f..a995f597fc4 100644 --- a/src/libstd/sys/redox/mutex.rs +++ b/src/libstd/sys/redox/mutex.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use cell::UnsafeCell; use intrinsics::{atomic_cxchg, atomic_xchg}; use ptr; diff --git a/src/libstd/sys/redox/net/dns/answer.rs b/src/libstd/sys/redox/net/dns/answer.rs index c0450c11ed6..8e6aaeb0293 100644 --- a/src/libstd/sys/redox/net/dns/answer.rs +++ b/src/libstd/sys/redox/net/dns/answer.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use string::String; use vec::Vec; diff --git a/src/libstd/sys/redox/net/dns/mod.rs b/src/libstd/sys/redox/net/dns/mod.rs index 4397b71b939..43c4fe7ac9d 100644 --- a/src/libstd/sys/redox/net/dns/mod.rs +++ b/src/libstd/sys/redox/net/dns/mod.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + pub use self::answer::DnsAnswer; pub use self::query::DnsQuery; diff --git a/src/libstd/sys/redox/net/dns/query.rs b/src/libstd/sys/redox/net/dns/query.rs index dcb554d82de..b0dcdcb624a 100644 --- a/src/libstd/sys/redox/net/dns/query.rs +++ b/src/libstd/sys/redox/net/dns/query.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use string::String; #[derive(Clone, Debug)] diff --git a/src/libstd/sys/redox/net/mod.rs b/src/libstd/sys/redox/net/mod.rs index 92c7d72887b..334c5e51c39 100644 --- a/src/libstd/sys/redox/net/mod.rs +++ b/src/libstd/sys/redox/net/mod.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use fs::File; use io::{Error, Result, Read}; use iter::Iterator; @@ -30,14 +40,17 @@ impl Iterator for LookupHost { pub fn lookup_host(host: &str) -> Result { let mut ip_string = String::new(); File::open("/etc/net/ip")?.read_to_string(&mut ip_string)?; - let ip: Vec = ip_string.trim().split(".").map(|part| part.parse::().unwrap_or(0)).collect(); + let ip: Vec = ip_string.trim().split(".").map(|part| part.parse::() + .unwrap_or(0)).collect(); let mut dns_string = String::new(); File::open("/etc/net/dns")?.read_to_string(&mut dns_string)?; - let dns: Vec = dns_string.trim().split(".").map(|part| part.parse::().unwrap_or(0)).collect(); + let dns: Vec = dns_string.trim().split(".").map(|part| part.parse::() + .unwrap_or(0)).collect(); if ip.len() == 4 && dns.len() == 4 { - let tid = (time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap().subsec_nanos() >> 16) as u16; + let time = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap(); + let tid = (time.subsec_nanos() >> 16) as u16; let packet = Dns { transaction_id: tid, @@ -52,8 +65,10 @@ pub fn lookup_host(host: &str) -> Result { let packet_data = packet.compile(); - let socket = UdpSocket::bind(&SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]), 0)))?; - socket.connect(&SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(dns[0], dns[1], dns[2], dns[3]), 53)))?; + let my_ip = Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]); + let dns_ip = Ipv4Addr::new(dns[0], dns[1], dns[2], dns[3]); + let socket = UdpSocket::bind(&SocketAddr::V4(SocketAddrV4::new(my_ip, 0)))?; + socket.connect(&SocketAddr::V4(SocketAddrV4::new(dns_ip, 53)))?; socket.send(&packet_data)?; let mut buf = [0; 65536]; @@ -63,8 +78,14 @@ pub fn lookup_host(host: &str) -> Result { Ok(response) => { let mut addrs = vec![]; for answer in response.answers.iter() { - if answer.a_type == 0x0001 && answer.a_class == 0x0001 && answer.data.len() == 4 { - addrs.push(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(answer.data[0], answer.data[1], answer.data[2], answer.data[3]), 0))); + if answer.a_type == 0x0001 && answer.a_class == 0x0001 + && answer.data.len() == 4 + { + let answer_ip = Ipv4Addr::new(answer.data[0], + answer.data[1], + answer.data[2], + answer.data[3]); + addrs.push(SocketAddr::V4(SocketAddrV4::new(answer_ip, 0))); } } Ok(LookupHost(addrs.into_iter())) diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs index ceaa5df267f..1bfec2e861a 100644 --- a/src/libstd/sys/redox/net/tcp.rs +++ b/src/libstd/sys/redox/net/tcp.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use io::{Error, ErrorKind, Result}; use net::{SocketAddr, Shutdown}; use path::Path; diff --git a/src/libstd/sys/redox/net/udp.rs b/src/libstd/sys/redox/net/udp.rs index 7856de033eb..b81508e8f0d 100644 --- a/src/libstd/sys/redox/net/udp.rs +++ b/src/libstd/sys/redox/net/udp.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use cell::UnsafeCell; use io::{Error, ErrorKind, Result}; use net::{SocketAddr, Ipv4Addr, Ipv6Addr}; diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs index 9ebbae4199b..15fb0cf2111 100644 --- a/src/libstd/sys/redox/os.rs +++ b/src/libstd/sys/redox/os.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs index 5a733c0cb87..8922bf04f56 100644 --- a/src/libstd/sys/redox/os_str.rs +++ b/src/libstd/sys/redox/os_str.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/path.rs b/src/libstd/sys/redox/path.rs index e609f83bc07..c896a39109a 100644 --- a/src/libstd/sys/redox/path.rs +++ b/src/libstd/sys/redox/path.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs index 7f192bef495..e7240fbe7bf 100644 --- a/src/libstd/sys/redox/pipe.rs +++ b/src/libstd/sys/redox/pipe.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -9,7 +9,7 @@ // except according to those terms. use io; -use sys::syscall; +use sys::{cvt, syscall}; use sys::fd::FileDesc; //////////////////////////////////////////////////////////////////////////////// @@ -20,9 +20,7 @@ pub struct AnonPipe(FileDesc); pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { let mut fds = [0; 2]; - - syscall::pipe2(&mut fds, syscall::O_CLOEXEC).map_err(|err| io::Error::from_raw_os_error(err.errno))?; - + cvt(syscall::pipe2(&mut fds, syscall::O_CLOEXEC))?; Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1])))) } @@ -52,7 +50,7 @@ pub fn read2(p1: AnonPipe, v1: &mut Vec, p2: AnonPipe, v2: &mut Vec) -> io::Result<()> { - //TODO: Use event based I/O multiplexing + //FIXME: Use event based I/O multiplexing //unimplemented!() p1.read_to_end(v1)?; diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 3c0d9691328..849f51013e6 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -1,4 +1,4 @@ -// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/rand.rs b/src/libstd/sys/redox/rand.rs index 7d2df6bf957..d7e4d09a9d6 100644 --- a/src/libstd/sys/redox/rand.rs +++ b/src/libstd/sys/redox/rand.rs @@ -1,4 +1,4 @@ -// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/rwlock.rs b/src/libstd/sys/redox/rwlock.rs index c752fa50ea9..d74b614ba47 100644 --- a/src/libstd/sys/redox/rwlock.rs +++ b/src/libstd/sys/redox/rwlock.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/stack_overflow.rs b/src/libstd/sys/redox/stack_overflow.rs index 92846bfe0c8..760fe06c57f 100644 --- a/src/libstd/sys/redox/stack_overflow.rs +++ b/src/libstd/sys/redox/stack_overflow.rs @@ -1,4 +1,4 @@ -// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -23,5 +23,5 @@ pub unsafe fn init() { } pub unsafe fn cleanup() { - + } diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs index aa8329bc283..607eef051d6 100644 --- a/src/libstd/sys/redox/stdio.rs +++ b/src/libstd/sys/redox/stdio.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs index 0e7b27d3961..b2c0e285f06 100644 --- a/src/libstd/sys/redox/thread.rs +++ b/src/libstd/sys/redox/thread.rs @@ -1,4 +1,4 @@ -// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/thread_local.rs b/src/libstd/sys/redox/thread_local.rs index 43b0bf09a6f..abdd9ace795 100644 --- a/src/libstd/sys/redox/thread_local.rs +++ b/src/libstd/sys/redox/thread_local.rs @@ -1,4 +1,4 @@ -// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs index 8f05e3bcfe7..dea406efe6c 100644 --- a/src/libstd/sys/redox/time.rs +++ b/src/libstd/sys/redox/time.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs index 1002c60d303..6d38b00b39e 100644 --- a/src/libstd/sys/unix/stdio.rs +++ b/src/libstd/sys/unix/stdio.rs @@ -71,7 +71,7 @@ impl io::Write for Stderr { fn write(&mut self, data: &[u8]) -> io::Result { Stderr::write(self, data) } - + fn flush(&mut self) -> io::Result<()> { Stderr::flush(self) } diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index 0d58da29323..a74e7699ba0 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -183,7 +183,7 @@ impl io::Write for Stderr { fn write(&mut self, data: &[u8]) -> io::Result { Stderr::write(self, data) } - + fn flush(&mut self) -> io::Result<()> { Stderr::flush(self) } -- cgit 1.4.1-3-g733a5 From 729442206cda26e1a6d03f545a872389b2139606 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 30 Nov 2016 21:50:17 -0700 Subject: Cleanup env --- src/libstd/sys/redox/os.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs index 15fb0cf2111..135e972bca4 100644 --- a/src/libstd/sys/redox/os.rs +++ b/src/libstd/sys/redox/os.rs @@ -144,10 +144,11 @@ pub fn env() -> Env { let mut string = String::new(); if file.read_to_string(&mut string).is_ok() { for line in string.lines() { - if let Some(equal_sign) = line.chars().position(|c| c == '=') { - let name = line.chars().take(equal_sign).collect::(); - let value = line.chars().skip(equal_sign+1).collect::(); - variables.push((OsString::from(name), OsString::from(value))); + let mut parts = line.splitn(2, '='); + if let Some(name) = parts.next() { + let value = parts.next().unwrap_or(""); + variables.push((OsString::from(name.to_string()), + OsString::from(value.to_string()))); } } } -- cgit 1.4.1-3-g733a5 From 9976f5f7c551edb557b0f4633dfcd772cf040a2b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Dec 2016 16:20:53 -0800 Subject: Add missing doc examples for SocketAddr struct --- src/libstd/sys/unix/ext/net.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 80f53da1cef..47a803424b5 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -85,6 +85,21 @@ enum AddressKind<'a> { } /// An address associated with a Unix socket. +/// +/// # Examples +/// +/// ``` +/// use std::os::unix::net::UnixListener; +/// +/// let socket = match UnixListener::bind("/tmp/sock") { +/// Ok(sock) => sock, +/// Err(e) => { +/// println!("Couldn't bind: {:?}", e); +/// return +/// } +/// }; +/// let addr = socket.local_addr().expect("Couldn't get local address"); +/// ``` #[derive(Clone)] #[stable(feature = "unix_socket", since = "1.10.0")] pub struct SocketAddr { @@ -121,6 +136,16 @@ impl SocketAddr { } /// Returns true if and only if the address is unnamed. + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixListener; + /// + /// let socket = match UnixListener::bind("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.is_unnamed(), false); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn is_unnamed(&self) -> bool { if let AddressKind::Unnamed = self.address() { @@ -131,6 +156,17 @@ impl SocketAddr { } /// Returns the contents of this address if it is a `pathname` address. + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixListener; + /// use std::path::Path; + /// + /// let socket = match UnixListener::bind("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn as_pathname(&self) -> Option<&Path> { if let AddressKind::Pathname(path) = self.address() { -- cgit 1.4.1-3-g733a5 From 7fe17f96d5acf5753e05414748cf3e1f63371c81 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Dec 2016 18:09:39 -0800 Subject: Add doc examples for UnixStream --- src/libstd/sys/unix/ext/net.rs | 151 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 145 insertions(+), 6 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 47a803424b5..69954d91857 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -218,7 +218,7 @@ impl<'a> fmt::Display for AsciiEscaped<'a> { /// /// # Examples /// -/// ```rust,no_run +/// ```no_run /// use std::os::unix::net::UnixStream; /// use std::io::prelude::*; /// @@ -248,6 +248,20 @@ impl fmt::Debug for UnixStream { impl UnixStream { /// Connects to the socket named by `path`. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn connect>(path: P) -> io::Result { fn inner(path: &Path) -> io::Result { @@ -265,6 +279,20 @@ impl UnixStream { /// Creates an unnamed pair of connected sockets. /// /// Returns two `UnixStream`s which are connected to each other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let (sock1, sock2) = match UnixStream::pair() { + /// Ok((sock1, sock2)) => (sock1, sock2), + /// Err(e) => { + /// println!("Couldn't create a pair of sockets: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn pair() -> io::Result<(UnixStream, UnixStream)> { let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?; @@ -277,18 +305,45 @@ impl UnixStream { /// object references. Both handles will read and write the same stream of /// data, and options set on one stream will be propogated to the other /// stream. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let sock_copy = socket.try_clone().expect("Couldn't clone socket..."); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixStream) } /// Returns the socket address of the local half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) } /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let addr = socket.peer_addr().expect("Couldn't get peer address"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn peer_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) @@ -296,9 +351,23 @@ impl UnixStream { /// Sets the read timeout for the socket. /// - /// If the provided value is `None`, then `read` calls will block - /// indefinitely. It is an error to pass the zero `Duration` to this + /// If the provided value is [`None`], then [`read()`] calls will block + /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`read()`]: ../../std/io/trait.Read.html#tymethod.read + /// [`Duration`]: ../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_RCVTIMEO) @@ -306,33 +375,91 @@ impl UnixStream { /// Sets the write timeout for the socket. /// - /// If the provided value is `None`, then `write` calls will block - /// indefinitely. It is an error to pass the zero `Duration` to this + /// If the provided value is [`None`], then [`write()`] calls will block + /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`read()`]: ../../std/io/trait.Write.html#tymethod.write + /// [`Duration`]: ../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_SNDTIMEO) } /// Returns the read timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn read_timeout(&self) -> io::Result> { self.0.timeout(libc::SO_RCVTIMEO) } /// Returns the write timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); + /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn write_timeout(&self) -> io::Result> { self.0.timeout(libc::SO_SNDTIMEO) } /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_nonblocking(true).expect("Couldn't set non blocking"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// if let Ok(Some(err)) = socket.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result> { self.0.take_error() @@ -342,7 +469,19 @@ impl UnixStream { /// /// This function will cause all pending and future I/O calls on the /// specified portions to immediately return with an appropriate value - /// (see the documentation of `Shutdown`). + /// (see the documentation of [`Shutdown`]). + /// + /// [`Shutdown`]: ../../std/net/enum.Shutdown.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixStream; + /// use std::time::Duration; + /// + /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.0.shutdown(how) -- cgit 1.4.1-3-g733a5 From c35b9f6703e11e08d5250434472b36a109353cc3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Dec 2016 18:26:54 -0800 Subject: Add UnixListener doc examples --- src/libstd/sys/unix/ext/net.rs | 111 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 10 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 69954d91857..f346e3eb44f 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -437,7 +437,6 @@ impl UnixStream { /// /// ```no_run /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; /// /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_nonblocking(true).expect("Couldn't set non blocking"); @@ -453,7 +452,6 @@ impl UnixStream { /// /// ```no_run /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; /// /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); /// if let Ok(Some(err)) = socket.take_error() { @@ -477,7 +475,6 @@ impl UnixStream { /// /// ```no_run /// use std::os::unix::net::UnixStream; - /// use std::time::Duration; /// /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); @@ -557,7 +554,7 @@ impl IntoRawFd for UnixStream { /// /// # Examples /// -/// ```rust,no_run +/// ```no_run /// use std::thread; /// use std::os::unix::net::{UnixStream, UnixListener}; /// @@ -580,9 +577,6 @@ impl IntoRawFd for UnixStream { /// } /// } /// } -/// -/// // close the listener socket -/// drop(listener); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixListener(Socket); @@ -601,6 +595,20 @@ impl fmt::Debug for UnixListener { impl UnixListener { /// Creates a new `UnixListener` bound to the specified socket. + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixListener; + /// + /// let listener = match UnixListener::bind("/path/to/the/socket") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn bind>(path: P) -> io::Result { fn inner(path: &Path) -> io::Result { @@ -620,8 +628,23 @@ impl UnixListener { /// Accepts a new incoming connection to this listener. /// /// This function will block the calling thread until a new Unix connection - /// is established. When established, the corersponding `UnixStream` and + /// is established. When established, the corersponding [`UnixStream`] and /// the remote peer's address will be returned. + /// + /// [`UnixStream`]: ../../std/os/unix/net/struct.UnixStream.html + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// match listener.accept() { + /// Ok((socket, addr)) => println!("Got a client: {:?}", addr), + /// Err(e) => println!("accept function failed: {:?}", e), + /// } + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() }; @@ -636,24 +659,65 @@ impl UnixListener { /// The returned `UnixListener` is a reference to the same socket that this /// object references. Both handles can be used to accept incoming /// connections and options set on one listener will affect the other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// let listener_copy = listener.try_clone().expect("try_clone failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixListener) } /// Returns the local socket address of this listener. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) } /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// socket.set_nonblocking(true).expect("Couldn't set non blocking"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixListener; + /// + /// let socket = match UnixListener::bind("/tmp/sock").unwrap(); + /// if let Ok(Some(err)) = socket.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result> { self.0.take_error() @@ -661,8 +725,35 @@ impl UnixListener { /// Returns an iterator over incoming connections. /// - /// The iterator will never return `None` and will also not yield the - /// peer's `SocketAddr` structure. + /// The iterator will never return [`None`] and will also not yield the + /// peer's [`SocketAddr`] structure. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`SocketAddr`]: struct.SocketAddr.html + /// + /// # Examples + /// + /// ```no_run + /// use std::thread; + /// use std::os::unix::net::{UnixStream, UnixListener}; + /// + /// fn handle_client(stream: UnixStream) { + /// // ... + /// } + /// + /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); + /// + /// for stream in listener.incoming() { + /// match stream { + /// Ok(stream) => { + /// thread::spawn(|| handle_client(stream)); + /// } + /// Err(err) => { + /// break; + /// } + /// } + /// } + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn incoming<'a>(&'a self) -> Incoming<'a> { Incoming { listener: self } -- cgit 1.4.1-3-g733a5 From a78a33c52a3a4766e170a8dbe0328cbbd03d4f14 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Dec 2016 18:28:07 -0800 Subject: Add Incoming doc examples --- src/libstd/sys/unix/ext/net.rs | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index f346e3eb44f..d49f9343b0e 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -791,9 +791,36 @@ impl<'a> IntoIterator for &'a UnixListener { } } -/// An iterator over incoming connections to a `UnixListener`. +/// An iterator over incoming connections to a [`UnixListener`]. /// -/// It will never return `None`. +/// It will never return [`None`]. +/// +/// [`None`]: ../../std/option/enum.Option.html#variant.None +/// [`UnixListener`]: struct.UnixListener.html +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// use std::os::unix::net::{UnixStream, UnixListener}; +/// +/// fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); +/// +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// break; +/// } +/// } +/// } +/// ``` #[derive(Debug)] #[stable(feature = "unix_socket", since = "1.10.0")] pub struct Incoming<'a> { @@ -817,7 +844,7 @@ impl<'a> Iterator for Incoming<'a> { /// /// # Examples /// -/// ```rust,no_run +/// ```no_run /// use std::os::unix::net::UnixDatagram; /// /// let socket = UnixDatagram::bind("/path/to/my/socket").unwrap(); -- cgit 1.4.1-3-g733a5 From f9bca00469f4e6826c79638a5058c838ab4c1925 Mon Sep 17 00:00:00 2001 From: Elahn Ientile Date: Sat, 10 Dec 2016 09:46:47 +1000 Subject: Ctrl-Z returns from Stdin.read() when reading from the console on Windows. Fixes #19914. Fixes read(), read_to_string(), read_to_end(), etc. --- src/libstd/sys/windows/c.rs | 13 +++++++++++-- src/libstd/sys/windows/stdio.rs | 24 ++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 4 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 1a563127f7f..6ac3e08f908 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -819,6 +819,16 @@ pub enum EXCEPTION_DISPOSITION { ExceptionCollidedUnwind } +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CONSOLE_READCONSOLE_CONTROL { + pub nLength: ULONG, + pub nInitialChars: ULONG, + pub dwCtrlWakeupMask: ULONG, + pub dwControlKeyState: ULONG, +} +pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL; + #[link(name = "ws2_32")] #[link(name = "userenv")] #[link(name = "shell32")] @@ -849,12 +859,11 @@ extern "system" { pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION); pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION); - // FIXME - pInputControl should be PCONSOLE_READCONSOLE_CONTROL pub fn ReadConsoleW(hConsoleInput: HANDLE, lpBuffer: LPVOID, nNumberOfCharsToRead: DWORD, lpNumberOfCharsRead: LPDWORD, - pInputControl: LPVOID) -> BOOL; + pInputControl: PCONSOLE_READCONSOLE_CONTROL) -> BOOL; pub fn WriteConsoleW(hConsoleOutput: HANDLE, lpBuffer: LPCVOID, diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index 72788776ded..e4335b9d0bb 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -111,19 +111,27 @@ impl Stdin { if utf8.position() as usize == utf8.get_ref().len() { let mut utf16 = vec![0u16; 0x1000]; let mut num = 0; + let mut input_control = readconsole_input_control(CTRL_Z_MASK); cvt(unsafe { c::ReadConsoleW(handle, utf16.as_mut_ptr() as c::LPVOID, utf16.len() as u32, &mut num, - ptr::null_mut()) + &mut input_control as c::PCONSOLE_READCONSOLE_CONTROL) })?; utf16.truncate(num as usize); // FIXME: what to do about this data that has already been read? - let data = match String::from_utf16(&utf16) { + let mut data = match String::from_utf16(&utf16) { Ok(utf8) => utf8.into_bytes(), Err(..) => return Err(invalid_encoding()), }; + if let Output::Console(_) = self.handle { + if let Some(&last_byte) = data.last() { + if last_byte == CTRL_Z { + data.pop(); + } + } + } *utf8 = Cursor::new(data); } @@ -206,6 +214,18 @@ fn invalid_encoding() -> io::Error { io::Error::new(io::ErrorKind::InvalidData, "text was not valid unicode") } +fn readconsole_input_control(wakeup_mask: c::ULONG) -> c::CONSOLE_READCONSOLE_CONTROL { + c::CONSOLE_READCONSOLE_CONTROL { + nLength: ::mem::size_of::() as c::ULONG, + nInitialChars: 0, + dwCtrlWakeupMask: wakeup_mask, + dwControlKeyState: 0, + } +} + +const CTRL_Z: u8 = 0x1A; +const CTRL_Z_MASK: c::ULONG = 0x4000000; //1 << 0x1A + pub const EBADF_ERR: i32 = ::sys::c::ERROR_INVALID_HANDLE as i32; // The default buffer capacity is 64k, but apparently windows // doesn't like 64k reads on stdin. See #13304 for details, but the -- cgit 1.4.1-3-g733a5 From 056ebccee3d9587623fab9a9b2e72796c95142b4 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 12 Dec 2016 14:21:44 -0700 Subject: Rollback prefix --- src/libstd/path.rs | 7 +------ src/libstd/sys/redox/path.rs | 6 +++--- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/path.rs b/src/libstd/path.rs index e38cff179c3..95c8af66425 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -136,9 +136,7 @@ use sys::path::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix}; // Windows Prefixes //////////////////////////////////////////////////////////////////////////////// -/// Path prefixes (Redox and Windows only). -/// -/// Redox uses schemes like `scheme:reference` to identify different I/O systems +/// Path prefixes (Windows only). /// /// Windows uses a variety of path styles, including references to drive /// volumes (like `C:`), network shared folders (like `\\server\share`) and @@ -187,9 +185,6 @@ impl<'a> Prefix<'a> { os_str_as_u8_slice(s).len() } match *self { - #[cfg(target_os = "redox")] - Verbatim(x) => 1 + os_str_len(x), - #[cfg(not(target_os = "redox"))] Verbatim(x) => 4 + os_str_len(x), VerbatimUNC(x, y) => { 8 + os_str_len(x) + diff --git a/src/libstd/sys/redox/path.rs b/src/libstd/sys/redox/path.rs index c896a39109a..bef10011887 100644 --- a/src/libstd/sys/redox/path.rs +++ b/src/libstd/sys/redox/path.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use path::Prefix; use ffi::OsStr; #[inline] @@ -23,8 +22,9 @@ pub fn is_verbatim_sep(b: u8) -> bool { pub fn parse_prefix(path: &OsStr) -> Option { if let Some(path_str) = path.to_str() { - if let Some(i) = path_str.find(':') { - Some(Prefix::Verbatim(OsStr::new(&path_str[..i]))) + if let Some(_i) = path_str.find(':') { + //TODO: Redox specific prefix Some(Prefix::Verbatim(OsStr::new(&path_str[..i]))) + None } else { None } -- cgit 1.4.1-3-g733a5 From c61baa0fc7a85bd2bcce34aac05ed739261cf037 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 12 Dec 2016 14:30:41 -0700 Subject: Fix accidental removal of import --- src/libstd/sys/redox/path.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/path.rs b/src/libstd/sys/redox/path.rs index bef10011887..dabec1acacd 100644 --- a/src/libstd/sys/redox/path.rs +++ b/src/libstd/sys/redox/path.rs @@ -9,6 +9,7 @@ // except according to those terms. use ffi::OsStr; +use path::Prefix; #[inline] pub fn is_sep_byte(b: u8) -> bool { -- cgit 1.4.1-3-g733a5 From daaa23187624543189e58fda5e5893c76252ff0a Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 12 Dec 2016 15:57:19 -0700 Subject: Fix tidy checks --- src/libstd/sys/redox/path.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/path.rs b/src/libstd/sys/redox/path.rs index dabec1acacd..e6a267dd5d9 100644 --- a/src/libstd/sys/redox/path.rs +++ b/src/libstd/sys/redox/path.rs @@ -24,7 +24,8 @@ pub fn is_verbatim_sep(b: u8) -> bool { pub fn parse_prefix(path: &OsStr) -> Option { if let Some(path_str) = path.to_str() { if let Some(_i) = path_str.find(':') { - //TODO: Redox specific prefix Some(Prefix::Verbatim(OsStr::new(&path_str[..i]))) + // FIXME: Redox specific prefix + // Some(Prefix::Verbatim(OsStr::new(&path_str[..i]))) None } else { None -- cgit 1.4.1-3-g733a5 From df26a5a9587c5fd922163d2b7625588fa97912cc Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Wed, 14 Dec 2016 11:35:05 -0800 Subject: Stabilize std::os::*::fs::FileExt --- src/libstd/sys/unix/ext/fs.rs | 8 ++++---- src/libstd/sys/unix/ext/mod.rs | 2 +- src/libstd/sys/windows/ext/fs.rs | 8 ++++---- src/libstd/sys/windows/ext/mod.rs | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index fcfab051588..900f463fa83 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -21,7 +21,7 @@ use sys_common::{FromInner, AsInner, AsInnerMut}; use sys::platform::fs::MetadataExt as UnixMetadataExt; /// Unix-specific extensions to `File` -#[unstable(feature = "file_offset", issue = "35918")] +#[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { /// Reads a number of bytes starting from a given offset. /// @@ -34,7 +34,7 @@ pub trait FileExt { /// /// Note that similar to `File::read`, it is not an error to return with a /// short read. - #[unstable(feature = "file_offset", issue = "35918")] + #[stable(feature = "file_offset", since = "1.15.0")] fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result; /// Writes a number of bytes starting from a given offset. @@ -51,11 +51,11 @@ pub trait FileExt { /// /// Note that similar to `File::write`, it is not an error to return a /// short write. - #[unstable(feature = "file_offset", issue = "35918")] + #[stable(feature = "file_offset", since = "1.15.0")] fn write_at(&self, buf: &[u8], offset: u64) -> io::Result; } -#[unstable(feature = "file_offset", issue = "35918")] +#[stable(feature = "file_offset", since = "1.15.0")] impl FileExt for fs::File { fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { self.as_inner().read_at(buf, offset) diff --git a/src/libstd/sys/unix/ext/mod.rs b/src/libstd/sys/unix/ext/mod.rs index b2483f4e209..1be9f11b92c 100644 --- a/src/libstd/sys/unix/ext/mod.rs +++ b/src/libstd/sys/unix/ext/mod.rs @@ -50,7 +50,7 @@ pub mod prelude { pub use super::fs::{PermissionsExt, OpenOptionsExt, MetadataExt, FileTypeExt}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use super::fs::DirEntryExt; - #[doc(no_inline)] #[unstable(feature = "file_offset", issue = "35918")] + #[doc(no_inline)] #[stable(feature = "file_offset", since = "1.15.0")] pub use super::fs::FileExt; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use super::thread::JoinHandleExt; diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index 1e2b8bf38fa..7fc04ad69d6 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -19,7 +19,7 @@ use sys; use sys_common::{AsInnerMut, AsInner}; /// Windows-specific extensions to `File` -#[unstable(feature = "file_offset", issue = "35918")] +#[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { /// Seeks to a given position and reads a number of bytes. /// @@ -35,7 +35,7 @@ pub trait FileExt { /// Note that similar to `File::read`, it is not an error to return with a /// short read. When returning from such a short read, the file pointer is /// still updated. - #[unstable(feature = "file_offset", issue = "35918")] + #[stable(feature = "file_offset", since = "1.15.0")] fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result; /// Seeks to a given position and writes a number of bytes. @@ -52,11 +52,11 @@ pub trait FileExt { /// Note that similar to `File::write`, it is not an error to return a /// short write. When returning from such a short write, the file pointer /// is still updated. - #[unstable(feature = "file_offset", issue = "35918")] + #[stable(feature = "file_offset", since = "1.15.0")] fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result; } -#[unstable(feature = "file_offset", issue = "35918")] +#[stable(feature = "file_offset", since = "1.15.0")] impl FileExt for fs::File { fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result { self.as_inner().read_at(buf, offset) diff --git a/src/libstd/sys/windows/ext/mod.rs b/src/libstd/sys/windows/ext/mod.rs index 932bb5e9564..f12e50cc923 100644 --- a/src/libstd/sys/windows/ext/mod.rs +++ b/src/libstd/sys/windows/ext/mod.rs @@ -36,6 +36,6 @@ pub mod prelude { pub use super::ffi::{OsStrExt, OsStringExt}; #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use super::fs::{OpenOptionsExt, MetadataExt}; - #[doc(no_inline)] #[unstable(feature = "file_offset", issue = "35918")] + #[doc(no_inline)] #[stable(feature = "file_offset", since = "1.15.0")] pub use super::fs::FileExt; } -- cgit 1.4.1-3-g733a5 From 65b144c964987970974742526ad5985d53f19da9 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Wed, 14 Dec 2016 12:22:15 -0800 Subject: Stabilize std::os::unix::process::CommandExt::before_exec --- src/libstd/sys/unix/ext/process.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs index 3a7c59d4e6d..585dcbb9a34 100644 --- a/src/libstd/sys/unix/ext/process.rs +++ b/src/libstd/sys/unix/ext/process.rs @@ -56,7 +56,7 @@ pub trait CommandExt { /// When this closure is run, aspects such as the stdio file descriptors and /// working directory have successfully been changed, so output to these /// locations may not appear where intended. - #[unstable(feature = "process_exec", issue = "31398")] + #[stable(feature = "process_exec", since = "1.15.0")] fn before_exec(&mut self, f: F) -> &mut process::Command where F: FnMut() -> io::Result<()> + Send + Sync + 'static; -- cgit 1.4.1-3-g733a5 From 3e7543a16ec6450b8fe0c3d50bc341b5f143cc54 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 15 Dec 2016 08:23:33 -0700 Subject: WIP: Cross-compilation for Redox target --- src/liballoc_jemalloc/build.rs | 3 +- src/liballoc_system/lib.rs | 45 ++++- src/libstd/Cargo.toml | 3 + src/libstd/build.rs | 2 +- src/libstd/lib.rs | 1 + src/libstd/sys/redox/mod.rs | 4 +- src/libstd/sys/redox/net/mod.rs | 3 +- src/libstd/sys/redox/net/netc.rs | 47 +++++ src/libstd/sys/redox/rand.rs | 25 ++- src/libstd/sys/redox/start.rs | 43 +++++ src/libstd/sys/redox/syscall/call.rs | 287 ++++++++++++++++++++++++++++++ src/libstd/sys/redox/syscall/data.rs | 127 +++++++++++++ src/libstd/sys/redox/syscall/error.rs | 315 +++++++++++++++++++++++++++++++++ src/libstd/sys/redox/syscall/flag.rs | 84 +++++++++ src/libstd/sys/redox/syscall/mod.rs | 33 ++++ src/libstd/sys/redox/syscall/number.rs | 63 +++++++ src/libstd/sys/redox/syscall/scheme.rs | 232 ++++++++++++++++++++++++ src/libstd/sys/redox/syscall/x86.rs | 72 ++++++++ src/libstd/sys/redox/syscall/x86_64.rs | 72 ++++++++ src/libtest/lib.rs | 11 ++ 20 files changed, 1462 insertions(+), 10 deletions(-) create mode 100644 src/libstd/sys/redox/net/netc.rs create mode 100644 src/libstd/sys/redox/start.rs create mode 100644 src/libstd/sys/redox/syscall/call.rs create mode 100644 src/libstd/sys/redox/syscall/data.rs create mode 100644 src/libstd/sys/redox/syscall/error.rs create mode 100644 src/libstd/sys/redox/syscall/flag.rs create mode 100644 src/libstd/sys/redox/syscall/mod.rs create mode 100644 src/libstd/sys/redox/syscall/number.rs create mode 100644 src/libstd/sys/redox/syscall/scheme.rs create mode 100644 src/libstd/sys/redox/syscall/x86.rs create mode 100644 src/libstd/sys/redox/syscall/x86_64.rs (limited to 'src/libstd/sys') diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index fc849e7a50c..e0763276113 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -36,7 +36,8 @@ fn main() { // targets, which means we have to build the alloc_jemalloc crate // for targets like emscripten, even if we don't use it. if target.contains("rumprun") || target.contains("bitrig") || target.contains("openbsd") || - target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") { + target.contains("msvc") || target.contains("emscripten") || target.contains("fuchsia") || + target.contains("redox") { println!("cargo:rustc-cfg=dummy_jemalloc"); return; } diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index a4fabb5a2c9..487e8e8e6ec 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -19,6 +19,7 @@ issue = "27783")] #![feature(allocator)] #![feature(staged_api)] +#![cfg_attr(target_os = "redox", feature(libc))] #![cfg_attr(unix, feature(libc))] // The minimum alignment guaranteed by the architecture. This value is used to @@ -71,7 +72,49 @@ pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize { imp::usable_size(size, align) } -#[cfg(unix)] +#[cfg(target_os = "redox")] +mod imp { + extern crate libc; + + use core::cmp; + use core::ptr; + use MIN_ALIGN; + + pub unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { + libc::malloc(size as libc::size_t) as *mut u8 + } + + pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 { + if align <= MIN_ALIGN { + libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8 + } else { + let new_ptr = allocate(size, align); + if !new_ptr.is_null() { + ptr::copy(ptr, new_ptr, cmp::min(size, old_size)); + deallocate(ptr, old_size, align); + } + new_ptr + } + } + + pub unsafe fn reallocate_inplace(_ptr: *mut u8, + old_size: usize, + _size: usize, + _align: usize) + -> usize { + old_size + } + + pub unsafe fn deallocate(ptr: *mut u8, _old_size: usize, _align: usize) { + libc::free(ptr as *mut libc::c_void) + } + + pub fn usable_size(size: usize, _align: usize) -> usize { + size + } +} + +#[cfg(any(unix))] mod imp { extern crate libc; diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index fcf84cb7169..0384c6666e3 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -23,6 +23,9 @@ compiler_builtins = { path = "../libcompiler_builtins" } std_unicode = { path = "../libstd_unicode" } unwind = { path = "../libunwind" } +[replace] +"core:0.0.0" = { path = "../libcore" } + [build-dependencies] build_helper = { path = "../build_helper" } gcc = "0.3.27" diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 1087d1f2447..535cb7e136c 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -26,7 +26,7 @@ fn main() { let target = env::var("TARGET").expect("TARGET was not set"); let host = env::var("HOST").expect("HOST was not set"); if cfg!(feature = "backtrace") && !target.contains("apple") && !target.contains("msvc") && - !target.contains("emscripten") && !target.contains("fuchsia") { + !target.contains("emscripten") && !target.contains("fuchsia") && !target.contains("redox") { build_libbacktrace(&host, &target); } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 414f25fa5eb..3c9e66a469c 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -299,6 +299,7 @@ #![feature(unwind_attributes)] #![feature(vec_push_all)] #![feature(zero_one)] +#![cfg_attr(target_os = "redox", feature(naked_functions))] #![cfg_attr(test, feature(update_panic_count))] // Explicitly import the prelude. The compiler uses this same unstable attribute diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index 96efa27c0d3..fce1cb364fa 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -10,8 +10,6 @@ #![allow(dead_code, missing_docs, bad_style)] -pub extern crate syscall; - use io::{self, ErrorKind}; pub mod args; @@ -33,7 +31,9 @@ pub mod process; pub mod rand; pub mod rwlock; pub mod stack_overflow; +pub mod start; pub mod stdio; +pub mod syscall; pub mod thread; pub mod thread_local; pub mod time; diff --git a/src/libstd/sys/redox/net/mod.rs b/src/libstd/sys/redox/net/mod.rs index 334c5e51c39..3fdf61cfed8 100644 --- a/src/libstd/sys/redox/net/mod.rs +++ b/src/libstd/sys/redox/net/mod.rs @@ -20,10 +20,11 @@ use vec::{IntoIter, Vec}; use self::dns::{Dns, DnsQuery}; -pub extern crate libc as netc; pub use self::tcp::{TcpStream, TcpListener}; pub use self::udp::UdpSocket; +pub mod netc; + mod dns; mod tcp; mod udp; diff --git a/src/libstd/sys/redox/net/netc.rs b/src/libstd/sys/redox/net/netc.rs new file mode 100644 index 00000000000..78045c54fb2 --- /dev/null +++ b/src/libstd/sys/redox/net/netc.rs @@ -0,0 +1,47 @@ +pub type in_addr_t = u32; +pub type in_port_t = u16; + +pub type socklen_t = u32; +pub type sa_family_t = u16; + +pub const AF_INET: sa_family_t = 1; +pub const AF_INET6: sa_family_t = 2; + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct in_addr { + pub s_addr: in_addr_t, +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct in6_addr { + pub s6_addr: [u8; 16], + __align: [u32; 0], +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct sockaddr { + pub sa_family: sa_family_t, + pub sa_data: [u8; 14], +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct sockaddr_in { + pub sin_family: sa_family_t, + pub sin_port: in_port_t, + pub sin_addr: in_addr, + pub sin_zero: [u8; 8], +} + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct sockaddr_in6 { + pub sin6_family: sa_family_t, + pub sin6_port: in_port_t, + pub sin6_flowinfo: u32, + pub sin6_addr: in6_addr, + pub sin6_scope_id: u32, +} diff --git a/src/libstd/sys/redox/rand.rs b/src/libstd/sys/redox/rand.rs index d7e4d09a9d6..eb28eca38bc 100644 --- a/src/libstd/sys/redox/rand.rs +++ b/src/libstd/sys/redox/rand.rs @@ -9,15 +9,19 @@ // except according to those terms. use io; -use libc; use rand::Rng; -pub struct OsRng; +// FIXME: Use rand: +pub struct OsRng { + state: [u64; 2] +} impl OsRng { /// Create a new `OsRng`. pub fn new() -> io::Result { - Ok(OsRng) + Ok(OsRng { + state: [0xBADF00D1, 0xDEADBEEF] + }) } } @@ -26,7 +30,20 @@ impl Rng for OsRng { self.next_u64() as u32 } fn next_u64(&mut self) -> u64 { - unsafe { libc::random() } + // Store the first and second part. + let mut x = self.state[0]; + let y = self.state[1]; + + // Put the second part into the first slot. + self.state[0] = y; + // Twist the first slot. + x ^= x << 23; + // Update the second slot. + self.state[1] = x ^ y ^ (x >> 17) ^ (y >> 26); + + // Generate the final integer. + self.state[1].wrapping_add(y) + } fn fill_bytes(&mut self, buf: &mut [u8]) { for chunk in buf.chunks_mut(8) { diff --git a/src/libstd/sys/redox/start.rs b/src/libstd/sys/redox/start.rs new file mode 100644 index 00000000000..b689be1cf4d --- /dev/null +++ b/src/libstd/sys/redox/start.rs @@ -0,0 +1,43 @@ +use sys::syscall::exit; + +#[allow(private_no_mangle_fns)] +#[no_mangle] +#[naked] +#[cfg(target_arch = "x86")] +pub unsafe fn _start() { + asm!("push esp + call _start_stack + pop esp" + : + : + : "memory" + : "intel", "volatile"); + let _ = exit(0); +} + +#[allow(private_no_mangle_fns)] +#[no_mangle] +#[naked] +#[cfg(target_arch = "x86_64")] +pub unsafe fn _start() { + asm!("mov rdi, rsp + and rsp, 0xFFFFFFFFFFFFFFF0 + call _start_stack" + : + : + : "memory" + : "intel", "volatile"); + let _ = exit(0); +} + +#[allow(private_no_mangle_fns)] +#[no_mangle] +pub unsafe extern "C" fn _start_stack(stack: *const usize){ + extern "C" { + fn main(argc: usize, argv: *const *const u8) -> usize; + } + + let argc = *stack as usize; + let argv = stack.offset(1) as *const *const u8; + let _ = exit(main(argc, argv)); +} diff --git a/src/libstd/sys/redox/syscall/call.rs b/src/libstd/sys/redox/syscall/call.rs new file mode 100644 index 00000000000..939ebf51072 --- /dev/null +++ b/src/libstd/sys/redox/syscall/call.rs @@ -0,0 +1,287 @@ +use super::arch::*; +use super::data::{Stat, StatVfs, TimeSpec}; +use super::error::Result; +use super::number::*; + +use core::mem; + +/// Set the end of the process's heap +/// +/// When `addr` is `0`, this function will return the current break. +/// +/// When `addr` is nonzero, this function will attempt to set the end of the process's +/// heap to `addr` and return the new program break. The new program break should be +/// checked by the allocator, it may not be exactly `addr`, as it may be aligned to a page +/// boundary. +/// +/// On error, `Err(ENOMEM)` will be returned indicating that no memory is available +pub unsafe fn brk(addr: usize) -> Result { + syscall1(SYS_BRK, addr) +} + +/// Change the process's working directory +/// +/// This function will attempt to set the process's working directory to `path`, which can be +/// either a relative, scheme relative, or absolute path. +/// +/// On success, `Ok(0)` will be returned. On error, one of the following errors will be returned. +/// +/// # Errors +/// +/// * `EACCES` - permission is denied for one of the components of `path`, or `path` +/// * `EFAULT` - `path` does not point to the process's addressible memory +/// * `EIO` - an I/O error occured +/// * `ENOENT` - `path` does not exit +/// * `ENOTDIR` - `path` is not a directory +pub fn chdir(path: &str) -> Result { + unsafe { syscall2(SYS_CHDIR, path.as_ptr() as usize, path.len()) } +} + +pub fn chmod(path: &str, mode: usize) -> Result { + unsafe { syscall3(SYS_CHMOD, path.as_ptr() as usize, path.len(), mode) } +} + +/// Produce a fork of the current process, or a new process thread +pub unsafe fn clone(flags: usize) -> Result { + syscall1_clobber(SYS_CLONE, flags) +} + +/// Close a file +pub fn close(fd: usize) -> Result { + unsafe { syscall1(SYS_CLOSE, fd) } +} + +/// Get the current system time +pub fn clock_gettime(clock: usize, tp: &mut TimeSpec) -> Result { + unsafe { syscall2(SYS_CLOCK_GETTIME, clock, tp as *mut TimeSpec as usize) } +} + +/// Copy and transform a file descriptor +pub fn dup(fd: usize, buf: &[u8]) -> Result { + unsafe { syscall3(SYS_DUP, fd, buf.as_ptr() as usize, buf.len()) } +} + +/// Replace the current process with a new executable +pub fn execve(path: &str, args: &[[usize; 2]]) -> Result { + unsafe { syscall4(SYS_EXECVE, path.as_ptr() as usize, path.len(), args.as_ptr() as usize, args.len()) } +} + +/// Exit the current process +pub fn exit(status: usize) -> Result { + unsafe { syscall1(SYS_EXIT, status) } +} + +/// Register a file for event-based I/O +pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result { + unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) } +} + +/// Register a file for event-based I/O +pub fn fevent(fd: usize, flags: usize) -> Result { + unsafe { syscall2(SYS_FEVENT, fd, flags) } +} + +/// Map a file into memory +pub unsafe fn fmap(fd: usize, offset: usize, size: usize) -> Result { + syscall3(SYS_FMAP, fd, offset, size) +} + +/// Unmap a memory-mapped file +pub unsafe fn funmap(addr: usize) -> Result { + syscall1(SYS_FUNMAP, addr) +} + +/// Retrieve the canonical path of a file +pub fn fpath(fd: usize, buf: &mut [u8]) -> Result { + unsafe { syscall3(SYS_FPATH, fd, buf.as_mut_ptr() as usize, buf.len()) } +} + +/// Get metadata about a file +pub fn fstat(fd: usize, stat: &mut Stat) -> Result { + unsafe { syscall3(SYS_FSTAT, fd, stat as *mut Stat as usize, mem::size_of::()) } +} + +/// Get metadata about a filesystem +pub fn fstatvfs(fd: usize, stat: &mut StatVfs) -> Result { + unsafe { syscall3(SYS_FSTATVFS, fd, stat as *mut StatVfs as usize, mem::size_of::()) } +} + +/// Sync a file descriptor to its underlying medium +pub fn fsync(fd: usize) -> Result { + unsafe { syscall1(SYS_FSYNC, fd) } +} + +/// Truncate or extend a file to a specified length +pub fn ftruncate(fd: usize, len: usize) -> Result { + unsafe { syscall2(SYS_FTRUNCATE, fd, len) } +} + +/// Fast userspace mutex - TODO: Document +pub unsafe fn futex(addr: *mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32) -> Result { + syscall5(SYS_FUTEX, addr as usize, op, (val as isize) as usize, val2, addr2 as usize) +} + +/// Get the current working directory +pub fn getcwd(buf: &mut [u8]) -> Result { + unsafe { syscall2(SYS_GETCWD, buf.as_mut_ptr() as usize, buf.len()) } +} + +/// Get the effective group ID +pub fn getegid() -> Result { + unsafe { syscall0(SYS_GETEGID) } +} + +/// Get the effective namespace +pub fn getens() -> Result { + unsafe { syscall0(SYS_GETENS) } +} + +/// Get the effective user ID +pub fn geteuid() -> Result { + unsafe { syscall0(SYS_GETEUID) } +} + +/// Get the current group ID +pub fn getgid() -> Result { + unsafe { syscall0(SYS_GETGID) } +} + +/// Get the current namespace +pub fn getns() -> Result { + unsafe { syscall0(SYS_GETNS) } +} + +/// Get the current process ID +pub fn getpid() -> Result { + unsafe { syscall0(SYS_GETPID) } +} + +/// Get the current user ID +pub fn getuid() -> Result { + unsafe { syscall0(SYS_GETUID) } +} + +/// Set the I/O privilege level +pub unsafe fn iopl(level: usize) -> Result { + syscall1(SYS_IOPL, level) +} + +/// Send a signal `sig` to the process identified by `pid` +pub fn kill(pid: usize, sig: usize) -> Result { + unsafe { syscall2(SYS_KILL, pid, sig) } +} + +/// Create a link to a file +pub unsafe fn link(old: *const u8, new: *const u8) -> Result { + syscall2(SYS_LINK, old as usize, new as usize) +} + +/// Seek to `offset` bytes in a file descriptor +pub fn lseek(fd: usize, offset: isize, whence: usize) -> Result { + unsafe { syscall3(SYS_LSEEK, fd, offset as usize, whence) } +} + +/// Make a new scheme namespace +pub fn mkns(schemes: &[[usize; 2]]) -> Result { + unsafe { syscall2(SYS_MKNS, schemes.as_ptr() as usize, schemes.len()) } +} + +/// Sleep for the time specified in `req` +pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result { + unsafe { syscall2(SYS_NANOSLEEP, req as *const TimeSpec as usize, rem as *mut TimeSpec as usize) } +} + +/// Open a file +pub fn open(path: &str, flags: usize) -> Result { + unsafe { syscall3(SYS_OPEN, path.as_ptr() as usize, path.len(), flags) } +} + +/// Allocate pages, linearly in physical memory +pub unsafe fn physalloc(size: usize) -> Result { + syscall1(SYS_PHYSALLOC, size) +} + +/// Free physically allocated pages +pub unsafe fn physfree(physical_address: usize, size: usize) -> Result { + syscall2(SYS_PHYSFREE, physical_address, size) +} + +/// Map physical memory to virtual memory +pub unsafe fn physmap(physical_address: usize, size: usize, flags: usize) -> Result { + syscall3(SYS_PHYSMAP, physical_address, size, flags) +} + +/// Unmap previously mapped physical memory +pub unsafe fn physunmap(virtual_address: usize) -> Result { + syscall1(SYS_PHYSUNMAP, virtual_address) +} + +/// Create a pair of file descriptors referencing the read and write ends of a pipe +pub fn pipe2(fds: &mut [usize; 2], flags: usize) -> Result { + unsafe { syscall2(SYS_PIPE2, fds.as_ptr() as usize, flags) } +} + +/// Read from a file descriptor into a buffer +pub fn read(fd: usize, buf: &mut [u8]) -> Result { + unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) } +} + +/// Remove a directory +pub fn rmdir(path: &str) -> Result { + unsafe { syscall2(SYS_RMDIR, path.as_ptr() as usize, path.len()) } +} + +/// Set the current process group IDs +pub fn setregid(rgid: usize, egid: usize) -> Result { + unsafe { syscall2(SYS_SETREGID, rgid, egid) } +} + +/// Make a new scheme namespace +pub fn setrens(rns: usize, ens: usize) -> Result { + unsafe { syscall2(SYS_SETRENS, rns, ens) } +} + +/// Set the current process user IDs +pub fn setreuid(ruid: usize, euid: usize) -> Result { + unsafe { syscall2(SYS_SETREUID, ruid, euid) } +} + +/// Remove a file +pub fn unlink(path: &str) -> Result { + unsafe { syscall2(SYS_UNLINK, path.as_ptr() as usize, path.len()) } +} + +/// Convert a virtual address to a physical one +pub unsafe fn virttophys(virtual_address: usize) -> Result { + syscall1(SYS_VIRTTOPHYS, virtual_address) +} + +/// Check if a child process has exited or received a signal +pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result { + unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options) } +} + +/// Write a buffer to a file descriptor +/// +/// The kernel will attempt to write the bytes in `buf` to the file descriptor `fd`, returning +/// either an `Err`, explained below, or `Ok(count)` where `count` is the number of bytes which +/// were written. +/// +/// # Errors +/// +/// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block +/// * `EBADF` - the file descriptor is not valid or is not open for writing +/// * `EFAULT` - `buf` does not point to the process's addressible memory +/// * `EIO` - an I/O error occured +/// * `ENOSPC` - the device containing the file descriptor has no room for data +/// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed +pub fn write(fd: usize, buf: &[u8]) -> Result { + unsafe { syscall3(SYS_WRITE, fd, buf.as_ptr() as usize, buf.len()) } +} + +/// Yield the process's time slice to the kernel +/// +/// This function will return Ok(0) on success +pub fn sched_yield() -> Result { + unsafe { syscall0(SYS_YIELD) } +} diff --git a/src/libstd/sys/redox/syscall/data.rs b/src/libstd/sys/redox/syscall/data.rs new file mode 100644 index 00000000000..240690befde --- /dev/null +++ b/src/libstd/sys/redox/syscall/data.rs @@ -0,0 +1,127 @@ +use core::ops::{Deref, DerefMut}; +use core::{mem, slice}; + +#[derive(Copy, Clone, Debug, Default)] +pub struct Event { + pub id: usize, + pub flags: usize, + pub data: usize +} + +impl Deref for Event { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const Event as *const u8, mem::size_of::()) as &[u8] + } + } +} + +impl DerefMut for Event { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut Event as *mut u8, mem::size_of::()) as &mut [u8] + } + } +} + +#[derive(Copy, Clone, Debug, Default)] +#[repr(packed)] +pub struct Packet { + pub id: u64, + pub pid: usize, + pub uid: u32, + pub gid: u32, + pub a: usize, + pub b: usize, + pub c: usize, + pub d: usize +} + +impl Deref for Packet { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const Packet as *const u8, mem::size_of::()) as &[u8] + } + } +} + +impl DerefMut for Packet { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut Packet as *mut u8, mem::size_of::()) as &mut [u8] + } + } +} + +#[derive(Copy, Clone, Debug, Default)] +#[repr(packed)] +pub struct Stat { + pub st_dev: u64, + pub st_ino: u64, + pub st_mode: u16, + pub st_nlink: u32, + pub st_uid: u32, + pub st_gid: u32, + pub st_size: u64, + pub st_blksize: u32, + pub st_blocks: u64, + pub st_mtime: u64, + pub st_mtime_nsec: u32, + pub st_atime: u64, + pub st_atime_nsec: u32, + pub st_ctime: u64, + pub st_ctime_nsec: u32, +} + +impl Deref for Stat { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const Stat as *const u8, mem::size_of::()) as &[u8] + } + } +} + +impl DerefMut for Stat { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut Stat as *mut u8, mem::size_of::()) as &mut [u8] + } + } +} + +#[derive(Copy, Clone, Debug, Default)] +#[repr(packed)] +pub struct StatVfs { + pub f_bsize: u32, + pub f_blocks: u64, + pub f_bfree: u64, + pub f_bavail: u64, + //TODO: More fields https://linux.die.net/man/2/statvfs +} + +impl Deref for StatVfs { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const StatVfs as *const u8, mem::size_of::()) as &[u8] + } + } +} + +impl DerefMut for StatVfs { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut StatVfs as *mut u8, mem::size_of::()) as &mut [u8] + } + } +} + +#[derive(Copy, Clone, Debug, Default)] +#[repr(packed)] +pub struct TimeSpec { + pub tv_sec: i64, + pub tv_nsec: i32, +} diff --git a/src/libstd/sys/redox/syscall/error.rs b/src/libstd/sys/redox/syscall/error.rs new file mode 100644 index 00000000000..7cbcbe98765 --- /dev/null +++ b/src/libstd/sys/redox/syscall/error.rs @@ -0,0 +1,315 @@ +use core::{fmt, result}; + +#[derive(Eq, PartialEq)] +pub struct Error { + pub errno: i32, +} + +pub type Result = result::Result; + +impl Error { + pub fn new(errno: i32) -> Error { + Error { errno: errno } + } + + pub fn mux(result: Result) -> usize { + match result { + Ok(value) => value, + Err(error) => -error.errno as usize, + } + } + + pub fn demux(value: usize) -> Result { + let errno = -(value as i32); + if errno >= 1 && errno < STR_ERROR.len() as i32 { + Err(Error::new(errno)) + } else { + Ok(value) + } + } + + pub fn text(&self) -> &str { + if let Some(description) = STR_ERROR.get(self.errno as usize) { + description + } else { + "Unknown Error" + } + } +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { + f.write_str(self.text()) + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { + f.write_str(self.text()) + } +} + +pub const EPERM: i32 = 1; /* Operation not permitted */ +pub const ENOENT: i32 = 2; /* No such file or directory */ +pub const ESRCH: i32 = 3; /* No such process */ +pub const EINTR: i32 = 4; /* Interrupted system call */ +pub const EIO: i32 = 5; /* I/O error */ +pub const ENXIO: i32 = 6; /* No such device or address */ +pub const E2BIG: i32 = 7; /* Argument list too long */ +pub const ENOEXEC: i32 = 8; /* Exec format error */ +pub const EBADF: i32 = 9; /* Bad file number */ +pub const ECHILD: i32 = 10; /* No child processes */ +pub const EAGAIN: i32 = 11; /* Try again */ +pub const ENOMEM: i32 = 12; /* Out of memory */ +pub const EACCES: i32 = 13; /* Permission denied */ +pub const EFAULT: i32 = 14; /* Bad address */ +pub const ENOTBLK: i32 = 15; /* Block device required */ +pub const EBUSY: i32 = 16; /* Device or resource busy */ +pub const EEXIST: i32 = 17; /* File exists */ +pub const EXDEV: i32 = 18; /* Cross-device link */ +pub const ENODEV: i32 = 19; /* No such device */ +pub const ENOTDIR: i32 = 20; /* Not a directory */ +pub const EISDIR: i32 = 21; /* Is a directory */ +pub const EINVAL: i32 = 22; /* Invalid argument */ +pub const ENFILE: i32 = 23; /* File table overflow */ +pub const EMFILE: i32 = 24; /* Too many open files */ +pub const ENOTTY: i32 = 25; /* Not a typewriter */ +pub const ETXTBSY: i32 = 26; /* Text file busy */ +pub const EFBIG: i32 = 27; /* File too large */ +pub const ENOSPC: i32 = 28; /* No space left on device */ +pub const ESPIPE: i32 = 29; /* Illegal seek */ +pub const EROFS: i32 = 30; /* Read-only file system */ +pub const EMLINK: i32 = 31; /* Too many links */ +pub const EPIPE: i32 = 32; /* Broken pipe */ +pub const EDOM: i32 = 33; /* Math argument out of domain of func */ +pub const ERANGE: i32 = 34; /* Math result not representable */ +pub const EDEADLK: i32 = 35; /* Resource deadlock would occur */ +pub const ENAMETOOLONG: i32 = 36; /* File name too long */ +pub const ENOLCK: i32 = 37; /* No record locks available */ +pub const ENOSYS: i32 = 38; /* Function not implemented */ +pub const ENOTEMPTY: i32 = 39; /* Directory not empty */ +pub const ELOOP: i32 = 40; /* Too many symbolic links encountered */ +pub const EWOULDBLOCK: i32 = 41; /* Operation would block */ +pub const ENOMSG: i32 = 42; /* No message of desired type */ +pub const EIDRM: i32 = 43; /* Identifier removed */ +pub const ECHRNG: i32 = 44; /* Channel number out of range */ +pub const EL2NSYNC: i32 = 45; /* Level 2 not synchronized */ +pub const EL3HLT: i32 = 46; /* Level 3 halted */ +pub const EL3RST: i32 = 47; /* Level 3 reset */ +pub const ELNRNG: i32 = 48; /* Link number out of range */ +pub const EUNATCH: i32 = 49; /* Protocol driver not attached */ +pub const ENOCSI: i32 = 50; /* No CSI structure available */ +pub const EL2HLT: i32 = 51; /* Level 2 halted */ +pub const EBADE: i32 = 52; /* Invalid exchange */ +pub const EBADR: i32 = 53; /* Invalid request descriptor */ +pub const EXFULL: i32 = 54; /* Exchange full */ +pub const ENOANO: i32 = 55; /* No anode */ +pub const EBADRQC: i32 = 56; /* Invalid request code */ +pub const EBADSLT: i32 = 57; /* Invalid slot */ +pub const EDEADLOCK: i32 = 58; /* Resource deadlock would occur */ +pub const EBFONT: i32 = 59; /* Bad font file format */ +pub const ENOSTR: i32 = 60; /* Device not a stream */ +pub const ENODATA: i32 = 61; /* No data available */ +pub const ETIME: i32 = 62; /* Timer expired */ +pub const ENOSR: i32 = 63; /* Out of streams resources */ +pub const ENONET: i32 = 64; /* Machine is not on the network */ +pub const ENOPKG: i32 = 65; /* Package not installed */ +pub const EREMOTE: i32 = 66; /* Object is remote */ +pub const ENOLINK: i32 = 67; /* Link has been severed */ +pub const EADV: i32 = 68; /* Advertise error */ +pub const ESRMNT: i32 = 69; /* Srmount error */ +pub const ECOMM: i32 = 70; /* Communication error on send */ +pub const EPROTO: i32 = 71; /* Protocol error */ +pub const EMULTIHOP: i32 = 72; /* Multihop attempted */ +pub const EDOTDOT: i32 = 73; /* RFS specific error */ +pub const EBADMSG: i32 = 74; /* Not a data message */ +pub const EOVERFLOW: i32 = 75; /* Value too large for defined data type */ +pub const ENOTUNIQ: i32 = 76; /* Name not unique on network */ +pub const EBADFD: i32 = 77; /* File descriptor in bad state */ +pub const EREMCHG: i32 = 78; /* Remote address changed */ +pub const ELIBACC: i32 = 79; /* Can not access a needed shared library */ +pub const ELIBBAD: i32 = 80; /* Accessing a corrupted shared library */ +pub const ELIBSCN: i32 = 81; /* .lib section in a.out corrupted */ +pub const ELIBMAX: i32 = 82; /* Attempting to link in too many shared libraries */ +pub const ELIBEXEC: i32 = 83; /* Cannot exec a shared library directly */ +pub const EILSEQ: i32 = 84; /* Illegal byte sequence */ +pub const ERESTART: i32 = 85; /* Interrupted system call should be restarted */ +pub const ESTRPIPE: i32 = 86; /* Streams pipe error */ +pub const EUSERS: i32 = 87; /* Too many users */ +pub const ENOTSOCK: i32 = 88; /* Socket operation on non-socket */ +pub const EDESTADDRREQ: i32 = 89; /* Destination address required */ +pub const EMSGSIZE: i32 = 90; /* Message too long */ +pub const EPROTOTYPE: i32 = 91; /* Protocol wrong type for socket */ +pub const ENOPROTOOPT: i32 = 92; /* Protocol not available */ +pub const EPROTONOSUPPORT: i32 = 93; /* Protocol not supported */ +pub const ESOCKTNOSUPPORT: i32 = 94; /* Socket type not supported */ +pub const EOPNOTSUPP: i32 = 95; /* Operation not supported on transport endpoint */ +pub const EPFNOSUPPORT: i32 = 96; /* Protocol family not supported */ +pub const EAFNOSUPPORT: i32 = 97; /* Address family not supported by protocol */ +pub const EADDRINUSE: i32 = 98; /* Address already in use */ +pub const EADDRNOTAVAIL: i32 = 99; /* Cannot assign requested address */ +pub const ENETDOWN: i32 = 100; /* Network is down */ +pub const ENETUNREACH: i32 = 101; /* Network is unreachable */ +pub const ENETRESET: i32 = 102; /* Network dropped connection because of reset */ +pub const ECONNABORTED: i32 = 103; /* Software caused connection abort */ +pub const ECONNRESET: i32 = 104; /* Connection reset by peer */ +pub const ENOBUFS: i32 = 105; /* No buffer space available */ +pub const EISCONN: i32 = 106; /* Transport endpoint is already connected */ +pub const ENOTCONN: i32 = 107; /* Transport endpoint is not connected */ +pub const ESHUTDOWN: i32 = 108; /* Cannot send after transport endpoint shutdown */ +pub const ETOOMANYREFS: i32 = 109; /* Too many references: cannot splice */ +pub const ETIMEDOUT: i32 = 110; /* Connection timed out */ +pub const ECONNREFUSED: i32 = 111; /* Connection refused */ +pub const EHOSTDOWN: i32 = 112; /* Host is down */ +pub const EHOSTUNREACH: i32 = 113; /* No route to host */ +pub const EALREADY: i32 = 114; /* Operation already in progress */ +pub const EINPROGRESS: i32 = 115; /* Operation now in progress */ +pub const ESTALE: i32 = 116; /* Stale NFS file handle */ +pub const EUCLEAN: i32 = 117; /* Structure needs cleaning */ +pub const ENOTNAM: i32 = 118; /* Not a XENIX named type file */ +pub const ENAVAIL: i32 = 119; /* No XENIX semaphores available */ +pub const EISNAM: i32 = 120; /* Is a named type file */ +pub const EREMOTEIO: i32 = 121; /* Remote I/O error */ +pub const EDQUOT: i32 = 122; /* Quota exceeded */ +pub const ENOMEDIUM: i32 = 123; /* No medium found */ +pub const EMEDIUMTYPE: i32 = 124; /* Wrong medium type */ +pub const ECANCELED: i32 = 125; /* Operation Canceled */ +pub const ENOKEY: i32 = 126; /* Required key not available */ +pub const EKEYEXPIRED: i32 = 127; /* Key has expired */ +pub const EKEYREVOKED: i32 = 128; /* Key has been revoked */ +pub const EKEYREJECTED: i32 = 129; /* Key was rejected by service */ +pub const EOWNERDEAD: i32 = 130; /* Owner died */ +pub const ENOTRECOVERABLE: i32 = 131; /* State not recoverable */ + +pub static STR_ERROR: [&'static str; 132] = ["Success", + "Operation not permitted", + "No such file or directory", + "No such process", + "Interrupted system call", + "I/O error", + "No such device or address", + "Argument list too long", + "Exec format error", + "Bad file number", + "No child processes", + "Try again", + "Out of memory", + "Permission denied", + "Bad address", + "Block device required", + "Device or resource busy", + "File exists", + "Cross-device link", + "No such device", + "Not a directory", + "Is a directory", + "Invalid argument", + "File table overflow", + "Too many open files", + "Not a typewriter", + "Text file busy", + "File too large", + "No space left on device", + "Illegal seek", + "Read-only file system", + "Too many links", + "Broken pipe", + "Math argument out of domain of func", + "Math result not representable", + "Resource deadlock would occur", + "File name too long", + "No record locks available", + "Function not implemented", + "Directory not empty", + "Too many symbolic links encountered", + "Operation would block", + "No message of desired type", + "Identifier removed", + "Channel number out of range", + "Level 2 not synchronized", + "Level 3 halted", + "Level 3 reset", + "Link number out of range", + "Protocol driver not attached", + "No CSI structure available", + "Level 2 halted", + "Invalid exchange", + "Invalid request descriptor", + "Exchange full", + "No anode", + "Invalid request code", + "Invalid slot", + "Resource deadlock would occur", + "Bad font file format", + "Device not a stream", + "No data available", + "Timer expired", + "Out of streams resources", + "Machine is not on the network", + "Package not installed", + "Object is remote", + "Link has been severed", + "Advertise error", + "Srmount error", + "Communication error on send", + "Protocol error", + "Multihop attempted", + "RFS specific error", + "Not a data message", + "Value too large for defined data type", + "Name not unique on network", + "File descriptor in bad state", + "Remote address changed", + "Can not access a needed shared library", + "Accessing a corrupted shared library", + ".lib section in a.out corrupted", + "Attempting to link in too many shared libraries", + "Cannot exec a shared library directly", + "Illegal byte sequence", + "Interrupted system call should be restarted", + "Streams pipe error", + "Too many users", + "Socket operation on non-socket", + "Destination address required", + "Message too long", + "Protocol wrong type for socket", + "Protocol not available", + "Protocol not supported", + "Socket type not supported", + "Operation not supported on transport endpoint", + "Protocol family not supported", + "Address family not supported by protocol", + "Address already in use", + "Cannot assign requested address", + "Network is down", + "Network is unreachable", + "Network dropped connection because of reset", + "Software caused connection abort", + "Connection reset by peer", + "No buffer space available", + "Transport endpoint is already connected", + "Transport endpoint is not connected", + "Cannot send after transport endpoint shutdown", + "Too many references: cannot splice", + "Connection timed out", + "Connection refused", + "Host is down", + "No route to host", + "Operation already in progress", + "Operation now in progress", + "Stale NFS file handle", + "Structure needs cleaning", + "Not a XENIX named type file", + "No XENIX semaphores available", + "Is a named type file", + "Remote I/O error", + "Quota exceeded", + "No medium found", + "Wrong medium type", + "Operation Canceled", + "Required key not available", + "Key has expired", + "Key has been revoked", + "Key was rejected by service", + "Owner died", + "State not recoverable"]; diff --git a/src/libstd/sys/redox/syscall/flag.rs b/src/libstd/sys/redox/syscall/flag.rs new file mode 100644 index 00000000000..97ff8e2d79a --- /dev/null +++ b/src/libstd/sys/redox/syscall/flag.rs @@ -0,0 +1,84 @@ +pub const CLONE_VM: usize = 0x100; +pub const CLONE_FS: usize = 0x200; +pub const CLONE_FILES: usize = 0x400; +pub const CLONE_VFORK: usize = 0x4000; + +pub const CLOCK_REALTIME: usize = 1; +pub const CLOCK_MONOTONIC: usize = 4; + +pub const EVENT_NONE: usize = 0; +pub const EVENT_READ: usize = 1; +pub const EVENT_WRITE: usize = 2; + +pub const F_GETFL: usize = 1; +pub const F_SETFL: usize = 2; + +pub const FUTEX_WAIT: usize = 0; +pub const FUTEX_WAKE: usize = 1; +pub const FUTEX_REQUEUE: usize = 2; + +pub const MAP_WRITE: usize = 1; +pub const MAP_WRITE_COMBINE: usize = 2; + +pub const MODE_TYPE: u16 = 0xF000; +pub const MODE_DIR: u16 = 0x4000; +pub const MODE_FILE: u16 = 0x8000; + +pub const MODE_PERM: u16 = 0x0FFF; +pub const MODE_SETUID: u16 = 0o4000; +pub const MODE_SETGID: u16 = 0o2000; + +pub const O_RDONLY: usize = 0x0001_0000; +pub const O_WRONLY: usize = 0x0002_0000; +pub const O_RDWR: usize = 0x0003_0000; +pub const O_NONBLOCK: usize = 0x0004_0000; +pub const O_APPEND: usize = 0x0008_0000; +pub const O_SHLOCK: usize = 0x0010_0000; +pub const O_EXLOCK: usize = 0x0020_0000; +pub const O_ASYNC: usize = 0x0040_0000; +pub const O_FSYNC: usize = 0x0080_0000; +pub const O_CLOEXEC: usize = 0x0100_0000; +pub const O_CREAT: usize = 0x0200_0000; +pub const O_TRUNC: usize = 0x0400_0000; +pub const O_EXCL: usize = 0x0800_0000; +pub const O_DIRECTORY: usize = 0x1000_0000; +pub const O_STAT: usize = 0x2000_0000; +pub const O_ACCMODE: usize = O_RDONLY | O_WRONLY | O_RDWR; + +pub const SEEK_SET: usize = 0; +pub const SEEK_CUR: usize = 1; +pub const SEEK_END: usize = 2; + +pub const SIGHUP: usize = 1; +pub const SIGINT: usize = 2; +pub const SIGQUIT: usize = 3; +pub const SIGILL: usize = 4; +pub const SIGTRAP: usize = 5; +pub const SIGABRT: usize = 6; +pub const SIGBUS: usize = 7; +pub const SIGFPE: usize = 8; +pub const SIGKILL: usize = 9; +pub const SIGUSR1: usize = 10; +pub const SIGSEGV: usize = 11; +pub const SIGUSR2: usize = 12; +pub const SIGPIPE: usize = 13; +pub const SIGALRM: usize = 14; +pub const SIGTERM: usize = 15; +pub const SIGSTKFLT: usize= 16; +pub const SIGCHLD: usize = 17; +pub const SIGCONT: usize = 18; +pub const SIGSTOP: usize = 19; +pub const SIGTSTP: usize = 20; +pub const SIGTTIN: usize = 21; +pub const SIGTTOU: usize = 22; +pub const SIGURG: usize = 23; +pub const SIGXCPU: usize = 24; +pub const SIGXFSZ: usize = 25; +pub const SIGVTALRM: usize= 26; +pub const SIGPROF: usize = 27; +pub const SIGWINCH: usize = 28; +pub const SIGIO: usize = 29; +pub const SIGPWR: usize = 30; +pub const SIGSYS: usize = 31; + +pub const WNOHANG: usize = 1; diff --git a/src/libstd/sys/redox/syscall/mod.rs b/src/libstd/sys/redox/syscall/mod.rs new file mode 100644 index 00000000000..77f98d5b36b --- /dev/null +++ b/src/libstd/sys/redox/syscall/mod.rs @@ -0,0 +1,33 @@ +pub use self::arch::*; +pub use self::call::*; +pub use self::data::*; +pub use self::error::*; +pub use self::flag::*; +pub use self::number::*; +pub use self::scheme::*; + +#[cfg(target_arch = "x86")] +#[path="x86.rs"] +mod arch; + +#[cfg(target_arch = "x86_64")] +#[path="x86_64.rs"] +mod arch; + +/// Function definitions +pub mod call; + +/// Complex structures that are used for some system calls +pub mod data; + +/// All errors that can be generated by a system call +pub mod error; + +/// Flags used as an argument to many system calls +pub mod flag; + +/// Call numbers used by each system call +pub mod number; + +/// A trait useful for scheme handlers +pub mod scheme; diff --git a/src/libstd/sys/redox/syscall/number.rs b/src/libstd/sys/redox/syscall/number.rs new file mode 100644 index 00000000000..719c8af218f --- /dev/null +++ b/src/libstd/sys/redox/syscall/number.rs @@ -0,0 +1,63 @@ +pub const SYS_CLASS: usize = 0xF000_0000; +pub const SYS_CLASS_PATH: usize=0x1000_0000; +pub const SYS_CLASS_FILE: usize=0x2000_0000; + +pub const SYS_ARG: usize = 0x0F00_0000; +pub const SYS_ARG_SLICE: usize =0x0100_0000; +pub const SYS_ARG_MSLICE: usize=0x0200_0000; +pub const SYS_ARG_PATH: usize = 0x0300_0000; + +pub const SYS_RET: usize = 0x00F0_0000; +pub const SYS_RET_FILE: usize = 0x0010_0000; + +pub const SYS_LINK: usize = SYS_CLASS_PATH | SYS_ARG_PATH | 9; +pub const SYS_OPEN: usize = SYS_CLASS_PATH | SYS_RET_FILE | 5; +pub const SYS_CHMOD: usize = SYS_CLASS_PATH | 15; +pub const SYS_RMDIR: usize = SYS_CLASS_PATH | 84; +pub const SYS_UNLINK: usize = SYS_CLASS_PATH | 10; + +pub const SYS_CLOSE: usize = SYS_CLASS_FILE | 6; +pub const SYS_DUP: usize = SYS_CLASS_FILE | SYS_RET_FILE | 41; +pub const SYS_READ: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 3; +pub const SYS_WRITE: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 4; +pub const SYS_LSEEK: usize = SYS_CLASS_FILE | 19; +pub const SYS_FCNTL: usize = SYS_CLASS_FILE | 55; +pub const SYS_FEVENT: usize = SYS_CLASS_FILE | 927; +pub const SYS_FMAP: usize = SYS_CLASS_FILE | 90; +pub const SYS_FUNMAP: usize = SYS_CLASS_FILE | 91; +pub const SYS_FPATH: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 928; +pub const SYS_FSTAT: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 28; +pub const SYS_FSTATVFS: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 100; +pub const SYS_FSYNC: usize = SYS_CLASS_FILE | 118; +pub const SYS_FTRUNCATE: usize =SYS_CLASS_FILE | 93; + +pub const SYS_BRK: usize = 45; +pub const SYS_CHDIR: usize = 12; +pub const SYS_CLOCK_GETTIME: usize = 265; +pub const SYS_CLONE: usize = 120; +pub const SYS_EXECVE: usize = 11; +pub const SYS_EXIT: usize = 1; +pub const SYS_FUTEX: usize = 240; +pub const SYS_GETCWD: usize = 183; +pub const SYS_GETEGID: usize = 202; +pub const SYS_GETENS: usize = 951; +pub const SYS_GETEUID: usize = 201; +pub const SYS_GETGID: usize = 200; +pub const SYS_GETNS: usize = 950; +pub const SYS_GETPID: usize = 20; +pub const SYS_GETUID: usize = 199; +pub const SYS_IOPL: usize = 110; +pub const SYS_KILL: usize = 37; +pub const SYS_MKNS: usize = 984; +pub const SYS_NANOSLEEP: usize =162; +pub const SYS_PHYSALLOC: usize =945; +pub const SYS_PHYSFREE: usize = 946; +pub const SYS_PHYSMAP: usize = 947; +pub const SYS_PHYSUNMAP: usize =948; +pub const SYS_VIRTTOPHYS: usize=949; +pub const SYS_PIPE2: usize = 331; +pub const SYS_SETREGID: usize = 204; +pub const SYS_SETRENS: usize = 952; +pub const SYS_SETREUID: usize = 203; +pub const SYS_WAITPID: usize = 7; +pub const SYS_YIELD: usize = 158; diff --git a/src/libstd/sys/redox/syscall/scheme.rs b/src/libstd/sys/redox/syscall/scheme.rs new file mode 100644 index 00000000000..d322f0b5a9c --- /dev/null +++ b/src/libstd/sys/redox/syscall/scheme.rs @@ -0,0 +1,232 @@ +use core::{mem, slice}; + +use super::*; + +pub trait Scheme { + fn handle(&self, packet: &mut Packet) { + packet.a = Error::mux(match packet.a { + SYS_OPEN => self.open(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d, packet.uid, packet.gid), + SYS_CHMOD => self.chmod(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d as u16, packet.uid, packet.gid), + SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid), + SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid), + + SYS_DUP => self.dup(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }), + SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }), + SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }), + SYS_LSEEK => self.seek(packet.b, packet.c, packet.d), + SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d), + SYS_FEVENT => self.fevent(packet.b, packet.c), + SYS_FMAP => self.fmap(packet.b, packet.c, packet.d), + SYS_FPATH => self.fpath(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }), + SYS_FSTAT => if packet.d >= mem::size_of::() { self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) }) } else { Err(Error::new(EFAULT)) }, + SYS_FSTATVFS => if packet.d >= mem::size_of::() { self.fstatvfs(packet.b, unsafe { &mut *(packet.c as *mut StatVfs) }) } else { Err(Error::new(EFAULT)) }, + SYS_FSYNC => self.fsync(packet.b), + SYS_FTRUNCATE => self.ftruncate(packet.b, packet.c), + SYS_CLOSE => self.close(packet.b), + + _ => Err(Error::new(ENOSYS)) + }); + } + + /* Scheme operations */ + + #[allow(unused_variables)] + fn open(&self, path: &[u8], flags: usize, uid: u32, gid: u32) -> Result { + Err(Error::new(ENOENT)) + } + + #[allow(unused_variables)] + fn chmod(&self, path: &[u8], mode: u16, uid: u32, gid: u32) -> Result { + Err(Error::new(ENOENT)) + } + + #[allow(unused_variables)] + fn rmdir(&self, path: &[u8], uid: u32, gid: u32) -> Result { + Err(Error::new(ENOENT)) + } + + #[allow(unused_variables)] + fn unlink(&self, path: &[u8], uid: u32, gid: u32) -> Result { + Err(Error::new(ENOENT)) + } + + /* Resource operations */ + #[allow(unused_variables)] + fn dup(&self, old_id: usize, buf: &[u8]) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn read(&self, id: usize, buf: &mut [u8]) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn write(&self, id: usize, buf: &[u8]) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn seek(&self, id: usize, pos: usize, whence: usize) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fevent(&self, id: usize, flags: usize) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fmap(&self, id: usize, offset: usize, size: usize) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fpath(&self, id: usize, buf: &mut [u8]) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fstat(&self, id: usize, stat: &mut Stat) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fstatvfs(&self, id: usize, stat: &mut StatVfs) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fsync(&self, id: usize) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn ftruncate(&self, id: usize, len: usize) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn close(&self, id: usize) -> Result { + Err(Error::new(EBADF)) + } +} + +pub trait SchemeMut { + fn handle(&mut self, packet: &mut Packet) { + packet.a = Error::mux(match packet.a { + SYS_OPEN => self.open(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d, packet.uid, packet.gid), + SYS_CHMOD => self.chmod(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d as u16, packet.uid, packet.gid), + SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid), + SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid), + + SYS_DUP => self.dup(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }), + SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }), + SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }), + SYS_LSEEK => self.seek(packet.b, packet.c, packet.d), + SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d), + SYS_FEVENT => self.fevent(packet.b, packet.c), + SYS_FMAP => self.fmap(packet.b, packet.c, packet.d), + SYS_FPATH => self.fpath(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }), + SYS_FSTAT => if packet.d >= mem::size_of::() { self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) }) } else { Err(Error::new(EFAULT)) }, + SYS_FSTATVFS => if packet.d >= mem::size_of::() { self.fstatvfs(packet.b, unsafe { &mut *(packet.c as *mut StatVfs) }) } else { Err(Error::new(EFAULT)) }, + SYS_FSYNC => self.fsync(packet.b), + SYS_FTRUNCATE => self.ftruncate(packet.b, packet.c), + SYS_CLOSE => self.close(packet.b), + + _ => Err(Error::new(ENOSYS)) + }); + } + + /* Scheme operations */ + #[allow(unused_variables)] + fn open(&mut self, path: &[u8], flags: usize, uid: u32, gid: u32) -> Result { + Err(Error::new(ENOENT)) + } + + #[allow(unused_variables)] + fn chmod(&self, path: &[u8], mode: u16, uid: u32, gid: u32) -> Result { + Err(Error::new(ENOENT)) + } + + #[allow(unused_variables)] + fn rmdir(&mut self, path: &[u8], uid: u32, gid: u32) -> Result { + Err(Error::new(ENOENT)) + } + + #[allow(unused_variables)] + fn unlink(&mut self, path: &[u8], uid: u32, gid: u32) -> Result { + Err(Error::new(ENOENT)) + } + + /* Resource operations */ + #[allow(unused_variables)] + fn dup(&mut self, old_id: usize, buf: &[u8]) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn read(&mut self, id: usize, buf: &mut [u8]) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn write(&mut self, id: usize, buf: &[u8]) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fcntl(&mut self, id: usize, cmd: usize, arg: usize) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fevent(&mut self, id: usize, flags: usize) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fmap(&mut self, id: usize, offset: usize, size: usize) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fstatvfs(&self, id: usize, stat: &mut StatVfs) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn fsync(&mut self, id: usize) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn ftruncate(&mut self, id: usize, len: usize) -> Result { + Err(Error::new(EBADF)) + } + + #[allow(unused_variables)] + fn close(&mut self, id: usize) -> Result { + Err(Error::new(EBADF)) + } +} diff --git a/src/libstd/sys/redox/syscall/x86.rs b/src/libstd/sys/redox/syscall/x86.rs new file mode 100644 index 00000000000..4bb6060c43e --- /dev/null +++ b/src/libstd/sys/redox/syscall/x86.rs @@ -0,0 +1,72 @@ +use super::error::{Error, Result}; + +pub unsafe fn syscall0(mut a: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall1(mut a: usize, b: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +// Clobbers all registers - special for clone +pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b) + : "memory", "ebx", "ecx", "edx", "esi", "edi" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b), "{ecx}"(c) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e), "{edi}"(f) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} diff --git a/src/libstd/sys/redox/syscall/x86_64.rs b/src/libstd/sys/redox/syscall/x86_64.rs new file mode 100644 index 00000000000..6c1f96adef9 --- /dev/null +++ b/src/libstd/sys/redox/syscall/x86_64.rs @@ -0,0 +1,72 @@ +use super::error::{Error, Result}; + +pub unsafe fn syscall0(mut a: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall1(mut a: usize, b: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +// Clobbers all registers - special for clone +pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b) + : "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b), "{rcx}"(c) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e), "{rdi}"(f) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index f5546b6aac4..82acbf93488 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -914,6 +914,11 @@ fn use_color(opts: &TestOpts) -> bool { } } +#[cfg(target_os = "redox")] +fn stdout_isatty() -> bool { + // FIXME: Implement isatty on Redox + false +} #[cfg(unix)] fn stdout_isatty() -> bool { unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } @@ -1103,6 +1108,12 @@ fn get_concurrency() -> usize { } } + #[cfg(target_os = "redox")] + fn num_cpus() -> usize { + // FIXME: Implement num_cpus on Redox + 1 + } + #[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", -- cgit 1.4.1-3-g733a5 From 773a0a2edb9a79733aca9f07f1fa8d7d155c4abc Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 15 Dec 2016 13:10:37 -0700 Subject: Add start functions, switch allocation crate to ralloc --- src/librustc_back/target/redox_base.rs | 4 +- src/libstd/lib.rs | 5 +++ src/libstd/sys/redox/start.rs | 81 ++++++++++++++++++++++++++++++++-- 3 files changed, 85 insertions(+), 5 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/librustc_back/target/redox_base.rs b/src/librustc_back/target/redox_base.rs index a04ec81e973..fc4c68276b6 100644 --- a/src/librustc_back/target/redox_base.rs +++ b/src/librustc_back/target/redox_base.rs @@ -40,8 +40,8 @@ pub fn opts() -> TargetOptions { target_family: Some("redox".to_string()), linker_is_gnu: true, no_default_libraries: true, - lib_allocation_crate: "alloc_system".to_string(), - exe_allocation_crate: "alloc_system".to_string(), + lib_allocation_crate: "ralloc".to_string(), + exe_allocation_crate: "ralloc".to_string(), has_elf_tls: true, panic_strategy: PanicStrategy::Abort, .. Default::default() diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 3c9e66a469c..6a1bb1268d7 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -423,6 +423,11 @@ pub use core_collections::vec; #[stable(feature = "rust1", since = "1.0.0")] pub use std_unicode::char; +// Reexport the start module on platforms that provide it +#[unstable(feature = "start_fn", issue="0")] +#[cfg(target_os = "redox")] +pub use sys::start::*; + pub mod f32; pub mod f64; diff --git a/src/libstd/sys/redox/start.rs b/src/libstd/sys/redox/start.rs index b689be1cf4d..87f58a4773c 100644 --- a/src/libstd/sys/redox/start.rs +++ b/src/libstd/sys/redox/start.rs @@ -1,6 +1,6 @@ use sys::syscall::exit; -#[allow(private_no_mangle_fns)] +#[unstable(feature = "start_fn", issue = "0")] #[no_mangle] #[naked] #[cfg(target_arch = "x86")] @@ -15,7 +15,7 @@ pub unsafe fn _start() { let _ = exit(0); } -#[allow(private_no_mangle_fns)] +#[unstable(feature = "start_fn", issue = "0")] #[no_mangle] #[naked] #[cfg(target_arch = "x86_64")] @@ -30,7 +30,7 @@ pub unsafe fn _start() { let _ = exit(0); } -#[allow(private_no_mangle_fns)] +#[unstable(feature = "start_fn", issue = "0")] #[no_mangle] pub unsafe extern "C" fn _start_stack(stack: *const usize){ extern "C" { @@ -41,3 +41,78 @@ pub unsafe extern "C" fn _start_stack(stack: *const usize){ let argv = stack.offset(1) as *const *const u8; let _ = exit(main(argc, argv)); } + +/// Memcpy +/// +/// Copy N bytes of memory from one location to another. +#[unstable(feature = "start_fn", issue = "0")] +#[no_mangle] +pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8, + n: usize) -> *mut u8 { + let mut i = 0; + while i < n { + *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); + i += 1; + } + + dest +} + +/// Memmove +/// +/// Copy N bytes of memory from src to dest. The memory areas may overlap. +#[unstable(feature = "start_fn", issue = "0")] +#[no_mangle] +pub unsafe extern fn memmove(dest: *mut u8, src: *const u8, + n: usize) -> *mut u8 { + if src < dest as *const u8 { + let mut i = n; + while i != 0 { + i -= 1; + *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); + } + } else { + let mut i = 0; + while i < n { + *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); + i += 1; + } + } + + dest +} + +/// Memset +/// +/// Fill a block of memory with a specified value. +#[unstable(feature = "start_fn", issue = "0")] +#[no_mangle] +pub unsafe extern fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 { + let mut i = 0; + while i < n { + *((dest as usize + i) as *mut u8) = c as u8; + i += 1; + } + + dest +} + +/// Memcmp +/// +/// Compare two blocks of memory. +#[unstable(feature = "start_fn", issue = "0")] +#[no_mangle] +pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { + let mut i = 0; + + while i < n { + let a = *((s1 as usize + i) as *const u8); + let b = *((s2 as usize + i) as *const u8); + if a != b { + return a as i32 - b as i32 + } + i += 1; + } + + 0 +} -- cgit 1.4.1-3-g733a5 From 2938e6a41172d1c71f5c58e9a71958f2d5c1a262 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 7 Dec 2016 21:55:09 -0800 Subject: Add missing doc examples for UnixDatagram --- src/libstd/sys/unix/ext/net.rs | 323 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 285 insertions(+), 38 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index d49f9343b0e..e822488c018 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -139,13 +139,25 @@ impl SocketAddr { /// /// # Examples /// + /// A named address: + /// /// ``` /// use std::os::unix::net::UnixListener; /// - /// let socket = match UnixListener::bind("/tmp/sock").unwrap(); + /// let socket = UnixListener::bind("/tmp/sock").unwrap(); /// let addr = socket.local_addr().expect("Couldn't get local address"); /// assert_eq!(addr.is_unnamed(), false); /// ``` + /// + /// An unnamed address: + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// + /// let socket = UnixDatagram::unbound().unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.is_unnamed(), true); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn is_unnamed(&self) -> bool { if let AddressKind::Unnamed = self.address() { @@ -159,14 +171,27 @@ impl SocketAddr { /// /// # Examples /// + /// With a pathname: + /// /// ``` /// use std::os::unix::net::UnixListener; /// use std::path::Path; /// - /// let socket = match UnixListener::bind("/tmp/sock").unwrap(); + /// let socket = UnixListener::bind("/tmp/sock").unwrap(); /// let addr = socket.local_addr().expect("Couldn't get local address"); /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); /// ``` + /// + /// Without a pathname: + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// use std::path::Path; + /// + /// let socket = UnixDatagram::unbound().unwrap(); + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), None); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn as_pathname(&self) -> Option<&Path> { if let AddressKind::Pathname(path) = self.address() { @@ -311,8 +336,8 @@ impl UnixStream { /// ```no_run /// use std::os::unix::net::UnixStream; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); - /// let sock_copy = socket.try_clone().expect("Couldn't clone socket..."); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result { @@ -326,7 +351,7 @@ impl UnixStream { /// ```no_run /// use std::os::unix::net::UnixStream; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// let addr = socket.local_addr().expect("Couldn't get local address"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] @@ -341,7 +366,7 @@ impl UnixStream { /// ```no_run /// use std::os::unix::net::UnixStream; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// let addr = socket.peer_addr().expect("Couldn't get peer address"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] @@ -355,9 +380,9 @@ impl UnixStream { /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// [`read()`]: ../../std/io/trait.Read.html#tymethod.read - /// [`Duration`]: ../../std/time/struct.Duration.html + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`read()`]: ../../../../std/io/trait.Read.html#tymethod.read + /// [`Duration`]: ../../../../std/time/struct.Duration.html /// /// # Examples /// @@ -365,7 +390,7 @@ impl UnixStream { /// use std::os::unix::net::UnixStream; /// use std::time::Duration; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] @@ -379,9 +404,9 @@ impl UnixStream { /// indefinitely. It is an error to pass the zero [`Duration`] to this /// method. /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None - /// [`read()`]: ../../std/io/trait.Write.html#tymethod.write - /// [`Duration`]: ../../std/time/struct.Duration.html + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`read()`]: ../../../../std/io/trait.Write.html#tymethod.write + /// [`Duration`]: ../../../../std/time/struct.Duration.html /// /// # Examples /// @@ -389,7 +414,7 @@ impl UnixStream { /// use std::os::unix::net::UnixStream; /// use std::time::Duration; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] @@ -405,7 +430,7 @@ impl UnixStream { /// use std::os::unix::net::UnixStream; /// use std::time::Duration; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0))); /// ``` @@ -422,7 +447,7 @@ impl UnixStream { /// use std::os::unix::net::UnixStream; /// use std::time::Duration; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout"); /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0))); /// ``` @@ -438,8 +463,8 @@ impl UnixStream { /// ```no_run /// use std::os::unix::net::UnixStream; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); - /// socket.set_nonblocking(true).expect("Couldn't set non blocking"); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); + /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { @@ -453,7 +478,7 @@ impl UnixStream { /// ```no_run /// use std::os::unix::net::UnixStream; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// if let Ok(Some(err)) = socket.take_error() { /// println!("Got error: {:?}", err); /// } @@ -469,14 +494,15 @@ impl UnixStream { /// specified portions to immediately return with an appropriate value /// (see the documentation of [`Shutdown`]). /// - /// [`Shutdown`]: ../../std/net/enum.Shutdown.html + /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html /// /// # Examples /// /// ```no_run /// use std::os::unix::net::UnixStream; + /// use std::net::Shutdown; /// - /// let socket = match UnixStream::connect("/tmp/sock").unwrap(); + /// let socket = UnixStream::connect("/tmp/sock").unwrap(); /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] @@ -631,7 +657,7 @@ impl UnixListener { /// is established. When established, the corersponding [`UnixStream`] and /// the remote peer's address will be returned. /// - /// [`UnixStream`]: ../../std/os/unix/net/struct.UnixStream.html + /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html /// /// # Examples /// @@ -683,7 +709,7 @@ impl UnixListener { /// /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); /// - /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// let addr = listener.local_addr().expect("Couldn't get local address"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { @@ -699,7 +725,7 @@ impl UnixListener { /// /// let listener = UnixListener::bind("/path/to/the/socket").unwrap(); /// - /// socket.set_nonblocking(true).expect("Couldn't set non blocking"); + /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { @@ -713,8 +739,9 @@ impl UnixListener { /// ```no_run /// use std::os::unix::net::UnixListener; /// - /// let socket = match UnixListener::bind("/tmp/sock").unwrap(); - /// if let Ok(Some(err)) = socket.take_error() { + /// let listener = UnixListener::bind("/tmp/sock").unwrap(); + /// + /// if let Ok(Some(err)) = listener.take_error() { /// println!("Got error: {:?}", err); /// } /// ``` @@ -728,7 +755,7 @@ impl UnixListener { /// The iterator will never return [`None`] and will also not yield the /// peer's [`SocketAddr`] structure. /// - /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None /// [`SocketAddr`]: struct.SocketAddr.html /// /// # Examples @@ -795,7 +822,7 @@ impl<'a> IntoIterator for &'a UnixListener { /// /// It will never return [`None`]. /// -/// [`None`]: ../../std/option/enum.Option.html#variant.None +/// [`None`]: ../../../../std/option/enum.Option.html#variant.None /// [`UnixListener`]: struct.UnixListener.html /// /// # Examples @@ -873,6 +900,20 @@ impl fmt::Debug for UnixDatagram { impl UnixDatagram { /// Creates a Unix datagram socket bound to the given path. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = match UnixDatagram::bind("/path/to/the/socket") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't bind: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn bind>(path: P) -> io::Result { fn inner(path: &Path) -> io::Result { @@ -889,6 +930,20 @@ impl UnixDatagram { } /// Creates a Unix Datagram socket which is not bound to any address. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = match UnixDatagram::unbound() { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't unbound: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn unbound() -> io::Result { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?; @@ -898,6 +953,20 @@ impl UnixDatagram { /// Create an unnamed pair of connected sockets. /// /// Returns two `UnixDatagrams`s which are connected to each other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let (sock1, sock2) = match UnixDatagram::pair() { + /// Ok((sock1, sock2)) => (sock1, sock2), + /// Err(e) => { + /// println!("Couldn't unbound: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> { let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?; @@ -906,8 +975,27 @@ impl UnixDatagram { /// Connects the socket to the specified address. /// - /// The `send` method may be used to send data to the specified address. - /// `recv` and `recv_from` will only receive data from that address. + /// The [`send()`] method may be used to send data to the specified address. + /// [`recv()`] and [`recv_from()`] will only receive data from that address. + /// + /// [`send()`]: #method.send + /// [`recv()`]: #method.recv + /// [`recv_from()`]: #method.recv_from + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// match sock.connect("/path/to/the/socket") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn connect>(&self, path: P) -> io::Result<()> { fn inner(d: &UnixDatagram, path: &Path) -> io::Result<()> { @@ -924,15 +1012,35 @@ impl UnixDatagram { /// Creates a new independently owned handle to the underlying socket. /// - /// The returned `UnixListener` is a reference to the same socket that this + /// The returned `UnixDatagram` is a reference to the same socket that this /// object references. Both handles can be used to accept incoming - /// connections and options set on one listener will affect the other. + /// connections and options set on one side will affect the other. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap(); + /// + /// let sock_copy = sock.try_clone().expect("try_clone failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(UnixDatagram) } /// Returns the address of this socket. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap(); + /// + /// let addr = sock.local_addr().expect("Couldn't get local address"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn local_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) @@ -940,7 +1048,20 @@ impl UnixDatagram { /// Returns the address of this socket's peer. /// - /// The `connect` method will connect the socket to a peer. + /// The [`connect()`] method will connect the socket to a peer. + /// + /// [`connect()`]: #method.connect + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.connect("/path/to/the/socket").unwrap(); + /// + /// let addr = sock.peer_addr().expect("Couldn't get peer address"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn peer_addr(&self) -> io::Result { SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) @@ -950,6 +1071,19 @@ impl UnixDatagram { /// /// On success, returns the number of bytes read and the address from /// whence the data came. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// let mut buf = vec![0; 10]; + /// match sock.recv_from(buf.as_mut_slice()) { + /// Ok((size, sender)) => println!("received {} bytes from {:?}", size, sender), + /// Err(e) => println!("recv_from function failed: {:?}", e), + /// } + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { let mut count = 0; @@ -977,6 +1111,16 @@ impl UnixDatagram { /// Receives data from the socket. /// /// On success, returns the number of bytes read. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap(); + /// let mut buf = vec![0; 10]; + /// sock.recv(buf.as_mut_slice()).expect("recv function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn recv(&self, buf: &mut [u8]) -> io::Result { self.0.read(buf) @@ -985,6 +1129,15 @@ impl UnixDatagram { /// Sends data on the socket to the specified address. /// /// On success, returns the number of bytes written. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn send_to>(&self, buf: &[u8], path: P) -> io::Result { fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result { @@ -1009,6 +1162,16 @@ impl UnixDatagram { /// will return an error if the socket has not already been connected. /// /// On success, returns the number of bytes written. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.connect("/some/sock").expect("Couldn't connect"); + /// sock.send(b"omelette au fromage").expect("send_to function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn send(&self, buf: &[u8]) -> io::Result { self.0.write(buf) @@ -1016,9 +1179,24 @@ impl UnixDatagram { /// Sets the read timeout for the socket. /// - /// If the provided value is `None`, then `recv` and `recv_from` calls will - /// block indefinitely. It is an error to pass the zero `Duration` to this + /// If the provided value is [`None`], then [`recv()`] and [`recv_from()`] calls will + /// block indefinitely. It is an error to pass the zero [`Duration`] to this /// method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`recv()`]: #method.recv + /// [`recv_from()`]: #method.recv_from + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// use std::time::Duration; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_RCVTIMEO) @@ -1026,33 +1204,92 @@ impl UnixDatagram { /// Sets the write timeout for the socket. /// - /// If the provided value is `None`, then `send` and `send_to` calls will - /// block indefinitely. It is an error to pass the zero `Duration` to this + /// If the provided value is [`None`], then [`send()`] and [`send_to()`] calls will + /// block indefinitely. It is an error to pass the zero [`Duration`] to this /// method. + /// + /// [`None`]: ../../../../std/option/enum.Option.html#variant.None + /// [`send()`]: #method.send + /// [`send_to()`]: #method.send_to + /// [`Duration`]: ../../../../std/time/struct.Duration.html + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// use std::time::Duration; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.set_write_timeout(Some(Duration::new(1, 0))) + /// .expect("set_write_timeout function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.0.set_timeout(timeout, libc::SO_SNDTIMEO) } /// Returns the read timeout of this socket. + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// use std::time::Duration; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed"); + /// assert_eq!(sock.read_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn read_timeout(&self) -> io::Result> { self.0.timeout(libc::SO_RCVTIMEO) } /// Returns the write timeout of this socket. + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// use std::time::Duration; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.set_write_timeout(Some(Duration::new(1, 0))) + /// .expect("set_write_timeout function failed"); + /// assert_eq!(sock.write_timeout().unwrap(), Some(Duration::new(1, 0))); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn write_timeout(&self) -> io::Result> { self.0.timeout(libc::SO_SNDTIMEO) } /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ``` + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.set_nonblocking(true).expect("set_nonblocking function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.0.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// if let Ok(Some(err)) = sock.take_error() { + /// println!("Got error: {:?}", err); + /// } + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn take_error(&self) -> io::Result> { self.0.take_error() @@ -1062,7 +1299,17 @@ impl UnixDatagram { /// /// This function will cause all pending and future I/O calls on the /// specified portions to immediately return with an appropriate value - /// (see the documentation of `Shutdown`). + /// (see the documentation of [`Shutdown`]). + /// + /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html + /// + /// ```no_run + /// use std::os::unix::net::UnixDatagram; + /// use std::net::Shutdown; + /// + /// let sock = UnixDatagram::unbound().unwrap(); + /// sock.shutdown(Shutdown::Both).expect("shutdown function failed"); + /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.0.shutdown(how) -- cgit 1.4.1-3-g733a5 From 9a5cef4de51c1c90fb2d05b0c7e6feb9cf0224d6 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Wed, 14 Dec 2016 13:02:00 -0800 Subject: Address fallout --- src/liballoc/rc.rs | 33 ++--------------------------- src/libcollectionstest/lib.rs | 1 - src/libcore/cell.rs | 2 ++ src/libcore/fmt/mod.rs | 10 ++++----- src/libcore/iter/iterator.rs | 2 -- src/libcoretest/cell.rs | 37 ++++++++++++++++++++------------- src/libcoretest/lib.rs | 4 ---- src/librustc/dep_graph/shadow.rs | 16 ++++++-------- src/librustc/lib.rs | 1 - src/librustc_resolve/lib.rs | 1 - src/librustc_resolve/resolve_imports.rs | 8 +++---- src/librustc_trans/lib.rs | 1 - src/libstd/io/stdio.rs | 6 +++--- src/libstd/sys/redox/ext/process.rs | 2 +- src/libstd_unicode/char.rs | 2 -- src/libstd_unicode/lib.rs | 1 - 16 files changed, 44 insertions(+), 83 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 8d2b1a770b2..86f8c746646 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -320,7 +320,7 @@ impl Rc { #[inline] #[stable(feature = "rc_unique", since = "1.4.0")] pub fn try_unwrap(this: Self) -> Result { - if Rc::would_unwrap(&this) { + if Rc::strong_count(&this) == 1 { unsafe { let val = ptr::read(&*this); // copy the contained object @@ -343,23 +343,6 @@ impl Rc { /// /// [try_unwrap]: struct.Rc.html#method.try_unwrap /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok - /// - /// # Examples - /// - /// ``` - /// #![feature(rc_would_unwrap)] - /// - /// use std::rc::Rc; - /// - /// let x = Rc::new(3); - /// assert!(Rc::would_unwrap(&x)); - /// assert_eq!(Rc::try_unwrap(x), Ok(3)); - /// - /// let x = Rc::new(4); - /// let _y = x.clone(); - /// assert!(!Rc::would_unwrap(&x)); - /// assert_eq!(*Rc::try_unwrap(x).unwrap_err(), 4); - /// ``` #[unstable(feature = "rc_would_unwrap", reason = "just added for niche usecase", issue = "28356")] @@ -518,20 +501,8 @@ impl Rc { /// this inner value. /// /// [weak]: struct.Weak.html - /// - /// # Examples - /// - /// ``` - /// #![feature(rc_counts)] - /// - /// use std::rc::Rc; - /// - /// let five = Rc::new(5); - /// - /// assert!(Rc::is_unique(&five)); - /// ``` #[inline] - #[unstable(feature = "rc_counts", reason = "uniqueness has unclear meaning", + #[unstable(feature = "is_unique", reason = "uniqueness has unclear meaning", issue = "28356")] #[rustc_deprecated(since = "1.15.0", reason = "too niche; use `strong_count` and `weak_count` instead")] diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 0fe0a1bad64..d4fb5ea03ad 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -29,7 +29,6 @@ #![feature(test)] #![feature(unboxed_closures)] #![feature(unicode)] -#![feature(vec_into_iter_as_slice)] extern crate collections; extern crate test; diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index efba8798309..c3f862e7c54 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -394,6 +394,7 @@ pub struct RefCell { #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[unstable(feature = "borrow_state", issue = "27733")] #[rustc_deprecated(since = "1.15.0", reason = "use `try_borrow` instead")] +#[allow(deprecated)] pub enum BorrowState { /// The cell is currently being read, there is at least one active `borrow`. Reading, @@ -513,6 +514,7 @@ impl RefCell { /// ``` #[unstable(feature = "borrow_state", issue = "27733")] #[rustc_deprecated(since = "1.15.0", reason = "use `try_borrow` instead")] + #[allow(deprecated)] #[inline] pub fn borrow_state(&self) -> BorrowState { match self.borrow.get() { diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 9167264ba9d..2ba7d6e8bd1 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -12,7 +12,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use cell::{UnsafeCell, Cell, RefCell, Ref, RefMut, BorrowState}; +use cell::{UnsafeCell, Cell, RefCell, Ref, RefMut}; use marker::PhantomData; use mem; use num::flt2dec; @@ -1634,13 +1634,13 @@ impl Debug for Cell { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for RefCell { fn fmt(&self, f: &mut Formatter) -> Result { - match self.borrow_state() { - BorrowState::Unused | BorrowState::Reading => { + match self.try_borrow() { + Ok(borrow) => { f.debug_struct("RefCell") - .field("value", &self.borrow()) + .field("value", &borrow) .finish() } - BorrowState::Writing => { + Err(_) => { f.debug_struct("RefCell") .field("value", &"") .finish() diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index cdc804b9ad6..ec590d2bd06 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1696,7 +1696,6 @@ pub trait Iterator { /// # Examples /// /// ``` - /// #![feature(iter_max_by)] /// let a = [-3_i32, 0, 1, 5, -10]; /// assert_eq!(*a.iter().max_by(|x, y| x.cmp(y)).unwrap(), 5); /// ``` @@ -1746,7 +1745,6 @@ pub trait Iterator { /// # Examples /// /// ``` - /// #![feature(iter_min_by)] /// let a = [-3_i32, 0, 1, 5, -10]; /// assert_eq!(*a.iter().min_by(|x, y| x.cmp(y)).unwrap(), -10); /// ``` diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs index a7c230ba979..724a312ea79 100644 --- a/src/libcoretest/cell.rs +++ b/src/libcoretest/cell.rs @@ -59,22 +59,22 @@ fn double_imm_borrow() { fn no_mut_then_imm_borrow() { let x = RefCell::new(0); let _b1 = x.borrow_mut(); - assert_eq!(x.borrow_state(), BorrowState::Writing); + assert!(x.try_borrow().is_err()); } #[test] fn no_imm_then_borrow_mut() { let x = RefCell::new(0); let _b1 = x.borrow(); - assert_eq!(x.borrow_state(), BorrowState::Reading); + assert!(x.try_borrow_mut().is_err()); } #[test] fn no_double_borrow_mut() { let x = RefCell::new(0); - assert_eq!(x.borrow_state(), BorrowState::Unused); + assert!(x.try_borrow().is_ok()); let _b1 = x.borrow_mut(); - assert_eq!(x.borrow_state(), BorrowState::Writing); + assert!(x.try_borrow().is_err()); } #[test] @@ -102,7 +102,8 @@ fn double_borrow_single_release_no_borrow_mut() { { let _b2 = x.borrow(); } - assert_eq!(x.borrow_state(), BorrowState::Reading); + assert!(x.try_borrow().is_ok()); + assert!(x.try_borrow_mut().is_err()); } #[test] @@ -119,14 +120,18 @@ fn ref_clone_updates_flag() { let x = RefCell::new(0); { let b1 = x.borrow(); - assert_eq!(x.borrow_state(), BorrowState::Reading); + assert!(x.try_borrow().is_ok()); + assert!(x.try_borrow_mut().is_err()); { let _b2 = Ref::clone(&b1); - assert_eq!(x.borrow_state(), BorrowState::Reading); + assert!(x.try_borrow().is_ok()); + assert!(x.try_borrow_mut().is_err()); } - assert_eq!(x.borrow_state(), BorrowState::Reading); + assert!(x.try_borrow().is_ok()); + assert!(x.try_borrow_mut().is_err()); } - assert_eq!(x.borrow_state(), BorrowState::Unused); + assert!(x.try_borrow().is_ok()); + assert!(x.try_borrow_mut().is_ok()); } #[test] @@ -134,15 +139,19 @@ fn ref_map_does_not_update_flag() { let x = RefCell::new(Some(5)); { let b1: Ref> = x.borrow(); - assert_eq!(x.borrow_state(), BorrowState::Reading); + assert!(x.try_borrow().is_ok()); + assert!(x.try_borrow_mut().is_err()); { let b2: Ref = Ref::map(b1, |o| o.as_ref().unwrap()); assert_eq!(*b2, 5); - assert_eq!(x.borrow_state(), BorrowState::Reading); + assert!(x.try_borrow().is_ok()); + assert!(x.try_borrow_mut().is_err()); } - assert_eq!(x.borrow_state(), BorrowState::Unused); + assert!(x.try_borrow().is_ok()); + assert!(x.try_borrow_mut().is_ok()); } - assert_eq!(x.borrow_state(), BorrowState::Unused); + assert!(x.try_borrow().is_ok()); + assert!(x.try_borrow_mut().is_ok()); } #[test] @@ -247,5 +256,3 @@ fn refcell_ref_coercion() { assert_eq!(&*coerced, comp); } } - - diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 05d98d4a212..d12616a97a6 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -10,9 +10,7 @@ #![deny(warnings)] -#![feature(borrow_state)] #![feature(box_syntax)] -#![feature(cell_extras)] #![feature(char_escape_debug)] #![feature(const_fn)] #![feature(core_private_bignum)] @@ -32,8 +30,6 @@ #![feature(try_from)] #![feature(unicode)] #![feature(unique)] -#![feature(iter_max_by)] -#![feature(iter_min_by)] #![feature(ordering_chaining)] #![feature(result_unwrap_or_default)] #![feature(ptr_unaligned)] diff --git a/src/librustc/dep_graph/shadow.rs b/src/librustc/dep_graph/shadow.rs index 06def4bf19a..5d4190a8ae1 100644 --- a/src/librustc/dep_graph/shadow.rs +++ b/src/librustc/dep_graph/shadow.rs @@ -27,7 +27,7 @@ //! created. See `./README.md` for details. use hir::def_id::DefId; -use std::cell::{BorrowState, RefCell}; +use std::cell::RefCell; use std::env; use super::DepNode; @@ -71,15 +71,11 @@ impl ShadowGraph { pub fn enqueue(&self, message: &DepMessage) { if ENABLED { - match self.stack.borrow_state() { - BorrowState::Unused => {} - _ => { - // When we apply edge filters, that invokes the - // Debug trait on DefIds, which in turn reads from - // various bits of state and creates reads! Ignore - // those recursive reads. - return; - } + if self.stack.try_borrow().is_err() { + // When we apply edge filters, that invokes the Debug trait on + // DefIds, which in turn reads from various bits of state and + // creates reads! Ignore those recursive reads. + return; } let mut stack = self.stack.borrow_mut(); diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 7c26b710a53..17cc34fcd83 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -24,7 +24,6 @@ #![cfg_attr(not(stage0), deny(warnings))] #![feature(associated_consts)] -#![feature(borrow_state)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(collections)] diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ea5aa5be013..509ee704e2e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -18,7 +18,6 @@ #![cfg_attr(not(stage0), deny(warnings))] #![feature(associated_consts)] -#![feature(borrow_state)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(staged_api)] diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index b634d57a842..890891fd090 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -144,11 +144,9 @@ impl<'a> Resolver<'a> { -> Result<&'a NameBinding<'a>, Determinacy> { self.populate_module_if_necessary(module); - let resolution = self.resolution(module, name, ns); - let resolution = match resolution.borrow_state() { - ::std::cell::BorrowState::Unused => resolution.borrow_mut(), - _ => return Err(Determined), // This happens when there is a cycle of imports - }; + let resolution = self.resolution(module, name, ns) + .try_borrow_mut() + .map_err(|_| Determined)?; // This happens when there is a cycle of imports if let Some(span) = record_used { if let Some(binding) = resolution.binding { diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index e2da635b159..d842827b6fe 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -26,7 +26,6 @@ #![feature(associated_consts)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(cell_extras)] #![feature(const_fn)] #![feature(custom_attribute)] #![allow(unused_attributes)] diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 6419a9ff683..1a65bee13b8 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -10,7 +10,7 @@ use io::prelude::*; -use cell::{RefCell, BorrowState}; +use cell::RefCell; use fmt; use io::lazy::Lazy; use io::{self, BufReader, LineWriter}; @@ -638,8 +638,8 @@ pub fn _print(args: fmt::Arguments) { LocalKeyState::Destroyed => stdout().write_fmt(args), LocalKeyState::Valid => { LOCAL_STDOUT.with(|s| { - if s.borrow_state() == BorrowState::Unused { - if let Some(w) = s.borrow_mut().as_mut() { + if let Ok(mut borrowed) = s.try_borrow_mut() { + if let Some(w) = borrowed.as_mut() { return w.write_fmt(args); } } diff --git a/src/libstd/sys/redox/ext/process.rs b/src/libstd/sys/redox/ext/process.rs index 1472242d3db..c59524974bf 100644 --- a/src/libstd/sys/redox/ext/process.rs +++ b/src/libstd/sys/redox/ext/process.rs @@ -56,7 +56,7 @@ pub trait CommandExt { /// When this closure is run, aspects such as the stdio file descriptors and /// working directory have successfully been changed, so output to these /// locations may not appear where intended. - #[unstable(feature = "process_exec", issue = "31398")] + #[stable(feature = "process_exec", since = "1.15.0")] fn before_exec(&mut self, f: F) -> &mut process::Command where F: FnMut() -> io::Result<()> + Send + Sync + 'static; diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index b6a502e8c1a..53dafadb5d5 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -460,7 +460,6 @@ impl char { /// A buffer that's too small: /// /// ``` - /// #![feature(unicode)] /// use std::thread; /// /// let result = thread::spawn(|| { @@ -501,7 +500,6 @@ impl char { /// A buffer that's too small: /// /// ``` - /// #![feature(unicode)] /// use std::thread; /// /// let result = thread::spawn(|| { diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs index b086658ee0d..11724e74cda 100644 --- a/src/libstd_unicode/lib.rs +++ b/src/libstd_unicode/lib.rs @@ -39,7 +39,6 @@ #![feature(lang_items)] #![feature(staged_api)] #![feature(try_from)] -#![feature(unicode)] mod tables; mod u_str; -- cgit 1.4.1-3-g733a5 From 5a1b62c0fdaef10c26c6242252d0f15dbe5f92bc Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Thu, 15 Dec 2016 18:47:05 +0900 Subject: Fix Windows --- src/librustc_trans/back/msvc/registry.rs | 4 +--- src/libstd/sys/windows/c.rs | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/librustc_trans/back/msvc/registry.rs b/src/librustc_trans/back/msvc/registry.rs index 44b161a7575..8242f53896a 100644 --- a/src/librustc_trans/back/msvc/registry.rs +++ b/src/librustc_trans/back/msvc/registry.rs @@ -12,7 +12,7 @@ use std::io; use std::ffi::{OsString, OsStr}; use std::os::windows::prelude::*; use std::ptr; -use libc::{c_void, c_long}; +use libc::c_long; pub type DWORD = u32; type LPCWSTR = *const u16; @@ -38,8 +38,6 @@ pub enum __HKEY__ {} pub type HKEY = *mut __HKEY__; pub type PHKEY = *mut HKEY; pub type REGSAM = DWORD; -pub type LPWSTR = *mut u16; -pub type PFILETIME = *mut c_void; #[link(name = "advapi32")] extern "system" { diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 1a563127f7f..5384ef46e9a 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -47,7 +47,9 @@ pub type CHAR = c_char; pub type HCRYPTPROV = LONG_PTR; pub type ULONG_PTR = c_ulonglong; pub type ULONG = c_ulong; +#[cfg(target_arch = "x86_64")] pub type ULONGLONG = u64; +#[cfg(target_arch = "x86_64")] pub type DWORDLONG = ULONGLONG; pub type LPBOOL = *mut BOOL; @@ -66,7 +68,6 @@ pub type LPVOID = *mut c_void; pub type LPWCH = *mut WCHAR; pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW; pub type LPWSADATA = *mut WSADATA; -pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN; pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO; pub type LPWSTR = *mut WCHAR; pub type LPFILETIME = *mut FILETIME; @@ -311,8 +312,6 @@ pub struct WSADATA { pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1], } -pub type WSAEVENT = HANDLE; - #[repr(C)] pub struct WSAPROTOCOL_INFO { pub dwServiceFlags1: DWORD, -- cgit 1.4.1-3-g733a5 From 86fc63e62ddc0a271210b8cc7cc2a6de6874b8f8 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Fri, 25 Nov 2016 13:21:49 -0500 Subject: Implement `fmt::Debug` for all structures in libstd. Part of https://github.com/rust-lang/rust/issues/31869. Also turn on the `missing_debug_implementations` lint at the crate level. --- src/libstd/ascii.rs | 8 +++ src/libstd/collections/hash/map.rs | 83 +++++++++++++++++++++++++++++++- src/libstd/collections/hash/set.rs | 77 +++++++++++++++++++++++++++++ src/libstd/collections/hash/table.rs | 29 +++++++++++ src/libstd/env.rs | 36 ++++++++++++++ src/libstd/fs.rs | 18 ++++++- src/libstd/io/mod.rs | 15 ++++++ src/libstd/io/stdio.rs | 42 ++++++++++++++++ src/libstd/io/util.rs | 22 +++++++++ src/libstd/lib.rs | 2 + src/libstd/net/mod.rs | 8 +++ src/libstd/net/tcp.rs | 1 + src/libstd/os/linux/raw.rs | 1 + src/libstd/os/macos/raw.rs | 2 +- src/libstd/os/raw.rs | 9 ++++ src/libstd/panic.rs | 10 ++++ src/libstd/panicking.rs | 2 + src/libstd/process.rs | 39 +++++++++++++++ src/libstd/rand/mod.rs | 7 +++ src/libstd/sync/barrier.rs | 17 +++++++ src/libstd/sync/condvar.rs | 8 +++ src/libstd/sync/mpsc/mod.rs | 3 ++ src/libstd/sync/mutex.rs | 9 ++++ src/libstd/sync/once.rs | 9 ++++ src/libstd/sync/rwlock.rs | 18 +++++++ src/libstd/sys/unix/fast_thread_local.rs | 7 +++ src/libstd/sys/unix/fd.rs | 1 + src/libstd/sys/unix/fs.rs | 3 +- src/libstd/sys/windows/fs.rs | 3 +- src/libstd/thread/local.rs | 18 ++++++- src/libstd/thread/mod.rs | 15 ++++++ 31 files changed, 515 insertions(+), 7 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index a063b856468..f5e9ec6d89d 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -12,6 +12,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use fmt; use mem; use ops::Range; use iter::FusedIterator; @@ -370,6 +371,13 @@ impl ExactSizeIterator for EscapeDefault {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for EscapeDefault {} +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for EscapeDefault { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("EscapeDefault { .. }") + } +} + static ASCII_LOWERCASE_MAP: [u8; 256] = [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 0b310eb2585..2fa3a9c4844 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1276,6 +1276,15 @@ impl<'a, K, V> Clone for Iter<'a, K, V> { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, K: Debug, V: Debug> fmt::Debug for Iter<'a, K, V> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + /// HashMap mutable values iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, K: 'a, V: 'a> { @@ -1285,7 +1294,7 @@ pub struct IterMut<'a, K: 'a, V: 'a> { /// HashMap move iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { - inner: table::IntoIter, + pub(super) inner: table::IntoIter, } /// HashMap keys iterator. @@ -1302,6 +1311,15 @@ impl<'a, K, V> Clone for Keys<'a, K, V> { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, K: Debug, V: Debug> fmt::Debug for Keys<'a, K, V> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + /// HashMap values iterator. #[stable(feature = "rust1", since = "1.0.0")] pub struct Values<'a, K: 'a, V: 'a> { @@ -1316,10 +1334,19 @@ impl<'a, K, V> Clone for Values<'a, K, V> { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, K: Debug, V: Debug> fmt::Debug for Values<'a, K, V> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + /// HashMap drain iterator. #[stable(feature = "drain", since = "1.6.0")] pub struct Drain<'a, K: 'a, V: 'a> { - inner: table::Drain<'a, K, V>, + pub(super) inner: table::Drain<'a, K, V>, } /// Mutable HashMap values iterator. @@ -1557,6 +1584,18 @@ impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {} +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, K, V> fmt::Debug for IterMut<'a, K, V> + where K: fmt::Debug, + V: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.inner.iter()) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for IntoIter { type Item = (K, V); @@ -1580,6 +1619,15 @@ impl ExactSizeIterator for IntoIter { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.inner.iter()) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for Keys<'a, K, V> { type Item = &'a K; @@ -1649,6 +1697,18 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {} +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, K, V> fmt::Debug for ValuesMut<'a, K, V> + where K: fmt::Debug, + V: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.inner.inner.iter()) + .finish() + } +} + #[stable(feature = "drain", since = "1.6.0")] impl<'a, K, V> Iterator for Drain<'a, K, V> { type Item = (K, V); @@ -1672,6 +1732,18 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K, V> FusedIterator for Drain<'a, K, V> {} +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, K, V> fmt::Debug for Drain<'a, K, V> + where K: fmt::Debug, + V: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.inner.iter()) + .finish() + } +} + impl<'a, K, V> Entry<'a, K, V> { #[stable(feature = "rust1", since = "1.0.0")] /// Ensures a value is in the entry by inserting the default if empty, and returns @@ -2148,6 +2220,13 @@ impl Default for RandomState { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for RandomState { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("RandomState { .. }") + } +} + impl super::Recover for HashMap where K: Eq + Hash + Borrow, S: BuildHasher, diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 72af612f569..341b050862f 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -948,6 +948,15 @@ impl<'a, K> ExactSizeIterator for Iter<'a, K> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K> FusedIterator for Iter<'a, K> {} +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, K: fmt::Debug> fmt::Debug for Iter<'a, K> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for IntoIter { type Item = K; @@ -968,6 +977,16 @@ impl ExactSizeIterator for IntoIter { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let entries_iter = self.iter.inner.iter().map(|(k, _)| k); + f.debug_list() + .entries(entries_iter) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K> Iterator for Drain<'a, K> { type Item = K; @@ -988,6 +1007,16 @@ impl<'a, K> ExactSizeIterator for Drain<'a, K> { #[unstable(feature = "fused", issue = "35602")] impl<'a, K> FusedIterator for Drain<'a, K> {} +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, K: fmt::Debug> fmt::Debug for Drain<'a, K> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let entries_iter = self.iter.inner.iter().map(|(k, _)| k); + f.debug_list() + .entries(entries_iter) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Clone for Intersection<'a, T, S> { fn clone(&self) -> Intersection<'a, T, S> { @@ -1021,6 +1050,18 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S> } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, T, S> fmt::Debug for Intersection<'a, T, S> + where T: fmt::Debug + Eq + Hash, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + #[unstable(feature = "fused", issue = "35602")] impl<'a, T, S> FusedIterator for Intersection<'a, T, S> where T: Eq + Hash, @@ -1068,6 +1109,18 @@ impl<'a, T, S> FusedIterator for Difference<'a, T, S> { } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, T, S> fmt::Debug for Difference<'a, T, S> + where T: fmt::Debug + Eq + Hash, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Clone for SymmetricDifference<'a, T, S> { fn clone(&self) -> SymmetricDifference<'a, T, S> { @@ -1097,6 +1150,18 @@ impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S> { } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, T, S> fmt::Debug for SymmetricDifference<'a, T, S> + where T: fmt::Debug + Eq + Hash, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Clone for Union<'a, T, S> { fn clone(&self) -> Union<'a, T, S> { @@ -1111,6 +1176,18 @@ impl<'a, T, S> FusedIterator for Union<'a, T, S> { } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, T, S> fmt::Debug for Union<'a, T, S> + where T: fmt::Debug + Eq + Hash, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, S> Iterator for Union<'a, T, S> where T: Eq + Hash, diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index a784d8e50f9..2cd9362a657 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -882,6 +882,15 @@ unsafe impl<'a, K: Sync, V: Sync> Sync for IterMut<'a, K, V> {} // but Send is the more useful bound unsafe impl<'a, K: Send, V: Send> Send for IterMut<'a, K, V> {} +impl<'a, K: 'a, V: 'a> IterMut<'a, K, V> { + pub fn iter(&self) -> Iter { + Iter { + iter: self.iter.clone(), + elems_left: self.elems_left, + } + } +} + /// Iterator over the entries in a table, consuming the table. pub struct IntoIter { table: RawTable, @@ -891,6 +900,15 @@ pub struct IntoIter { unsafe impl Sync for IntoIter {} unsafe impl Send for IntoIter {} +impl IntoIter { + pub fn iter(&self) -> Iter { + Iter { + iter: self.iter.clone(), + elems_left: self.table.size, + } + } +} + /// Iterator over the entries in a table, clearing the table. pub struct Drain<'a, K: 'a, V: 'a> { table: Shared>, @@ -901,6 +919,17 @@ pub struct Drain<'a, K: 'a, V: 'a> { unsafe impl<'a, K: Sync, V: Sync> Sync for Drain<'a, K, V> {} unsafe impl<'a, K: Send, V: Send> Send for Drain<'a, K, V> {} +impl<'a, K, V> Drain<'a, K, V> { + pub fn iter(&self) -> Iter { + unsafe { + Iter { + iter: self.iter.clone(), + elems_left: (**self.table).size, + } + } + } +} + impl<'a, K, V> Iterator for Iter<'a, K, V> { type Item = (&'a K, &'a V); diff --git a/src/libstd/env.rs b/src/libstd/env.rs index ee6a907f616..0521f301321 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -143,6 +143,13 @@ impl Iterator for Vars { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Vars { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Vars { .. }") + } +} + #[stable(feature = "env", since = "1.0.0")] impl Iterator for VarsOs { type Item = (OsString, OsString); @@ -150,6 +157,13 @@ impl Iterator for VarsOs { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for VarsOs { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("VarsOs { .. }") + } +} + /// Fetches the environment variable `key` from the current process. /// /// The returned result is `Ok(s)` if the environment variable is present and is @@ -364,6 +378,13 @@ impl<'a> Iterator for SplitPaths<'a> { fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a> fmt::Debug for SplitPaths<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("SplitPaths { .. }") + } +} + /// Error type returned from `std::env::join_paths` when paths fail to be /// joined. #[derive(Debug)] @@ -640,6 +661,13 @@ impl DoubleEndedIterator for Args { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Args { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Args { .. }") + } +} + #[stable(feature = "env", since = "1.0.0")] impl Iterator for ArgsOs { type Item = OsString; @@ -657,6 +685,14 @@ impl ExactSizeIterator for ArgsOs { impl DoubleEndedIterator for ArgsOs { fn next_back(&mut self) -> Option { self.inner.next_back() } } + +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for ArgsOs { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("ArgsOs { .. }") + } +} + /// Constants associated with the current target #[stable(feature = "env", since = "1.0.0")] pub mod consts { diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index e91e808c548..176b5f66fc4 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -140,7 +140,7 @@ pub struct DirEntry(fs_imp::DirEntry); /// .create(true) /// .open("foo.txt"); /// ``` -#[derive(Clone)] +#[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub struct OpenOptions(fs_imp::OpenOptions); @@ -168,6 +168,7 @@ pub struct FileType(fs_imp::FileType); /// /// This builder also supports platform-specific options. #[stable(feature = "dir_builder", since = "1.6.0")] +#[derive(Debug)] pub struct DirBuilder { inner: fs_imp::DirBuilder, recursive: bool, @@ -834,6 +835,21 @@ impl Metadata { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Metadata { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Metadata") + .field("file_type", &self.file_type()) + .field("is_dir", &self.is_dir()) + .field("is_file", &self.is_file()) + .field("permissions", &self.permissions()) + .field("modified", &self.modified()) + .field("accessed", &self.accessed()) + .field("created", &self.created()) + .finish() + } +} + impl AsInner for Metadata { fn as_inner(&self) -> &fs_imp::FileAttr { &self.0 } } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index b07da0dc268..143a85ae321 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1444,6 +1444,16 @@ pub struct Chain { done_first: bool, } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Chain { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Chain") + .field("t", &self.first) + .field("u", &self.second) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Read for Chain { fn read(&mut self, buf: &mut [u8]) -> Result { @@ -1485,6 +1495,7 @@ impl BufRead for Chain { /// /// [`take()`]: trait.Read.html#method.take #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Take { inner: T, limit: u64, @@ -1602,6 +1613,7 @@ fn read_one_byte(reader: &mut Read) -> Option> { /// /// [`bytes()`]: trait.Read.html#method.bytes #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Bytes { inner: R, } @@ -1623,6 +1635,7 @@ impl Iterator for Bytes { /// [chars]: trait.Read.html#method.chars #[unstable(feature = "io", reason = "awaiting stability of Read::chars", issue = "27802")] +#[derive(Debug)] pub struct Chars { inner: R, } @@ -1712,6 +1725,7 @@ impl fmt::Display for CharsError { /// /// [split]: trait.BufRead.html#method.split #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Split { buf: B, delim: u8, @@ -1743,6 +1757,7 @@ impl Iterator for Split { /// /// [lines]: trait.BufRead.html#method.lines #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Lines { buf: B, } diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 1a65bee13b8..9d1c8942f8c 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -282,6 +282,13 @@ impl Stdin { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Stdin { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Stdin { .. }") + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Read for Stdin { fn read(&mut self, buf: &mut [u8]) -> io::Result { @@ -314,6 +321,13 @@ impl<'a> BufRead for StdinLock<'a> { fn consume(&mut self, n: usize) { self.inner.consume(n) } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a> fmt::Debug for StdinLock<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("StdinLock { .. }") + } +} + /// A handle to the global standard output stream of the current process. /// /// Each handle shares a global buffer of data to be written to the standard @@ -424,6 +438,13 @@ impl Stdout { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Stdout { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Stdout { .. }") + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { @@ -449,6 +470,13 @@ impl<'a> Write for StdoutLock<'a> { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a> fmt::Debug for StdoutLock<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("StdoutLock { .. }") + } +} + /// A handle to the standard error stream of a process. /// /// For more information, see the [`io::stderr`] method. @@ -545,6 +573,13 @@ impl Stderr { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Stderr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Stderr { .. }") + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result { @@ -570,6 +605,13 @@ impl<'a> Write for StderrLock<'a> { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a> fmt::Debug for StderrLock<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("StderrLock { .. }") + } +} + /// Resets the thread-local stderr handle to the specified writer /// /// This will replace the current thread's stderr handle, returning the old diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 2c6880281b5..436511031ef 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -10,6 +10,7 @@ #![allow(missing_copy_implementations)] +use fmt; use io::{self, Read, Write, ErrorKind, BufRead}; /// Copies the entire contents of a reader into a writer. @@ -97,6 +98,13 @@ impl BufRead for Empty { fn consume(&mut self, _n: usize) {} } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Empty { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Empty { .. }") + } +} + /// A reader which yields one byte over and over and over and over and over and... /// /// This struct is generally created by calling [`repeat()`][repeat]. Please @@ -133,6 +141,13 @@ impl Read for Repeat { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Repeat { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Repeat { .. }") + } +} + /// A writer which will move data into the void. /// /// This struct is generally created by calling [`sink()`][sink]. Please @@ -165,6 +180,13 @@ impl Write for Sink { fn flush(&mut self) -> io::Result<()> { Ok(()) } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Sink { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Sink { .. }") + } +} + #[cfg(test)] mod tests { use io::prelude::*; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 414f25fa5eb..fc5c6968544 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -214,6 +214,7 @@ #![no_std] #![deny(missing_docs)] +#![deny(missing_debug_implementations)] // Tell the compiler to link to either panic_abort or panic_unwind #![needs_panic_runtime] @@ -276,6 +277,7 @@ #![feature(panic_unwind)] #![feature(placement_in_syntax)] #![feature(prelude_import)] +#![feature(pub_restricted)] #![feature(rand)] #![feature(raw)] #![feature(repr_simd)] diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index 56286fbe253..cadf87f32b1 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -12,6 +12,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use fmt; use io::{self, Error, ErrorKind}; use sys_common::net as net_imp; @@ -105,6 +106,13 @@ impl Iterator for LookupHost { fn next(&mut self) -> Option { self.0.next() } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for LookupHost { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("LookupHost { .. }") + } +} + /// Resolve the host specified by `host` as a number of `SocketAddr` instances. /// /// This method may perform a DNS query to resolve `host` and may also inspect diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index be9636a0a19..63817c9f10f 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -76,6 +76,7 @@ pub struct TcpListener(net_imp::TcpListener); /// [`incoming`]: struct.TcpListener.html#method.incoming /// [`TcpListener`]: struct.TcpListener.html #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Incoming<'a> { listener: &'a TcpListener } impl TcpStream { diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs index e6a95bc831f..7c9274d0601 100644 --- a/src/libstd/os/linux/raw.rs +++ b/src/libstd/os/linux/raw.rs @@ -17,6 +17,7 @@ crates.io should be used instead for the correct \ definitions")] #![allow(deprecated)] +#![allow(missing_debug_implementations)] use os::raw::c_ulong; diff --git a/src/libstd/os/macos/raw.rs b/src/libstd/os/macos/raw.rs index 8f9b29462c4..0b96295f9e6 100644 --- a/src/libstd/os/macos/raw.rs +++ b/src/libstd/os/macos/raw.rs @@ -33,7 +33,7 @@ use os::raw::c_long; pub type pthread_t = usize; #[repr(C)] -#[derive(Clone)] +#[derive(Clone, Debug)] #[stable(feature = "raw_ext", since = "1.1.0")] pub struct stat { #[stable(feature = "raw_ext", since = "1.1.0")] diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs index 2a918d8aeb7..cc154f7ab41 100644 --- a/src/libstd/os/raw.rs +++ b/src/libstd/os/raw.rs @@ -12,6 +12,8 @@ #![stable(feature = "raw_os", since = "1.1.0")] +use fmt; + #[cfg(any(target_os = "android", target_os = "emscripten", all(target_os = "linux", any(target_arch = "aarch64", @@ -71,6 +73,13 @@ pub enum c_void { #[doc(hidden)] __variant2, } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for c_void { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("c_void") + } +} + #[cfg(test)] #[allow(unused_imports)] mod tests { diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index a7e8c4fab37..faf4949e861 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -14,6 +14,7 @@ use any::Any; use cell::UnsafeCell; +use fmt; use ops::{Deref, DerefMut}; use panicking; use ptr::{Unique, Shared}; @@ -296,6 +297,15 @@ impl R> FnOnce<()> for AssertUnwindSafe { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for AssertUnwindSafe { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("AssertUnwindSafe") + .field(&self.0) + .finish() + } +} + /// Invokes a closure, capturing the cause of an unwinding panic if one occurs. /// /// This function will return `Ok` with the closure's result if the closure diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 45a10d24528..e5edea241e1 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -177,6 +177,7 @@ pub fn take_hook() -> Box { /// panic!("Normal panic"); /// ``` #[stable(feature = "panic_hooks", since = "1.10.0")] +#[derive(Debug)] pub struct PanicInfo<'a> { payload: &'a (Any + Send), location: Location<'a>, @@ -256,6 +257,7 @@ impl<'a> PanicInfo<'a> { /// /// panic!("Normal panic"); /// ``` +#[derive(Debug)] #[stable(feature = "panic_hooks", since = "1.10.0")] pub struct Location<'a> { file: &'a str, diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 858537dd2de..66373615a1c 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -114,6 +114,17 @@ impl IntoInner for Child { fn into_inner(self) -> imp::Process { self.handle } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Child { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Child") + .field("stdin", &self.stdin) + .field("stdout", &self.stdout) + .field("stderr", &self.stderr) + .finish() + } +} + /// A handle to a child process's stdin. This struct is used in the [`stdin`] /// field on [`Child`]. /// @@ -149,6 +160,13 @@ impl FromInner for ChildStdin { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for ChildStdin { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("ChildStdin { .. }") + } +} + /// A handle to a child process's stdout. This struct is used in the [`stdout`] /// field on [`Child`]. /// @@ -183,6 +201,13 @@ impl FromInner for ChildStdout { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for ChildStdout { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("ChildStdout { .. }") + } +} + /// A handle to a child process's stderr. This struct is used in the [`stderr`] /// field on [`Child`]. /// @@ -217,6 +242,13 @@ impl FromInner for ChildStderr { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for ChildStderr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("ChildStderr { .. }") + } +} + /// A process builder, providing fine-grained control /// over how a new process should be spawned. /// @@ -622,6 +654,13 @@ impl FromInner for Stdio { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Stdio { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Stdio { .. }") + } +} + /// Describes the result of a process after it has terminated. #[derive(PartialEq, Eq, Clone, Copy, Debug)] #[stable(feature = "process", since = "1.0.0")] diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index f48325218fb..b853e83de5d 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -59,6 +59,7 @@ #![unstable(feature = "rand", issue = "0")] use cell::RefCell; +use fmt; use io; use mem; use rc::Rc; @@ -143,6 +144,12 @@ pub struct ThreadRng { rng: Rc>, } +impl fmt::Debug for ThreadRng { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("ThreadRng { .. }") + } +} + /// Retrieve the lazily-initialized thread-local random number /// generator, seeded by the system. Intended to be used in method /// chaining style, e.g. `thread_rng().gen::()`. diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index f46eab68484..b8e83dced8d 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use fmt; use sync::{Mutex, Condvar}; /// A barrier enables multiple threads to synchronize the beginning @@ -54,6 +55,13 @@ struct BarrierState { #[stable(feature = "rust1", since = "1.0.0")] pub struct BarrierWaitResult(bool); +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Barrier { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Barrier { .. }") + } +} + impl Barrier { /// Creates a new barrier that can block a given number of threads. /// @@ -102,6 +110,15 @@ impl Barrier { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for BarrierWaitResult { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("BarrierWaitResult") + .field("is_leader", &self.is_leader()) + .finish() + } +} + impl BarrierWaitResult { /// Returns whether this thread from `wait` is the "leader thread". /// diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index a983ae716a4..8ab30c51b28 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use fmt; use sync::atomic::{AtomicUsize, Ordering}; use sync::{mutex, MutexGuard, PoisonError}; use sys_common::condvar as sys; @@ -239,6 +240,13 @@ impl Condvar { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Condvar { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Condvar { .. }") + } +} + #[stable(feature = "condvar_default", since = "1.9.0")] impl Default for Condvar { /// Creates a `Condvar` which is ready to be waited on and notified. diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 63745388eb6..756d02b625f 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -306,6 +306,7 @@ impl !Sync for Receiver { } /// whenever `next` is called, waiting for a new message, and `None` will be /// returned when the corresponding channel has hung up. #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Iter<'a, T: 'a> { rx: &'a Receiver } @@ -317,6 +318,7 @@ pub struct Iter<'a, T: 'a> { /// This Iterator will never block the caller in order to wait for data to /// become available. Instead, it will return `None`. #[stable(feature = "receiver_try_iter", since = "1.15.0")] +#[derive(Debug)] pub struct TryIter<'a, T: 'a> { rx: &'a Receiver } @@ -325,6 +327,7 @@ pub struct TryIter<'a, T: 'a> { /// whenever `next` is called, waiting for a new message, and `None` will be /// returned when the corresponding channel has hung up. #[stable(feature = "receiver_into_iter", since = "1.1.0")] +#[derive(Debug)] pub struct IntoIter { rx: Receiver } diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index df4a3746a49..f6dbe01d7bd 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -351,6 +351,15 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("MutexGuard") + .field("lock", &self.__lock) + .finish() + } +} + pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { &guard.__lock.inner } diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 71e163321ae..a9747639aac 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -64,6 +64,7 @@ // You'll find a few more details in the implementation, but that's the gist of // it! +use fmt; use marker; use ptr; use sync::atomic::{AtomicUsize, AtomicBool, Ordering}; @@ -103,6 +104,7 @@ unsafe impl Send for Once {} /// State yielded to the `call_once_force` method which can be used to query /// whether the `Once` was previously poisoned or not. #[unstable(feature = "once_poison", issue = "33577")] +#[derive(Debug)] pub struct OnceState { poisoned: bool, } @@ -328,6 +330,13 @@ impl Once { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for Once { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Once { .. }") + } +} + impl Drop for Finish { fn drop(&mut self) { // Swap out our state with however we finished. We should only ever see diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index f83cf7ba9c2..0a11c71706b 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -362,6 +362,24 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("RwLockReadGuard") + .field("lock", &self.__lock) + .finish() + } +} + +#[stable(feature = "std_debug", since = "1.15.0")] +impl<'a, T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("RwLockWriteGuard") + .field("lock", &self.__lock) + .finish() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'rwlock, T: ?Sized> Deref for RwLockReadGuard<'rwlock, T> { type Target = T; diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs index 0c625e7add9..f4f73646e1b 100644 --- a/src/libstd/sys/unix/fast_thread_local.rs +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -12,6 +12,7 @@ #![unstable(feature = "thread_local_internals", issue = "0")] use cell::{Cell, UnsafeCell}; +use fmt; use intrinsics; use ptr; @@ -24,6 +25,12 @@ pub struct Key { dtor_running: Cell, } +impl fmt::Debug for Key { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Key { .. }") + } +} + unsafe impl ::marker::Sync for Key { } impl Key { diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index 61eb60da486..2384d959881 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -18,6 +18,7 @@ use sys::cvt; use sys_common::AsInner; use sys_common::io::read_to_end_uninitialized; +#[derive(Debug)] pub struct FileDesc { fd: c_int, } diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 9ee0458b5da..8b5c0c04276 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -66,7 +66,7 @@ pub struct DirEntry { name: Box<[u8]> } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct OpenOptions { // generic read: bool, @@ -86,6 +86,7 @@ pub struct FilePermissions { mode: mode_t } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct FileType { mode: mode_t } +#[derive(Debug)] pub struct DirBuilder { mode: mode_t } impl FileAttr { diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 7d7d78bbd87..c410fcd1ee0 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -58,7 +58,7 @@ pub struct DirEntry { data: c::WIN32_FIND_DATAW, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct OpenOptions { // generic read: bool, @@ -79,6 +79,7 @@ pub struct OpenOptions { #[derive(Clone, PartialEq, Eq, Debug)] pub struct FilePermissions { attrs: c::DWORD } +#[derive(Debug)] pub struct DirBuilder; impl fmt::Debug for ReadDir { diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index f74dd592495..01584979aab 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -13,6 +13,7 @@ #![unstable(feature = "thread_local_internals", issue = "0")] use cell::UnsafeCell; +use fmt; use mem; /// A thread local storage key which owns its contents. @@ -98,6 +99,13 @@ pub struct LocalKey { init: fn() -> T, } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for LocalKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("LocalKey { .. }") + } +} + /// Declare a new thread local storage key of type `std::thread::LocalKey`. /// /// # Syntax @@ -184,7 +192,7 @@ macro_rules! __thread_local_inner { #[unstable(feature = "thread_local_state", reason = "state querying was recently added", issue = "27716")] -#[derive(Eq, PartialEq, Copy, Clone)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum LocalKeyState { /// All keys are in this state whenever a thread starts. Keys will /// transition to the `Valid` state once the first call to `with` happens @@ -313,6 +321,7 @@ impl LocalKey { #[doc(hidden)] pub mod os { use cell::{Cell, UnsafeCell}; + use fmt; use marker; use ptr; use sys_common::thread_local::StaticKey as OsStaticKey; @@ -323,6 +332,13 @@ pub mod os { marker: marker::PhantomData>, } + #[stable(feature = "std_debug", since = "1.15.0")] + impl fmt::Debug for Key { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Key { .. }") + } + } + unsafe impl ::marker::Sync for Key { } struct Value { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 255cd2a9bc0..8cfa0200bf8 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -203,6 +203,7 @@ pub use self::local::{LocalKey, LocalKeyState}; /// Thread configuration. Provides detailed control over the properties /// and behavior of new threads. #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Debug)] pub struct Builder { // A name for the thread-to-be, for identification in panic messages name: Option, @@ -573,6 +574,13 @@ impl ThreadId { } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for ThreadId { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("ThreadId { .. }") + } +} + //////////////////////////////////////////////////////////////////////////////// // Thread //////////////////////////////////////////////////////////////////////////////// @@ -788,6 +796,13 @@ impl IntoInner for JoinHandle { fn into_inner(self) -> imp::Thread { self.0.native.unwrap() } } +#[stable(feature = "std_debug", since = "1.15.0")] +impl fmt::Debug for JoinHandle { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("JoinHandle { .. }") + } +} + fn _assert_sync_and_send() { fn _assert_both() {} _assert_both::>(); -- cgit 1.4.1-3-g733a5 From 57bc1a982e20524bbaac892c04e537c8f714dce6 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 20 Dec 2016 11:17:09 -0700 Subject: Add arm syscalls --- src/libstd/sys/redox/syscall/arch/arm.rs | 72 +++++++++++++++++++++++++++++ src/libstd/sys/redox/syscall/arch/x86.rs | 72 +++++++++++++++++++++++++++++ src/libstd/sys/redox/syscall/arch/x86_64.rs | 72 +++++++++++++++++++++++++++++ src/libstd/sys/redox/syscall/mod.rs | 8 +++- src/libstd/sys/redox/syscall/x86.rs | 72 ----------------------------- src/libstd/sys/redox/syscall/x86_64.rs | 72 ----------------------------- 6 files changed, 222 insertions(+), 146 deletions(-) create mode 100644 src/libstd/sys/redox/syscall/arch/arm.rs create mode 100644 src/libstd/sys/redox/syscall/arch/x86.rs create mode 100644 src/libstd/sys/redox/syscall/arch/x86_64.rs delete mode 100644 src/libstd/sys/redox/syscall/x86.rs delete mode 100644 src/libstd/sys/redox/syscall/x86_64.rs (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/syscall/arch/arm.rs b/src/libstd/sys/redox/syscall/arch/arm.rs new file mode 100644 index 00000000000..6e8bc2c0e63 --- /dev/null +++ b/src/libstd/sys/redox/syscall/arch/arm.rs @@ -0,0 +1,72 @@ +use super::error::{Error, Result}; + +pub unsafe fn syscall0(mut a: usize) -> Result { + asm!("swi $$0" + : "={r0}"(a) + : "{r7}"(a) + : "memory" + : "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall1(mut a: usize, b: usize) -> Result { + asm!("swi $$0" + : "={r0}"(a) + : "{r7}"(a), "{r0}"(b) + : "memory" + : "volatile"); + + Error::demux(a) +} + +// Clobbers all registers - special for clone +pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result { + asm!("swi $$0" + : "={r0}"(a) + : "{r7}"(a), "{r0}"(b) + : "memory", "r0", "r1", "r2", "r3", "r4" + : "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result { + asm!("swi $$0" + : "={r0}"(a) + : "{r7}"(a), "{r0}"(b), "{r1}"(c) + : "memory" + : "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result { + asm!("swi $$0" + : "={r0}"(a) + : "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d) + : "memory" + : "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result { + asm!("swi $$0" + : "={r0}"(a) + : "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d), "{r3}"(e) + : "memory" + : "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result { + asm!("swi $$0" + : "={r0}"(a) + : "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d), "{r3}"(e), "{r4}"(f) + : "memory" + : "volatile"); + + Error::demux(a) +} diff --git a/src/libstd/sys/redox/syscall/arch/x86.rs b/src/libstd/sys/redox/syscall/arch/x86.rs new file mode 100644 index 00000000000..4bb6060c43e --- /dev/null +++ b/src/libstd/sys/redox/syscall/arch/x86.rs @@ -0,0 +1,72 @@ +use super::error::{Error, Result}; + +pub unsafe fn syscall0(mut a: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall1(mut a: usize, b: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +// Clobbers all registers - special for clone +pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b) + : "memory", "ebx", "ecx", "edx", "esi", "edi" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b), "{ecx}"(c) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result { + asm!("int 0x80" + : "={eax}"(a) + : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e), "{edi}"(f) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} diff --git a/src/libstd/sys/redox/syscall/arch/x86_64.rs b/src/libstd/sys/redox/syscall/arch/x86_64.rs new file mode 100644 index 00000000000..6c1f96adef9 --- /dev/null +++ b/src/libstd/sys/redox/syscall/arch/x86_64.rs @@ -0,0 +1,72 @@ +use super::error::{Error, Result}; + +pub unsafe fn syscall0(mut a: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall1(mut a: usize, b: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +// Clobbers all registers - special for clone +pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b) + : "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b), "{rcx}"(c) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} + +pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result { + asm!("int 0x80" + : "={rax}"(a) + : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e), "{rdi}"(f) + : "memory" + : "intel", "volatile"); + + Error::demux(a) +} diff --git a/src/libstd/sys/redox/syscall/mod.rs b/src/libstd/sys/redox/syscall/mod.rs index 77f98d5b36b..34a35b967b1 100644 --- a/src/libstd/sys/redox/syscall/mod.rs +++ b/src/libstd/sys/redox/syscall/mod.rs @@ -6,12 +6,16 @@ pub use self::flag::*; pub use self::number::*; pub use self::scheme::*; +#[cfg(target_arch = "arm")] +#[path="arch/arm.rs"] +mod arch; + #[cfg(target_arch = "x86")] -#[path="x86.rs"] +#[path="arch/x86.rs"] mod arch; #[cfg(target_arch = "x86_64")] -#[path="x86_64.rs"] +#[path="arch/x86_64.rs"] mod arch; /// Function definitions diff --git a/src/libstd/sys/redox/syscall/x86.rs b/src/libstd/sys/redox/syscall/x86.rs deleted file mode 100644 index 4bb6060c43e..00000000000 --- a/src/libstd/sys/redox/syscall/x86.rs +++ /dev/null @@ -1,72 +0,0 @@ -use super::error::{Error, Result}; - -pub unsafe fn syscall0(mut a: usize) -> Result { - asm!("int 0x80" - : "={eax}"(a) - : "{eax}"(a) - : "memory" - : "intel", "volatile"); - - Error::demux(a) -} - -pub unsafe fn syscall1(mut a: usize, b: usize) -> Result { - asm!("int 0x80" - : "={eax}"(a) - : "{eax}"(a), "{ebx}"(b) - : "memory" - : "intel", "volatile"); - - Error::demux(a) -} - -// Clobbers all registers - special for clone -pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result { - asm!("int 0x80" - : "={eax}"(a) - : "{eax}"(a), "{ebx}"(b) - : "memory", "ebx", "ecx", "edx", "esi", "edi" - : "intel", "volatile"); - - Error::demux(a) -} - -pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result { - asm!("int 0x80" - : "={eax}"(a) - : "{eax}"(a), "{ebx}"(b), "{ecx}"(c) - : "memory" - : "intel", "volatile"); - - Error::demux(a) -} - -pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result { - asm!("int 0x80" - : "={eax}"(a) - : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d) - : "memory" - : "intel", "volatile"); - - Error::demux(a) -} - -pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result { - asm!("int 0x80" - : "={eax}"(a) - : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e) - : "memory" - : "intel", "volatile"); - - Error::demux(a) -} - -pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result { - asm!("int 0x80" - : "={eax}"(a) - : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e), "{edi}"(f) - : "memory" - : "intel", "volatile"); - - Error::demux(a) -} diff --git a/src/libstd/sys/redox/syscall/x86_64.rs b/src/libstd/sys/redox/syscall/x86_64.rs deleted file mode 100644 index 6c1f96adef9..00000000000 --- a/src/libstd/sys/redox/syscall/x86_64.rs +++ /dev/null @@ -1,72 +0,0 @@ -use super::error::{Error, Result}; - -pub unsafe fn syscall0(mut a: usize) -> Result { - asm!("int 0x80" - : "={rax}"(a) - : "{rax}"(a) - : "memory" - : "intel", "volatile"); - - Error::demux(a) -} - -pub unsafe fn syscall1(mut a: usize, b: usize) -> Result { - asm!("int 0x80" - : "={rax}"(a) - : "{rax}"(a), "{rbx}"(b) - : "memory" - : "intel", "volatile"); - - Error::demux(a) -} - -// Clobbers all registers - special for clone -pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result { - asm!("int 0x80" - : "={rax}"(a) - : "{rax}"(a), "{rbx}"(b) - : "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" - : "intel", "volatile"); - - Error::demux(a) -} - -pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result { - asm!("int 0x80" - : "={rax}"(a) - : "{rax}"(a), "{rbx}"(b), "{rcx}"(c) - : "memory" - : "intel", "volatile"); - - Error::demux(a) -} - -pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result { - asm!("int 0x80" - : "={rax}"(a) - : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d) - : "memory" - : "intel", "volatile"); - - Error::demux(a) -} - -pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result { - asm!("int 0x80" - : "={rax}"(a) - : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e) - : "memory" - : "intel", "volatile"); - - Error::demux(a) -} - -pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result { - asm!("int 0x80" - : "={rax}"(a) - : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e), "{rdi}"(f) - : "memory" - : "intel", "volatile"); - - Error::demux(a) -} -- cgit 1.4.1-3-g733a5 From 214a6c61666202ab073fceaeab13885027c8c3f2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 20 Dec 2016 12:18:55 -0800 Subject: Fix compile errors and such --- src/librustc_resolve/lib.rs | 2 +- src/libstd/os/macos/raw.rs | 2 +- src/libstd/os/mod.rs | 2 +- src/libstd/sys/mod.rs | 2 ++ src/libstd/sys/unix/ext/net.rs | 7 +++---- src/libstd/sys_common/mod.rs | 1 + 6 files changed, 9 insertions(+), 7 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 18d7499e751..f73227681c5 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1358,7 +1358,7 @@ impl<'a> Resolver<'a> { span: span, name: ident.name, lexical: false, b1: b1, b2: b2, legacy: legacy, }); if legacy { - self.record_use(name, ns, b1, span); + self.record_use(ident, ns, b1, span); } !legacy } diff --git a/src/libstd/os/macos/raw.rs b/src/libstd/os/macos/raw.rs index 0b96295f9e6..8f9b29462c4 100644 --- a/src/libstd/os/macos/raw.rs +++ b/src/libstd/os/macos/raw.rs @@ -33,7 +33,7 @@ use os::raw::c_long; pub type pthread_t = usize; #[repr(C)] -#[derive(Clone, Debug)] +#[derive(Clone)] #[stable(feature = "raw_ext", since = "1.1.0")] pub struct stat { #[stable(feature = "raw_ext", since = "1.1.0")] diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index 58f1604de1c..e45af867055 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -11,7 +11,7 @@ //! OS-specific functionality. #![stable(feature = "os", since = "1.0.0")] -#![allow(missing_docs, bad_style)] +#![allow(missing_docs, bad_style, missing_debug_implementations)] #[cfg(any(target_os = "redox", unix))] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index e4b0d980c92..14da376efa9 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -30,6 +30,8 @@ //! inter-dependencies within `std` that will be a challenging goal to //! achieve. +#![allow(missing_debug_implementations)] + pub use self::imp::*; #[cfg(target_os = "redox")] diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index e822488c018..1ba4a104e51 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -141,7 +141,7 @@ impl SocketAddr { /// /// A named address: /// - /// ``` + /// ```no_run /// use std::os::unix::net::UnixListener; /// /// let socket = UnixListener::bind("/tmp/sock").unwrap(); @@ -173,7 +173,7 @@ impl SocketAddr { /// /// With a pathname: /// - /// ``` + /// ```no_run /// use std::os::unix::net::UnixListener; /// use std::path::Path; /// @@ -186,7 +186,6 @@ impl SocketAddr { /// /// ``` /// use std::os::unix::net::UnixDatagram; - /// use std::path::Path; /// /// let socket = UnixDatagram::unbound().unwrap(); /// let addr = socket.local_addr().expect("Couldn't get local address"); @@ -624,7 +623,7 @@ impl UnixListener { /// /// # Examples /// - /// ``` + /// ```no_run /// use std::os::unix::net::UnixListener; /// /// let listener = match UnixListener::bind("/path/to/the/socket") { diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 5c07e36508c..634d6258885 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -23,6 +23,7 @@ //! `std::sys` from the standard library. #![allow(missing_docs)] +#![allow(missing_debug_implementations)] use sync::Once; use sys; -- cgit 1.4.1-3-g733a5 From e55596fa2011254fc29e7b386fb36416c79cf17f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 20 Dec 2016 15:26:58 -0700 Subject: Move rt into sys::rt, fix tidy --- src/libstd/rt.rs | 5 +- src/libstd/sys/redox/mod.rs | 2 +- src/libstd/sys/redox/net/netc.rs | 10 ++ src/libstd/sys/redox/rt.rs | 130 ++++++++++++++++ src/libstd/sys/redox/start.rs | 118 -------------- src/libstd/sys/redox/syscall/arch/arm.rs | 13 +- src/libstd/sys/redox/syscall/arch/x86.rs | 13 +- src/libstd/sys/redox/syscall/arch/x86_64.rs | 16 +- src/libstd/sys/redox/syscall/call.rs | 21 ++- src/libstd/sys/redox/syscall/data.rs | 94 ++--------- src/libstd/sys/redox/syscall/error.rs | 10 ++ src/libstd/sys/redox/syscall/flag.rs | 10 ++ src/libstd/sys/redox/syscall/mod.rs | 14 +- src/libstd/sys/redox/syscall/number.rs | 10 ++ src/libstd/sys/redox/syscall/scheme.rs | 232 ---------------------------- src/libstd/sys/unix/mod.rs | 1 + src/libstd/sys/unix/rt.rs | 11 ++ src/libstd/sys/windows/mod.rs | 1 + src/libstd/sys/windows/rt.rs | 11 ++ 19 files changed, 274 insertions(+), 448 deletions(-) create mode 100644 src/libstd/sys/redox/rt.rs delete mode 100644 src/libstd/sys/redox/start.rs delete mode 100644 src/libstd/sys/redox/syscall/scheme.rs create mode 100644 src/libstd/sys/unix/rt.rs create mode 100644 src/libstd/sys/windows/rt.rs (limited to 'src/libstd/sys') diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index abaa6358645..1f2b94239a8 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -26,9 +26,8 @@ pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count}; // Reexport the start module on platforms that provide it -#[unstable(feature = "start_fn", issue="0")] -#[cfg(target_os = "redox")] -pub use sys::start::*; +#[unstable(feature = "sys_rt", issue="0")] +pub use sys::rt::*; #[cfg(not(test))] #[lang = "start"] diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index fce1cb364fa..d4811a3444f 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -29,9 +29,9 @@ pub mod path; pub mod pipe; pub mod process; pub mod rand; +pub mod rt; pub mod rwlock; pub mod stack_overflow; -pub mod start; pub mod stdio; pub mod syscall; pub mod thread; diff --git a/src/libstd/sys/redox/net/netc.rs b/src/libstd/sys/redox/net/netc.rs index 78045c54fb2..03e1c9fffa4 100644 --- a/src/libstd/sys/redox/net/netc.rs +++ b/src/libstd/sys/redox/net/netc.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + pub type in_addr_t = u32; pub type in_port_t = u16; diff --git a/src/libstd/sys/redox/rt.rs b/src/libstd/sys/redox/rt.rs new file mode 100644 index 00000000000..0e854989c12 --- /dev/null +++ b/src/libstd/sys/redox/rt.rs @@ -0,0 +1,130 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Defintion of functions like _start for the linker + +use sys::syscall::exit; + +#[unstable(feature = "sys_rt", issue = "0")] +#[no_mangle] +#[naked] +#[cfg(target_arch = "x86")] +pub unsafe fn _start() { + asm!("push esp + call _start_stack + pop esp" + : + : + : "memory" + : "intel", "volatile"); + let _ = exit(0); +} + +#[unstable(feature = "sys_rt", issue = "0")] +#[no_mangle] +#[naked] +#[cfg(target_arch = "x86_64")] +pub unsafe fn _start() { + asm!("mov rdi, rsp + and rsp, 0xFFFFFFFFFFFFFFF0 + call _start_stack" + : + : + : "memory" + : "intel", "volatile"); + let _ = exit(0); +} + +#[unstable(feature = "sys_rt", issue = "0")] +#[no_mangle] +pub unsafe extern "C" fn _start_stack(stack: *const usize){ + extern "C" { + fn main(argc: usize, argv: *const *const u8) -> usize; + } + + let argc = *stack as usize; + let argv = stack.offset(1) as *const *const u8; + let _ = exit(main(argc, argv)); +} + +/// Memcpy +/// +/// Copy N bytes of memory from one location to another. +#[unstable(feature = "sys_rt", issue = "0")] +#[no_mangle] +pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8, + n: usize) -> *mut u8 { + let mut i = 0; + while i < n { + *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); + i += 1; + } + + dest +} + +/// Memmove +/// +/// Copy N bytes of memory from src to dest. The memory areas may overlap. +#[unstable(feature = "sys_rt", issue = "0")] +#[no_mangle] +pub unsafe extern fn memmove(dest: *mut u8, src: *const u8, + n: usize) -> *mut u8 { + if src < dest as *const u8 { + let mut i = n; + while i != 0 { + i -= 1; + *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); + } + } else { + let mut i = 0; + while i < n { + *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); + i += 1; + } + } + + dest +} + +/// Memset +/// +/// Fill a block of memory with a specified value. +#[unstable(feature = "sys_rt", issue = "0")] +#[no_mangle] +pub unsafe extern fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 { + let mut i = 0; + while i < n { + *((dest as usize + i) as *mut u8) = c as u8; + i += 1; + } + + dest +} + +/// Memcmp +/// +/// Compare two blocks of memory. +#[unstable(feature = "sys_rt", issue = "0")] +#[no_mangle] +pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { + let mut i = 0; + + while i < n { + let a = *((s1 as usize + i) as *const u8); + let b = *((s2 as usize + i) as *const u8); + if a != b { + return a as i32 - b as i32 + } + i += 1; + } + + 0 +} diff --git a/src/libstd/sys/redox/start.rs b/src/libstd/sys/redox/start.rs deleted file mode 100644 index 87f58a4773c..00000000000 --- a/src/libstd/sys/redox/start.rs +++ /dev/null @@ -1,118 +0,0 @@ -use sys::syscall::exit; - -#[unstable(feature = "start_fn", issue = "0")] -#[no_mangle] -#[naked] -#[cfg(target_arch = "x86")] -pub unsafe fn _start() { - asm!("push esp - call _start_stack - pop esp" - : - : - : "memory" - : "intel", "volatile"); - let _ = exit(0); -} - -#[unstable(feature = "start_fn", issue = "0")] -#[no_mangle] -#[naked] -#[cfg(target_arch = "x86_64")] -pub unsafe fn _start() { - asm!("mov rdi, rsp - and rsp, 0xFFFFFFFFFFFFFFF0 - call _start_stack" - : - : - : "memory" - : "intel", "volatile"); - let _ = exit(0); -} - -#[unstable(feature = "start_fn", issue = "0")] -#[no_mangle] -pub unsafe extern "C" fn _start_stack(stack: *const usize){ - extern "C" { - fn main(argc: usize, argv: *const *const u8) -> usize; - } - - let argc = *stack as usize; - let argv = stack.offset(1) as *const *const u8; - let _ = exit(main(argc, argv)); -} - -/// Memcpy -/// -/// Copy N bytes of memory from one location to another. -#[unstable(feature = "start_fn", issue = "0")] -#[no_mangle] -pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8, - n: usize) -> *mut u8 { - let mut i = 0; - while i < n { - *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); - i += 1; - } - - dest -} - -/// Memmove -/// -/// Copy N bytes of memory from src to dest. The memory areas may overlap. -#[unstable(feature = "start_fn", issue = "0")] -#[no_mangle] -pub unsafe extern fn memmove(dest: *mut u8, src: *const u8, - n: usize) -> *mut u8 { - if src < dest as *const u8 { - let mut i = n; - while i != 0 { - i -= 1; - *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); - } - } else { - let mut i = 0; - while i < n { - *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); - i += 1; - } - } - - dest -} - -/// Memset -/// -/// Fill a block of memory with a specified value. -#[unstable(feature = "start_fn", issue = "0")] -#[no_mangle] -pub unsafe extern fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 { - let mut i = 0; - while i < n { - *((dest as usize + i) as *mut u8) = c as u8; - i += 1; - } - - dest -} - -/// Memcmp -/// -/// Compare two blocks of memory. -#[unstable(feature = "start_fn", issue = "0")] -#[no_mangle] -pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { - let mut i = 0; - - while i < n { - let a = *((s1 as usize + i) as *const u8); - let b = *((s2 as usize + i) as *const u8); - if a != b { - return a as i32 - b as i32 - } - i += 1; - } - - 0 -} diff --git a/src/libstd/sys/redox/syscall/arch/arm.rs b/src/libstd/sys/redox/syscall/arch/arm.rs index 6e8bc2c0e63..9fb3961486d 100644 --- a/src/libstd/sys/redox/syscall/arch/arm.rs +++ b/src/libstd/sys/redox/syscall/arch/arm.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use super::error::{Error, Result}; pub unsafe fn syscall0(mut a: usize) -> Result { @@ -61,7 +71,8 @@ pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Error::demux(a) } -pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result { +pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) + -> Result { asm!("swi $$0" : "={r0}"(a) : "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d), "{r3}"(e), "{r4}"(f) diff --git a/src/libstd/sys/redox/syscall/arch/x86.rs b/src/libstd/sys/redox/syscall/arch/x86.rs index 4bb6060c43e..724a6b927f4 100644 --- a/src/libstd/sys/redox/syscall/arch/x86.rs +++ b/src/libstd/sys/redox/syscall/arch/x86.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use super::error::{Error, Result}; pub unsafe fn syscall0(mut a: usize) -> Result { @@ -61,7 +71,8 @@ pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Error::demux(a) } -pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result { +pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) + -> Result { asm!("int 0x80" : "={eax}"(a) : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e), "{edi}"(f) diff --git a/src/libstd/sys/redox/syscall/arch/x86_64.rs b/src/libstd/sys/redox/syscall/arch/x86_64.rs index 6c1f96adef9..a321c31f207 100644 --- a/src/libstd/sys/redox/syscall/arch/x86_64.rs +++ b/src/libstd/sys/redox/syscall/arch/x86_64.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use super::error::{Error, Result}; pub unsafe fn syscall0(mut a: usize) -> Result { @@ -25,7 +35,8 @@ pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result { asm!("int 0x80" : "={rax}"(a) : "{rax}"(a), "{rbx}"(b) - : "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" + : "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8", + "r9", "r10", "r11", "r12", "r13", "r14", "r15" : "intel", "volatile"); Error::demux(a) @@ -61,7 +72,8 @@ pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Error::demux(a) } -pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> Result { +pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) + -> Result { asm!("int 0x80" : "={rax}"(a) : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e), "{rdi}"(f) diff --git a/src/libstd/sys/redox/syscall/call.rs b/src/libstd/sys/redox/syscall/call.rs index 939ebf51072..f58c240f31e 100644 --- a/src/libstd/sys/redox/syscall/call.rs +++ b/src/libstd/sys/redox/syscall/call.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use super::arch::*; use super::data::{Stat, StatVfs, TimeSpec}; use super::error::Result; @@ -63,7 +73,8 @@ pub fn dup(fd: usize, buf: &[u8]) -> Result { /// Replace the current process with a new executable pub fn execve(path: &str, args: &[[usize; 2]]) -> Result { - unsafe { syscall4(SYS_EXECVE, path.as_ptr() as usize, path.len(), args.as_ptr() as usize, args.len()) } + unsafe { syscall4(SYS_EXECVE, path.as_ptr() as usize, path.len(), + args.as_ptr() as usize, args.len()) } } /// Exit the current process @@ -116,8 +127,9 @@ pub fn ftruncate(fd: usize, len: usize) -> Result { unsafe { syscall2(SYS_FTRUNCATE, fd, len) } } -/// Fast userspace mutex - TODO: Document -pub unsafe fn futex(addr: *mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32) -> Result { +/// Fast userspace mutex +pub unsafe fn futex(addr: *mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32) + -> Result { syscall5(SYS_FUTEX, addr as usize, op, (val as isize) as usize, val2, addr2 as usize) } @@ -188,7 +200,8 @@ pub fn mkns(schemes: &[[usize; 2]]) -> Result { /// Sleep for the time specified in `req` pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result { - unsafe { syscall2(SYS_NANOSLEEP, req as *const TimeSpec as usize, rem as *mut TimeSpec as usize) } + unsafe { syscall2(SYS_NANOSLEEP, req as *const TimeSpec as usize, + rem as *mut TimeSpec as usize) } } /// Open a file diff --git a/src/libstd/sys/redox/syscall/data.rs b/src/libstd/sys/redox/syscall/data.rs index 240690befde..223167d6bf7 100644 --- a/src/libstd/sys/redox/syscall/data.rs +++ b/src/libstd/sys/redox/syscall/data.rs @@ -1,60 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use core::ops::{Deref, DerefMut}; use core::{mem, slice}; -#[derive(Copy, Clone, Debug, Default)] -pub struct Event { - pub id: usize, - pub flags: usize, - pub data: usize -} - -impl Deref for Event { - type Target = [u8]; - fn deref(&self) -> &[u8] { - unsafe { - slice::from_raw_parts(self as *const Event as *const u8, mem::size_of::()) as &[u8] - } - } -} - -impl DerefMut for Event { - fn deref_mut(&mut self) -> &mut [u8] { - unsafe { - slice::from_raw_parts_mut(self as *mut Event as *mut u8, mem::size_of::()) as &mut [u8] - } - } -} - -#[derive(Copy, Clone, Debug, Default)] -#[repr(packed)] -pub struct Packet { - pub id: u64, - pub pid: usize, - pub uid: u32, - pub gid: u32, - pub a: usize, - pub b: usize, - pub c: usize, - pub d: usize -} - -impl Deref for Packet { - type Target = [u8]; - fn deref(&self) -> &[u8] { - unsafe { - slice::from_raw_parts(self as *const Packet as *const u8, mem::size_of::()) as &[u8] - } - } -} - -impl DerefMut for Packet { - fn deref_mut(&mut self) -> &mut [u8] { - unsafe { - slice::from_raw_parts_mut(self as *mut Packet as *mut u8, mem::size_of::()) as &mut [u8] - } - } -} - #[derive(Copy, Clone, Debug, Default)] #[repr(packed)] pub struct Stat { @@ -87,34 +43,8 @@ impl Deref for Stat { impl DerefMut for Stat { fn deref_mut(&mut self) -> &mut [u8] { unsafe { - slice::from_raw_parts_mut(self as *mut Stat as *mut u8, mem::size_of::()) as &mut [u8] - } - } -} - -#[derive(Copy, Clone, Debug, Default)] -#[repr(packed)] -pub struct StatVfs { - pub f_bsize: u32, - pub f_blocks: u64, - pub f_bfree: u64, - pub f_bavail: u64, - //TODO: More fields https://linux.die.net/man/2/statvfs -} - -impl Deref for StatVfs { - type Target = [u8]; - fn deref(&self) -> &[u8] { - unsafe { - slice::from_raw_parts(self as *const StatVfs as *const u8, mem::size_of::()) as &[u8] - } - } -} - -impl DerefMut for StatVfs { - fn deref_mut(&mut self) -> &mut [u8] { - unsafe { - slice::from_raw_parts_mut(self as *mut StatVfs as *mut u8, mem::size_of::()) as &mut [u8] + slice::from_raw_parts_mut(self as *mut Stat as *mut u8, + mem::size_of::()) as &mut [u8] } } } diff --git a/src/libstd/sys/redox/syscall/error.rs b/src/libstd/sys/redox/syscall/error.rs index 7cbcbe98765..d8d78d55016 100644 --- a/src/libstd/sys/redox/syscall/error.rs +++ b/src/libstd/sys/redox/syscall/error.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use core::{fmt, result}; #[derive(Eq, PartialEq)] diff --git a/src/libstd/sys/redox/syscall/flag.rs b/src/libstd/sys/redox/syscall/flag.rs index 97ff8e2d79a..9f0d3e6f779 100644 --- a/src/libstd/sys/redox/syscall/flag.rs +++ b/src/libstd/sys/redox/syscall/flag.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + pub const CLONE_VM: usize = 0x100; pub const CLONE_FS: usize = 0x200; pub const CLONE_FILES: usize = 0x400; diff --git a/src/libstd/sys/redox/syscall/mod.rs b/src/libstd/sys/redox/syscall/mod.rs index 34a35b967b1..ce789c269a7 100644 --- a/src/libstd/sys/redox/syscall/mod.rs +++ b/src/libstd/sys/redox/syscall/mod.rs @@ -1,10 +1,19 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + pub use self::arch::*; pub use self::call::*; pub use self::data::*; pub use self::error::*; pub use self::flag::*; pub use self::number::*; -pub use self::scheme::*; #[cfg(target_arch = "arm")] #[path="arch/arm.rs"] @@ -32,6 +41,3 @@ pub mod flag; /// Call numbers used by each system call pub mod number; - -/// A trait useful for scheme handlers -pub mod scheme; diff --git a/src/libstd/sys/redox/syscall/number.rs b/src/libstd/sys/redox/syscall/number.rs index 719c8af218f..358746cd20a 100644 --- a/src/libstd/sys/redox/syscall/number.rs +++ b/src/libstd/sys/redox/syscall/number.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + pub const SYS_CLASS: usize = 0xF000_0000; pub const SYS_CLASS_PATH: usize=0x1000_0000; pub const SYS_CLASS_FILE: usize=0x2000_0000; diff --git a/src/libstd/sys/redox/syscall/scheme.rs b/src/libstd/sys/redox/syscall/scheme.rs deleted file mode 100644 index d322f0b5a9c..00000000000 --- a/src/libstd/sys/redox/syscall/scheme.rs +++ /dev/null @@ -1,232 +0,0 @@ -use core::{mem, slice}; - -use super::*; - -pub trait Scheme { - fn handle(&self, packet: &mut Packet) { - packet.a = Error::mux(match packet.a { - SYS_OPEN => self.open(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d, packet.uid, packet.gid), - SYS_CHMOD => self.chmod(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d as u16, packet.uid, packet.gid), - SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid), - SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid), - - SYS_DUP => self.dup(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }), - SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }), - SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }), - SYS_LSEEK => self.seek(packet.b, packet.c, packet.d), - SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d), - SYS_FEVENT => self.fevent(packet.b, packet.c), - SYS_FMAP => self.fmap(packet.b, packet.c, packet.d), - SYS_FPATH => self.fpath(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }), - SYS_FSTAT => if packet.d >= mem::size_of::() { self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) }) } else { Err(Error::new(EFAULT)) }, - SYS_FSTATVFS => if packet.d >= mem::size_of::() { self.fstatvfs(packet.b, unsafe { &mut *(packet.c as *mut StatVfs) }) } else { Err(Error::new(EFAULT)) }, - SYS_FSYNC => self.fsync(packet.b), - SYS_FTRUNCATE => self.ftruncate(packet.b, packet.c), - SYS_CLOSE => self.close(packet.b), - - _ => Err(Error::new(ENOSYS)) - }); - } - - /* Scheme operations */ - - #[allow(unused_variables)] - fn open(&self, path: &[u8], flags: usize, uid: u32, gid: u32) -> Result { - Err(Error::new(ENOENT)) - } - - #[allow(unused_variables)] - fn chmod(&self, path: &[u8], mode: u16, uid: u32, gid: u32) -> Result { - Err(Error::new(ENOENT)) - } - - #[allow(unused_variables)] - fn rmdir(&self, path: &[u8], uid: u32, gid: u32) -> Result { - Err(Error::new(ENOENT)) - } - - #[allow(unused_variables)] - fn unlink(&self, path: &[u8], uid: u32, gid: u32) -> Result { - Err(Error::new(ENOENT)) - } - - /* Resource operations */ - #[allow(unused_variables)] - fn dup(&self, old_id: usize, buf: &[u8]) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn read(&self, id: usize, buf: &mut [u8]) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn write(&self, id: usize, buf: &[u8]) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn seek(&self, id: usize, pos: usize, whence: usize) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fevent(&self, id: usize, flags: usize) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fmap(&self, id: usize, offset: usize, size: usize) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fpath(&self, id: usize, buf: &mut [u8]) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fstat(&self, id: usize, stat: &mut Stat) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fstatvfs(&self, id: usize, stat: &mut StatVfs) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fsync(&self, id: usize) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn ftruncate(&self, id: usize, len: usize) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn close(&self, id: usize) -> Result { - Err(Error::new(EBADF)) - } -} - -pub trait SchemeMut { - fn handle(&mut self, packet: &mut Packet) { - packet.a = Error::mux(match packet.a { - SYS_OPEN => self.open(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d, packet.uid, packet.gid), - SYS_CHMOD => self.chmod(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.d as u16, packet.uid, packet.gid), - SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid), - SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid), - - SYS_DUP => self.dup(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }), - SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }), - SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }), - SYS_LSEEK => self.seek(packet.b, packet.c, packet.d), - SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d), - SYS_FEVENT => self.fevent(packet.b, packet.c), - SYS_FMAP => self.fmap(packet.b, packet.c, packet.d), - SYS_FPATH => self.fpath(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }), - SYS_FSTAT => if packet.d >= mem::size_of::() { self.fstat(packet.b, unsafe { &mut *(packet.c as *mut Stat) }) } else { Err(Error::new(EFAULT)) }, - SYS_FSTATVFS => if packet.d >= mem::size_of::() { self.fstatvfs(packet.b, unsafe { &mut *(packet.c as *mut StatVfs) }) } else { Err(Error::new(EFAULT)) }, - SYS_FSYNC => self.fsync(packet.b), - SYS_FTRUNCATE => self.ftruncate(packet.b, packet.c), - SYS_CLOSE => self.close(packet.b), - - _ => Err(Error::new(ENOSYS)) - }); - } - - /* Scheme operations */ - #[allow(unused_variables)] - fn open(&mut self, path: &[u8], flags: usize, uid: u32, gid: u32) -> Result { - Err(Error::new(ENOENT)) - } - - #[allow(unused_variables)] - fn chmod(&self, path: &[u8], mode: u16, uid: u32, gid: u32) -> Result { - Err(Error::new(ENOENT)) - } - - #[allow(unused_variables)] - fn rmdir(&mut self, path: &[u8], uid: u32, gid: u32) -> Result { - Err(Error::new(ENOENT)) - } - - #[allow(unused_variables)] - fn unlink(&mut self, path: &[u8], uid: u32, gid: u32) -> Result { - Err(Error::new(ENOENT)) - } - - /* Resource operations */ - #[allow(unused_variables)] - fn dup(&mut self, old_id: usize, buf: &[u8]) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn read(&mut self, id: usize, buf: &mut [u8]) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn write(&mut self, id: usize, buf: &[u8]) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fcntl(&mut self, id: usize, cmd: usize, arg: usize) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fevent(&mut self, id: usize, flags: usize) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fmap(&mut self, id: usize, offset: usize, size: usize) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fstatvfs(&self, id: usize, stat: &mut StatVfs) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn fsync(&mut self, id: usize) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn ftruncate(&mut self, id: usize, len: usize) -> Result { - Err(Error::new(EBADF)) - } - - #[allow(unused_variables)] - fn close(&mut self, id: usize) -> Result { - Err(Error::new(EBADF)) - } -} diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index fd7dc17cccd..5e14b392bdc 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -50,6 +50,7 @@ pub mod path; pub mod pipe; pub mod process; pub mod rand; +pub mod rt; pub mod rwlock; pub mod stack_overflow; pub mod thread; diff --git a/src/libstd/sys/unix/rt.rs b/src/libstd/sys/unix/rt.rs new file mode 100644 index 00000000000..188e31cb5d7 --- /dev/null +++ b/src/libstd/sys/unix/rt.rs @@ -0,0 +1,11 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Stub for placing functions like _start for the linker diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index defc41c5f46..52d256630a5 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -36,6 +36,7 @@ pub mod path; pub mod pipe; pub mod process; pub mod rand; +pub mod rt; pub mod rwlock; pub mod stack_overflow; pub mod thread; diff --git a/src/libstd/sys/windows/rt.rs b/src/libstd/sys/windows/rt.rs new file mode 100644 index 00000000000..188e31cb5d7 --- /dev/null +++ b/src/libstd/sys/windows/rt.rs @@ -0,0 +1,11 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Stub for placing functions like _start for the linker -- cgit 1.4.1-3-g733a5 From 65eecf8bb311efe4174cb7a90271344b72371884 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 20 Dec 2016 16:12:36 -0700 Subject: Readd statvfs --- src/libstd/sys/redox/syscall/data.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/syscall/data.rs b/src/libstd/sys/redox/syscall/data.rs index 223167d6bf7..11f007c52ab 100644 --- a/src/libstd/sys/redox/syscall/data.rs +++ b/src/libstd/sys/redox/syscall/data.rs @@ -49,6 +49,32 @@ impl DerefMut for Stat { } } +#[derive(Copy, Clone, Debug, Default)] +#[repr(packed)] +pub struct StatVfs { + pub f_bsize: u32, + pub f_blocks: u64, + pub f_bfree: u64, + pub f_bavail: u64, +} + +impl Deref for StatVfs { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const StatVfs as *const u8, mem::size_of::()) as &[u8] + } + } +} + +impl DerefMut for StatVfs { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut StatVfs as *mut u8, mem::size_of::()) as &mut [u8] + } + } +} + #[derive(Copy, Clone, Debug, Default)] #[repr(packed)] pub struct TimeSpec { -- cgit 1.4.1-3-g733a5 From fd4bc88880bd7aeb2a1a5cb56fbfea639bc6f2e7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 20 Dec 2016 17:52:47 -0700 Subject: Fix building without backtrace --- src/libstd/sys/redox/mod.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index d4811a3444f..a8dbac28fb6 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -13,6 +13,7 @@ use io::{self, ErrorKind}; pub mod args; +#[cfg(any(not(cargobuild), feature = "backtrace"))] pub mod backtrace; pub mod condvar; pub mod env; -- cgit 1.4.1-3-g733a5 From bf50acbc09fe1acd627b8d4879e26b07d89e31e2 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 20 Dec 2016 21:29:42 -0700 Subject: Fix tidy --- src/libstd/sys/redox/syscall/data.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/syscall/data.rs b/src/libstd/sys/redox/syscall/data.rs index 11f007c52ab..ac3946672a3 100644 --- a/src/libstd/sys/redox/syscall/data.rs +++ b/src/libstd/sys/redox/syscall/data.rs @@ -35,7 +35,8 @@ impl Deref for Stat { type Target = [u8]; fn deref(&self) -> &[u8] { unsafe { - slice::from_raw_parts(self as *const Stat as *const u8, mem::size_of::()) as &[u8] + slice::from_raw_parts(self as *const Stat as *const u8, + mem::size_of::()) as &[u8] } } } @@ -62,7 +63,8 @@ impl Deref for StatVfs { type Target = [u8]; fn deref(&self) -> &[u8] { unsafe { - slice::from_raw_parts(self as *const StatVfs as *const u8, mem::size_of::()) as &[u8] + slice::from_raw_parts(self as *const StatVfs as *const u8, + mem::size_of::()) as &[u8] } } } @@ -70,7 +72,8 @@ impl Deref for StatVfs { impl DerefMut for StatVfs { fn deref_mut(&mut self) -> &mut [u8] { unsafe { - slice::from_raw_parts_mut(self as *mut StatVfs as *mut u8, mem::size_of::()) as &mut [u8] + slice::from_raw_parts_mut(self as *mut StatVfs as *mut u8, + mem::size_of::()) as &mut [u8] } } } -- cgit 1.4.1-3-g733a5 From 88af5bf5ecfebe1683ab449213d218de7871cc92 Mon Sep 17 00:00:00 2001 From: Jason Campbell Date: Wed, 21 Dec 2016 13:28:08 -0800 Subject: Removes magenta build warning. Small bug fix to remove an unused type in the magenta process code that causes build failures for magenta's rustc. --- src/libstd/sys/unix/process/magenta.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/unix/process/magenta.rs b/src/libstd/sys/unix/process/magenta.rs index 319fbce35cd..2bb005be4ec 100644 --- a/src/libstd/sys/unix/process/magenta.rs +++ b/src/libstd/sys/unix/process/magenta.rs @@ -23,7 +23,6 @@ pub type mx_rights_t = u32; pub type mx_status_t = i32; pub type mx_size_t = usize; -pub type mx_ssize_t = isize; pub const MX_HANDLE_INVALID: mx_handle_t = 0; -- cgit 1.4.1-3-g733a5 From 7d3ae874534421e3cca560f33175e61cb2262fd0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 21 Dec 2016 20:19:19 -0700 Subject: Add RawFd traits for net --- src/libstd/sys/redox/ext/io.rs | 35 ++++++++++++++++++++--------------- src/libstd/sys/redox/net/tcp.rs | 29 +++++++++++++++++++++++++++++ src/libstd/sys/redox/net/udp.rs | 15 +++++++++++++++ 3 files changed, 64 insertions(+), 15 deletions(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/ext/io.rs b/src/libstd/sys/redox/ext/io.rs index 135e31fae1e..8e7cc593dbd 100644 --- a/src/libstd/sys/redox/ext/io.rs +++ b/src/libstd/sys/redox/ext/io.rs @@ -13,8 +13,9 @@ #![stable(feature = "rust1", since = "1.0.0")] use fs; +use net; use sys; -use sys_common::{AsInner, FromInner, IntoInner}; +use sys_common::{self, AsInner, FromInner, IntoInner}; /// Raw file descriptors. #[stable(feature = "rust1", since = "1.0.0")] @@ -89,58 +90,62 @@ impl IntoRawFd for fs::File { } } -/* #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::TcpStream { - fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } + fn as_raw_fd(&self) -> RawFd { + self.as_inner().as_inner().fd().raw() + } } #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::TcpListener { - fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } + fn as_raw_fd(&self) -> RawFd { + self.as_inner().as_inner().fd().raw() + } } #[stable(feature = "rust1", since = "1.0.0")] impl AsRawFd for net::UdpSocket { - fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } + fn as_raw_fd(&self) -> RawFd { + self.as_inner().as_inner().fd().raw() + } } #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for net::TcpStream { unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { - let socket = sys::net::Socket::from_inner(fd); - net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket)) + let file = sys::fs::File::from_inner(fd); + net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(file)) } } #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for net::TcpListener { unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener { - let socket = sys::net::Socket::from_inner(fd); - net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket)) + let file = sys::fs::File::from_inner(fd); + net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(file)) } } #[stable(feature = "from_raw_os", since = "1.1.0")] impl FromRawFd for net::UdpSocket { unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket { - let socket = sys::net::Socket::from_inner(fd); - net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket)) + let file = sys::fs::File::from_inner(fd); + net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(file)) } } #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawFd for net::TcpStream { fn into_raw_fd(self) -> RawFd { - self.into_inner().into_socket().into_inner() + self.into_inner().into_inner().into_fd().into_raw() } } #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawFd for net::TcpListener { fn into_raw_fd(self) -> RawFd { - self.into_inner().into_socket().into_inner() + self.into_inner().into_inner().into_fd().into_raw() } } #[stable(feature = "into_raw_os", since = "1.4.0")] impl IntoRawFd for net::UdpSocket { fn into_raw_fd(self) -> RawFd { - self.into_inner().into_socket().into_inner() + self.into_inner().into_inner().into_fd().into_raw() } } -*/ diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs index 1bfec2e861a..d5362c9f131 100644 --- a/src/libstd/sys/redox/net/tcp.rs +++ b/src/libstd/sys/redox/net/tcp.rs @@ -12,6 +12,7 @@ use io::{Error, ErrorKind, Result}; use net::{SocketAddr, Shutdown}; use path::Path; use sys::fs::{File, OpenOptions}; +use sys_common::{AsInner, FromInner, IntoInner}; use time::Duration; use vec::Vec; @@ -112,6 +113,20 @@ impl TcpStream { } } +impl AsInner for TcpStream { + fn as_inner(&self) -> &File { &self.0 } +} + +impl FromInner for TcpStream { + fn from_inner(file: File) -> TcpStream { + TcpStream(file) + } +} + +impl IntoInner for TcpStream { + fn into_inner(self) -> File { self.0 } +} + #[derive(Debug)] pub struct TcpListener(File); @@ -168,3 +183,17 @@ impl TcpListener { Err(Error::new(ErrorKind::Other, "TcpListener::set_ttl not implemented")) } } + +impl AsInner for TcpListener { + fn as_inner(&self) -> &File { &self.0 } +} + +impl FromInner for TcpListener { + fn from_inner(file: File) -> TcpListener { + TcpListener(file) + } +} + +impl IntoInner for TcpListener { + fn into_inner(self) -> File { self.0 } +} diff --git a/src/libstd/sys/redox/net/udp.rs b/src/libstd/sys/redox/net/udp.rs index b81508e8f0d..607c66c2ba7 100644 --- a/src/libstd/sys/redox/net/udp.rs +++ b/src/libstd/sys/redox/net/udp.rs @@ -13,6 +13,7 @@ use io::{Error, ErrorKind, Result}; use net::{SocketAddr, Ipv4Addr, Ipv6Addr}; use path::Path; use sys::fs::{File, OpenOptions}; +use sys_common::{AsInner, FromInner, IntoInner}; use time::Duration; use super::{path_to_peer_addr, path_to_local_addr}; @@ -171,3 +172,17 @@ impl UdpSocket { Err(Error::new(ErrorKind::Other, "UdpSocket::leave_multicast_v6 not implemented")) } } + +impl AsInner for UdpSocket { + fn as_inner(&self) -> &File { &self.0 } +} + +impl FromInner for UdpSocket { + fn from_inner(file: File) -> UdpSocket { + UdpSocket(file, UnsafeCell::new(None)) + } +} + +impl IntoInner for UdpSocket { + fn into_inner(self) -> File { self.0 } +} -- cgit 1.4.1-3-g733a5 From 1eb6c44b1c21483dbab25d8ca23d616b34f4cf4d Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Thu, 22 Dec 2016 16:13:14 -0700 Subject: Remove start functions, use newlib instead of openlibm + ralloc --- src/librustc_back/target/redox_base.rs | 11 +-- src/libstd/build.rs | 2 - src/libstd/lib.rs | 1 - src/libstd/rt.rs | 4 - src/libstd/sys/redox/mod.rs | 1 - src/libstd/sys/redox/rt.rs | 130 --------------------------------- src/libstd/sys/unix/mod.rs | 1 - src/libstd/sys/unix/rt.rs | 11 --- src/libstd/sys/windows/mod.rs | 1 - src/libstd/sys/windows/rt.rs | 11 --- 10 files changed, 6 insertions(+), 167 deletions(-) delete mode 100644 src/libstd/sys/redox/rt.rs delete mode 100644 src/libstd/sys/unix/rt.rs delete mode 100644 src/libstd/sys/windows/rt.rs (limited to 'src/libstd/sys') diff --git a/src/librustc_back/target/redox_base.rs b/src/librustc_back/target/redox_base.rs index fc4c68276b6..c804d283ba7 100644 --- a/src/librustc_back/target/redox_base.rs +++ b/src/librustc_back/target/redox_base.rs @@ -27,12 +27,13 @@ pub fn opts() -> TargetOptions { // Always enable NX protection when it is available "-Wl,-z,noexecstack".to_string(), - // Do not link libc - "-nostdlib".to_string(), - // Static link "-static".to_string() ], + late_link_args: vec![ + "-lc".to_string(), + "-lm".to_string() + ], executables: true, relocation_model: "static".to_string(), disable_redzone: true, @@ -40,8 +41,8 @@ pub fn opts() -> TargetOptions { target_family: Some("redox".to_string()), linker_is_gnu: true, no_default_libraries: true, - lib_allocation_crate: "ralloc".to_string(), - exe_allocation_crate: "ralloc".to_string(), + lib_allocation_crate: "alloc_system".to_string(), + exe_allocation_crate: "alloc_system".to_string(), has_elf_tls: true, panic_strategy: PanicStrategy::Abort, .. Default::default() diff --git a/src/libstd/build.rs b/src/libstd/build.rs index b8f9b51172a..535cb7e136c 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -62,8 +62,6 @@ fn main() { println!("cargo:rustc-link-lib=magenta"); println!("cargo:rustc-link-lib=mxio"); println!("cargo:rustc-link-lib=launchpad"); // for std::process - } else if target.contains("redox") { - println!("cargo:rustc-link-lib=openlibm"); } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 3c9e66a469c..414f25fa5eb 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -299,7 +299,6 @@ #![feature(unwind_attributes)] #![feature(vec_push_all)] #![feature(zero_one)] -#![cfg_attr(target_os = "redox", feature(naked_functions))] #![cfg_attr(test, feature(update_panic_count))] // Explicitly import the prelude. The compiler uses this same unstable attribute diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 1f2b94239a8..185b7bbd736 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -25,10 +25,6 @@ // Reexport some of our utilities which are expected by other crates. pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count}; -// Reexport the start module on platforms that provide it -#[unstable(feature = "sys_rt", issue="0")] -pub use sys::rt::*; - #[cfg(not(test))] #[lang = "start"] fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize { diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index a8dbac28fb6..5982bdd6549 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -30,7 +30,6 @@ pub mod path; pub mod pipe; pub mod process; pub mod rand; -pub mod rt; pub mod rwlock; pub mod stack_overflow; pub mod stdio; diff --git a/src/libstd/sys/redox/rt.rs b/src/libstd/sys/redox/rt.rs deleted file mode 100644 index 0e854989c12..00000000000 --- a/src/libstd/sys/redox/rt.rs +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Defintion of functions like _start for the linker - -use sys::syscall::exit; - -#[unstable(feature = "sys_rt", issue = "0")] -#[no_mangle] -#[naked] -#[cfg(target_arch = "x86")] -pub unsafe fn _start() { - asm!("push esp - call _start_stack - pop esp" - : - : - : "memory" - : "intel", "volatile"); - let _ = exit(0); -} - -#[unstable(feature = "sys_rt", issue = "0")] -#[no_mangle] -#[naked] -#[cfg(target_arch = "x86_64")] -pub unsafe fn _start() { - asm!("mov rdi, rsp - and rsp, 0xFFFFFFFFFFFFFFF0 - call _start_stack" - : - : - : "memory" - : "intel", "volatile"); - let _ = exit(0); -} - -#[unstable(feature = "sys_rt", issue = "0")] -#[no_mangle] -pub unsafe extern "C" fn _start_stack(stack: *const usize){ - extern "C" { - fn main(argc: usize, argv: *const *const u8) -> usize; - } - - let argc = *stack as usize; - let argv = stack.offset(1) as *const *const u8; - let _ = exit(main(argc, argv)); -} - -/// Memcpy -/// -/// Copy N bytes of memory from one location to another. -#[unstable(feature = "sys_rt", issue = "0")] -#[no_mangle] -pub unsafe extern fn memcpy(dest: *mut u8, src: *const u8, - n: usize) -> *mut u8 { - let mut i = 0; - while i < n { - *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); - i += 1; - } - - dest -} - -/// Memmove -/// -/// Copy N bytes of memory from src to dest. The memory areas may overlap. -#[unstable(feature = "sys_rt", issue = "0")] -#[no_mangle] -pub unsafe extern fn memmove(dest: *mut u8, src: *const u8, - n: usize) -> *mut u8 { - if src < dest as *const u8 { - let mut i = n; - while i != 0 { - i -= 1; - *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); - } - } else { - let mut i = 0; - while i < n { - *((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8); - i += 1; - } - } - - dest -} - -/// Memset -/// -/// Fill a block of memory with a specified value. -#[unstable(feature = "sys_rt", issue = "0")] -#[no_mangle] -pub unsafe extern fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 { - let mut i = 0; - while i < n { - *((dest as usize + i) as *mut u8) = c as u8; - i += 1; - } - - dest -} - -/// Memcmp -/// -/// Compare two blocks of memory. -#[unstable(feature = "sys_rt", issue = "0")] -#[no_mangle] -pub unsafe extern fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { - let mut i = 0; - - while i < n { - let a = *((s1 as usize + i) as *const u8); - let b = *((s2 as usize + i) as *const u8); - if a != b { - return a as i32 - b as i32 - } - i += 1; - } - - 0 -} diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 5e14b392bdc..fd7dc17cccd 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -50,7 +50,6 @@ pub mod path; pub mod pipe; pub mod process; pub mod rand; -pub mod rt; pub mod rwlock; pub mod stack_overflow; pub mod thread; diff --git a/src/libstd/sys/unix/rt.rs b/src/libstd/sys/unix/rt.rs deleted file mode 100644 index 188e31cb5d7..00000000000 --- a/src/libstd/sys/unix/rt.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Stub for placing functions like _start for the linker diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 52d256630a5..defc41c5f46 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -36,7 +36,6 @@ pub mod path; pub mod pipe; pub mod process; pub mod rand; -pub mod rt; pub mod rwlock; pub mod stack_overflow; pub mod thread; diff --git a/src/libstd/sys/windows/rt.rs b/src/libstd/sys/windows/rt.rs deleted file mode 100644 index 188e31cb5d7..00000000000 --- a/src/libstd/sys/windows/rt.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Stub for placing functions like _start for the linker -- cgit 1.4.1-3-g733a5 From a0a600f0c68e7afa23f934f088b956026cce36a7 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 23 Dec 2016 09:42:38 -0700 Subject: Add Debug to OpenOptions and DirBuilder --- src/libstd/sys/redox/fs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index e3bd77f4009..bff5ce4a1cf 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -43,7 +43,7 @@ pub struct DirEntry { name: Box<[u8]> } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct OpenOptions { // generic read: bool, @@ -63,6 +63,7 @@ pub struct FilePermissions { mode: u16 } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct FileType { mode: u16 } +#[derive(Debug)] pub struct DirBuilder { mode: u16 } impl FileAttr { -- cgit 1.4.1-3-g733a5 From 9f9489b976b137cbff65b11f4e0a55199c4a1970 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 23 Dec 2016 12:21:29 -0700 Subject: Cloexec when creating directories --- src/libstd/sys/redox/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd/sys') diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs index bff5ce4a1cf..a8391d2b898 100644 --- a/src/libstd/sys/redox/fs.rs +++ b/src/libstd/sys/redox/fs.rs @@ -337,7 +337,7 @@ impl DirBuilder { } pub fn mkdir(&self, p: &Path) -> io::Result<()> { - let flags = syscall::O_CREAT | syscall::O_DIRECTORY | syscall::O_EXCL; + let flags = syscall::O_CREAT | syscall::O_CLOEXEC | syscall::O_DIRECTORY | syscall::O_EXCL; let fd = cvt(syscall::open(p.to_str().unwrap(), flags | (self.mode as usize & 0o777)))?; let _ = syscall::close(fd); Ok(()) -- cgit 1.4.1-3-g733a5