mirror of
https://git.savannah.gnu.org/git/coreutils.git
synced 2025-09-10 07:59:52 +02:00
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.
This commit is contained in:
@@ -273,6 +273,7 @@ gnulib_modules="
|
||||
xprintf
|
||||
xprintf-posix
|
||||
xreadlink
|
||||
xdectoint
|
||||
xstrtod
|
||||
xstrtoimax
|
||||
xstrtol
|
||||
|
||||
2
cfg.mk
2
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)
|
||||
|
||||
|
||||
6
gl/lib/xdectoimax.c
Normal file
6
gl/lib/xdectoimax.c
Normal file
@@ -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"
|
||||
85
gl/lib/xdectoint.c
Normal file
85
gl/lib/xdectoint.c
Normal file
@@ -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);
|
||||
}
|
||||
36
gl/lib/xdectoint.h
Normal file
36
gl/lib/xdectoint.h
Normal file
@@ -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_ */
|
||||
6
gl/lib/xdectoumax.c
Normal file
6
gl/lib/xdectoumax.c
Normal file
@@ -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"
|
||||
29
gl/modules/xdectoint
Normal file
29
gl/modules/xdectoint
Normal file
@@ -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
|
||||
@@ -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':
|
||||
|
||||
2
src/dd.c
2
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
18
src/fmt.c
18
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;
|
||||
}
|
||||
|
||||
13
src/fold.c
13
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;
|
||||
|
||||
32
src/head.c
32
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
|
||||
|
||||
25
src/ls.c
25
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;
|
||||
|
||||
46
src/nl.c
46
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"))
|
||||
|
||||
@@ -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:
|
||||
|
||||
98
src/pr.c
98
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);
|
||||
|
||||
29
src/shred.c
29
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':
|
||||
|
||||
19
src/shuf.c
19
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;
|
||||
|
||||
94
src/split.c
94
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. */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
46
src/tail.c
46
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;
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
34
tests/misc/shred-size.sh
Executable file
34
tests/misc/shred-size.sh
Executable file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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'};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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' "\
|
||||
|
||||
Reference in New Issue
Block a user