Allow `cp -d -u' to copy one symlink onto another that's identical.
authorJim Meyering <jim@meyering.net>
Mon, 29 May 2000 21:05:07 +0000 (21:05 +0000)
committerJim Meyering <jim@meyering.net>
Mon, 29 May 2000 21:05:07 +0000 (21:05 +0000)
(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.

src/copy.c

index 48b4d22..32f5e5b 100644 (file)
@@ -448,7 +448,7 @@ copy_internal (const char *src_path, const char *dst_path,
                      && 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 @@ copy_internal (const char *src_path, const char *dst_path,
 
       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)