split: fix the suffix length calculation
authorPádraig Brady <P@draigBrady.com>
Thu, 30 Dec 2010 01:36:59 +0000 (01:36 +0000)
committerPádraig Brady <P@draigBrady.com>
Thu, 30 Dec 2010 16:26:20 +0000 (16:26 +0000)
* src/split.c (set_suffix_length): Only auto-calculate
the suffix length when the number of files is specified.
* tests/misc/split-a: Add a case to trigger the bug,
and exercise the suffix length auto-calculation.
* NEWS: Mention the fix.
Reported by Dmitry V. Levin and Sergey Vlasov at
https://bugzilla.altlinux.org/show_bug.cgi?id=24841

NEWS
THANKS
src/split.c
tests/misc/split-a

diff --git a/NEWS b/NEWS
index 401b2f5..88596b5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,12 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
+** Bug fixes
+
+  split no longer creates files with a suffix length that
+  is dependent on the number of bytes or lines per file.
+  [bug introduced in coreutils-8.8]
+
 
 * Noteworthy changes in release 8.8 (2010-12-22) [stable]
 
diff --git a/THANKS b/THANKS
index 9060c2f..311fa5b 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -553,6 +553,7 @@ Scott Harrison                      scott.gnu.2009@scottrix.co.uk
 Scott Lurndal                       slurn@griffin.engr.sgi.com
 Sébastien Maret                     smaret@umich.edu
 Sergei Steshenko                    sergstesh@yahoo.com
+Sergey Vlasov                       vsu@altlinux.org
 Shing-Shong Shei                    shei@cs.indiana.edu
 Soeren Sonnenburg                   sonnenburg@informatik.hu-berlin.de
 Solar Designer                      solar@owl.openwall.com
index ae98bc7..a5eda15 100644 (file)
@@ -78,6 +78,13 @@ static bool elide_empty_files;
    input to output, which is much slower, so disabled by default.  */
 static bool unbuffered;
 
+/* The split mode to use.  */
+enum Split_type
+{
+  type_undef, type_bytes, type_byteslines, type_lines, type_digits,
+  type_chunk_bytes, type_chunk_lines, type_rr
+};
+
 /* For long options that have no equivalent short option, use a
    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
 enum
@@ -105,16 +112,22 @@ static struct option const longopts[] =
 };
 
 static void
-set_suffix_length (uintmax_t n_units)
+set_suffix_length (uintmax_t n_units, enum Split_type split_type)
 {
 #define DEFAULT_SUFFIX_LENGTH 2
 
   size_t suffix_needed = 0;
-  size_t alphabet_len = strlen (suffix_alphabet);
-  bool alphabet_slop = (n_units % alphabet_len) != 0;
-  while (n_units /= alphabet_len)
-    suffix_needed++;
-  suffix_needed += alphabet_slop;
+
+  /* Auto-calculate the suffix length if the number of files is given.  */
+  if (split_type == type_chunk_bytes || split_type == type_chunk_lines
+      || split_type == type_rr)
+    {
+      size_t alphabet_len = strlen (suffix_alphabet);
+      bool alphabet_slop = (n_units % alphabet_len) != 0;
+      while (n_units /= alphabet_len)
+        suffix_needed++;
+      suffix_needed += alphabet_slop;
+    }
 
   if (suffix_length)            /* set by user */
     {
@@ -780,11 +793,7 @@ int
 main (int argc, char **argv)
 {
   struct stat stat_buf;
-  enum
-    {
-      type_undef, type_bytes, type_byteslines, type_lines, type_digits,
-      type_chunk_bytes, type_chunk_lines, type_rr
-    } split_type = type_undef;
+  enum Split_type split_type = type_undef;
   size_t in_blk_size = 0;      /* optimal block size of input file device */
   char *buf;                   /* file i/o buffer */
   size_t page_size = getpagesize ();
@@ -984,7 +993,7 @@ main (int argc, char **argv)
       usage (EXIT_FAILURE);
     }
 
-  set_suffix_length (n_units);
+  set_suffix_length (n_units, split_type);
 
   /* Get out the filename arguments.  */
 
index d861b92..08d313e 100755 (executable)
@@ -63,4 +63,14 @@ for f in $files; do
   n=$(expr $n + 1)
 done
 
+# Ensure that -a is independent of -[bCl]
+split -a2 -b1000 < /dev/null || fail=1
+split -a2 -l1000 < /dev/null || fail=1
+split -a2 -C1000 < /dev/null || fail=1
+
+# Ensure that -a fails early with a -n that is too large
+rm -f x*
+split -a2 -n1000 < /dev/null && fail=1
+test -f xaa && fail=1
+
 Exit $fail