GNU bug report logs -
#32455
cp gets confused by symlinks to parent directory
Previous Next
Reported by: Mike Crowe <mac <at> mcrowe.com>
Date: Thu, 16 Aug 2018 14:48:01 UTC
Severity: normal
Tags: notabug
Done: Assaf Gordon <assafgordon <at> gmail.com>
Bug is archived. No further changes may be made.
Full log
Message #8 received at 32455 <at> debbugs.gnu.org (full text, mbox):
tags 32455 notabug
close 32455
stop
Hello,
It seems your message has not been replied to in a long while.
Sorry about that.
On 2018-08-16 8:47 a.m., Mike Crowe wrote:
> If cp is passed the -d option and told to copy a symlink to the directory
> containing the symlink then it ends up removing the target directory so it
> is unable to create the symlink.
If my understanding is correct, the "-d" flag is not relevant to the
issue. The problem is that "self" is a symlink to a directory:
>
> Reproduction script:
>
> --8<--
> #!/bin/sh
> set -x
>
> rm -rf temp
> mkdir -p temp/src temp/dest
>
> ln -s . temp/src/self
>
> # This one works
> cp -vd temp/src/self temp/dest/self
This works because "temp/dest/self" does not exist.
In this case, "temp/dest" is taken as the destination directory,
and "self" is taken as the name of the file/dir/symlink to create.
That is, you could run "cp -vd temp/src/self temp/dest/foobar"
to create "foobar" as a copy of "self".
> # This one fails
> cp -vd temp/src/self temp/dest/self
Here, "temp/dest/self" already exists, and it is a symlink to
a directory.
Meaning, the request is: copy "temp/src/self" into the directory
"temp/dest/self/" (and create "temp/dest/self/self").
This would have gone well, except that because "self" is a symlink
to ".", it can be resolved indefinitely:
$ file temp/dest/self
temp/dest/self: symbolic link to .
$ file temp/dest/self/self/self/self/self/self
temp/dest/self/self/self/self/self/self: symbolic link to .
$ file temp/dest/self/self/self/self/self/self/self
temp/dest/self/self/self/self/self/self/self: symbolic link to .
"cp" first removes "temp/dest/self/self" (which is valid),
but then, "temp/dest/self" is gone (since it is the same file path after
resolving it).
Hence, "cp" fails by saying "no such directory" on "temp/dest/self/self".
When this step is done, "temp/dest/self" does not exist,
and so:
> # This one works again
> cp -vd temp/src/self temp/dest/self
This works as before.
You can observe what happens on the kernel level
by adding "strace -e trace=file" before the "cp" commands,
this might help in deeper understanding.
To illustrate this differently:
When creating regular directories and files,
then deleting the innermost files, it is naively expected
that the parent directories still exist:
mkdir -p a/b/c/d
touch a/b/c/d/e
rm a/b/c/d/e
That is, a normal program can call "dirname("a/b/c/d/e")"
to get the parent directory of "e", and expect it to still
exist even after "e" is deleted.
But with your case:
$ mkdir a
$ ln -s . a/self
$ rm a/self/self/self/self/self/self
All the "apparent" parent directories ("self/self/self/self/self")
are gone!
> Expected behaviour:
>
> There should be no error message emitted by the second invocation of cp,
> and the target directory should be in the same state as it is after the
> first or third attempts to copy the symlink.
Not exactly.
What you want is for the DEST parameter of "cp" to always be a file,
never to be considered a directory, i.e. "temp/dest/self"
should always be interpreted as file "self" in directory "temp/dest",
never as directory "temp/dest/self".
Luckily, there is already an option for that:
-T, --no-target-directory
treat DEST as a normal file
With "-T", repeated commands work as you expected:
$ mkdir -p temp/src temp/dest
$ ln -s . temp/src/self
$ cp -vdT temp/src/self temp/dest/self
'temp/src/self' -> 'temp/dest/self'
$ cp -vdT temp/src/self temp/dest/self
removed 'temp/dest/self'
'temp/src/self' -> 'temp/dest/self'
$ cp -vdT temp/src/self temp/dest/self
removed 'temp/dest/self'
'temp/src/self' -> 'temp/dest/self'
$ cp -vdT temp/src/self temp/dest/self
removed 'temp/dest/self'
'temp/src/self' -> 'temp/dest/self'
[... ad infinitum ...]
I hope this addresses the issue,
I'm closing this as "not a bug", but discussion can continue by replying
to this thread.
regards,
- assaf
This bug report was last modified 6 years and 163 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.