From b2d3b4afa07bd97e4b842ffc0be57cf0ed3e636b Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Fri, 5 Feb 2016 14:17:55 +0300 Subject: [PATCH 1/9] wait: support ptrace events for Linux --- src/sys/wait.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/sys/wait.rs b/src/sys/wait.rs index 3d9b3a5044..37adbd2535 100644 --- a/src/sys/wait.rs +++ b/src/sys/wait.rs @@ -42,7 +42,7 @@ const WSTOPPED: WaitPidFlag = WUNTRACED; pub enum WaitStatus { Exited(pid_t, i8), Signaled(pid_t, signal::SigNum, bool), - Stopped(pid_t, signal::SigNum), + Stopped(pid_t, signal::SigNum, c_int), Continued(pid_t), StillAlive } @@ -51,6 +51,7 @@ pub enum WaitStatus { target_os = "android"))] mod status { use sys::signal; + use libc::c_int; pub fn exited(status: i32) -> bool { (status & 0x7F) == 0 @@ -80,6 +81,10 @@ mod status { ((status & 0xFF00) >> 8) as signal::SigNum } + pub fn stop_additional(status: i32) -> c_int { + (status >> 16) as c_int + } + pub fn continued(status: i32) -> bool { status == 0xFFFF } @@ -89,6 +94,7 @@ mod status { target_os = "ios"))] mod status { use sys::signal; + use libc::c_int; const WCOREFLAG: i32 = 0x80; const WSTOPPED: i32 = 0x7f; @@ -105,6 +111,10 @@ mod status { (status >> 8) as signal::SigNum } + pub fn stop_additional(status: i32) -> c_int { + 0 + } + pub fn continued(status: i32) -> bool { wstatus(status) == WSTOPPED && stop_signal(status) == 0x13 } @@ -136,6 +146,7 @@ mod status { target_os = "netbsd"))] mod status { use sys::signal; + use libc::c_int; const WCOREFLAG: i32 = 0x80; const WSTOPPED: i32 = 0x7f; @@ -152,6 +163,10 @@ mod status { (status >> 8) as signal::SigNum } + pub fn stop_additional(status: i32) -> c_int { + 0 + } + pub fn signaled(status: i32) -> bool { wstatus(status) != WSTOPPED && wstatus(status) != 0 && status != 0x13 } @@ -183,7 +198,7 @@ fn decode(pid : pid_t, status: i32) -> WaitStatus { } else if status::signaled(status) { WaitStatus::Signaled(pid, status::term_signal(status), status::dumped_core(status)) } else if status::stopped(status) { - WaitStatus::Stopped(pid, status::stop_signal(status)) + WaitStatus::Stopped(pid, status::stop_signal(status), status::stop_additional(status)) } else { assert!(status::continued(status)); WaitStatus::Continued(pid) From 82dd53a2dc5ce1a50fed7ce7a4c5f2dadef02df2 Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Fri, 30 Oct 2015 14:08:12 +0300 Subject: [PATCH 2/9] syscall: add more syscall numbers --- src/sys/syscall.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/sys/syscall.rs b/src/sys/syscall.rs index f3ec60e0fa..a428947f2f 100644 --- a/src/sys/syscall.rs +++ b/src/sys/syscall.rs @@ -10,8 +10,12 @@ mod arch { pub type Syscall = c_long; - pub static SYSPIVOTROOT: Syscall = 155; - pub static MEMFD_CREATE: Syscall = 319; + pub const SOCKET: Syscall = 41; + pub const CONNECT: Syscall = 42; + pub const SENDMSG: Syscall = 46; + pub const RECVMSG: Syscall = 47; + pub const SYSPIVOTROOT: Syscall = 155; + pub const MEMFD_CREATE: Syscall = 319; } #[cfg(target_arch = "x86")] @@ -20,8 +24,9 @@ mod arch { pub type Syscall = c_long; - pub static SYSPIVOTROOT: Syscall = 217; - pub static MEMFD_CREATE: Syscall = 356; + pub const SOCKETCALL: Syscall = 102; + pub const SYSPIVOTROOT: Syscall = 217; + pub const MEMFD_CREATE: Syscall = 356; } #[cfg(target_arch = "aarch64")] @@ -40,8 +45,12 @@ mod arch { pub type Syscall = c_long; - pub static SYSPIVOTROOT: Syscall = 218; - pub static MEMFD_CREATE: Syscall = 385; + pub const SYSPIVOTROOT: Syscall = 218; + pub const SOCKET: Syscall = 281; + pub const CONNECT: Syscall = 283; + pub const SENDMSG: Syscall = 296; + pub const RECVMSG: Syscall = 297; + pub const MEMFD_CREATE: Syscall = 385; } From 352d4c82c4ad525317b24a3f029d65224ccee96f Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Fri, 19 Feb 2016 17:22:50 +0300 Subject: [PATCH 3/9] mqueue: change types to allow more cases --- src/mqueue.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/mqueue.rs b/src/mqueue.rs index bc3eca2cc1..4db38914dc 100644 --- a/src/mqueue.rs +++ b/src/mqueue.rs @@ -4,9 +4,11 @@ use {Errno, Result}; -use libc::{c_int, c_long, c_char, size_t, mode_t, strlen}; +use libc::{c_int, c_long, c_char, size_t, mode_t}; use std::ffi::CString; use sys::stat::Mode; +use std::ptr::null; +use std::mem::transmute; pub use self::consts::*; @@ -75,9 +77,12 @@ impl MqAttr { } -#[inline] -pub fn mq_open(name: &CString, oflag: MQ_OFlag, mode: Mode, attr: &MqAttr) -> Result { - let res = unsafe { ffi::mq_open(name.as_ptr(), oflag.bits(), mode.bits() as mode_t, attr as *const MqAttr) }; +pub fn mq_open(name: &CString, oflag: MQ_OFlag, mode: Mode, attr: Option<&MqAttr>) -> Result { + let attr_p = match attr { + None => null(), + Some(val) => val as *const MqAttr, + }; + let res = unsafe { ffi::mq_open(name.as_ptr(), oflag.bits(), mode.bits() as mode_t, attr_p) }; Errno::result(res) } @@ -100,11 +105,10 @@ pub fn mq_receive(mqdes: MQd, message: &mut [u8], msq_prio: u32) -> Result Result { - let len = unsafe { strlen(message.as_ptr()) as size_t }; - let res = unsafe { ffi::mq_send(mqdes, message.as_ptr(), len, msq_prio) }; +pub fn mq_send(mqdes: MQd, message: &[u8], msq_prio: u32) -> Result<()> { + let res = unsafe { ffi::mq_send(mqdes, transmute(message.as_ptr()), message.len(), msq_prio) }; - Errno::result(res).map(|r| r as usize) + Errno::result(res).map(drop) } pub fn mq_getattr(mqd: MQd) -> Result { From 94ea763cad1c8e438a5b622bbfbfbde51838588e Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Fri, 19 Feb 2016 17:24:14 +0300 Subject: [PATCH 4/9] timerfd: add new module --- src/sys/mod.rs | 4 +++ src/sys/timerfd.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 src/sys/timerfd.rs diff --git a/src/sys/mod.rs b/src/sys/mod.rs index de449b769a..a0a11fa807 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -78,3 +78,7 @@ pub mod statfs; target_arch = "arm")), )] pub mod statvfs; + +#[cfg(any(target_os = "linux", + target_os = "android"))] +pub mod timerfd; diff --git a/src/sys/timerfd.rs b/src/sys/timerfd.rs new file mode 100644 index 0000000000..d43a2726c5 --- /dev/null +++ b/src/sys/timerfd.rs @@ -0,0 +1,71 @@ +use Result; +use errno::Errno; +use libc::{CLOCK_REALTIME, CLOCK_MONOTONIC, c_int}; +use std::os::unix::io::RawFd; +use std::ptr::null_mut; +use std::mem::uninitialized; + +pub use libc::timespec; + +pub enum ClockId { + Realtime = CLOCK_REALTIME as isize, + Monotonic = CLOCK_MONOTONIC as isize, +} + +bitflags! { + flags TfFlag: c_int { + const TFD_NONBLOCK = 0o00004000, + const TFD_CLOEXEC = 0o02000000, + } +} + +bitflags! { + flags TfTimerFlag: c_int { + const TFD_TIMER_ABSTIME = 1, + } +} + +mod ffi { + use libc::{c_int, timespec}; + + #[repr(C)] + #[derive(Clone)] + pub struct ITimerSpec { + pub it_interval: timespec, + pub it_value: timespec, + } + + extern { + + pub fn timerfd_create(clockid: c_int, flags: c_int) -> c_int; + + pub fn timerfd_settime(fd: c_int, flags: c_int, new_value: *const ITimerSpec, old_value: *mut ITimerSpec) -> c_int; + + pub fn timerfd_gettime(fd: c_int, curr_value: *mut ITimerSpec) -> c_int; + } +} + +pub use self::ffi::ITimerSpec; + +pub fn timerfd_create(clockid: ClockId, flags: TfFlag) -> Result { + let fd = unsafe { ffi::timerfd_create(clockid as c_int, flags.bits() as c_int) }; + + Errno::result(fd) +} + +pub fn timerfd_settime(fd: RawFd, flags: TfTimerFlag, new_value: &ITimerSpec, old_value: Option<&mut ITimerSpec>) -> Result<()> { + let res = unsafe { ffi::timerfd_settime(fd as c_int, + flags.bits() as c_int, + new_value as *const ITimerSpec, + old_value.map(|x| x as *mut ITimerSpec).unwrap_or(null_mut()) + ) }; + + Errno::result(res).map(drop) +} + +pub fn timerfd_gettime(fd: RawFd) -> Result { + let mut spec = unsafe { uninitialized() }; + let res = unsafe { ffi::timerfd_gettime(fd as c_int, &mut spec as *mut ITimerSpec) }; + + Errno::result(res).map(|_| spec) +} From 987697931c1fd3edbf232cbb26593e971e8ef7ba Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Fri, 19 Feb 2016 17:25:46 +0300 Subject: [PATCH 5/9] select: allow infinite timeout --- src/sys/select.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sys/select.rs b/src/sys/select.rs index 9d7c41f8b8..48746e72fd 100644 --- a/src/sys/select.rs +++ b/src/sys/select.rs @@ -71,11 +71,11 @@ pub fn select(nfds: c_int, readfds: Option<&mut FdSet>, writefds: Option<&mut FdSet>, errorfds: Option<&mut FdSet>, - timeout: &mut TimeVal) -> Result { + timeout: Option<&mut TimeVal>) -> Result { let readfds = readfds.map(|set| set as *mut FdSet).unwrap_or(null_mut()); let writefds = writefds.map(|set| set as *mut FdSet).unwrap_or(null_mut()); let errorfds = errorfds.map(|set| set as *mut FdSet).unwrap_or(null_mut()); - let timeout = timeout as *mut TimeVal; + let timeout = timeout.map(|tv| tv as *mut TimeVal).unwrap_or(null_mut()); let res = unsafe { ffi::select(nfds, readfds, writefds, errorfds, timeout) From 6c25ad931418dca83ec8f8d53daac0edff64854c Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Fri, 19 Feb 2016 17:32:21 +0300 Subject: [PATCH 6/9] select: add pselect syscall --- src/sys/select.rs | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/sys/select.rs b/src/sys/select.rs index 48746e72fd..0ab75019de 100644 --- a/src/sys/select.rs +++ b/src/sys/select.rs @@ -1,8 +1,9 @@ -use std::ptr::null_mut; +use std::ptr::{null, null_mut}; use std::os::unix::io::RawFd; -use libc::c_int; -use {Errno, Result}; +use libc::{c_int, timespec}; +use {Error, Errno, Result}; use sys::time::TimeVal; +use sys::signal::sigset_t; pub const FD_SETSIZE: RawFd = 1024; @@ -54,8 +55,9 @@ impl FdSet { } mod ffi { - use libc::c_int; + use libc::{c_int, timespec}; use sys::time::TimeVal; + use sys::signal::sigset_t; use super::FdSet; extern { @@ -64,6 +66,13 @@ mod ffi { writefds: *mut FdSet, errorfds: *mut FdSet, timeout: *mut TimeVal) -> c_int; + + pub fn pselect(nfds: c_int, + readfds: *mut FdSet, + writefds: *mut FdSet, + errorfds: *mut FdSet, + timeout: *const timespec, + sigmask: *const sigset_t) -> c_int; } } @@ -83,3 +92,22 @@ pub fn select(nfds: c_int, Errno::result(res) } + +pub fn pselect(nfds: c_int, + readfds: Option<&mut FdSet>, + writefds: Option<&mut FdSet>, + errorfds: Option<&mut FdSet>, + timeout: Option<×pec>, + sigmask: Option<&sigset_t>) -> Result { + let readfds = readfds.map(|set| set as *mut FdSet).unwrap_or(null_mut()); + let writefds = writefds.map(|set| set as *mut FdSet).unwrap_or(null_mut()); + let errorfds = errorfds.map(|set| set as *mut FdSet).unwrap_or(null_mut()); + let timeout = timeout.map(|ts| ts as *const timespec).unwrap_or(null()); + let sigmask = sigmask.map(|sm| sm as *const sigset_t).unwrap_or(null()); + + let res = unsafe { + ffi::pselect(nfds, readfds, writefds, errorfds, timeout, sigmask) + }; + + Errno::result(res) +} From e54b87dd60ba77c3a71017970dd7642e7fa02362 Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Fri, 19 Feb 2016 17:32:29 +0300 Subject: [PATCH 7/9] select: make FdSet Cloneable --- src/sys/select.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sys/select.rs b/src/sys/select.rs index 0ab75019de..1b55490b25 100644 --- a/src/sys/select.rs +++ b/src/sys/select.rs @@ -18,6 +18,7 @@ const BITS: usize = 32; #[cfg(not(any(target_os = "macos", target_os = "ios")))] #[repr(C)] +#[derive(Clone)] pub struct FdSet { bits: [u64; FD_SETSIZE as usize / 64] } From 2b82dd2b1e19698bfb52a03b2cce15a64313886b Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Fri, 19 Feb 2016 17:37:53 +0300 Subject: [PATCH 8/9] unistd: add setuid, setgid syscalls --- src/unistd.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/unistd.rs b/src/unistd.rs index a4e666180c..1e3bdfb8fd 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -13,7 +13,7 @@ pub use self::linux::*; mod ffi { use libc::{c_char, c_int, size_t}; - pub use libc::{fork, close, read, write, pipe, ftruncate, unlink, setpgid, getegid, geteuid, getgid, getpid, getppid, getuid}; + pub use libc::{fork, close, read, write, pipe, ftruncate, unlink, setpgid, getegid, geteuid, getgid, getpid, getppid, getuid, setuid, setgid}; #[allow(improper_ctypes)] extern { @@ -369,6 +369,20 @@ pub fn getegid() -> gid_t { unsafe { ffi::getegid() } } +#[inline] +pub fn setuid(uid: uid_t) -> Result<()> { + let res = unsafe { ffi::setuid(uid) }; + + Errno::result(res).map(drop) +} + +#[inline] +pub fn setgid(gid: gid_t) -> Result<()> { + let res = unsafe { ffi::setgid(gid) }; + + Errno::result(res).map(drop) +} + #[cfg(any(target_os = "linux", target_os = "android"))] mod linux { use sys::syscall::{syscall, SYSPIVOTROOT}; From 02dcbe5443a18955485116941368394b3f7803fb Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Fri, 19 Feb 2016 17:38:33 +0300 Subject: [PATCH 9/9] unistd: add chown syscall --- src/unistd.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/unistd.rs b/src/unistd.rs index 1e3bdfb8fd..b821e8db91 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -13,7 +13,7 @@ pub use self::linux::*; mod ffi { use libc::{c_char, c_int, size_t}; - pub use libc::{fork, close, read, write, pipe, ftruncate, unlink, setpgid, getegid, geteuid, getgid, getpid, getppid, getuid, setuid, setgid}; + pub use libc::{fork, close, read, write, pipe, ftruncate, unlink, setpgid, getegid, geteuid, getgid, getpid, getppid, getuid, setuid, setgid, chown}; #[allow(improper_ctypes)] extern { @@ -28,7 +28,7 @@ mod ffi { // Execute PATH with arguments ARGV and environment from `environ'. // doc: http://man7.org/linux/man-pages/man3/execv.3.html - pub fn execv (path: *const c_char, argv: *const *const c_char) -> c_int; + pub fn execv(path: *const c_char, argv: *const *const c_char) -> c_int; // execute program // doc: http://man7.org/linux/man-pages/man2/execve.2.html @@ -157,6 +157,15 @@ pub fn chdir(path: &P) -> Result<()> { Errno::result(res).map(drop) } +#[inline] +pub fn chown(path: &P, owner: Option, group: Option) -> Result<()> { + let res = try!(path.with_nix_path(|cstr| { + unsafe { ffi::chown(cstr.as_ptr(), owner.unwrap_or(uid_t::max_value()), group.unwrap_or(gid_t::max_value())) } + })); + + Errno::result(res).map(drop) +} + fn to_exec_array(args: &[CString]) -> Vec<*const c_char> { use std::ptr; use libc::c_char;