summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md9
-rw-r--r--src/fcntl.rs301
-rw-r--r--src/macros.rs17
-rw-r--r--src/sched.rs23
-rw-r--r--src/sys/memfd.rs5
-rw-r--r--src/sys/mod.rs9
-rw-r--r--src/sys/ptrace.rs235
-rw-r--r--src/sys/quota.rs313
-rw-r--r--src/sys/syscall.rs91
-rw-r--r--src/unistd.rs8
-rw-r--r--test/sys/test_ptrace.rs3
-rw-r--r--test/sys/test_termios.rs2
-rw-r--r--test/sys/test_wait.rs4
13 files changed, 604 insertions, 416 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 148f0c6d..36b528ca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#739](https://github.com/nix-rust/nix/pull/739))
- Expose `signalfd` module on Android as well.
([#739](https://github.com/nix-rust/nix/pull/739))
+- Added nix::sys::ptrace::detach.
+ ([#749](https://github.com/nix-rust/nix/pull/749))
### Changed
- Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692))
@@ -47,11 +49,18 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#731](https://github.com/nix-rust/nix/pull/731))
- Marked `pty::ptsname` function as `unsafe`
([#744](https://github.com/nix-rust/nix/pull/744))
+- Moved constants ptrace request, event and options to enums and updated ptrace functions and argument types accordingly.
+ ([#749](https://github.com/nix-rust/nix/pull/749))
# Fixed
- Fix compilation and tests for OpenBSD targets
([#688](https://github.com/nix-rust/nix/pull/688))
+# Removed
+- The syscall module has been removed. This only exposed enough functionality for
+ `memfd_create()` and `pivot_root()`, which are still exposed as separate functions.
+ ([#747](https://github.com/nix-rust/nix/pull/747))
+
## [0.9.0] 2017-07-23
### Added
diff --git a/src/fcntl.rs b/src/fcntl.rs
index e42c923e..003c316c 100644
--- a/src/fcntl.rs
+++ b/src/fcntl.rs
@@ -5,31 +5,138 @@ use std::os::unix::io::RawFd;
use std::ffi::OsStr;
use std::os::unix::ffi::OsStrExt;
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(any(target_os = "android", target_os = "linux"))]
use sys::uio::IoVec; // For vmsplice
-pub use self::consts::*;
-
-// TODO: The remainder of the ffi module should be removed afer work on
-// https://github.com/rust-lang/libc/issues/235 is resolved.
-#[allow(dead_code)]
-mod ffi {
- use libc::c_int;
-
- pub const F_ADD_SEALS: c_int = 1033;
- pub const F_GET_SEALS: c_int = 1034;
-}
-
libc_bitflags!{
pub struct AtFlags: c_int {
AT_SYMLINK_NOFOLLOW;
- #[cfg(any(target_os = "linux", target_os = "android"))]
+ #[cfg(any(target_os = "android", target_os = "linux"))]
AT_NO_AUTOMOUNT;
- #[cfg(any(target_os = "linux", target_os = "android"))]
+ #[cfg(any(target_os = "android", target_os = "linux"))]
AT_EMPTY_PATH;
}
}
+libc_bitflags!(
+ /// Configuration options for opened files.
+ pub struct OFlag: c_int {
+ /// Mask for the access mode of the file.
+ O_ACCMODE;
+ /// Use alternate I/O semantics.
+ #[cfg(target_os = "netbsd")]
+ O_ALT_IO;
+ /// Open the file in append-only mode.
+ O_APPEND;
+ /// Generate a signal when input or output becomes possible.
+ O_ASYNC;
+ /// Closes the file descriptor once an `execve` call is made.
+ ///
+ /// Also sets the file offset to the beginning of the file.
+ O_CLOEXEC;
+ /// Create the file if it does not exist.
+ O_CREAT;
+ /// Try to minimize cache effects of the I/O for this file.
+ #[cfg(any(target_os = "android",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd"))]
+ O_DIRECT;
+ /// If the specified path isn't a directory, fail.
+ O_DIRECTORY;
+ /// Implicitly follow each `write()` with an `fdatasync()`.
+ #[cfg(any(target_os = "android",
+ target_os = "dragonfly",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"))]
+ O_DSYNC;
+ /// Error out if a file was not created.
+ O_EXCL;
+ /// Open for execute only.
+ #[cfg(target_os = "freebsd")]
+ O_EXEC;
+ /// Open with an exclusive file lock.
+ #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"))]
+ O_EXLOCK;
+ /// Same as `O_SYNC`.
+ #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ all(target_os = "linux", not(target_env = "musl")),
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"))]
+ O_FSYNC;
+ /// Allow files whose sizes can't be represented in an `off_t` to be opened.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ O_LARGEFILE;
+ /// Do not update the file last access time during `read(2)`s.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ O_NOATIME;
+ /// Don't attach the device as the process' controlling terminal.
+ O_NOCTTY;
+ /// Same as `O_NONBLOCK`.
+ O_NDELAY;
+ /// `open()` will fail if the given path is a symbolic link.
+ O_NOFOLLOW;
+ /// When possible, open the file in nonblocking mode.
+ O_NONBLOCK;
+ /// Don't deliver `SIGPIPE`.
+ #[cfg(target_os = "netbsd")]
+ O_NOSIGPIPE;
+ /// Obtain a file descriptor for low-level access.
+ ///
+ /// The file itself is not opened and other file operations will fail.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ O_PATH;
+ /// Only allow reading.
+ ///
+ /// This should not be combined with `O_WRONLY` or `O_RDWR`.
+ O_RDONLY;
+ /// Allow both reading and writing.
+ ///
+ /// This should not be combined with `O_WRONLY` or `O_RDWR`.
+ O_RDWR;
+ /// Similar to `O_DSYNC` but applies to `read`s instead.
+ #[cfg(any(target_os = "linux", target_os = "netbsd", target_os = "openbsd"))]
+ O_RSYNC;
+ /// Skip search permission checks.
+ #[cfg(target_os = "netbsd")]
+ O_SEARCH;
+ /// Open with a shared file lock.
+ #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"))]
+ O_SHLOCK;
+ /// Implicitly follow each `write()` with an `fsync()`.
+ O_SYNC;
+ /// Create an unnamed temporary file.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ O_TMPFILE;
+ /// Truncate an existing regular file to 0 length if it allows writing.
+ O_TRUNC;
+ /// Restore default TTY attributes.
+ #[cfg(target_os = "freebsd")]
+ O_TTY_INIT;
+ /// Only allow writing.
+ ///
+ /// This should not be combined with `O_RDONLY` or `O_RDWR`.
+ O_WRONLY;
+ }
+);
+
pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
let fd = try!(path.with_nix_path(|cstr| {
unsafe { libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
@@ -76,6 +183,29 @@ pub fn readlinkat<'a, P: ?Sized + NixPath>(dirfd: RawFd, path: &P, buffer: &'a m
wrap_readlink_result(buffer, res)
}
+#[cfg(any(target_os = "android", target_os = "linux"))]
+libc_bitflags!(
+ /// Additional flags for file sealing, which allows for limiting operations on a file.
+ pub struct SealFlag: c_int {
+ /// Prevents further calls to `fcntl()` with `F_ADD_SEALS`.
+ F_SEAL_SEAL;
+ /// The file cannot be reduced in size.
+ F_SEAL_SHRINK;
+ /// The size of the file cannot be increased.
+ F_SEAL_GROW;
+ /// The file contents cannot be modified.
+ F_SEAL_WRITE;
+ }
+);
+
+libc_bitflags!(
+ /// Additional configuration flags for `fcntl`'s `F_SETFD`.
+ pub struct FdFlag: c_int {
+ /// The file descriptor will automatically be closed during a successful `execve(2)`.
+ FD_CLOEXEC;
+ }
+);
+
pub enum FcntlArg<'a> {
F_DUPFD(RawFd),
F_DUPFD_CLOEXEC(RawFd),
@@ -92,9 +222,9 @@ pub enum FcntlArg<'a> {
F_OFD_SETLKW(&'a libc::flock),
#[cfg(any(target_os = "linux", target_os = "android"))]
F_OFD_GETLK(&'a mut libc::flock),
- #[cfg(target_os = "linux")]
+ #[cfg(any(target_os = "android", target_os = "linux"))]
F_ADD_SEALS(SealFlag),
- #[cfg(target_os = "linux")]
+ #[cfg(any(target_os = "android", target_os = "linux"))]
F_GET_SEALS,
#[cfg(any(target_os = "macos", target_os = "ios"))]
F_FULLFSYNC,
@@ -120,10 +250,10 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
F_SETLK(flock) => libc::fcntl(fd, libc::F_SETLK, flock),
F_SETLKW(flock) => libc::fcntl(fd, libc::F_SETLKW, flock),
F_GETLK(flock) => libc::fcntl(fd, libc::F_GETLK, flock),
- #[cfg(target_os = "linux")]
- F_ADD_SEALS(flag) => libc::fcntl(fd, ffi::F_ADD_SEALS, flag.bits()),
- #[cfg(target_os = "linux")]
- F_GET_SEALS => libc::fcntl(fd, ffi::F_GET_SEALS),
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ F_ADD_SEALS(flag) => libc::fcntl(fd, libc::F_ADD_SEALS, flag.bits()),
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ F_GET_SEALS => libc::fcntl(fd, libc::F_GET_SEALS),
#[cfg(any(target_os = "macos", target_os = "ios"))]
F_FULLFSYNC => libc::fcntl(fd, libc::F_FULLFSYNC),
#[cfg(any(target_os = "linux", target_os = "android"))]
@@ -164,6 +294,27 @@ pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
Errno::result(res).map(drop)
}
+#[cfg(any(target_os = "android", target_os = "linux"))]
+libc_bitflags! {
+ /// Additional flags to `splice` and friends.
+ pub struct SpliceFFlags: c_uint {
+ /// Request that pages be moved instead of copied.
+ ///
+ /// Not applicable to `vmsplice`.
+ SPLICE_F_MOVE;
+ /// Do not block on I/O.
+ SPLICE_F_NONBLOCK;
+ /// Hint that more data will be coming in a subsequent splice.
+ ///
+ /// Not applicable to `vmsplice`.
+ SPLICE_F_MORE;
+ /// Gift the user pages to the kernel.
+ ///
+ /// Not applicable to `splice`.
+ SPLICE_F_GIFT;
+ }
+}
+
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn splice(fd_in: RawFd, off_in: Option<&mut libc::loff_t>,
fd_out: RawFd, off_out: Option<&mut libc::loff_t>,
@@ -190,111 +341,3 @@ pub fn vmsplice(fd: RawFd, iov: &[IoVec<&[u8]>], flags: SpliceFFlags) -> Result<
Errno::result(ret).map(|r| r as usize)
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
-mod consts {
- use libc::{self, c_int, c_uint};
-
- libc_bitflags! {
- pub struct SpliceFFlags: c_uint {
- SPLICE_F_MOVE;
- SPLICE_F_NONBLOCK;
- SPLICE_F_MORE;
- SPLICE_F_GIFT;
- }
- }
-
- bitflags!(
- pub struct OFlag: c_int {
- const O_ACCMODE = libc::O_ACCMODE;
- const O_RDONLY = libc::O_RDONLY;
- const O_WRONLY = libc::O_WRONLY;
- const O_RDWR = libc::O_RDWR;
- const O_CREAT = libc::O_CREAT;
- const O_EXCL = libc::O_EXCL;
- const O_NOCTTY = libc::O_NOCTTY;
- const O_TRUNC = libc::O_TRUNC;
- const O_APPEND = libc::O_APPEND;
- const O_NONBLOCK = libc::O_NONBLOCK;
- const O_DSYNC = libc::O_DSYNC;
- const O_DIRECT = libc::O_DIRECT;
- const O_LARGEFILE = 0o00100000;
- const O_DIRECTORY = libc::O_DIRECTORY;
- const O_NOFOLLOW = libc::O_NOFOLLOW;
- const O_NOATIME = 0o01000000;
- const O_CLOEXEC = libc::O_CLOEXEC;
- const O_SYNC = libc::O_SYNC;
- const O_PATH = 0o10000000;
- const O_TMPFILE = libc::O_TMPFILE;
- const O_NDELAY = libc::O_NDELAY;
- }
- );
-
- libc_bitflags!(
- pub struct FdFlag: c_int {
- FD_CLOEXEC;
- }
- );
-
- bitflags!(
- pub struct SealFlag: c_int {
- const F_SEAL_SEAL = 1;
- const F_SEAL_SHRINK = 2;
- const F_SEAL_GROW = 4;
- const F_SEAL_WRITE = 8;
- }
- );
-
-}
-
-#[cfg(any(target_os = "netbsd", target_os = "dragonfly", target_os = "openbsd",
- target_os = "freebsd", target_os = "macos", target_os = "ios"))]
-mod consts {
- use libc::{self,c_int};
-
- libc_bitflags!(
- pub struct OFlag: c_int {
- O_ACCMODE;
- O_RDONLY;
- O_WRONLY;
- O_RDWR;
- O_NONBLOCK;
- O_APPEND;
- O_SHLOCK;
- O_EXLOCK;
- O_ASYNC;
- O_SYNC;
- O_NOFOLLOW;
- O_CREAT;
- O_TRUNC;
- O_EXCL;
- O_NOCTTY;
- O_DIRECTORY;
- O_CLOEXEC;
- O_FSYNC;
- O_NDELAY;
- #[cfg(any(target_os = "netbsd", target_os = "openbsd", target_os = "macos",
- target_os = "ios"))]
- O_DSYNC;
- #[cfg(any(target_os = "netbsd", target_os = "dragonfly", target_os = "freebsd"))]
- O_DIRECT;
- #[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
- O_RSYNC;
- #[cfg(target_os = "freebsd")]
- O_EXEC;
- #[cfg(target_os = "freebsd")]
- O_TTY_INIT;
- #[cfg(target_os = "netbsd")]
- O_ALT_IO;
- #[cfg(target_os = "netbsd")]
- O_NOSIGPIPE;
- #[cfg(target_os = "netbsd")]
- O_SEARCH;
- }
- );
-
- libc_bitflags!(
- pub struct FdFlag: c_int {
- FD_CLOEXEC;
- }
- );
-}
diff --git a/src/macros.rs b/src/macros.rs
index 7a0eb07c..39bc466d 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -379,6 +379,23 @@ macro_rules! libc_enum {
}
};
+ // Munch an ident and cast it to the given type; covers terminating comma.
+ (@accumulate_entries
+ $prefix:tt,
+ [$($entries:tt)*];
+ $entry:ident as $ty:ty, $($tail:tt)*
+ ) => {
+ libc_enum! {
+ @accumulate_entries
+ $prefix,
+ [
+ $($entries)*
+ $entry = libc::$entry as $ty,
+ ];
+ $($tail)*
+ }
+ };
+
// (non-pub) Entry rule.
(
$(#[$attr:meta])*
diff --git a/src/sched.rs b/src/sched.rs
index 943b432b..74c23072 100644
--- a/src/sched.rs
+++ b/src/sched.rs
@@ -73,25 +73,6 @@ impl CpuSet {
}
}
-mod ffi {
- use libc::{c_void, c_int};
-
- pub type CloneCb = extern "C" fn(data: *const super::CloneCb) -> c_int;
-
- // We cannot give a proper #[repr(C)] to super::CloneCb
- #[allow(improper_ctypes)]
- extern "C" {
- // create a child process
- // doc: http://man7.org/linux/man-pages/man2/clone.2.html
- pub fn clone(cb: *const CloneCb,
- child_stack: *mut c_void,
- flags: c_int,
- arg: *mut super::CloneCb,
- ...)
- -> c_int;
- }
-}
-
pub fn sched_setaffinity(pid: Pid, cpuset: &CpuSet) -> Result<()> {
let res = unsafe {
libc::sched_setaffinity(pid.into(),
@@ -116,10 +97,10 @@ pub fn clone(mut cb: CloneCb,
let combined = flags.bits() | signal.unwrap_or(0);
let ptr = stack.as_mut_ptr().offset(stack.len() as isize);
let ptr_aligned = ptr.offset((ptr as usize % 16) as isize * -1);
- ffi::clone(mem::transmute(callback as extern "C" fn(*mut Box<::std::ops::FnMut() -> isize>) -> i32),
+ libc::clone(mem::transmute(callback as extern "C" fn(*mut Box<::std::ops::FnMut() -> isize>) -> i32),
ptr_aligned as *mut c_void,
combined,
- &mut cb)
+ &mut cb as *mut _ as *mut c_void)
};
Errno::result(res).map(Pid::from_raw)
diff --git a/src/sys/memfd.rs b/src/sys/memfd.rs
index b9812943..056e9e43 100644
--- a/src/sys/memfd.rs
+++ b/src/sys/memfd.rs
@@ -11,8 +11,9 @@ bitflags!(
);
pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<RawFd> {
- use sys::syscall::{syscall, MEMFD_CREATE};
- let res = unsafe { syscall(MEMFD_CREATE, name.as_ptr(), flags.bits()) };
+ let res = unsafe {
+ libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags.bits())
+ };
Errno::result(res).map(|r| r as RawFd)
}
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index c73a09cd..c99fe2db 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -31,9 +31,6 @@ pub mod socket;
pub mod stat;
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub mod syscall;
-
#[cfg(any(target_os = "linux"))]
pub mod reboot;
@@ -54,11 +51,7 @@ pub mod ptrace;
pub mod select;
-#[cfg(all(target_os = "linux",
- any(target_arch = "x86",
- target_arch = "x86_64",
- target_arch = "arm")),
- )]
+#[cfg(target_os = "linux")]
pub mod quota;
diff --git a/src/sys/ptrace.rs b/src/sys/ptrace.rs
index 5f0391d4..64b523c3 100644
--- a/src/sys/ptrace.rs
+++ b/src/sys/ptrace.rs
@@ -6,68 +6,117 @@ use libc::{self, c_void, c_long, siginfo_t};
use ::unistd::Pid;
use sys::signal::Signal;
-pub mod ptrace {
- use libc::c_int;
-
- cfg_if! {
- if #[cfg(any(all(target_os = "linux", arch = "s390x"),
- all(target_os = "linux", target_env = "gnu")))] {
- pub type PtraceRequest = ::libc::c_uint;
- } else {
- pub type PtraceRequest = c_int;
- }
+
+cfg_if! {
+ if #[cfg(any(all(target_os = "linux", arch = "s390x"),
+ all(target_os = "linux", target_env = "gnu")))] {
+ #[doc(hidden)]
+ pub type RequestType = ::libc::c_uint;
+ } else {
+ #[doc(hidden)]
+ pub type RequestType = ::libc::c_int;
+ }
+}
+
+libc_enum!{
+ #[cfg_attr(not(any(target_env = "musl", target_os = "android")), repr(u32))]
+ #[cfg_attr(any(target_env = "musl", target_os = "android"), repr(i32))]
+ /// Ptrace Request enum defining the action to be taken.
+ pub enum Request {
+ PTRACE_TRACEME,
+ PTRACE_PEEKTEXT,
+ PTRACE_PEEKDATA,
+ PTRACE_PEEKUSER,
+ PTRACE_POKETEXT,
+ PTRACE_POKEDATA,
+ PTRACE_POKEUSER,
+ PTRACE_CONT,
+ PTRACE_KILL,
+ PTRACE_SINGLESTEP,
+ #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
+ PTRACE_GETREGS,
+ #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
+ PTRACE_SETREGS,
+ #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
+ PTRACE_GETFPREGS,
+ #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
+ PTRACE_SETFPREGS,
+ PTRACE_ATTACH,
+ PTRACE_DETACH,
+ #[cfg(all(any(target_env = "musl", target_arch ="x86_64"), not(target_os = "android")))]
+ PTRACE_GETFPXREGS,
+ #[cfg(all(any(target_env = "musl", target_arch ="x86_64"), not(target_os = "android")))]
+ PTRACE_SETFPXREGS,
+ PTRACE_SYSCALL,
+ PTRACE_SETOPTIONS,
+ PTRACE_GETEVENTMSG,
+ PTRACE_GETSIGINFO,
+ PTRACE_SETSIGINFO,
+ #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
+ PTRACE_GETREGSET,
+ #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
+ PTRACE_SETREGSET,
+ #[cfg(not(any(target_os = "android", target_arch = "mips", target_arch = "mips64")))]
+ PTRACE_SEIZE,
+ #[cfg(not(any(target_os = "android", target_arch = "mips", target_arch = "mips64")))]
+ PTRACE_INTERRUPT,
+ #[cfg(not(any(target_os = "android", target_arch = "mips", target_arch = "mips64")))]
+ PTRACE_LISTEN,
+ #[cfg(not(any(target_os = "android", target_arch = "mips", target_arch = "mips64")))]
+ PTRACE_PEEKSIGINFO,
+ }
+}
+
+libc_enum!{
+ #[repr(i32)]
+ /// Using the ptrace options the tracer can configure the tracee to stop
+ /// at certain events. This enum is used to define those events as defined
+ /// in `man ptrace`.
+ pub enum Event {
+ /// Event that stops before a return from fork or clone.
+ PTRACE_EVENT_FORK,
+ /// Event that stops before a return from vfork or clone.
+ PTRACE_EVENT_VFORK,
+ /// Event that stops before a return from clone.
+ PTRACE_EVENT_CLONE,
+ /// Event that stops before a return from execve.
+ PTRACE_EVENT_EXEC,
+ /// Event for a return from vfork.
+ PTRACE_EVENT_VFORK_DONE,
+ /// Event for a stop before an exit. Unlike the waitpid Exit status program.
+ /// registers can still be examined
+ PTRACE_EVENT_EXIT,
+ /// STop triggered by a seccomp rule on a tracee.
+ PTRACE_EVENT_SECCOMP,
+ // PTRACE_EVENT_STOP not provided by libc because it's defined in glibc 2.26
}
+}
- pub const PTRACE_TRACEME: PtraceRequest = 0;
- pub const PTRACE_PEEKTEXT: PtraceRequest = 1;
- pub const PTRACE_PEEKDATA: PtraceRequest = 2;
- pub const PTRACE_PEEKUSER: PtraceRequest = 3;
- pub const PTRACE_POKETEXT: PtraceRequest = 4;
- pub const PTRACE_POKEDATA: PtraceRequest = 5;
- pub const PTRACE_POKEUSER: PtraceRequest = 6;
- pub const PTRACE_CONT: PtraceRequest = 7;
- pub const PTRACE_KILL: PtraceRequest = 8;
- pub const PTRACE_SINGLESTEP: PtraceRequest = 9;
- pub const PTRACE_GETREGS: PtraceRequest = 12;
- pub const PTRACE_SETREGS: PtraceRequest = 13;
- pub const PTRACE_GETFPREGS: PtraceRequest = 14;
- pub const PTRACE_SETFPREGS: PtraceRequest = 15;
- pub const PTRACE_ATTACH: PtraceRequest = 16;
- pub const PTRACE_DETACH: PtraceRequest = 17;
- pub const PTRACE_GETFPXREGS: PtraceRequest = 18;
- pub const PTRACE_SETFPXREGS: PtraceRequest = 19;
- pub const PTRACE_SYSCALL: PtraceRequest = 24;
- pub const PTRACE_SETOPTIONS: PtraceRequest = 0x4200;
- pub const PTRACE_GETEVENTMSG: PtraceRequest = 0x4201;
- pub const PTRACE_GETSIGINFO: PtraceRequest = 0x4202;
- pub const PTRACE_SETSIGINFO: PtraceRequest = 0x4203;
- pub const PTRACE_GETREGSET: PtraceRequest = 0x4204;
- pub const PTRACE_SETREGSET: PtraceRequest = 0x4205;
- pub const PTRACE_SEIZE: PtraceRequest = 0x4206;
- pub const PTRACE_INTERRUPT: PtraceRequest = 0x4207;
- pub const PTRACE_LISTEN: PtraceRequest = 0x4208;
- pub const PTRACE_PEEKSIGINFO: PtraceRequest = 0x4209;
-
- pub type PtraceEvent = c_int;
-
- pub const PTRACE_EVENT_FORK: PtraceEvent = 1;
- pub const PTRACE_EVENT_VFORK: PtraceEvent = 2;
- pub const PTRACE_EVENT_CLONE: PtraceEvent = 3;
- pub const PTRACE_EVENT_EXEC: PtraceEvent = 4;
- pub const PTRACE_EVENT_VFORK_DONE: PtraceEvent = 5;
- pub const PTRACE_EVENT_EXIT: PtraceEvent = 6;
- pub const PTRACE_EVENT_SECCOMP: PtraceEvent = 6;
- pub const PTRACE_EVENT_STOP: PtraceEvent = 128;
-
- pub type PtraceOptions = c_int;
- pub const PTRACE_O_TRACESYSGOOD: PtraceOptions = 1;
- pub const PTRACE_O_TRACEFORK: PtraceOptions = (1 << PTRACE_EVENT_FORK);
- pub const PTRACE_O_TRACEVFORK: PtraceOptions = (1 << PTRACE_EVENT_VFORK);
- pub const PTRACE_O_TRACECLONE: PtraceOptions = (1 << PTRACE_EVENT_CLONE);
- pub const PTRACE_O_TRACEEXEC: PtraceOptions = (1 << PTRACE_EVENT_EXEC);
- pub const PTRACE_O_TRACEVFORKDONE: PtraceOptions = (1 << PTRACE_EVENT_VFORK_DONE);
- pub const PTRACE_O_TRACEEXIT: PtraceOptions = (1 << PTRACE_EVENT_EXIT);
- pub const PTRACE_O_TRACESECCOMP: PtraceOptions = (1 << PTRACE_EVENT_SECCOMP);
+libc_bitflags! {
+ /// Ptrace options used in conjunction with the PTRACE_SETOPTIONS request.
+ /// See `man ptrace` for more details.
+ pub struct Options: libc::c_int {
+ /// When delivering system call traps set a bit to allow tracer to
+ /// distinguish between normal stops or syscall stops. May not work on
+ /// all systems.
+ PTRACE_O_TRACESYSGOOD;
+ /// Stop tracee at next fork and start tracing the forked process.
+ PTRACE_O_TRACEFORK;
+ /// Stop tracee at next vfork call and trace the vforked process.
+ PTRACE_O_TRACEVFORK;
+ /// Stop tracee at next clone call and trace the cloned process.
+ PTRACE_O_TRACECLONE;
+ /// Stop tracee at next execve call.
+ PTRACE_O_TRACEEXEC;
+ /// Stop tracee at vfork completion.
+ PTRACE_O_TRACEVFORKDONE;
+ /// Stop tracee at next exit call. Stops before exit commences allowing
+ /// tracer to see location of exit and register states.
+ PTRACE_O_TRACEEXIT;
+ /// Stop tracee when a SECCOMP_RET_TRACE rule is triggered. See `man seccomp` for more
+ /// details.
+ PTRACE_O_TRACESECCOMP;
+ }
}
/// Performs a ptrace request. If the request in question is provided by a specialised function
@@ -76,9 +125,8 @@ pub mod ptrace {
since="0.10.0",
note="usages of `ptrace()` should be replaced with the specialized helper functions instead"
)]
-pub unsafe fn ptrace(request: ptrace::PtraceRequest, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
- use self::ptrace::*;
-
+pub unsafe fn ptrace(request: Request, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
+ use self::Request::*;
match request {
PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_PEEKUSER => ptrace_peek(request, pid, addr, data),
PTRACE_GETSIGINFO | PTRACE_GETEVENTMSG | PTRACE_SETSIGINFO | PTRACE_SETOPTIONS => Err(Error::UnsupportedOperation),
@@ -86,10 +134,10 @@ pub unsafe fn ptrace(request: ptrace::PtraceRequest, pid: Pid, addr: *mut c_void
}
}
-fn ptrace_peek(request: ptrace::PtraceRequest, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
+fn ptrace_peek(request: Request, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
let ret = unsafe {
Errno::clear();
- libc::ptrace(request, libc::pid_t::from(pid), addr, data)
+ libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)
};
match Errno::result(ret) {
Ok(..) | Err(Error::Sys(Errno::UnknownErrno)) => Ok(ret),
@@ -101,45 +149,54 @@ fn ptrace_peek(request: ptrace::PtraceRequest, pid: Pid, addr: *mut c_void, data
/// Some ptrace get requests populate structs or larger elements than c_long
/// and therefore use the data field to return values. This function handles these
/// requests.
-fn ptrace_get_data<T>(request: ptrace::PtraceRequest, pid: Pid) -> Result<T> {
+fn ptrace_get_data<T>(request: Request, pid: Pid) -> Result<T> {
// Creates an uninitialized pointer to store result in
let data: T = unsafe { mem::uninitialized() };
- let res = unsafe { libc::ptrace(request, libc::pid_t::from(pid), ptr::null_mut::<T>(), &data as *const _ as *const c_void) };
+ let res = unsafe {
+ libc::ptrace(request as RequestType,
+ libc::pid_t::from(pid),
+ ptr::null_mut::<T>(),
+ &data as *const _ as *const c_void)
+ };
Errno::result(res)?;
Ok(data)
}
-unsafe fn ptrace_other(request: ptrace::PtraceRequest, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
- Errno::result(libc::ptrace(request, libc::pid_t::from(pid), addr, data)).map(|_| 0)
+unsafe fn ptrace_other(request: Request, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
+ Errno::result(libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)).map(|_| 0)
}
/// Set options, as with `ptrace(PTRACE_SETOPTIONS,...)`.
-pub fn setoptions(pid: Pid, options: ptrace::PtraceOptions) -> Result<()> {
- use self::ptrace::*;
+pub fn setoptions(pid: Pid, options: Options) -> Result<()> {
use std::ptr;
- let res = unsafe { libc::ptrace(PTRACE_SETOPTIONS, libc::pid_t::from(pid), ptr::null_mut::<libc::c_void>(), options as *mut c_void) };
+ let res = unsafe {
+ libc::ptrace(Request::PTRACE_SETOPTIONS as RequestType,
+ libc::pid_t::from(pid),
+ ptr::null_mut::<libc::c_void>(),
+ options.bits() as *mut c_void)
+ };
Errno::result(res).map(|_| ())
}
/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)`
pub fn getevent(pid: Pid) -> Result<c_long> {
- use self::ptrace::*;
- ptrace_get_data::<c_long>(PTRACE_GETEVENTMSG, pid)
+ ptrace_get_data::<c_long>(Request::PTRACE_GETEVENTMSG, pid)
}
/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO,...)`
pub fn getsiginfo(pid: Pid) -> Result<siginfo_t> {
- use self::ptrace::*;
- ptrace_get_data::<siginfo_t>(PTRACE_GETSIGINFO, pid)
+ ptrace_get_data::<siginfo_t>(Request::PTRACE_GETSIGINFO, pid)
}
/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)`
pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> {
- use self::ptrace::*;
let ret = unsafe{
Errno::clear();
- libc::ptrace(PTRACE_SETSIGINFO, libc::pid_t::from(pid), ptr::null_mut::<libc::c_void>(), sig as *const _ as *const c_void)
+ libc::ptrace(Request::PTRACE_SETSIGINFO as RequestType,
+ libc::pid_t::from(pid),
+ ptr::null_mut::<libc::c_void>(),
+ sig as *const _ as *const c_void)
};
match Errno::result(ret) {
Ok(_) => Ok(()),
@@ -154,7 +211,7 @@ pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> {
pub fn traceme() -> Result<()> {
unsafe {
ptrace_other(
- ptrace::PTRACE_TRACEME,
+ Request::PTRACE_TRACEME,
Pid::from_raw(0),
ptr::null_mut(),
ptr::null_mut(),
@@ -168,7 +225,7 @@ pub fn traceme() -> Result<()> {
pub fn syscall(pid: Pid) -> Result<()> {
unsafe {
ptrace_other(
- ptrace::PTRACE_SYSCALL,
+ Request::PTRACE_SYSCALL,
pid,
ptr::null_mut(),
ptr::null_mut(),
@@ -182,7 +239,7 @@ pub fn syscall(pid: Pid) -> Result<()> {
pub fn attach(pid: Pid) -> Result<()> {
unsafe {
ptrace_other(
- ptrace::PTRACE_ATTACH,
+ Request::PTRACE_ATTACH,
pid,
ptr::null_mut(),
ptr::null_mut(),
@@ -190,6 +247,20 @@ pub fn attach(pid: Pid) -> Result<()> {
}
}
+/// Detaches the current running process, as with `ptrace(PTRACE_DETACH, ...)`
+///
+/// Detaches from the process specified in pid allowing it to run freely
+pub fn detach(pid: Pid) -> Result<()> {
+ unsafe {
+ ptrace_other(
+ Request::PTRACE_DETACH,
+ pid,
+ ptr::null_mut(),
+ ptr::null_mut()
+ ).map(|_| ())
+ }
+}
+
/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
///
/// Continues the execution of the process with PID `pid`, optionally
@@ -200,7 +271,7 @@ pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
None => ptr::null_mut(),
};
unsafe {
- ptrace_other(ptrace::PTRACE_CONT, pid, ptr::null_mut(), data).map(|_| ()) // ignore the useless return value
+ ptrace_other(Request::PTRACE_CONT, pid, ptr::null_mut(), data).map(|_| ()) // ignore the useless return value
}
}
diff --git a/src/sys/quota.rs b/src/sys/quota.rs
index 1cd143bd..77b13335 100644
--- a/src/sys/quota.rs
+++ b/src/sys/quota.rs
@@ -1,78 +1,235 @@
-use {Errno, Result, NixPath};
+//! Set and configure disk quotas for users, groups, or projects.
+//!
+//! # Examples
+//!
+//! Enabling and setting a quota:
+//!
+//! ```rust,no_run
+//! # use nix::sys::quota::*;
+//! quotactl_on(QuotaType::USRQUOTA, "/dev/sda1", QuotaFmt::QFMT_VFS_V1, "aquota.user");
+//! let mut dqblk: Dqblk = Default::default();
+//! dqblk.set_blocks_hard_limit(10000);
+//! dqblk.set_blocks_soft_limit(8000);
+//! quotactl_set(QuotaType::USRQUOTA, "/dev/sda1", 50, &dqblk, QIF_BLIMITS);
+//! ```
+use std::default::Default;
+use std::{mem, ptr};
use libc::{self, c_int, c_char};
+use {Errno, Result, NixPath};
-#[cfg(all(target_os = "linux",
- any(target_arch = "x86",
- target_arch = "x86_64",
- target_arch = "arm")),
- )]
-pub mod quota {
- use libc::{self, c_int};
+struct QuotaCmd(QuotaSubCmd, QuotaType);
- pub struct QuotaCmd(pub QuotaSubCmd, pub QuotaType);
- pub type QuotaSubCmd = c_int;
+impl QuotaCmd {
+ fn as_int(&self) -> c_int {
+ unsafe { libc::QCMD(self.0 as i32, self.1 as i32) }
+ }
+}
+
+// linux quota version >= 2
+libc_enum!{
+ #[repr(i32)]
+ enum QuotaSubCmd {
+ Q_SYNC,
+ Q_QUOTAON,
+ Q_QUOTAOFF,
+ Q_GETFMT,
+ Q_GETINFO,
+ Q_SETINFO,
+ Q_GETQUOTA,
+ Q_SETQUOTA,
+ }
+}
+
+libc_enum!{
+ /// The scope of the quota.
+ #[repr(i32)]
+ pub enum QuotaType {
+ /// Specify a user quota
+ USRQUOTA,
+ /// Specify a group quota
+ GRPQUOTA,
+ }
+}
+
+libc_enum!{
+ /// The type of quota format to use.
+ #[repr(i32)]
+ pub enum QuotaFmt {
+ /// Use the original quota format.
+ QFMT_VFS_OLD,
+ /// Use the standard VFS v0 quota format.
+ ///
+ /// Handles 32-bit UIDs/GIDs and quota limits up to 2^42 bytes/2^32 inodes.
+ QFMT_VFS_V0,
+ /// Use the VFS v1 quota format.
+ ///
+ /// Handles 32-bit UIDs/GIDs and quota limits of 2^64 bytes/2^64 inodes.
+ QFMT_VFS_V1,
+ }
+}
- impl QuotaCmd {
- pub fn as_int(&self) -> c_int {
- ((self.0 << 8) | (self.1 & 0x00ff)) as c_int
+libc_bitflags!(
+ /// Indicates the quota fields that are valid to read from.
+ #[derive(Default)]
+ pub struct QuotaValidFlags: u32 {
+ /// The block hard & soft limit fields.
+ QIF_BLIMITS;
+ /// The current space field.
+ QIF_SPACE;
+ /// The inode hard & soft limit fields.
+ QIF_ILIMITS;
+ /// The current inodes field.
+ QIF_INODES;
+ /// The disk use time limit field.
+ QIF_BTIME;
+ /// The file quote time limit field.
+ QIF_ITIME;
+ /// All block & inode limits.
+ QIF_LIMITS;
+ /// The space & inodes usage fields.
+ QIF_USAGE;
+ /// The time limit fields.
+ QIF_TIMES;
+ /// All fields.
+ QIF_ALL;
+ }
+);
+
+/// Wrapper type for `if_dqblk`
+// FIXME: Change to repr(transparent)
+#[repr(C)]
+#[derive(Clone, Copy)]
+pub struct Dqblk(libc::dqblk);
+
+impl Default for Dqblk {
+ fn default() -> Dqblk {
+ Dqblk(libc::dqblk {
+ dqb_bhardlimit: 0,
+ dqb_bsoftlimit: 0,
+ dqb_curspace: 0,
+ dqb_ihardlimit: 0,
+ dqb_isoftlimit: 0,
+ dqb_curinodes: 0,
+ dqb_btime: 0,
+ dqb_itime: 0,
+ dqb_valid: 0,
+ })
+ }
+}
+
+impl Dqblk {
+ /// The absolute limit on disk quota blocks allocated.
+ pub fn blocks_hard_limit(&self) -> Option<u64> {
+ let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ if valid_fields.contains(QIF_BLIMITS) {
+ Some(self.0.dqb_bhardlimit)
+ } else {
+ None
}
}
- // linux quota version >= 2
- pub const Q_SYNC: QuotaSubCmd = 0x800001;
- pub const Q_QUOTAON: QuotaSubCmd = 0x800002;
- pub const Q_QUOTAOFF: QuotaSubCmd = 0x800003;
- pub const Q_GETFMT: QuotaSubCmd = 0x800004;
- pub const Q_GETINFO: QuotaSubCmd = 0x800005;
- pub const Q_SETINFO: QuotaSubCmd = 0x800006;
- pub const Q_GETQUOTA: QuotaSubCmd = 0x800007;
- pub const Q_SETQUOTA: QuotaSubCmd = 0x800008;
-
- pub type QuotaType = c_int;
-
- pub const USRQUOTA: QuotaType = 0;
- pub const GRPQUOTA: QuotaType = 1;
-
- pub type QuotaFmt = c_int;
-
- pub const QFMT_VFS_OLD: QuotaFmt = 1;
- pub const QFMT_VFS_V0: QuotaFmt = 2;
- pub const QFMT_VFS_V1: QuotaFmt = 4;
-
- libc_bitflags!(
- #[derive(Default)]
- pub struct QuotaValidFlags: u32 {
- QIF_BLIMITS;
- QIF_SPACE;
- QIF_ILIMITS;
- QIF_INODES;
- QIF_BTIME;
- QIF_ITIME;
- QIF_LIMITS;
- QIF_USAGE;
- QIF_TIMES;
- QIF_ALL;
+ /// Set the absolute limit on disk quota blocks allocated.
+ pub fn set_blocks_hard_limit(&mut self, limit: u64) {
+ self.0.dqb_bhardlimit = limit;
+ }
+
+ /// Preferred limit on disk quota blocks
+ pub fn blocks_soft_limit(&self) -> Option<u64> {
+ let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ if valid_fields.contains(QIF_BLIMITS) {
+ Some(self.0.dqb_bsoftlimit)
+ } else {
+ None
}
- );
-
- #[repr(C)]
- #[derive(Default,Debug,Copy,Clone)]
- pub struct Dqblk {
- pub bhardlimit: u64,
- pub bsoftlimit: u64,
- pub curspace: u64,
- pub ihardlimit: u64,
- pub isoftlimit: u64,
- pub curinodes: u64,
- pub btime: u64,
- pub itime: u64,
- pub valid: QuotaValidFlags,
}
-}
-use std::ptr;
+ /// Set the preferred limit on disk quota blocks allocated.
+ pub fn set_blocks_soft_limit(&mut self, limit: u64) {
+ self.0.dqb_bsoftlimit = limit;
+ }
+
+ /// Current occupied space (bytes).
+ pub fn occupied_space(&self) -> Option<u64> {
+ let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ if valid_fields.contains(QIF_SPACE) {
+ Some(self.0.dqb_curspace)
+ } else {
+ None
+ }
+ }
+
+ /// Maximum number of allocated inodes.
+ pub fn inodes_hard_limit(&self) -> Option<u64> {
+ let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ if valid_fields.contains(QIF_ILIMITS) {
+ Some(self.0.dqb_ihardlimit)
+ } else {
+ None
+ }
+ }
+
+ /// Set the maximum number of allocated inodes.
+ pub fn set_inodes_hard_limit(&mut self, limit: u64) {
+ self.0.dqb_ihardlimit = limit;
+ }
+
+ /// Preferred inode limit
+ pub fn inodes_soft_limit(&self) -> Option<u64> {
+ let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ if valid_fields.contains(QIF_ILIMITS) {
+ Some(self.0.dqb_isoftlimit)
+ } else {
+ None
+ }
+ }
+
+ /// Set the preferred limit of allocated inodes.
+ pub fn set_inodes_soft_limit(&mut self, limit: u64) {
+ self.0.dqb_isoftlimit = limit;
+ }
+
+ /// Current number of allocated inodes.
+ pub fn allocated_inodes(&self) -> Option<u64> {
+ let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ if valid_fields.contains(QIF_INODES) {
+ Some(self.0.dqb_curinodes)
+ } else {
+ None
+ }
+ }
+
+ /// Time limit for excessive disk use.
+ pub fn block_time_limit(&self) -> Option<u64> {
+ let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ if valid_fields.contains(QIF_BTIME) {
+ Some(self.0.dqb_btime)
+ } else {
+ None
+ }
+ }
+
+ /// Set the time limit for excessive disk use.
+ pub fn set_block_time_limit(&mut self, limit: u64) {
+ self.0.dqb_btime = limit;
+ }
+
+ /// Time limit for excessive files.
+ pub fn inode_time_limit(&self) -> Option<u64> {
+ let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
+ if valid_fields.contains(QIF_ITIME) {
+ Some(self.0.dqb_itime)
+ } else {
+ None
+ }
+ }
+
+ /// Set the time limit for excessive files.
+ pub fn set_inode_time_limit(&mut self, limit: u64) {
+ self.0.dqb_itime = limit;
+ }
+}
-fn quotactl<P: ?Sized + NixPath>(cmd: quota::QuotaCmd, special: Option<&P>, id: c_int, addr: *mut c_char) -> Result<()> {
+fn quotactl<P: ?Sized + NixPath>(cmd: QuotaCmd, special: Option<&P>, id: c_int, addr: *mut c_char) -> Result<()> {
unsafe {
Errno::clear();
let res = try!(
@@ -86,27 +243,35 @@ fn quotactl<P: ?Sized + NixPath>(cmd: quota::QuotaCmd, special: Option<&P>, id:
}
}
-pub fn quotactl_on<P: ?Sized + NixPath>(which: quota::QuotaType, special: &P, format: quota::QuotaFmt, quota_file: &P) -> Result<()> {
+/// Turn on disk quotas for a block device.
+pub fn quotactl_on<P: ?Sized + NixPath>(which: QuotaType, special: &P, format: QuotaFmt, quota_file: &P) -> Result<()> {
try!(quota_file.with_nix_path(|path| {
let mut path_copy = path.to_bytes_with_nul().to_owned();
let p: *mut c_char = path_copy.as_mut_ptr() as *mut c_char;
- quotactl(quota::QuotaCmd(quota::Q_QUOTAON, which), Some(special), format as c_int, p)
+ quotactl(QuotaCmd(QuotaSubCmd::Q_QUOTAON, which), Some(special), format as c_int, p)
}))
}
-pub fn quotactl_off<P: ?Sized + NixPath>(which: quota::QuotaType, special: &P) -> Result<()> {
- quotactl(quota::QuotaCmd(quota::Q_QUOTAOFF, which), Some(special), 0, ptr::null_mut())
+/// Disable disk quotas for a block device.
+pub fn quotactl_off<P: ?Sized + NixPath>(which: QuotaType, special: &P) -> Result<()> {
+ quotactl(QuotaCmd(QuotaSubCmd::Q_QUOTAOFF, which), Some(special), 0, ptr::null_mut())
}
-pub fn quotactl_sync<P: ?Sized + NixPath>(which: quota::QuotaType, special: Option<&P>) -> Result<()> {
- quotactl(quota::QuotaCmd(quota::Q_SYNC, which), special, 0, ptr::null_mut())
+/// Update the on-disk copy of quota usages for a filesystem.
+pub fn quotactl_sync<P: ?Sized + NixPath>(which: QuotaType, special: Option<&P>) -> Result<()> {
+ quotactl(QuotaCmd(QuotaSubCmd::Q_SYNC, which), special, 0, ptr::null_mut())
}
-pub fn quotactl_get<P: ?Sized + NixPath>(which: quota::QuotaType, special: &P, id: c_int, dqblk: &mut quota::Dqblk) -> Result<()> {
- quotactl(quota::QuotaCmd(quota::Q_GETQUOTA, which), Some(special), id, dqblk as *mut _ as *mut c_char)
+/// Get disk quota limits and current usage for the given user/group id.
+pub fn quotactl_get<P: ?Sized + NixPath>(which: QuotaType, special: &P, id: c_int) -> Result<Dqblk> {
+ let mut dqblk = unsafe { mem::uninitialized() };
+ quotactl(QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which), Some(special), id, &mut dqblk as *mut _ as *mut c_char)?;
+ dqblk
}
-pub fn quotactl_set<P: ?Sized + NixPath>(which: quota::QuotaType, special: &P, id: c_int, dqblk: &quota::Dqblk) -> Result<()> {
+/// Configure quota values for the specified fields for a given user/group id.
+pub fn quotactl_set<P: ?Sized + NixPath>(which: QuotaType, special: &P, id: c_int, dqblk: &Dqblk, fields: QuotaValidFlags) -> Result<()> {
let mut dqblk_copy = *dqblk;
- quotactl(quota::QuotaCmd(quota::Q_SETQUOTA, which), Some(special), id, &mut dqblk_copy as *mut _ as *mut c_char)
+ dqblk_copy.0.dqb_valid = fields.bits();
+ quotactl(QuotaCmd(QuotaSubCmd::Q_SETQUOTA, which), Some(special), id, &mut dqblk_copy as *mut _ as *mut c_char)
}
diff --git a/src/sys/syscall.rs b/src/sys/syscall.rs
deleted file mode 100644
index 50866ca7..00000000
--- a/src/sys/syscall.rs
+++ /dev/null
@@ -1,91 +0,0 @@
-//! Indirect system call
-//!
-use libc::c_int;
-
-pub use self::arch::*;
-
-#[cfg(target_arch = "x86_64")]
-mod arch {
- use libc::c_long;
-
- pub type Syscall = c_long;
-
- pub static SYSPIVOTROOT: Syscall = 155;
- pub static MEMFD_CREATE: Syscall = 319;
-}
-
-#[cfg(target_arch = "x86")]
-mod arch {
- use libc::c_long;
-
- pub type Syscall = c_long;
-
- pub static SYSPIVOTROOT: Syscall = 217;
- pub static MEMFD_CREATE: Syscall = 356;
-}
-
-#[cfg(target_arch = "aarch64")]
-mod arch {
- use libc::c_long;
-
- pub type Syscall = c_long;
-
- pub static SYSPIVOTROOT: Syscall = 41;
- pub static MEMFD_CREATE: Syscall = 279;
-}
-
-#[cfg(target_arch = "arm")]
-mod arch {
- use libc::c_long;
-
- pub type Syscall = c_long;
-
- pub static SYSPIVOTROOT: Syscall = 218;
- pub static MEMFD_CREATE: Syscall = 385;
-}
-
-// Rust on mips uses the N32 ABI
-#[cfg(target_arch = "mips")]
-mod arch {
- use libc::c_long;
-
- pub type Syscall = c_long;
-
- pub static SYSPIVOTROOT: Syscall = 216;
- pub static MEMFD_CREATE: Syscall = 354;
-}
-
-// Rust on mips64 uses the N64 ABI
-#[cfg(target_arch = "mips64")]
-mod arch {
- use libc::c_long;
-
- pub type Syscall = c_long;
-
- pub static SYSPIVOTROOT: Syscall = 151;
- pub static MEMFD_CREATE: Syscall = 314;
-}
-
-#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
-mod arch {
- use libc::c_long;
-
- pub type Syscall = c_long;
-
- pub static SYSPIVOTROOT: Syscall = 203;
- pub static MEMFD_CREATE: Syscall = 360;
-}
-
-#[cfg(target_arch = "s390x")]
-mod arch {
- use libc::c_long;
-
- pub type Syscall = c_long;
-
- pub static SYSPIVOTROOT: Syscall = 217;
- pub static MEMFD_CREATE: Syscall = 350;
-}
-
-extern {
- pub fn syscall(num: Syscall, ...) -> c_int;
-}
diff --git a/src/unistd.rs b/src/unistd.rs
index af38cf2d..fad51272 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -16,7 +16,7 @@ use sys::stat::Mode;
use std::fmt;
#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use self::linux::*;
+pub use self::pivot_root::*;
#[cfg(any(target_os = "android", target_os = "freebsd",
target_os = "linux", target_os = "openbsd"))]
@@ -1647,8 +1647,8 @@ pub fn sysconf(var: SysconfVar) -> Result<Option<c_long>> {
}
#[cfg(any(target_os = "android", target_os = "linux"))]
-mod linux {
- use sys::syscall::{syscall, SYSPIVOTROOT};
+mod pivot_root {
+ use libc;
use {Errno, Result, NixPath};
pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
@@ -1656,7 +1656,7 @@ mod linux {
let res = try!(try!(new_root.with_nix_path(|new_root| {
put_old.with_nix_path(|put_old| {
unsafe {
- syscall(SYSPIVOTROOT, new_root.as_ptr(), put_old.as_ptr())
+ libc::syscall(libc::SYS_pivot_root, new_root.as_ptr(), put_old.as_ptr())
}
})
})));
diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs
index 16b24110..20cde1aa 100644
--- a/test/sys/test_ptrace.rs
+++ b/test/sys/test_ptrace.rs
@@ -16,8 +16,7 @@ fn test_ptrace() {
// Just make sure ptrace_setoptions can be called at all, for now.
#[test]
fn test_ptrace_setoptions() {
- use nix::sys::ptrace::ptrace::PTRACE_O_TRACESYSGOOD;
- let err = ptrace::setoptions(getpid(), PTRACE_O_TRACESYSGOOD).unwrap_err();
+ let err = ptrace::setoptions(getpid(), ptrace::PTRACE_O_TRACESYSGOOD).unwrap_err();
assert!(err != Error::UnsupportedOperation);
}
diff --git a/test/sys/test_termios.rs b/test/sys/test_termios.rs
index 2455a4e5..6640c3af 100644
--- a/test/sys/test_termios.rs
+++ b/test/sys/test_termios.rs
@@ -116,7 +116,7 @@ fn test_local_flags() {
// Set the master is in nonblocking mode or reading will never return.
let flags = fcntl::fcntl(pty.master, fcntl::F_GETFL).unwrap();
- let new_flags = fcntl::OFlag::from_bits(flags).unwrap() | fcntl::O_NONBLOCK;
+ let new_flags = fcntl::OFlag::from_bits_truncate(flags) | fcntl::O_NONBLOCK;
fcntl::fcntl(pty.master, fcntl::F_SETFL(new_flags)).unwrap();
// Write into the master
diff --git a/test/sys/test_wait.rs b/test/sys/test_wait.rs
index 0193e262..0fcaa19c 100644
--- a/test/sys/test_wait.rs
+++ b/test/sys/test_wait.rs
@@ -55,7 +55,7 @@ fn test_waitstatus_pid() {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod ptrace {
use nix::sys::ptrace;
- use nix::sys::ptrace::ptrace::*;
+ use nix::sys::ptrace::*;
use nix::sys::signal::*;
use nix::sys::wait::*;
use nix::unistd::*;
@@ -81,7 +81,7 @@ mod ptrace {
assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
// Then get the ptrace event for the process exiting
assert!(ptrace::cont(child, None).is_ok());
- assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceEvent(child, SIGTRAP, PTRACE_EVENT_EXIT)));
+ assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceEvent(child, SIGTRAP, Event::PTRACE_EVENT_EXIT as i32)));
// Finally get the normal wait() result, now that the process has exited
assert!(ptrace::cont(child, None).is_ok());
assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 0)));