summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2006-09-20 17:32:14 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2006-09-20 17:32:14 +0000
commit2a01141018637fc06604335aea673dff95efd033 (patch)
tree4cf78e6c99e09e4a5d947e465b92829fc7a43bae /src
parentfae30e1af9aec9486b0a278c1c5e7b8c6abba498 (diff)
downloadcoreutils-2a01141018637fc06604335aea673dff95efd033.tar.xz
* NEWS: Document fix for cp -i and mv -i.
* src/copy.c (copy_internal): With -i, prompt even if the source is a directory and the destination is not. This is required by POSIX and gives the user a chance to bail out before failing. * tests/cp/Makefile.am (TESTS): Add cp-i. * tests/cp/cp-i: New file. * tests/mv/Makefile.am (TESTS): Add i-5. * tests/mv/i-5: New file.
Diffstat (limited to 'src')
-rw-r--r--src/copy.c82
1 files changed, 36 insertions, 46 deletions
diff --git a/src/copy.c b/src/copy.c
index f8b0ee678..c1f374049 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -1036,31 +1036,52 @@ copy_internal (char const *src_name, char const *dst_name,
that it is XSTAT'able. */
bool return_now;
bool unlink_src;
- bool ok = same_file_ok (src_name, &src_sb, dst_name, &dst_sb,
- x, &return_now, &unlink_src);
- if (unlink_src)
+
+ if (! same_file_ok (src_name, &src_sb, dst_name, &dst_sb,
+ x, &return_now, &unlink_src))
+ {
+ error (0, 0, _("%s and %s are the same file"),
+ quote_n (0, src_name), quote_n (1, dst_name));
+ return false;
+ }
+
+ /* When there is an existing destination file, we may end up
+ returning early, and hence not copying/moving the file.
+ This may be due to an interactive `negative' reply to the
+ prompt about the existing file. It may also be due to the
+ use of the --reply=no option.
+
+ cp and mv treat -i and -f differently. */
+ if (x->move_mode)
{
- if (!abandon_move (x, dst_name, &dst_sb)
- && unlink (src_name) != 0)
+ if (abandon_move (x, dst_name, &dst_sb)
+ || (unlink_src && unlink (src_name) == 0))
+ {
+ /* Pretend the rename succeeded, so the caller (mv)
+ doesn't end up removing the source file. */
+ if (rename_succeeded)
+ *rename_succeeded = true;
+ return true;
+ }
+ if (unlink_src)
{
error (0, errno, _("cannot remove %s"), quote (src_name));
return false;
}
- /* Tell the caller that there's no need to remove src_name. */
- if (rename_succeeded)
- *rename_succeeded = true;
+ }
+ else
+ {
+ if (! S_ISDIR (src_mode)
+ && (x->interactive == I_ALWAYS_NO
+ || (x->interactive == I_ASK_USER
+ && (overwrite_prompt (dst_name, &dst_sb), 1)
+ && ! yesno ())))
+ return true;
}
if (return_now)
return true;
- if (! ok)
- {
- error (0, 0, _("%s and %s are the same file"),
- quote_n (0, src_name), quote_n (1, dst_name));
- return false;
- }
-
if (!S_ISDIR (dst_sb.st_mode))
{
if (S_ISDIR (src_type))
@@ -1140,37 +1161,6 @@ copy_internal (char const *src_name, char const *dst_name,
}
}
- /* When there is an existing destination file, we may end up
- returning early, and hence not copying/moving the file.
- This may be due to an interactive `negative' reply to the
- prompt about the existing file. It may also be due to the
- use of the --reply=no option. */
- if (!S_ISDIR (src_type))
- {
- /* cp and mv treat -i and -f differently. */
- if (x->move_mode)
- {
- if (abandon_move (x, dst_name, &dst_sb))
- {
- /* Pretend the rename succeeded, so the caller (mv)
- doesn't end up removing the source file. */
- if (rename_succeeded)
- *rename_succeeded = true;
- return true;
- }
- }
- else
- {
- if (x->interactive == I_ALWAYS_NO
- || (x->interactive == I_ASK_USER
- && (overwrite_prompt (dst_name, &dst_sb), 1)
- && ! yesno ()))
- {
- return true;
- }
- }
- }
-
if (x->move_mode)
{
/* Don't allow user to move a directory onto a non-directory. */