Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace OFlag & Mode with nix-independent type #389

Merged
merged 17 commits into from
Jul 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

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

9 changes: 5 additions & 4 deletions yash-builtin/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ mod tests {
use std::cell::RefCell;
use std::rc::Rc;
use yash_env::system::r#virtual::{FileBody, INode};
use yash_env::system::Mode;
use yash_env::variable::{Scope, PATH};
use yash_env::VirtualSystem;

Expand All @@ -164,7 +165,7 @@ mod tests {
content: Vec::new(),
is_native_executable: true,
};
content.permissions.0 |= 0o100;
content.permissions.set(Mode::USER_EXEC, true);
let content = Rc::new(RefCell::new(content));
system
.state
Expand Down Expand Up @@ -199,7 +200,7 @@ mod tests {
content: Vec::new(),
is_native_executable: true,
};
content.permissions.0 |= 0o100;
content.permissions.set(Mode::USER_EXEC, true);
let content = Rc::new(RefCell::new(content));
system
.state
Expand Down Expand Up @@ -234,7 +235,7 @@ mod tests {
content: Vec::new(),
is_native_executable: true,
};
content.permissions.0 |= 0o100;
content.permissions.set(Mode::USER_EXEC, true);
let content = Rc::new(RefCell::new(content));
system
.state
Expand Down Expand Up @@ -264,7 +265,7 @@ mod tests {
content: Vec::new(),
is_native_executable: true,
};
content.permissions.0 |= 0o100;
content.permissions.set(Mode::USER_EXEC, true);
let content = Rc::new(RefCell::new(content));
system
.state
Expand Down
10 changes: 8 additions & 2 deletions yash-builtin/src/source/semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ use yash_env::semantics::Field;
use yash_env::stack::Frame;
use yash_env::system::Errno;
use yash_env::system::Mode;
use yash_env::system::OFlag;
use yash_env::system::OfdAccess;
use yash_env::system::OpenFlag;
use yash_env::system::System;
use yash_env::system::SystemEx as _;
use yash_env::variable::PATH;
Expand Down Expand Up @@ -116,7 +117,12 @@ fn find_and_open_file(env: &mut Env, filename: &str) -> Result<Fd, Errno> {
/// least [`MIN_INTERNAL_FD`](yash_env::io::MIN_INTERNAL_FD).
fn open_file<S: System>(system: &mut S, path: &CStr) -> Result<Fd, Errno> {
system
.open(path, OFlag::O_RDONLY | OFlag::O_CLOEXEC, Mode::empty())
.open(
path,
OfdAccess::ReadOnly,
OpenFlag::Cloexec.into(),
Mode::empty(),
)
.and_then(|fd| system.move_fd_internal(fd))
}

Expand Down
9 changes: 7 additions & 2 deletions yash-cli/src/startup/init_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use yash_env::io::Fd;
use yash_env::option::Option::Interactive;
use yash_env::option::State::Off;
use yash_env::stack::Frame;
use yash_env::system::{Errno, Mode, OFlag, SystemEx};
use yash_env::system::{Errno, Mode, OfdAccess, OpenFlag, SystemEx};
use yash_env::variable::ENV;
use yash_env::Env;
use yash_env::System;
Expand Down Expand Up @@ -146,7 +146,12 @@ pub async fn run_init_file(env: &mut Env, path: &str) {

fn open_fd<S: System>(system: &mut S, path: String) -> Result<Fd, Errno> {
let c_path = CString::new(path).map_err(|_| Errno::EILSEQ)?;
let fd = system.open(&c_path, OFlag::O_RDONLY | OFlag::O_CLOEXEC, Mode::empty())?;
let fd = system.open(
&c_path,
OfdAccess::ReadOnly,
OpenFlag::Cloexec.into(),
Mode::empty(),
)?;
system.move_fd_internal(fd)
}

Expand Down
12 changes: 9 additions & 3 deletions yash-cli/src/startup/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ use yash_env::option::Option::Interactive;
use yash_env::option::State::On;
use yash_env::system::Errno;
use yash_env::system::Mode;
use yash_env::system::OFlag;
use yash_env::system::OfdAccess;
use yash_env::system::OpenFlag;
use yash_env::system::SystemEx as _;
use yash_env::Env;
use yash_env::System;
Expand Down Expand Up @@ -89,7 +90,7 @@ pub fn prepare_input<'a>(
// since we will be doing non-blocking reads anyway,
// but POSIX requires us to do it.
// https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/sh.html#tag_20_117_06
system.set_blocking(Fd::STDIN).ok();
_ = system.get_and_set_nonblocking(Fd::STDIN, false);
}

let reader = FdReader::new(Fd::STDIN, system);
Expand All @@ -110,7 +111,12 @@ pub fn prepare_input<'a>(
path,
})?;
let fd = system
.open(&c_path, OFlag::O_RDONLY | OFlag::O_CLOEXEC, Mode::empty())
.open(
&c_path,
OfdAccess::ReadOnly,
OpenFlag::Cloexec.into(),
Mode::empty(),
)
.and_then(|fd| system.move_fd_internal(fd))
.map_err(|errno| PrepareInputError { errno, path })?;

Expand Down
30 changes: 27 additions & 3 deletions yash-env/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- The `Uid`, `RawUid`, `Gid`, and `RawGid` types in the `system` module
- The `System` trait now has the `getuid`, `geteuid`, `getgid`, and `getegid`
methods.
- The `OfdAccess`, `OpenFlag`, `Mode`, `RawMode`, `Uid`, `RawUid`, `Gid`, and
`RawGid` types in the `system` module
- The `System` trait now has the `ofd_access`, `get_and_set_nonblocking`,
`getuid`, `geteuid`, `getgid`, and `getegid` methods.
- `Mode` has been moved from `system::virtual` to `system` and now has constants
with more human-friendly names, e.g., `USER_READ` and `GROUP_WRITE`.
- The `system::virtual::Process` struct now has the getters/setters for the
real/effective user/group IDs: `uid`, `set_uid`, `euid`, `set_euid`, `gid`,
`set_gid`, `egid`, and `set_egid`.
- The `stack::Frame` enum now has the `InitFile` variant.
- External dependencies:
- enumset 1.1.2 (previously an internal dependency)
- Internal dependencies:
- bitflags 2.6.0

### Changed

- `system::Mode` is no longer a re-export of `nix::sys::stat::Mode`.
- The `system::System::open` method has been redefined to take `OfdAccess` and
`OpenFlag` parameters instead of `nix::fcntl::OFlag`.
- The `system::System::umask` method now takes and returns a value of the new
`system::Mode` type.

### Deprecated

- `system::virtual::Mode` in favor of `system::Mode`

### Removed

- The `system` module no longer reexports `nix::fcntl::OFlag`.
- The `fcntl_getfl` and `fcntl_setfl` methods from the `System` trait

## [0.2.1] - 2024-07-12

Expand Down
1 change: 1 addition & 0 deletions yash-env/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ categories = ["command-line-utilities"]
[dependencies]
annotate-snippets = "0.11.4"
async-trait = "0.1.73"
bitflags = "2.6.0"
either = "1.9.0"
enumset = "1.1.2"
futures-util = "0.3.28"
Expand Down
12 changes: 10 additions & 2 deletions yash-env/src/input/fd_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ mod tests {
use crate::system::r#virtual::VirtualSystem;
use crate::system::Errno;
use crate::system::Mode;
use crate::system::OFlag;
use crate::system::OfdAccess;
use crate::system::OpenFlag;
use crate::System;
use assert_matches::assert_matches;
use futures_util::FutureExt;
Expand Down Expand Up @@ -219,7 +220,14 @@ mod tests {
}
let mut system = SharedSystem::new(Box::new(system));
let path = c"/foo";
let fd = system.open(path, OFlag::O_RDONLY, Mode::empty()).unwrap();
let fd = system
.open(
path,
OfdAccess::ReadOnly,
OpenFlag::Cloexec.into(),
Mode::empty(),
)
.unwrap();
let mut reader = FdReader::new(fd, system);

let line = reader
Expand Down
3 changes: 2 additions & 1 deletion yash-env/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,8 @@ impl Env {

let first_fd = self.system.open(
c"/dev/tty",
crate::system::OFlag::O_RDWR | crate::system::OFlag::O_CLOEXEC,
crate::system::OfdAccess::ReadWrite,
crate::system::OpenFlag::Cloexec.into(),
crate::system::Mode::empty(),
)?;
let final_fd = self.system.move_fd_internal(first_fd);
Expand Down
75 changes: 26 additions & 49 deletions yash-env/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

mod errno;
pub mod fd_set;
mod file_system;
mod id;
mod open_flag;
pub mod real;
pub mod resource;
mod select;
Expand All @@ -29,10 +31,17 @@ pub use self::errno::Errno;
pub use self::errno::RawErrno;
pub use self::errno::Result;
use self::fd_set::FdSet;
pub use self::file_system::Dir;
pub use self::file_system::DirEntry;
pub use self::file_system::Mode;
pub use self::file_system::RawMode;
pub use self::file_system::AT_FDCWD;
pub use self::id::Gid;
pub use self::id::RawGid;
pub use self::id::RawUid;
pub use self::id::Uid;
pub use self::open_flag::OfdAccess;
pub use self::open_flag::OpenFlag;
#[cfg(doc)]
use self::r#virtual::VirtualSystem;
#[cfg(doc)]
Expand All @@ -52,23 +61,21 @@ use crate::signal;
use crate::subshell::Subshell;
use crate::trap::SignalSystem;
use crate::Env;
use enumset::EnumSet;
#[doc(no_inline)]
pub use nix::fcntl::AtFlags;
#[doc(no_inline)]
pub use nix::fcntl::FdFlag;
#[doc(no_inline)]
pub use nix::fcntl::OFlag;
#[doc(no_inline)]
pub use nix::sys::signal::SigmaskHow;
#[doc(no_inline)]
pub use nix::sys::stat::{FileStat, Mode, SFlag};
pub use nix::sys::stat::{FileStat, SFlag};
#[doc(no_inline)]
pub use nix::sys::time::TimeSpec;
use std::convert::Infallible;
use std::ffi::c_int;
use std::ffi::CStr;
use std::ffi::CString;
use std::ffi::OsStr;
use std::ffi::OsString;
use std::fmt::Debug;
use std::future::Future;
Expand Down Expand Up @@ -125,7 +132,13 @@ pub trait System: Debug {
/// Opens a file descriptor.
///
/// This is a thin wrapper around the `open` system call.
fn open(&mut self, path: &CStr, option: OFlag, mode: Mode) -> Result<Fd>;
fn open(
&mut self,
path: &CStr,
access: OfdAccess,
flags: EnumSet<OpenFlag>,
mode: Mode,
) -> Result<Fd>;

/// Opens a file descriptor associated with an anonymous temporary file.
///
Expand All @@ -140,15 +153,15 @@ pub trait System: Debug {
/// This function returns `Ok(())` when the FD is already closed.
fn close(&mut self, fd: Fd) -> Result<()>;

/// Returns the file status flags for the open file description.
///
/// This is a thin wrapper around the `fcntl` system call.
fn fcntl_getfl(&self, fd: Fd) -> Result<OFlag>;
/// Returns the open file description access mode.
fn ofd_access(&self, fd: Fd) -> Result<OfdAccess>;

/// Sets the file status flags for the open file description.
/// Gets and sets the non-blocking mode for the open file description.
///
/// This is a thin wrapper around the `fcntl` system call.
fn fcntl_setfl(&mut self, fd: Fd, flags: OFlag) -> Result<()>;
/// This is a wrapper around the `fcntl` system call.
/// This function sets the non-blocking mode to the given value and returns
/// the previous mode.
fn get_and_set_nonblocking(&mut self, fd: Fd, nonblocking: bool) -> Result<bool>;

/// Returns the attributes for the file descriptor.
///
Expand Down Expand Up @@ -201,7 +214,7 @@ pub trait System: Debug {
/// You cannot tell the current mask without setting a new one. If you only
/// want to get the current mask, you need to set it back to the original
/// value after getting it.
fn umask(&mut self, mask: Mode) -> Mode;
fn umask(&mut self, new_mask: Mode) -> Mode;

/// Returns the current time.
#[must_use]
Expand Down Expand Up @@ -463,12 +476,6 @@ pub trait System: Debug {
fn setrlimit(&mut self, resource: Resource, limits: LimitPair) -> std::io::Result<()>;
}

/// Sentinel for the current working directory
///
/// This value can be passed to system calls named "*at" such as
/// [`System::fstatat`].
pub const AT_FDCWD: Fd = Fd(nix::libc::AT_FDCWD);

/// Set of consumed CPU time
///
/// This structure contains four CPU time values, all in seconds.
Expand Down Expand Up @@ -531,26 +538,6 @@ pub type ChildProcessStarter = Box<
dyn for<'a> FnOnce(&'a mut Env, ChildProcessTask) -> Pin<Box<dyn Future<Output = Pid> + 'a>>,
>;

/// Metadata of a file contained in a directory
///
/// `DirEntry` objects are enumerated by a [`Dir`] implementor.
#[derive(Clone, Copy, Debug)]
#[non_exhaustive]
pub struct DirEntry<'a> {
/// Filename
pub name: &'a OsStr,
}

/// Trait for enumerating directory entries
///
/// An implementor of `Dir` may retain a file descriptor (or any other resource
/// alike) to access the underlying system and obtain entry information. The
/// file descriptor is released when the implementor object is dropped.
pub trait Dir: Debug {
/// Returns the next directory entry.
fn next(&mut self) -> Result<Option<DirEntry>>;
}

/// Extension for [`System`]
///
/// This trait provides some extension methods for `System`.
Expand Down Expand Up @@ -590,16 +577,6 @@ pub trait SystemEx: System {
if SFlag::from_bits_truncate(stat.st_mode) & SFlag::S_IFMT == SFlag::S_IFIFO)
}

/// Clears the `O_NONBLOCK` flag for the file descriptor.
fn set_blocking(&mut self, fd: Fd) -> Result<()> {
let flags = self.fcntl_getfl(fd)?;
let new_flags = flags & !OFlag::O_NONBLOCK;
if new_flags == flags {
return Ok(());
}
self.fcntl_setfl(fd, new_flags)
}

/// Switches the foreground process group with SIGTTOU blocked.
///
/// This is a convenience function to change the foreground process group
Expand Down
Loading
Loading