bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: mv silently does nothing for hard links


From: Paul Eggert
Subject: Re: mv silently does nothing for hard links
Date: 07 Apr 2003 16:33:31 -0700
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3

Jim Meyering <address@hidden> writes:

> Here's a patch that solves the problem at zero-to-negligible cost.

You mentioned in
<http://www.opengroup.org/sophocles/show_mail.tpl?source=L&listname=austin-group-l&id=5156>
that NetBSD rename(A,B) removes A if A and B are hard links but are
distinct directory entries, but from code inspection it appears that
copy_internal will report an error in that case.  Surely it shouldn't
report an error, as it's not the user's fault that NetBSD behaves the
way that the POSIX authors intended (as opposed to what they actually
wrote down :-).

Also, I'm not sure I follow the code completely, but shouldn't hard
links to symbolic links be handled the same way as hard links to
regular files?  If rename(A,B) does nothing when A and B are hard
links to the same symbolic link, then that situation also needs to be
protected against.

Here's a draft (untested) patch to give you a feel for what I'm talking
about.


2003-04-07  Paul Eggert  <address@hidden>

        * src/copy.c (same_file_ok): Set *UNLINK_SRC for hard links to
        symlinks, too.
        (copy_internal): Don't complain if an UNLINK_SRC-prompted unlink
        fails with errno==ENOENT.  That is the expected behavior on
        NetBSD, and I guess it might also happen on other systems that
        use a NetBSD filesystem remotely.

--- copy.c      2003-04-07 16:10:02.043752000 -0700
+++ copy-fix.c  2003-04-07 16:21:27.256142000 -0700
@@ -561,9 +561,6 @@ same_file_ok (const char *src_path, cons
      It's also ok if they're distinct hard links to the same file.  */
   if (x->move_mode || x->unlink_dest_before_opening)
     {
-      if (S_ISLNK (dst_sb_link->st_mode))
-       return 1;
-
       if (same_link && !same_name (src_path, dst_path))
        {
          if (x->move_mode)
@@ -573,6 +570,9 @@ same_file_ok (const char *src_path, cons
            }
          return 1;
        }
+
+      if (S_ISLNK (dst_sb_link->st_mode))
+       return 1;
     }
 
   /* If neither is a symlink, then it's ok as long as they aren't
@@ -883,7 +883,7 @@ copy_internal (const char *src_path, con
                                 x, &return_now, &unlink_src);
          if (unlink_src)
            {
-             if (unlink (src_path))
+             if (unlink (src_path) && errno != ENOENT)
                {
                  error (0, errno, _("cannot remove %s"), quote (src_path));
                  return 1;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]