Skip to content

Commit

Permalink
[cap-primitives] add support for illumos (#369)
Browse files Browse the repository at this point in the history
Get the cap-primitives library building and passing all tests on illumos. There
were just a couple of minor tweaks required.

I also ran into an issue where the minimum version of `ipnet` required was too
old, so I took the liberty to bump it to 2.5.0 which has `IpNet::new`.

The note in `dir_entry.rs` is copied over from Rust's std:
https://doc.rust-lang.org/std/fs/struct.DirEntry.html#method.file_type
  • Loading branch information
sunshowers authored Oct 30, 2024
1 parent 9ec2ba7 commit ef0c8ac
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 7 deletions.
4 changes: 2 additions & 2 deletions cap-primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ edition = "2021"
[dependencies]
ambient-authority = "0.0.2"
arbitrary = { version = "1.0.0", optional = true, features = ["derive"] }
ipnet = "2.3.0"
ipnet = "2.5.0"
maybe-owned = "0.3.4"
fs-set-times = "0.20.0"
io-extras = "0.18.0"
Expand All @@ -25,7 +25,7 @@ io-lifetimes = { version = "2.0.0", default-features = false }
cap-tempfile = { path = "../cap-tempfile" }

[target.'cfg(not(windows))'.dependencies]
rustix = { version = "0.38.32", features = ["fs", "process", "procfs", "termios", "time"] }
rustix = { version = "0.38.38", features = ["fs", "process", "procfs", "termios", "time"] }

[target.'cfg(windows)'.dependencies]
winx = "0.36.0"
Expand Down
6 changes: 6 additions & 0 deletions cap-primitives/src/fs/dir_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ impl DirEntry {
/// Returns the file type for the file that this entry points at.
///
/// This corresponds to [`std::fs::DirEntry::file_type`].
///
/// # Platform-specific behavior
///
/// On Windows and most Unix platforms this function is free (no extra system calls needed), but
/// some Unix platforms may require the equivalent call to `metadata` to learn about the target
/// file type.
#[inline]
pub fn file_type(&self) -> io::Result<FileType> {
self.inner.file_type()
Expand Down
13 changes: 11 additions & 2 deletions cap-primitives/src/rustix/fs/dir_entry_inner.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::fs::{
FileType, FollowSymlinks, ImplFileTypeExt, Metadata, MetadataExt, OpenOptions, ReadDir,
ReadDirInner,
FileType, FollowSymlinks, Metadata, MetadataExt, OpenOptions, ReadDir, ReadDirInner,
};
use rustix::fs::DirEntry;
use std::ffi::{OsStr, OsString};
Expand Down Expand Up @@ -41,9 +40,12 @@ impl DirEntryInner {
self.read_dir.remove_dir(self.file_name_bytes())
}

#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
#[inline]
#[allow(clippy::unnecessary_wraps)]
pub(crate) fn file_type(&self) -> io::Result<FileType> {
use crate::fs::ImplFileTypeExt;

Ok(match self.rustix.file_type() {
rustix::fs::FileType::Directory => FileType::dir(),
rustix::fs::FileType::RegularFile => FileType::file(),
Expand All @@ -58,6 +60,13 @@ impl DirEntryInner {
})
}

#[cfg(any(target_os = "illumos", target_os = "solaris"))]
#[inline]
pub(crate) fn file_type(&self) -> io::Result<FileType> {
// These platforms don't have the file type on the dirent, so we must lstat the file.
self.metadata().map(|m| m.file_type())
}

#[inline]
pub(crate) fn file_name(&self) -> OsString {
self.file_name_bytes().to_os_string()
Expand Down
2 changes: 2 additions & 0 deletions cap-primitives/src/rustix/fs/dir_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ pub(crate) const fn target_o_path() -> OFlags {
target_os = "netbsd",
target_os = "openbsd",
target_os = "wasi",
target_os = "illumos",
target_os = "solaris",
))]
{
OFlags::empty()
Expand Down
10 changes: 7 additions & 3 deletions cap-primitives/src/rustix/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,13 @@ fn tty_path() {
#[cfg(unix)]
use std::os::unix::fs::FileTypeExt;

// On FreeBSD, /dev/{tty,stdin,stdout,stderr} are aliases to different real
// devices.
let paths: &[&str] = if cfg!(target_os = "freebsd") {
// On FreeBSD, /dev/{tty,stdin,stdout,stderr} are aliases to different
// real devices.
&["/dev/ttyv0", "/dev/pts/0"]
} else if cfg!(target_os = "illumos") {
// On illumos, /dev/std{in,out,err} only exist if they're open.
&["/dev/tty", "/dev/pts/0"]
} else {
&["/dev/tty", "/dev/stdin", "/dev/stdout", "/dev/stderr"]
};
Expand All @@ -162,7 +165,8 @@ fn tty_path() {
.as_ref()
.map(std::fs::canonicalize)
.map(Result::unwrap),
Some(canonical)
Some(canonical),
"for path {path}, file_path matches canonicalized path"
);
}
}
Expand Down

0 comments on commit ef0c8ac

Please sign in to comment.