`cp -r` throws read permission error on unwritable destination file (mode: 440)
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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