rm: fix empty-name bug introduced with conversion to use fts
authorJim Meyering <meyering@redhat.com>
Tue, 1 Dec 2009 11:02:11 +0000 (12:02 +0100)
committerJim Meyering <meyering@redhat.com>
Tue, 1 Dec 2009 13:38:39 +0000 (14:38 +0100)
While "rm ''" would properly fail, "rm F1 '' F2" would fail
to remove F1 and F2, due to the empty string argument.
This bug was introduced on 2009-07-12, via commit 4f73ecaf,
"rm: rewrite to use fts".
* gnulib: Update to latest, for fixed fts.c.
* NEWS (Bug fixes): Describe it.
* tests/rm/empty-name: Adjust for changed diagnostic.
(mk_file): Define, copied from misc/ls-misc.
(empty-name-2): New test, for today's fix.
* lib/xfts.c (xfts_open): Reflect the change in fts_open, now that
it no longer fails immediately when one argument is the empty string.
Assert that the bit flags were not the cause of failure.
* po/POTFILES.in: Remove xfts.c.
* THANKS: Update.
Reported by Ladislav Hagara.

NEWS
THANKS
gnulib
lib/xfts.c
po/POTFILES.in
tests/rm/empty-name

diff --git a/NEWS b/NEWS
index df258e2..9f7bf2e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,14 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
+** Bug fixes
+
+  rm once again handles zero-length arguments properly.
+  The rewrite to make rm use fts introduced a regression whereby
+  a command like "rm a '' b" would fail to remove "a" and "b", due to
+  the presence of the empty string argument.
+  [bug introduced in coreutils-8.0]
+
 
 * Noteworthy changes in release 8.1 (2009-11-18) [stable]
 
diff --git a/THANKS b/THANKS
index f9bc476..52d4170 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -334,6 +334,7 @@ Kirk Kelsey                         kirk.kelsey@0x4b.net
 Kristin E Thomas                    kristint@us.ibm.com
 Kjetil Torgrim Homme                kjetilho@ifi.uio.no
 Kristoffer Rose                     kris@diku.dk
+Ladislav Hagara                     ladislav.hagara@unob.cz
 Larry McVoy                         lm@sgi.com
 Lars Hecking                        lhecking@nmrc.ucc.ie
 Leah Q                              eequor@earthlink.net
diff --git a/gnulib b/gnulib
index cf8ddf0..cdfe647 160000 (submodule)
--- a/gnulib
+++ b/gnulib
@@ -1 +1 @@
-Subproject commit cf8ddf08dec79be620c011ce204cbdb6bff35c50
+Subproject commit cdfe647f8d29540cdfe90cef0fa568c5d2fd4481
index 9c46f6a..dd86a5c 100644 (file)
 
 #include <stdbool.h>
 #include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
 
-#include "error.h"
-
-#include "gettext.h"
-#define _(msgid) gettext (msgid)
-
-#include "quote.h"
 #include "xalloc.h"
 #include "xfts.h"
 
@@ -40,23 +36,10 @@ xfts_open (char * const *argv, int options,
   FTS *fts = fts_open (argv, options | FTS_CWDFD, compar);
   if (fts == NULL)
     {
-      /* This can fail in three ways: out of memory, invalid bit_flags,
-         and one or more of the FILES is an empty string.  We could try
-         to decipher that errno==EINVAL means invalid bit_flags and
-         errno==ENOENT means there's an empty string, but that seems wrong.
-         Ideally, fts_open would return a proper error indicator.  For now,
-         we'll presume that the bit_flags are valid and just check for
-         empty strings.  */
-      bool invalid_arg = false;
-      for (; *argv; ++argv)
-        {
-          if (**argv == '\0')
-            invalid_arg = true;
-        }
-      if (invalid_arg)
-        error (EXIT_FAILURE, 0, _("invalid argument: %s"), quote (""));
-      else
-        xalloc_die ();
+      /* This can fail in two ways: out of memory or with errno==EINVAL,
+         which indicates it was called with invalid bit_flags.  */
+      assert (errno != EINVAL);
+      xalloc_die ();
     }
 
   return fts;
index 9a46a9a..e744dda 100644 (file)
@@ -28,7 +28,6 @@ lib/verror.c
 lib/version-etc.c
 lib/xalloc-die.c
 lib/xfreopen.c
-lib/xfts.c
 lib/xmemcoll.c
 lib/xmemxfrm.c
 lib/xprintf.c
index 08cc8e3..27f76d0 100755 (executable)
@@ -29,12 +29,28 @@ use strict;
 
 my $prog = 'rm';
 
+# FIXME: copied from misc/ls-misc; factor into Coreutils.pm?
+sub mk_file(@)
+{
+  foreach my $f (@_)
+    {
+      open (F, '>', $f) && close F
+        or die "creating $f: $!\n";
+    }
+}
+
 my @Tests =
     (
      # test-name options input expected-output
      #
      ['empty-name-1', "''", {EXIT => 1},
-      {ERR => "$prog: invalid argument: `'\n"}],
+      {ERR => "$prog: cannot remove `': No such file or directory\n"}],
+
+     ['empty-name-2', "a '' b", {EXIT => 1},
+      {ERR => "$prog: cannot remove `': No such file or directory\n"},
+      {PRE => sub { mk_file qw(a b) }},
+      {POST => sub {-f 'a' || -f 'b' and die "a or b remain\n" }},
+     ],
     );
 
 my $save_temps = $ENV{SAVE_TEMPS};