From 0f13740153320e8777ba62564d17d8f56a3a3e12 Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Tue, 31 Dec 2024 12:21:16 +0900 Subject: [PATCH 01/11] Add libc dependency to yash-env As the first step to remove the nix crate dependency from yash-env, this commit adds the libc crate as a direct dependency to yash-env. Previously, we used the libc crate through the nix crate, but now we use it directly. --- Cargo.lock | 5 +- yash-env/CHANGELOG.md | 2 + yash-env/Cargo.toml | 1 + yash-env/src/job.rs | 5 +- yash-env/src/system/errno.rs | 162 ++++++++++---------- yash-env/src/system/file_system.rs | 6 +- yash-env/src/system/id.rs | 10 +- yash-env/src/system/real.rs | 192 ++++++++++++------------ yash-env/src/system/real/file_system.rs | 18 +-- yash-env/src/system/real/open_flag.rs | 34 ++--- yash-env/src/system/real/resource.rs | 38 ++--- yash-env/src/system/real/signal.rs | 172 ++++++++++----------- yash-env/src/system/resource.rs | 4 +- 13 files changed, 317 insertions(+), 332 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41751df8..aebecf26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,9 +227,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.167" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "linux-raw-sys" @@ -579,6 +579,7 @@ dependencies = [ "futures-executor", "futures-util", "itertools", + "libc", "nix", "slab", "strum", diff --git a/yash-env/CHANGELOG.md b/yash-env/CHANGELOG.md index 5817f677..89efc4fc 100644 --- a/yash-env/CHANGELOG.md +++ b/yash-env/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The `builtin::Builtin` struct now has the `is_declaration_utility` field. - The `builtin::Builtin` struct now can be constructed with the associated function `new`. +- Internal dependencies: + - libc 0.2.169 ### Changed diff --git a/yash-env/Cargo.toml b/yash-env/Cargo.toml index 768e7ee3..1b18a503 100644 --- a/yash-env/Cargo.toml +++ b/yash-env/Cargo.toml @@ -33,6 +33,7 @@ yash-syntax = { path = "../yash-syntax", version = "0.14.0", features = [ ] } [target.'cfg(unix)'.dependencies] +libc = { version = "0.2.169", default-features = false } nix = { version = "0.29.0", features = ["fs", "signal", "user"] } yash-executor = { path = "../yash-executor", version = "1.0.0" } diff --git a/yash-env/src/job.rs b/yash-env/src/job.rs index ee2d5917..f50242fc 100644 --- a/yash-env/src/job.rs +++ b/yash-env/src/job.rs @@ -50,7 +50,7 @@ use std::ops::Deref; use thiserror::Error; #[cfg(unix)] -type RawPidDef = nix::libc::pid_t; +type RawPidDef = libc::pid_t; #[cfg(not(unix))] type RawPidDef = i32; @@ -63,8 +63,6 @@ type RawPidDef = i32; /// /// Process IDs are usually wrapped in the [`Pid`] type for better type safety, /// so this type is not used directly in most cases. -/// -/// [`libc`]: nix::libc pub type RawPid = RawPidDef; /// Process ID @@ -82,7 +80,6 @@ pub type RawPid = RawPidDef; /// /// This type may also be used to represent process group IDs, session IDs, etc. /// -/// [`libc`]: nix::libc /// [`kill`]: crate::system::System::kill /// [`wait`]: crate::system::System::wait /// [`setpgid`]: crate::system::System::setpgid diff --git a/yash-env/src/system/errno.rs b/yash-env/src/system/errno.rs index f0e556ad..1188e065 100644 --- a/yash-env/src/system/errno.rs +++ b/yash-env/src/system/errno.rs @@ -50,167 +50,167 @@ impl Errno { #[cfg(unix)] impl Errno { /// Argument list too long - pub const E2BIG: Self = Self(nix::libc::E2BIG as _); + pub const E2BIG: Self = Self(libc::E2BIG as _); /// Permission denied - pub const EACCES: Self = Self(nix::libc::EACCES as _); + pub const EACCES: Self = Self(libc::EACCES as _); /// Address in use. - pub const EADDRINUSE: Self = Self(nix::libc::EADDRINUSE as _); + pub const EADDRINUSE: Self = Self(libc::EADDRINUSE as _); /// Address not available - pub const EADDRNOTAVAIL: Self = Self(nix::libc::EADDRNOTAVAIL as _); + pub const EADDRNOTAVAIL: Self = Self(libc::EADDRNOTAVAIL as _); /// Address family not supported - pub const EAFNOSUPPORT: Self = Self(nix::libc::EAFNOSUPPORT as _); + pub const EAFNOSUPPORT: Self = Self(libc::EAFNOSUPPORT as _); /// Resource unavailable, try again (may be the same value as [`EWOULDBLOCK`](Self::EWOULDBLOCK)) - pub const EAGAIN: Self = Self(nix::libc::EAGAIN as _); + pub const EAGAIN: Self = Self(libc::EAGAIN as _); /// Connection already in progress - pub const EALREADY: Self = Self(nix::libc::EALREADY as _); + pub const EALREADY: Self = Self(libc::EALREADY as _); /// Bad file descriptor - pub const EBADF: Self = Self(nix::libc::EBADF as _); + pub const EBADF: Self = Self(libc::EBADF as _); /// Bad message - pub const EBADMSG: Self = Self(nix::libc::EBADMSG as _); + pub const EBADMSG: Self = Self(libc::EBADMSG as _); /// Device or resource busy - pub const EBUSY: Self = Self(nix::libc::EBUSY as _); + pub const EBUSY: Self = Self(libc::EBUSY as _); /// Operation canceled - pub const ECANCELED: Self = Self(nix::libc::ECANCELED as _); + pub const ECANCELED: Self = Self(libc::ECANCELED as _); /// No child processes - pub const ECHILD: Self = Self(nix::libc::ECHILD as _); + pub const ECHILD: Self = Self(libc::ECHILD as _); /// Connection aborted - pub const ECONNABORTED: Self = Self(nix::libc::ECONNABORTED as _); + pub const ECONNABORTED: Self = Self(libc::ECONNABORTED as _); /// Connection refused - pub const ECONNREFUSED: Self = Self(nix::libc::ECONNREFUSED as _); + pub const ECONNREFUSED: Self = Self(libc::ECONNREFUSED as _); /// Connection reset - pub const ECONNRESET: Self = Self(nix::libc::ECONNRESET as _); + pub const ECONNRESET: Self = Self(libc::ECONNRESET as _); /// Resource deadlock would occur - pub const EDEADLK: Self = Self(nix::libc::EDEADLK as _); + pub const EDEADLK: Self = Self(libc::EDEADLK as _); /// Destination address required - pub const EDESTADDRREQ: Self = Self(nix::libc::EDESTADDRREQ as _); + pub const EDESTADDRREQ: Self = Self(libc::EDESTADDRREQ as _); /// Mathematics argument out of domain of function - pub const EDOM: Self = Self(nix::libc::EDOM as _); + pub const EDOM: Self = Self(libc::EDOM as _); /// Reserved - pub const EDQUOT: Self = Self(nix::libc::EDQUOT as _); + pub const EDQUOT: Self = Self(libc::EDQUOT as _); /// File exists - pub const EEXIST: Self = Self(nix::libc::EEXIST as _); + pub const EEXIST: Self = Self(libc::EEXIST as _); /// Bad address - pub const EFAULT: Self = Self(nix::libc::EFAULT as _); + pub const EFAULT: Self = Self(libc::EFAULT as _); /// File too large - pub const EFBIG: Self = Self(nix::libc::EFBIG as _); + pub const EFBIG: Self = Self(libc::EFBIG as _); /// Host is unreachable - pub const EHOSTUNREACH: Self = Self(nix::libc::EHOSTUNREACH as _); + pub const EHOSTUNREACH: Self = Self(libc::EHOSTUNREACH as _); /// Identifier removed - pub const EIDRM: Self = Self(nix::libc::EIDRM as _); + pub const EIDRM: Self = Self(libc::EIDRM as _); /// Illegal byte sequence - pub const EILSEQ: Self = Self(nix::libc::EILSEQ as _); + pub const EILSEQ: Self = Self(libc::EILSEQ as _); /// Operation in progress - pub const EINPROGRESS: Self = Self(nix::libc::EINPROGRESS as _); + pub const EINPROGRESS: Self = Self(libc::EINPROGRESS as _); /// Interrupted function - pub const EINTR: Self = Self(nix::libc::EINTR as _); + pub const EINTR: Self = Self(libc::EINTR as _); /// Invalid argument - pub const EINVAL: Self = Self(nix::libc::EINVAL as _); + pub const EINVAL: Self = Self(libc::EINVAL as _); /// I/O error - pub const EIO: Self = Self(nix::libc::EIO as _); + pub const EIO: Self = Self(libc::EIO as _); /// Socket is connected - pub const EISCONN: Self = Self(nix::libc::EISCONN as _); + pub const EISCONN: Self = Self(libc::EISCONN as _); /// Is a directory - pub const EISDIR: Self = Self(nix::libc::EISDIR as _); + pub const EISDIR: Self = Self(libc::EISDIR as _); /// Too many levels of symbolic links - pub const ELOOP: Self = Self(nix::libc::ELOOP as _); + pub const ELOOP: Self = Self(libc::ELOOP as _); /// File descriptor value too large - pub const EMFILE: Self = Self(nix::libc::EMFILE as _); + pub const EMFILE: Self = Self(libc::EMFILE as _); /// Too many links - pub const EMLINK: Self = Self(nix::libc::EMLINK as _); + pub const EMLINK: Self = Self(libc::EMLINK as _); /// Message too large - pub const EMSGSIZE: Self = Self(nix::libc::EMSGSIZE as _); + pub const EMSGSIZE: Self = Self(libc::EMSGSIZE as _); // Not supported on every platform /// Reserved - // pub const EMULTIHOP: Self = Self(nix::libc::EMULTIHOP as _); + // pub const EMULTIHOP: Self = Self(libc::EMULTIHOP as _); /// Filename too long - pub const ENAMETOOLONG: Self = Self(nix::libc::ENAMETOOLONG as _); + pub const ENAMETOOLONG: Self = Self(libc::ENAMETOOLONG as _); /// Network is down - pub const ENETDOWN: Self = Self(nix::libc::ENETDOWN as _); + pub const ENETDOWN: Self = Self(libc::ENETDOWN as _); /// Connection aborted by network - pub const ENETRESET: Self = Self(nix::libc::ENETRESET as _); + pub const ENETRESET: Self = Self(libc::ENETRESET as _); /// Network unreachable - pub const ENETUNREACH: Self = Self(nix::libc::ENETUNREACH as _); + pub const ENETUNREACH: Self = Self(libc::ENETUNREACH as _); /// Too many files open in system - pub const ENFILE: Self = Self(nix::libc::ENFILE as _); + pub const ENFILE: Self = Self(libc::ENFILE as _); /// No buffer space available - pub const ENOBUFS: Self = Self(nix::libc::ENOBUFS as _); + pub const ENOBUFS: Self = Self(libc::ENOBUFS as _); // Not supported on every platform /// No message is available on the STREAM head read queue - // pub const ENODATA: Self = Self(nix::libc::ENODATA as _); + // pub const ENODATA: Self = Self(libc::ENODATA as _); /// No such device - pub const ENODEV: Self = Self(nix::libc::ENODEV as _); + pub const ENODEV: Self = Self(libc::ENODEV as _); /// No such file or directory - pub const ENOENT: Self = Self(nix::libc::ENOENT as _); + pub const ENOENT: Self = Self(libc::ENOENT as _); /// Executable file format error - pub const ENOEXEC: Self = Self(nix::libc::ENOEXEC as _); + pub const ENOEXEC: Self = Self(libc::ENOEXEC as _); /// No locks available - pub const ENOLCK: Self = Self(nix::libc::ENOLCK as _); + pub const ENOLCK: Self = Self(libc::ENOLCK as _); // Not supported on every platform /// Reserved - // pub const ENOLINK: Self = Self(nix::libc::ENOLINK as _); + // pub const ENOLINK: Self = Self(libc::ENOLINK as _); /// Not enough space - pub const ENOMEM: Self = Self(nix::libc::ENOMEM as _); + pub const ENOMEM: Self = Self(libc::ENOMEM as _); /// No message of the desired type - pub const ENOMSG: Self = Self(nix::libc::ENOMSG as _); + pub const ENOMSG: Self = Self(libc::ENOMSG as _); /// Protocol not available - pub const ENOPROTOOPT: Self = Self(nix::libc::ENOPROTOOPT as _); + pub const ENOPROTOOPT: Self = Self(libc::ENOPROTOOPT as _); /// No space left on device - pub const ENOSPC: Self = Self(nix::libc::ENOSPC as _); + pub const ENOSPC: Self = Self(libc::ENOSPC as _); // Obsolete: Not supported /// No STREAM resources - // pub const ENOSR: Self = Self(nix::libc::ENOSR as _); + // pub const ENOSR: Self = Self(libc::ENOSR as _); // Obsolete: Not supported /// Not a STREAM - // pub const ENOSTR: Self = Self(nix::libc::ENOSTR as _); + // pub const ENOSTR: Self = Self(libc::ENOSTR as _); /// Functionality not supported - pub const ENOSYS: Self = Self(nix::libc::ENOSYS as _); + pub const ENOSYS: Self = Self(libc::ENOSYS as _); /// The socket is not connected - pub const ENOTCONN: Self = Self(nix::libc::ENOTCONN as _); + pub const ENOTCONN: Self = Self(libc::ENOTCONN as _); /// Not a directory or a symbolic link to a directory - pub const ENOTDIR: Self = Self(nix::libc::ENOTDIR as _); + pub const ENOTDIR: Self = Self(libc::ENOTDIR as _); /// Directory not empty - pub const ENOTEMPTY: Self = Self(nix::libc::ENOTEMPTY as _); + pub const ENOTEMPTY: Self = Self(libc::ENOTEMPTY as _); // Not supported on every platform /// State not recoverable - // pub const ENOTRECOVERABLE: Self = Self(nix::libc::ENOTRECOVERABLE as _); + // pub const ENOTRECOVERABLE: Self = Self(libc::ENOTRECOVERABLE as _); /// Not a socket - pub const ENOTSOCK: Self = Self(nix::libc::ENOTSOCK as _); + pub const ENOTSOCK: Self = Self(libc::ENOTSOCK as _); /// Not supported (may be the same value as [`EOPNOTSUPP`](Self::EOPNOTSUPP)) - pub const ENOTSUP: Self = Self(nix::libc::ENOTSUP as _); + pub const ENOTSUP: Self = Self(libc::ENOTSUP as _); /// Inappropriate I/O control operation - pub const ENOTTY: Self = Self(nix::libc::ENOTTY as _); + pub const ENOTTY: Self = Self(libc::ENOTTY as _); /// No such device or address - pub const ENXIO: Self = Self(nix::libc::ENXIO as _); + pub const ENXIO: Self = Self(libc::ENXIO as _); /// Operation not supported on socket (may be the same value as [`ENOTSUP`](Self::ENOTSUP)) - pub const EOPNOTSUPP: Self = Self(nix::libc::EOPNOTSUPP as _); + pub const EOPNOTSUPP: Self = Self(libc::EOPNOTSUPP as _); /// Value too large to be stored in data type - pub const EOVERFLOW: Self = Self(nix::libc::EOVERFLOW as _); + pub const EOVERFLOW: Self = Self(libc::EOVERFLOW as _); // Not supported on every platform /// Previous owner died - // pub const EOWNERDEAD: Self = Self(nix::libc::EOWNERDEAD as _); + // pub const EOWNERDEAD: Self = Self(libc::EOWNERDEAD as _); /// Operation not permitted - pub const EPERM: Self = Self(nix::libc::EPERM as _); + pub const EPERM: Self = Self(libc::EPERM as _); /// Broken pipe - pub const EPIPE: Self = Self(nix::libc::EPIPE as _); + pub const EPIPE: Self = Self(libc::EPIPE as _); /// Protocol error - pub const EPROTO: Self = Self(nix::libc::EPROTO as _); + pub const EPROTO: Self = Self(libc::EPROTO as _); /// Protocol not supported - pub const EPROTONOSUPPORT: Self = Self(nix::libc::EPROTONOSUPPORT as _); + pub const EPROTONOSUPPORT: Self = Self(libc::EPROTONOSUPPORT as _); /// Protocol wrong type for socket - pub const EPROTOTYPE: Self = Self(nix::libc::EPROTOTYPE as _); + pub const EPROTOTYPE: Self = Self(libc::EPROTOTYPE as _); /// Result too large - pub const ERANGE: Self = Self(nix::libc::ERANGE as _); + pub const ERANGE: Self = Self(libc::ERANGE as _); /// Read-only file system - pub const EROFS: Self = Self(nix::libc::EROFS as _); + pub const EROFS: Self = Self(libc::EROFS as _); /// Invalid seek - pub const ESPIPE: Self = Self(nix::libc::ESPIPE as _); + pub const ESPIPE: Self = Self(libc::ESPIPE as _); /// No such process - pub const ESRCH: Self = Self(nix::libc::ESRCH as _); + pub const ESRCH: Self = Self(libc::ESRCH as _); /// Reserved - pub const ESTALE: Self = Self(nix::libc::ESTALE as _); + pub const ESTALE: Self = Self(libc::ESTALE as _); // Obsolete: Not supported /// Stream ioctl() timeout - // pub const ETIME: Self = Self(nix::libc::ETIME as _); + // pub const ETIME: Self = Self(libc::ETIME as _); /// Connection timed out - pub const ETIMEDOUT: Self = Self(nix::libc::ETIMEDOUT as _); + pub const ETIMEDOUT: Self = Self(libc::ETIMEDOUT as _); /// Text file busy - pub const ETXTBSY: Self = Self(nix::libc::ETXTBSY as _); + pub const ETXTBSY: Self = Self(libc::ETXTBSY as _); /// Operation would block (may be the same value as [`EAGAIN`](Self::EAGAIN)) - pub const EWOULDBLOCK: Self = Self(nix::libc::EWOULDBLOCK as _); + pub const EWOULDBLOCK: Self = Self(libc::EWOULDBLOCK as _); /// Cross-device link - pub const EXDEV: Self = Self(nix::libc::EXDEV as _); + pub const EXDEV: Self = Self(libc::EXDEV as _); } #[doc = include_str!("errno.md")] diff --git a/yash-env/src/system/file_system.rs b/yash-env/src/system/file_system.rs index 6a9d62ab..029d1a25 100644 --- a/yash-env/src/system/file_system.rs +++ b/yash-env/src/system/file_system.rs @@ -23,7 +23,7 @@ use std::fmt::Debug; use yash_syntax::syntax::Fd; #[cfg(unix)] -const RAW_AT_FDCWD: i32 = nix::libc::AT_FDCWD; +const RAW_AT_FDCWD: i32 = libc::AT_FDCWD; #[cfg(not(unix))] const RAW_AT_FDCWD: i32 = -100; @@ -54,7 +54,7 @@ pub trait Dir: Debug { } #[cfg(unix)] -type RawModeDef = nix::libc::mode_t; +type RawModeDef = libc::mode_t; #[cfg(not(unix))] type RawModeDef = u32; @@ -67,8 +67,6 @@ type RawModeDef = u32; /// /// File permission bits are usually wrapped in the [`Mode`] type for better type /// safety, so this type is not used directly in most cases. -/// -/// [`libc`]: nix::libc pub type RawMode = RawModeDef; /// File permission bits diff --git a/yash-env/src/system/id.rs b/yash-env/src/system/id.rs index fc520849..def86ef4 100644 --- a/yash-env/src/system/id.rs +++ b/yash-env/src/system/id.rs @@ -17,7 +17,7 @@ //! Definitions of ID types #[cfg(unix)] -type RawUidDef = nix::libc::uid_t; +type RawUidDef = libc::uid_t; #[cfg(not(unix))] type RawUidDef = u32; @@ -30,8 +30,6 @@ type RawUidDef = u32; /// /// User IDs are usually wrapped in the [`Uid`] type for better type safety, so /// this type is not used directly in most cases. -/// -/// [`libc`]: nix::libc pub type RawUid = RawUidDef; /// User ID @@ -39,14 +37,12 @@ pub type RawUid = RawUidDef; /// This type implements the new type pattern for the raw user ID type /// [`RawUid`]. The advantage of using this type is that it is more type-safe /// than using the raw integer value directly. -/// -/// [`libc`]: nix::libc #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] #[repr(transparent)] pub struct Uid(pub RawUid); #[cfg(unix)] -type RawGidDef = nix::libc::gid_t; +type RawGidDef = libc::gid_t; #[cfg(not(unix))] type RawGidDef = u32; @@ -59,8 +55,6 @@ type RawGidDef = u32; /// /// Group IDs are usually wrapped in the [`Gid`] type for better type safety, so /// this type is not used directly in most cases. -/// -/// [`libc`]: nix::libc pub type RawGid = RawGidDef; /// Group ID diff --git a/yash-env/src/system/real.rs b/yash-env/src/system/real.rs index 7b5ad39b..7aba9bbb 100644 --- a/yash-env/src/system/real.rs +++ b/yash-env/src/system/real.rs @@ -56,10 +56,10 @@ use crate::path::PathBuf; use crate::str::UnixStr; use crate::str::UnixString; use enumset::EnumSet; +use libc::DIR; +use libc::{S_IFDIR, S_IFMT, S_IFREG}; use nix::errno::Errno as NixErrno; use nix::fcntl::AtFlags; -use nix::libc::DIR; -use nix::libc::{S_IFDIR, S_IFMT, S_IFREG}; use nix::sys::stat::stat; use nix::unistd::AccessFlags; use std::convert::Infallible; @@ -153,12 +153,9 @@ fn is_directory(path: &CStr) -> bool { /// The return value is a `MaybeUninit` because the `timespec` struct may have /// padding or extension fields that are not initialized by this function. #[must_use] -fn to_timespec(duration: Duration) -> MaybeUninit { - let seconds = duration - .as_secs() - .try_into() - .unwrap_or(nix::libc::time_t::MAX); - let mut timespec = MaybeUninit::::uninit(); +fn to_timespec(duration: Duration) -> MaybeUninit { + let seconds = duration.as_secs().try_into().unwrap_or(libc::time_t::MAX); + let mut timespec = MaybeUninit::::uninit(); unsafe { (&raw mut (*timespec.as_mut_ptr()).tv_sec).write(seconds); (&raw mut (*timespec.as_mut_ptr()).tv_nsec).write(duration.subsec_nanos() as _); @@ -221,8 +218,8 @@ impl RealSystem { impl System for RealSystem { fn fstat(&self, fd: Fd) -> Result { - let mut stat = MaybeUninit::::uninit(); - unsafe { nix::libc::fstat(fd.0, stat.as_mut_ptr()) }.errno_if_m1()?; + let mut stat = MaybeUninit::::uninit(); + unsafe { libc::fstat(fd.0, stat.as_mut_ptr()) }.errno_if_m1()?; Ok(Stat::from_raw(&stat)) } @@ -230,11 +227,11 @@ impl System for RealSystem { let flags = if follow_symlinks { 0 } else { - nix::libc::AT_SYMLINK_NOFOLLOW + libc::AT_SYMLINK_NOFOLLOW }; - let mut stat = MaybeUninit::::uninit(); - unsafe { nix::libc::fstatat(dir_fd.0, path.as_ptr(), stat.as_mut_ptr(), flags) } + let mut stat = MaybeUninit::::uninit(); + unsafe { libc::fstatat(dir_fd.0, path.as_ptr(), stat.as_mut_ptr(), flags) } .errno_if_m1()?; Ok(Stat::from_raw(&stat)) } @@ -250,27 +247,25 @@ impl System for RealSystem { fn pipe(&mut self) -> Result<(Fd, Fd)> { let mut fds = MaybeUninit::<[c_int; 2]>::uninit(); // TODO Use as_mut_ptr rather than cast when array_ptr_get is stabilized - unsafe { nix::libc::pipe(fds.as_mut_ptr().cast()) }.errno_if_m1()?; + unsafe { libc::pipe(fds.as_mut_ptr().cast()) }.errno_if_m1()?; let fds = unsafe { fds.assume_init() }; Ok((Fd(fds[0]), Fd(fds[1]))) } fn dup(&mut self, from: Fd, to_min: Fd, flags: EnumSet) -> Result { let command = if flags.contains(FdFlag::CloseOnExec) { - nix::libc::F_DUPFD_CLOEXEC + libc::F_DUPFD_CLOEXEC } else { - nix::libc::F_DUPFD + libc::F_DUPFD }; - unsafe { nix::libc::fcntl(from.0, command, to_min.0) } + unsafe { libc::fcntl(from.0, command, to_min.0) } .errno_if_m1() .map(Fd) } fn dup2(&mut self, from: Fd, to: Fd) -> Result { loop { - let result = unsafe { nix::libc::dup2(from.0, to.0) } - .errno_if_m1() - .map(Fd); + let result = unsafe { libc::dup2(from.0, to.0) }.errno_if_m1().map(Fd); if result != Err(Errno::EINTR) { return result; } @@ -294,7 +289,7 @@ impl System for RealSystem { #[cfg(target_os = "redox")] let mode_bits = mode.bits() as c_int; - unsafe { nix::libc::open(path.as_ptr(), raw_flags, mode_bits) } + unsafe { libc::open(path.as_ptr(), raw_flags, mode_bits) } .errno_if_m1() .map(Fd) } @@ -313,7 +308,7 @@ impl System for RealSystem { fn close(&mut self, fd: Fd) -> Result<()> { loop { - let result = unsafe { nix::libc::close(fd.0) }.errno_if_m1().map(drop); + let result = unsafe { libc::close(fd.0) }.errno_if_m1().map(drop); match result { Err(Errno::EBADF) => return Ok(()), Err(Errno::EINTR) => continue, @@ -323,28 +318,28 @@ impl System for RealSystem { } fn ofd_access(&self, fd: Fd) -> Result { - let flags = unsafe { nix::libc::fcntl(fd.0, nix::libc::F_GETFL) }.errno_if_m1()?; + let flags = unsafe { libc::fcntl(fd.0, libc::F_GETFL) }.errno_if_m1()?; Ok(OfdAccess::from_real_flags(flags)) } fn get_and_set_nonblocking(&mut self, fd: Fd, nonblocking: bool) -> Result { - let old_flags = unsafe { nix::libc::fcntl(fd.0, nix::libc::F_GETFL) }.errno_if_m1()?; + let old_flags = unsafe { libc::fcntl(fd.0, libc::F_GETFL) }.errno_if_m1()?; let new_flags = if nonblocking { - old_flags | nix::libc::O_NONBLOCK + old_flags | libc::O_NONBLOCK } else { - old_flags & !nix::libc::O_NONBLOCK + old_flags & !libc::O_NONBLOCK }; if new_flags != old_flags { - unsafe { nix::libc::fcntl(fd.0, nix::libc::F_SETFL, new_flags) }.errno_if_m1()?; + unsafe { libc::fcntl(fd.0, libc::F_SETFL, new_flags) }.errno_if_m1()?; } - let was_nonblocking = old_flags & nix::libc::O_NONBLOCK != 0; + let was_nonblocking = old_flags & libc::O_NONBLOCK != 0; Ok(was_nonblocking) } fn fcntl_getfd(&self, fd: Fd) -> Result> { - let bits = unsafe { nix::libc::fcntl(fd.0, nix::libc::F_GETFD) }.errno_if_m1()?; + let bits = unsafe { libc::fcntl(fd.0, libc::F_GETFD) }.errno_if_m1()?; let mut flags = EnumSet::empty(); - if bits & nix::libc::FD_CLOEXEC != 0 { + if bits & libc::FD_CLOEXEC != 0 { flags.insert(FdFlag::CloseOnExec); } Ok(flags) @@ -353,21 +348,21 @@ impl System for RealSystem { fn fcntl_setfd(&mut self, fd: Fd, flags: EnumSet) -> Result<()> { let mut bits = 0 as c_int; if flags.contains(FdFlag::CloseOnExec) { - bits |= nix::libc::FD_CLOEXEC; + bits |= libc::FD_CLOEXEC; } - unsafe { nix::libc::fcntl(fd.0, nix::libc::F_SETFD, bits) } + unsafe { libc::fcntl(fd.0, libc::F_SETFD, bits) } .errno_if_m1() .map(drop) } fn isatty(&self, fd: Fd) -> bool { - (unsafe { nix::libc::isatty(fd.0) } != 0) + (unsafe { libc::isatty(fd.0) } != 0) } fn read(&mut self, fd: Fd, buffer: &mut [u8]) -> Result { loop { - let result = unsafe { nix::libc::read(fd.0, buffer.as_mut_ptr().cast(), buffer.len()) } - .errno_if_m1(); + let result = + unsafe { libc::read(fd.0, buffer.as_mut_ptr().cast(), buffer.len()) }.errno_if_m1(); if result != Err(Errno::EINTR) { return Ok(result?.try_into().unwrap()); } @@ -376,8 +371,8 @@ impl System for RealSystem { fn write(&mut self, fd: Fd, buffer: &[u8]) -> Result { loop { - let result = unsafe { nix::libc::write(fd.0, buffer.as_ptr().cast(), buffer.len()) } - .errno_if_m1(); + let result = + unsafe { libc::write(fd.0, buffer.as_ptr().cast(), buffer.len()) }.errno_if_m1(); if result != Err(Errno::EINTR) { return Ok(result?.try_into().unwrap()); } @@ -388,29 +383,29 @@ impl System for RealSystem { let (offset, whence) = match position { SeekFrom::Start(offset) => { let offset = offset.try_into().map_err(|_| Errno::EOVERFLOW)?; - (offset, nix::libc::SEEK_SET) + (offset, libc::SEEK_SET) } - SeekFrom::End(offset) => (offset, nix::libc::SEEK_END), - SeekFrom::Current(offset) => (offset, nix::libc::SEEK_CUR), + SeekFrom::End(offset) => (offset, libc::SEEK_END), + SeekFrom::Current(offset) => (offset, libc::SEEK_CUR), }; - let new_offset = unsafe { nix::libc::lseek(fd.0, offset, whence) }.errno_if_m1()?; + let new_offset = unsafe { libc::lseek(fd.0, offset, whence) }.errno_if_m1()?; Ok(new_offset.try_into().unwrap()) } fn fdopendir(&mut self, fd: Fd) -> Result> { - let dir = unsafe { nix::libc::fdopendir(fd.0) }; + let dir = unsafe { libc::fdopendir(fd.0) }; let dir = NonNull::new(dir).ok_or_else(NixErrno::last)?; Ok(Box::new(RealDir(dir))) } fn opendir(&mut self, path: &CStr) -> Result> { - let dir = unsafe { nix::libc::opendir(path.as_ptr()) }; + let dir = unsafe { libc::opendir(path.as_ptr()) }; let dir = NonNull::new(dir).ok_or_else(NixErrno::last)?; Ok(Box::new(RealDir(dir))) } fn umask(&mut self, new_mask: Mode) -> Mode { - Mode::from_bits_retain(unsafe { nix::libc::umask(new_mask.bits()) }) + Mode::from_bits_retain(unsafe { libc::umask(new_mask.bits()) }) } fn now(&self) -> Instant { @@ -418,13 +413,13 @@ impl System for RealSystem { } fn times(&self) -> Result { - let mut tms = MaybeUninit::::uninit(); - let raw_result = unsafe { nix::libc::times(tms.as_mut_ptr()) }; + let mut tms = MaybeUninit::::uninit(); + let raw_result = unsafe { libc::times(tms.as_mut_ptr()) }; if raw_result == (-1) as _ { return Err(Errno::last()); } - let ticks_per_second = unsafe { nix::libc::sysconf(nix::libc::_SC_CLK_TCK) }; + let ticks_per_second = unsafe { libc::sysconf(libc::_SC_CLK_TCK) }; if ticks_per_second <= 0 { return Err(Errno::last()); } @@ -463,19 +458,18 @@ impl System for RealSystem { ) -> Result<()> { unsafe { let (how, raw_mask) = match op { - None => (nix::libc::SIG_BLOCK, None), + None => (libc::SIG_BLOCK, None), Some((op, mask)) => { let how = match op { - SigmaskOp::Add => nix::libc::SIG_BLOCK, - SigmaskOp::Remove => nix::libc::SIG_UNBLOCK, - SigmaskOp::Set => nix::libc::SIG_SETMASK, + SigmaskOp::Add => libc::SIG_BLOCK, + SigmaskOp::Remove => libc::SIG_UNBLOCK, + SigmaskOp::Set => libc::SIG_SETMASK, }; - let mut raw_mask = MaybeUninit::::uninit(); - nix::libc::sigemptyset(raw_mask.as_mut_ptr()).errno_if_m1()?; + let mut raw_mask = MaybeUninit::::uninit(); + libc::sigemptyset(raw_mask.as_mut_ptr()).errno_if_m1()?; for &signal in mask { - nix::libc::sigaddset(raw_mask.as_mut_ptr(), signal.as_raw()) - .errno_if_m1()?; + libc::sigaddset(raw_mask.as_mut_ptr(), signal.as_raw()).errno_if_m1()?; } (how, Some(raw_mask)) @@ -484,9 +478,9 @@ impl System for RealSystem { let mut old_mask_pair = match old_mask { None => None, Some(old_mask) => { - let mut raw_old_mask = MaybeUninit::::uninit(); + let mut raw_old_mask = MaybeUninit::::uninit(); // POSIX requires *all* sigset_t objects to be initialized before use. - nix::libc::sigemptyset(raw_old_mask.as_mut_ptr()).errno_if_m1()?; + libc::sigemptyset(raw_old_mask.as_mut_ptr()).errno_if_m1()?; Some((old_mask, raw_old_mask)) } }; @@ -499,7 +493,7 @@ impl System for RealSystem { .map_or(std::ptr::null_mut(), |(_, raw_old_mask)| { raw_old_mask.as_mut_ptr() }); - let result = nix::libc::sigprocmask(how, raw_set_ptr, raw_old_set_ptr); + let result = libc::sigprocmask(how, raw_set_ptr, raw_old_set_ptr); result.errno_if_m1().map(drop)?; if let Some((old_mask, raw_old_mask)) = old_mask_pair { @@ -515,12 +509,12 @@ impl System for RealSystem { unsafe { let new_action = handling.to_sigaction(); - let mut old_action = MaybeUninit::::uninit(); + let mut old_action = MaybeUninit::::uninit(); let old_mask_ptr = &raw mut (*old_action.as_mut_ptr()).sa_mask; // POSIX requires *all* sigset_t objects to be initialized before use. - nix::libc::sigemptyset(old_mask_ptr).errno_if_m1()?; + libc::sigemptyset(old_mask_ptr).errno_if_m1()?; - nix::libc::sigaction( + libc::sigaction( signal.as_raw(), new_action.as_ptr(), old_action.as_mut_ptr(), @@ -561,7 +555,7 @@ impl System for RealSystem { ) -> Pin>)>> { Box::pin(async move { let raw = signal.map_or(0, signal::Number::as_raw); - unsafe { nix::libc::kill(target.0, raw) }.errno_if_m1()?; + unsafe { libc::kill(target.0, raw) }.errno_if_m1()?; Ok(()) }) } @@ -581,12 +575,12 @@ impl System for RealSystem { .transpose()? .unwrap_or(0); - fn to_raw_fd_set(fds: &[Fd]) -> MaybeUninit { - let mut raw_fds = MaybeUninit::::uninit(); + fn to_raw_fd_set(fds: &[Fd]) -> MaybeUninit { + let mut raw_fds = MaybeUninit::::uninit(); unsafe { - nix::libc::FD_ZERO(raw_fds.as_mut_ptr()); + libc::FD_ZERO(raw_fds.as_mut_ptr()); for fd in fds { - nix::libc::FD_SET(fd.0, raw_fds.as_mut_ptr()); + libc::FD_SET(fd.0, raw_fds.as_mut_ptr()); } } raw_fds @@ -604,13 +598,13 @@ impl System for RealSystem { null() }; - let mut raw_mask = MaybeUninit::::uninit(); + let mut raw_mask = MaybeUninit::::uninit(); let raw_mask_ptr = match signal_mask { None => null(), Some(signal_mask) => { - unsafe { nix::libc::sigemptyset(raw_mask.as_mut_ptr()) }.errno_if_m1()?; + unsafe { libc::sigemptyset(raw_mask.as_mut_ptr()) }.errno_if_m1()?; for &signal in signal_mask { - unsafe { nix::libc::sigaddset(raw_mask.as_mut_ptr(), signal.as_raw()) } + unsafe { libc::sigaddset(raw_mask.as_mut_ptr(), signal.as_raw()) } .errno_if_m1()?; } raw_mask.as_ptr() @@ -618,7 +612,7 @@ impl System for RealSystem { }; let count = unsafe { - nix::libc::pselect( + libc::pselect( nfds, readers_ptr, writers_ptr, @@ -629,35 +623,35 @@ impl System for RealSystem { } .errno_if_m1()?; - readers.retain(|fd| unsafe { nix::libc::FD_ISSET(fd.0, readers_ptr) }); - writers.retain(|fd| unsafe { nix::libc::FD_ISSET(fd.0, writers_ptr) }); + readers.retain(|fd| unsafe { libc::FD_ISSET(fd.0, readers_ptr) }); + writers.retain(|fd| unsafe { libc::FD_ISSET(fd.0, writers_ptr) }); Ok(count) } fn getpid(&self) -> Pid { - Pid(unsafe { nix::libc::getpid() }) + Pid(unsafe { libc::getpid() }) } fn getppid(&self) -> Pid { - Pid(unsafe { nix::libc::getppid() }) + Pid(unsafe { libc::getppid() }) } fn getpgrp(&self) -> Pid { - Pid(unsafe { nix::libc::getpgrp() }) + Pid(unsafe { libc::getpgrp() }) } fn setpgid(&mut self, pid: Pid, pgid: Pid) -> Result<()> { - let result = unsafe { nix::libc::setpgid(pid.0, pgid.0) }; + let result = unsafe { libc::setpgid(pid.0, pgid.0) }; result.errno_if_m1().map(drop) } fn tcgetpgrp(&self, fd: Fd) -> Result { - unsafe { nix::libc::tcgetpgrp(fd.0) }.errno_if_m1().map(Pid) + unsafe { libc::tcgetpgrp(fd.0) }.errno_if_m1().map(Pid) } fn tcsetpgrp(&mut self, fd: Fd, pgid: Pid) -> Result<()> { - let result = unsafe { nix::libc::tcsetpgrp(fd.0, pgid.0) }; + let result = unsafe { libc::tcsetpgrp(fd.0, pgid.0) }; result.errno_if_m1().map(drop) } @@ -669,7 +663,7 @@ impl System for RealSystem { /// process ID. In the child, the starter runs the task and exits the /// process. fn new_child_process(&mut self) -> Result { - let raw_pid = unsafe { nix::libc::fork() }.errno_if_m1()?; + let raw_pid = unsafe { libc::fork() }.errno_if_m1()?; if raw_pid != 0 { // Parent process return Ok(Box::new(move |_env, _task| Pid(raw_pid))); @@ -747,19 +741,19 @@ impl System for RealSystem { } fn getuid(&self) -> Uid { - Uid(unsafe { nix::libc::getuid() }) + Uid(unsafe { libc::getuid() }) } fn geteuid(&self) -> Uid { - Uid(unsafe { nix::libc::geteuid() }) + Uid(unsafe { libc::geteuid() }) } fn getgid(&self) -> Gid { - Gid(unsafe { nix::libc::getgid() }) + Gid(unsafe { libc::getgid() }) } fn getegid(&self) -> Gid { - Gid(unsafe { nix::libc::getegid() }) + Gid(unsafe { libc::getegid() }) } fn getpwnam_dir(&self, name: &str) -> Result> { @@ -779,13 +773,12 @@ impl System for RealSystem { target_os = "watchos" ))] unsafe { - let size = nix::libc::confstr(nix::libc::_CS_PATH, std::ptr::null_mut(), 0); + let size = libc::confstr(libc::_CS_PATH, std::ptr::null_mut(), 0); if size == 0 { return Err(Errno::last()); } let mut buffer = Vec::::with_capacity(size); - let final_size = - nix::libc::confstr(nix::libc::_CS_PATH, buffer.as_mut_ptr() as *mut _, size); + let final_size = libc::confstr(libc::_CS_PATH, buffer.as_mut_ptr() as *mut _, size); if final_size == 0 { return Err(Errno::last()); } @@ -833,8 +826,8 @@ impl System for RealSystem { fn getrlimit(&self, resource: Resource) -> Result { let raw_resource = resource.as_raw_type().ok_or(Errno::EINVAL)?; - let mut limits = MaybeUninit::::uninit(); - unsafe { nix::libc::getrlimit(raw_resource as _, limits.as_mut_ptr()) }.errno_if_m1()?; + let mut limits = MaybeUninit::::uninit(); + unsafe { libc::getrlimit(raw_resource as _, limits.as_mut_ptr()) }.errno_if_m1()?; Ok(LimitPair { soft: unsafe { (&raw const (*limits.as_ptr()).rlim_cur).read() }, hard: unsafe { (&raw const (*limits.as_ptr()).rlim_max).read() }, @@ -844,13 +837,13 @@ impl System for RealSystem { fn setrlimit(&mut self, resource: Resource, limits: LimitPair) -> Result<()> { let raw_resource = resource.as_raw_type().ok_or(Errno::EINVAL)?; - let mut rlimit = MaybeUninit::::uninit(); + let mut rlimit = MaybeUninit::::uninit(); unsafe { (&raw mut (*rlimit.as_mut_ptr()).rlim_cur).write(limits.soft); (&raw mut (*rlimit.as_mut_ptr()).rlim_max).write(limits.hard); } - unsafe { nix::libc::setrlimit(raw_resource as _, rlimit.as_ptr()) }.errno_if_m1()?; + unsafe { libc::setrlimit(raw_resource as _, rlimit.as_ptr()) }.errno_if_m1()?; Ok(()) } } @@ -862,7 +855,7 @@ struct RealDir(NonNull); impl Drop for RealDir { fn drop(&mut self) { unsafe { - nix::libc::closedir(self.0.as_ptr()); + libc::closedir(self.0.as_ptr()); } } } @@ -870,7 +863,7 @@ impl Drop for RealDir { impl Dir for RealDir { fn next(&mut self) -> Result> { Errno::clear(); - let entry = unsafe { nix::libc::readdir(self.0.as_ptr()) }; + let entry = unsafe { libc::readdir(self.0.as_ptr()) }; let errno = Errno::last(); if entry.is_null() { if errno == Errno::NO_ERROR { @@ -910,17 +903,16 @@ mod tests { let result = system.caught_signals(); assert_eq!(result, []); - catch_signal(nix::libc::SIGINT); - catch_signal(nix::libc::SIGTERM); - catch_signal(nix::libc::SIGTERM); - catch_signal(nix::libc::SIGCHLD); + catch_signal(libc::SIGINT); + catch_signal(libc::SIGTERM); + catch_signal(libc::SIGTERM); + catch_signal(libc::SIGCHLD); - let sigint = - signal::Number::from_raw_unchecked(NonZeroI32::new(nix::libc::SIGINT).unwrap()); + let sigint = signal::Number::from_raw_unchecked(NonZeroI32::new(libc::SIGINT).unwrap()); let sigterm = - signal::Number::from_raw_unchecked(NonZeroI32::new(nix::libc::SIGTERM).unwrap()); + signal::Number::from_raw_unchecked(NonZeroI32::new(libc::SIGTERM).unwrap()); let sigchld = - signal::Number::from_raw_unchecked(NonZeroI32::new(nix::libc::SIGCHLD).unwrap()); + signal::Number::from_raw_unchecked(NonZeroI32::new(libc::SIGCHLD).unwrap()); let result = system.caught_signals(); assert_eq!(result, [sigint, sigterm, sigchld]); diff --git a/yash-env/src/system/real/file_system.rs b/yash-env/src/system/real/file_system.rs index f88fa42d..6bae34ef 100644 --- a/yash-env/src/system/real/file_system.rs +++ b/yash-env/src/system/real/file_system.rs @@ -22,14 +22,14 @@ use std::mem::MaybeUninit; impl FileType { #[must_use] pub(super) const fn from_raw(mode: RawMode) -> Self { - match mode & nix::libc::S_IFMT { - nix::libc::S_IFREG => Self::Regular, - nix::libc::S_IFDIR => Self::Directory, - nix::libc::S_IFLNK => Self::Symlink, - nix::libc::S_IFIFO => Self::Fifo, - nix::libc::S_IFBLK => Self::BlockDevice, - nix::libc::S_IFCHR => Self::CharacterDevice, - nix::libc::S_IFSOCK => Self::Socket, + match mode & libc::S_IFMT { + libc::S_IFREG => Self::Regular, + libc::S_IFDIR => Self::Directory, + libc::S_IFLNK => Self::Symlink, + libc::S_IFIFO => Self::Fifo, + libc::S_IFBLK => Self::BlockDevice, + libc::S_IFCHR => Self::CharacterDevice, + libc::S_IFSOCK => Self::Socket, _ => Self::Other, } } @@ -42,7 +42,7 @@ impl Stat { /// passed as `MaybeUninit` because of possible padding or extension fields /// in the structure which may not be initialized by the `stat` system call. #[must_use] - pub(super) const fn from_raw(stat: &MaybeUninit) -> Self { + pub(super) const fn from_raw(stat: &MaybeUninit) -> Self { let ptr = stat.as_ptr(); let raw_mode = unsafe { (&raw const (*ptr).st_mode).read() }; Self { diff --git a/yash-env/src/system/real/open_flag.rs b/yash-env/src/system/real/open_flag.rs index 179c8c9e..b34e36dc 100644 --- a/yash-env/src/system/real/open_flag.rs +++ b/yash-env/src/system/real/open_flag.rs @@ -23,9 +23,9 @@ impl OfdAccess { #[must_use] pub(super) fn to_real_flags(self) -> Option { match self { - Self::ReadOnly => Some(nix::libc::O_RDONLY), - Self::WriteOnly => Some(nix::libc::O_WRONLY), - Self::ReadWrite => Some(nix::libc::O_RDWR), + Self::ReadOnly => Some(libc::O_RDONLY), + Self::WriteOnly => Some(libc::O_WRONLY), + Self::ReadWrite => Some(libc::O_RDWR), // TODO Support O_EXEC, O_PATH and O_SEARCH Self::Exec | Self::Search => None, } @@ -33,10 +33,10 @@ impl OfdAccess { #[must_use] pub(super) fn from_real_flags(flags: c_int) -> Self { - match flags & nix::libc::O_ACCMODE { - nix::libc::O_RDONLY => Self::ReadOnly, - nix::libc::O_WRONLY => Self::WriteOnly, - nix::libc::O_RDWR => Self::ReadWrite, + match flags & libc::O_ACCMODE { + libc::O_RDONLY => Self::ReadOnly, + libc::O_WRONLY => Self::WriteOnly, + libc::O_RDWR => Self::ReadWrite, _ => Self::Exec, // TODO Support O_PATH and O_SEARCH } } @@ -46,22 +46,22 @@ impl OpenFlag { #[must_use] pub(super) fn to_real_flags(self) -> Option { match self { - Self::Append => Some(nix::libc::O_APPEND), - Self::CloseOnExec => Some(nix::libc::O_CLOEXEC), - Self::Create => Some(nix::libc::O_CREAT), - Self::Directory => Some(nix::libc::O_DIRECTORY), - Self::Exclusive => Some(nix::libc::O_EXCL), + Self::Append => Some(libc::O_APPEND), + Self::CloseOnExec => Some(libc::O_CLOEXEC), + Self::Create => Some(libc::O_CREAT), + Self::Directory => Some(libc::O_DIRECTORY), + Self::Exclusive => Some(libc::O_EXCL), #[cfg(not(any(target_env = "newlib", target_os = "redox")))] - Self::NoCtty => Some(nix::libc::O_NOCTTY), + Self::NoCtty => Some(libc::O_NOCTTY), #[cfg(any(target_env = "newlib", target_os = "redox"))] Self::NoCtty => None, - Self::NoFollow => Some(nix::libc::O_NOFOLLOW), - Self::NonBlock => Some(nix::libc::O_NONBLOCK), + Self::NoFollow => Some(libc::O_NOFOLLOW), + Self::NonBlock => Some(libc::O_NONBLOCK), #[cfg(not(target_os = "redox"))] - Self::Sync => Some(nix::libc::O_SYNC), + Self::Sync => Some(libc::O_SYNC), #[cfg(target_os = "redox")] Self::Sync => None, - Self::Truncate => Some(nix::libc::O_TRUNC), + Self::Truncate => Some(libc::O_TRUNC), } } } diff --git a/yash-env/src/system/real/resource.rs b/yash-env/src/system/real/resource.rs index db204a3f..f95a0100 100644 --- a/yash-env/src/system/real/resource.rs +++ b/yash-env/src/system/real/resource.rs @@ -27,15 +27,15 @@ impl Resource { pub(super) const fn as_raw_type(&self) -> Option { match *self { #[cfg(not(any(target_env = "newlib", target_os = "redox")))] - Self::AS => Some(nix::libc::RLIMIT_AS as _), - Self::CORE => Some(nix::libc::RLIMIT_CORE as _), - Self::CPU => Some(nix::libc::RLIMIT_CPU as _), - Self::DATA => Some(nix::libc::RLIMIT_DATA as _), - Self::FSIZE => Some(nix::libc::RLIMIT_FSIZE as _), + Self::AS => Some(libc::RLIMIT_AS as _), + Self::CORE => Some(libc::RLIMIT_CORE as _), + Self::CPU => Some(libc::RLIMIT_CPU as _), + Self::DATA => Some(libc::RLIMIT_DATA as _), + Self::FSIZE => Some(libc::RLIMIT_FSIZE as _), #[cfg(target_os = "freebsd")] - Self::KQUEUES => Some(nix::libc::RLIMIT_KQUEUES as _), + Self::KQUEUES => Some(libc::RLIMIT_KQUEUES as _), #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))] - Self::LOCKS => Some(nix::libc::RLIMIT_LOCKS as _), + Self::LOCKS => Some(libc::RLIMIT_LOCKS as _), #[cfg(any( target_os = "macos", target_os = "ios", @@ -50,12 +50,12 @@ impl Resource { target_os = "emscripten", target_os = "nto" ))] - Self::MEMLOCK => Some(nix::libc::RLIMIT_MEMLOCK as _), + Self::MEMLOCK => Some(libc::RLIMIT_MEMLOCK as _), #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))] - Self::MSGQUEUE => Some(nix::libc::RLIMIT_MSGQUEUE as _), + Self::MSGQUEUE => Some(libc::RLIMIT_MSGQUEUE as _), #[cfg(any(target_os = "linux", target_os = "android"))] - Self::NICE => Some(nix::libc::RLIMIT_NICE as _), - Self::NOFILE => Some(nix::libc::RLIMIT_NOFILE as _), + Self::NICE => Some(libc::RLIMIT_NICE as _), + Self::NOFILE => Some(libc::RLIMIT_NOFILE as _), #[cfg(any( target_os = "aix", target_os = "macos", @@ -71,7 +71,7 @@ impl Resource { target_os = "emscripten", target_os = "nto" ))] - Self::NPROC => Some(nix::libc::RLIMIT_NPROC as _), + Self::NPROC => Some(libc::RLIMIT_NPROC as _), #[cfg(any( target_os = "aix", target_os = "macos", @@ -87,18 +87,18 @@ impl Resource { target_os = "emscripten", target_os = "nto" ))] - Self::RSS => Some(nix::libc::RLIMIT_RSS as _), + Self::RSS => Some(libc::RLIMIT_RSS as _), #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))] - Self::RTPRIO => Some(nix::libc::RLIMIT_RTPRIO as _), + Self::RTPRIO => Some(libc::RLIMIT_RTPRIO as _), #[cfg(target_os = "linux")] - Self::RTTIME => Some(nix::libc::RLIMIT_RTTIME as _), + Self::RTTIME => Some(libc::RLIMIT_RTTIME as _), #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))] - Self::SBSIZE => Some(nix::libc::RLIMIT_SBSIZE as _), + Self::SBSIZE => Some(libc::RLIMIT_SBSIZE as _), #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))] - Self::SIGPENDING => Some(nix::libc::RLIMIT_SIGPENDING as _), - Self::STACK => Some(nix::libc::RLIMIT_STACK as _), + Self::SIGPENDING => Some(libc::RLIMIT_SIGPENDING as _), + Self::STACK => Some(libc::RLIMIT_STACK as _), #[cfg(target_os = "freebsd")] - Self::SWAP => Some(nix::libc::RLIMIT_SWAP as _), + Self::SWAP => Some(libc::RLIMIT_SWAP as _), _ => None, } } diff --git a/yash-env/src/system/real/signal.rs b/yash-env/src/system/real/signal.rs index 50e5b487..81b84228 100644 --- a/yash-env/src/system/real/signal.rs +++ b/yash-env/src/system/real/signal.rs @@ -30,7 +30,7 @@ use std::ops::RangeInclusive; #[must_use] fn rt_range() -> RangeInclusive { #[cfg(target_os = "aix")] - return nix::libc::SIGRTMIN..=nix::libc::SIGRTMAX; + return libc::SIGRTMIN..=libc::SIGRTMAX; #[cfg(any( target_os = "android", @@ -38,7 +38,7 @@ fn rt_range() -> RangeInclusive { target_os = "l4re", target_os = "linux", ))] - return nix::libc::SIGRTMIN()..=nix::libc::SIGRTMAX(); + return libc::SIGRTMIN()..=libc::SIGRTMAX(); #[allow(unreachable_code)] { @@ -56,17 +56,17 @@ impl Name { } match self { - Self::Abrt => wrap(nix::libc::SIGABRT), - Self::Alrm => wrap(nix::libc::SIGALRM), - Self::Bus => wrap(nix::libc::SIGBUS), - Self::Chld => wrap(nix::libc::SIGCHLD), + Self::Abrt => wrap(libc::SIGABRT), + Self::Alrm => wrap(libc::SIGALRM), + Self::Bus => wrap(libc::SIGBUS), + Self::Chld => wrap(libc::SIGCHLD), #[cfg(any( target_os = "aix", target_os = "horizon", target_os = "illumos", target_os = "solaris", ))] - Self::Cld => wrap(nix::libc::SIGCLD), + Self::Cld => wrap(libc::SIGCLD), #[cfg(not(any( target_os = "aix", target_os = "horizon", @@ -74,7 +74,7 @@ impl Name { target_os = "solaris", )))] Self::Cld => None, - Self::Cont => wrap(nix::libc::SIGCONT), + Self::Cont => wrap(libc::SIGCONT), #[cfg(not(any( target_os = "android", target_os = "emscripten", @@ -83,7 +83,7 @@ impl Name { target_os = "linux", target_os = "redox", )))] - Self::Emt => wrap(nix::libc::SIGEMT), + Self::Emt => wrap(libc::SIGEMT), #[cfg(any( target_os = "android", target_os = "emscripten", @@ -93,9 +93,9 @@ impl Name { target_os = "redox", ))] Self::Emt => None, - Self::Fpe => wrap(nix::libc::SIGFPE), - Self::Hup => wrap(nix::libc::SIGHUP), - Self::Ill => wrap(nix::libc::SIGILL), + Self::Fpe => wrap(libc::SIGFPE), + Self::Hup => wrap(libc::SIGHUP), + Self::Ill => wrap(libc::SIGILL), #[cfg(not(any( target_os = "aix", target_os = "android", @@ -105,7 +105,7 @@ impl Name { target_os = "linux", target_os = "redox", )))] - Self::Info => wrap(nix::libc::SIGINFO), + Self::Info => wrap(libc::SIGINFO), #[cfg(any( target_os = "aix", target_os = "android", @@ -116,7 +116,7 @@ impl Name { target_os = "redox", ))] Self::Info => None, - Self::Int => wrap(nix::libc::SIGINT), + Self::Int => wrap(libc::SIGINT), #[cfg(any( target_os = "aix", target_os = "android", @@ -128,7 +128,7 @@ impl Name { target_os = "nto", target_os = "solaris", ))] - Self::Io => wrap(nix::libc::SIGIO), + Self::Io => wrap(libc::SIGIO), #[cfg(not(any( target_os = "aix", target_os = "android", @@ -141,13 +141,13 @@ impl Name { target_os = "solaris", )))] Self::Io => None, - Self::Iot => wrap(nix::libc::SIGIOT), - Self::Kill => wrap(nix::libc::SIGKILL), + Self::Iot => wrap(libc::SIGIOT), + Self::Kill => wrap(libc::SIGKILL), #[cfg(target_os = "horizon")] - Self::Lost => wrap(nix::libc::SIGLOST), + Self::Lost => wrap(libc::SIGLOST), #[cfg(not(target_os = "horizon"))] Self::Lost => None, - Self::Pipe => wrap(nix::libc::SIGPIPE), + Self::Pipe => wrap(libc::SIGPIPE), #[cfg(any( target_os = "aix", target_os = "android", @@ -160,7 +160,7 @@ impl Name { target_os = "nto", target_os = "solaris", ))] - Self::Poll => wrap(nix::libc::SIGPOLL), + Self::Poll => wrap(libc::SIGPOLL), #[cfg(not(any( target_os = "aix", target_os = "android", @@ -174,7 +174,7 @@ impl Name { target_os = "solaris", )))] Self::Poll => None, - Self::Prof => wrap(nix::libc::SIGPROF), + Self::Prof => wrap(libc::SIGPROF), #[cfg(any( target_os = "aix", target_os = "android", @@ -186,7 +186,7 @@ impl Name { target_os = "redox", target_os = "solaris", ))] - Self::Pwr => wrap(nix::libc::SIGPWR), + Self::Pwr => wrap(libc::SIGPWR), #[cfg(not(any( target_os = "aix", target_os = "android", @@ -199,8 +199,8 @@ impl Name { target_os = "solaris", )))] Self::Pwr => None, - Self::Quit => wrap(nix::libc::SIGQUIT), - Self::Segv => wrap(nix::libc::SIGSEGV), + Self::Quit => wrap(libc::SIGQUIT), + Self::Segv => wrap(libc::SIGSEGV), #[cfg(all( any( target_os = "android", @@ -210,7 +210,7 @@ impl Name { ), not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")) ))] - Self::Stkflt => wrap(nix::libc::SIGSTKFLT), + Self::Stkflt => wrap(libc::SIGSTKFLT), #[cfg(not(all( any( target_os = "android", @@ -221,24 +221,24 @@ impl Name { not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")) )))] Self::Stkflt => None, - Self::Stop => wrap(nix::libc::SIGSTOP), - Self::Sys => wrap(nix::libc::SIGSYS), - Self::Term => wrap(nix::libc::SIGTERM), + Self::Stop => wrap(libc::SIGSTOP), + Self::Sys => wrap(libc::SIGSYS), + Self::Term => wrap(libc::SIGTERM), #[cfg(target_os = "freebsd")] - Self::Thr => wrap(nix::libc::SIGTHR), + Self::Thr => wrap(libc::SIGTHR), #[cfg(not(target_os = "freebsd"))] Self::Thr => None, - Self::Trap => wrap(nix::libc::SIGTRAP), - Self::Tstp => wrap(nix::libc::SIGTSTP), - Self::Ttin => wrap(nix::libc::SIGTTIN), - Self::Ttou => wrap(nix::libc::SIGTTOU), - Self::Urg => wrap(nix::libc::SIGURG), - Self::Usr1 => wrap(nix::libc::SIGUSR1), - Self::Usr2 => wrap(nix::libc::SIGUSR2), - Self::Vtalrm => wrap(nix::libc::SIGVTALRM), - Self::Winch => wrap(nix::libc::SIGWINCH), - Self::Xcpu => wrap(nix::libc::SIGXCPU), - Self::Xfsz => wrap(nix::libc::SIGXFSZ), + Self::Trap => wrap(libc::SIGTRAP), + Self::Tstp => wrap(libc::SIGTSTP), + Self::Ttin => wrap(libc::SIGTTIN), + Self::Ttou => wrap(libc::SIGTTOU), + Self::Urg => wrap(libc::SIGURG), + Self::Usr1 => wrap(libc::SIGUSR1), + Self::Usr2 => wrap(libc::SIGUSR2), + Self::Vtalrm => wrap(libc::SIGVTALRM), + Self::Winch => wrap(libc::SIGWINCH), + Self::Xcpu => wrap(libc::SIGXCPU), + Self::Xfsz => wrap(libc::SIGXFSZ), Self::Rtmin(n) => { let range = rt_range(); @@ -270,26 +270,26 @@ impl Name { #[allow(unreachable_patterns)] match number { // Standard signals - nix::libc::SIGABRT => Some(Self::Abrt), - nix::libc::SIGALRM => Some(Self::Alrm), - nix::libc::SIGBUS => Some(Self::Bus), - nix::libc::SIGCHLD => Some(Self::Chld), - nix::libc::SIGCONT => Some(Self::Cont), - nix::libc::SIGFPE => Some(Self::Fpe), - nix::libc::SIGHUP => Some(Self::Hup), - nix::libc::SIGILL => Some(Self::Ill), - nix::libc::SIGINT => Some(Self::Int), - nix::libc::SIGKILL => Some(Self::Kill), - nix::libc::SIGPIPE => Some(Self::Pipe), - nix::libc::SIGQUIT => Some(Self::Quit), - nix::libc::SIGSEGV => Some(Self::Segv), - nix::libc::SIGSTOP => Some(Self::Stop), - nix::libc::SIGTERM => Some(Self::Term), - nix::libc::SIGTSTP => Some(Self::Tstp), - nix::libc::SIGTTIN => Some(Self::Ttin), - nix::libc::SIGTTOU => Some(Self::Ttou), - nix::libc::SIGUSR1 => Some(Self::Usr1), - nix::libc::SIGUSR2 => Some(Self::Usr2), + libc::SIGABRT => Some(Self::Abrt), + libc::SIGALRM => Some(Self::Alrm), + libc::SIGBUS => Some(Self::Bus), + libc::SIGCHLD => Some(Self::Chld), + libc::SIGCONT => Some(Self::Cont), + libc::SIGFPE => Some(Self::Fpe), + libc::SIGHUP => Some(Self::Hup), + libc::SIGILL => Some(Self::Ill), + libc::SIGINT => Some(Self::Int), + libc::SIGKILL => Some(Self::Kill), + libc::SIGPIPE => Some(Self::Pipe), + libc::SIGQUIT => Some(Self::Quit), + libc::SIGSEGV => Some(Self::Segv), + libc::SIGSTOP => Some(Self::Stop), + libc::SIGTERM => Some(Self::Term), + libc::SIGTSTP => Some(Self::Tstp), + libc::SIGTTIN => Some(Self::Ttin), + libc::SIGTTOU => Some(Self::Ttou), + libc::SIGUSR1 => Some(Self::Usr1), + libc::SIGUSR2 => Some(Self::Usr2), // Non-standard but common signals #[cfg(any( @@ -304,15 +304,15 @@ impl Name { target_os = "nto", target_os = "solaris", ))] - nix::libc::SIGPOLL => Some(Self::Poll), - nix::libc::SIGPROF => Some(Self::Prof), - nix::libc::SIGSYS => Some(Self::Sys), - nix::libc::SIGTRAP => Some(Self::Trap), - nix::libc::SIGURG => Some(Self::Urg), - nix::libc::SIGVTALRM => Some(Self::Vtalrm), - nix::libc::SIGWINCH => Some(Self::Winch), - nix::libc::SIGXCPU => Some(Self::Xcpu), - nix::libc::SIGXFSZ => Some(Self::Xfsz), + libc::SIGPOLL => Some(Self::Poll), + libc::SIGPROF => Some(Self::Prof), + libc::SIGSYS => Some(Self::Sys), + libc::SIGTRAP => Some(Self::Trap), + libc::SIGURG => Some(Self::Urg), + libc::SIGVTALRM => Some(Self::Vtalrm), + libc::SIGWINCH => Some(Self::Winch), + libc::SIGXCPU => Some(Self::Xcpu), + libc::SIGXFSZ => Some(Self::Xfsz), // other signals #[cfg(not(any( @@ -323,7 +323,7 @@ impl Name { target_os = "linux", target_os = "redox", )))] - nix::libc::SIGEMT => Some(Self::Emt), + libc::SIGEMT => Some(Self::Emt), #[cfg(not(any( target_os = "aix", target_os = "android", @@ -333,7 +333,7 @@ impl Name { target_os = "linux", target_os = "redox", )))] - nix::libc::SIGINFO => Some(Self::Info), + libc::SIGINFO => Some(Self::Info), #[cfg(any( target_os = "aix", target_os = "android", @@ -345,9 +345,9 @@ impl Name { target_os = "nto", target_os = "solaris", ))] - nix::libc::SIGIO => Some(Self::Io), + libc::SIGIO => Some(Self::Io), #[cfg(target_os = "horizon")] - nix::libc::SIGLOST => Some(Self::Lost), + libc::SIGLOST => Some(Self::Lost), #[cfg(any( target_os = "aix", target_os = "android", @@ -359,7 +359,7 @@ impl Name { target_os = "redox", target_os = "solaris", ))] - nix::libc::SIGPWR => Some(Self::Pwr), + libc::SIGPWR => Some(Self::Pwr), #[cfg(all( any( target_os = "android", @@ -369,9 +369,9 @@ impl Name { ), not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")) ))] - nix::libc::SIGSTKFLT => Some(Self::Stkflt), + libc::SIGSTKFLT => Some(Self::Stkflt), #[cfg(target_os = "freebsd")] - nix::libc::SIGTHR => Some(Self::Thr), + libc::SIGTHR => Some(Self::Thr), // Real-time signals _ => { @@ -414,9 +414,9 @@ fn all_signals() -> impl Iterator { /// Converts the signal set to a vector of signal numbers. /// /// This function adds the signal numbers in the set to the vector. -pub(super) fn sigset_to_vec(set: *const nix::libc::sigset_t, vec: &mut Vec) { +pub(super) fn sigset_to_vec(set: *const libc::sigset_t, vec: &mut Vec) { vec.extend( - all_signals().filter(|number| unsafe { nix::libc::sigismember(set, number.as_raw()) == 1 }), + all_signals().filter(|number| unsafe { libc::sigismember(set, number.as_raw()) == 1 }), ); } @@ -426,18 +426,18 @@ impl Disposition { /// This function returns the `sigaction` in an `MaybeUninit` because the /// `sigaction` structure may contain platform-dependent extra fields that /// are not initialized by this function. - pub(super) fn to_sigaction(self) -> MaybeUninit { + pub(super) fn to_sigaction(self) -> MaybeUninit { let handler = match self { - Disposition::Default => nix::libc::SIG_DFL, - Disposition::Ignore => nix::libc::SIG_IGN, + Disposition::Default => libc::SIG_DFL, + Disposition::Ignore => libc::SIG_IGN, Disposition::Catch => super::catch_signal as *const extern "C" fn(c_int) as _, }; - let mut sa = MaybeUninit::::uninit(); + let mut sa = MaybeUninit::::uninit(); let sa_ptr = sa.as_mut_ptr(); unsafe { (&raw mut (*sa_ptr).sa_flags).write(0); - nix::libc::sigemptyset(&raw mut ((*sa_ptr).sa_mask)); + libc::sigemptyset(&raw mut ((*sa_ptr).sa_mask)); #[cfg(not(target_os = "aix"))] #[allow(clippy::useless_transmute)] // See from_sigaction below @@ -451,7 +451,7 @@ impl Disposition { } /// Converts the `sigaction` to the signal disposition for the real system. - pub(super) unsafe fn from_sigaction(sa: &MaybeUninit) -> Self { + pub(super) unsafe fn from_sigaction(sa: &MaybeUninit) -> Self { #[cfg(not(target_os = "aix"))] let handler = (&raw const (*sa.as_ptr()).sa_sigaction).read(); @@ -461,8 +461,8 @@ impl Disposition { // It is platform-specific whether we really need to transmute the handler. #[allow(clippy::useless_transmute)] match std::mem::transmute(handler) { - nix::libc::SIG_DFL => Self::Default, - nix::libc::SIG_IGN => Self::Ignore, + libc::SIG_DFL => Self::Default, + libc::SIG_IGN => Self::Ignore, _ => Self::Catch, } } diff --git a/yash-env/src/system/resource.rs b/yash-env/src/system/resource.rs index 33a29c2b..cf1e52c0 100644 --- a/yash-env/src/system/resource.rs +++ b/yash-env/src/system/resource.rs @@ -23,7 +23,7 @@ //! [`setrlimit`]: super::System::setrlimit #[cfg(unix)] -type RawLimit = nix::libc::rlim_t; +type RawLimit = libc::rlim_t; #[cfg(not(unix))] type RawLimit = u64; @@ -33,7 +33,7 @@ type RawLimit = u64; pub type Limit = RawLimit; #[cfg(unix)] -const RLIM_INFINITY: Limit = nix::libc::RLIM_INFINITY; +const RLIM_INFINITY: Limit = libc::RLIM_INFINITY; #[cfg(not(unix))] const RLIM_INFINITY: Limit = Limit::MAX; From b24157fbcc33ba1124291b42c788ec04d3619c11 Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Fri, 10 Jan 2025 00:56:49 +0900 Subject: [PATCH 02/11] Migrate to errno crate The real system implementation now uses the `errno` crate instead of the `nix` crate for accessing the `errno` value in the underlying system. This allows removing the `nix` dependency from the `yash-env` crate. --- Cargo.lock | 1 + yash-env/CHANGELOG.md | 3 +++ yash-env/Cargo.toml | 1 + yash-env/src/system/errno.rs | 16 ++++++++++++++ yash-env/src/system/real.rs | 4 ++-- yash-env/src/system/real/errno.rs | 35 +++++++++++++++---------------- 6 files changed, 40 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aebecf26..24ec202b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -576,6 +576,7 @@ dependencies = [ "bitflags", "either", "enumset", + "errno", "futures-executor", "futures-util", "itertools", diff --git a/yash-env/CHANGELOG.md b/yash-env/CHANGELOG.md index 89efc4fc..4c154192 100644 --- a/yash-env/CHANGELOG.md +++ b/yash-env/CHANGELOG.md @@ -13,7 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The `builtin::Builtin` struct now has the `is_declaration_utility` field. - The `builtin::Builtin` struct now can be constructed with the associated function `new`. +- The `system::errno::Errno` struct now can be converted to and from the `Errno` + type from the `errno` crate. - Internal dependencies: + - errno 0.3.10 - libc 0.2.169 ### Changed diff --git a/yash-env/Cargo.toml b/yash-env/Cargo.toml index 1b18a503..3aa503ed 100644 --- a/yash-env/Cargo.toml +++ b/yash-env/Cargo.toml @@ -19,6 +19,7 @@ annotate-snippets = "0.11.4" bitflags = "2.6.0" either = "1.9.0" enumset = "1.1.2" +errno = { version = "0.3.10", default-features = false } futures-util = "0.3.31" itertools = "0.13.0" slab = "0.4.9" diff --git a/yash-env/src/system/errno.rs b/yash-env/src/system/errno.rs index 1188e065..aafe6056 100644 --- a/yash-env/src/system/errno.rs +++ b/yash-env/src/system/errno.rs @@ -394,6 +394,22 @@ impl From for Errno { } } +/// Converts [`Errno`] to [`errno::Errno`]. +impl From for errno::Errno { + #[inline] + fn from(errno: Errno) -> Self { + Self(errno.0) + } +} + +/// Converts [`errno::Errno`] to [`Errno`]. +impl From for Errno { + #[inline] + fn from(errno: errno::Errno) -> Self { + Self(errno.into()) + } +} + /// Converts [`Errno`] to [`nix::Error`]. /// /// This conversion is only available on Unix-like systems. diff --git a/yash-env/src/system/real.rs b/yash-env/src/system/real.rs index 7aba9bbb..e2ac3ae6 100644 --- a/yash-env/src/system/real.rs +++ b/yash-env/src/system/real.rs @@ -394,13 +394,13 @@ impl System for RealSystem { fn fdopendir(&mut self, fd: Fd) -> Result> { let dir = unsafe { libc::fdopendir(fd.0) }; - let dir = NonNull::new(dir).ok_or_else(NixErrno::last)?; + let dir = NonNull::new(dir).ok_or_else(Errno::last)?; Ok(Box::new(RealDir(dir))) } fn opendir(&mut self, path: &CStr) -> Result> { let dir = unsafe { libc::opendir(path.as_ptr()) }; - let dir = NonNull::new(dir).ok_or_else(NixErrno::last)?; + let dir = NonNull::new(dir).ok_or_else(Errno::last)?; Ok(Box::new(RealDir(dir))) } diff --git a/yash-env/src/system/real/errno.rs b/yash-env/src/system/real/errno.rs index 65341468..b9cdbf84 100644 --- a/yash-env/src/system/real/errno.rs +++ b/yash-env/src/system/real/errno.rs @@ -29,21 +29,21 @@ impl Errno { #[inline] #[must_use] pub(super) fn last() -> Self { - Self(nix::Error::last() as _) + errno::errno().into() } - // TODO Need nix 0.28.0 - // /// Sets the current `errno` value. - // /// - // /// This function sets the current `errno` value to the specified value. - // /// The next call to [`last`](Self::last) will return the specified value - // /// unless another system call changes the `errno` value. This function is - // /// useful when you want to simulate an error condition in a system call. - // /// - // /// Use [`clear`](Self::clear) to reset the `errno` value. - // pub(super) fn set_last(errno: Self) { - // nix::Error::set_raw(errno.0) - // } + /// Sets the current `errno` value. + /// + /// This function sets the current `errno` value to the specified value. + /// The next call to [`last`](Self::last) will return the specified value + /// unless another system call changes the `errno` value. This function is + /// useful when you want to simulate an error condition in a system call. + /// + /// Use [`clear`](Self::clear) to reset the `errno` value. + #[inline] + pub(super) fn set_last(errno: Self) { + errno::set_errno(errno.into()) + } /// Clears the current `errno` value. /// @@ -53,12 +53,11 @@ impl Errno { /// and check the `errno` value after calling the function to see if an /// error occurred. This function resets the current `errno` value to /// [`NO_ERROR`](Self::NO_ERROR). - // /// - // /// Use [`set_last`](Self::set_last) to set the `errno` value to an - // /// arbitrary value. + /// + /// Use [`set_last`](Self::set_last) to set the `errno` value to an + /// arbitrary value. #[inline] pub(super) fn clear() { - // Self::set_last(Self::NO_ERROR) - nix::Error::clear() + Self::set_last(Self::NO_ERROR) } } From 97ab9016e6aad9a3e03e4161b1f8bed148f2a4c3 Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Sat, 11 Jan 2025 01:23:23 +0900 Subject: [PATCH 03/11] Migrate nix stat and faccessat to libc --- yash-env/src/system/real.rs | 44 +++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/yash-env/src/system/real.rs b/yash-env/src/system/real.rs index e2ac3ae6..0fa82f90 100644 --- a/yash-env/src/system/real.rs +++ b/yash-env/src/system/real.rs @@ -37,6 +37,7 @@ use super::Disposition; use super::Env; use super::Errno; use super::FdFlag; +use super::FileType; use super::Gid; use super::Mode; use super::OfdAccess; @@ -47,6 +48,7 @@ use super::Stat; use super::System; use super::Times; use super::Uid; +use super::AT_FDCWD; use crate::io::Fd; use crate::job::Pid; use crate::job::ProcessResult; @@ -57,11 +59,7 @@ use crate::str::UnixStr; use crate::str::UnixString; use enumset::EnumSet; use libc::DIR; -use libc::{S_IFDIR, S_IFMT, S_IFREG}; use nix::errno::Errno as NixErrno; -use nix::fcntl::AtFlags; -use nix::sys::stat::stat; -use nix::unistd::AccessFlags; use std::convert::Infallible; use std::convert::TryInto; use std::ffi::c_int; @@ -130,24 +128,6 @@ impl Pid { } } -// TODO Should use AT_EACCESS on all platforms -#[cfg(not(target_os = "redox"))] -fn is_executable(path: &CStr) -> bool { - nix::unistd::faccessat(None, path, AccessFlags::X_OK, AtFlags::AT_EACCESS).is_ok() -} -#[cfg(target_os = "redox")] -fn is_executable(path: &CStr) -> bool { - nix::unistd::access(path, AccessFlags::X_OK).is_ok() -} - -fn is_regular_file(path: &CStr) -> bool { - matches!(stat(path), Ok(stat) if stat.st_mode & S_IFMT == S_IFREG) -} - -fn is_directory(path: &CStr) -> bool { - matches!(stat(path), Ok(stat) if stat.st_mode & S_IFMT == S_IFDIR) -} - /// Converts a `Duration` to a `timespec`. /// /// The return value is a `MaybeUninit` because the `timespec` struct may have @@ -214,6 +194,22 @@ impl RealSystem { pub unsafe fn new() -> Self { RealSystem(()) } + + fn file_has_type(&self, path: &CStr, r#type: FileType) -> bool { + self.fstatat(AT_FDCWD, path, true) + .is_ok_and(|stat| stat.r#type == r#type) + } + + // TODO Should use AT_EACCESS on all platforms + #[cfg(not(target_os = "redox"))] + fn has_execute_permission(&self, path: &CStr) -> bool { + (unsafe { libc::faccessat(libc::AT_FDCWD, path.as_ptr(), libc::X_OK, libc::AT_EACCESS) }) + != -1 + } + #[cfg(target_os = "redox")] + fn has_execute_permission(&self, path: &CStr) -> bool { + (unsafe { libc::access(path.as_ptr(), libc::X_OK) }) != -1 + } } impl System for RealSystem { @@ -237,11 +233,11 @@ impl System for RealSystem { } fn is_executable_file(&self, path: &CStr) -> bool { - is_regular_file(path) && is_executable(path) + self.file_has_type(path, FileType::Regular) && self.has_execute_permission(path) } fn is_directory(&self, path: &CStr) -> bool { - is_directory(path) + self.file_has_type(path, FileType::Directory) } fn pipe(&mut self) -> Result<(Fd, Fd)> { From 4007c308fe2e3f3c206698abfd91134fc9e59f57 Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Sat, 11 Jan 2025 15:03:43 +0900 Subject: [PATCH 04/11] Migrate waitpid from nix to libc --- yash-env/src/system/real.rs | 64 +++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/yash-env/src/system/real.rs b/yash-env/src/system/real.rs index 0fa82f90..5ee5c25c 100644 --- a/yash-env/src/system/real.rs +++ b/yash-env/src/system/real.rs @@ -117,17 +117,6 @@ impl ErrnoIfM1 for isize { const MINUS_1: Self = -1; } -impl Pid { - #[inline(always)] - const fn to_nix(self) -> nix::unistd::Pid { - nix::unistd::Pid::from_raw(self.0) - } - #[inline(always)] - const fn from_nix(pid: nix::unistd::Pid) -> Self { - Pid(pid.as_raw()) - } -} - /// Converts a `Duration` to a `timespec`. /// /// The return value is a `MaybeUninit` because the `timespec` struct may have @@ -687,31 +676,36 @@ impl System for RealSystem { } fn wait(&mut self, target: Pid) -> Result> { - use nix::sys::wait::{WaitPidFlag, WaitStatus::*}; - let options = WaitPidFlag::WUNTRACED | WaitPidFlag::WCONTINUED | WaitPidFlag::WNOHANG; - let status = nix::sys::wait::waitpid(Some(target.to_nix()), options.into())?; - match status { - StillAlive => Ok(None), - Continued(pid) => Ok(Some((Pid::from_nix(pid), ProcessState::Running))), - Exited(pid, exit_status) => Ok(Some(( - Pid::from_nix(pid), - ProcessState::exited(exit_status), - ))), - Signaled(pid, signal, core_dump) => { - // SAFETY: The signal number is always a valid signal number, which is non-zero. - let raw_number = unsafe { NonZeroI32::new_unchecked(signal as _) }; - let signal = signal::Number::from_raw_unchecked(raw_number); - let process_result = ProcessResult::Signaled { signal, core_dump }; - Ok(Some((Pid::from_nix(pid), process_result.into()))) - } - Stopped(pid, signal) => { - // SAFETY: The signal number is always a valid signal number, which is non-zero. - let raw_number = unsafe { NonZeroI32::new_unchecked(signal as _) }; - let signal = signal::Number::from_raw_unchecked(raw_number); - Ok(Some((Pid::from_nix(pid), ProcessState::stopped(signal)))) + let mut status = 0; + let options = libc::WUNTRACED | libc::WCONTINUED | libc::WNOHANG; + match unsafe { libc::waitpid(target.0, &mut status, options) } { + -1 => Err(Errno::last()), + 0 => Ok(None), + pid => { + let state = if libc::WIFCONTINUED(status) { + ProcessState::Running + } else if libc::WIFEXITED(status) { + let exit_status = libc::WEXITSTATUS(status); + ProcessState::exited(exit_status) + } else if libc::WIFSIGNALED(status) { + let signal = libc::WTERMSIG(status); + let core_dump = libc::WCOREDUMP(status); + // SAFETY: The signal number is always a valid signal number, which is non-zero. + let raw_number = unsafe { NonZeroI32::new_unchecked(signal as _) }; + let signal = signal::Number::from_raw_unchecked(raw_number); + let process_result = ProcessResult::Signaled { signal, core_dump }; + process_result.into() + } else if libc::WIFSTOPPED(status) { + let signal = libc::WSTOPSIG(status); + // SAFETY: The signal number is always a valid signal number, which is non-zero. + let raw_number = unsafe { NonZeroI32::new_unchecked(signal as _) }; + let signal = signal::Number::from_raw_unchecked(raw_number); + ProcessState::stopped(signal) + } else { + unreachable!() + }; + Ok(Some((Pid(pid), state))) } - #[allow(unreachable_patterns)] - _ => unreachable!(), } } From be7f409c6a9dc2be69acca43e570ceb89b5333f7 Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Sat, 11 Jan 2025 16:10:24 +0900 Subject: [PATCH 05/11] Migrate getcwd from nix to libc This is part of the effort to remove the dependency on nix. In nix 0.29.0, the getcwd function does not allocate a buffer larger than PATH_MAX, which may not be enough for some systems. --- yash-env/src/system/real.rs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/yash-env/src/system/real.rs b/yash-env/src/system/real.rs index 5ee5c25c..0a7f0f35 100644 --- a/yash-env/src/system/real.rs +++ b/yash-env/src/system/real.rs @@ -720,9 +720,30 @@ impl System for RealSystem { } fn getcwd(&self) -> Result { - let path = nix::unistd::getcwd()?; - let raw = path.into_os_string().into_vec(); - Ok(PathBuf::from(UnixString::from_vec(raw))) + // Some getcwd implementations allocate a buffer for the path if the + // first argument is null, but we cannot use that feature because Vec's + // allocator may not be compatible with the system's allocator. + + // Since there is no way to know the required buffer size, we try + // several buffer sizes. + let mut buffer = Vec::::new(); + for capacity in [1 << 10, 1 << 12, 1 << 14, 1 << 16] { + buffer.reserve_exact(capacity); + + let result = unsafe { libc::getcwd(buffer.as_mut_ptr().cast(), capacity) }; + if !result.is_null() { + // len does not include the null terminator + let len = unsafe { CStr::from_ptr(buffer.as_ptr().cast()) }.count_bytes(); + unsafe { buffer.set_len(len) } + buffer.shrink_to_fit(); + return Ok(PathBuf::from(UnixString::from_vec(buffer))); + } + let errno = Errno::last(); + if errno != Errno::ERANGE { + return Err(errno); + } + } + Err(Errno::ERANGE) } fn chdir(&mut self, path: &CStr) -> Result<()> { From 571719a347039044aa7eb12a6354a45191a6dd52 Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Sat, 11 Jan 2025 16:14:06 +0900 Subject: [PATCH 06/11] Migrate chdir from nix to libc --- yash-env/src/system/real.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yash-env/src/system/real.rs b/yash-env/src/system/real.rs index 0a7f0f35..e9bbd107 100644 --- a/yash-env/src/system/real.rs +++ b/yash-env/src/system/real.rs @@ -747,8 +747,8 @@ impl System for RealSystem { } fn chdir(&mut self, path: &CStr) -> Result<()> { - nix::unistd::chdir(path)?; - Ok(()) + let result = unsafe { libc::chdir(path.as_ptr()) }; + result.errno_if_m1().map(drop) } fn getuid(&self) -> Uid { From b4b099aa744b830193bd28f22cf6aefe444fd289 Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Sat, 11 Jan 2025 17:01:15 +0900 Subject: [PATCH 07/11] Migrate getpwnam_dir from nix to libc --- yash-env/CHANGELOG.md | 1 + yash-env/src/system.rs | 2 +- yash-env/src/system/real.rs | 21 ++++++++++++------- yash-env/src/system/shared.rs | 4 ++-- yash-env/src/system/virtual.rs | 6 +++++- yash-semantics/src/expansion/initial/tilde.rs | 9 +++++--- 6 files changed, 29 insertions(+), 14 deletions(-) diff --git a/yash-env/CHANGELOG.md b/yash-env/CHANGELOG.md index 4c154192..5fa16a55 100644 --- a/yash-env/CHANGELOG.md +++ b/yash-env/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- `System::getpwnam_dir` now takes a `&CStr` parameter instead of a `&str`. - The `builtin::Builtin` struct is now `non_exhaustive`. - External dependency versions: - yash-syntax 0.13.0 → 0.14.0 diff --git a/yash-env/src/system.rs b/yash-env/src/system.rs index 1cf3baa9..a4bc064e 100644 --- a/yash-env/src/system.rs +++ b/yash-env/src/system.rs @@ -434,7 +434,7 @@ pub trait System: Debug { /// Returns the home directory path of the given user. /// /// Returns `Ok(None)` if the user is not found. - fn getpwnam_dir(&self, name: &str) -> Result>; + fn getpwnam_dir(&self, name: &CStr) -> Result>; /// Returns the standard `$PATH` value where all standard utilities are /// expected to be found. diff --git a/yash-env/src/system/real.rs b/yash-env/src/system/real.rs index e9bbd107..a6710b88 100644 --- a/yash-env/src/system/real.rs +++ b/yash-env/src/system/real.rs @@ -71,7 +71,6 @@ use std::io::SeekFrom; use std::mem::MaybeUninit; use std::num::NonZeroI32; use std::os::unix::ffi::OsStrExt as _; -use std::os::unix::ffi::OsStringExt as _; use std::os::unix::io::IntoRawFd; use std::pin::Pin; use std::ptr::NonNull; @@ -767,12 +766,20 @@ impl System for RealSystem { Gid(unsafe { libc::getegid() }) } - fn getpwnam_dir(&self, name: &str) -> Result> { - let user = nix::unistd::User::from_name(name)?; - Ok(user.map(|user| { - let dir = user.dir.into_os_string().into_vec(); - PathBuf::from(UnixString::from_vec(dir)) - })) + fn getpwnam_dir(&self, name: &CStr) -> Result> { + Errno::clear(); + let passwd = unsafe { libc::getpwnam(name.as_ptr()) }; + if passwd.is_null() { + let errno = Errno::last(); + return if errno == Errno::NO_ERROR { + Ok(None) + } else { + Err(errno) + }; + } + + let dir = unsafe { CStr::from_ptr(*&raw const (*passwd).pw_dir) }; + Ok(Some(UnixString::from_vec(dir.to_bytes().to_vec()).into())) } fn confstr_path(&self) -> Result { diff --git a/yash-env/src/system/shared.rs b/yash-env/src/system/shared.rs index e545119a..3fda698a 100644 --- a/yash-env/src/system/shared.rs +++ b/yash-env/src/system/shared.rs @@ -455,7 +455,7 @@ impl System for &SharedSystem { fn getegid(&self) -> Gid { self.0.borrow().getegid() } - fn getpwnam_dir(&self, name: &str) -> Result> { + fn getpwnam_dir(&self, name: &CStr) -> Result> { self.0.borrow().getpwnam_dir(name) } fn confstr_path(&self) -> Result { @@ -677,7 +677,7 @@ impl System for SharedSystem { (&self).getegid() } #[inline] - fn getpwnam_dir(&self, name: &str) -> Result> { + fn getpwnam_dir(&self, name: &CStr) -> Result> { (&self).getpwnam_dir(name) } #[inline] diff --git a/yash-env/src/system/virtual.rs b/yash-env/src/system/virtual.rs index f4ca6474..3075bb39 100644 --- a/yash-env/src/system/virtual.rs +++ b/yash-env/src/system/virtual.rs @@ -982,8 +982,12 @@ impl System for VirtualSystem { self.current_process().egid() } - fn getpwnam_dir(&self, name: &str) -> Result> { + fn getpwnam_dir(&self, name: &CStr) -> Result> { let state = self.state.borrow(); + let name = match name.to_str() { + Ok(name) => name, + Err(_utf8_error) => return Ok(None), + }; Ok(state.home_dirs.get(name).cloned()) } diff --git a/yash-semantics/src/expansion/initial/tilde.rs b/yash-semantics/src/expansion/initial/tilde.rs index 0dd4d859..06561081 100644 --- a/yash-semantics/src/expansion/initial/tilde.rs +++ b/yash-semantics/src/expansion/initial/tilde.rs @@ -18,6 +18,7 @@ use crate::expansion::attr::AttrChar; use crate::expansion::attr::Origin; +use std::ffi::CString; use yash_env::variable::HOME; use yash_env::Env; use yash_env::System; @@ -42,9 +43,11 @@ pub fn expand(name: &str, env: &Env) -> Vec { let result = env.variables.get_scalar(HOME).unwrap_or("~"); into_attr_chars(result.chars()) } else { - if let Ok(Some(path)) = env.system.getpwnam_dir(name) { - if let Ok(path) = path.into_unix_string().into_string() { - return into_attr_chars(path.chars()); + if let Ok(name) = CString::new(name) { + if let Ok(Some(path)) = env.system.getpwnam_dir(&name) { + if let Ok(path) = path.into_unix_string().into_string() { + return into_attr_chars(path.chars()); + } } } into_attr_chars(std::iter::once('~').chain(name.chars())) From dc878f2dd359f3b7cf30f6553b2f33911a5449be Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Sat, 11 Jan 2025 18:35:58 +0900 Subject: [PATCH 08/11] Simplify field access thru raw pointers The previous implementation verbosely used `&raw const` to access fields of a struct through a raw pointer. This is unnecessary because field access and pointer dereference are place expressions in Rust, so we don't have to care if the other fields in the dereferenced struct are initialized or not. --- yash-env/src/system/real.rs | 20 ++++++++++++-------- yash-env/src/system/real/file_system.rs | 14 +++++++------- yash-env/src/system/real/signal.rs | 8 ++++---- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/yash-env/src/system/real.rs b/yash-env/src/system/real.rs index a6710b88..4201ceb1 100644 --- a/yash-env/src/system/real.rs +++ b/yash-env/src/system/real.rs @@ -408,13 +408,13 @@ impl System for RealSystem { return Err(Errno::last()); } - // SAFETY: The four fields of `tms` have been initialized by `times`. + // SAFETY: These four fields of `tms` have been initialized by `times`. // (But that does not mean *all* fields are initialized, // so we cannot use `assume_init` here.) - let utime = unsafe { (&raw const (*tms.as_ptr()).tms_utime).read() }; - let stime = unsafe { (&raw const (*tms.as_ptr()).tms_stime).read() }; - let cutime = unsafe { (&raw const (*tms.as_ptr()).tms_cutime).read() }; - let cstime = unsafe { (&raw const (*tms.as_ptr()).tms_cstime).read() }; + let utime = unsafe { (*tms.as_ptr()).tms_utime }; + let stime = unsafe { (*tms.as_ptr()).tms_stime }; + let cutime = unsafe { (*tms.as_ptr()).tms_cutime }; + let cstime = unsafe { (*tms.as_ptr()).tms_cstime }; Ok(Times { self_user: utime as f64 / ticks_per_second as f64, @@ -778,7 +778,7 @@ impl System for RealSystem { }; } - let dir = unsafe { CStr::from_ptr(*&raw const (*passwd).pw_dir) }; + let dir = unsafe { CStr::from_ptr((*passwd).pw_dir) }; Ok(Some(UnixString::from_vec(dir.to_bytes().to_vec()).into())) } @@ -846,9 +846,13 @@ impl System for RealSystem { let mut limits = MaybeUninit::::uninit(); unsafe { libc::getrlimit(raw_resource as _, limits.as_mut_ptr()) }.errno_if_m1()?; + + // SAFETY: These two fields of `limits` have been initialized by `getrlimit`. + // (But that does not mean *all* fields are initialized, + // so we cannot use `assume_init` here.) Ok(LimitPair { - soft: unsafe { (&raw const (*limits.as_ptr()).rlim_cur).read() }, - hard: unsafe { (&raw const (*limits.as_ptr()).rlim_max).read() }, + soft: unsafe { (*limits.as_ptr()).rlim_cur }, + hard: unsafe { (*limits.as_ptr()).rlim_max }, }) } diff --git a/yash-env/src/system/real/file_system.rs b/yash-env/src/system/real/file_system.rs index 6bae34ef..e639e999 100644 --- a/yash-env/src/system/real/file_system.rs +++ b/yash-env/src/system/real/file_system.rs @@ -44,16 +44,16 @@ impl Stat { #[must_use] pub(super) const fn from_raw(stat: &MaybeUninit) -> Self { let ptr = stat.as_ptr(); - let raw_mode = unsafe { (&raw const (*ptr).st_mode).read() }; + let raw_mode = unsafe { (*ptr).st_mode }; Self { - dev: unsafe { (&raw const (*ptr).st_dev).read() } as _, - ino: unsafe { (&raw const (*ptr).st_ino).read() } as _, + dev: unsafe { (*ptr).st_dev } as _, + ino: unsafe { (*ptr).st_ino } as _, mode: Mode::from_bits_truncate(raw_mode), r#type: FileType::from_raw(raw_mode), - nlink: unsafe { (&raw const (*ptr).st_nlink).read() } as _, - uid: Uid(unsafe { (&raw const (*ptr).st_uid).read() }), - gid: Gid(unsafe { (&raw const (*ptr).st_gid).read() }), - size: unsafe { (&raw const (*ptr).st_size).read() } as _, + nlink: unsafe { (*ptr).st_nlink } as _, + uid: Uid(unsafe { (*ptr).st_uid }), + gid: Gid(unsafe { (*ptr).st_gid }), + size: unsafe { (*ptr).st_size } as _, } } } diff --git a/yash-env/src/system/real/signal.rs b/yash-env/src/system/real/signal.rs index 81b84228..2ec51af7 100644 --- a/yash-env/src/system/real/signal.rs +++ b/yash-env/src/system/real/signal.rs @@ -436,8 +436,8 @@ impl Disposition { let mut sa = MaybeUninit::::uninit(); let sa_ptr = sa.as_mut_ptr(); unsafe { - (&raw mut (*sa_ptr).sa_flags).write(0); - libc::sigemptyset(&raw mut ((*sa_ptr).sa_mask)); + (*sa_ptr).sa_flags = 0; + libc::sigemptyset(&raw mut (*sa_ptr).sa_mask); #[cfg(not(target_os = "aix"))] #[allow(clippy::useless_transmute)] // See from_sigaction below @@ -453,10 +453,10 @@ impl Disposition { /// Converts the `sigaction` to the signal disposition for the real system. pub(super) unsafe fn from_sigaction(sa: &MaybeUninit) -> Self { #[cfg(not(target_os = "aix"))] - let handler = (&raw const (*sa.as_ptr()).sa_sigaction).read(); + let handler = (*sa.as_ptr()).sa_sigaction; #[cfg(target_os = "aix")] - let handler = (&raw const (*sa.as_ptr()).sa_union.__su_sigaction).read(); + let handler = (*sa.as_ptr()).sa_union.__su_sigaction; // It is platform-specific whether we really need to transmute the handler. #[allow(clippy::useless_transmute)] From 32051be5d22684ad83522280fa10be37d664f2c2 Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Sat, 11 Jan 2025 18:41:22 +0900 Subject: [PATCH 09/11] Make Stat::from_raw unsafe This function is safe to call only if the `stat` structure is initialized by the `stat` system call. This is a safe assumption in practice, but it is not enforced by the type system. Therefore, the function should be marked as unsafe. --- yash-env/src/system/real.rs | 6 ++++-- yash-env/src/system/real/file_system.rs | 9 +++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/yash-env/src/system/real.rs b/yash-env/src/system/real.rs index 4201ceb1..abc35760 100644 --- a/yash-env/src/system/real.rs +++ b/yash-env/src/system/real.rs @@ -204,7 +204,8 @@ impl System for RealSystem { fn fstat(&self, fd: Fd) -> Result { let mut stat = MaybeUninit::::uninit(); unsafe { libc::fstat(fd.0, stat.as_mut_ptr()) }.errno_if_m1()?; - Ok(Stat::from_raw(&stat)) + let stat = unsafe { Stat::from_raw(&stat) }; + Ok(stat) } fn fstatat(&self, dir_fd: Fd, path: &CStr, follow_symlinks: bool) -> Result { @@ -217,7 +218,8 @@ impl System for RealSystem { let mut stat = MaybeUninit::::uninit(); unsafe { libc::fstatat(dir_fd.0, path.as_ptr(), stat.as_mut_ptr(), flags) } .errno_if_m1()?; - Ok(Stat::from_raw(&stat)) + let stat = unsafe { Stat::from_raw(&stat) }; + Ok(stat) } fn is_executable_file(&self, path: &CStr) -> bool { diff --git a/yash-env/src/system/real/file_system.rs b/yash-env/src/system/real/file_system.rs index e639e999..bedf7f44 100644 --- a/yash-env/src/system/real/file_system.rs +++ b/yash-env/src/system/real/file_system.rs @@ -38,11 +38,12 @@ impl FileType { impl Stat { /// Converts a raw `stat` structure to a `Stat` object. /// - /// This function requires the `stat` structure to be initialized, but it is - /// passed as `MaybeUninit` because of possible padding or extension fields - /// in the structure which may not be initialized by the `stat` system call. + /// This function assumes the `stat` structure to be initialized by the + /// `stat` system call, but it is passed as `MaybeUninit` because of + /// possible padding or extension fields in the structure which may not be + /// initialized by the system call. #[must_use] - pub(super) const fn from_raw(stat: &MaybeUninit) -> Self { + pub(super) const unsafe fn from_raw(stat: &MaybeUninit) -> Self { let ptr = stat.as_ptr(); let raw_mode = unsafe { (*ptr).st_mode }; Self { From da1947737200f7dbe766b922ce7d18659513e591 Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Sun, 12 Jan 2025 17:05:09 +0900 Subject: [PATCH 10/11] Use libc::execve --- yash-env/src/system/real.rs | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/yash-env/src/system/real.rs b/yash-env/src/system/real.rs index abc35760..5ce02abe 100644 --- a/yash-env/src/system/real.rs +++ b/yash-env/src/system/real.rs @@ -59,7 +59,6 @@ use crate::str::UnixStr; use crate::str::UnixString; use enumset::EnumSet; use libc::DIR; -use nix::errno::Errno as NixErrno; use std::convert::Infallible; use std::convert::TryInto; use std::ffi::c_int; @@ -711,11 +710,29 @@ impl System for RealSystem { } fn execve(&mut self, path: &CStr, args: &[CString], envs: &[CString]) -> Result { + fn to_pointer_array>(strs: &[S]) -> Vec<*const libc::c_char> { + strs.iter() + .map(|s| s.as_ref().as_ptr()) + .chain(std::iter::once(std::ptr::null())) + .collect() + } + // TODO Uncomment when upgrading to libc 1.0 + // // This function makes mutable char pointers from immutable string + // // slices since `execve` requires mutable pointers. + // fn to_pointer_array>(strs: &[S]) -> Vec<*mut libc::c_char> { + // strs.iter() + // .map(|s| s.as_ref().as_ptr().cast_mut()) + // .chain(std::iter::once(std::ptr::null_mut())) + // .collect() + // } + + let args = to_pointer_array(args); + let envs = to_pointer_array(envs); loop { - // TODO Use Result::into_err - let result = nix::unistd::execve(path, args, envs); - if result != Err(NixErrno::EINTR) { - return Ok(result?); + let _ = unsafe { libc::execve(path.as_ptr(), args.as_ptr(), envs.as_ptr()) }; + let errno = Errno::last(); + if errno != Errno::EINTR { + return Err(errno); } } } From 1405b3030274a9f526c52b6d76216e35bcddaa7c Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Sun, 12 Jan 2025 17:11:35 +0900 Subject: [PATCH 11/11] Remove nix dependency Now that the `yash-env` crate directly depends on the `errno` and `libc` crates, the `nix` crate is no longer needed. This commit removes the `nix` dependency from the `yash-env` crate. --- Cargo.lock | 1 - yash-env/CHANGELOG.md | 7 +++++++ yash-env/Cargo.toml | 1 - yash-env/src/system/errno.rs | 22 ---------------------- 4 files changed, 7 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24ec202b..282b501a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -581,7 +581,6 @@ dependencies = [ "futures-util", "itertools", "libc", - "nix", "slab", "strum", "tempfile", diff --git a/yash-env/CHANGELOG.md b/yash-env/CHANGELOG.md index 5fa16a55..ee79dd05 100644 --- a/yash-env/CHANGELOG.md +++ b/yash-env/CHANGELOG.md @@ -26,6 +26,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - External dependency versions: - yash-syntax 0.13.0 → 0.14.0 +### Removed + +- The implementation of `From` for converting `errno::Errno` to and from + `nix::errno::Errno`. +- Internal dependencies: + - nix 0.29.0 + ## [0.5.0] - 2024-12-14 ### Changed diff --git a/yash-env/Cargo.toml b/yash-env/Cargo.toml index 3aa503ed..df63815d 100644 --- a/yash-env/Cargo.toml +++ b/yash-env/Cargo.toml @@ -35,7 +35,6 @@ yash-syntax = { path = "../yash-syntax", version = "0.14.0", features = [ [target.'cfg(unix)'.dependencies] libc = { version = "0.2.169", default-features = false } -nix = { version = "0.29.0", features = ["fs", "signal", "user"] } yash-executor = { path = "../yash-executor", version = "1.0.0" } [dev-dependencies] diff --git a/yash-env/src/system/errno.rs b/yash-env/src/system/errno.rs index aafe6056..f9a352fe 100644 --- a/yash-env/src/system/errno.rs +++ b/yash-env/src/system/errno.rs @@ -410,28 +410,6 @@ impl From for Errno { } } -/// Converts [`Errno`] to [`nix::Error`]. -/// -/// This conversion is only available on Unix-like systems. -#[cfg(unix)] -impl From for nix::Error { - #[inline] - fn from(errno: Errno) -> Self { - Self::from_raw(errno.0) - } -} - -/// Converts [`nix::Error`] to [`Errno`]. -/// -/// This conversion is only available on Unix-like systems. -#[cfg(unix)] -impl From for Errno { - #[inline] - fn from(error: nix::Error) -> Self { - Self(error as RawErrno) - } -} - impl From for std::io::Error { #[inline] fn from(errno: Errno) -> Self {