Skip to content

feat: option to prevent cross-filesystem traversal#363

Merged
KSXGitHub merged 73 commits intomasterfrom
claude/fix-mounted-directories-pEvuV
Mar 27, 2026
Merged

feat: option to prevent cross-filesystem traversal#363
KSXGitHub merged 73 commits intomasterfrom
claude/fix-mounted-directories-pEvuV

Conversation

@KSXGitHub
Copy link
Copy Markdown
Owner

@KSXGitHub KSXGitHub commented Mar 22, 2026

Closes #349.

This PR adds support for skipping directories on different filesystems, similar to the -x/--one-file-system flag found in tools like du. This allows users to analyze disk usage within a single filesystem without counting mounted directories.

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6

claude added 5 commits March 22, 2026 16:34
Directories on different devices (mount points) were being traversed,
leading to inaccurate usage reports and severe performance issues.
Compare each entry's device ID against the root's device ID and treat
cross-device directories as leaf nodes.

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Instead of unconditionally skipping cross-device directories, make it
opt-in via -x/--one-file-system (matching du convention). The default
behavior now crosses device boundaries like du, dust, and dua.

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 22, 2026

Performance Regression Reports

commit: b00e32c

There are no regressions.

claude and others added 2 commits March 22, 2026 18:39
…tforms

The `volume_serial_number()` API requires `windows_by_handle` which is
an unstable library feature (rust-lang/rust#63010), so --one-file-system
cannot be supported on Windows with stable Rust. Instead, return a
RuntimeError::UnsupportedFeature(OneFileSystem) early and remove the
Windows-specific device_id implementation.

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a --one-file-system / -x option to keep traversal within the root filesystem (similar to du -x), wiring the flag through the CLI/app layers into FsTreeBuilder, and updating generated help/docs and tests accordingly.

Changes:

  • Introduced filesystem device-id detection and used it in FsTreeBuilder to skip descending into directories on other filesystems when enabled.
  • Added --one-file-system / -x CLI flag and threaded it through AppSubFsTreeBuilder.
  • Updated tests and regenerated help/usage/completion exports to include the new option.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/fs_tree_builder.rs Adds one_file_system config and device-id checks during traversal.
src/fs_tree_builder/device_id.rs New platform-gated device-id helper used by FsTreeBuilder.
src/args.rs Adds --one-file-system / -x flag to CLI args (Unix-gated in help).
src/app.rs Validates/threads the flag and rejects it on non-Unix builds.
src/app/sub.rs Plumbs one_file_system into the FsTreeBuilder invocation.
src/runtime_error.rs Adds UnsupportedFeature::OneFileSystem for non-Unix.
tests/usual_cli.rs Updates FsTreeBuilder construction in CLI snapshot-style tests.
tests/json.rs Updates FsTreeBuilder construction for JSON-related test.
tests/cli_errors.rs Updates FsTreeBuilder construction for error-path tests.
tests/_utils.rs Updates shared FsTreeBuilder helper construction used by tests.
exports/short.help Regenerated short help including the new flag.
exports/long.help Regenerated long help including the new flag.
exports/completion.bash Regenerated bash completions including the new flag.
exports/completion.zsh Regenerated zsh completions including the new flag.
exports/completion.fish Regenerated fish completions including the new flag.
exports/completion.ps1 Regenerated PowerShell completions including the new flag.
exports/completion.elv Regenerated Elvish completions including the new flag.
USAGE.md Regenerated usage docs including the new flag.
README.md Removes prior limitation statement about not differentiating filesystems.

claude added 3 commits March 22, 2026 19:30
The `#[clap(long)]` attribute on `one_file_system` already generates
`--one-file-system`, so `visible_alias = "one-file-system"` was a
duplicate causing doubled anchors in USAGE.md and redundant entries in
shell completions. Regenerate all exports.

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Unit tests in device_id.rs verify that get_device_id returns equal IDs
for the same filesystem and different IDs across filesystems (/ vs /proc).

Integration tests in one_file_system.rs:
- same_device_on_sample_workspace: one_file_system=true produces the
  same tree as false when all files are on one device
- cross_device_excludes_mount: uses unshare --user --mount --map-root-user
  to create a tmpfs mount inside a user namespace (no root required) and
  verifies -x excludes entries on the mounted filesystem

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
The different_filesystem_returns_different_ids unit test uses /proc
(Linux-only) and /dev (macOS devfs), so split into two functions gated
with #[cfg(target_os = "linux")] and #[cfg(target_os = "macos")].

The cross_device_excludes_mount integration test uses unshare which is
Linux-only, so gate it with #[cfg(target_os = "linux")].

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.

claude added 9 commits March 22, 2026 21:38
- Use `writeln!` to build the shell script instead of `format!` with
  inline braces, making the script construction clearer
- Use `command_extra::CommandExtra` with `.with_args`/`.with_stdout`/
  `.with_stderr` instead of bare `std::process` methods
- Import `pretty_assertions::assert_eq` at module level

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
…tput

Write each pdu invocation's output to a separate temp file, then emit
them NUL-delimited with labels. Use find_section() to locate each
section by label instead of splitting on '===' and indexing.

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Replace the silent skip with a panic and actionable error message,
matching the pattern from `fs_errors`. The test can be excluded via
`RUSTFLAGS='--cfg pdu_test_skip_cross_device'`.

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
The previous check only verified that `unshare --user --mount
--map-root-user` succeeds, but not that tmpfs mounting is permitted
inside the namespace. On systems where user namespaces work but
unprivileged mounts are blocked, the test would fail instead of
being caught by the probe.

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
A bool discards the reason for failure. Return a Result with the
stderr output from the probe command so the panic message includes
actionable diagnostics (e.g. "unshare: unshare failed: Operation
not permitted").

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Replace the user-namespace-based (`unshare --user --mount`) cross-device
test with a FUSE-based approach using `fuse2fs`. User namespaces are
often disabled in CI containers, making the unshare test unreliable.

The new test creates a small ext2 filesystem image, mounts it via
`fuse2fs` (which only needs `/dev/fuse` and `fusermount`), and verifies
that `pdu -x` correctly excludes entries on the mounted filesystem.

Diagnostic messages clearly report which FUSE component is missing.
The `--cfg pdu_test_skip_cross_device` skip flag is preserved.

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 3 comments.

The `cross_device_excludes_mount` test requires `fuse2fs` (from
e2fsprogs) and `fusermount3` (from fuse3) to mount an ext2 image via
FUSE. Install these packages on Linux runners in both test.yaml and
deploy.yaml so the test can run in CI without being skipped.

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated 2 comments.

@KSXGitHub KSXGitHub force-pushed the claude/fix-mounted-directories-pEvuV branch from 054aa8f to 876739a Compare March 27, 2026 17:38
KSXGitHub and others added 3 commits March 28, 2026 00:50
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated 1 comment.

Align with the existing naming convention used by
`Direction::from_top_down` and `BarAlignment::from_align_right`.

https://claude.ai/code/session_01LfpnUZrgq93MVZgA3KVqE6
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated no new comments.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated 1 comment.

@KSXGitHub KSXGitHub force-pushed the claude/fix-mounted-directories-pEvuV branch from 3fab8d3 to cfddd52 Compare March 27, 2026 18:43
@KSXGitHub KSXGitHub marked this pull request as ready for review March 27, 2026 18:53
@KSXGitHub KSXGitHub merged commit 5a88f61 into master Mar 27, 2026
13 checks passed
@KSXGitHub KSXGitHub deleted the claude/fix-mounted-directories-pEvuV branch March 27, 2026 18:57
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.

3 participants