Skip to content

wasi: add cat/sort/tail/touch integration coverage and related fixes - #11712

Draft
DePasqualeOrg wants to merge 17 commits into
uutils:mainfrom
DePasqualeOrg:wasi-support
Draft

wasi: add cat/sort/tail/touch integration coverage and related fixes#11712
DePasqualeOrg wants to merge 17 commits into
uutils:mainfrom
DePasqualeOrg:wasi-support

Conversation

@DePasqualeOrg

@DePasqualeOrg DePasqualeOrg commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

This draft tracks the combined WASI work that is being divided into smaller PRs. It is not intended to merge in its current form.

Planned sequence

  1. A cat PR will enable its WASI integration coverage and document the small set of unsupported test conditions.
  2. A touch PR will add WASI timestamp support and focused integration coverage.
  3. A cp PR will add WASI symlink and timestamp behavior with focused tests.
  4. A tail PR will enable its WASI coverage and document follow-mode and platform limitations.
  5. The sort work will be divided into independently buildable review stages before submission because the current combined diff remains too large.

@oech3

oech3 commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Would you split PR (at least for symlink support)?

@DePasqualeOrg
DePasqualeOrg force-pushed the wasi-support branch 2 times, most recently from 9bced35 to aa75a81 Compare April 8, 2026 11:08
@DePasqualeOrg

Copy link
Copy Markdown
Contributor Author

I separated the symlink changes out into #11713.

@DePasqualeOrg DePasqualeOrg changed the title wasi: atomics-aware threading, synchronous sort pipeline, and symlink support wasi: atomics-aware threading and synchronous sort pipeline Apr 8, 2026
@DePasqualeOrg

Copy link
Copy Markdown
Contributor Author

I added a new commit to address an issue that would cause CI failures.

The WASI CI uses stable Rust, but std::os::wasi::fs requires the unstable feature(wasi_ext) gate. This commit replaces all unstable APIs with stable libc equivalents:

  • uucore/fs.rs: FileInformation now stores libc::stat instead of std::fs::Metadata on WASI, using libc::fstat/libc::stat/libc::lstat for dev/ino/nlink access
  • cp.rs: std::os::wasi::fs::symlink_path replaced with libc::symlink
  • uucore/lib.rs: #![cfg_attr(..., feature(wasi_ext))] removed entirely
  • is_enotsup_error() updated to use libc::EOPNOTSUPP on WASI instead of a hardcoded value

@DePasqualeOrg

Copy link
Copy Markdown
Contributor Author

I resolved the linter error in CI.

@github-actions

github-actions Bot commented Apr 8, 2026

Copy link
Copy Markdown

GNU testsuite comparison:

GNU test failed: tests/tail/tail-n0f. tests/tail/tail-n0f is passing on 'main'. Maybe you have to rebase?
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/expand/bounded-memory is now passing!
Congrats! The gnu test tests/printf/printf-surprise is now passing!

@github-actions

github-actions Bot commented Apr 8, 2026

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/tail/symlink (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Note: The gnu test tests/cp/link-heap is now being skipped but was previously passing.
Note: The gnu test tests/pr/bounded-memory is now being skipped but was previously passing.
Congrats! The gnu test tests/expand/bounded-memory is now passing!
Congrats! The gnu test tests/printf/printf-surprise is now passing!

@github-actions

github-actions Bot commented Apr 8, 2026

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/cut/bounded-memory (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/expand/bounded-memory is now passing!
Congrats! The gnu test tests/printf/printf-surprise is now passing!

@oech3

oech3 commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Is it able to split PR per utility? Diff is still too big. How about sort?

@DePasqualeOrg

Copy link
Copy Markdown
Contributor Author

The changes here are interdependent, and splitting out sort would result in PRs of ~560 and ~110 lines each, which would need to be sequenced properly and rebased on upstream changes. They should also probably wait for #11717, in which I've enabled integration tests. If/when that PR is merged, I can enable more tests for these tools in this PR. Keeping them in one PR would reduce the cognitive load for me, since I'm now keeping track of three related PRs.

@DePasqualeOrg

Copy link
Copy Markdown
Contributor Author

I've added WASI integration coverage for four more tools, plus the fixes needed to make those tests pass.

New integration tests

Added test_cat, test_sort, test_tail, test_touch to wasi.yml. Every skip carries a specific reason; those reasons are categorized in docs/src/wasi-test-gaps.md.

Fixes

touch: filetime's WASI backend is stubbed out (FileTime::from_last_{access,modification}_time panics; set_file_times returns "Wasm not implemented"). Swapped for rustix::fs::utimensat and Metadata::{accessed,modified}FileTime::from_system_time. 31 tests fixed.

sort: /tmp isn't a WASI preopen by default, so the hardcoded fallback broke external sort. Added uucore::fs::wasi_default_tmp_dir (gated to cfg(target_os = "wasi")) which returns /tmp if visible, else the current directory. --tmp-dir and TMPDIR still override. 4 tests fixed.

cp: replaced CString + unsafe libc::symlink with rustix::fs::symlink (matches the ln pattern). Implemented --preserve=timestamps on WASI via rustix::fs::utimensat (mirroring touch) and reverted the Preserve::Yes { required: false } downgrade so cp -a no longer silently drops timestamps.

uucore: FileInformation's WASI arm hand-rolled fstat/stat/lstat via libc + CString. Collapsed into the unix arm – rustix::fs::Stat is a typedef to libc::stat on WASI, and rustix::fs::{stat, lstat, fstat} work there without any cfg gate. Removed ~35 lines of unsafe code.

cat: stub stays – when stdout is inherited from a host file descriptor, wasmtime reports its fstat as all-zero so dev/inode comparison can never match. Comment updated to reflect that accurately.

Deferred

test_cp is not added here. ~41 of its failures still cluster around WASI symlink handling that needs follow-up: under wasmtime, symlinks with absolute targets (for example bar -> /foo) fail in ways that do not match POSIX, while equivalent relative symlinks work. The same limitation also affects readlink, realpath, and other symlink-heavy paths. Separately, some remaining failures are test-harness expectation issues because the WASI guest sees the per-test tempdir as /, not as the host absolute temp path. I documented both gaps in docs/src/wasi-test-gaps.md for follow-up.

Verification

Integration tests pass on macOS host and on Linux in an Ubuntu 24.04 Docker container (1592 passed / 0 failed / 176 ignored).

@DePasqualeOrg DePasqualeOrg changed the title wasi: atomics-aware threading and synchronous sort pipeline wasi: add cat/sort/tail/touch integration coverage and related fixes Apr 12, 2026
@github-actions

Copy link
Copy Markdown

GNU testsuite comparison:

Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Skipping an intermittent issue tests/pr/bounded-memory (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/dd/no-allocate is now passing!
Congrats! The gnu test tests/printf/printf-surprise is now passing!

@github-actions

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/cut/bounded-memory (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tail/tail-n0f (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tty/tty-eof (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/dd/no-allocate is now passing!
Congrats! The gnu test tests/printf/printf-surprise is now passing!

@github-actions

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/tty/tty-eof (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/dd/no-allocate is now passing!
Congrats! The gnu test tests/printf/printf-surprise is now passing!

@github-actions

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/cut/bounded-memory (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tty/tty-eof (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Note: The gnu test tests/basenc/bounded-memory is now being skipped but was previously passing.
Congrats! The gnu test tests/dd/no-allocate is now passing!
Congrats! The gnu test tests/printf/printf-surprise is now passing!

Comment thread src/uu/cp/src/cp.rs Outdated
} else {
filetime::set_file_times(dest, atime, mtime)?;
#[cfg(target_os = "wasi")]
{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please move that into a new function

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@sylvestre

sylvestre commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

i am sorry but it can't be merged this way, it needs to be split into several PRs

also, it adds way too many wasi_no_threads everywhere

@github-actions

github-actions Bot commented Apr 21, 2026

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/date/date-locale-hour (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tail/retry (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tail/tail-n0f (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/tail/symlink (passes in this run but fails in the 'main' branch)
Note: The gnu test tests/misc/write-errors was skipped on 'main' but is now failing.

@DePasqualeOrg
DePasqualeOrg force-pushed the wasi-support branch 2 times, most recently from 5aa26b0 to f96a56c Compare April 21, 2026 09:41
@DePasqualeOrg

Copy link
Copy Markdown
Contributor Author

Before I split this up, I moved the sync/threaded variants into separate files, which reduces the number of cfg attributes in uu_sort significantly. If that's the direction you'd like to take, I'll start splitting this into separate PRs.

@DePasqualeOrg
DePasqualeOrg force-pushed the wasi-support branch 3 times, most recently from b887346 to ae780ef Compare August 4, 2026 13:06
@sylvestre

Copy link
Copy Markdown
Contributor

could you please keep your comments shorter on this PR ? it is hard to read otherwise.
thanks

1 similar comment
@sylvestre

Copy link
Copy Markdown
Contributor

could you please keep your comments shorter on this PR ? it is hard to read otherwise.
thanks

Add #[cfg(target_os = "wasi")] blocks alongside existing unix and windows
platform code. No changes to existing platform behavior.

Enables compilation to wasm32-wasip1 and wasm32-wasip1-threads targets
for running in WASI-compatible runtimes like WasmKit and Wasmer.
On wasm32-wasip1 (no atomics), sort crashes because ext_sort, merge,
check, and rayon all spawn threads unconditionally. Add synchronous
code paths gated on cfg(all(target_os = "wasi", not(target_feature
= "atomics"))) so sort works on both wasip1 (sync) and
wasip1-threads (threaded).

Key changes:
- Extract read_to_chunk() from chunks::read() for shared use
- Add synchronous ext_sort with chunked sort-write-merge flow
- Add SyncFileMerger for threadless merge operations
- Add synchronous check for order verification
- Gate rayon par_sort with sequential fallback
Comment thread util/run-wasi-tests-docker.sh Outdated
Comment on lines +11 to +13
# The gap this closes: integration tests are host-built and many are gated
# with #[cfg(not(target_vendor = "apple"))] / #[cfg(target_os = "linux")],
# so macOS silently excludes them.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been improved a bit with the merge of #13666, where we have enabled more tests that can run in Unix-based systems (including macOS).

@eduardomourar

eduardomourar commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

I believe I missed this PR because it was in draft. There are few changes here that are overlapping with PR #13625 I am currently working on. Also, the spin-off PRs I created might simplify the implementation for this PR.

@eduardomourar

Copy link
Copy Markdown
Contributor

@sylvestre, let me know if you agree on the following proposal, please?

Already covered by my PRs (please drop from this PR):

Unique value in this PR that I'd love to see land:

  • The entire sort refactoring (parallel.rs, check/ module split, ext_sort/sync.rs, merge/sync.rs) is architecturally cleaner and more complete than my simpler fix(wasi): sort ordering check and external-merge separator #13688. I'm happy to close mine in favor of your sort work.
  • The build.rs with wasi_no_threads cfg alias is a great ergonomic win.
  • The wasi-test-gaps.md documentation additions are valuable.
  • The Docker test script is a nice developer experience addition.

Suggested path forward:

  1. Wait for PR 13685 (cp) and PR 13686 (touch) to merge
  2. Rebase this PR dropping cp/touch/uucore-fs changes
  3. Focus this PR on the sort refactoring + test annotations + docs
  4. I'll close my PR 13688 once your sort changes are ready
    The tail stubs and cat comment improvement are fine to keep — no conflict.

@DePasqualeOrg

DePasqualeOrg commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

could you please keep your comments shorter on this PR ? it is hard to read otherwise. thanks

@sylvestre, I don't know why you keep posting that. We already discussed this. Just ignore this draft PR.

As I stated multiple times before, this is in draft because it's not meant for review. It's my combined Wasm fixes from which smaller PRs can be split out.

@eduardomourar, I had Codex review your PRs, comparing them with the changes I already have here, and it found multiple issues. For that reason, I'll submit my own PRs based on this work that I submitted already four months ago, and @sylvestre can decide which he wants to work with.

@eduardomourar

Copy link
Copy Markdown
Contributor

I don't think I follow your reasoning. You have this PR in draft (that part I understand). You will be creating multiple PRs out of this one. Then, I say that I have already started doing that for you (without me realizing it, of course). If you have found any issues, I am happy to make the necessary changes to accommodate your approach. It is very similar so they should be small tweaks that can done without any real impact.

@sylvestre

Copy link
Copy Markdown
Contributor

@sylvestre, I don't know why you keep posting that. We already discussed this. Just ignore this draft PR.

because i am tired of seeing 3 pages comments written by LLM

@DePasqualeOrg

Copy link
Copy Markdown
Contributor Author

@sylvestre, there are no 3-page comments here.

Just ignore this draft PR and any other draft PRs, which represent work in progress, until they're marked as ready for review, at which point comments will be concise as per your preference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants