git: db95aeb922c9 - stable/13 - split: Further option parsing improvements.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 05 Oct 2023 15:56:06 UTC
The branch stable/13 has been updated by des:
URL: https://cgit.FreeBSD.org/src/commit/?id=db95aeb922c9ca20d0914a6ee449064e6d507fe8
commit db95aeb922c9ca20d0914a6ee449064e6d507fe8
Author: Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2023-09-28 16:29:52 +0000
Commit: Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2023-10-05 15:55:30 +0000
split: Further option parsing improvements.
* Whenever possible, use strtonum() to parse numeric arguments.
* Improve usefulness and consistency of error messages.
* While here, fix some type and style issues.
Sponsored by: Klara, Inc.
Reviewed by: christos, kevans
Differential Revision: https://reviews.freebsd.org/D42010
(cherry picked from commit d7399551b02861b910b15c7b7a78a2835644aa45)
split: Improve GNU compatibility.
* Like GNU split, turn autoextend back on if given -a0.
* Add a test case that verifies that -a<non-zero> turns autoextend off.
* Add a test case that verifies that -a0 turns autoextend back on.
Sponsored by: Klara, Inc.
Reviewed by: christos, kevans
Differential Revision: https://reviews.freebsd.org/D42011
(cherry picked from commit d9d69a6f6fc1f8d80df9ce6493e8ab9388781615)
---
usr.bin/split/split.c | 89 ++++++++++++++++++++++-----------------
usr.bin/split/tests/split_test.sh | 19 +++++++++
2 files changed, 70 insertions(+), 38 deletions(-)
diff --git a/usr.bin/split/split.c b/usr.bin/split/split.c
index af1ed69c9482..e246a0d4adfc 100644
--- a/usr.bin/split/split.c
+++ b/usr.bin/split/split.c
@@ -63,7 +63,7 @@ static const char sccsid[] = "@(#)split.c 8.2 (Berkeley) 4/16/94";
#define DEFLINE 1000 /* Default num lines per file. */
static off_t bytecnt; /* Byte count to split on. */
-static off_t chunks = 0; /* Chunks count to split into. */
+static long chunks; /* Chunks count to split into. */
static bool clobber = true; /* Whether to overwrite existing output files. */
static long numlines; /* Line count to split on. */
static int file_open; /* If a file open. */
@@ -73,7 +73,7 @@ static regex_t rgx;
static int pflag;
static bool dflag;
static long sufflen = 2; /* File name suffix length. */
-static int autosfx = 1; /* Whether to auto-extend the suffix length. */
+static bool autosfx = true; /* Whether to auto-extend the suffix length. */
static void newfile(void);
static void split1(void);
@@ -84,8 +84,8 @@ static void usage(void) __dead2;
int
main(int argc, char **argv)
{
- const char *p;
- char *ep;
+ char errbuf[64];
+ const char *p, *errstr;
int ch, error;
setlocale(LC_ALL, "");
@@ -106,20 +106,27 @@ main(int argc, char **argv)
while (numlines >= 0 && *p >= '0' && *p <= '9')
numlines = numlines * 10 + *p++ - '0';
if (numlines <= 0 || *p != '\0')
- errx(EX_USAGE, "%c%s: illegal line count", ch,
- optarg ? optarg : "");
+ errx(EX_USAGE, "%c%s: line count is invalid",
+ ch, optarg ? optarg : "");
break;
case 'a': /* Suffix length */
- if ((sufflen = strtol(optarg, &ep, 10)) <= 0 || *ep)
- errx(EX_USAGE,
- "%s: illegal suffix length", optarg);
- autosfx = 0;
+ sufflen = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr != NULL) {
+ errx(EX_USAGE, "%s: suffix length is %s",
+ optarg, errstr);
+ }
+ if (sufflen == 0) {
+ sufflen = 2;
+ autosfx = true;
+ } else {
+ autosfx = false;
+ }
break;
case 'b': /* Byte count. */
- errno = 0;
- error = expand_number(optarg, &bytecnt);
- if (error == -1)
- errx(EX_USAGE, "%s: offset too large", optarg);
+ if (expand_number(optarg, &bytecnt) != 0) {
+ errx(EX_USAGE, "%s: byte count is invalid",
+ optarg);
+ }
break;
case 'c': /* Continue, don't overwrite output files. */
clobber = false;
@@ -130,22 +137,27 @@ main(int argc, char **argv)
case 'l': /* Line count. */
if (numlines != 0)
usage();
- if ((numlines = strtol(optarg, &ep, 10)) <= 0 || *ep)
- errx(EX_USAGE,
- "%s: illegal line count", optarg);
+ numlines = strtonum(optarg, 1, LONG_MAX, &errstr);
+ if (errstr != NULL) {
+ errx(EX_USAGE, "%s: line count is %s",
+ optarg, errstr);
+ }
break;
case 'n': /* Chunks. */
- if (!isdigit((unsigned char)optarg[0]) ||
- (chunks = (size_t)strtoul(optarg, &ep, 10)) == 0 ||
- *ep != '\0') {
- errx(EX_USAGE, "%s: illegal number of chunks",
- optarg);
+ chunks = strtonum(optarg, 1, LONG_MAX, &errstr);
+ if (errstr != NULL) {
+ errx(EX_USAGE, "%s: number of chunks is %s",
+ optarg, errstr);
}
break;
case 'p': /* pattern matching. */
- if (regcomp(&rgx, optarg, REG_EXTENDED|REG_NOSUB) != 0)
- errx(EX_USAGE, "%s: illegal regexp", optarg);
+ error = regcomp(&rgx, optarg, REG_EXTENDED|REG_NOSUB);
+ if (error != 0) {
+ regerror(error, &rgx, errbuf, sizeof(errbuf));
+ errx(EX_USAGE, "%s: regex is invalid: %s",
+ optarg, errbuf);
+ }
pflag = 1;
break;
default:
@@ -163,9 +175,10 @@ main(int argc, char **argv)
--argc;
}
if (argc > 0) { /* File name prefix. */
- if (strlcpy(fname, *argv, sizeof(fname)) >= sizeof(fname))
- errx(EX_USAGE, "file name prefix is too long: %s",
+ if (strlcpy(fname, *argv, sizeof(fname)) >= sizeof(fname)) {
+ errx(EX_USAGE, "%s: file name prefix is too long",
*argv);
+ }
++argv;
--argc;
}
@@ -182,16 +195,16 @@ main(int argc, char **argv)
else if (bytecnt != 0 || chunks != 0)
usage();
- if (bytecnt && chunks)
+ if (bytecnt != 0 && chunks != 0)
usage();
if (ifd == -1) /* Stdin by default. */
ifd = 0;
- if (bytecnt) {
+ if (bytecnt != 0) {
split1();
exit (0);
- } else if (chunks) {
+ } else if (chunks != 0) {
split3();
exit (0);
}
@@ -225,7 +238,7 @@ split1(void)
/* NOTREACHED */
default:
if (!file_open) {
- if (!chunks || (nfiles < chunks)) {
+ if (chunks == 0 || nfiles < chunks) {
newfile();
nfiles++;
}
@@ -236,24 +249,24 @@ split1(void)
err(EX_IOERR, "write");
len -= dist;
for (C = bfr + dist; len >= bytecnt;
- len -= bytecnt, C += bytecnt) {
- if (!chunks || (nfiles < chunks)) {
- newfile();
+ len -= bytecnt, C += bytecnt) {
+ if (chunks == 0 || nfiles < chunks) {
+ newfile();
nfiles++;
}
- if (write(ofd,
- C, bytecnt) != bytecnt)
+ if (write(ofd, C, bytecnt) != bytecnt)
err(EX_IOERR, "write");
}
if (len != 0) {
- if (!chunks || (nfiles < chunks)) {
- newfile();
+ if (chunks == 0 || nfiles < chunks) {
+ newfile();
nfiles++;
}
if (write(ofd, C, len) != len)
err(EX_IOERR, "write");
- } else
+ } else {
file_open = 0;
+ }
bcnt = len;
} else {
bcnt += len;
diff --git a/usr.bin/split/tests/split_test.sh b/usr.bin/split/tests/split_test.sh
index c9b87c01618c..48065719055a 100755
--- a/usr.bin/split/tests/split_test.sh
+++ b/usr.bin/split/tests/split_test.sh
@@ -209,6 +209,23 @@ autoextend_body()
atf_check -o inline:"$((26*25+1))\n" cat xzaaa
}
+atf_test_case noautoextend
+noautoextend_body()
+{
+ seq $((26*26)) >input
+ atf_check split -a2 -l1 input
+ atf_check -o inline:"$((26*26))\n" cat xzz
+}
+
+atf_test_case reautoextend
+reautoextend_body()
+{
+ seq $((26*25+1)) >input
+ atf_check split -a2 -a0 -l1 input
+ atf_check -o inline:"$((26*25))\n" cat xyz
+ atf_check -o inline:"$((26*25+1))\n" cat xzaaa
+}
+
atf_test_case continue
continue_body()
{
@@ -249,6 +266,8 @@ atf_init_test_cases()
atf_add_test_case larger_suffix_length
atf_add_test_case pattern
atf_add_test_case autoextend
+ atf_add_test_case noautoextend
+ atf_add_test_case reautoextend
atf_add_test_case continue
atf_add_test_case undocumented_kludge
atf_add_test_case duplicate_linecount