summaryrefslogtreecommitdiff
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-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
16 files changed, 142 insertions, 345 deletions
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"));