Date: Thu, 24 Feb 2005 18:28:40 -0500 From: Tom Rhodes <trhodes@FreeBSD.org> To: Bruce Evans <bde@zeta.org.au> Cc: cvs-src@FreeBSD.org Subject: Re: cvs commit: src/bin/cp cp.1 Message-ID: <20050224182840.5740b751@mobile.pittgoth.com> In-Reply-To: <20050225042045.L99633@delplex.bde.org> References: <200502240006.j1O06MDs099490@repoman.freebsd.org> <20050225042045.L99633@delplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, 25 Feb 2005 05:37:20 +1100 (EST) Bruce Evans <bde@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@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050224182840.5740b751>