diff options
author | green <green@FreeBSD.org> | 1999-09-12 16:51:53 +0000 |
---|---|---|
committer | green <green@FreeBSD.org> | 1999-09-12 16:51:53 +0000 |
commit | 4c16a85a3ff03636818f24c79ff2bc5947df9263 (patch) | |
tree | 27ec4fb5de7c3368adcff8f419831e3fad5929a9 /bin/dd/args.c | |
parent | 24f1ee63f7883c5a3b659be2be4b666369e6142d (diff) | |
download | FreeBSD-src-4c16a85a3ff03636818f24c79ff2bc5947df9263.zip FreeBSD-src-4c16a85a3ff03636818f24c79ff2bc5947df9263.tar.gz |
Even more cleanups to dd(1). This is probably the culmination of the
BDEification process of dd(1). Most of the changes are from BDE's archive.
Support for negative offsets is gone again, but the case where you
lseek() onto byte -1 of something from a negative offset using seek/skip
is fixed; if you end up on -1, you won't get a false positive lseek failure.
The biggest changes are to data types (more size_t, for instance) and
argument parsing. skip/seek on /dev/{,k}mem now occurs (instead of "read
until you reach the offset") due to mem devices now being D_DISK. Some
const things are now correctly declared as such, and the "case table"
building is better. The only thing that seems to be left to make dd(1)
everything TOG wants it to be is l10n.
Diffstat (limited to 'bin/dd/args.c')
-rw-r--r-- | bin/dd/args.c | 76 |
1 files changed, 46 insertions, 30 deletions
diff --git a/bin/dd/args.c b/bin/dd/args.c index 08555c1..606da90 100644 --- a/bin/dd/args.c +++ b/bin/dd/args.c @@ -68,8 +68,9 @@ static void f_of __P((char *)); static void f_seek __P((char *)); static void f_skip __P((char *)); static quad_t get_num __P((char *)); +static off_t get_offset __P((char *)); -static struct arg { +static const struct arg { char *name; void (*f) __P((char *)); u_int set, noset; @@ -160,6 +161,11 @@ jcl(argv) errx(1, "cbs meaningless if not doing record operations"); } else cfunc = def; + /* + * Bail out if the calculation of a file offset would overflow. + */ + if (in.offset > QUAD_MAX / in.dbsz || out.offset > QUAD_MAX / out.dbsz) + errx(1, "seek offsets cannot be larger than %qd", QUAD_MAX); } static int @@ -174,22 +180,24 @@ static void f_bs(arg) char *arg; { - quad_t res = get_num(arg); + quad_t res; - if (res < 1 || res > INT_MAX) - errx(1, "bs must be between 1 and %d", INT_MAX); - in.dbsz = out.dbsz = (int)res; + res = get_num(arg); + if (res < 1 || res > SSIZE_MAX) + errx(1, "bs must be between 1 and %d", SSIZE_MAX); + in.dbsz = out.dbsz = (size_t)res; } static void f_cbs(arg) char *arg; { - quad_t res = get_num(arg); + quad_t res; - if (res < 1 || res > INT_MAX) - errx(1, "cbs must be between 1 and %d", INT_MAX); - cbsz = (int)res; + res = get_num(arg); + if (res < 1 || res > SSIZE_MAX) + errx(1, "cbs must be between 1 and %d", SSIZE_MAX); + cbsz = (size_t)res; } static void @@ -201,8 +209,6 @@ f_count(arg) if (!cpy_cnt) terminate(0); - if (cpy_cnt < 0) - errx(1, "count cannot be negative"); } static void @@ -211,19 +217,17 @@ f_files(arg) { files_cnt = get_num(arg); - if (files_cnt < 0) - errx(1, "files cannot be negative"); } static void f_ibs(arg) char *arg; { + quad_t res; if (!(ddflags & C_BS)) { - quad_t res = get_num(arg); - - if (res < 1 || res > INT_MAX) + res = get_num(arg); + if (res < 1 || res > SSIZE_MAX) errx(1, "ibs must be between 1 and %d", INT_MAX); in.dbsz = (int)res; } @@ -241,13 +245,13 @@ static void f_obs(arg) char *arg; { + quad_t res; if (!(ddflags & C_BS)) { - quad_t res = get_num(arg); - - if (res < 1 || res > INT_MAX) - errx(1, "ibs must be between 1 and %d", INT_MAX); - out.dbsz = (int)res; + res = get_num(arg); + if (res < 1 || res > SSIZE_MAX) + errx(1, "obs must be between 1 and %d", SSIZE_MAX); + out.dbsz = (size_t)res; } } @@ -264,7 +268,7 @@ f_seek(arg) char *arg; { - out.offset = get_num(arg); + out.offset = get_offset(arg); } static void @@ -272,13 +276,13 @@ f_skip(arg) char *arg; { - in.offset = get_num(arg); + in.offset = get_offset(arg); } -static struct conv { +static const struct conv { char *name; u_int set, noset; - u_char *ctab; + const u_char *ctab; } clist[] = { { "ascii", C_ASCII, C_EBCDIC, e2a_POSIX }, { "block", C_BLOCK, C_UNBLOCK, NULL }, @@ -306,9 +310,9 @@ f_conv(arg) while (arg != NULL) { tmp.name = strsep(&arg, ","); - if (!(cp = (struct conv *)bsearch(&tmp, clist, - sizeof(clist)/sizeof(struct conv), sizeof(struct conv), - c_conv))) + cp = bsearch(&tmp, clist, sizeof(clist) / sizeof(struct conv), + sizeof(struct conv), c_conv); + if (cp == NULL) errx(1, "unknown conversion %s", tmp.name); if (ddflags & cp->noset) errx(1, "%s: illegal conversion combination", tmp.name); @@ -347,10 +351,10 @@ get_num(val) errno = 0; num = strtoq(val, &expr, 0); - if (errno) /* Overflow or underflow. */ + if (errno != 0) /* Overflow or underflow. */ err(1, "%s", oper); - if (expr == val) /* Not a valid number */ + if (expr == val) /* No valid digits. */ errx(1, "%s: illegal numeric value", oper); switch (*expr) { @@ -407,3 +411,15 @@ erange: } return (num); } + +static off_t +get_offset(val) + char *val; +{ + quad_t num; + + num = get_num(val); + if (num > QUAD_MAX || num < 0) /* XXX quad_t != off_t */ + errx(1, "%s: illegal offset", oper); /* Too big/negative. */ + return ((off_t)num); +} |