diff options
author | Alan Somers <asomers@gmail.com> | 2021-02-20 13:52:50 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-20 13:52:50 -0700 |
commit | 1bca8059eb47d81e6a54cf87a5ff9eb17cd02687 (patch) | |
tree | 413ac7c5a2abf84ea4fb0d1eceb208187b86b07f | |
parent | c33fa7498a66c45ce2a708a514df1a05ad1ef7c9 (diff) | |
parent | 661738cceee4e479ded272a63e3082035b860351 (diff) | |
download | nix-1bca8059eb47d81e6a54cf87a5ff9eb17cd02687.zip |
Merge branch 'master' into timerfd-file-leak
-rw-r--r-- | .cirrus.yml | 4 | ||||
-rw-r--r-- | CHANGELOG.md | 14 | ||||
-rw-r--r-- | Cargo.toml | 4 | ||||
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | src/dir.rs | 86 | ||||
-rw-r--r-- | src/mqueue.rs | 21 | ||||
-rw-r--r-- | src/pty.rs | 2 | ||||
-rw-r--r-- | src/sys/signalfd.rs | 7 | ||||
-rw-r--r-- | src/sys/statfs.rs | 175 | ||||
-rw-r--r-- | src/sys/sysinfo.rs | 8 | ||||
-rw-r--r-- | src/sys/time.rs | 19 | ||||
-rw-r--r-- | src/sys/wait.rs | 38 | ||||
-rw-r--r-- | src/unistd.rs | 3 | ||||
-rw-r--r-- | test/sys/test_ptrace.rs | 10 | ||||
-rw-r--r-- | test/test_dir.rs | 2 | ||||
-rw-r--r-- | test/test_mq.rs | 18 |
16 files changed, 251 insertions, 161 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index d2df8701..d15b7eec 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -157,6 +157,10 @@ task: - name: Linux s390x env: TARGET: s390x-unknown-linux-gnu + - name: Linux x32 + env: + TARGET: x86_64-unknown-linux-gnux32 + CHECK_TESTS: true - name: NetBSD x86_64 env: TARGET: x86_64-unknown-netbsd diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c945c28..a00679d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,24 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate ### Added + +- Added a `passwd` field to `Group` (#[1338](https://github.com/nix-rust/nix/pull/1338)) - Added `mremap` (#[1306](https://github.com/nix-rust/nix/pull/1306)) - Added `personality` (#[1331](https://github.com/nix-rust/nix/pull/1331)) - Added limited Fuchsia support (#[1285](https://github.com/nix-rust/nix/pull/1285)) - Added `getpeereid` (#[1342](https://github.com/nix-rust/nix/pull/1342)) +- Implemented `IntoIterator` for `Dir` + (#[1333](https://github.com/nix-rust/nix/pull/1333)). +### Changed + ### Fixed - `TimerFd` now closes the underlying fd on drop. ([#1381](https://github.com/nix-rust/nix/pull/1381)) +- Define `*_MAGIC` filesystem constants on Linux s390x + (#[1372](https://github.com/nix-rust/nix/pull/1372)) +- mqueue, sysinfo, timespec, statfs, test_ptrace_syscall() on x32 + (#[1366](https://github.com/nix-rust/nix/pull/1366)) + ### Changed - Minimum supported Rust version is now 1.40.0. @@ -25,6 +36,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Removed +- `Dir`, `SignalFd`, and `PtyMaster` are no longer `Clone`. + (#[1382](https://github.com/nix-rust/nix/pull/1382)) + - Removed `SockLevel`, which hasn't been used for a few years (#[1362](https://github.com/nix-rust/nix/pull/1362)) - Removed both `Copy` and `Clone` from `TimerFd`. @@ -31,7 +31,7 @@ targets = [ ] [dependencies] -libc = { version = "0.2.78", features = [ "extra_traits" ] } +libc = { version = "0.2.82", features = [ "extra_traits" ] } bitflags = "1.1" cfg-if = "1.0" @@ -46,7 +46,7 @@ tempfile = "3.0.5" semver = "0.9.0" [target.'cfg(any(target_os = "android", target_os = "linux"))'.dev-dependencies] -caps = "0.3.1" +caps = "0.5.1" [target.'cfg(target_os = "freebsd")'.dev-dependencies] sysctl = "0.1" @@ -83,6 +83,7 @@ Tier 2: Tier 3: * x86_64-fuchsia * x86_64-unknown-redox + * x86_64-unknown-linux-gnux32 ## Usage @@ -25,7 +25,7 @@ use libc::{dirent, readdir_r}; /// * returns entries for `.` (current directory) and `..` (parent directory). /// * returns entries' names as a `CStr` (no allocation or conversion beyond whatever libc /// does). -#[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[derive(Debug, Eq, Hash, PartialEq)] pub struct Dir( ptr::NonNull<libc::DIR> ); @@ -85,7 +85,32 @@ impl AsRawFd for Dir { impl Drop for Dir { fn drop(&mut self) { - unsafe { libc::closedir(self.0.as_ptr()) }; + let e = Errno::result(unsafe { libc::closedir(self.0.as_ptr()) }); + if !std::thread::panicking() && e == Err(Error::Sys(Errno::EBADF)) { + panic!("Closing an invalid file descriptor!"); + }; + } +} + +fn next(dir: &mut Dir) -> Option<Result<Entry>> { + unsafe { + // Note: POSIX specifies that portable applications should dynamically allocate a + // buffer with room for a `d_name` field of size `pathconf(..., _PC_NAME_MAX)` plus 1 + // for the NUL byte. It doesn't look like the std library does this; it just uses + // fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate). + // Probably fine here too then. + let mut ent = std::mem::MaybeUninit::<dirent>::uninit(); + let mut result = ptr::null_mut(); + if let Err(e) = Errno::result( + readdir_r(dir.0.as_ptr(), ent.as_mut_ptr(), &mut result)) + { + return Some(Err(e)); + } + if result.is_null() { + return None; + } + assert_eq!(result, ent.as_mut_ptr()); + Some(Ok(Entry(ent.assume_init()))) } } @@ -96,25 +121,7 @@ impl<'d> Iterator for Iter<'d> { type Item = Result<Entry>; fn next(&mut self) -> Option<Self::Item> { - unsafe { - // Note: POSIX specifies that portable applications should dynamically allocate a - // buffer with room for a `d_name` field of size `pathconf(..., _PC_NAME_MAX)` plus 1 - // for the NUL byte. It doesn't look like the std library does this; it just uses - // fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate). - // Probably fine here too then. - let mut ent = std::mem::MaybeUninit::<dirent>::uninit(); - let mut result = ptr::null_mut(); - if let Err(e) = Errno::result( - readdir_r((self.0).0.as_ptr(), ent.as_mut_ptr(), &mut result)) - { - return Some(Err(e)); - } - if result.is_null() { - return None; - } - assert_eq!(result, ent.as_mut_ptr()); - Some(Ok(Entry(ent.assume_init()))) - } + next(self.0) } } @@ -124,6 +131,43 @@ impl<'d> Drop for Iter<'d> { } } +/// The return type of [Dir::into_iter] +#[derive(Debug, Eq, Hash, PartialEq)] +pub struct OwningIter(Dir); + +impl Iterator for OwningIter { + type Item = Result<Entry>; + + fn next(&mut self) -> Option<Self::Item> { + next(&mut self.0) + } +} + +impl IntoIterator for Dir { + type Item = Result<Entry>; + type IntoIter = OwningIter; + + /// Creates a owning iterator, that is, one that takes ownership of the + /// `Dir`. The `Dir` cannot be used after calling this. This can be useful + /// when you have a function that both creates a `Dir` instance and returns + /// an `Iterator`. + /// + /// Example: + /// + /// ``` + /// use nix::{dir::Dir, fcntl::OFlag, sys::stat::Mode}; + /// use std::{iter::Iterator, string::String}; + /// + /// fn ls_upper(dirname: &str) -> impl Iterator<Item=String> { + /// let d = Dir::open(dirname, OFlag::O_DIRECTORY, Mode::S_IXUSR).unwrap(); + /// d.into_iter().map(|x| x.unwrap().file_name().as_ref().to_string_lossy().to_ascii_uppercase()) + /// } + /// ``` + fn into_iter(self) -> Self::IntoIter { + OwningIter(self) + } +} + /// A directory entry, similar to `std::fs::DirEntry`. /// /// Note that unlike the std version, this may represent the `.` or `..` entries. diff --git a/src/mqueue.rs b/src/mqueue.rs index 122705a5..0215de5a 100644 --- a/src/mqueue.rs +++ b/src/mqueue.rs @@ -5,7 +5,7 @@ use crate::Result; use crate::errno::Errno; -use libc::{self, c_char, c_long, mqd_t, size_t}; +use libc::{self, c_char, mqd_t, size_t}; use std::ffi::CString; use crate::sys::stat::Mode; use std::mem; @@ -34,11 +34,18 @@ pub struct MqAttr { mq_attr: libc::mq_attr, } +// x32 compatibility +// See https://sourceware.org/bugzilla/show_bug.cgi?id=21279 +#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] +pub type mq_attr_member_t = i64; +#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] +pub type mq_attr_member_t = libc::c_long; + impl MqAttr { - pub fn new(mq_flags: c_long, - mq_maxmsg: c_long, - mq_msgsize: c_long, - mq_curmsgs: c_long) + pub fn new(mq_flags: mq_attr_member_t, + mq_maxmsg: mq_attr_member_t, + mq_msgsize: mq_attr_member_t, + mq_curmsgs: mq_attr_member_t) -> MqAttr { let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit(); @@ -52,7 +59,7 @@ impl MqAttr { } } - pub fn flags(&self) -> c_long { + pub fn flags(&self) -> mq_attr_member_t { self.mq_attr.mq_flags } } @@ -150,7 +157,7 @@ pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> { /// Returns the old attributes pub fn mq_set_nonblock(mqd: mqd_t) -> Result<MqAttr> { let oldattr = mq_getattr(mqd)?; - let newattr = MqAttr::new(c_long::from(MQ_OFlag::O_NONBLOCK.bits()), + let newattr = MqAttr::new(mq_attr_member_t::from(MQ_OFlag::O_NONBLOCK.bits()), oldattr.mq_attr.mq_maxmsg, oldattr.mq_attr.mq_msgsize, oldattr.mq_attr.mq_curmsgs); @@ -43,7 +43,7 @@ pub struct ForkptyResult { /// While this datatype is a thin wrapper around `RawFd`, it enforces that the available PTY /// functions are given the correct file descriptor. Additionally this type implements `Drop`, /// so that when it's consumed or goes out of scope, it's automatically cleaned-up. -#[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[derive(Debug, Eq, Hash, PartialEq)] pub struct PtyMaster(RawFd); impl AsRawFd for PtyMaster { diff --git a/src/sys/signalfd.rs b/src/sys/signalfd.rs index e3ded1f7..c43b4504 100644 --- a/src/sys/signalfd.rs +++ b/src/sys/signalfd.rs @@ -79,7 +79,7 @@ pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> { /// Err(err) => (), // some error happend /// } /// ``` -#[derive(Clone, Debug, Eq, Hash, PartialEq)] +#[derive(Debug, Eq, Hash, PartialEq)] pub struct SignalFd(RawFd); impl SignalFd { @@ -116,7 +116,10 @@ impl SignalFd { impl Drop for SignalFd { fn drop(&mut self) { - let _ = unistd::close(self.0); + let e = unistd::close(self.0); + if !std::thread::panicking() && e == Err(Error::Sys(Errno::EBADF)) { + panic!("Closing an invalid file descriptor!"); + }; } } diff --git a/src/sys/statfs.rs b/src/sys/statfs.rs index 8e90a58d..27b72592 100644 --- a/src/sys/statfs.rs +++ b/src/sys/statfs.rs @@ -16,79 +16,85 @@ pub type fsid_t = libc::fsid_t; pub struct Statfs(libc::statfs); #[cfg(target_os = "freebsd")] -#[derive(Eq, Copy, Clone, PartialEq, Debug)] -pub struct FsType(pub u32); +type fs_type_t = u32; #[cfg(target_os = "android")] -#[derive(Eq, Copy, Clone, PartialEq, Debug)] -pub struct FsType(pub libc::c_ulong); +type fs_type_t = libc::c_ulong; #[cfg(all(target_os = "linux", target_arch = "s390x"))] -#[derive(Eq, Copy, Clone, PartialEq, Debug)] -pub struct FsType(pub u32); +type fs_type_t = libc::c_uint; #[cfg(all(target_os = "linux", target_env = "musl"))] -#[derive(Eq, Copy, Clone, PartialEq, Debug)] -pub struct FsType(pub libc::c_ulong); +type fs_type_t = libc::c_ulong; #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))] +type fs_type_t = libc::__fsword_t; + +#[cfg(any( + target_os = "freebsd", + target_os = "android", + all(target_os = "linux", target_arch = "s390x"), + all(target_os = "linux", target_env = "musl"), + all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))), +))] #[derive(Eq, Copy, Clone, PartialEq, Debug)] -pub struct FsType(pub libc::c_long); - -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const OVERLAYFS_SUPER_MAGIC: FsType = FsType(libc::OVERLAYFS_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const CGROUP_SUPER_MAGIC: FsType = FsType(libc::CGROUP_SUPER_MAGIC); -#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))] -pub const CGROUP2_SUPER_MAGIC: FsType = FsType(libc::CGROUP2_SUPER_MAGIC); +pub struct FsType(pub fs_type_t); + +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const OVERLAYFS_SUPER_MAGIC: FsType = FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const CGROUP_SUPER_MAGIC: FsType = FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t); +#[cfg(all(target_os = "linux", not(target_env = "musl")))] +pub const CGROUP2_SUPER_MAGIC: FsType = FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t); + impl Statfs { /// Magic code defining system type @@ -138,7 +144,7 @@ impl Statfs { /// Optimal transfer block size #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))] - pub fn optimal_transfer_size(&self) -> libc::c_long { + pub fn optimal_transfer_size(&self) -> libc::__fsword_t { self.0.f_bsize } @@ -177,7 +183,7 @@ impl Statfs { /// Size of a block // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471 #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))] - pub fn block_size(&self) -> libc::c_long { + pub fn block_size(&self) -> libc::__fsword_t { self.0.f_bsize } @@ -219,7 +225,7 @@ impl Statfs { /// Maximum length of filenames #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))] - pub fn maximum_name_length(&self) -> libc::c_long { + pub fn maximum_name_length(&self) -> libc::__fsword_t { self.0.f_namelen } @@ -248,7 +254,7 @@ impl Statfs { } /// Total data blocks in filesystem - #[cfg(all(target_os = "linux", target_env = "musl"))] + #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))] pub fn blocks(&self) -> u64 { self.0.f_blocks } @@ -261,7 +267,7 @@ impl Statfs { target_os = "freebsd", target_os = "openbsd", target_os = "dragonfly", - all(target_os = "linux", target_env = "musl") + all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))) )))] pub fn blocks(&self) -> libc::c_ulong { self.0.f_blocks @@ -286,7 +292,7 @@ impl Statfs { } /// Free blocks in filesystem - #[cfg(all(target_os = "linux", target_env = "musl"))] + #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))] pub fn blocks_free(&self) -> u64 { self.0.f_bfree } @@ -299,7 +305,7 @@ impl Statfs { target_os = "freebsd", target_os = "openbsd", target_os = "dragonfly", - all(target_os = "linux", target_env = "musl") + all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))) )))] pub fn blocks_free(&self) -> libc::c_ulong { self.0.f_bfree @@ -324,7 +330,7 @@ impl Statfs { } /// Free blocks available to unprivileged user - #[cfg(all(target_os = "linux", target_env = "musl"))] + #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))] pub fn blocks_available(&self) -> u64 { self.0.f_bavail } @@ -337,7 +343,7 @@ impl Statfs { target_os = "freebsd", target_os = "openbsd", target_os = "dragonfly", - all(target_os = "linux", target_env = "musl") + all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))) )))] pub fn blocks_available(&self) -> libc::c_ulong { self.0.f_bavail @@ -362,8 +368,8 @@ impl Statfs { } /// Total file nodes in filesystem - #[cfg(all(target_os = "linux", target_env = "musl"))] - pub fn files(&self) -> u64 { + #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))] + pub fn files(&self) -> libc::fsfilcnt_t { self.0.f_files } @@ -375,7 +381,7 @@ impl Statfs { target_os = "freebsd", target_os = "openbsd", target_os = "dragonfly", - all(target_os = "linux", target_env = "musl") + all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))) )))] pub fn files(&self) -> libc::c_ulong { self.0.f_files @@ -385,7 +391,6 @@ impl Statfs { #[cfg(any( target_os = "android", target_os = "ios", - all(target_os = "linux", target_env = "musl"), target_os = "macos", target_os = "openbsd" ))] @@ -406,6 +411,12 @@ impl Statfs { } /// Free file nodes in filesystem + #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))] + pub fn files_free(&self) -> libc::fsfilcnt_t { + self.0.f_ffree + } + + /// Free file nodes in filesystem #[cfg(not(any( target_os = "ios", target_os = "macos", @@ -413,7 +424,7 @@ impl Statfs { target_os = "freebsd", target_os = "openbsd", target_os = "dragonfly", - all(target_os = "linux", target_env = "musl") + all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))) )))] pub fn files_free(&self) -> libc::c_ulong { self.0.f_ffree diff --git a/src/sys/sysinfo.rs b/src/sys/sysinfo.rs index f4b82798..222a2fc0 100644 --- a/src/sys/sysinfo.rs +++ b/src/sys/sysinfo.rs @@ -10,6 +10,12 @@ use crate::errno::Errno; #[repr(transparent)] pub struct SysInfo(libc::sysinfo); +// The fields are c_ulong on 32-bit linux, u64 on 64-bit linux; x32's ulong is u32 +#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] +type mem_blocks_t = u64; +#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] +type mem_blocks_t = libc::c_ulong; + impl SysInfo { /// Returns the load average tuple. /// @@ -58,7 +64,7 @@ impl SysInfo { self.scale_mem(self.0.freeram) } - fn scale_mem(&self, units: libc::c_ulong) -> u64 { + fn scale_mem(&self, units: mem_blocks_t) -> u64 { units as u64 * self.0.mem_unit as u64 } } diff --git a/src/sys/time.rs b/src/sys/time.rs index bdcfe3c9..7546d1b3 100644 --- a/src/sys/time.rs +++ b/src/sys/time.rs @@ -1,7 +1,7 @@ use std::{cmp, fmt, ops}; use std::time::Duration; use std::convert::From; -use libc::{c_long, timespec, timeval}; +use libc::{timespec, timeval}; #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 pub use libc::{time_t, suseconds_t}; @@ -62,6 +62,13 @@ const TS_MAX_SECONDS: i64 = ::std::isize::MAX as i64; const TS_MIN_SECONDS: i64 = -TS_MAX_SECONDS; +// x32 compatibility +// See https://sourceware.org/bugzilla/show_bug.cgi?id=16437 +#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] +type timespec_tv_nsec_t = i64; +#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] +type timespec_tv_nsec_t = libc::c_long; + impl From<timespec> for TimeSpec { fn from(ts: timespec) -> Self { Self(ts) @@ -73,7 +80,7 @@ impl From<Duration> for TimeSpec { #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 TimeSpec(timespec { tv_sec: duration.as_secs() as time_t, - tv_nsec: duration.subsec_nanos() as c_long + tv_nsec: duration.subsec_nanos() as timespec_tv_nsec_t }) } } @@ -148,7 +155,7 @@ impl TimeValLike for TimeSpec { "TimeSpec out of bounds"); #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 TimeSpec(timespec {tv_sec: secs as time_t, - tv_nsec: nanos as c_long }) + tv_nsec: nanos as timespec_tv_nsec_t }) } fn num_seconds(&self) -> i64 { @@ -175,9 +182,9 @@ impl TimeValLike for TimeSpec { } impl TimeSpec { - fn nanos_mod_sec(&self) -> c_long { + fn nanos_mod_sec(&self) -> timespec_tv_nsec_t { if self.tv_sec() < 0 && self.tv_nsec() > 0 { - self.tv_nsec() - NANOS_PER_SEC as c_long + self.tv_nsec() - NANOS_PER_SEC as timespec_tv_nsec_t } else { self.tv_nsec() } @@ -188,7 +195,7 @@ impl TimeSpec { self.0.tv_sec } - pub fn tv_nsec(&self) -> c_long { + pub fn tv_nsec(&self) -> timespec_tv_nsec_t { self.0.tv_nsec } } diff --git a/src/sys/wait.rs b/src/sys/wait.rs index 0c040427..faf8543c 100644 --- a/src/sys/wait.rs +++ b/src/sys/wait.rs @@ -1,9 +1,9 @@ -use cfg_if::cfg_if; -use libc::{self, c_int}; -use crate::Result; use crate::errno::Errno; -use crate::unistd::Pid; use crate::sys::signal::Signal; +use crate::unistd::Pid; +use crate::Result; +use cfg_if::cfg_if; +use libc::{self, c_int}; use std::convert::TryFrom; libc_bitflags!( @@ -108,8 +108,7 @@ impl WaitStatus { pub fn pid(&self) -> Option<Pid> { use self::WaitStatus::*; match *self { - Exited(p, _) | Signaled(p, _, _) | - Stopped(p, _) | Continued(p) => Some(p), + Exited(p, _) | Signaled(p, _, _) | Stopped(p, _) | Continued(p) => Some(p), StillAlive => None, #[cfg(any(target_os = "android", target_os = "linux"))] PtraceEvent(p, _, _) | PtraceSyscall(p) => Some(p), @@ -117,49 +116,41 @@ impl WaitStatus { } } -#[allow(unused_unsafe)] fn exited(status: i32) -> bool { - unsafe { libc::WIFEXITED(status) } + libc::WIFEXITED(status) } -#[allow(unused_unsafe)] fn exit_status(status: i32) -> i32 { - unsafe { libc::WEXITSTATUS(status) } + libc::WEXITSTATUS(status) } -#[allow(unused_unsafe)] fn signaled(status: i32) -> bool { - unsafe { libc::WIFSIGNALED(status) } + libc::WIFSIGNALED(status) } -#[allow(unused_unsafe)] fn term_signal(status: i32) -> Result<Signal> { - Signal::try_from(unsafe { libc::WTERMSIG(status) }) + Signal::try_from(libc::WTERMSIG(status)) } -#[allow(unused_unsafe)] fn dumped_core(status: i32) -> bool { - unsafe { libc::WCOREDUMP(status) } + libc::WCOREDUMP(status) } -#[allow(unused_unsafe)] fn stopped(status: i32) -> bool { - unsafe { libc::WIFSTOPPED(status) } + libc::WIFSTOPPED(status) } -#[allow(unused_unsafe)] fn stop_signal(status: i32) -> Result<Signal> { - Signal::try_from(unsafe { libc::WSTOPSIG(status) }) + Signal::try_from(libc::WSTOPSIG(status)) } #[cfg(any(target_os = "android", target_os = "linux"))] -#[allow(unused_unsafe)] fn syscall_stop(status: i32) -> bool { // From ptrace(2), setting PTRACE_O_TRACESYSGOOD has the effect // of delivering SIGTRAP | 0x80 as the signal number for syscall // stops. This allows easily distinguishing syscall stops from // genuine SIGTRAP signals. - unsafe { libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80 } + libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80 } #[cfg(any(target_os = "android", target_os = "linux"))] @@ -167,9 +158,8 @@ fn stop_additional(status: i32) -> c_int { (status >> 16) as c_int } -#[allow(unused_unsafe)] fn continued(status: i32) -> bool { - unsafe { libc::WIFCONTINUED(status) } + libc::WIFCONTINUED(status) } impl WaitStatus { diff --git a/src/unistd.rs b/src/unistd.rs index dd335596..7a4517e6 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -2671,6 +2671,8 @@ impl User { pub struct Group { /// Group name pub name: String, + /// Group password + pub passwd: CString, /// Group ID pub gid: Gid, /// List of Group members @@ -2683,6 +2685,7 @@ impl From<&libc::group> for Group { unsafe { Group { name: CStr::from_ptr((*gr).gr_name).to_string_lossy().into_owned(), + passwd: CString::new(CStr::from_ptr((*gr).gr_passwd).to_bytes()).unwrap(), gid: Gid::from_raw((*gr).gr_gid), mem: Group::members((*gr).gr_mem) } diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs index 38cf408b..b9793b39 100644 --- a/test/sys/test_ptrace.rs +++ b/test/sys/test_ptrace.rs @@ -100,7 +100,7 @@ fn test_ptrace_cont() { ptrace::cont(child, Some(Signal::SIGKILL)).unwrap(); match waitpid(child, None) { Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => { - // FIXME It's been observed on some systems (apple) the + // FIXME It's been observed on some systems (apple) the // tracee may not be killed but remain as a zombie process // affecting other wait based tests. Add an extra kill just // to make sure there are no zombies. @@ -150,11 +150,11 @@ fn test_ptrace_syscall() { // set this option to recognize syscall-stops ptrace::setoptions(child, ptrace::Options::PTRACE_O_TRACESYSGOOD).unwrap(); - #[cfg(target_pointer_width = "64")] - let get_syscall_id = || ptrace::getregs(child).unwrap().orig_rax as i64; + #[cfg(target_arch = "x86_64")] + let get_syscall_id = || ptrace::getregs(child).unwrap().orig_rax as libc::c_long; - #[cfg(target_pointer_width = "32")] - let get_syscall_id = || ptrace::getregs(child).unwrap().orig_eax as i32; + #[cfg(target_arch = "x86")] + let get_syscall_id = || ptrace::getregs(child).unwrap().orig_eax as libc::c_long; // kill entry ptrace::syscall(child, None).unwrap(); diff --git a/test/test_dir.rs b/test/test_dir.rs index c5f9c517..505277e7 100644 --- a/test/test_dir.rs +++ b/test/test_dir.rs @@ -34,7 +34,9 @@ fn rewind() { Mode::empty()).unwrap(); let entries1: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect(); let entries2: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect(); + let entries3: Vec<_> = dir.into_iter().map(|e| e.unwrap().file_name().to_owned()).collect(); assert_eq!(entries1, entries2); + assert_eq!(entries2, entries3); } #[test] diff --git a/test/test_mq.rs b/test/test_mq.rs index ecee2009..1667a35b 100644 --- a/test/test_mq.rs +++ b/test/test_mq.rs @@ -1,17 +1,15 @@ -use libc::c_long; - use std::ffi::CString; use std::str; use nix::errno::Errno::*; use nix::Error::Sys; -use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive}; +use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive, mq_attr_member_t}; use nix::mqueue::{MqAttr, MQ_OFlag}; use nix::sys::stat::Mode; #[test] fn test_mq_send_and_receive() { - const MSG_SIZE: c_long = 32; + const MSG_SIZE: mq_attr_member_t = 32; let attr = MqAttr::new(0, 10, MSG_SIZE, 0); let mq_name= &CString::new(b"/a_nix_test_queue".as_ref()).unwrap(); @@ -43,7 +41,7 @@ fn test_mq_send_and_receive() { #[cfg(not(any(target_os = "netbsd")))] fn test_mq_getattr() { use nix::mqueue::mq_getattr; - const MSG_SIZE: c_long = 32; + const MSG_SIZE: mq_attr_member_t = 32; let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap(); let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; @@ -66,7 +64,7 @@ fn test_mq_getattr() { #[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)] fn test_mq_setattr() { use nix::mqueue::{mq_getattr, mq_setattr}; - const MSG_SIZE: c_long = 32; + const MSG_SIZE: mq_attr_member_t = 32; let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap(); let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; @@ -87,7 +85,7 @@ fn test_mq_setattr() { // O_NONBLOCK can be set (see tests below) assert_ne!(new_attr_get, new_attr); - let new_attr_non_blocking = MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as c_long, 10, MSG_SIZE, 0); + let new_attr_non_blocking = MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t, 10, MSG_SIZE, 0); mq_setattr(mqd, &new_attr_non_blocking).unwrap(); let new_attr_get = mq_getattr(mqd).unwrap(); @@ -103,7 +101,7 @@ fn test_mq_setattr() { #[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)] fn test_mq_set_nonblocking() { use nix::mqueue::{mq_getattr, mq_set_nonblock, mq_remove_nonblock}; - const MSG_SIZE: c_long = 32; + const MSG_SIZE: mq_attr_member_t = 32; let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap(); let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; @@ -116,7 +114,7 @@ fn test_mq_set_nonblocking() { let mqd = r.unwrap(); mq_set_nonblock(mqd).unwrap(); let new_attr = mq_getattr(mqd); - assert_eq!(new_attr.unwrap().flags(), MQ_OFlag::O_NONBLOCK.bits() as c_long); + assert_eq!(new_attr.unwrap().flags(), MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t); mq_remove_nonblock(mqd).unwrap(); let new_attr = mq_getattr(mqd); assert_eq!(new_attr.unwrap().flags(), 0); @@ -127,7 +125,7 @@ fn test_mq_set_nonblocking() { #[cfg(not(any(target_os = "netbsd")))] fn test_mq_unlink() { use nix::mqueue::mq_unlink; - const MSG_SIZE: c_long = 32; + const MSG_SIZE: mq_attr_member_t = 32; let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); let mq_name_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap(); let mq_name_not_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap(); |