summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2014-12-16 12:36:39 +0000
committerPádraig Brady <P@draigBrady.com>2014-12-19 11:56:20 +0000
commit6894816c653adef54f3a85becbf75a865d6d39d6 (patch)
tree82bb3126d3c8cfaeebc950bd03a52a4f5e0f056c
parent178f8e79dcd1e0b8bbb3b04da664d05eaae56186 (diff)
downloadcoreutils-6894816c653adef54f3a85becbf75a865d6d39d6.tar.xz
diagnose too-large numbers better
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.
-rw-r--r--bootstrap.conf1
-rw-r--r--cfg.mk2
-rw-r--r--gl/lib/xdectoimax.c6
-rw-r--r--gl/lib/xdectoint.c85
-rw-r--r--gl/lib/xdectoint.h36
-rw-r--r--gl/lib/xdectoumax.c6
-rw-r--r--gl/modules/xdectoint29
-rw-r--r--src/csplit.c8
-rw-r--r--src/dd.c2
-rw-r--r--src/fmt.c18
-rw-r--r--src/fold.c13
-rw-r--r--src/head.c32
-rw-r--r--src/ls.c25
-rw-r--r--src/nl.c46
-rw-r--r--src/nproc.c8
-rw-r--r--src/pr.c98
-rw-r--r--src/shred.c29
-rw-r--r--src/shuf.c19
-rw-r--r--src/split.c94
-rw-r--r--src/stdbuf.c4
-rw-r--r--src/stty.c9
-rw-r--r--src/tail.c46
-rw-r--r--src/truncate.c36
-rwxr-xr-xtests/fmt/base.pl6
-rw-r--r--tests/local.mk3
-rwxr-xr-xtests/ls/hex-option.sh (renamed from tests/misc/shred-negative.sh)10
-rwxr-xr-xtests/misc/shred-size.sh34
-rwxr-xr-xtests/misc/stty-row-col.sh2
-rwxr-xr-xtests/misc/tail.pl12
-rwxr-xr-xtests/pr/pr-tests.pl10
-rwxr-xr-xtests/split/l-chunk.sh7
31 files changed, 367 insertions, 369 deletions
diff --git a/bootstrap.conf b/bootstrap.conf
index c0b5f0233..7706c5a79 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -273,6 +273,7 @@ gnulib_modules="
xprintf
xprintf-posix
xreadlink
+ xdectoint
xstrtod
xstrtoimax
xstrtol
diff --git a/cfg.mk b/cfg.mk
index ee444bac2..5a96acfaf 100644
--- 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
index 000000000..d4bb18fa1
--- /dev/null
+++ b/gl/lib/xdectoimax.c
@@ -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
index 000000000..2164d1ef4
--- /dev/null
+++ b/gl/lib/xdectoint.c
@@ -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
index 000000000..770e18571
--- /dev/null
+++ b/gl/lib/xdectoint.h
@@ -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
index 000000000..412ddf962
--- /dev/null
+++ b/gl/lib/xdectoumax.c
@@ -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
index 000000000..cbd372666
--- /dev/null
+++ b/gl/modules/xdectoint
@@ -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
diff --git a/src/csplit.c b/src/csplit.c
index af72d8f67..15c477178 100644
--- a/src/csplit.c
+++ b/src/csplit.c
@@ -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':
diff --git a/src/dd.c b/src/dd.c
index d652fee14..49d0d2a0c 100644
--- 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));
}
}
diff --git a/src/fmt.c b/src/fmt.c
index f235da9ac..e3719d2c3 100644
--- 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;
}
diff --git a/src/fold.c b/src/fold.c
index 3bc9ba29f..20cb61eca 100644
--- a/src/fold.c
+++ b/src/fold.c
@@ -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;
diff --git a/src/head.c b/src/head.c
index 2782f8e8c..7fc161a49 100644
--- a/src/head.c
+++ b/src/head.c
@@ -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
diff --git a/src/ls.c b/src/ls.c
index 5bae06fbe..82402ee77 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -105,6 +105,7 @@
#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;
diff --git a/src/nl.c b/src/nl.c
index 7fc113442..5c341620a 100644
--- 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"))
diff --git a/src/nproc.c b/src/nproc.c
index e1bc1d0b7..4ba146a34 100644
--- a/src/nproc.c
+++ b/src/nproc.c
@@ -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:
diff --git a/src/pr.c b/src/pr.c
index 529964985..d6823b513 100644
--- a/src/pr.c
+++ b/src/pr.c
@@ -322,6 +322,7 @@
#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);
diff --git a/src/shred.c b/src/shred.c
index b235b29ae..2e5719914 100644
--- a/src/shred.c
+++ b/src/shred.c
@@ -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':
diff --git a/src/shuf.c b/src/shuf.c
index df0092b90..0678c3da6 100644
--- a/src/shuf.c
+++ b/src/shuf.c
@@ -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;
diff --git a/src/split.c b/src/split.c
index 0eec3ecc2..008d2a7e2 100644
--- a/src/split.c
+++ b/src/split.c
@@ -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. */
diff --git a/src/stdbuf.c b/src/stdbuf.c
index 3fb5d3c42..94a7a4fca 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 42ec3b447..41909b75e 100644
--- a/src/stty.c
+++ b/src/stty.c
@@ -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);
}
diff --git a/src/tail.c b/src/tail.c
index 4c5f943c7..28524d71f 100644
--- a/src/tail.c
+++ b/src/tail.c
@@ -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;
diff --git a/src/truncate.c b/src/truncate.c
index f06668de5..e4ef5e733 100644
--- a/src/truncate.c
+++ b/src/truncate.c
@@ -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"));
diff --git a/tests/fmt/base.pl b/tests/fmt/base.pl
index c6b978785..8751119f1 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/local.mk b/tests/local.mk
index 349e322b0..6aec69b0a 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -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 \
diff --git a/tests/misc/shred-negative.sh b/tests/ls/hex-option.sh
index 86cbf3e02..0a684b06e 100755
--- a/tests/misc/shred-negative.sh
+++ b/tests/ls/hex-option.sh
@@ -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.
@@ -17,12 +17,8 @@
# 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
index 000000000..9eabf606c
--- /dev/null
+++ b/tests/misc/shred-size.sh
@@ -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
diff --git a/tests/misc/stty-row-col.sh b/tests/misc/stty-row-col.sh
index 729d6f913..1c7af1da0 100755
--- a/tests/misc/stty-row-col.sh
+++ b/tests/misc/stty-row-col.sh
@@ -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
diff --git a/tests/misc/tail.pl b/tests/misc/tail.pl
index 6798eb05d..adeff6857 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;
@@ -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'};
diff --git a/tests/pr/pr-tests.pl b/tests/pr/pr-tests.pl
index 10947ac95..cc2ef38c4 100755
--- a/tests/pr/pr-tests.pl
+++ b/tests/pr/pr-tests.pl
@@ -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;
}
diff --git a/tests/split/l-chunk.sh b/tests/split/l-chunk.sh
index 792c55691..39ee4dc03 100755
--- a/tests/split/l-chunk.sh
+++ b/tests/split/l-chunk.sh
@@ -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' "\