Skip to content

Add userspace /bin/cat and /bin/ls#909

Merged
dburkart merged 2 commits intomainfrom
m902-userspace-cat-ls
May 6, 2026
Merged

Add userspace /bin/cat and /bin/ls#909
dburkart merged 2 commits intomainfrom
m902-userspace-cat-ls

Conversation

@dburkart
Copy link
Copy Markdown
Owner

@dburkart dburkart commented May 6, 2026

Closes #902
Closes #903

Summary

  • Add base/cat/ — a minimal cat implementation that reads files from argv to stdout, or copies stdin to stdout when no args are given. Handles errors (file not found prints to stderr, exits 1).
  • Add base/ls/ — a minimal ls implementation that lists directory entries sorted alphabetically, one per line, with / suffix for directories. Supports multiple path args with headers; defaults to . when no args given.
  • Both crates follow the established base/sh/ pattern: standalone packages with #![feature(restricted_std)], built out-of-tree with -Z build-std against the in-repo std fork.
  • Both include a minimal syscalls.rs module providing the close C-ABI shim needed by the std PAL's OwnedFd::drop.
  • Wire both binaries into the ext2 rootfs image via xtask (build_userspace_cat() / build_userspace_ls()), installed alongside /bin/sh in all code paths that assemble the rootfs.

Test plan

  • cargo xtask build — full kernel build succeeds
  • cargo fmt --all -- --check — no formatting issues
  • cargo test -p xtask — all 71 xtask tests pass
  • Both cat and ls binaries compile successfully for the x86_64-unknown-vibix target

Implement cat and ls as standalone base system programs following the
established base/sh pattern. Both use the in-repo std fork via
-Z build-std and provide minimal syscall shims (close) needed by the
std PAL.

cat: reads files from argv to stdout; reads stdin if no args; supports
"-" for explicit stdin; prints errors to stderr and exits 1 on failure.

ls: lists directory entries sorted alphabetically, one per line, with
"/" suffix for directories; supports multiple path args with headers;
defaults to "." when no args given.

Both binaries are wired into the ext2 rootfs image via xtask alongside
/bin/sh, installed as /bin/cat and /bin/ls respectively.

Closes #902
Closes #903

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Warning

Rate limit exceeded

@dburkart has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 4 seconds before requesting another review.

To continue reviewing without waiting, purchase usage credits in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c97fea48-e97d-44e4-b3c2-3a0322594302

📥 Commits

Reviewing files that changed from the base of the PR and between 1c7ca82 and a410939.

📒 Files selected for processing (3)
  • base/cat/src/main.rs
  • base/ls/src/main.rs
  • xtask/src/main.rs
📝 Walkthrough

Walkthrough

Adds two new user-space command-line utilities (/bin/cat and /bin/ls) to the vibix ecosystem. Each includes a Cargo manifest, Rust implementation with restricted_std and syscall shims for POSIX-like close semantics, and integration into the xtask build system for inclusion in ext2 rootfs test images.

Changes

Userspace Cat and Ls Utilities

Layer / File(s) Summary
Project Manifests
base/cat/Cargo.toml, base/ls/Cargo.toml
Define standalone packages with name, version 0.1.0, edition 2021, authors, MIT OR Apache-2.0 license, and binary targets at src/main.rs.
Core Implementation
base/cat/src/main.rs, base/ls/src/main.rs
cat: implements cat_reader() to stream data in 4 KiB chunks and main() to parse args, read stdin or files, handle "-" as stdin, and exit with error status. ls: implements list_dir() to read directory entries, sort by name, append "/" suffix to directories, and main() to list current or specified paths with optional headers for multiple arguments.
Syscalls Integration
base/cat/src/syscalls.rs, base/ls/src/syscalls.rs
Both provide identical C-ABI syscall shims: SYS_CLOSE constant, __errno_location() extern declaration, raw1() syscall dispatcher via inline assembly, cvt() errno conversion, and public no_mangle close(fd: i32) -> i32 function for vibix libc compatibility.
Build & Deploy Wiring
xtask/src/main.rs
Adds build_userspace_cat() and build_userspace_ls() helper functions following the cargo-build-strip pattern, and updates run_with_root, smoke, and sh_test paths to build and include both binaries in the ext2 rootfs image at /bin/cat and /bin/ls.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • dburkart/vibix#873: Introduces the base/ workspace layout and foundational build patterns that this PR extends with new cat and ls utilities.
  • dburkart/vibix#867: Implements vibix syscall wrappers and std/fs/process support including close(), which overlaps with the low-level C-ABI syscall shims added here.
  • dburkart/vibix#611: Establishes the deterministic ext2-image builder and xtask integration that this PR uses to package cat and ls into the rootfs.

🐰 A cat and ls in the bin
Ready to read and to list
With syscalls that grin
And errors dismissed—
The userspace tools now begin! 📂📖

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding two new userspace binaries (/bin/cat and /bin/ls) to the system.
Description check ✅ Passed The description is well-detailed and directly related to the changeset, explaining the implementation of cat and ls utilities, their patterns, integration into xtask, and test results.
Linked Issues check ✅ Passed The PR successfully implements all coding requirements from issues #902 and #903: cat/ls binaries following base/sh/ pattern, stdin/argv file reading, error handling, directory listing with trailing slashes, syscalls.rs close() shim, and xtask wiring.
Out of Scope Changes check ✅ Passed All changes are directly in scope: two new utility crate implementations (cat and ls) following established patterns, syscalls modules, and xtask integration. No unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch m902-userspace-cat-ls

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
xtask/src/main.rs (1)

846-930: ⚡ Quick win

Factor the standalone userspace build flow into one helper.

build_userspace_cat, build_userspace_ls, and build_userspace_sh now all carry the same out-of-tree build-std/target-dir/strip sequence. That makes the next flag or path tweak easy to update in one helper and miss in the others.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xtask/src/main.rs` around lines 846 - 930, The three functions
build_userspace_cat, build_userspace_ls and build_userspace_sh duplicate the
same out-of-tree cargo invocation, target-dir handling, existence check and
strip_debug sequence; factor those common steps into a single helper (e.g.
build_userspace_bin or build_userspace_crate) that accepts the manifest path and
desired binary name (or crate dir) and returns the PathBuf, then replace
build_userspace_cat and build_userspace_ls to call that helper; ensure the
helper reproduces workspace_root(), VIBIX_USERSPACE_TARGET usage, sets
__CARGO_TESTS_ONLY_SRC_ROOT, runs the same cargo args, invokes
check(cmd.status()?) , verifies the binary exists at
target_dir.join("x86_64-unknown-vibix").join("debug").join(bin_name"), calls
strip_debug(&bin) and returns Ok(bin).
base/cat/src/main.rs (1)

23-64: ⚡ Quick win

Prefer returning ExitCode from main — it's more idiomatic than calling process::exit().

While this code works correctly (Rust's standard library ensures stdout is flushed during shutdown even when using process::exit()), returning ExitCode from main follows Rust conventions and avoids the less common exit path. No correctness risk here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@base/cat/src/main.rs` around lines 23 - 64, Change main to return
std::process::ExitCode instead of calling process::exit(): update the signature
of main to -> ExitCode, remove all process::exit(status) and process::exit(1)
calls, and at the end return ExitCode::from(status) (or return ExitCode::SUCCESS
/ ExitCode::from(1) where appropriate). Ensure you import std::process::ExitCode
or fully qualify it, and keep the existing logic in functions like cat_reader
unchanged while mapping the final integer status to an ExitCode.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@base/ls/src/main.rs`:
- Around line 50-73: The main function currently calls process::exit(status)
which bypasses normal stdio flushing; change main to return
std::process::ExitCode instead of calling process::exit. Keep the existing loop
and use the same status variable (or make it i32/u8 as you prefer), then at the
end return ExitCode::from(status as u8) (convert the final status to u8) and
remove the process::exit call; this preserves list_dir and its returns but
ensures stdout/stderr are flushed before exit.

---

Nitpick comments:
In `@base/cat/src/main.rs`:
- Around line 23-64: Change main to return std::process::ExitCode instead of
calling process::exit(): update the signature of main to -> ExitCode, remove all
process::exit(status) and process::exit(1) calls, and at the end return
ExitCode::from(status) (or return ExitCode::SUCCESS / ExitCode::from(1) where
appropriate). Ensure you import std::process::ExitCode or fully qualify it, and
keep the existing logic in functions like cat_reader unchanged while mapping the
final integer status to an ExitCode.

In `@xtask/src/main.rs`:
- Around line 846-930: The three functions build_userspace_cat,
build_userspace_ls and build_userspace_sh duplicate the same out-of-tree cargo
invocation, target-dir handling, existence check and strip_debug sequence;
factor those common steps into a single helper (e.g. build_userspace_bin or
build_userspace_crate) that accepts the manifest path and desired binary name
(or crate dir) and returns the PathBuf, then replace build_userspace_cat and
build_userspace_ls to call that helper; ensure the helper reproduces
workspace_root(), VIBIX_USERSPACE_TARGET usage, sets
__CARGO_TESTS_ONLY_SRC_ROOT, runs the same cargo args, invokes
check(cmd.status()?) , verifies the binary exists at
target_dir.join("x86_64-unknown-vibix").join("debug").join(bin_name"), calls
strip_debug(&bin) and returns Ok(bin).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a34ea613-0fd0-4761-8e7b-b3f54eff88cb

📥 Commits

Reviewing files that changed from the base of the PR and between 46c38d0 and 1c7ca82.

📒 Files selected for processing (7)
  • base/cat/Cargo.toml
  • base/cat/src/main.rs
  • base/cat/src/syscalls.rs
  • base/ls/Cargo.toml
  • base/ls/src/main.rs
  • base/ls/src/syscalls.rs
  • xtask/src/main.rs

Comment thread base/ls/src/main.rs Outdated
- Replace process::exit() with ExitCode return in cat and ls main
  functions to ensure stdout is flushed before exit.
- Factor the duplicated out-of-tree build-std cargo invocation into
  build_userspace_std_bin() and call it from sh/cat/ls wrappers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@dburkart dburkart merged commit e7b3382 into main May 6, 2026
15 checks passed
@dburkart dburkart deleted the m902-userspace-cat-ls branch May 6, 2026 05:33
dburkart added a commit that referenced this pull request May 6, 2026
…and /bin/uname (#913)

Closes #904
Closes #905

## Summary
- Add eight new base system programs following the cat/ls pattern from
PR #909: `stat`, `cp`, `mv`, `rm`, `mkdir`, `rmdir`, `touch`, and
`uname`
- Each is a standalone crate in `base/<name>/` with its own
`syscalls.rs` shim, built via the `build_userspace_std_bin()` helper
- All binaries are wired into the ext2 rootfs across all four extras
assembly sites (run ext2, run default, smoke, sh_test)
- Updated ext2 image hash

### Utilities
| Utility | Description | std API |
|---------|-------------|---------|
| `stat` | Print file type and size for paths | `fs::symlink_metadata()`
|
| `cp`    | Copy a file (`cp <src> <dst>`) | `fs::copy()` |
| `mv`    | Move/rename a file (`mv <src> <dst>`) | `fs::rename()` |
| `rm`    | Remove files (`rm <path>...`) | `fs::remove_file()` |
| `mkdir` | Create directories (`mkdir <path>...`) | `fs::create_dir()`
|
| `rmdir` | Remove empty directories (`rmdir <path>...`) |
`fs::remove_dir()` |
| `touch` | Create empty files if not exist |
`OpenOptions::new().create(true).write(true).open()` |
| `uname` | Print system info; `-a` for full | Hardcoded (no syscall
yet) |

## Test plan
- [x] `cargo xtask build` — passes
- [x] `cargo xtask smoke` — all 43 markers present
- [x] `cargo fmt --all -- --check` — clean
- [x] `cargo xtask ext2-image` — hash updated and verified

---------

Co-authored-by: vibix auto-engineer <noreply@anthropic.com>
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.

Userspace /bin/ls: list directory contents Userspace /bin/cat: concatenate files to stdout

2 participants