Skip to content
Open
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
4 changes: 2 additions & 2 deletions .github/workflows/wasi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
# Tests incompatible with WASI are annotated with
# #[cfg_attr(wasi_runner, ignore)] in the test source files.
# TODO: add integration tests for these tools as WASI support is extended:
# arch b2sum cat cksum cp csplit date dir dircolors fmt join ln
# arch b2sum cat cksum cp csplit date dir dircolors fmt join
# ls md5sum mkdir mv nproc pathchk pr printenv ptx pwd readlink
# realpath rm rmdir seq sha1sum sha224sum sha256sum sha384sum
# sha512sum shred sleep sort split tail touch tsort uname uniq
Expand All @@ -61,7 +61,7 @@ jobs:
test_base32:: test_base64:: test_basenc:: test_basename:: \
test_comm:: test_cut:: test_dirname:: test_echo:: \
test_expand:: test_factor:: test_false:: test_fold:: \
test_head:: test_link:: test_nl:: test_numfmt:: \
test_head:: test_link:: test_ln:: test_nl:: test_numfmt:: \
test_od:: test_paste:: test_printf:: test_shuf:: test_sum:: \
test_tee:: test_tr:: test_true:: test_truncate:: \
test_unexpand:: test_unlink:: test_wc::
1 change: 1 addition & 0 deletions Cargo.lock

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

6 changes: 5 additions & 1 deletion docs/src/wasi-test-gaps.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ To find all annotated tests: `grep -rn 'wasi_runner, ignore' tests/`

## Tools not yet covered by integration tests

arch, b2sum, cat, cksum, cp, csplit, date, dir, dircolors, fmt, join, ln, ls, md5sum, mkdir, mv, nproc, pathchk, pr, printenv, ptx, pwd, readlink, realpath, rm, rmdir, seq, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, shred, sleep, sort, split, tail, touch, tsort, uname, uniq, vdir, yes
arch, b2sum, cat, cksum, cp, csplit, date, dir, dircolors, fmt, join, ls, md5sum, mkdir, mv, nproc, pathchk, pr, printenv, ptx, pwd, readlink, realpath, rm, rmdir, seq, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, shred, sleep, sort, split, tail, touch, tsort, uname, uniq, vdir, yes

## WASI sandbox: host paths not visible

Expand All @@ -31,3 +31,7 @@ WASI does not support spawning child processes. Tests that shell out to other co
## WASI: stdin file position not preserved through wasmtime

When stdin is a seekable file, wasmtime does not preserve the file position between the host and guest. Tests that validate stdin offset behavior after `head` reads are skipped.

## WASI: read_link on absolute paths fails under wasmtime via spawned test harness

`fs::read_link` on an absolute path inside the sandbox (e.g. `/file2`) returns `EPERM` when the WASI binary is launched through `std::process::Command` from the test harness, even though the same call works when wasmtime is invoked directly. This breaks `uucore::fs::canonicalize` for symlink sources, so tests that rely on following a symlink to compute a relative path are skipped.
1 change: 1 addition & 0 deletions src/uu/ln/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ path = "src/ln.rs"

[dependencies]
clap = { workspace = true }
rustix = { workspace = true, features = ["fs"] }
uucore = { workspace = true, features = ["backup-control", "fs"] }
thiserror = { workspace = true }
fluent = { workspace = true }
Expand Down
9 changes: 4 additions & 5 deletions src/uu/ln/src/ln.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use std::ffi::OsString;
use std::fs;
use thiserror::Error;

#[cfg(target_os = "wasi")]
use std::io;
#[cfg(any(unix, target_os = "redox"))]
use std::os::unix::fs::symlink;
#[cfg(windows)]
Expand Down Expand Up @@ -490,9 +492,6 @@ pub fn symlink<P1: AsRef<Path>, P2: AsRef<Path>>(src: P1, dst: P2) -> std::io::R
}

#[cfg(target_os = "wasi")]
fn symlink<P1: AsRef<Path>, P2: AsRef<Path>>(_src: P1, _dst: P2) -> std::io::Result<()> {
Err(std::io::Error::new(
std::io::ErrorKind::Unsupported,
"symlinks not supported on this platform",
))
pub fn symlink<P1: AsRef<Path>, P2: AsRef<Path>>(src: P1, dst: P2) -> io::Result<()> {
rustix::fs::symlink(src.as_ref(), dst.as_ref()).map_err(io::Error::from)
}
9 changes: 7 additions & 2 deletions src/uucore/src/lib/features/backup_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ use std::{
error::Error,
ffi::{OsStr, OsString},
fmt::{Debug, Display},
fs,
path::{Path, PathBuf},
};

Expand Down Expand Up @@ -442,7 +443,11 @@ fn numbered_backup_path(path: &Path) -> PathBuf {
let mut i: u64 = 1;
loop {
let new_path = simple_backup_path(path, OsString::from(format!(".~{i}~")));
if !new_path.exists() {
// Use `symlink_metadata` rather than `exists()` so that a dangling
// symlink still counts as an existing backup (avoiding a silent
// overwrite), and so we do not report a live symlink as missing when
// the target cannot be stat'd.
if fs::symlink_metadata(&new_path).is_err() {
return new_path;
}
i += 1;
Expand All @@ -451,7 +456,7 @@ fn numbered_backup_path(path: &Path) -> PathBuf {

fn existing_backup_path<S: AsRef<OsStr>>(path: &Path, suffix: S) -> PathBuf {
let test_path = simple_backup_path(path, OsString::from(".~1~"));
if test_path.exists() {
if fs::symlink_metadata(&test_path).is_ok() {
return numbered_backup_path(path);
}
simple_backup_path(path, suffix.as_ref())
Expand Down
6 changes: 6 additions & 0 deletions tests/by-util/test_ln.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ fn test_symlink_implicit_target_dir() {
}

#[test]
#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")]
fn test_symlink_to_dir_2args() {
let (at, mut ucmd) = at_and_ucmd!();
let filename = "test_symlink_to_dir_2args_file";
Expand Down Expand Up @@ -754,6 +755,10 @@ fn test_relative_dst_already_symlink() {
}

#[test]
#[cfg_attr(
wasi_runner,
ignore = "WASI: read_link on absolute paths fails under wasmtime via spawned test harness"
)]
fn test_relative_src_already_symlink() {
let (at, mut ucmd) = at_and_ucmd!();
at.touch("file1");
Expand Down Expand Up @@ -967,6 +972,7 @@ fn test_ln_seen_file() {

#[test]
#[cfg(target_os = "linux")]
#[cfg_attr(wasi_runner, ignore = "WASI: argv/filenames must be valid UTF-8")]
fn test_ln_non_utf8_paths() {
use std::ffi::OsStr;
use std::os::unix::ffi::OsStrExt;
Expand Down
Loading