]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
diagnose too-large numbers better
authorPádraig Brady <P@draigBrady.com>
Tue, 16 Dec 2014 12:36:39 +0000 (12:36 +0000)
committerPádraig Brady <P@draigBrady.com>
Fri, 19 Dec 2014 11:56:20 +0000 (11:56 +0000)
Following on from commit v8.23-82-gaddae94, consistently diagnose
numbers that are too large, so as to distinguish from other errors,
and make the limits obvious.

* gl/modules/xdectoint: A new module implementing xdecto[iu]max(),
which handles the common case of parsing a bounded integer and
exiting with a diagnostic on error.
* gl/lib/xdectoimax.c: The signed variant.
* gl/lib/xdectoint.c: The parameterized implementation.
* gl/lib/xdectoint.h: The interface.
* gl/lib/xdectoumax.c: The unsigned variant.
* bootstrap.conf: Reference the new module.
* cfg.mk (exclude_file_name_regexp--sc_require_config_h_first):
Exclude the parameterized templates.
* src/csplit.c: Output EOVERFLOW or ERANGE errors if appropriate.
* src/fmt.c: Likewise.
* src/fold.c: Likewise.
* src/head.c: Likewise.
* src/ls.c: Likewise.
* src/nl.c: Likewise.
* src/nproc.c: Likewise.
* src/shred.c: Likewise.
* src/shuf.c: Likewise.
* src/stdbuf.c: Likewise.
* src/stty.c: Likewise.
* src/tail.c: Likewise.
* src/truncate.c: Likewise.
* src/split.c: Likewise.
* src/pr.c: Likewise.
* tests/pr/pr-tests.pl: Adjust to avoid matching errno diagnostic.
* tests/fmt/base.pl: Likewise.
* tests/split/l-chunk.sh: Likewise.
* tests/misc/shred-negative.sh: Likewise.
* tests/misc/tail.pl: Likewise.  Also remove the redundant
existing ERR_SUBST from test err-6.
* tests/ls/hex-option.sh: Check HEX/OCT options.
* tests/misc/shred-size.sh: Likewise.
* tests/misc/stty-row-col.sh: Likewise.

31 files changed:
bootstrap.conf
cfg.mk
gl/lib/xdectoimax.c [new file with mode: 0644]
gl/lib/xdectoint.c [new file with mode: 0644]
gl/lib/xdectoint.h [new file with mode: 0644]
gl/lib/xdectoumax.c [new file with mode: 0644]
gl/modules/xdectoint [new file with mode: 0644]
src/csplit.c
src/dd.c
src/fmt.c
src/fold.c
src/head.c
src/ls.c
src/nl.c
src/nproc.c
src/pr.c
src/shred.c
src/shuf.c
src/split.c
src/stdbuf.c
src/stty.c
src/tail.c
src/truncate.c
tests/fmt/base.pl
tests/local.mk
tests/ls/hex-option.sh [moved from tests/misc/shred-negative.sh with 79% similarity]
tests/misc/shred-size.sh [new file with mode: 0755]
tests/misc/stty-row-col.sh
tests/misc/tail.pl
tests/pr/pr-tests.pl
tests/split/l-chunk.sh

index c0b5f0233bd5871c3589dd638b88420eb3799ca8..7706c5a794390b658cb41e2e710e8ebf3d9bcba8 100644 (file)
@@ -273,6 +273,7 @@ gnulib_modules="
   xprintf
   xprintf-posix
   xreadlink
+  xdectoint
   xstrtod
   xstrtoimax
   xstrtol
diff --git a/cfg.mk b/cfg.mk
index ee444bac283cf7b444c34a06df8a162c429320ad..5a96acfaf7f484c3a068a559b6838b09cfdea879 100644 (file)
--- a/cfg.mk
+++ b/cfg.mk
@@ -607,7 +607,7 @@ exclude_file_name_regexp--sc_system_h_headers = \
 
 _src = (false|lbracket|ls-(dir|ls|vdir)|tac-pipe|uname-(arch|uname))
 exclude_file_name_regexp--sc_require_config_h_first = \
-  (^lib/buffer-lcm\.c|src/$(_src)\.c)$$
+  (^lib/buffer-lcm\.c|gl/lib/xdecto.max\.c|src/$(_src)\.c)$$
 exclude_file_name_regexp--sc_require_config_h = \
   $(exclude_file_name_regexp--sc_require_config_h_first)
 
diff --git a/gl/lib/xdectoimax.c b/gl/lib/xdectoimax.c
new file mode 100644 (file)
index 0000000..d4bb18f
--- /dev/null
@@ -0,0 +1,6 @@
+#define __xdectoint xdectoimax
+#define __xnumtoint xnumtoimax
+#define __xdectoint_t intmax_t
+#define __xstrtol xstrtoimax
+#define __xdectoint_signed 1
+#include "xdectoint.c"
diff --git a/gl/lib/xdectoint.c b/gl/lib/xdectoint.c
new file mode 100644 (file)
index 0000000..2164d1e
--- /dev/null
@@ -0,0 +1,85 @@
+/* Convert decimal strings with bounds checking and exit on error.
+
+   Copyright (C) 2014 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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "xdectoint.h"
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include "error.h"
+#include "quote.h"
+#include "xstrtol.h"
+
+/* Parse numeric string N_STR of base BASE, and return the value.
+   Exit on parse error or if MIN or MAX are exceeded.
+   Strings can have multiplicative SUFFIXES if specified.
+   ERR is printed along with N_STR on error.  */
+
+__xdectoint_t
+__xnumtoint (const char *n_str, int base, __xdectoint_t min, __xdectoint_t max,
+             const char *suffixes, const char *err, int err_exit)
+{
+  strtol_error s_err;
+
+  __xdectoint_t tnum;
+  s_err = __xstrtol (n_str, NULL, base, &tnum, suffixes);
+
+  if (s_err == LONGINT_OK)
+    {
+      if (tnum < min || max < tnum)
+        {
+          s_err = LONGINT_OVERFLOW;
+          /* Use have the INT range as a heuristic to distinguish
+             type overflow rather than other min/max limits.  */
+          if (tnum > INT_MAX/2)
+            errno = EOVERFLOW;
+#if __xdectoint_signed
+          else if (tnum < INT_MIN/2)
+            errno = EOVERFLOW;
+#endif
+          else
+            errno = ERANGE;
+        }
+    }
+  else if (s_err == LONGINT_OVERFLOW)
+    errno = EOVERFLOW;
+  else if (s_err == LONGINT_INVALID_SUFFIX_CHAR_WITH_OVERFLOW)
+    errno = 0; /* Don't show ERANGE errors for invalid numbers.  */
+
+  if (s_err != LONGINT_OK)
+    {
+      error (err_exit ? err_exit : EXIT_FAILURE, errno,
+             "%s: %s", err, quote (n_str));
+    }
+
+  return tnum;
+}
+
+/* Parse decimal string N_STR, and return the value.
+   Exit on parse error or if MIN or MAX are exceeded.
+   Strings can have multiplicative SUFFIXES if specified.
+   ERR is printed along with N_STR on error.  */
+
+__xdectoint_t
+__xdectoint (const char *n_str, __xdectoint_t min, __xdectoint_t max,
+             const char *suffixes, const char *err, int err_exit)
+{
+  return __xnumtoint (n_str, 10, min, max, suffixes, err, err_exit);
+}
diff --git a/gl/lib/xdectoint.h b/gl/lib/xdectoint.h
new file mode 100644 (file)
index 0000000..770e185
--- /dev/null
@@ -0,0 +1,36 @@
+/* Convert decimal strings with bounds checking and exit on error.
+
+   Copyright (C) 2014 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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef XDECTOINT_H_
+# define XDECTOINT_H_ 1
+
+# include <inttypes.h>
+
+# define _DECLARE_XDECTOINT(name, type) \
+  type name (const char *n_str, type min, type max, \
+             const char *suffixes, const char *err, int err_exit);
+# define _DECLARE_XNUMTOINT(name, type) \
+  type name (const char *n_str, int base, type min, type max, \
+             const char *suffixes, const char *err, int err_exit);
+
+_DECLARE_XDECTOINT (xdectoimax, intmax_t)
+_DECLARE_XDECTOINT (xdectoumax, uintmax_t)
+
+_DECLARE_XNUMTOINT (xnumtoimax, intmax_t)
+_DECLARE_XNUMTOINT (xnumtoumax, uintmax_t)
+
+#endif  /* not XDECTOINT_H_ */
diff --git a/gl/lib/xdectoumax.c b/gl/lib/xdectoumax.c
new file mode 100644 (file)
index 0000000..412ddf9
--- /dev/null
@@ -0,0 +1,6 @@
+#define __xdectoint xdectoumax
+#define __xnumtoint xnumtoumax
+#define __xdectoint_t uintmax_t
+#define __xstrtol xstrtoumax
+#define __xdectoint_signed 0
+#include "xdectoint.c"
diff --git a/gl/modules/xdectoint b/gl/modules/xdectoint
new file mode 100644 (file)
index 0000000..cbd3726
--- /dev/null
@@ -0,0 +1,29 @@
+Description:
+Convert decimal string to '[u]intmax_t', with bounds checking and exit on error
+
+Files:
+lib/xdectoint.h
+lib/xdectoint.c
+lib/xdectoimax.c
+lib/xdectoumax.c
+
+Depends-on:
+error
+errno
+quote
+xstrtoimax
+xstrtoumax
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += xdectoimax.c xdectoumax.c
+
+Include:
+"xdectoint.h"
+
+License:
+GPL
+
+Maintainer:
+all
index af72d8f67e6f034b5e738ba489c519c593a3926c..15c4771788295b61be1052ce8046827efda6ab8b 100644 (file)
@@ -33,6 +33,7 @@
 #include "quote.h"
 #include "safe-read.h"
 #include "stdio--.h"
+#include "xdectoint.h"
 #include "xstrtol.h"
 
 /* The official name of this program (e.g., no 'g' prefix).  */
@@ -1332,7 +1333,6 @@ int
 main (int argc, char **argv)
 {
   int optc;
-  unsigned long int val;
 
   initialize_main (&argc, &argv);
   set_program_name (argv[0]);
@@ -1366,10 +1366,8 @@ main (int argc, char **argv)
         break;
 
       case 'n':
-        if (xstrtoul (optarg, NULL, 10, &val, "") != LONGINT_OK
-            || MIN (INT_MAX, SIZE_MAX) < val)
-          error (EXIT_FAILURE, 0, _("%s: invalid number"), optarg);
-        digits = val;
+        digits = xdectoimax (optarg, 0, MIN (INT_MAX, SIZE_MAX), "",
+                             _("invalid number"), 0);
         break;
 
       case 's':
index d652fee1435ab7177ae9d24305c9deb26a344473..49d0d2a0cb4d25f848cc364b3758dd5dbdc37fb2 100644 (file)
--- a/src/dd.c
+++ b/src/dd.c
@@ -1433,7 +1433,7 @@ scanargs (int argc, char *const *argv)
 
           if (invalid != LONGINT_OK)
             error (EXIT_FAILURE, invalid == LONGINT_OVERFLOW ? EOVERFLOW : 0,
-                   _("invalid number %s"), quote (val));
+                   "%s: %s", _("invalid number"), quote (val));
         }
     }
 
index f235da9acd4359027d41a07237e5231fbcb9479a..e3719d2c3b8aafdc721a4b8af95a4ada01d8bfed 100644 (file)
--- a/src/fmt.c
+++ b/src/fmt.c
@@ -30,7 +30,7 @@
 #include "error.h"
 #include "fadvise.h"
 #include "quote.h"
-#include "xstrtol.h"
+#include "xdectoint.h"
 
 /* The official name of this program (e.g., no 'g' prefix).  */
 #define PROGRAM_NAME "fmt"
@@ -399,23 +399,15 @@ main (int argc, char **argv)
     {
       /* Limit max_width to MAXCHARS / 2; otherwise, the resulting
          output can be quite ugly.  */
-      unsigned long int tmp;
-      if (! (xstrtoul (max_width_option, NULL, 10, &tmp, "") == LONGINT_OK
-             && tmp <= MAXCHARS / 2))
-        error (EXIT_FAILURE, 0, _("invalid width: %s"),
-               quote (max_width_option));
-      max_width = tmp;
+      max_width = xdectoumax (max_width_option, 0, MAXCHARS / 2, "",
+                              _("invalid width"), 0);
     }
 
   if (goal_width_option)
     {
       /* Limit goal_width to max_width.  */
-      unsigned long int tmp;
-      if (! (xstrtoul (goal_width_option, NULL, 10, &tmp, "") == LONGINT_OK
-             && tmp <= max_width))
-        error (EXIT_FAILURE, 0, _("invalid width: %s"),
-               quote (goal_width_option));
-      goal_width = tmp;
+      goal_width = xdectoumax (goal_width_option, 0, max_width, "",
+                               _("invalid width"), 0);
       if (max_width_option == NULL)
         max_width = goal_width + 10;
     }
index 3bc9ba29fa611123e5d776128ef6b62aaeef4968..20cb61ecaa3f4f069c73fcc3f96df2613053e76c 100644 (file)
@@ -25,8 +25,7 @@
 #include "system.h"
 #include "error.h"
 #include "fadvise.h"
-#include "quote.h"
-#include "xstrtol.h"
+#include "xdectoint.h"
 
 #define TAB_WIDTH 8
 
@@ -280,14 +279,8 @@ main (int argc, char **argv)
             }
           /* Fall through.  */
         case 'w':              /* Line width. */
-          {
-            unsigned long int tmp_ulong;
-            if (! (xstrtoul (optarg, NULL, 10, &tmp_ulong, "") == LONGINT_OK
-                   && 0 < tmp_ulong && tmp_ulong < SIZE_MAX - TAB_WIDTH))
-              error (EXIT_FAILURE, 0,
-                     _("invalid number of columns: %s"), quote (optarg));
-            width = tmp_ulong;
-          }
+          width = xdectoumax (optarg, 1, SIZE_MAX - TAB_WIDTH - 1, "",
+                              _("invalid number of columns"), 0);
           break;
 
         case_GETOPT_HELP_CHAR;
index 2782f8e8c1d57ad286952e87c5fdaab195f38c4b..7fc161a4972b004ff6fd9e4857812fb6e3c55896 100644 (file)
@@ -38,7 +38,7 @@
 #include "safe-read.h"
 #include "stat-size.h"
 #include "xfreopen.h"
-#include "xstrtol.h"
+#include "xdectoint.h"
 
 /* The official name of this program (e.g., no 'g' prefix).  */
 #define PROGRAM_NAME "head"
@@ -893,7 +893,7 @@ head_file (const char *filename, uintmax_t n_units, bool count_lines,
   return ok;
 }
 
-/* Convert a string of decimal digits, N_STRING, with an optional suffinx
+/* Convert a string of decimal digits, N_STRING, with an optional suffix
    to an integral value.  Upon successful conversion,
    return that value.  If it cannot be converted, give a diagnostic and exit.
    COUNT_LINES indicates whether N_STRING is a number of bytes or a number
@@ -902,27 +902,9 @@ head_file (const char *filename, uintmax_t n_units, bool count_lines,
 static uintmax_t
 string_to_integer (bool count_lines, const char *n_string)
 {
-  strtol_error s_err;
-  uintmax_t n;
-
-  s_err = xstrtoumax (n_string, NULL, 10, &n, "bkKmMGTPEZY0");
-
-  if (s_err == LONGINT_OVERFLOW)
-    {
-      error (EXIT_FAILURE, 0,
-             _("%s: %s is so large that it is not representable"), n_string,
-             count_lines ? _("number of lines") : _("number of bytes"));
-    }
-
-  if (s_err != LONGINT_OK)
-    {
-      error (EXIT_FAILURE, 0, "%s: %s", n_string,
-             (count_lines
-              ? _("invalid number of lines")
-              : _("invalid number of bytes")));
-    }
-
-  return n;
+  return xdectoumax (n_string, 0, UINTMAX_MAX, "bkKmMGTPEZY0",
+                     count_lines ? _("invalid number of lines")
+                                 : _("invalid number of bytes"), 0);
 }
 
 int
@@ -1076,8 +1058,8 @@ main (int argc, char **argv)
   if ( ! count_lines && elide_from_end && OFF_T_MAX < n_units)
     {
       char umax_buf[INT_BUFSIZE_BOUND (n_units)];
-      error (EXIT_FAILURE, 0, _("%s: number of bytes is too large"),
-             umaxtostr (n_units, umax_buf));
+      error (EXIT_FAILURE, EOVERFLOW, "%s: %s", _("invalid number of bytes"),
+             quote (umaxtostr (n_units, umax_buf)));
     }
 
   file_list = (optind < argc
index 5bae06fbeccb50285ea2662bcb5851e404a75acf..82402ee7756fb1c7674999750f7605054752fb53 100644 (file)
--- a/src/ls.c
+++ b/src/ls.c
 #include "stat-size.h"
 #include "stat-time.h"
 #include "strftime.h"
+#include "xdectoint.h"
 #include "xstrtol.h"
 #include "areadlink.h"
 #include "mbsalign.h"
@@ -1742,15 +1743,9 @@ decode_switches (int argc, char **argv)
           break;
 
         case 'w':
-          {
-            unsigned long int tmp_ulong;
-            if (xstrtoul (optarg, NULL, 0, &tmp_ulong, NULL) != LONGINT_OK
-                || ! (0 < tmp_ulong && tmp_ulong <= SIZE_MAX))
-              error (LS_FAILURE, 0, _("invalid line width: %s"),
-                     quotearg (optarg));
-            line_length = tmp_ulong;
-            break;
-          }
+          line_length = xnumtoumax (optarg, 0, 1, SIZE_MAX, "",
+                                    _("invalid line width"), LS_FAILURE);
+          break;
 
         case 'x':
           format = horizontal;
@@ -1816,15 +1811,9 @@ decode_switches (int argc, char **argv)
           break;
 
         case 'T':
-          {
-            unsigned long int tmp_ulong;
-            if (xstrtoul (optarg, NULL, 0, &tmp_ulong, NULL) != LONGINT_OK
-                || SIZE_MAX < tmp_ulong)
-              error (LS_FAILURE, 0, _("invalid tab size: %s"),
-                     quotearg (optarg));
-            tabsize = tmp_ulong;
-            break;
-          }
+          tabsize = xnumtoumax (optarg, 0, 0, SIZE_MAX, "",
+                                _("invalid tab size"), LS_FAILURE);
+          break;
 
         case 'U':
           sort_type = sort_none;
index 7fc113442189407da78d4b889f79a13cbf4125b1..5c341620a64b049da5e007befcee2746e5c23977 100644 (file)
--- a/src/nl.c
+++ b/src/nl.c
@@ -31,7 +31,7 @@
 #include "fadvise.h"
 #include "linebuffer.h"
 #include "quote.h"
-#include "xstrtol.h"
+#include "xdectoint.h"
 
 /* The official name of this program (e.g., no 'g' prefix).  */
 #define PROGRAM_NAME "nl"
@@ -497,53 +497,27 @@ main (int argc, char **argv)
             }
           break;
         case 'v':
-          if (xstrtoimax (optarg, NULL, 10, &starting_line_number, "")
-              != LONGINT_OK)
-            {
-              error (0, 0, _("invalid starting line number: %s"),
-                     quote (optarg));
-              ok = false;
-            }
+          starting_line_number = xdectoimax (optarg, INTMAX_MIN, INTMAX_MAX, "",
+                                             _("invalid starting line number"),
+                                             0);
           break;
         case 'i':
-          if (! (xstrtoimax (optarg, NULL, 10, &page_incr, "") == LONGINT_OK
-                 && 0 < page_incr))
-            {
-              error (0, 0, _("invalid line number increment: %s"),
-                     quote (optarg));
-              ok = false;
-            }
+          page_incr = xdectoimax (optarg, 1, INTMAX_MAX, "",
+                                  _("invalid line number increment"), 0);
           break;
         case 'p':
           reset_numbers = false;
           break;
         case 'l':
-          if (! (xstrtoimax (optarg, NULL, 10, &blank_join, "") == LONGINT_OK
-                 && 0 < blank_join))
-            {
-              error (0, 0, _("invalid number of blank lines: %s"),
-                     quote (optarg));
-              ok = false;
-            }
+          blank_join = xdectoimax (optarg, 1, INTMAX_MAX, "",
+                                   _("invalid line number of blank lines"), 0);
           break;
         case 's':
           separator_str = optarg;
           break;
         case 'w':
-          {
-            long int tmp_long;
-            if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
-                || tmp_long <= 0 || tmp_long > INT_MAX)
-              {
-                error (0, 0, _("invalid line number field width: %s"),
-                       quote (optarg));
-                ok = false;
-              }
-            else
-              {
-                lineno_width = tmp_long;
-              }
-          }
+          lineno_width = xdectoimax (optarg, 1, INT_MAX, "",
+                                     _("invalid line number field width"), 0);
           break;
         case 'n':
           if (STREQ (optarg, "ln"))
index e1bc1d0b7ff5d2b572f184d221d7df8d271a41f6..4ba146a34c89fd3790735bb916a23439a49afa8e 100644 (file)
@@ -25,7 +25,7 @@
 #include "error.h"
 #include "nproc.h"
 #include "quote.h"
-#include "xstrtol.h"
+#include "xdectoint.h"
 
 /* The official name of this program (e.g., no 'g' prefix).  */
 #define PROGRAM_NAME "nproc"
@@ -102,11 +102,7 @@ main (int argc, char **argv)
           break;
 
         case IGNORE_OPTION:
-          if (xstrtoul (optarg, NULL, 10, &ignore, "") != LONGINT_OK)
-            {
-              error (0, 0, _("%s: invalid number to ignore"), optarg);
-              usage (EXIT_FAILURE);
-            }
+          ignore = xdectoumax (optarg, 0, ULONG_MAX, "", _("invalid number"),0);
           break;
 
         default:
index 529964985025a7976504859e133b15b107d4a202..d6823b51396af07c30342200892b874b174268c2 100644 (file)
--- a/src/pr.c
+++ b/src/pr.c
 #include "stdio--.h"
 #include "strftime.h"
 #include "xstrtol.h"
+#include "xdectoint.h"
 
 /* The official name of this program (e.g., no 'g' prefix).  */
 #define PROGRAM_NAME "pr"
@@ -424,6 +425,8 @@ static bool skip_to_page (uintmax_t page);
 static void print_header (void);
 static void pad_across_to (int position);
 static void add_line_number (COLUMN *p);
+static void getoptnum (const char *n_str, int min, int *num,
+                       const char *errfmt);
 static void getoptarg (char *arg, char switch_char, char *character,
                        int *number);
 static void print_files (int number_of_files, char **av);
@@ -820,18 +823,12 @@ first_last_page (int oi, char c, char const *pages)
 
 /* Parse column count string S, and if it's valid (1 or larger and
    within range of the type of 'columns') set the global variables
-   columns and explicit_columns and return true.
-   Otherwise, exit with a diagnostic.  */
+   columns and explicit_columns.  Otherwise, exit with a diagnostic.  */
+
 static void
 parse_column_count (char const *s)
 {
-  long int tmp_long;
-  if (xstrtol (s, NULL, 10, &tmp_long, "") != LONGINT_OK
-      || !(1 <= tmp_long && tmp_long <= INT_MAX))
-    error (EXIT_FAILURE, 0,
-           _("invalid number of columns: %s"), quote (s));
-
-  columns = tmp_long;
+  getoptnum (s, 1, &columns, _("invalid number of columns"));
   explicit_columns = true;
 }
 
@@ -966,18 +963,9 @@ main (int argc, char **argv)
           join_lines = true;
           break;
         case 'l':
-          {
-            long int tmp_long;
-            if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
-                || tmp_long <= 0 || tmp_long > INT_MAX)
-              {
-                error (EXIT_FAILURE, 0,
-                       _("'-l PAGE_LENGTH' invalid number of lines: %s"),
-                       quote (optarg));
-              }
-            lines_per_page = tmp_long;
-            break;
-          }
+          getoptnum (optarg, 1, &lines_per_page,
+                     _("'-l PAGE_LENGTH' invalid number of lines"));
+          break;
         case 'm':
           parallel_files = true;
           storing_columns = false;
@@ -990,28 +978,13 @@ main (int argc, char **argv)
           break;
         case 'N':
           skip_count = false;
-          {
-            long int tmp_long;
-            if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
-                || tmp_long > INT_MAX)
-              {
-                error (EXIT_FAILURE, 0,
-                       _("'-N NUMBER' invalid starting line number: %s"),
-                       quote (optarg));
-              }
-            start_line_num = tmp_long;
-            break;
-          }
+          getoptnum (optarg, INT_MIN, &start_line_num,
+                     _("'-N NUMBER' invalid starting line number"));
+          break;
         case 'o':
-          {
-            long int tmp_long;
-            if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
-                || tmp_long < 0 || tmp_long > INT_MAX)
-              error (EXIT_FAILURE, 0,
-                     _("'-o MARGIN' invalid line offset: %s"), quote (optarg));
-            chars_per_margin = tmp_long;
-            break;
-          }
+          getoptnum (optarg, 0, &chars_per_margin,
+                     _("'-o MARGIN' invalid line offset"));
+          break;
         case 'r':
           ignore_failed_opens = true;
           break;
@@ -1045,29 +1018,19 @@ main (int argc, char **argv)
           old_options = true;
           old_w = true;
           {
-            long int tmp_long;
-            if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
-                || tmp_long <= 0 || tmp_long > INT_MAX)
-              error (EXIT_FAILURE, 0,
-                     _("'-w PAGE_WIDTH' invalid number of characters: %s"),
-                     quote (optarg));
-            if (!truncate_lines)
-              chars_per_line = tmp_long;
-            break;
+            int tmp_cpl;
+            getoptnum (optarg, 1, &tmp_cpl,
+                       _("'-w PAGE_WIDTH' invalid number of characters"));
+            if (! truncate_lines)
+              chars_per_line = tmp_cpl;
           }
+          break;
         case 'W':
           old_w = false;                       /* dominates -w */
           truncate_lines = true;
-          {
-            long int tmp_long;
-            if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
-                || tmp_long <= 0 || tmp_long > INT_MAX)
-              error (EXIT_FAILURE, 0,
-                     _("'-W PAGE_WIDTH' invalid number of characters: %s"),
-                     quote (optarg));
-            chars_per_line = tmp_long;
-            break;
-          }
+          getoptnum (optarg, 1, &chars_per_line,
+                     _("'-W PAGE_WIDTH' invalid number of characters"));
+          break;
         case_GETOPT_HELP_CHAR;
         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
         default:
@@ -1173,6 +1136,15 @@ main (int argc, char **argv)
   return failed_opens ? EXIT_FAILURE : EXIT_SUCCESS;
 }
 
+/* Parse numeric arguments, ensuring MIN <= number <= INT_MAX.  */
+
+static void
+getoptnum (const char *n_str, int min, int *num, const char *err)
+{
+  intmax_t tnum = xdectoimax (n_str, min, INT_MAX, "", err, 0);
+  *num = tnum;
+}
+
 /* Parse options of the form -scNNN.
 
    Example: -nck, where 'n' is the option, c is the optional number
@@ -1188,9 +1160,9 @@ getoptarg (char *arg, char switch_char, char *character, int *number)
     {
       long int tmp_long;
       if (xstrtol (arg, NULL, 10, &tmp_long, "") != LONGINT_OK
-          || tmp_long <= 0 || tmp_long > INT_MAX)
+          || tmp_long <= 0 || INT_MAX < tmp_long)
         {
-          error (0, 0,
+          error (0, INT_MAX < tmp_long ?  EOVERFLOW : errno,
              _("'-%c' extra characters or invalid number in the argument: %s"),
                  switch_char, quote (arg));
           usage (EXIT_FAILURE);
index b235b29aebf79ba5620b531dee14f7f97d402702..2e57199140171de21d1b77a8225603d25966938a 100644 (file)
@@ -86,7 +86,7 @@
 
 #include "system.h"
 #include "argmatch.h"
-#include "xstrtol.h"
+#include "xdectoint.h"
 #include "error.h"
 #include "fcntl--.h"
 #include "human.h"
@@ -1228,16 +1228,10 @@ main (int argc, char **argv)
           break;
 
         case 'n':
-          {
-            uintmax_t tmp;
-            if (xstrtoumax (optarg, NULL, 10, &tmp, NULL) != LONGINT_OK
-                || MIN (ULONG_MAX, SIZE_MAX / sizeof (int)) <= tmp)
-              {
-                error (EXIT_FAILURE, 0, _("%s: invalid number of passes"),
-                       quotearg_colon (optarg));
-              }
-            flags.n_iterations = tmp;
-          }
+          flags.n_iterations = xdectoumax (optarg, 0,
+                                           MIN (ULONG_MAX,
+                                                SIZE_MAX / sizeof (int)), "",
+                                           _("invalid number of passes"), 0);
           break;
 
         case RANDOM_SOURCE_OPTION:
@@ -1255,17 +1249,8 @@ main (int argc, char **argv)
           break;
 
         case 's':
-          {
-            uintmax_t tmp;
-            if ((xstrtoumax (optarg, NULL, 0, &tmp, "cbBkKMGTPEZY0")
-                 != LONGINT_OK)
-                || OFF_T_MAX < tmp)
-              {
-                error (EXIT_FAILURE, 0, _("%s: invalid file size"),
-                       quotearg_colon (optarg));
-              }
-            flags.size = tmp;
-          }
+          flags.size = xnumtoumax (optarg, 0, 0, OFF_T_MAX, "cbBkKMGTPEZY0",
+                                   _("invalid file size"), 0);
           break;
 
         case 'v':
index df0092b9025d0d671cce240af3be9253d4646992..0678c3da6dcdeb70f3a668b93f4f9da7a3fcda39 100644 (file)
@@ -32,6 +32,7 @@
 #include "randperm.h"
 #include "read-file.h"
 #include "stdio--.h"
+#include "xdectoint.h"
 #include "xstrtol.h"
 
 /* The official name of this program (e.g., no 'g' prefix).  */
@@ -422,7 +423,6 @@ main (int argc, char **argv)
 
       case 'i':
         {
-          unsigned long int argval = 0;
           char *p = strchr (optarg, '-');
           char const *hi_optarg = optarg;
           bool invalid = !p;
@@ -434,22 +434,19 @@ main (int argc, char **argv)
           if (p)
             {
               *p = '\0';
-              invalid = ((xstrtoul (optarg, NULL, 10, &argval, NULL)
-                          != LONGINT_OK)
-                         || SIZE_MAX < argval);
+              lo_input = xdectoumax (optarg, 0, SIZE_MAX, "",
+                                     _("invalid input range"), 0);
               *p = '-';
-              lo_input = argval;
               hi_optarg = p + 1;
             }
 
-          invalid |= ((xstrtoul (hi_optarg, NULL, 10, &argval, NULL)
-                       != LONGINT_OK)
-                      || SIZE_MAX < argval);
-          hi_input = argval;
+          hi_input = xdectoumax (hi_optarg, 0, SIZE_MAX, "",
+                                 _("invalid input range"), 0);
+
           n_lines = hi_input - lo_input + 1;
           invalid |= ((lo_input <= hi_input) == (n_lines == 0));
           if (invalid)
-            error (EXIT_FAILURE, 0, _("invalid input range %s"),
+            error (EXIT_FAILURE, errno, "%s: %s", _("invalid input range"),
                    quote (optarg));
         }
         break;
@@ -462,7 +459,7 @@ main (int argc, char **argv)
           if (e == LONGINT_OK)
             head_lines = MIN (head_lines, argval);
           else if (e != LONGINT_OVERFLOW)
-            error (EXIT_FAILURE, 0, _("invalid line count %s"),
+            error (EXIT_FAILURE, 0, _("invalid line count: %s"),
                    quote (optarg));
         }
         break;
index 0eec3ecc24c13ef74b3bb2de17fc1d40b65a8d20..008d2a7e25f00a1da3f39a87ba6c9c3f510ad3aa 100644 (file)
@@ -39,7 +39,7 @@
 #include "safe-read.h"
 #include "sig2str.h"
 #include "xfreopen.h"
-#include "xstrtol.h"
+#include "xdectoint.h"
 
 /* The official name of this program (e.g., no 'g' prefix).  */
 #define PROGRAM_NAME "split"
@@ -1174,19 +1174,20 @@ no_filters:
     }                                                          \
   while (0)
 
+
 /* Parse K/N syntax of chunk options.  */
 
 static void
 parse_chunk (uintmax_t *k_units, uintmax_t *n_units, char *slash)
 {
-  *slash = '\0';
-  if (xstrtoumax (slash + 1, NULL, 10, n_units, "") != LONGINT_OK
-      || *n_units == 0)
-    error (EXIT_FAILURE, 0, _("%s: invalid number of chunks"), slash + 1);
-  if (slash != optarg           /* a leading number is specified.  */
-      && (xstrtoumax (optarg, NULL, 10, k_units, "") != LONGINT_OK
-          || *k_units == 0 || *n_units < *k_units))
-    error (EXIT_FAILURE, 0, _("%s: invalid chunk number"), optarg);
+  *n_units = xdectoumax (slash + 1, 1, UINTMAX_MAX, "",
+                         _("invalid number of chunks"), 0);
+  if (slash != optarg)           /* a leading number is specified.  */
+    {
+      *slash = '\0';
+      *k_units = xdectoumax (optarg, 1, *n_units, "",
+                             _("invalid chunk number"), 0);
+    }
 }
 
 
@@ -1197,7 +1198,7 @@ main (int argc, char **argv)
   size_t in_blk_size = 0;      /* optimal block size of input file device */
   size_t page_size = getpagesize ();
   uintmax_t k_units = 0;
-  uintmax_t n_units;
+  uintmax_t n_units = 0;
 
   static char const multipliers[] = "bEGKkMmPTYZ0";
   int c;
@@ -1231,16 +1232,8 @@ main (int argc, char **argv)
       switch (c)
         {
         case 'a':
-          {
-            unsigned long tmp;
-            if (xstrtoul (optarg, NULL, 10, &tmp, "") != LONGINT_OK
-                || SIZE_MAX / sizeof (size_t) < tmp)
-              {
-                error (0, 0, _("%s: invalid suffix length"), optarg);
-                usage (EXIT_FAILURE);
-              }
-            suffix_length = tmp;
-          }
+          suffix_length = xdectoumax (optarg, 0, SIZE_MAX / sizeof (size_t),
+                                      "", _("invalid suffix length"), 0);
           break;
 
         case ADDITIONAL_SUFFIX_OPTION:
@@ -1258,46 +1251,27 @@ main (int argc, char **argv)
           if (split_type != type_undef)
             FAIL_ONLY_ONE_WAY ();
           split_type = type_bytes;
-          if (xstrtoumax (optarg, NULL, 10, &n_units, multipliers) != LONGINT_OK
-              || n_units == 0)
-            {
-              error (0, 0, _("%s: invalid number of bytes"), optarg);
-              usage (EXIT_FAILURE);
-            }
-          /* If input is a pipe, we could get more data than is possible
-             to write to a single file, so indicate that immediately
-             rather than having possibly future invocations fail.  */
-          if (OFF_T_MAX < n_units)
-            error (EXIT_FAILURE, EFBIG,
-                   _("%s: invalid number of bytes"), optarg);
-
+          /* Limit to OFF_T_MAX, becaue if input is a pipe, we could get more
+             data than is possible to write to a single file, so indicate that
+             immediately rather than having possibly future invocations fail. */
+          n_units = xdectoumax (optarg, 1, OFF_T_MAX, multipliers,
+                                _("invalid number of bytes"), 0);
           break;
 
         case 'l':
           if (split_type != type_undef)
             FAIL_ONLY_ONE_WAY ();
           split_type = type_lines;
-          if (xstrtoumax (optarg, NULL, 10, &n_units, "") != LONGINT_OK
-              || n_units == 0)
-            {
-              error (0, 0, _("%s: invalid number of lines"), optarg);
-              usage (EXIT_FAILURE);
-            }
+          n_units = xdectoumax (optarg, 1, UINTMAX_MAX, "",
+                                _("invalid number of lines"), 0);
           break;
 
         case 'C':
           if (split_type != type_undef)
             FAIL_ONLY_ONE_WAY ();
           split_type = type_byteslines;
-          if (xstrtoumax (optarg, NULL, 10, &n_units, multipliers) != LONGINT_OK
-              || n_units == 0 || SIZE_MAX < n_units)
-            {
-              error (0, 0, _("%s: invalid number of bytes"), optarg);
-              usage (EXIT_FAILURE);
-            }
-          if (OFF_T_MAX < n_units)
-            error (EXIT_FAILURE, EFBIG,
-                   _("%s: invalid number of bytes"), optarg);
+          n_units = xdectoumax (optarg, 1, MIN (SIZE_MAX, OFF_T_MAX),
+                                multipliers, _("invalid number of bytes"), 0);
           break;
 
         case 'n':
@@ -1320,9 +1294,9 @@ main (int argc, char **argv)
             split_type = type_chunk_bytes;
           if ((slash = strchr (optarg, '/')))
             parse_chunk (&k_units, &n_units, slash);
-          else if (xstrtoumax (optarg, NULL, 10, &n_units, "") != LONGINT_OK
-                   || n_units == 0)
-            error (EXIT_FAILURE, 0, _("%s: invalid number of chunks"), optarg);
+          else
+            n_units = xdectoumax (optarg, 1, UINTMAX_MAX, "",
+                                  _("invalid number of chunks"), 0);
           break;
 
         case 'u':
@@ -1388,15 +1362,8 @@ main (int argc, char **argv)
           break;
 
         case IO_BLKSIZE_OPTION:
-          {
-            uintmax_t tmp_blk_size;
-            if (xstrtoumax (optarg, NULL, 10, &tmp_blk_size,
-                            multipliers) != LONGINT_OK
-                || tmp_blk_size == 0 || SIZE_MAX - page_size < tmp_blk_size)
-              error (0, 0, _("%s: invalid IO block size"), optarg);
-            else
-              in_blk_size = tmp_blk_size;
-          }
+          in_blk_size = xdectoumax (optarg, 1, SIZE_MAX - page_size,
+                                    multipliers, _("invalid IO block size"), 0);
           break;
 
         case VERBOSE_OPTION:
@@ -1427,7 +1394,7 @@ main (int argc, char **argv)
 
   if (n_units == 0)
     {
-      error (0, 0, _("%s: invalid number of lines"), "0");
+      error (0, 0, "%s: %s", _("invalid number of lines"), quote ("0"));
       usage (EXIT_FAILURE);
     }
 
@@ -1505,8 +1472,9 @@ main (int argc, char **argv)
       if (OFF_T_MAX < n_units)
         {
           char buffer[INT_BUFSIZE_BOUND (uintmax_t)];
-          error (EXIT_FAILURE, EFBIG, _("%s: invalid number of chunks"),
-                 umaxtostr (n_units, buffer));
+          error (EXIT_FAILURE, EOVERFLOW, "%s: %s",
+                 _("invalid number of chunks"),
+                 quote (umaxtostr (n_units, buffer)));
         }
       /* increase file_size to n_units here, so that we still process
          any input data, and create empty files for the rest.  */
index 3fb5d3c42fa597d458b0f73acfa7a43a77ae57ba..94a7a4fca57c5ad2750efc0f8a23f9cf4705963d 100644 (file)
@@ -66,7 +66,7 @@ parse_size (char const *str, size_t *size)
 {
   uintmax_t tmp_size;
   enum strtol_error e = xstrtoumax (str, NULL, 10, &tmp_size, "EGkKMPTYZ0");
-  if (e == LONGINT_OK && tmp_size > SIZE_MAX)
+  if (e == LONGINT_OK && SIZE_MAX < tmp_size)
     e = LONGINT_OVERFLOW;
 
   if (e == LONGINT_OK)
@@ -76,7 +76,7 @@ parse_size (char const *str, size_t *size)
       return 0;
     }
 
-  errno = (e == LONGINT_OVERFLOW ? EOVERFLOW : 0);
+  errno = (e == LONGINT_OVERFLOW ? EOVERFLOW : errno);
   return -1;
 }
 
index 42ec3b447f533e2db5aceed3ae4e8f67b93d2ce1..41909b75ec936ccf96acdff8323bd824c3622578 100644 (file)
@@ -58,6 +58,7 @@
 #include "error.h"
 #include "fd-reopen.h"
 #include "quote.h"
+#include "xdectoint.h"
 #include "xstrtol.h"
 
 /* The official name of this program (e.g., no 'g' prefix).  */
@@ -2087,11 +2088,5 @@ visible (cc_t ch)
 static unsigned long int
 integer_arg (const char *s, unsigned long int maxval)
 {
-  unsigned long int value;
-  if (xstrtoul (s, NULL, 0, &value, "bB") != LONGINT_OK || maxval < value)
-    {
-      error (0, 0, _("invalid integer argument %s"), quote (s));
-      usage (EXIT_FAILURE);
-    }
-  return value;
+  return xnumtoumax (s, 0, 0, maxval, "bB", _("invalid integer argument"), 0);
 }
index 4c5f943c7fb8c0d9bea239f0e4c2fdd5552eb6ac..28524d71faae6063acdd557cb5b5732fc886a598 100644 (file)
@@ -44,6 +44,7 @@
 #include "stat-time.h"
 #include "xfreopen.h"
 #include "xnanosleep.h"
+#include "xdectoint.h"
 #include "xstrtol.h"
 #include "xstrtod.h"
 
@@ -1949,7 +1950,10 @@ parse_obsolete_option (int argc, char * const *argv, uintmax_t *n_units)
   else if ((xstrtoumax (n_string, NULL, 10, n_units, "b")
             & ~LONGINT_INVALID_SUFFIX_CHAR)
            != LONGINT_OK)
-    error (EXIT_FAILURE, 0, _("number in %s is too large"), quote (argv[1]));
+    {
+      error (EXIT_FAILURE, errno, "%s: %s", _("invalid number"),
+             quote (argv[1]));
+    }
 
   /* Set globals.  */
   from_start = t_from_start;
@@ -1986,17 +1990,10 @@ parse_options (int argc, char **argv,
           else if (*optarg == '-')
             ++optarg;
 
-          {
-            strtol_error s_err;
-            s_err = xstrtoumax (optarg, NULL, 10, n_units, "bkKmMGTPEZY0");
-            if (s_err != LONGINT_OK)
-              {
-                error (EXIT_FAILURE, 0, "%s: %s", optarg,
-                       (c == 'n'
-                        ? _("invalid number of lines")
-                        : _("invalid number of bytes")));
-              }
-          }
+          *n_units = xdectoumax (optarg, 0, UINTMAX_MAX, "bkKmMGTPEZY0",
+                                 count_lines
+                                 ? _("invalid number of lines")
+                                 : _("invalid number of bytes"), 0);
           break;
 
         case 'f':
@@ -2015,15 +2012,9 @@ parse_options (int argc, char **argv,
 
         case MAX_UNCHANGED_STATS_OPTION:
           /* --max-unchanged-stats=N */
-          if (xstrtoumax (optarg, NULL, 10,
-                          &max_n_unchanged_stats_between_opens,
-                          "")
-              != LONGINT_OK)
-            {
-              error (EXIT_FAILURE, 0,
-               _("%s: invalid maximum number of unchanged stats between opens"),
-                     optarg);
-            }
+          max_n_unchanged_stats_between_opens =
+            xdectoumax (optarg, 0, UINTMAX_MAX, "",
+              _("invalid maximum number of unchanged stats between opens"), 0);
           break;
 
         case DISABLE_INOTIFY_OPTION:
@@ -2031,16 +2022,7 @@ parse_options (int argc, char **argv,
           break;
 
         case PID_OPTION:
-          {
-            strtol_error s_err;
-            unsigned long int tmp_ulong;
-            s_err = xstrtoul (optarg, NULL, 10, &tmp_ulong, "");
-            if (s_err != LONGINT_OK || tmp_ulong > PID_T_MAX)
-              {
-                error (EXIT_FAILURE, 0, _("%s: invalid PID"), optarg);
-              }
-            pid = tmp_ulong;
-          }
+          pid = xdectoumax (optarg, 0, PID_T_MAX, "", _("invalid PID"), 0);
           break;
 
         case PRESUME_INPUT_PIPE_OPTION:
@@ -2056,7 +2038,7 @@ parse_options (int argc, char **argv,
             double s;
             if (! (xstrtod (optarg, NULL, &s, c_strtod) && 0 <= s))
               error (EXIT_FAILURE, 0,
-                     _("%s: invalid number of seconds"), optarg);
+                     _("invalid number of seconds: %s"), quote (optarg));
             *sleep_interval = s;
           }
           break;
index f06668de5d09c98d794adabd96438511a000f174..e4ef5e733af160b2d044e9401ddd26cf5ec6f397 100644 (file)
@@ -29,7 +29,7 @@
 #include "error.h"
 #include "quote.h"
 #include "stat-size.h"
-#include "xstrtol.h"
+#include "xdectoint.h"
 
 /* The official name of this program (e.g., no 'g' prefix).  */
 #define PROGRAM_NAME "truncate"
@@ -59,33 +59,6 @@ static struct option const longopts[] =
 typedef enum
 { rm_abs = 0, rm_rel, rm_min, rm_max, rm_rdn, rm_rup } rel_mode_t;
 
-/* Set size to the value of STR, interpreted as a decimal integer,
-   optionally multiplied by various values.
-   Return -1 on error, 0 on success.
-
-   This supports dd BLOCK size suffixes + lowercase g,t,m for bsd compat
-   Note we don't support dd's b=512, c=1, w=2 or 21x512MiB formats.  */
-static int
-parse_len (char const *str, off_t *size)
-{
-  enum strtol_error e;
-  intmax_t tmp_size;
-  e = xstrtoimax (str, NULL, 10, &tmp_size, "EgGkKmMPtTYZ0");
-  if (e == LONGINT_OK
-      && !(OFF_T_MIN <= tmp_size && tmp_size <= OFF_T_MAX))
-    e = LONGINT_OVERFLOW;
-
-  if (e == LONGINT_OK)
-    {
-      errno = 0;
-      *size = tmp_size;
-      return 0;
-    }
-
-  errno = (e == LONGINT_OVERFLOW ? EOVERFLOW : 0);
-  return -1;
-}
-
 void
 usage (int status)
 {
@@ -306,9 +279,10 @@ main (int argc, char **argv)
                 }
               rel_mode = rm_rel;
             }
-          if (parse_len (optarg, &size) == -1)
-            error (EXIT_FAILURE, errno, _("invalid number %s"),
-                   quote (optarg));
+          /* Support dd BLOCK size suffixes + lowercase g,t,m for bsd compat.
+             Note we don't support dd's b=512, c=1, w=2 or 21x512MiB formats. */
+          size = xdectoimax (optarg, OFF_T_MIN, OFF_T_MAX, "EgGkKmMPtTYZ0",
+                             _("Invalid number"), 0);
           /* Rounding to multiple of 0 is nonsensical */
           if ((rel_mode == rm_rup || rel_mode == rm_rdn) && size == 0)
             error (EXIT_FAILURE, 0, _("division by zero"));
index c6b978785f66a216e473432266ef50f54dfac357..8751119f11ad62e8611f04b4a89a671f780e642e 100755 (executable)
@@ -26,9 +26,11 @@ my @Tests =
       {IN=> "ça\nçb\n"},
       {OUT=>"ça b\n"}],
      ['wide-1', '-w 32768',
-      {ERR => "fmt: invalid width: '32768'\n"}, {EXIT => 1}],
+      {ERR => "fmt: invalid width: '32768'"}, {EXIT => 1},
+      {ERR_SUBST => 's/:[^:]*$//'}],
      ['wide-2', '-w 2147483647',
-      {ERR => "fmt: invalid width: '2147483647'\n"}, {EXIT => 1}],
+      {ERR => "fmt: invalid width: '2147483647'"}, {EXIT => 1},
+      {ERR_SUBST => 's/:[^:]*$//'}],
      ['bad-suffix', '-72x',    {IN=> ''},
       {ERR => "fmt: invalid width: '72x'\n"}, {EXIT => 1}],
      ['no-file', 'no-such-file',
index 349e322b05e4fe38b9832f82f24ab10105d24251..6aec69b0ae80a28e17f00a5b9196f66c07d5d3da 100644 (file)
@@ -320,9 +320,9 @@ all_tests =                                 \
   tests/misc/sha384sum.pl                      \
   tests/misc/sha512sum.pl                      \
   tests/misc/shred-exact.sh                    \
-  tests/misc/shred-negative.sh                 \
   tests/misc/shred-passes.sh                   \
   tests/misc/shred-remove.sh                   \
+  tests/misc/shred-size.sh                     \
   tests/misc/shuf.sh                           \
   tests/misc/shuf-reservoir.sh                 \
   tests/misc/sort.pl                           \
@@ -557,6 +557,7 @@ all_tests =                                 \
   tests/ls/file-type.sh                                \
   tests/ls/follow-slink.sh                     \
   tests/ls/getxattr-speedup.sh                 \
+  tests/ls/hex-option.sh                       \
   tests/ls/infloop.sh                          \
   tests/ls/inode.sh                            \
   tests/ls/m-option.sh                         \
similarity index 79%
rename from tests/misc/shred-negative.sh
rename to tests/ls/hex-option.sh
index 86cbf3e02d05be54af1080082fb717a0c7f51ff1..0a684b06e223b2136c3b7a87fe669f4160e37485 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# Exercise shred -s-3 FILE
+# accept hex/oct numbers to -w and -T
 
 # Copyright (C) 2014 Free Software Foundation, Inc.
 
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
-print_ver_ shred
+print_ver_ ls
 
-echo 'shred: -2: invalid file size' > exp || framework_failure_
-echo 1234 > f || framework_failure_
-
-shred -s-2 f 2>err && fail=1
-compare exp err || fail=1
+ls -x -T0x10 -w010 || fail=1
 
 Exit $fail
diff --git a/tests/misc/shred-size.sh b/tests/misc/shred-size.sh
new file mode 100755 (executable)
index 0000000..9eabf60
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+# Exercise shred --size
+
+# Copyright (C) 2014 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 3 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, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ shred
+
+# Negative size
+echo "shred: invalid file size: '-2'" > exp || framework_failure_
+echo 1234 > f || framework_failure_
+shred -s-2 f 2>err && fail=1
+compare exp err || fail=1
+
+# Octal/Hex
+shred -s010 f || fail=1
+test $(stat --printf=%s f) = 8 || fail=1
+shred -s0x10 f || fail=1
+test $(stat --printf=%s f) = 16 || fail=1
+
+Exit $fail
index 729d6f91365bb7616bead009078139cd267c2f27..1c7af1da0a38780978f96154d5052545b4f339be 100755 (executable)
@@ -47,6 +47,8 @@ tests='
 7 rows_1 1_1
 8 columns_80 1_80
 9 rows_30 30_80
+10 rows_0x1E 30_80
+11 rows_036 30_80
 NA LAST NA
 '
 set $tests
index 6798eb05dd3539c48b8a6c1e6e2ab1cccd260450..adeff685721f1f7bfe17d2299f53b5e3ed0ce272 100755 (executable)
@@ -19,7 +19,7 @@
 use strict;
 
 my $prog = 'tail';
-my $normalize_filename = {ERR_SUBST => 's/^$prog: .*?:/$prog: -:/'};
+my $normalize_strerror = 's/:[^:]*$//';
 
 # Turn off localization of executable's output.
 @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
@@ -59,7 +59,7 @@ my @tv = (
  "$prog: cannot open '+cl' for reading: No such file or directory\n"],
 
 ['err-2', '-cl', '', '', 1,
- "$prog: l: invalid number of bytes\n"],
+ "$prog: invalid number of bytes: 'l'\n"],
 
 ['err-3', '+2cz', '', '', 1,
  "$prog: cannot open '+2cz' for reading: No such file or directory\n"],
@@ -72,9 +72,9 @@ my @tv = (
 # the diagnostic: 'tail: 99999999999999999999: invalid number of bytes'
 # on all systems... probably, for now, maybe.
 ['err-5', '-c99999999999999999999', '', '', 1,
- "$prog: 99999999999999999999: invalid number of bytes\n"],
+ "$prog: invalid number of bytes: '99999999999999999999'", $normalize_strerror],
 ['err-6', '-c --', '', '', 1,
- "$prog: -: invalid number of bytes\n", $normalize_filename],
+ "$prog: invalid number of bytes: '-'\n"],
 
 # Same as -n 10
 ['minus-1', '-', '', '', 0],
@@ -106,10 +106,10 @@ my @Tests;
 
 foreach my $t (@tv)
   {
-    my ($test_name, $flags, $in, $exp, $ret, $err_msg) = @$t;
+    my ($test_name, $flags, $in, $exp, $ret, $err_msg, $err_sub) = @$t;
     my $e = [$test_name, $flags, {IN=>$in}, {OUT=>$exp}];
     $ret
-      and push @$e, {EXIT=>$ret}, {ERR=>$err_msg};
+      and push @$e, {EXIT=>$ret}, {ERR=>$err_msg}, {ERR_SUBST=>$err_sub};
 
     $test_name =~ /^(obs-plus-|minus-)/
       and push @$e, {ENV=>'_POSIX2_VERSION=199209'};
index 10947ac95d377cbbd725a4b0fd737e4834901f1b..cc2ef38c47cd3bcb30ce693b600781a5de258df3 100755 (executable)
@@ -385,9 +385,11 @@ my @tv = (
 ['col-long', '-W3 -t -1 --columns=2',     "a\nb\nc\n", "a c\nb\n", 0],
 # Make sure these fail.
 ['col-0', '-0', '', '', 1,
- "$prog: invalid number of columns: '0'\n"],
+ "$prog: invalid number of columns: '0'",
+ 's/:[^:]*$//'],
 ['col-inval', '-'.'9'x100, '', '', 1,
- "$prog: invalid number of columns: '". ('9'x100) ."'\n"],
+ "$prog: invalid number of columns: '". ('9'x100) ."'",
+ 's/:[^:]*$//'],
 
 # Before coreutils-5.3.1, --pages=1:-1 would be treated like
 # --pages=1:18446744073709551615.
@@ -427,7 +429,7 @@ my $common_option_prefix = '--date-format="-- Date/Time --" -h x';
 my @Tests;
 foreach my $t (@tv)
   {
-    my ($test_name, $flags, $in, $exp, $ret, $err_msg) = @$t;
+    my ($test_name, $flags, $in, $exp, $ret, $err_msg, $err_sub) = @$t;
     my $new_ent = [$test_name, $common_option_prefix, $flags];
     if (!ref $in)
       {
@@ -454,7 +456,7 @@ foreach my $t (@tv)
           }
       }
     $ret
-      and push @$new_ent, {EXIT=>$ret}, {ERR=>$err_msg};
+      and push @$new_ent, {EXIT=>$ret}, {ERR=>$err_msg}, {ERR_SUBST=>$err_sub};
     push @Tests, $new_ent;
   }
 
index 792c556915d7172cd97a3ad1a9b21785b6fbda58..39ee4dc036385844794b9d8bb8c3456773eec345 100755 (executable)
@@ -20,7 +20,7 @@
 print_ver_ split
 
 # invalid number of chunks
-echo 'split: 1o: invalid number of chunks' > exp
+echo "split: invalid number of chunks: '1o'" > exp
 split -n l/1o 2>err && fail=1
 compare exp err || fail=1
 
@@ -53,8 +53,9 @@ lines=\
 
 printf "%s" "$lines" | tr '~' '\n' > in || framework_failure_
 
-echo 'split: 16: invalid chunk number' > exp
-split -n l/16/15 in 2>err && fail=1
+echo "split: invalid chunk number: '16'" > exp
+split -n l/16/15 in 2>err.t && fail=1
+sed 's/:[^:]*$//' < err.t > err || framework_failure_
 compare exp err || fail=1
 
 printf '%s' "\