summaryrefslogtreecommitdiffstats
path: root/bin/dd
diff options
context:
space:
mode:
authorgreen <green@FreeBSD.org>2002-01-25 17:44:47 +0000
committergreen <green@FreeBSD.org>2002-01-25 17:44:47 +0000
commitdb659d013d23ff96422e926be81a65c691e66d5d (patch)
treecbdf085e599e71955f65e013d6fd88971e36dd93 /bin/dd
parentf8c5229a8926cad7188085666cbc3854f6cd4ed6 (diff)
downloadFreeBSD-src-db659d013d23ff96422e926be81a65c691e66d5d.zip
FreeBSD-src-db659d013d23ff96422e926be81a65c691e66d5d.tar.gz
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.)
Diffstat (limited to 'bin/dd')
-rw-r--r--bin/dd/args.c163
-rw-r--r--bin/dd/dd.c2
-rw-r--r--bin/dd/extern.h3
3 files changed, 109 insertions, 59 deletions
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;
OpenPOWER on IntegriCloud