From db659d013d23ff96422e926be81a65c691e66d5d Mon Sep 17 00:00:00 2001 From: green Date: Fri, 25 Jan 2002 17:44:47 +0000 Subject: Commit general cleanups (separate get_num() and get_off_t() functions to debogosify some of the command-line string-number conversions into an unsigned and signed variant.) --- bin/dd/args.c | 163 +++++++++++++++++++++++++++++++++++++------------------- bin/dd/dd.c | 2 +- bin/dd/extern.h | 3 +- 3 files changed, 109 insertions(+), 59 deletions(-) (limited to 'bin') diff --git a/bin/dd/args.c b/bin/dd/args.c index 252f0fa..f639e77 100644 --- a/bin/dd/args.c +++ b/bin/dd/args.c @@ -67,8 +67,8 @@ static void f_obs __P((char *)); 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 u_quad_t get_num __P((const char *)); +static off_t get_off_t __P((const char *)); static const struct arg { const char *name; @@ -185,7 +185,7 @@ static void f_bs(arg) char *arg; { - quad_t res; + u_quad_t res; res = get_num(arg); if (res < 1 || res > SSIZE_MAX) @@ -197,7 +197,7 @@ static void f_cbs(arg) char *arg; { - quad_t res; + u_quad_t res; res = get_num(arg); if (res < 1 || res > SSIZE_MAX) @@ -209,12 +209,15 @@ static void f_count(arg) char *arg; { + u_quad_t res; - cpy_cnt = get_num(arg); - if (cpy_cnt < 0) + res = get_num(arg); + if ((quad_t)res < 0) errx(1, "count cannot be negative"); - if (cpy_cnt == 0) + if (res == 0) cpy_cnt = -1; + else + cpy_cnt = (quad_t)res; } static void @@ -231,7 +234,7 @@ static void f_ibs(arg) char *arg; { - quad_t res; + u_quad_t res; if (!(ddflags & C_BS)) { res = get_num(arg); @@ -253,7 +256,7 @@ static void f_obs(arg) char *arg; { - quad_t res; + u_quad_t res; if (!(ddflags & C_BS)) { res = get_num(arg); @@ -276,7 +279,7 @@ f_seek(arg) char *arg; { - out.offset = get_offset(arg); + out.offset = get_off_t(arg); } static void @@ -284,7 +287,7 @@ f_skip(arg) char *arg; { - in.offset = get_offset(arg); + in.offset = get_off_t(arg); } static const struct conv { @@ -340,78 +343,69 @@ c_conv(a, b) } /* - * Convert an expression of the following forms to a quad_t. + * Convert an expression of the following forms to a u_quad_t. * 1) A positive decimal number. - * 2) A positive decimal number followed by a b (mult by 512.) - * 3) A positive decimal number followed by a k (mult by 1 << 10.) - * 4) A positive decimal number followed by a m (mult by 1 << 20.) - * 5) A positive decimal number followed by a g (mult by 1 << 30.) - * 5) A positive decimal number followed by a w (mult by sizeof int.) + * 2) A positive decimal number followed by a b (mult by 512). + * 3) A positive decimal number followed by a k (mult by 1 << 10). + * 4) A positive decimal number followed by a m (mult by 1 << 20). + * 5) A positive decimal number followed by a g (mult by 1 << 30). + * 5) A positive decimal number followed by a w (mult by sizeof int). * 6) Two or more positive decimal numbers (with/without [bkmgw]) * separated by x (also * for backwards compatibility), specifying * the product of the indicated values. */ -static quad_t +static u_quad_t get_num(val) - char *val; + const char *val; { - quad_t num, t; + u_quad_t num, mult, prevnum; char *expr; errno = 0; - num = strtoq(val, &expr, 0); + num = strtouq(val, &expr, 0); if (errno != 0) /* Overflow or underflow. */ err(1, "%s", oper); if (expr == val) /* No valid digits. */ errx(1, "%s: illegal numeric value", oper); + mult = 0; switch (*expr) { case 'b': - t = num; - num *= 512; - if (t > num) - goto erange; - ++expr; + mult = 512; break; case 'k': - t = num; - num *= 1 << 10; - if (t > num) - goto erange; - ++expr; + mult = 1 << 10; break; case 'm': - t = num; - num *= 1 << 20; - if (t > num) - goto erange; - ++expr; + mult = 1 << 20; break; case 'g': - t = num; - num *= 1 << 30; - if (t > num) - goto erange; - ++expr; + mult = 1 << 30; break; case 'w': - t = num; - num *= sizeof(int); - if (t > num) - goto erange; - ++expr; + mult = sizeof(int); break; } + if (mult != 0) { + prevnum = num; + num *= mult; + /* Check for overflow. */ + if (num / mult != prevnum) + goto erange; + expr++; + } + switch (*expr) { case '\0': break; case '*': /* Backward compatible. */ case 'x': - t = num; - num *= get_num(expr + 1); - if (t <= num) + mult = get_num(expr + 1); + prevnum = num; + num *= mult; + if (num / mult == prevnum) break; erange: errx(1, "%s: %s", oper, strerror(ERANGE)); @@ -421,14 +415,71 @@ erange: return (num); } +/* + * Convert an expression of the following forms to an off_t. This is the + * same as get_num(), but it uses signed numbers. + * + * The major problem here is that an off_t may not necessarily be a quad_t. + * The right thing to do would be to use intmax_t when available and then + * cast down to an off_t, if possible. + */ static off_t -get_offset(val) - char *val; +get_off_t(val) + const char *val; { - quad_t num; + quad_t num, mult, prevnum; + char *expr; + + errno = 0; + num = strtoq(val, &expr, 0); + if (errno != 0) /* Overflow or underflow. */ + err(1, "%s", oper); + + if (expr == val) /* No valid digits. */ + errx(1, "%s: illegal numeric value", oper); + + mult = 0; + switch (*expr) { + case 'b': + mult = 512; + break; + case 'k': + mult = 1 << 10; + break; + case 'm': + mult = 1 << 20; + break; + case 'g': + mult = 1 << 30; + break; + case 'w': + mult = sizeof(int); + break; + } + + if (mult != 0) { + prevnum = num; + num *= mult; + /* Check for overflow. */ + if ((prevnum > 0) != (num > 0) || num / mult != prevnum) + goto erange; + expr++; + } - num = get_num(val); - if (num > QUAD_MAX) /* XXX can't happen && quad_t != off_t */ - errx(1, "%s: illegal offset", oper); /* Too big. */ - return ((off_t)num); + switch (*expr) { + case '\0': + break; + case '*': /* Backward compatible. */ + case 'x': + mult = (quad_t)get_off_t(expr + 1); + prevnum = num; + num *= mult; + if ((prevnum > 0) != (num > 0) && num / mult == prevnum) + break; +erange: + errx(1, "%s: %s", oper, strerror(ERANGE)); + default: + errx(1, "%s: illegal numeric value", oper); + } + return (num); } diff --git a/bin/dd/dd.c b/bin/dd/dd.c index 04f9573..35d3d37 100644 --- a/bin/dd/dd.c +++ b/bin/dd/dd.c @@ -78,7 +78,7 @@ static void setup __P((void)); IO in, out; /* input/output state */ STAT st; /* statistics */ void (*cfunc) __P((void)); /* conversion function */ -quad_t cpy_cnt; /* # of blocks to copy */ +u_quad_t cpy_cnt; /* # of blocks to copy */ off_t pending = 0; /* pending seek if sparse */ u_int ddflags; /* conversion options */ size_t cbsz; /* conversion block size */ diff --git a/bin/dd/extern.h b/bin/dd/extern.h index bdfeeb7..7f01b8b 100644 --- a/bin/dd/extern.h +++ b/bin/dd/extern.h @@ -53,12 +53,11 @@ void summaryx __P((int)); void terminate __P((int)); void unblock __P((void)); void unblock_close __P((void)); -void bitswab __P((void *, size_t)); extern IO in, out; extern STAT st; extern void (*cfunc) __P((void)); -extern quad_t cpy_cnt; +extern u_quad_t cpy_cnt; extern size_t cbsz; extern u_int ddflags; extern quad_t files_cnt; -- cgit v1.1