summaryrefslogtreecommitdiff
path: root/src/copy.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2005-03-11 09:36:52 +0000
committerJim Meyering <jim@meyering.net>2005-03-11 09:36:52 +0000
commitd0f21b4a5583235001aaac254efc0802de414eec (patch)
tree706ad85397b060e1294b8c82d7b3e165897ef924 /src/copy.c
parentd1d993432f0a4460e426b32e6442e0bded14ece0 (diff)
downloadcoreutils-d0f21b4a5583235001aaac254efc0802de414eec.tar.xz
Prompt once again for `mv -i A B' when A and B are hard links
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.
Diffstat (limited to 'src/copy.c')
-rw-r--r--src/copy.c34
1 files changed, 25 insertions, 9 deletions
diff --git a/src/copy.c b/src/copy.c
index 62cf4ec6e..88df1d4b3 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -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. */