cvs commit: src/bin/cp cp.1
Tom Rhodes
trhodes at FreeBSD.org
Thu Feb 24 23:28:53 GMT 2005
On Fri, 25 Feb 2005 05:37:20 +1100 (EST)
Bruce Evans <bde at zeta.org.au> wrote:
> On Thu, 24 Feb 2005, Tom Rhodes wrote:
>
> > trhodes 2005-02-24 00:06:22 UTC
> >
> > FreeBSD src repository
> >
> > Modified files:
> > bin/cp cp.1
> > Log:
> > Note how cp(1) handles directories ending in "/."
>
> I think you mean ones ending in "/". Ones ending in "/." are similarly
> mishandled, but this is not noted. The strange English rule for putting
> "." in quotes is very confusing here. I don't know the exact rule.
In my case, I was using the period to end the sentence, not to
cover the "." entry in the file system.
With regards to English, I was always taught that you end a sentence
with punctuation in quotes; however, this rule may be broken when
confusion may occur. This seems to be one of those cases and I
double checked with my friend, Matt, who teaches college
English courses.
>
> >
> > PR: 75774
> > Submitted by: Mike Meyer <mwm at mired.org> (original version)
>
> This is a bug in cp.c, not in cp.1. cp starts getting confused here:
>
> % /*
> % * If we are in case (2) or (3) above, we need to append the
> % * source name to the target name.
> % */
> % if (type != FILE_TO_FILE) {
> % /*
> % * Need to remember the roots of traversals to create
> % * correct pathnames. If there's a directory being
> % * copied to a non-existent directory, e.g.
> % * cp -R a/dir noexist
> % * the resulting path name should be noexist/foo, not
> % * noexist/dir/foo (where foo is a file in dir), which
> % * is the case where the target exists.
I had to read that paragraph twice.
> % *
> % * Also, check for "..". This is for correct path
> % * concatenation for paths ending in "..", e.g.
> % * cp -R .. /tmp
> % * Paths ending in ".." are changed to ".". This is
> % * tricky, but seems the easiest way to fix the problem.
> % *
> % * XXX
> % * Since the first level MUST be FTS_ROOTLEVEL, base
> % * is always initialized.
> % */
> % if (curr->fts_level == FTS_ROOTLEVEL) {
> % if (type != DIR_TO_DNE) {
> % p = strrchr(curr->fts_path, '/');
> % base = (p == NULL) ? 0 :
> % (int)(p - curr->fts_path + 1);
> %
> % if (!strcmp(&curr->fts_path[base],
> % ".."))
> % base += 1;
> % } else
> % base = curr->fts_pathlen;
> % }
>
> It needs to strip to the basename, but for source file names ending in a
> slash, it strips everything. This is handled correctly in basename(3).
> OTOH, cp needs something special for "foo/.." and basename() doesn't do
> the right thing for that (it gives ".."). Somehow stripping "foo/.."
> to "." doesn't give the same result as stripping "foo/." to ".".
>
> There is an interesting subcase of this bug for symlinks. After:
>
> mkdir /tmp/z
> cd /tmp/z
> mkdir a1 b
> ln -s a1 a
>
> "cp -R a/ b" copies nothing but succeeds (wrong), but part of
> "cp -pR a/ b" thinks that the other part copied something and fails
> trying to change the attributes:
>
> %%%
> cp: utimes: b/a: No such file or directory
> cp: chown: b/a: No such file or directory
> cp: chmod: b/a: No such file or directory
> cp: chflags: b/a: No such file or directory
> %%%
>
> Then after putting a file in "a1", "cp -R a/ b" just copies the wrong
> thing (it follows the symlink OK but then copies the contents of the
> directory pointed to by the symlink when it should copy the directory
> itself) and then "cp -pR" doesn't try to change the attributes of a
> nonexistent file.
>
> The case of a trailing slash is most important for symlinks since it is
> the only way to get "cp -R" to follow the symlink.
>
> Bruce
>
So, do you want to fix the bugs or should I just move the part
I added into a BUGS section?
--
Tom Rhodes
More information about the cvs-src
mailing list