diff options
Diffstat (limited to 'src')
-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 |
9 files changed, 215 insertions, 144 deletions
@@ -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) } |