]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
* NEWS: Document fix for cp -i and mv -i.
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 20 Sep 2006 17:32:14 +0000 (17:32 +0000)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 20 Sep 2006 17:32:14 +0000 (17:32 +0000)
* 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.

ChangeLog
NEWS
src/copy.c
tests/cp/Makefile.am
tests/cp/cp-i [new file with mode: 0755]
tests/mv/Makefile.am
tests/mv/i-5 [new file with mode: 0755]

index f31c1e76bbabbd7aa78aaeb4252c2529ec69d2dd..6455f6939ac10d84f11fd10d817eb9d9be87cdc1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2006-09-20  Paul Eggert  <eggert@cs.ucla.edu>
+
+       * 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.
+
 2006-09-20  Jim Meyering  <jim@meyering.net>
 
        * NEWS: Mention the chmod bug fix.
diff --git a/NEWS b/NEWS
index 21dcc4cf6aa1a04adfb134e53331294d5f5c5ee3..62e51631672c8ff2272cec29083528dce20b54e6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,8 @@ GNU coreutils NEWS                                    -*- outline -*-
   preceding command line argument.  This bug also affects chgrp, but
   it is harder to demonstrate.  It does not affect chown.
 
+  cp -i and mv -i occasionally neglected to prompt when the copy or
+  move action was bound to fail.
 
 * Major changes in release 6.2 (2006-09-18) [stable candidate]
 
index f8b0ee678ac546868302d1119f7a514daa720874..c1f3740496d57fbb8d10fbf12cd2276f54ea53d5 100644 (file)
@@ -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.  */
index 0b42f3a8ad8c1e79be9bd70e81c63ed1130b38da..832bb328e05a99c5c4380a8d57c059c9789eb0dd 100644 (file)
@@ -29,7 +29,7 @@ TESTS = \
   preserve-2 r-vs-symlink link-preserve \
   backup-1 no-deref-link1 no-deref-link2 no-deref-link3 backup-is-src \
   same-file cp-mv-backup symlink-slash slink-2-slink fail-perm dir-slash \
-  perm cp-HL special-bits link dir-rm-dest cp-parents deref-slink \
+  perm cp-HL cp-i special-bits link dir-rm-dest cp-parents deref-slink \
   dir-vs-file into-self
 EXTRA_DIST = $(TESTS) trailing-slash
 TESTS_ENVIRONMENT = \
diff --git a/tests/cp/cp-i b/tests/cp/cp-i
new file mode 100755 (executable)
index 0000000..119d8c8
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/sh
+# Test whether cp -i prompts in the right place.
+
+# Copyright (C) 2006 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+if test "$VERBOSE" = yes; then
+  set -x
+  cp --version
+fi
+
+. $srcdir/../envvar-check
+. $srcdir/../lang-default
+
+pwd=`pwd`
+t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
+trap 'status=$?; cd $pwd; chmod -R u+rwx $t0; rm -rf $t0 && exit $status' 0
+trap '(exit $?); exit $?' 1 2 13 15
+
+framework_failure=0
+mkdir -p $tmp || framework_failure=1
+cd $tmp || framework_failure=1
+
+mkdir -p a b/a/c || framework_failure=1
+touch a/c || framework_failure=1
+
+if test $framework_failure = 1; then
+  echo "$0: failure in testing framework" 1>&2
+  (exit 1); exit 1
+fi
+
+fail=0
+
+# coreutils 6.2 cp would neglect to prompt in this case.
+echo n | cp -iR a b 2>/dev/null || fail=1
+
+(exit $fail); exit $fail
index b5294b4e2c61e0be1a70879c2aff7fb1081ff8b7..01db2285cec8ba9a6fef0346485bb758fdfbaf93 100644 (file)
@@ -36,7 +36,7 @@ TESTS = \
   perm-1 \
   i-link-no \
   part-fail \
-  dup-source childproof i-4 update i-2 mv-special-1 \
+  dup-source childproof i-4 i-5 update i-2 mv-special-1 \
   into-self into-self-2 into-self-3 into-self-4 \
   backup-is-src \
   i-1 hard-link-1 force partition-perm to-symlink dir-file diag \
diff --git a/tests/mv/i-5 b/tests/mv/i-5
new file mode 100755 (executable)
index 0000000..8b29545
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/sh
+# Make sure `mv -i dir file' prompts before failing.
+
+# Copyright (C) 2006 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+if test "$VERBOSE" = yes; then
+  set -x
+  mv --version
+fi
+
+. $srcdir/../envvar-check
+. $srcdir/../lang-default
+
+pwd=`pwd`
+t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
+trap 'status=$?; cd $pwd; chmod -R u+rwx $t0; rm -rf $t0 && exit $status' 0
+trap '(exit $?); exit $?' 1 2 13 15
+
+framework_failure=0
+mkdir -p $tmp || framework_failure=1
+cd $tmp || framework_failure=1
+
+mkdir a || framework_failure=1
+touch b || framework_failure=1
+
+if test $framework_failure = 1; then
+  echo 'failure in testing framework'
+  exit 1
+fi
+
+fail=0
+
+# coreutils 6.2 mv would neglect to prompt in this case.
+echo n | mv -i a b 2>/dev/null || fail=1
+
+(exit $fail); exit $fail