Skip to content

Commit 60f692a

Browse files
committed
chore: fix build errors
1 parent b5c6031 commit 60f692a

11 files changed

Lines changed: 71 additions & 20 deletions

File tree

.vscode/cspell.dictionaries/workspace.wordlist.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,10 @@ addrlen
198198
blocksize
199199
canonname
200200
chroot
201+
cmdline
201202
dlsym
202203
execvp
204+
fchmod
203205
fdatasync
204206
freeaddrinfo
205207
getaddrinfo
@@ -219,6 +221,7 @@ inodes
219221
isatty
220222
lchown
221223
pathlen
224+
reflink
222225
setgid
223226
setgroups
224227
settime
@@ -232,6 +235,8 @@ strcmp
232235
strerror
233236
strlen
234237
syncfs
238+
unflushed
239+
utimensat
235240
umask
236241
waitpid
237242

src/uu/sort/src/sort.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2015,7 +2015,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
20152015
for (line_num, line_res) in buf_reader.split(b'\0').enumerate() {
20162016
let line = line_res.map_err(|error| SortError::ReadFailed {
20172017
path: files0_from.clone(),
2018-
error,
2018+
error: uucore::error::wasi_normalize_read_error(error),
20192019
})?;
20202020
if line.as_slice() == STDIN_FILE.as_bytes() {
20212021
return Err(SortError::MinusInStdIn.into());

src/uu/touch/src/touch.rs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub mod error;
1111
use clap::builder::{PossibleValue, ValueParser};
1212
use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command};
1313
use filetime::FileTime;
14-
#[cfg(any(not(unix), target_os = "redox"))]
14+
#[cfg(any(all(not(unix), not(target_os = "wasi")), target_os = "redox"))]
1515
use filetime::set_file_times;
1616
#[cfg(not(target_os = "wasi"))]
1717
use filetime::set_symlink_file_times;
@@ -649,14 +649,53 @@ fn update_times(
649649
set_times_by_path(path, atime, mtime)
650650
}
651651

652-
#[cfg(not(unix))]
652+
#[cfg(target_os = "wasi")]
653+
{
654+
set_times_by_path_wasi(path, atime, mtime)
655+
}
656+
657+
#[cfg(not(any(unix, target_os = "wasi")))]
653658
{
654659
set_file_times(path, atime, mtime).map_err_context(
655660
|| translate!("touch-error-setting-times-of-path", "path" => path.quote()),
656661
)
657662
}
658663
}
659664

665+
#[cfg(target_os = "wasi")]
666+
/// Set file times by path on WASI.
667+
///
668+
/// wasmtime's `utimensat` implementation refuses to set times on a
669+
/// follow-symlink path if it cannot `open()` the target (it returns
670+
/// `ENOTSUP`, since honoring the symlink race-freely would otherwise require
671+
/// an FD), even for files the caller owns but cannot open (e.g. mode 0).
672+
/// Native Unix `utimensat` has no such restriction. When the follow variant
673+
/// fails and the path is not itself a symlink, retry with
674+
/// `SYMLINK_NOFOLLOW`, which resolves the same file without opening it.
675+
fn set_times_by_path_wasi(path: &Path, atime: FileTime, mtime: FileTime) -> UResult<()> {
676+
let timestamps = build_timestamps(atime, mtime);
677+
let result = rustix::fs::utimensat(
678+
rustix::fs::CWD,
679+
path,
680+
&timestamps,
681+
rustix::fs::AtFlags::empty(),
682+
);
683+
let result = match result {
684+
Err(_) if !fs::symlink_metadata(path).is_ok_and(|m| m.file_type().is_symlink()) => {
685+
rustix::fs::utimensat(
686+
rustix::fs::CWD,
687+
path,
688+
&timestamps,
689+
rustix::fs::AtFlags::SYMLINK_NOFOLLOW,
690+
)
691+
}
692+
other => other,
693+
};
694+
result
695+
.map_err(|e| Error::from_raw_os_error(e.raw_os_error()))
696+
.map_err_context(|| translate!("touch-error-setting-times-of-path", "path" => path.quote()))
697+
}
698+
660699
#[cfg(any(unix, target_os = "wasi"))]
661700
/// Build a rustix `Timestamps` from the access and modification `FileTime`s,
662701
/// preserving the `UTIME_NOW`/`UTIME_OMIT` sentinels in the nanoseconds field.

src/uu/wc/src/wc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,7 @@ fn files0_iter<'a>(
820820
}
821821
}
822822
Err(e) => {
823-
let e = uucore::error::wasi_normalize_open_error(e);
823+
let e = uucore::error::wasi_normalize_read_error(e);
824824
Err(e.map_err_context(
825825
|| translate!("wc-error-read-error", "path" => escape_name_wrapper(&err_path)),
826826
) as Box<dyn UError>)

src/uucore/src/lib/mods/error.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -524,19 +524,23 @@ pub fn wasi_normalize_open_error(err: std::io::Error) -> std::io::Error {
524524
/// directory file descriptor (e.g. stdin redirected from a directory, or a
525525
/// raw `read()` on an fd already open on a directory).
526526
///
527-
/// This is a distinct case from [`wasi_normalize_open_error`]: WASI reports
528-
/// `EISDIR` here (unlike the `EBADF` it reports for filesystem operations
529-
/// like `open` or `remove_file` on a directory), but under a different
530-
/// errno per preview version: `31` on preview 1, `29` on preview 2.
527+
/// This covers two distinct WASI error shapes for the same underlying
528+
/// condition: reading a directory fd that was already open when handed to
529+
/// us (e.g. stdin redirected from a directory) surfaces `EISDIR`, under a
530+
/// different errno per preview version (`31` on preview 1, `29` on preview
531+
/// 2); reading a directory fd that we opened ourselves via
532+
/// `std::fs::File::open` surfaces the same `EBADF` (errno `8`) that
533+
/// [`wasi_normalize_open_error`] handles for `open()`-time failures, because
534+
/// on WASI the directory check is deferred from `open` to the first `read`.
531535
///
532536
/// This is a no-op on non-WASI targets.
533537
pub fn wasi_normalize_read_error(err: std::io::Error) -> std::io::Error {
534538
#[cfg(all(target_os = "wasi", target_env = "p1"))]
535-
if err.raw_os_error() == Some(31) {
539+
if matches!(err.raw_os_error(), Some(31) | Some(8)) {
536540
return std::io::Error::new(std::io::ErrorKind::IsADirectory, "Is a directory");
537541
}
538542
#[cfg(all(target_os = "wasi", target_env = "p2"))]
539-
if err.raw_os_error() == Some(29) {
543+
if matches!(err.raw_os_error(), Some(29) | Some(8)) {
540544
return std::io::Error::new(std::io::ErrorKind::IsADirectory, "Is a directory");
541545
}
542546
err

tests/by-util/test_du.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2391,7 +2391,7 @@ fn test_du_long_path_from_unreadable() {
23912391
}
23922392

23932393
#[test]
2394-
#[cfg(unix)]
2394+
#[cfg(all(unix, not(target_os = "android")))]
23952395
fn test_du_hard_links_multiple_dirs_in_args() {
23962396
let ts = TestScenario::new(util_name!());
23972397
let at = &ts.fixtures;
@@ -2408,7 +2408,7 @@ fn test_du_hard_links_multiple_dirs_in_args() {
24082408
}
24092409

24102410
#[test]
2411-
#[cfg(unix)]
2411+
#[cfg(all(unix, not(target_os = "android")))]
24122412
fn test_du_hard_links_multiple_links_in_args() {
24132413
let ts = TestScenario::new(util_name!());
24142414
let at = &ts.fixtures;

tests/by-util/test_install.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -792,8 +792,12 @@ fn strip_source_file() -> PathBuf {
792792
BINARY
793793
.get_or_init(|| {
794794
let dir = std::env::temp_dir();
795-
let source = dir.join("hello.rs");
796-
let binary = dir.join("hello_bin");
795+
// Include the PID so concurrent test processes (e.g. under `cargo
796+
// nextest`, which runs each test in its own process) don't race
797+
// on the same source/binary path.
798+
let pid = process::id();
799+
let source = dir.join(format!("hello-{pid}.rs"));
800+
let binary = dir.join(format!("hello_bin-{pid}"));
797801
let mut file = File::create(&source).unwrap();
798802
file.write_all(b"fn main() {}").unwrap();
799803
process::Command::new("rustc")

tests/by-util/test_ls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1498,7 +1498,7 @@ fn test_ls_long_dangling_symlink_color() {
14981498
// Ensure dangling link name uses `or=` and target uses `mi=`.
14991499
let name_regex =
15001500
Regex::new(r"(?:\x1b\[[0-9;]*m)*\x1b\[([0-9;]*)mdir1/dangling_symlink\x1b\[0m").unwrap();
1501-
let target_path = regex::escape("../foo");
1501+
let target_path = regex::escape(&format!("..{}foo", std::path::MAIN_SEPARATOR));
15021502
let target_pattern = format!(r"(?:\x1b\[[0-9;]*m)*\x1b\[([0-9;]*)m{target_path}\x1b\[0m");
15031503
let target_regex = Regex::new(&target_pattern).unwrap();
15041504

tests/by-util/test_realpath.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,8 @@ fn test_realpath_logical_mode() {
176176
fn test_realpath_dangling() {
177177
let (at, mut ucmd) = at_and_ucmd!();
178178
at.symlink_file("nonexistent-file", "link");
179-
ucmd.arg("link")
180-
.succeeds()
181-
.stdout_contains(at.plus_as_string("nonexistent-file\n"));
179+
let expect = path_concat!(at.root_dir_resolved(), "nonexistent-file") + "\n";
180+
ucmd.arg("link").succeeds().stdout_contains(expect);
182181
}
183182

184183
#[test]

tests/by-util/test_sort.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1463,7 +1463,7 @@ fn test_batch_size_too_large() {
14631463
"--batch-size argument '{large_batch_size}' too large"
14641464
));
14651465

1466-
#[cfg(target_os = "linux")]
1466+
#[cfg(all(target_os = "linux", not(wasi_runner)))]
14671467
new_ucmd!()
14681468
.arg(format!("--batch-size={large_batch_size}"))
14691469
.fails_with_code(2)

0 commit comments

Comments
 (0)