Andrew Burgess <[EMAIL PROTECTED]> writes:
| # bug1
| # cp gets confused when copying a symbolic link when the target link already exists
|
| cd /tmp
| rm -rf cptest*
| mkdir cptest
| mkdir cptest2
| echo foo > cptest/foo
| ln -s foo cptest/foolink
| cp -auxv cptest/* cptest2
| ls -l cptest* # looks good
| rm cptest/foolink
| sleep 2 # let the clock advance
| ln -s foo cptest/foolink # make the date on the link newer
| cp -auxv cptest/* cptest2
|
| # gives error: cp: cannot create symbolic link `cptest2/foolink': File exists
|
| # bug2
| # now almost the same thing except the link target doesn't exist
|
| cd /tmp
| rm -rf cptest*
| mkdir cptest
| mkdir cptest2
| ln -s foo cptest/foolink
| cp -auxv cptest/* cptest2
| ls -l cptest* # looks good
| rm cptest/foolink
| sleep 2 # let the clock advance
| ln -s foo cptest/foolink # make the date on the link newer
| cp -auxv cptest/* cptest2
|
| # gives: cp: overwrite `cptest2/foolink', overriding mode 0777?
| # even though --interactive was not specified
|
| If you do consider either of these to be errors and would like me to find and fix
|them
| and send you a patch please let me know.
Thanks for the report.
I've fixed it so those both work now.
Here's the change relative to the latest test release in
ftp://alpha.gnu.org/gnu/fetish/
Allow `cp -d -u' to copy one symlink onto another that's identical.
* src/copy.c (copy_internal): Change the || to ^ in the big sameness
test, so copying one symlink onto another, identical one doesn't fail
here.
If the symlink call fails, don't report the failure if the destination
already exists and is a symlink pointing to the proper name.
Reported by Andrew Burgess.
* tests/cp/slink-2-slink: New test.
* tests/cp/Makefile.am (TESTS): Add slink-2-slink.
* tests/cp/same-file: Adapt to fit new semantics of `cp -d'.
Index: copy.c
===================================================================
RCS file: /fetish/fileutils/src/copy.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -r1.60 -r1.61
--- copy.c 2000/05/12 20:40:39 1.60
+++ copy.c 2000/05/29 21:05:07 1.61
@@ -448,7 +448,7 @@
&& S_ISLNK (src_sb.st_mode)
&& !S_ISLNK (dst_sb.st_mode)))
&& !x->dereference
- && (S_ISLNK (dst_sb.st_mode) || S_ISLNK (src_sb.st_mode)))
+ && (S_ISLNK (dst_sb.st_mode) ^ S_ISLNK (src_sb.st_mode)))
{
struct stat dst2_sb;
struct stat src2_sb;
@@ -848,8 +848,28 @@
if (symlink (link_val, dst_path))
{
- error (0, errno, _("cannot create symbolic link `%s'"), dst_path);
- goto un_backup;
+ int saved_errno = errno;
+ int same_link = 0;
+ if (x->update && !new_dst && S_ISLNK (dst_sb.st_mode))
+ {
+ /* See if the destination is already the desired symlink. */
+ char *dest_link_name = (char *) alloca (PATH_MAX + 2);
+ int dest_link_len = readlink (dst_path, dest_link_name,
+ PATH_MAX + 1);
+ if (dest_link_len > 0)
+ {
+ dest_link_name[dest_link_len] = '\0';
+ if (STREQ (dest_link_name, link_val))
+ same_link = 1;
+ }
+ }
+
+ if (! same_link)
+ {
+ error (0, saved_errno, _("cannot create symbolic link `%s'"),
+ dst_path);
+ goto un_backup;
+ }
}
if (x->preserve_owner_and_group)