uutils / uutils/coreutils

`cp -r` throws read permission error on unwritable destination file (mode: 440)

Open
#9,235 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

U - cp
Dominant language
Rust
Stars
24.1k
Forks
2k
Avg merge
1d 5h
Merged PRs (30d)
365

Description

When copying recursively and trying to overwrite existing files with write permission flag removed, e.g. mode 440, cp fails for the wrong reason:

coreutils --version
coreutils 0.4.0 (multi-call binary)

umask
027
mkdir a b
touch a/foo
chmod -w a/foo # mode is now 440
cd b

coreutils cp -r ../a .
# and again to try overwriting
coreutils cp -r ../a .
cp: cannot open '../a/foo' for reading: permission denied

# and now GNU coreutils
cp -r ../a .
cp: cannot create regular file './a/foo': Permission denied

# when overwriting the file directly (without -r) the error is correct, albeit the message differs
coreutils cp ../a/foo a
cp: '../a/foo' -> 'a/foo': Permission denied (os error 13) # I like the GNU message more, os error 13 means nothing to me but that the target is a regular file is not immediately obvious

Somewhere there is confusion about the cause of the error, because the cause is clearly the unwritable destination. And it must be something to do with recursive copying, because when overwriting the destination file directly the error message matches the failure condition.

Also the (last, correct) message is not quite the same as the one GNU cp emits. I don't know if this counts as one of those feature parity bugs or if it's an intended divergence, but in this case I find the GNU message just a tad more informative. As a user I have never seen os error 13 and I'd argue that users don't need to concern themselves with such details; they should be translated, i.e. "Permission denied", "os error 13" is thus redundant. The space is better used by providing additional information, such as the GNU message, that the destination is a regular file.

P.S.: I don't think it's relevant but for completeness I've added information about the umask.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the recursive overwrite case with an existing mode-440 destination file, then inspect the cp recursive-copy entry point and its error handling. Done means the failure identifies the unwritable destination rather than the source, and the resulting message is as informative as the direct-copy case.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.