Date: Mon, 4 May 1998 08:10:21 -0400 (EDT) From: Luoqi Chen <luoqi@chen.ml.org> To: FreeBSD-gnats-submit@FreeBSD.ORG Subject: bin/6509: 64bit offset support in dd Message-ID: <199805041210.IAA06341@chen.ml.org>
next in thread | raw e-mail | index | archive | help
>Number: 6509
>Category: bin
>Synopsis: Allow dd to seek/skip to offset beyond the 2G limit
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Mon May 4 05:10:01 PDT 1998
>Last-Modified:
>Originator: Luoqi Chen
>Organization:
>Release: FreeBSD 3.0-CURRENT i386
>Environment:
>Description:
Currently dd doesn't allow offset to be greater than INT_MAX
(2G for i386). This means on disks larger than 2G (which by the
way are true for almost all new disks sold nowadays) a substantial
portaion of the disk blocks are unreachable through dd. This patch
raises the limit to QUAD_MAX (2^63).
>How-To-Repeat:
>Fix:
Index: args.c
===================================================================
RCS file: /fun/cvs/src/bin/dd/args.c,v
retrieving revision 1.11
diff -u -r1.11 args.c
--- args.c 1997/11/11 20:35:29 1.11
+++ args.c 1998/05/04 11:55:58
@@ -67,6 +67,7 @@
static void f_seek __P((char *));
static void f_skip __P((char *));
static u_long get_bsz __P((char *));
+static u_int64_t get_bsz64 __P((char *));
static struct arg {
char *name;
@@ -165,15 +166,10 @@
if (in.dbsz == 0 || out.dbsz == 0)
errx(1, "buffer sizes cannot be zero");
- /*
- * Read, write and seek calls take ints as arguments. Seek sizes
- * could be larger if we wanted to do it in stages or check only
- * regular files, but it's probably not worth it.
- */
if (in.dbsz > INT_MAX || out.dbsz > INT_MAX)
errx(1, "buffer sizes cannot be greater than %d", INT_MAX);
- if (in.offset > INT_MAX / in.dbsz || out.offset > INT_MAX / out.dbsz)
- errx(1, "seek offsets cannot be larger than %d", INT_MAX);
+ if (in.offset > QUAD_MAX / in.dbsz || out.offset > QUAD_MAX / out.dbsz)
+ errx(1, "seek offsets cannot be larger than %d", QUAD_MAX);
}
static int
@@ -257,7 +253,7 @@
char *arg;
{
- out.offset = (u_int)get_bsz(arg);
+ out.offset = (u_int64_t)get_bsz64(arg);
}
static void
@@ -265,7 +261,7 @@
char *arg;
{
- in.offset = (u_int)get_bsz(arg);
+ in.offset = (u_int64_t)get_bsz64(arg);
}
static struct conv {
@@ -324,9 +320,9 @@
* 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 1024).
- * 4) A positive decimal number followed by a m (mult by 512).
+ * 4) A positive decimal number followed by a m (mult by 1048576).
* 5) A positive decimal number followed by a w (mult by sizeof int)
- * 6) Two or more positive decimal numbers (with/without k,b or w).
+ * 6) Two or more positive decimal numbers (with/without k,b,m or w).
* seperated by x (also * for backwards compatibility), specifying
* the product of the indicated values.
*/
@@ -381,6 +377,85 @@
case 'x':
t = num;
num *= get_bsz(expr + 1);
+ if (t > num)
+erange: errx(1, "%s: %s", oper, strerror(ERANGE));
+ break;
+ default:
+ errx(1, "%s: illegal numeric value", oper);
+ }
+ return (num);
+}
+
+/*
+ * Convert an expression of the following forms to a 64bit unsigned int.
+ * 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 1024).
+ * 4) A positive decimal number followed by a m (mult by 1048576).
+ * 5) A positive decimal number followed by a g (mult by 1073741824).
+ * 6) A positive decimal number followed by a w (mult by sizeof int)
+ * 7) Two or more positive decimal numbers (with/without k,b,m,g or w).
+ * seperated by x (also * for backwards compatibility), specifying
+ * the product of the indicated values.
+ */
+static u_int64_t
+get_bsz64(val)
+ char *val;
+{
+ u_int64_t num, t;
+ char *expr;
+
+ num = strtouq(val, &expr, 0);
+ if (num == UQUAD_MAX) /* Overflow. */
+ err(1, "%s", oper);
+ if (expr == val) /* No digits. */
+ errx(1, "%s: illegal numeric value", oper);
+
+ switch(*expr) {
+ case 'b':
+ t = num;
+ num *= 512;
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'k':
+ t = num;
+ num *= 1024;
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'm':
+ t = num;
+ num *= 1048576;
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'g':
+ t = num;
+ num *= 1073741824;
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'w':
+ t = num;
+ num *= sizeof(int);
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ }
+
+ switch(*expr) {
+ case '\0':
+ break;
+ case '*': /* Backward compatible. */
+ case 'x':
+ t = num;
+ num *= get_bsz64(expr + 1);
if (t > num)
erange: errx(1, "%s: %s", oper, strerror(ERANGE));
break;
Index: dd.h
===================================================================
RCS file: /fun/cvs/src/bin/dd/dd.h,v
retrieving revision 1.8
diff -u -r1.8 dd.h
--- dd.h 1998/02/11 02:23:31 1.8
+++ dd.h 1998/05/04 10:05:29
@@ -54,7 +54,7 @@
char *name; /* name */
int fd; /* file descriptor */
- u_long offset; /* # of blocks to skip */
+ u_int64_t offset; /* # of blocks to skip */
u_long f_stats; /* # of full blocks processed */
u_long p_stats; /* # of partial blocks processed */
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199805041210.IAA06341>
