Skip to content

chmod: report Permission denied instead of No such file when stat fails#12338

Open
c-tonneslan wants to merge 1 commit into
uutils:mainfrom
c-tonneslan:fix/chmod-permission-denied
Open

chmod: report Permission denied instead of No such file when stat fails#12338
c-tonneslan wants to merge 1 commit into
uutils:mainfrom
c-tonneslan:fix/chmod-permission-denied

Conversation

@c-tonneslan
Copy link
Copy Markdown

Closes #9789.

Path::exists() returns false whenever it can't stat the path — including when the parent directory is unreadable. That makes chmod surface "No such file or directory" in cases where the file is actually there:

$ mkdir locked && touch locked/file && chmod 000 locked
$ chmod 000 locked/file                     # GNU
chmod: cannot access 'locked/file': Permission denied
$ ./target/debug/chmod 000 locked/file      # uutils (before this PR)
chmod: cannot access 'locked/file': No such file or directory

Swap exists() for try_exists() and emit the existing PermissionDenied variant when the kind matches. Other IO errors fall through and the actual chmod call surfaces its own message.

Path::exists() swallows the underlying io error and returns false on
"can't stat", so chmod was telling people "No such file or directory"
when the real problem was that the parent directory had mode 000:

    $ chmod 000 locked && chmod 000 locked/file
    chmod: cannot access 'locked/file': No such file or directory   # us
    chmod: cannot access 'locked/file': Permission denied            # GNU

Use try_exists() and surface the PermissionDenied case explicitly. Other
IO errors fall through to the actual chmod call so we still produce a
useful message there.

Closes uutils#9789.

Signed-off-by: Charlie Tonneslan <cst0520@gmail.com>
@github-actions
Copy link
Copy Markdown

GNU testsuite comparison:

GNU test failed: tests/timeout/timeout-group. tests/timeout/timeout-group is passing on 'main'. Maybe you have to rebase?
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/tail-n0f (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/tail/retry (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/tee/tee is no longer failing!
Congrats! The gnu test tests/printf/printf-surprise is now passing!
Congrats! The gnu test tests/seq/seq-epipe is now passing!

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.

chmod: behavioral divergence from coreutils when the target file is not accessible

1 participant