incorrect cp(1) behaviour upon "mkdir foo; cp -r foo foo"

Bug #154602 reported by ropers
4
Affects Status Importance Assigned to Milestone
coreutils
Confirmed
Undecided
Unassigned
coreutils (Ubuntu)
Triaged
Wishlist
Unassigned

Bug Description

Binary package hint: coreutils

GNU coreutils cp(1) behaves incorrectly if the user tries to copy a directory recursively. It (rightly) prints an error message, BUT copies the directory anyway, at least one level deep. To demonstrate:

| ropers@tranquility:~$ uname -a
| Linux tranquility 2.6.22-14-386 #1 Sun Oct 14 22:36:54 GMT 2007 i686 GNU/Linux

We're using Ubuntu "Gutsy Gibbon" 7.10.

| ropers@tranquility:~$ mkdir foo
| ropers@tranquility:~$ touch foo/testfile

We're creating a folder containing one file.

| ropers@tranquility:~$ cp -r foo foo
| cp: cannot copy a directory, `foo', into itself, `foo/foo'

We're trying to copy that folde into itself. cp(1) prints an error (as it should). However, ls -al (ll) shows that despite the error message, foo and the testfile it contains have nevertheless been copied into foo:

| ropers@tranquility:~$ ll foo
| total 12
| drwxr-xr-x 3 ropers ropers 4096 2007-10-19 22:57 ./
| drwxr-xr-x 85 ropers ropers 4096 2007-10-19 22:56 ../
| drwxr-xr-x 2 ropers ropers 4096 2007-10-19 22:57 foo/
| -rw-r--r-- 1 ropers ropers 0 2007-10-19 22:56 testfile
| ropers@tranquility:~$ ll foo/foo
| total 8
| drwxr-xr-x 2 ropers ropers 4096 2007-10-19 22:57 ./
| drwxr-xr-x 3 ropers ropers 4096 2007-10-19 22:57 ../
| -rw-r--r-- 1 ropers ropers 0 2007-10-19 22:57 testfile
| ropers@tranquility:~$

This should not happen. When asked to copy a directory recursively, cp(1) should print an error and not perform any copy operation at all.

Revision history for this message
C de-Avillez (hggdh2) wrote :

My understanding is the behaviour is correct: when 'cp' is copying to a directory, it will copy *under* the target directory, not *over* it. So it will start the copy and later it will notice it is copying recursively -- and immediately stop.

Nevertheless, I am open to suggestions ;-)

Changed in coreutils:
importance: Undecided → Low
status: New → Incomplete
Revision history for this message
jaduncan (jaduncan) wrote :

This is correct behaviour as per POSIX - it's how it should work!

This is something that would be an upstream bug, but they will not want to change this behaviour.

Changed in coreutils:
assignee: nobody → jaduncan
status: Incomplete → Invalid
Revision history for this message
ropers (ropers) wrote : Re: [Bug 154602] Re: incorrect cp(1) behaviour upon "mkdir foo; cp -r foo foo"

2009/3/30 jaduncan <email address hidden>:
> This is correct behaviour as per POSIX - it's how it should work!

Says who?

> This is something that would be an upstream bug, but they will not want
> to change this behaviour.

Well, have you asked them?

Revision history for this message
C de-Avillez (hggdh2) wrote :

Interesting. Jim Meyring's answer did not make it here (although, AFAICS, it was correctly addressed). So, here it is:

Jens Ropers wrote:
> 2009/3/30 jaduncan <email address hidden>:
>> This is correct behaviour as per POSIX - it's how it should work!
>
> Says who?

I'm confident that POSIX does not require
cp -r dir dir to create dir/dir ;-)

>> This is something that would be an upstream bug, but they will not want
>> to change this behaviour.
>
> Well, have you asked them?

I don't like the existing behavior, but this is a rather hairy corner of
copy.c already, and considering we're talking about the state left after
the user runs a bogus command (which is surprisingly hard to detect _in
general_), I'm in no big hurry to fix it.

However, if someone sends in a perfect patch,

  http://git.sv.gnu.org/cgit/coreutils.git/plain/HACKING

I'll be very interested.

Revision history for this message
C de-Avillez (hggdh2) wrote :

And, just for the record: it is "Jim Meyering". I missed an 'e'. Sorry.

Left for consideration is it is worth it to reopen and set as wishlist. Jim's response suggests that. Since, right now, this bug is assigned to jaducan, I am not changing it -- right now.

Revision history for this message
ropers (ropers) wrote :

2009/3/31 C de-Avillez <email address hidden>:
> Interesting. Jim Meyring's answer did not make it here (although,
> AFAICS, it was correctly addressed). So, here it is:
>
> Jens Ropers wrote:
>> 2009/3/30 jaduncan <email address hidden>:
>>> This is correct behaviour as per POSIX - it's how it should work!
>>
>> Says who?
>
> I'm confident that POSIX does not require
> cp -r dir dir to create dir/dir ;-)

Just to clarify again, what bothers me about this is that cp says that
is can't copy a directory into itself *and then does it anyway, once*.

[I.] If it said that it can't do it and then didn't do it, that would be fine.

[II.] If it accepted the recursive directory copying command and tried
to execute it until it errored out because the path got too long, that
would be fine as well. Possibly a bit crude, but better than the
current inconsistency between what it says it can't do and what it
still does.

I tried this on OpenBSD 4.3 for comparison purposes:

Unlike GNU's coreutils cp(1), OpenBSD's cp(1) --which is derived from
AT&T UNIX Version 1-- expressly says on its man page that it is
POSIX-compliant: http://www.openbsd.org/cgi-bin/man.cgi?query=cp
OpenBSD's cp(1) behaves as described under [II.]: It recursively
copies foo into itself until the path becomes too long, at which stage
it produces an error message and stops copying any further. This
produces a long subtree of foo/foo/foo/foo... and so forth, and the
testfile is also present at each level. Again, this may seem more
bare-bones, as it doesn't attempt to catch attempts at recursive
copying beforehand, but it's actually more consistent and more logical
and doesn't do anything it said it couldn't do.

So apologies if I'm being impolite, but I'm more inclined to believe
that OpenBSD's cp(1) really is POSIX-compliant --as its man page says
it is-- than I am inclined to believe jaduncan's claim that GNU
coreutils cp(1) was POSIX-compliant.
Of course it's also possible that POSIX doesn't specify at all how
cp(1) should behave in this case. But that too would only invalidate
jaduncan's citation of POSIX compliance in his objection.

And yes, I absolutely believe that it makes good sense to keep this
open as a tracking bug here, and to take it up with upstream. And
--apologies again-- but I'm sceptical of the declaration that the GNU
project would not want to change this; asking won't hurt.

Thanks and regards,
--ropers

>>> This is something that would be an upstream bug, but they will not want
>>> to change this behaviour.
>>
>> Well, have you asked them?
>
> I don't like the existing behavior, but this is a rather hairy corner of
> copy.c already, and considering we're talking about the state left after
> the user runs a bogus command (which is surprisingly hard to detect _in
> general_), I'm in no big hurry to fix it.
>
> However, if someone sends in a perfect patch,
>
>  http://git.sv.gnu.org/cgit/coreutils.git/plain/HACKING
>
> I'll be very interested.

Revision history for this message
Jim Meyering (meyering) wrote : Re: [Bug 154602] Re: incorrect cp(1) behaviour upon "mkdir foo; cp -r foo foo"

C de-Avillez wrote:
> Interesting. Jim Meyring's answer did not make it here (although,
> AFAICS, it was correctly addressed). So, here it is:

Thanks for forwarding that. It didn't go through because
I sent it with a From address not matching the subscribed one.

Revision history for this message
jaduncan (jaduncan) wrote :

Original refusal was based on an IRC refusal, but upstream have now said that while they won't do the work they are interested in patches. Reopened to track.

Changed in coreutils:
status: Invalid → Confirmed
Revision history for this message
ropers (ropers) wrote : Re: [Bug 154602] Re: incorrect cp(1) behaviour upon "mkdir foo; cp -r foo foo"

Thank you! :)

2009/3/31 jaduncan <email address hidden>:
> Original refusal was based on an IRC refusal, but upstream have now said
> that while they won't do the work they are interested in patches.
> Reopened to track.
>
> ** Changed in: coreutils (Ubuntu)
>       Status: Invalid => Confirmed
>
> --
> incorrect cp(1)  behaviour upon "mkdir foo; cp -r foo foo"
> https://bugs.launchpad.net/bugs/154602
> You received this bug notification because you are a direct subscriber
> of the bug.
>

Revision history for this message
C de-Avillez (hggdh2) wrote :

A bit of update on this (from the coreutils ML; the mini-thread (so far) can be seen here: http://lists.gnu.org/archive/html/bug-coreutils/2009-03/msg00469.html.

---------begin email---------
> I'm confident that POSIX does not require
> cp -r dir dir to create dir/dir ;-)

That's certainly true: an implementation is clearly allowed to (but not
required to) report an error and exit without doing anything when it
sees this example. However, that's not what GNU cp does, which raises
the issue.

As near as I can figure out, this is a hole in POSIX. It nowhere
specifies what "cp" should do when inputs and outputs overlap, which
they can in even-more-interesting ways than "cp -R dir dir". Perhaps
this should be raised with the POSIX folks, but in the meantime I don't
see that GNU cp needs to change as far as conformance goes.
---------end email---------

Also, from Jens' previous comment:

"And yes, I absolutely believe that it makes good sense to keep this
open as a tracking bug here, and to take it up with upstream. And
--apologies again-- but I'm sceptical of the declaration that the GNU
project would not want to change this; asking won't hurt."

Jim is the upstream maintainer for coreutils, so he already answered it: upstream is not going to run and, er, correct it, but are very willing to accept such a patch. If it helps any, my personal (and meager) experience with upstream is that they will help on getting a patch.

So. The offer is open. Anyone willing to write such a patch, please feel welcome.

Revision history for this message
C de-Avillez (hggdh2) wrote :

Setting to Triaged/Wishlist; adding an upstream tracker to the email thread.

Changed in coreutils:
assignee: jaduncan → nobody
importance: Low → Wishlist
status: Confirmed → Triaged
Revision history for this message
C de-Avillez (hggdh2) wrote :

@jaduncan: when I added the upstream tracker, you got unassigned from the bug. While I think this was indeed the correct option, please feel free to reassign yourself, *as long as* you are actively working on writing the patch.

Otherwise, anyone willing to write such as patch (as I have already stated)... feel welcome. We appreciate the help ;-)

Revision history for this message
C de-Avillez (hggdh2) wrote :

I should have done that earlier. Setting upstream task to confirmed (actually, it should be wishlist, but we do not have such a status).

Changed in coreutils:
status: New → Confirmed
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

  • auto-bug-coreutils Edit

Bug watches keep track of this bug in other bug trackers.