On 16/12/14 07:46, Paul Eggert wrote:
> Pádraig Brady wrote:
>> I wonder should other coreutils use that for "invalid number..." errors?
> 
> Well, at least dd should.  I installed the attached patch into coreutils.
> [http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=addae94b]

For consistency the attached does so for other coreutils.

thanks,
Pádraig
From 375749c8c685cc209303192b9f04fc77c454caa6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email protected]>
Date: Tue, 16 Dec 2014 12:36:39 +0000
Subject: [PATCH] split,head,tail,pr: give better diagnostics for large numbers

Following on from commit v8.23-82-gaddae94, consistently diagnose
in other utilities, numbers that are too large, so as to
distinguish from other parsing errors.

* src/csplit.c: Output the EOVERFLOW diagnostic where 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/split.c: Likewise.
* src/stdbuf.c: Likewise.
* src/stty.c: Likewise.
* src/tail.c: Likewise.
* src/pr.c: Likewise.
(getoptnum): Refactor int parsing to this new function.
* tests/pr/pr-tests.pl: Adjust to avoid matching EOVERFLOW diagnostic.
* tests/fmt/base.pl: Likewise.
* tests/misc/tail.pl: Likewise.  Also remove the redundant
existing ERR_SUBST from test err-6.
---
 src/csplit.c         |  4 +--
 src/fmt.c            | 12 +++----
 src/fold.c           |  6 ++--
 src/head.c           | 18 ++++------
 src/ls.c             |  9 ++---
 src/nl.c             | 10 +++---
 src/nproc.c          |  2 +-
 src/pr.c             | 93 +++++++++++++++++++++-------------------------------
 src/shred.c          | 15 +++++----
 src/shuf.c           |  6 ++--
 src/split.c          | 30 +++++++++--------
 src/stdbuf.c         |  4 +--
 src/stty.c           |  5 +--
 src/tail.c           | 15 +++++----
 tests/fmt/base.pl    |  6 ++--
 tests/misc/tail.pl   | 10 +++---
 tests/pr/pr-tests.pl |  7 ++--
 17 files changed, 120 insertions(+), 132 deletions(-)

diff --git a/src/csplit.c b/src/csplit.c
index af72d8f..6171303 100644
--- a/src/csplit.c
+++ b/src/csplit.c
@@ -1367,8 +1367,8 @@ main (int argc, char **argv)
 
       case 'n':
         if (xstrtoul (optarg, NULL, 10, &val, "") != LONGINT_OK
-            || MIN (INT_MAX, SIZE_MAX) < val)
-          error (EXIT_FAILURE, 0, _("%s: invalid number"), optarg);
+            || (MIN (INT_MAX, SIZE_MAX) < val && (errno = EOVERFLOW)))
+          error (EXIT_FAILURE, errno, _("invalid number %s"), quote (optarg));
         digits = val;
         break;
 
diff --git a/src/fmt.c b/src/fmt.c
index f235da9..17e7101 100644
--- a/src/fmt.c
+++ b/src/fmt.c
@@ -400,9 +400,9 @@ 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"),
+      if (xstrtoul (max_width_option, NULL, 10, &tmp, "") != LONGINT_OK
+          || (MAXCHARS / 2 < tmp && (errno = EOVERFLOW)))
+        error (EXIT_FAILURE, errno, _("invalid width: %s"),
                quote (max_width_option));
       max_width = tmp;
     }
@@ -411,9 +411,9 @@ main (int argc, char **argv)
     {
       /* 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"),
+      if (xstrtoul (goal_width_option, NULL, 10, &tmp, "") != LONGINT_OK
+          || (max_width < tmp && (errno = EOVERFLOW)))
+        error (EXIT_FAILURE, errno, _("invalid width: %s"),
                quote (goal_width_option));
       goal_width = tmp;
       if (max_width_option == NULL)
diff --git a/src/fold.c b/src/fold.c
index 3bc9ba2..fa66fea 100644
--- a/src/fold.c
+++ b/src/fold.c
@@ -282,9 +282,9 @@ main (int argc, char **argv)
         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,
+            if (xstrtoul (optarg, NULL, 10, &tmp_ulong, "") != LONGINT_OK
+                || (SIZE_MAX - TAB_WIDTH <= tmp_ulong && (errno = EOVERFLOW)))
+              error (EXIT_FAILURE, errno,
                      _("invalid number of columns: %s"), quote (optarg));
             width = tmp_ulong;
           }
diff --git a/src/head.c b/src/head.c
index 2782f8e..bb22669 100644
--- a/src/head.c
+++ b/src/head.c
@@ -907,19 +907,13 @@ string_to_integer (bool count_lines, const char *n_string)
 
   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,
+      error (EXIT_FAILURE, s_err == LONGINT_OVERFLOW ? EOVERFLOW : errno,
              (count_lines
-              ? _("invalid number of lines")
-              : _("invalid number of bytes")));
+              ? _("invalid number of lines %s")
+              : _("invalid number of bytes %s")),
+             quote (n_string));
     }
 
   return n;
@@ -1076,8 +1070,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, _("invalid number of bytes %s"),
+             quote (umaxtostr (n_units, umax_buf)));
     }
 
   file_list = (optind < argc
diff --git a/src/ls.c b/src/ls.c
index 5bae06f..48ba73c 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -1745,8 +1745,9 @@ decode_switches (int argc, char **argv)
           {
             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"),
+                || tmp_ulong <= 0
+                || (SIZE_MAX < tmp_ulong && (errno = EOVERFLOW)))
+              error (LS_FAILURE, errno, _("invalid line width: %s"),
                      quotearg (optarg));
             line_length = tmp_ulong;
             break;
@@ -1819,8 +1820,8 @@ decode_switches (int argc, char **argv)
           {
             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"),
+                || (SIZE_MAX < tmp_ulong && (errno = EOVERFLOW)))
+              error (LS_FAILURE, errno, _("invalid tab size: %s"),
                      quotearg (optarg));
             tabsize = tmp_ulong;
             break;
diff --git a/src/nl.c b/src/nl.c
index 7fc1134..33e51da 100644
--- a/src/nl.c
+++ b/src/nl.c
@@ -500,7 +500,7 @@ main (int argc, char **argv)
           if (xstrtoimax (optarg, NULL, 10, &starting_line_number, "")
               != LONGINT_OK)
             {
-              error (0, 0, _("invalid starting line number: %s"),
+              error (0, errno, _("invalid starting line number: %s"),
                      quote (optarg));
               ok = false;
             }
@@ -509,7 +509,7 @@ main (int argc, char **argv)
           if (! (xstrtoimax (optarg, NULL, 10, &page_incr, "") == LONGINT_OK
                  && 0 < page_incr))
             {
-              error (0, 0, _("invalid line number increment: %s"),
+              error (0, errno, _("invalid line number increment: %s"),
                      quote (optarg));
               ok = false;
             }
@@ -521,7 +521,7 @@ main (int argc, char **argv)
           if (! (xstrtoimax (optarg, NULL, 10, &blank_join, "") == LONGINT_OK
                  && 0 < blank_join))
             {
-              error (0, 0, _("invalid number of blank lines: %s"),
+              error (0, errno, _("invalid number of blank lines: %s"),
                      quote (optarg));
               ok = false;
             }
@@ -533,9 +533,9 @@ main (int argc, char **argv)
           {
             long int tmp_long;
             if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK
-                || tmp_long <= 0 || tmp_long > INT_MAX)
+                || tmp_long <= 0 || (INT_MAX < tmp_long && (errno = EOVERFLOW)))
               {
-                error (0, 0, _("invalid line number field width: %s"),
+                error (0, errno, _("invalid line number field width: %s"),
                        quote (optarg));
                 ok = false;
               }
diff --git a/src/nproc.c b/src/nproc.c
index e1bc1d0..5395535 100644
--- a/src/nproc.c
+++ b/src/nproc.c
@@ -104,7 +104,7 @@ main (int argc, char **argv)
         case IGNORE_OPTION:
           if (xstrtoul (optarg, NULL, 10, &ignore, "") != LONGINT_OK)
             {
-              error (0, 0, _("%s: invalid number to ignore"), optarg);
+              error (0, errno, _("invalid number %s"), quote (optarg));
               usage (EXIT_FAILURE);
             }
           break;
diff --git a/src/pr.c b/src/pr.c
index 5299649..d2a1c0e 100644
--- a/src/pr.c
+++ b/src/pr.c
@@ -424,6 +424,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);
@@ -827,8 +829,8 @@ 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,
+      || tmp_long < 1 || (INT_MAX < tmp_long && (errno = EOVERFLOW)))
+    error (EXIT_FAILURE, errno,
            _("invalid number of columns: %s"), quote (s));
 
   columns = tmp_long;
@@ -966,18 +968,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: %s"));
+          break;
         case 'm':
           parallel_files = true;
           storing_columns = false;
@@ -990,28 +983,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: %s"));
+          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: %s"));
+          break;
         case 'r':
           ignore_failed_opens = true;
           break;
@@ -1045,29 +1023,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: %s"));
+            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: %s"));
+          break;
         case_GETOPT_HELP_CHAR;
         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
         default:
@@ -1173,6 +1141,19 @@ main (int argc, char **argv)
   return failed_opens ? EXIT_FAILURE : EXIT_SUCCESS;
 }
 
+/* Parse numeric arguments, ensuring 0 < number < INT_MAX.  */
+
+static void
+getoptnum (const char *n_str, int min, int *num, const char *errfmt)
+{
+  long int tmp_long;
+  if (xstrtol (n_str, NULL, 10, &tmp_long, "") != LONGINT_OK
+      || tmp_long < min || (INT_MAX < tmp_long && (errno = EOVERFLOW)))
+    error (EXIT_FAILURE, errno, errfmt, quote (n_str));
+
+  *num = tmp_long;
+}
+
 /* Parse options of the form -scNNN.
 
    Example: -nck, where 'n' is the option, c is the optional number
@@ -1188,9 +1169,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 && (errno = EOVERFLOW)))
         {
-          error (0, 0,
+          error (0, errno,
              _("'-%c' extra characters or invalid number in the argument: %s"),
                  switch_char, quote (arg));
           usage (EXIT_FAILURE);
diff --git a/src/shred.c b/src/shred.c
index b235b29..17c24a5 100644
--- a/src/shred.c
+++ b/src/shred.c
@@ -1231,9 +1231,10 @@ main (int argc, char **argv)
           {
             uintmax_t tmp;
             if (xstrtoumax (optarg, NULL, 10, &tmp, NULL) != LONGINT_OK
-                || MIN (ULONG_MAX, SIZE_MAX / sizeof (int)) <= tmp)
+                || (MIN (ULONG_MAX, SIZE_MAX / sizeof (int)) <= tmp
+                    && (errno = EOVERFLOW)))
               {
-                error (EXIT_FAILURE, 0, _("%s: invalid number of passes"),
+                error (EXIT_FAILURE, errno, _("%s: invalid number of passes"),
                        quotearg_colon (optarg));
               }
             flags.n_iterations = tmp;
@@ -1257,11 +1258,13 @@ main (int argc, char **argv)
         case 's':
           {
             uintmax_t tmp;
-            if ((xstrtoumax (optarg, NULL, 0, &tmp, "cbBkKMGTPEZY0")
-                 != LONGINT_OK)
-                || OFF_T_MAX < tmp)
+            strtol_error s_err;
+            s_err = xstrtoumax (optarg, NULL, 0, &tmp, "cbBkKMGTPEZY0");
+            if ((s_err == LONGINT_OVERFLOW && (errno = EOVERFLOW))
+                || s_err != LONGINT_OK
+                || (OFF_T_MAX < tmp && (errno = EOVERFLOW)))
               {
-                error (EXIT_FAILURE, 0, _("%s: invalid file size"),
+                error (EXIT_FAILURE, errno, _("%s: invalid file size"),
                        quotearg_colon (optarg));
               }
             flags.size = tmp;
diff --git a/src/shuf.c b/src/shuf.c
index df0092b..feac6f9 100644
--- a/src/shuf.c
+++ b/src/shuf.c
@@ -436,7 +436,7 @@ main (int argc, char **argv)
               *p = '\0';
               invalid = ((xstrtoul (optarg, NULL, 10, &argval, NULL)
                           != LONGINT_OK)
-                         || SIZE_MAX < argval);
+                         || (SIZE_MAX < argval && (errno = EOVERFLOW)));
               *p = '-';
               lo_input = argval;
               hi_optarg = p + 1;
@@ -444,12 +444,12 @@ main (int argc, char **argv)
 
           invalid |= ((xstrtoul (hi_optarg, NULL, 10, &argval, NULL)
                        != LONGINT_OK)
-                      || SIZE_MAX < argval);
+                      || (SIZE_MAX < argval && (errno = EOVERFLOW)));
           hi_input = argval;
           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, _("invalid input range %s"),
                    quote (optarg));
         }
         break;
diff --git a/src/split.c b/src/split.c
index 0eec3ec..75f75b8 100644
--- a/src/split.c
+++ b/src/split.c
@@ -1182,11 +1182,11 @@ 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);
+    error (EXIT_FAILURE, errno, _("%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);
+    error (EXIT_FAILURE, errno, _("%s: invalid chunk number"), optarg);
 }
 
 
@@ -1234,9 +1234,9 @@ main (int argc, char **argv)
           {
             unsigned long tmp;
             if (xstrtoul (optarg, NULL, 10, &tmp, "") != LONGINT_OK
-                || SIZE_MAX / sizeof (size_t) < tmp)
+                || (SIZE_MAX / sizeof (size_t) < tmp && (errno = EOVERFLOW)))
               {
-                error (0, 0, _("%s: invalid suffix length"), optarg);
+                error (0, errno, _("%s: invalid suffix length"), optarg);
                 usage (EXIT_FAILURE);
               }
             suffix_length = tmp;
@@ -1261,14 +1261,14 @@ main (int argc, char **argv)
           if (xstrtoumax (optarg, NULL, 10, &n_units, multipliers) != LONGINT_OK
               || n_units == 0)
             {
-              error (0, 0, _("%s: invalid number of bytes"), optarg);
+              error (0, errno, _("%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,
+            error (EXIT_FAILURE, EOVERFLOW,
                    _("%s: invalid number of bytes"), optarg);
 
           break;
@@ -1280,7 +1280,7 @@ main (int argc, char **argv)
           if (xstrtoumax (optarg, NULL, 10, &n_units, "") != LONGINT_OK
               || n_units == 0)
             {
-              error (0, 0, _("%s: invalid number of lines"), optarg);
+              error (0, errno, _("%s: invalid number of lines"), optarg);
               usage (EXIT_FAILURE);
             }
           break;
@@ -1290,13 +1290,13 @@ main (int argc, char **argv)
             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)
+              || n_units == 0 || (SIZE_MAX < n_units && (errno = EOVERFLOW)))
             {
-              error (0, 0, _("%s: invalid number of bytes"), optarg);
+              error (0, errno, _("%s: invalid number of bytes"), optarg);
               usage (EXIT_FAILURE);
             }
           if (OFF_T_MAX < n_units)
-            error (EXIT_FAILURE, EFBIG,
+            error (EXIT_FAILURE, EOVERFLOW,
                    _("%s: invalid number of bytes"), optarg);
           break;
 
@@ -1322,7 +1322,10 @@ main (int argc, char **argv)
             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);
+            {
+              error (EXIT_FAILURE, errno, _("%s: invalid number of chunks"),
+                     optarg);
+            }
           break;
 
         case 'u':
@@ -1392,8 +1395,9 @@ main (int argc, char **argv)
             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);
+                || tmp_blk_size == 0 || (SIZE_MAX - page_size < tmp_blk_size
+                                         && (errno = EOVERFLOW)))
+              error (0, errno, _("%s: invalid IO block size"), optarg);
             else
               in_blk_size = tmp_blk_size;
           }
diff --git a/src/stdbuf.c b/src/stdbuf.c
index 3fb5d3c..94a7a4f 100644
--- a/src/stdbuf.c
+++ b/src/stdbuf.c
@@ -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;
 }
 
diff --git a/src/stty.c b/src/stty.c
index 42ec3b4..51ae3b7 100644
--- a/src/stty.c
+++ b/src/stty.c
@@ -2088,9 +2088,10 @@ 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)
+  if (xstrtoul (s, NULL, 0, &value, "bB") != LONGINT_OK
+      || (maxval < value && (errno = EOVERFLOW)))
     {
-      error (0, 0, _("invalid integer argument %s"), quote (s));
+      error (0, errno, _("invalid integer argument %s"), quote (s));
       usage (EXIT_FAILURE);
     }
   return value;
diff --git a/src/tail.c b/src/tail.c
index 4c5f943..0bcf160 100644
--- a/src/tail.c
+++ b/src/tail.c
@@ -1949,7 +1949,7 @@ 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, _("invalid number %s"), quote (argv[1]));
 
   /* Set globals.  */
   from_start = t_from_start;
@@ -1991,7 +1991,9 @@ parse_options (int argc, char **argv,
             s_err = xstrtoumax (optarg, NULL, 10, n_units, "bkKmMGTPEZY0");
             if (s_err != LONGINT_OK)
               {
-                error (EXIT_FAILURE, 0, "%s: %s", optarg,
+                error (EXIT_FAILURE,
+                       s_err == LONGINT_OVERFLOW ? EOVERFLOW : errno,
+                       "%s: %s", optarg,
                        (c == 'n'
                         ? _("invalid number of lines")
                         : _("invalid number of bytes")));
@@ -2020,7 +2022,7 @@ parse_options (int argc, char **argv,
                           "")
               != LONGINT_OK)
             {
-              error (EXIT_FAILURE, 0,
+              error (EXIT_FAILURE, errno,
                _("%s: invalid maximum number of unchanged stats between opens"),
                      optarg);
             }
@@ -2035,10 +2037,9 @@ parse_options (int argc, char **argv,
             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);
-              }
+            if (s_err != LONGINT_OK || (PID_T_MAX < tmp_ulong
+                                        && (errno = EOVERFLOW)))
+              error (EXIT_FAILURE, errno, _("%s: invalid PID"), optarg);
             pid = tmp_ulong;
           }
           break;
diff --git a/tests/fmt/base.pl b/tests/fmt/base.pl
index c6b9787..8751119 100755
--- a/tests/fmt/base.pl
+++ b/tests/fmt/base.pl
@@ -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',
diff --git a/tests/misc/tail.pl b/tests/misc/tail.pl
index 6798eb0..aa946b2 100755
--- a/tests/misc/tail.pl
+++ b/tests/misc/tail.pl
@@ -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;
@@ -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: 99999999999999999999: invalid number of bytes", $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'};
diff --git a/tests/pr/pr-tests.pl b/tests/pr/pr-tests.pl
index 10947ac..a1fee2e 100755
--- a/tests/pr/pr-tests.pl
+++ b/tests/pr/pr-tests.pl
@@ -387,7 +387,8 @@ my @tv = (
 ['col-0', '-0', '', '', 1,
  "$prog: invalid number of columns: '0'\n"],
 ['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 +428,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 +455,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;
   }
 
-- 
2.1.0

Reply via email to