summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml4
-rw-r--r--CHANGELOG.md14
-rw-r--r--Cargo.toml4
-rw-r--r--README.md1
-rw-r--r--src/dir.rs86
-rw-r--r--src/mqueue.rs21
-rw-r--r--src/pty.rs2
-rw-r--r--src/sys/signalfd.rs7
-rw-r--r--src/sys/statfs.rs175
-rw-r--r--src/sys/sysinfo.rs8
-rw-r--r--src/sys/time.rs19
-rw-r--r--src/sys/wait.rs38
-rw-r--r--src/unistd.rs3
-rw-r--r--test/sys/test_ptrace.rs10
-rw-r--r--test/test_dir.rs2
-rw-r--r--test/test_mq.rs18
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`.
diff --git a/Cargo.toml b/Cargo.toml
index 8c12b6dc..46f8cad0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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"
diff --git a/README.md b/README.md
index 177f6f2a..67e76726 100644
--- a/README.md
+++ b/README.md
@@ -83,6 +83,7 @@ Tier 2:
Tier 3:
* x86_64-fuchsia
* x86_64-unknown-redox
+ * x86_64-unknown-linux-gnux32
## Usage
diff --git a/src/dir.rs b/src/dir.rs
index 1d48f18c..7d4ab82f 100644
--- a/src/dir.rs
+++ b/src/dir.rs
@@ -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);
diff --git a/src/pty.rs b/src/pty.rs
index 3a6a9232..d67518f4 100644
--- a/src/pty.rs
+++ b/src/pty.rs
@@ -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();