Prompt once again for `mv -i A B' when A and B are hard links
authorJim Meyering <jim@meyering.net>
Fri, 11 Mar 2005 09:36:52 +0000 (09:36 +0000)
committerJim Meyering <jim@meyering.net>
Fri, 11 Mar 2005 09:36:52 +0000 (09:36 +0000)
to the same file.  This fixes a bug introduced by my 2003-04-04
(coreutils-5.0.1) change.

(abandon_move): New function, factored out of
copy_internal, now that this code is being used from two places.
(copy_internal): Perform the same interactive-related test for
whether it's alright to proceed and (usually) overwrite the
destination file.

src/copy.c

index 62cf4ec6e7078bd5223e885ddd938b7e4f6bd516..88df1d4b366b56cd5943d117334d00c50fc8101f 100644 (file)
@@ -792,6 +792,28 @@ record_file (Hash_table *ht, char const *filename,
   }
 }
 
+/* When effecting a move (e.g., for mv(1)), and given the name DST_PATH
+   of the destination and a corresponding stat buffer, DST_SB, return
+   true if the logical `move' operation should not proceed.
+   Return true if it may proceed.
+   Depending on options specified in X, this code may issue an
+   interactive prompt asking whether it's ok to overwrite DST_PATH.  */
+static bool
+abandon_move (const struct cp_options *x,
+              char const *dst_path,
+              struct stat const *dst_sb)
+{
+  assert (x->move_mode);
+  return ((x->interactive == I_ALWAYS_NO
+           && UNWRITABLE (dst_path, dst_sb->st_mode))
+          || ((x->interactive == I_ASK_USER
+               || (x->interactive == I_UNSPECIFIED
+                   && x->stdin_tty
+                   && UNWRITABLE (dst_path, dst_sb->st_mode)))
+              && (overwrite_prompt (dst_path, dst_sb), 1)
+              && ! yesno ()));
+}
+
 /* Copy the file SRC_PATH to the file DST_PATH.  The files may be of
    any type.  NEW_DST should be true if the file DST_PATH cannot
    exist because its parent directory was just created; NEW_DST should
@@ -887,7 +909,8 @@ copy_internal (const char *src_path, const char *dst_path,
                                  x, &return_now, &unlink_src);
          if (unlink_src)
            {
-             if (unlink (src_path))
+             if (!abandon_move (x, dst_path, &dst_sb)
+                 && unlink (src_path))
                {
                  error (0, errno, _("cannot remove %s"), quote (src_path));
                  return false;
@@ -980,14 +1003,7 @@ copy_internal (const char *src_path, const char *dst_path,
              /* cp and mv treat -i and -f differently.  */
              if (x->move_mode)
                {
-                 if ((x->interactive == I_ALWAYS_NO
-                      && UNWRITABLE (dst_path, dst_sb.st_mode))
-                     || ((x->interactive == I_ASK_USER
-                          || (x->interactive == I_UNSPECIFIED
-                              && x->stdin_tty
-                              && UNWRITABLE (dst_path, dst_sb.st_mode)))
-                         && (overwrite_prompt (dst_path, &dst_sb), 1)
-                         && ! yesno ()))
+                 if (abandon_move (x, dst_path, &dst_sb))
                    {
                      /* Pretend the rename succeeded, so the caller (mv)
                         doesn't end up removing the source file.  */