Skip to content

Commit

Permalink
Remove nix dependency from yash-env (#444)
Browse files Browse the repository at this point in the history
I want to completely remove the nix crate dependency from the yash-env crate. I find nix unreliable because of its careless use of MaybeUninit::assume_init (and similar functions) and the drastic changes sometimes made to the API. Nix has been transitioning to use AsFd instead of RawFd for functions that require a valid FD, which is incompatible with our use of raw FDs for RealSystem.
  • Loading branch information
magicant authored Jan 12, 2025
2 parents 8a58f1f + 1405b30 commit 1ca1143
Show file tree
Hide file tree
Showing 18 changed files with 509 additions and 471 deletions.
7 changes: 4 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions yash-env/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,26 @@ 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

- `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

### 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
Expand Down
3 changes: 2 additions & 1 deletion yash-env/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -33,7 +34,7 @@ yash-syntax = { path = "../yash-syntax", version = "0.14.0", features = [
] }

[target.'cfg(unix)'.dependencies]
nix = { version = "0.29.0", features = ["fs", "signal", "user"] }
libc = { version = "0.2.169", default-features = false }
yash-executor = { path = "../yash-executor", version = "1.0.0" }

[dev-dependencies]
Expand Down
5 changes: 1 addition & 4 deletions yash-env/src/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion yash-env/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Option<PathBuf>>;
fn getpwnam_dir(&self, name: &CStr) -> Result<Option<PathBuf>>;

/// Returns the standard `$PATH` value where all standard utilities are
/// expected to be found.
Expand Down
182 changes: 88 additions & 94 deletions yash-env/src/system/errno.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down Expand Up @@ -394,25 +394,19 @@ impl From<RawErrno> for Errno {
}
}

/// Converts [`Errno`] to [`nix::Error`].
///
/// This conversion is only available on Unix-like systems.
#[cfg(unix)]
impl From<Errno> for nix::Error {
/// Converts [`Errno`] to [`errno::Errno`].
impl From<Errno> for errno::Errno {
#[inline]
fn from(errno: Errno) -> Self {
Self::from_raw(errno.0)
Self(errno.0)
}
}

/// Converts [`nix::Error`] to [`Errno`].
///
/// This conversion is only available on Unix-like systems.
#[cfg(unix)]
impl From<nix::Error> for Errno {
/// Converts [`errno::Errno`] to [`Errno`].
impl From<errno::Errno> for Errno {
#[inline]
fn from(error: nix::Error) -> Self {
Self(error as RawErrno)
fn from(errno: errno::Errno) -> Self {
Self(errno.into())
}
}

Expand Down
Loading

0 comments on commit 1ca1143

Please sign in to comment.