diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 7a77066..da84d9e 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -117,9 +117,12 @@ jobs: run: cargo build --all-targets - name: cargo test run: cargo test --all-targets - tests-windows: - name: Tests, Windows - runs-on: windows-latest + build-and-test: + name: Build and test on ${{ matrix.host }} + runs-on: ${{ matrix.host }} + strategy: + matrix: + host: [windows-latest, macos-latest] steps: - name: Check out repository uses: actions/checkout@v5 diff --git a/src/cmdext.rs b/src/cmdext.rs index fb40603..2fabe33 100644 --- a/src/cmdext.rs +++ b/src/cmdext.rs @@ -87,7 +87,7 @@ impl CapStdExtCommandExt for std::process::Command { } } -#[cfg(test)] +#[cfg(all(test, any(target_os = "android", target_os = "linux")))] mod tests { use super::*; use std::sync::Arc; @@ -99,8 +99,13 @@ mod tests { let tempd = cap_tempfile::TempDir::new(cap_std::ambient_authority())?; let tempd_fd = Arc::new(tempd.as_fd().try_clone_to_owned()?); let n = tempd_fd.as_raw_fd() + i; - let st = std::process::Command::new("ls") - .arg(format!("/proc/self/fd/{n}")) + #[cfg(any(target_os = "android", target_os = "linux"))] + let path = format!("/proc/self/fd/{n}"); + #[cfg(not(any(target_os = "android", target_os = "linux")))] + let path = format!("/dev/fd/{n}"); + let st = std::process::Command::new("/usr/bin/env") + .arg("readlink") + .arg(path) .take_fd_n(tempd_fd, n) .status()?; assert!(st.success()); diff --git a/src/dirext.rs b/src/dirext.rs index f98d622..078ed3d 100644 --- a/src/dirext.rs +++ b/src/dirext.rs @@ -244,16 +244,16 @@ pub trait CapStdExtDirExt { /// to determine, and `None` will be returned in those cases. fn is_mountpoint(&self, path: impl AsRef) -> Result>; - #[cfg(not(windows))] + #[cfg(any(target_os = "android", target_os = "linux"))] /// Get the value of an extended attribute. If the attribute is not present, /// this function will return `Ok(None)`. fn getxattr(&self, path: impl AsRef, key: impl AsRef) -> Result>>; - #[cfg(not(windows))] + #[cfg(any(target_os = "android", target_os = "linux"))] /// List all extended attribute keys for this path. fn listxattrs(&self, path: impl AsRef) -> Result; - #[cfg(not(windows))] + #[cfg(any(target_os = "android", target_os = "linux"))] /// Set the value of an extended attribute. fn setxattr( &self, @@ -614,6 +614,10 @@ where // Ensure that the target path isn't absolute, and doesn't // have any parent references. +#[cfg_attr( + not(any(target_os = "android", target_os = "linux", test)), + allow(dead_code) +)] pub(crate) fn validate_relpath_no_uplinks(path: &Path) -> Result<&Path> { let is_absolute = path.is_absolute(); let contains_uplinks = path @@ -828,17 +832,17 @@ impl CapStdExtDirExt for Dir { is_mountpoint_impl_statx(self, path.as_ref()).map_err(Into::into) } - #[cfg(not(windows))] + #[cfg(any(target_os = "android", target_os = "linux"))] fn getxattr(&self, path: impl AsRef, key: impl AsRef) -> Result>> { crate::xattrs::impl_getxattr(self, path.as_ref(), key.as_ref()) } - #[cfg(not(windows))] + #[cfg(any(target_os = "android", target_os = "linux"))] fn listxattrs(&self, path: impl AsRef) -> Result { crate::xattrs::impl_listxattrs(self, path.as_ref()) } - #[cfg(not(windows))] + #[cfg(any(target_os = "android", target_os = "linux"))] fn setxattr( &self, path: impl AsRef, diff --git a/src/lib.rs b/src/lib.rs index 0aabca9..e78618f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,12 +22,16 @@ pub mod dirext; mod rootdir; #[cfg(any(target_os = "android", target_os = "linux"))] pub use rootdir::*; -#[cfg(not(windows))] +#[cfg(any(target_os = "android", target_os = "linux"))] mod xattrs; -#[cfg(not(windows))] +#[cfg(any(target_os = "android", target_os = "linux"))] pub use xattrs::XattrList; #[cold] +#[cfg_attr( + not(any(target_os = "android", target_os = "linux", test)), + allow(dead_code) +)] pub(crate) fn escape_attempt() -> io::Error { io::Error::new( io::ErrorKind::PermissionDenied, diff --git a/tests/it/main.rs b/tests/it/main.rs index 214592c..a745b91 100644 --- a/tests/it/main.rs +++ b/tests/it/main.rs @@ -12,6 +12,7 @@ use cap_std_ext::RootDir; #[cfg(unix)] use rustix::path::DecInt; use std::cmp::Ordering; +#[cfg(any(target_os = "android", target_os = "linux"))] use std::ffi::OsStr; use std::io::Write; use std::ops::ControlFlow; @@ -33,7 +34,8 @@ fn take_fd() -> Result<()> { c.stdout(std::process::Stdio::piped()); let s = c.output()?; assert!(s.status.success()); - assert_eq!(s.stdout.as_slice(), b"11\n"); + let out = String::from_utf8_lossy(&s.stdout); + assert_eq!(out.trim(), "11"); Ok(()) } @@ -43,7 +45,10 @@ fn fchdir() -> Result<()> { static CONTENTS: &[u8] = b"hello world"; fn new_cmd() -> Command { + #[cfg(any(target_os = "android", target_os = "linux"))] let mut c = Command::new("/usr/bin/cat"); + #[cfg(not(any(target_os = "android", target_os = "linux")))] + let mut c = Command::new("/bin/cat"); c.arg("somefile"); c } @@ -718,7 +723,7 @@ fn test_walk_noxdev() -> Result<()> { } #[test] -#[cfg(not(windows))] +#[cfg(any(target_os = "android", target_os = "linux"))] fn test_xattrs() -> Result<()> { use std::os::unix::ffi::OsStrExt; @@ -779,7 +784,7 @@ fn test_xattrs() -> Result<()> { } #[test] -#[cfg(not(windows))] +#[cfg(any(target_os = "android", target_os = "linux"))] fn test_big_xattr() -> Result<()> { let td = &cap_tempfile::TempDir::new(cap_std::ambient_authority())?;