From owner-freebsd-bugs Mon May 4 05:12:35 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id FAA15983 for freebsd-bugs-outgoing; Mon, 4 May 1998 05:12:35 -0700 (PDT) (envelope-from owner-freebsd-bugs@FreeBSD.ORG) Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id FAA15960 for ; Mon, 4 May 1998 05:12:27 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.8.8/8.8.5) id FAA29722; Mon, 4 May 1998 05:10:02 -0700 (PDT) Received: from chen.ml.org (luoqi.watermarkgroup.com [207.202.73.170]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id FAA15412 for ; Mon, 4 May 1998 05:10:22 -0700 (PDT) (envelope-from luoqi@chen.ml.org) Received: (from luoqi@localhost) by chen.ml.org (8.8.8/8.8.8) id IAA06341; Mon, 4 May 1998 08:10:21 -0400 (EDT) (envelope-from luoqi) Message-Id: <199805041210.IAA06341@chen.ml.org> Date: Mon, 4 May 1998 08:10:21 -0400 (EDT) From: Luoqi Chen Reply-To: luoqi@chen.ml.org To: FreeBSD-gnats-submit@FreeBSD.ORG X-Send-Pr-Version: 3.2 Subject: bin/6509: 64bit offset support in dd Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >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