Skip to content
Draft
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
16 changes: 15 additions & 1 deletion src/uu/ls/src/ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,20 @@ pub fn list_with_output<O: LsOutput>(
Ok(())
}

/// Build the path for the ".." entry of `parent`.
///
/// On WASI the sandbox may block access to ".." at the preopened root,
/// so fall back to the parent path itself when its metadata can't be
/// read. On other targets this is just `parent/..`.
fn dotdot_path(parent: &Path) -> PathBuf {
let dotdot = parent.join("..");
#[cfg(target_os = "wasi")]
if dotdot.metadata().is_err() {
return parent.to_path_buf();
}
dotdot
}

fn collect_directory_entries<O: LsOutput>(
entries: &mut Vec<PathData>,
path_data: &PathData,
Expand All @@ -1266,7 +1280,7 @@ fn collect_directory_entries<O: LsOutput>(
false,
));
entries.push(PathData::new(
path_data.path().join("..").into(),
dotdot_path(path_data.path()).into(),
None,
Some(OsStr::new("..").into()),
config,
Expand Down
17 changes: 17 additions & 0 deletions tests/by-util/test_ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7244,3 +7244,20 @@
.stdout_contains("..")
.no_stderr();
}

#[test]
#[cfg(target_os = "wasi")]
fn test_ls_al_no_capabilities_insufficient_on_wasi() {
// `ls -al` reads metadata for every entry including "..". Without the
// WASI fallback, stat on ".." at the preopened root returns
// ERRNO_NOTCAPABLE, which surfaces to the user as "Capabilities

Check failure on line 7253 in tests/by-util/test_ls.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

ERROR: `cspell`: Unknown word 'NOTCAPABLE' (file:'tests/by-util/test_ls.rs', line:7253)
// insufficient". Guard against that regression here.
let scene = TestScenario::new(util_name!());
let out = scene.ucmd().arg("-al").succeeds();
out.no_stderr();
assert!(
!out.stdout_str().contains("Capabilities insufficient"),
"ls -al stdout leaked a WASI capability error: {}",
out.stdout_str()
);
}
Loading