diff --git a/Cargo.lock b/Cargo.lock index 8d0655551e..9dcca7e3f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -523,6 +523,7 @@ dependencies = [ "pretty_assertions", "rand 0.10.3", "regex", + "rlimit", "rstest", "rstest_reuse", "rustc-hash", @@ -2477,6 +2478,15 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" +[[package]] +name = "rlimit" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f35ee2729c56bb610f6dba436bf78135f728b7373bdffae2ec815b2d3eb98cc3" +dependencies = [ + "libc", +] + [[package]] name = "roff" version = "1.1.1" @@ -4488,6 +4498,7 @@ dependencies = [ "pretty_assertions", "rand 0.10.3", "regex", + "rlimit", "rustix", "tempfile", "uucore", diff --git a/Cargo.toml b/Cargo.toml index ecba1f96c4..d93aba7796 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,6 +113,7 @@ rand = { version = "0.10.1", features = ["std_rng"] } rand_chacha = { version = "0.10.0" } rayon = "1.10" regex = "1.10.4" +rlimit = "0.11.0" rstest = "0.28.0" rstest_reuse = "0.7.0" rustc-hash = "2.1.1" @@ -394,6 +395,9 @@ runcon = { optional = true, version = "0.13.0", package = "uu_runcon", path = "s nix = { workspace = true, features = ["fs", "signal"] } rustix = { workspace = true, features = ["net", "process"] } +[target.'cfg(all(unix, not(target_os = "fuchsia")))'.dev-dependencies] +rlimit = { workspace = true } + [build-dependencies] phf_codegen.workspace = true diff --git a/tests/by-util/test_cat.rs b/tests/by-util/test_cat.rs index 877d361bc5..002fcdc104 100644 --- a/tests/by-util/test_cat.rs +++ b/tests/by-util/test_cat.rs @@ -3,10 +3,10 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore Nofile nonewline cmdline setrlimit ELOOP bcde acde +// spell-checker:ignore NOFILE nonewline cmdline setrlimit ELOOP bcde acde -#[cfg(any(target_os = "linux", target_os = "android"))] -use rustix::process::Resource; +#[cfg(target_os = "linux")] +use rlimit::Resource; #[cfg(unix)] use std::fs::File; use std::fs::OpenOptions; @@ -121,7 +121,6 @@ fn test_fifo_symlink() { #[test] // TODO(#7542): Re-enable on Android once we figure out why setting limit is broken. -// #[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(target_os = "linux")] #[cfg_attr(wasi_runner, ignore = "WASI: rlimit/setrlimit not supported")] fn test_closes_file_descriptors() { @@ -135,7 +134,7 @@ fn test_closes_file_descriptors() { "alpha.txt", "alpha.txt", ]) - .limit(Resource::Nofile, 9, 9) + .limit(Resource::NOFILE, 9, 9) .succeeds(); } diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index f0400cc3d2..57ea5225e1 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -3,7 +3,7 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore (flags) reflink (fs) tmpfs (linux) filefrag rlimit Rlim Nofile Fsize SIGXFSZ clob btrfs neve ROOTDIR USERDIR outfile subvolume uufs xattrs ELOOP +// spell-checker:ignore (flags) reflink (fs) tmpfs (linux) filefrag rlimit Rlim NOFILE FSIZE SIGXFSZ clob btrfs neve ROOTDIR USERDIR outfile subvolume uufs xattrs ELOOP // spell-checker:ignore bdfl hlsl IRWXO IRWXG nconfined matchpathcon libselinux-devel prwx doesnotexist reftests subdirs mksocket srwx dstlink mcstransd use rstest::rstest; @@ -3370,7 +3370,7 @@ fn test_cp_reflink_insufficient_permission() { #[cfg(target_os = "linux")] #[test] fn test_closes_file_descriptors() { - use rustix::process::Resource; + use rlimit::Resource; let pid = std::process::id(); let fd_path = format!("/proc/{pid}/fd"); @@ -3390,7 +3390,7 @@ fn test_closes_file_descriptors() { .arg("--reflink=auto") .arg("dir_with_10_files/") .arg("dir_with_10_files_new/") - .limit(Resource::Nofile, limit_fd, limit_fd) + .limit(Resource::NOFILE, limit_fd, limit_fd) .succeeds(); } @@ -3400,7 +3400,7 @@ fn test_closes_file_descriptors() { #[cfg(not(wasi_runner))] // linux specific #[test] fn test_cp_failed_write_does_not_spill_into_next_file() { - use rustix::process::Resource; + use rlimit::Resource; const CAP: u64 = 100 * 1024; @@ -3410,7 +3410,7 @@ fn test_cp_failed_write_does_not_spill_into_next_file() { at.write("small2", "another small file\n"); at.mkdir("out"); ucmd.args(&["--reflink=never", "big", "small", "small2", "out"]) - .limit(Resource::Fsize, CAP, CAP) + .limit(Resource::FSIZE, CAP, CAP) .ignore_sigxfsz() .fails() .stderr_contains("'big'"); diff --git a/tests/by-util/test_dd.rs b/tests/by-util/test_dd.rs index 6b344eb886..e8b9172beb 100644 --- a/tests/by-util/test_dd.rs +++ b/tests/by-util/test_dd.rs @@ -3,7 +3,7 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore fname, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile, fullblock, urand, fileio, atoe, atoibm, availible, behaviour, bmax, bremain, btotal, cflags, creat, ctable, ctty, datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, iseek, nocache, noctty, noerror, nofollow, nolinks, nonblock, oconvflags, oseek, outfile, parseargs, rlen, rmax, rposition, rremain, rsofar, rstat, sigusr, sigval, wlen, wstat abcdefghijklm abcdefghi nabcde nabcdefg abcdefg fifoname FADV DONTNEED Fsize SIGXFSZ rusage maxrss cdefg ncdefg cdefh memfd ftruncate +// spell-checker:ignore fname, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile, fullblock, urand, fileio, atoe, atoibm, availible, behaviour, bmax, bremain, btotal, cflags, creat, ctable, ctty, datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, iseek, nocache, noctty, noerror, nofollow, nolinks, nonblock, oconvflags, oseek, outfile, parseargs, rlen, rmax, rposition, rremain, rsofar, rstat, sigusr, sigval, wlen, wstat abcdefghijklm abcdefghi nabcde nabcdefg abcdefg fifoname FADV DONTNEED FSIZE SIGXFSZ rusage maxrss cdefg ncdefg cdefh memfd ftruncate use rstest::rstest; use uutests::at_and_ucmd; @@ -2381,14 +2381,14 @@ fn test_count_bytes_with_expanding_block_conv() { #[test] #[cfg(all(unix, not(target_vendor = "apple")))] fn test_stats_are_reported_when_a_write_fails() { - use rustix::process::Resource; + use rlimit::Resource; const CAP: u64 = 768 * 1024; let (at, mut ucmd) = at_and_ucmd!(); let result = ucmd .args(&["if=/dev/zero", "of=capped.bin", "bs=512K", "count=3"]) - .limit(Resource::Fsize, CAP, CAP) + .limit(Resource::FSIZE, CAP, CAP) .ignore_sigxfsz() .fails(); @@ -2404,7 +2404,7 @@ fn test_stats_are_reported_when_a_write_fails() { #[test] #[cfg(all(unix, not(target_vendor = "apple")))] fn test_block_stats_are_reported_when_a_write_fails() { - use rustix::process::Resource; + use rlimit::Resource; const CAP: u64 = 200 * 1024; @@ -2412,7 +2412,7 @@ fn test_block_stats_are_reported_when_a_write_fails() { let result = ucmd .args(&["conv=block", "cbs=1M", "obs=64K", "of=capped.bin"]) .pipe_in("x\n") - .limit(Resource::Fsize, CAP, CAP) + .limit(Resource::FSIZE, CAP, CAP) .ignore_sigxfsz() .fails(); diff --git a/tests/by-util/test_expand.rs b/tests/by-util/test_expand.rs index c943854b8b..22b2ac35e0 100644 --- a/tests/by-util/test_expand.rs +++ b/tests/by-util/test_expand.rs @@ -248,12 +248,12 @@ fn test_tabs_with_too_large_size() { )] #[test] fn test_large_tab_stop_without_tabs_does_not_allocate() { - use rustix::process::Resource; + use rlimit::Resource; const AS_LIMIT: u64 = 200 * 1024 * 1024; new_ucmd!() - .limit(Resource::As, AS_LIMIT, AS_LIMIT) + .limit(Resource::AS, AS_LIMIT, AS_LIMIT) .arg("--tabs=267672676527678256") .pipe_in("hello\n") .succeeds() diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index 97f925a4de..54bea7dec8 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -4,7 +4,7 @@ // file that was distributed with this source code. // spell-checker:ignore (words) READMECAREFULLY birthtime doesntexist oneline onetwo somebackup lrwx somefile somegroup somehiddenbackup somehiddenfile tabsize aaaaaaaa bbbb cccc dddddddd ncccc neee naaaaa nbcdef nfffff dired subdired tmpfs mdir COLORTERM mexe bcdef mfoo timefile -// spell-checker:ignore (words) fakeroot setcap drwxr bcdlps mdangling mentry awith acolons Nofile NOTCAPABLE iproduct newfstatat isox +// spell-checker:ignore (words) fakeroot setcap drwxr bcdlps mdangling mentry awith acolons NOFILE NOTCAPABLE iproduct newfstatat isox #![allow( clippy::similar_names, @@ -14,7 +14,7 @@ use regex::Regex; #[cfg(unix)] -use rustix::process::Resource; +use rlimit::Resource; #[cfg(not(target_os = "openbsd"))] use std::collections::HashMap; #[cfg(target_os = "linux")] @@ -8260,7 +8260,7 @@ fn test_ls_recursive_no_fd_leak() { .ucmd() .arg("-R") .arg("1") - .limit(Resource::Nofile, 20, 20) + .limit(Resource::NOFILE, 20, 20) .succeeds() .no_stderr(); } diff --git a/tests/by-util/test_pr.rs b/tests/by-util/test_pr.rs index e626f0cc55..d47e7e69b3 100644 --- a/tests/by-util/test_pr.rs +++ b/tests/by-util/test_pr.rs @@ -563,13 +563,13 @@ fn test_large_page_width_does_not_panic() { ignore = "WASI: wasmtime itself needs more memory than the guest's rlimit allows" )] fn test_offset_large_value_does_not_abort_under_memory_limit() { - use rustix::process::Resource; + use rlimit::Resource; use std::process::Stdio; const AS_LIMIT: u64 = 200 * 1024 * 1024; new_ucmd!() - .limit(Resource::As, AS_LIMIT, AS_LIMIT) + .limit(Resource::AS, AS_LIMIT, AS_LIMIT) .set_stdout(Stdio::null()) .args(&["-t", "-o", "999999999"]) .pipe_in("hi\n") diff --git a/tests/by-util/test_sort.rs b/tests/by-util/test_sort.rs index 0f149f517c..b93cc22f98 100644 --- a/tests/by-util/test_sort.rs +++ b/tests/by-util/test_sort.rs @@ -3,7 +3,7 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore (words) ints (linux) Nofile dfgi abmon avril naab +// spell-checker:ignore (words) ints (linux) NOFILE dfgi abmon avril naab #![allow(clippy::cast_possible_wrap)] @@ -14,6 +14,9 @@ use std::fmt::Write as FmtWrite; use std::process::Command; use std::time::Duration; +#[cfg(target_os = "linux")] +use rlimit::Resource; + use uutests::at_and_ucmd; use uutests::new_ucmd; use uutests::util::TestScenario; @@ -1729,14 +1732,13 @@ fn test_merge_batch_size() { // #[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(target_os = "linux")] fn test_merge_batch_size_with_limit() { - use rustix::process::Resource; // Currently need... // 3 descriptors for stdin, stdout, stderr // 2 descriptors for CTRL+C handling logic (to be reworked at some point) // 2 descriptors for the input files (i.e. batch-size of 2). let limit_fd = 3 + 2 + 2; new_ucmd!() - .limit(Resource::Nofile, limit_fd, limit_fd) + .limit(Resource::NOFILE, limit_fd, limit_fd) .arg("--batch-size=2") .arg("-m") .arg("--unique") @@ -1754,13 +1756,12 @@ fn test_merge_batch_size_with_limit() { // TODO(#7542): Re-enable on Android once we figure out why setting limit is broken. #[cfg(target_os = "linux")] fn test_batch_size_above_fd_limit_is_rejected() { - use rustix::process::Resource; // Only stdin, stdout and stderr are unavailable for merge inputs, so the // largest acceptable --batch-size is the soft limit minus 3, here 27 - 3. let limit_fd = 27; let (at, mut ucmd) = at_and_ucmd!(); at.write("gamma.txt", "delta\nalpha\n"); - ucmd.limit(Resource::Nofile, limit_fd, limit_fd) + ucmd.limit(Resource::NOFILE, limit_fd, limit_fd) .arg("--batch-size=31") .arg("gamma.txt") .fails_with_code(2) @@ -1772,12 +1773,11 @@ fn test_batch_size_above_fd_limit_is_rejected() { #[test] #[cfg(target_os = "linux")] fn test_batch_size_at_fd_limit_is_accepted() { - use rustix::process::Resource; let limit_fd = 27; let (at, mut ucmd) = at_and_ucmd!(); at.write("gamma.txt", "delta\nalpha\n"); // 24 is the largest value the limit above allows, and sorting must still happen. - ucmd.limit(Resource::Nofile, limit_fd, limit_fd) + ucmd.limit(Resource::NOFILE, limit_fd, limit_fd) .arg("--batch-size=24") .arg("gamma.txt") .succeeds() @@ -1787,7 +1787,6 @@ fn test_batch_size_at_fd_limit_is_accepted() { #[test] #[cfg(target_os = "linux")] fn test_merge_more_files_than_fd_limit() { - use rustix::process::Resource; let (at, mut ucmd) = at_and_ucmd!(); // 40 single-line files cannot all be open at once with a soft limit of 24, // so sort has to merge them in several batches through temporary files. @@ -1803,7 +1802,7 @@ fn test_merge_more_files_than_fd_limit() { writeln!(expected, "{i:02}").unwrap(); } let limit_fd = 24; - ucmd.limit(Resource::Nofile, limit_fd, limit_fd) + ucmd.limit(Resource::NOFILE, limit_fd, limit_fd) .arg("-m") .args(&names) .succeeds() @@ -1813,7 +1812,6 @@ fn test_merge_more_files_than_fd_limit() { #[test] #[cfg(target_os = "linux")] fn test_more_files_than_fd_limit() { - use rustix::process::Resource; let (at, mut ucmd) = at_and_ucmd!(); // The inputs are read one after another, so sorting must not need more open // file descriptors than the soft limit allows, no matter how many inputs there are. @@ -1829,7 +1827,7 @@ fn test_more_files_than_fd_limit() { writeln!(expected, "{i:02}").unwrap(); } let limit_fd = 24; - ucmd.limit(Resource::Nofile, limit_fd, limit_fd) + ucmd.limit(Resource::NOFILE, limit_fd, limit_fd) .args(&names) .succeeds() .stdout_only(expected); @@ -1838,7 +1836,6 @@ fn test_more_files_than_fd_limit() { #[test] #[cfg(target_os = "linux")] fn test_temporary_files_with_few_file_descriptors() { - use rustix::process::Resource; let ts = TestScenario::new("sort"); // Each input is larger than what the merge reads ahead, so it stays open. let mut names = Vec::new(); @@ -1857,20 +1854,20 @@ fn test_temporary_files_with_few_file_descriptors() { // Stdin, stdout, stderr, two merge inputs and the merge output. ts.ucmd() - .limit(Resource::Nofile, 6, 6) + .limit(Resource::NOFILE, 6, 6) .arg("-m") .args(&names) .succeeds() .stdout_only(&expected); ts.ucmd() - .limit(Resource::Nofile, 6, 6) + .limit(Resource::NOFILE, 6, 6) .args(&["-S", "64K", "unsorted"]) .succeeds() .stdout_only(&expected); // Starting the compress program can take two more for a moment: on musl and // glibc before 2.24, a failed exec is reported through a pipe. ts.ucmd() - .limit(Resource::Nofile, 10, 10) + .limit(Resource::NOFILE, 10, 10) .args(&["-S", "64K", "--compress-program", "gzip", "unsorted"]) .succeeds() .stdout_only(&expected); diff --git a/tests/by-util/test_split.rs b/tests/by-util/test_split.rs index 29a6a7dad5..dc33b6f5b3 100644 --- a/tests/by-util/test_split.rs +++ b/tests/by-util/test_split.rs @@ -3,12 +3,12 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore xzaaa sixhundredfiftyonebytes ninetyonebytes threebytes asciilowercase ghijkl mnopq rstuv wxyz fivelines twohundredfortyonebytes onehundredlines nbbbb dxen ncccc rlimit Nofile +// spell-checker:ignore xzaaa sixhundredfiftyonebytes ninetyonebytes threebytes asciilowercase ghijkl mnopq rstuv wxyz fivelines twohundredfortyonebytes onehundredlines nbbbb dxen ncccc rlimit NOFILE use rand::{RngExt as _, SeedableRng, rng}; use regex::Regex; -#[cfg(any(target_os = "linux", target_os = "android"))] -use rustix::process::Resource; +#[cfg(target_os = "linux")] +use rlimit::Resource; #[cfg(target_os = "linux")] use std::os::unix::ffi::OsStringExt; use std::path::Path; @@ -1731,12 +1731,11 @@ fn test_round_robin() { #[test] // TODO(#7542): Re-enable on Android once we figure out why rlimit is broken. -// #[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(target_os = "linux")] fn test_round_robin_limited_file_descriptors() { new_ucmd!() .args(&["-n", "r/40", "onehundredlines.txt"]) - .limit(Resource::Nofile, 9, 9) + .limit(Resource::NOFILE, 9, 9) .succeeds(); } diff --git a/tests/by-util/test_tee.rs b/tests/by-util/test_tee.rs index 00e30eada0..3595e22c8e 100644 --- a/tests/by-util/test_tee.rs +++ b/tests/by-util/test_tee.rs @@ -3,7 +3,7 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore nopipe Fsize Nofile sigxfsz +// spell-checker:ignore nopipe FSIZE NOFILE sigxfsz #![allow(clippy::borrow_as_ptr)] @@ -702,7 +702,7 @@ mod linux_only { /// Runs tee with 2 outputs that fail part-way, and checks that the bytes they did /// not take do not end up in the other outputs. fn check_failed_outputs_do_not_spill(open_file_limit: Option) { - use rustix::process::Resource; + use rlimit::Resource; const CAP: u64 = 100 * 1024; let (at, mut ucmd) = at_and_ucmd!(); @@ -713,10 +713,10 @@ mod linux_only { // through tee's 2nd pipe, which stdout and /dev/null keep using after it fails; // "capped2", the last output, through its 1st. ucmd.args(&["capped", "/dev/null", "capped2"]) - .limit(Resource::Fsize, CAP, CAP) + .limit(Resource::FSIZE, CAP, CAP) .ignore_sigxfsz(); if let Some(limit) = open_file_limit { - ucmd.limit(Resource::Nofile, limit, limit); + ucmd.limit(Resource::NOFILE, limit, limit); } let mut child = ucmd .set_stdin(std::fs::File::open(at.plus("in")).unwrap()) diff --git a/tests/uutests/Cargo.toml b/tests/uutests/Cargo.toml index ee810110c3..d4b6f5c805 100644 --- a/tests/uutests/Cargo.toml +++ b/tests/uutests/Cargo.toml @@ -18,8 +18,7 @@ all-features = true [lib] path = "src/lib/lib.rs" -[dependencies] -ctor = { workspace = true } +[target.'cfg(not(any(target_os = "aix", target_os = "horizon")))'.dependencies] libc = { workspace = true } pretty_assertions = { workspace = true } rand = { workspace = true } @@ -35,12 +34,18 @@ uucore = { workspace = true, features = [ [target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] -[target.'cfg(unix)'.dependencies] +[target.'cfg(all(unix, not(any(target_os = "aix", target_os = "fuchsia", target_os = "horizon"))))'.dependencies] +rlimit = { workspace = true } + +[target.'cfg(all(unix, not(any(target_os = "aix", target_os = "horizon"))))'.dependencies] nix = { workspace = true, features = ["fs", "term"] } -rustix = { workspace = true, features = ["process", "pty", "termios"] } +rustix = { workspace = true, features = ["pty", "termios"] } [target.'cfg(any(target_os = "freebsd", target_os = "hurd", target_os = "linux", target_os = "android", target_os = "netbsd"))'.dependencies] xattr = { workspace = true } +[target.'cfg(not(any(target_os = "aix", target_os = "horizon")))'.dev-dependencies] +ctor = { workspace = true } + [lints] workspace = true diff --git a/tests/uutests/src/lib/lib.rs b/tests/uutests/src/lib/lib.rs index afd8f1a393..91777f33fd 100644 --- a/tests/uutests/src/lib/lib.rs +++ b/tests/uutests/src/lib/lib.rs @@ -3,6 +3,8 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. +#![cfg(not(any(target_os = "aix", target_os = "horizon")))] + #[macro_use] pub mod macros; pub mod random; diff --git a/tests/uutests/src/lib/util.rs b/tests/uutests/src/lib/util.rs index dae3df62f3..5920b3ea3c 100644 --- a/tests/uutests/src/lib/util.rs +++ b/tests/uutests/src/lib/util.rs @@ -4,7 +4,7 @@ // file that was distributed with this source code. // spell-checker:ignore (linux) rlimit prlimit coreutil ggroups uchild uncaptured scmd SHLVL canonicalized openpty openpt grantpt unlockpt ptsname tcsetwinsize CLOEXEC RDWR SETFD -// spell-checker:ignore (linux) winsize xpixel ypixel setrlimit Fsize SIGBUS SIGSEGV SIGXFSZ EFBIG sigbus tmpfs mksocket +// spell-checker:ignore (linux) winsize xpixel ypixel setrlimit FSIZE SIGBUS SIGSEGV SIGXFSZ EFBIG sigbus tmpfs mksocket // spell-checker:ignore (ToDO) ttyname #![allow(dead_code)] @@ -17,15 +17,15 @@ use core::str; #[cfg(unix)] use libc::mode_t; -#[cfg(all(unix, not(target_os = "redox")))] +#[cfg(all(unix, not(any(target_os = "fuchsia", target_os = "redox"))))] use nix::pty::OpenptyResult; #[cfg(unix)] use nix::sys; -#[cfg(not(windows))] +#[cfg(unix)] use nix::sys::stat::{self, SFlag}; use pretty_assertions::assert_eq; -#[cfg(unix)] -use rustix::process::{Resource, Rlimit, setrlimit}; +#[cfg(all(unix, not(target_os = "fuchsia")))] +use rlimit::{Resource, setrlimit}; use std::borrow::Cow; use std::collections::{BTreeMap, VecDeque}; use std::ffi::{OsStr, OsString}; @@ -353,8 +353,16 @@ impl CmdResult { /// /// # Platform specific behavior /// - /// This assertion method is only available on unix systems, except for fuchsia. - #[cfg(all(unix, not(target_os = "fuchsia")))] + /// This assertion method is only available on unix systems, except for fuchsia, haiku and hurd. + #[cfg(all( + unix, + not(any( + target_os = "dragonfly", + target_os = "fuchsia", + target_os = "haiku", + target_os = "hurd" + )) + ))] #[track_caller] pub fn signal_name_is(&self, name: &str) -> &Self { use uucore::signals::signal_by_name_or_value; @@ -1216,7 +1224,7 @@ impl AtPath { File::create(self.plus(file)).unwrap(); } - #[cfg(not(windows))] + #[cfg(unix)] pub fn mkfifo(&self, fifo: &str) { // rustix::fs::mkfifoat is linux only use nix::sys::stat::Mode; @@ -1234,13 +1242,13 @@ impl AtPath { UnixListener::bind(full_path).expect("Socket file creation failed."); } - #[cfg(not(windows))] + #[cfg(unix)] pub fn is_fifo(&self, fifo: &str) -> bool { stat::stat(&self.plus(fifo)) .is_ok_and(|s| SFlag::from_bits_truncate(s.st_mode).contains(SFlag::S_IFIFO)) } - #[cfg(not(windows))] + #[cfg(unix)] pub fn is_char_device(&self, char_dev: &str) -> bool { stat::stat(&self.plus(char_dev)) .is_ok_and(|s| SFlag::from_bits_truncate(s.st_mode).contains(SFlag::S_IFCHR)) @@ -1258,6 +1266,7 @@ impl AtPath { hard_link(self.plus(original), self.plus(link)).unwrap(); } + #[cfg(any(unix, windows))] pub fn symlink_file(&self, original: &str, link: &str) { log_info( "symlink", @@ -1270,6 +1279,7 @@ impl AtPath { symlink_file(self.plus(original), self.plus(link)).unwrap(); } + #[cfg(any(unix, windows))] pub fn relative_symlink_file(&self, original: &str, link: &str) { #[cfg(windows)] let original = original.replace('/', MAIN_SEPARATOR_STR); @@ -1280,6 +1290,7 @@ impl AtPath { symlink_file(original, self.plus(link)).unwrap(); } + #[cfg(any(unix, windows))] pub fn symlink_dir(&self, original: &str, link: &str) { log_info( "symlink", @@ -1292,6 +1303,7 @@ impl AtPath { symlink_dir(self.plus(original), self.plus(link)).unwrap(); } + #[cfg(any(unix, windows))] pub fn relative_symlink_dir(&self, original: &str, link: &str) { #[cfg(windows)] let original = original.replace('/', MAIN_SEPARATOR_STR); @@ -1403,7 +1415,7 @@ impl AtPath { /// /// This function panics if there is an error loading the metadata /// or setting the permissions of the file. - #[cfg(not(windows))] + #[cfg(unix)] pub fn set_mode(&self, filename: &str, mode: u32) { let path = self.plus(filename); let mut perms = fs::metadata(&path).unwrap().permissions(); @@ -1562,7 +1574,7 @@ pub struct UCommand { stdout: Option, stderr: Option, bytes_into_stdin: Option>, - #[cfg(unix)] + #[cfg(all(unix, not(target_os = "fuchsia")))] limits: Vec<(Resource, u64, u64)>, #[cfg(unix)] ignore_sigxfsz: bool, @@ -1727,7 +1739,7 @@ impl UCommand { self } - #[cfg(unix)] + #[cfg(all(unix, not(target_os = "fuchsia")))] pub fn limit(&mut self, resource: Resource, soft_limit: u64, hard_limit: u64) -> &mut Self { self.limits.push((resource, soft_limit, hard_limit)); self @@ -2000,9 +2012,9 @@ impl UCommand { let mut captured_stdout = None; let mut captured_stderr = None; - #[cfg(all(unix, not(target_os = "redox")))] + #[cfg(all(unix, not(any(target_os = "fuchsia", target_os = "redox"))))] let mut stdin_pty: Option = None; - #[cfg(not(all(unix, not(target_os = "redox"))))] + #[cfg(not(all(unix, not(any(target_os = "fuchsia", target_os = "redox")))))] let stdin_pty: Option = None; if self.stderr_to_stdout { let mut output = CapturedOutput::default(); @@ -2037,7 +2049,7 @@ impl UCommand { .stderr(stderr); } - #[cfg(all(unix, not(target_os = "redox")))] + #[cfg(all(unix, not(any(target_os = "fuchsia", target_os = "redox"))))] if let Some(simulated_terminal) = &self.terminal_simulation { let terminal_size = simulated_terminal.size.unwrap_or(libc::winsize { ws_col: 80, @@ -2086,20 +2098,14 @@ impl UCommand { } } - #[cfg(unix)] + #[cfg(all(unix, not(target_os = "fuchsia")))] if !self.limits.is_empty() { // just to be safe: move a copy of the limits list into the closure. // this way the closure is fully self-contained. let limits_copy = self.limits.clone(); let closure = move || -> Result<()> { for &(resource, soft_limit, hard_limit) in &limits_copy { - setrlimit( - resource, - Rlimit { - current: Some(soft_limit), - maximum: Some(hard_limit), - }, - )?; + setrlimit(resource, soft_limit, hard_limit)?; } Ok(()) }; @@ -3056,14 +3062,9 @@ pub fn whoami() -> String { /// Open a PTY whose two ends are close-on-exec, so that commands started by /// other tests in the meantime don't inherit them. -#[cfg(all(unix, not(target_os = "redox")))] +#[cfg(all(unix, not(any(target_os = "fuchsia", target_os = "redox"))))] fn open_pty(size: Option<&libc::winsize>) -> OpenptyResult { - #[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd" - ))] + #[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))] { use rustix::fs::{Mode, OFlags, open}; use rustix::pty::{OpenptFlags, grantpt, openpt, ptsname, unlockpt}; @@ -3094,12 +3095,7 @@ fn open_pty(size: Option<&libc::winsize>) -> OpenptyResult { // Elsewhere a PTY can't be opened close-on-exec, so a command started // between openpty and fcntl can still inherit it. - #[cfg(not(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd" - )))] + #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "freebsd")))] { use nix::fcntl::{FcntlArg, FdFlag, fcntl}; @@ -3117,7 +3113,7 @@ fn open_pty(size: Option<&libc::winsize>) -> OpenptyResult { /// - path: The filesystem path to the PTY replica device /// - controller: The controller file /// - replica: The replica file -#[cfg(all(unix, not(target_os = "redox")))] +#[cfg(all(unix, not(any(target_os = "fuchsia", target_os = "redox"))))] pub fn pty_path() -> (String, File, File) { use nix::unistd::ttyname; let pty = open_pty(None); @@ -3774,7 +3770,7 @@ mod tests { .stdout_is("unlimited\nunlimited\n"); } - #[cfg(unix)] + #[cfg(all(unix, not(target_os = "fuchsia")))] #[test] fn test_application_of_process_resource_limits_limited_file_size() { let unit_size_bytes = if cfg!(target_vendor = "apple") { @@ -3786,7 +3782,7 @@ mod tests { let ts = TestScenario::new("util"); ts.cmd("sh") .args(&["-c", "ulimit -Sf; ulimit -Hf"]) - .limit(Resource::Fsize, 8 * unit_size_bytes, 16 * unit_size_bytes) + .limit(Resource::FSIZE, 8 * unit_size_bytes, 16 * unit_size_bytes) .succeeds() .no_stderr() .stdout_is("8\n16\n");