diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2006-09-20 17:32:14 +0000 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2006-09-20 17:32:14 +0000 |
commit | 2a01141018637fc06604335aea673dff95efd033 (patch) | |
tree | 4cf78e6c99e09e4a5d947e465b92829fc7a43bae /src | |
parent | fae30e1af9aec9486b0a278c1c5e7b8c6abba498 (diff) | |
download | coreutils-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.c | 82 |
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. */ |