- Use u_longlong_t instead of u_quad_t, u_long, or int for various buffer sizes

- Add strsuftoull(), which parses a number into a u_longlong_t, with
  multiplication support, and support for 'g' (GB) and 't' (TB) suffices.
  If an error occurs, print to stderr and exit.
  Based on get_blk() from args.c and strsufto*() (in other programs)
- Add strsuftoullx(), which acts as per strsuftoull() but returns the
  error in the supplied buffer instead (if the returned buffer != "", an
  error occurred)
- Replace get_bsz() use with strsuftoull()
- Remove (now) unnecessary argument validation
- Remove unused {f,p,s,t}_stats fields in struct IO
This commit is contained in:
lukem 2001-11-25 10:50:06 +00:00
parent d271a36466
commit b6ce735c04
10 changed files with 346 additions and 177 deletions

View File

@ -1,8 +1,8 @@
# $NetBSD: Makefile,v 1.7 2001/11/25 06:53:48 lukem Exp $
# $NetBSD: Makefile,v 1.8 2001/11/25 10:50:06 lukem Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= dd
SRCS= args.c conv.c conv_tab.c dd.c misc.c position.c
SRCS= args.c conv.c conv_tab.c dd.c misc.c position.c strsuftoull.c
WARNS=2

View File

@ -1,4 +1,4 @@
/* $NetBSD: args.c,v 1.18 2001/11/25 06:57:55 lukem Exp $ */
/* $NetBSD: args.c,v 1.19 2001/11/25 10:50:06 lukem Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)args.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: args.c,v 1.18 2001/11/25 06:57:55 lukem Exp $");
__RCSID("$NetBSD: args.c,v 1.19 2001/11/25 10:50:06 lukem Exp $");
#endif
#endif /* not lint */
@ -58,6 +58,7 @@ __RCSID("$NetBSD: args.c,v 1.18 2001/11/25 06:57:55 lukem Exp $");
#include "dd.h"
#include "extern.h"
#include "strsuftoull.h"
static int c_arg(const void *, const void *);
#ifndef NO_CONV
@ -75,7 +76,6 @@ static void f_of(char *);
static void f_seek(char *);
static void f_skip(char *);
static void f_progress(char *);
static u_long get_bsz(const char *);
static const struct arg {
const char *name;
@ -98,8 +98,6 @@ static const struct arg {
{ "skip", f_skip, C_SKIP, C_SKIP },
};
static char *oper;
/*
* args -- parse JCL syntax of dd.
*/
@ -107,7 +105,7 @@ void
jcl(char **argv)
{
struct arg *ap, tmp;
char *arg;
char *oper, *arg;
in.dbsz = out.dbsz = 512;
@ -153,8 +151,6 @@ jcl(char **argv)
if (ddflags & (C_BLOCK|C_UNBLOCK)) {
if (!(ddflags & C_CBS))
errx(1, "record operations require cbs");
if (cbsz == 0)
errx(1, "cbs cannot be zero");
cfunc = ddflags & C_BLOCK ? block : unblock;
} else if (ddflags & C_CBS) {
if (ddflags & (C_ASCII|C_EBCDIC)) {
@ -168,20 +164,9 @@ jcl(char **argv)
} else
errx(1,
"cbs meaningless if not doing record operations");
if (cbsz == 0)
errx(1, "cbs cannot be zero");
} else
cfunc = def;
if (in.dbsz == 0 || out.dbsz == 0)
errx(1, "buffer sizes cannot be zero");
/*
* Check to make sure that the buffers are not too large.
*/
if (in.dbsz > INT_MAX || out.dbsz > INT_MAX)
errx(1, "buffer sizes cannot be greater than %d", INT_MAX);
/* Read, write and seek calls take off_t as arguments.
*
* The following check is not done because an off_t is a quad
@ -204,21 +189,21 @@ static void
f_bs(char *arg)
{
in.dbsz = out.dbsz = (int)get_bsz(arg);
in.dbsz = out.dbsz = strsuftoull("block size", arg, 1, UINT_MAX);
}
static void
f_cbs(char *arg)
{
cbsz = (int)get_bsz(arg);
cbsz = strsuftoull("conversion record size", arg, 1, UINT_MAX);
}
static void
f_count(char *arg)
{
cpy_cnt = (u_int)get_bsz(arg);
cpy_cnt = strsuftoull("block count", arg, 0, ULLONG_MAX);
if (!cpy_cnt)
terminate(0);
}
@ -227,7 +212,9 @@ static void
f_files(char *arg)
{
files_cnt = (int)get_bsz(arg);
files_cnt = (u_int)strsuftoull("file count", arg, 0, UINT_MAX);
if (!files_cnt)
terminate(0);
}
static void
@ -235,7 +222,7 @@ f_ibs(char *arg)
{
if (!(ddflags & C_BS))
in.dbsz = (int)get_bsz(arg);
in.dbsz = strsuftoull("input block size", arg, 1, UINT_MAX);
}
static void
@ -250,7 +237,7 @@ f_obs(char *arg)
{
if (!(ddflags & C_BS))
out.dbsz = (int)get_bsz(arg);
out.dbsz = strsuftoull("output block size", arg, 1, UINT_MAX);
}
static void
@ -264,14 +251,14 @@ static void
f_seek(char *arg)
{
out.offset = (u_int)get_bsz(arg);
out.offset = strsuftoull("seek blocks", arg, 0, ULLONG_MAX);
}
static void
f_skip(char *arg)
{
in.offset = (u_int)get_bsz(arg);
in.offset = strsuftoull("skip blocks", arg, 0, ULLONG_MAX);
}
static void
@ -342,73 +329,3 @@ c_conv(const void *a, const void *b)
}
#endif /* NO_CONV */
/*
* Convert an expression of the following forms to an unsigned long.
* 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 w (mult by sizeof int)
* 6) Two or more positive decimal numbers (with/without k,b or w).
* separated by x (also * for backwards compatibility), specifying
* the product of the indicated values.
*/
static u_long
get_bsz(const char *val)
{
u_long num, t;
char *expr;
num = strtoul(val, &expr, 0);
if (num == ULONG_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 '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_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);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: conv.c,v 1.12 2001/11/25 06:53:48 lukem Exp $ */
/* $NetBSD: conv.c,v 1.13 2001/11/25 10:50:06 lukem Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: conv.c,v 1.12 2001/11/25 06:53:48 lukem Exp $");
__RCSID("$NetBSD: conv.c,v 1.13 2001/11/25 10:50:06 lukem Exp $");
#endif
#endif /* not lint */
@ -64,7 +64,7 @@ __RCSID("$NetBSD: conv.c,v 1.12 2001/11/25 06:53:48 lukem Exp $");
void
def(void)
{
int cnt;
u_longlong_t cnt;
u_char *inp;
const u_char *t;
@ -121,7 +121,7 @@ block(void)
{
static int intrunc;
int ch = 0; /* pacify gcc */
int cnt, maxlen;
u_longlong_t cnt, maxlen;
u_char *inp, *outp;
const u_char *t;
@ -232,7 +232,7 @@ block_close(void)
void
unblock(void)
{
int cnt;
u_longlong_t cnt;
u_char *inp;
const u_char *t;
@ -266,7 +266,7 @@ unblock(void)
void
unblock_close(void)
{
int cnt;
u_longlong_t cnt;
u_char *t;
if (in.dbcnt) {

View File

@ -1,4 +1,4 @@
.\" $NetBSD: dd.1,v 1.10 2000/09/04 07:30:08 kleink Exp $
.\" $NetBSD: dd.1,v 1.11 2001/11/25 10:50:06 lukem Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -36,7 +36,7 @@
.\"
.\" @(#)dd.1 8.2 (Berkeley) 1/13/94
.\"
.Dd July 28, 1999
.Dd November 25, 2001
.Dt DD 1
.Os
.Sh NAME
@ -140,8 +140,11 @@ distinguishing between a partial or complete block being read.
.It Cm progress= Ns Ar n
Switch on display of progress if
.Va n
is set to ``1'', i.e. a ``.'' is printed for each
block written to the output file.
is set to
.Dq 1 ,
i.e. a
.Dq \&.
is printed for each block written to the output file.
.It Xo
.Cm conv=
.Ns Cm value Ns Op \&, Cm value \&...
@ -285,10 +288,24 @@ appended.
.El
.Pp
Where sizes are specified, a decimal number of bytes is expected.
If the number ends with a ``b'', ``k'', ``m'' or ``w'', the number
is multiplied by 512, 1024 (1K), 1048576 (1M) or the number of bytes
in an integer, respectively.
Two or more numbers may be separated by an ``x'' to indicate a product.
Two or more numbers may be separated by an
.Dq x
to indicate a product.
Each number may have one of the following optional suffices:
.Bl -tag -width 3n -offset indent -compact
.It b
Block; multiply by 512
.It k
Kilo; multiply by 1024 (1 KB)
.It m
Mega; multiply by 1048576 (1 MB)
.It g
Giga; multiply by 1073741824 (1 GB)
.It t
Tera; multiply by 1099511627776 (1 TB)
.It w
Word; multiply by the number of bytes in an integer
.El
.Pp
When finished,
.Nm
@ -317,9 +334,12 @@ If
.Nm
receives a
.Dv SIGINFO
(see the ``status'' argument for
.Xr stty 1 )
signal, the current input and output block counts will
signal
(see the
.Ic status
argument for
.Xr stty 1 ) ,
the current input and output block counts will
be written to the standard error output
in the same format as the standard completion message.
If

View File

@ -1,4 +1,4 @@
/* $NetBSD: dd.c,v 1.22 2001/11/25 06:57:55 lukem Exp $ */
/* $NetBSD: dd.c,v 1.23 2001/11/25 10:50:06 lukem Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -47,7 +47,7 @@ __COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\n\
#if 0
static char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: dd.c,v 1.22 2001/11/25 06:57:55 lukem Exp $");
__RCSID("$NetBSD: dd.c,v 1.23 2001/11/25 10:50:06 lukem Exp $");
#endif
#endif /* not lint */
@ -77,16 +77,16 @@ static void setup(void);
int main(int, char *[]);
IO in, out; /* input/output state */
STAT st; /* statistics */
void (*cfunc)(void); /* conversion function */
u_long cpy_cnt; /* # of blocks to copy */
u_int ddflags; /* conversion options */
u_int cbsz; /* conversion block size */
u_int files_cnt = 1; /* # of files to copy */
int progress = 0; /* display sign of life */
const u_char *ctab; /* conversion table */
sigset_t infoset; /* a set blocking SIGINFO */
IO in, out; /* input/output state */
STAT st; /* statistics */
void (*cfunc)(void); /* conversion function */
u_longlong_t cpy_cnt; /* # of blocks to copy */
u_int ddflags; /* conversion options */
u_longlong_t cbsz; /* conversion block size */
u_int files_cnt = 1; /* # of files to copy */
int progress = 0; /* display sign of life */
const u_char *ctab; /* conversion table */
sigset_t infoset; /* a set blocking SIGINFO */
int
main(int argc, char *argv[])
@ -243,7 +243,8 @@ getfdtype(IO *io)
static void
dd_in(void)
{
int flags, n;
int flags;
u_longlong_t n;
for (flags = ddflags;;) {
if (cpy_cnt && (st.in_full + st.in_part) >= cpy_cnt)
@ -364,7 +365,7 @@ void
dd_out(int force)
{
static int warned;
int cnt, n, nw;
u_longlong_t cnt, n, nw;
u_char *outp;
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: dd.h,v 1.7 2001/11/25 06:53:48 lukem Exp $ */
/* $NetBSD: dd.h,v 1.8 2001/11/25 10:50:06 lukem Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -41,37 +41,32 @@
/* Input/output stream state. */
typedef struct {
u_char *db; /* buffer address */
u_char *dbp; /* current buffer I/O address */
u_long dbcnt; /* current buffer byte count */
int dbrcnt; /* last read byte count */
u_long dbsz; /* buffer size */
u_char *db; /* buffer address */
u_char *dbp; /* current buffer I/O address */
u_longlong_t dbcnt; /* current buffer byte count */
u_longlong_t dbrcnt; /* last read byte count */
u_longlong_t dbsz; /* buffer size */
#define ISCHR 0x01 /* character device (warn on short) */
#define ISPIPE 0x02 /* pipe (not truncatable) */
#define ISTAPE 0x04 /* tape (not seekable) */
#define NOREAD 0x08 /* not readable */
u_int flags;
u_int flags;
const char *name; /* name */
int fd; /* file descriptor */
u_long offset; /* # of blocks to skip */
u_long f_stats; /* # of full blocks processed */
u_long p_stats; /* # of partial blocks processed */
u_long s_stats; /* # of odd swab blocks */
u_long t_stats; /* # of truncations */
const char *name; /* name */
int fd; /* file descriptor */
u_longlong_t offset; /* # of blocks to skip */
} IO;
typedef struct {
u_long in_full; /* # of full input blocks */
u_long in_part; /* # of partial input blocks */
u_long out_full; /* # of full output blocks */
u_long out_part; /* # of partial output blocks */
u_long trunc; /* # of truncated records */
u_long swab; /* # of odd-length swab blocks */
u_quad_t bytes; /* # of bytes written */
struct timeval start; /* start time of dd */
u_longlong_t in_full; /* # of full input blocks */
u_longlong_t in_part; /* # of partial input blocks */
u_longlong_t out_full; /* # of full output blocks */
u_longlong_t out_part; /* # of partial output blocks */
u_longlong_t trunc; /* # of truncated records */
u_longlong_t swab; /* # of odd-length swab blocks */
u_longlong_t bytes; /* # of bytes written */
struct timeval start; /* start time of dd */
} STAT;
/* Flags (in ddflags). */

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.11 2001/11/25 06:53:48 lukem Exp $ */
/* $NetBSD: extern.h,v 1.12 2001/11/25 10:50:06 lukem Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -56,16 +56,16 @@ void unblock(void);
void unblock_close(void);
ssize_t bwrite(int, const void *, size_t);
extern IO in, out;
extern STAT st;
extern void (*cfunc)(void);
extern u_long cpy_cnt;
extern u_int cbsz;
extern u_int ddflags;
extern u_int files_cnt;
extern int progress;
extern const u_char *ctab;
extern const u_char a2e_32V[], a2e_POSIX[];
extern const u_char e2a_32V[], e2a_POSIX[];
extern const u_char a2ibm_32V[], a2ibm_POSIX[];
extern u_char casetab[];
extern IO in, out;
extern STAT st;
extern void (*cfunc)(void);
extern u_longlong_t cpy_cnt;
extern u_longlong_t cbsz;
extern u_int ddflags;
extern u_int files_cnt;
extern int progress;
extern const u_char *ctab;
extern const u_char a2e_32V[], a2e_POSIX[];
extern const u_char e2a_32V[], e2a_POSIX[];
extern const u_char a2ibm_32V[], a2ibm_POSIX[];
extern u_char casetab[];

View File

@ -1,4 +1,4 @@
/* $NetBSD: misc.c,v 1.12 2001/11/25 06:53:48 lukem Exp $ */
/* $NetBSD: misc.c,v 1.13 2001/11/25 10:50:06 lukem Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -42,7 +42,7 @@
#if 0
static char sccsid[] = "@(#)misc.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: misc.c,v 1.12 2001/11/25 06:53:48 lukem Exp $");
__RCSID("$NetBSD: misc.c,v 1.13 2001/11/25 10:50:06 lukem Exp $");
#endif
#endif /* not lint */
@ -77,25 +77,28 @@ summary(void)
mS = 1;
/* Use snprintf(3) so that we don't reenter stdio(3). */
(void)snprintf(buf, sizeof(buf),
"%lu+%lu records in\n%lu+%lu records out\n",
st.in_full, st.in_part, st.out_full, st.out_part);
"%llu+%llu records in\n%llu+%llu records out\n",
(unsigned long long)st.in_full, (unsigned long long)st.in_part,
(unsigned long long)st.out_full, (unsigned long long)st.out_part);
(void)write(STDERR_FILENO, buf, strlen(buf));
if (st.swab) {
(void)snprintf(buf, sizeof(buf), "%lu odd length swab %s\n",
st.swab, (st.swab == 1) ? "block" : "blocks");
(void)snprintf(buf, sizeof(buf), "%llu odd length swab %s\n",
(unsigned long long)st.swab,
(st.swab == 1) ? "block" : "blocks");
(void)write(STDERR_FILENO, buf, strlen(buf));
}
if (st.trunc) {
(void)snprintf(buf, sizeof(buf), "%lu truncated %s\n",
st.trunc, (st.trunc == 1) ? "block" : "blocks");
(void)snprintf(buf, sizeof(buf), "%llu truncated %s\n",
(unsigned long long)st.trunc,
(st.trunc == 1) ? "block" : "blocks");
(void)write(STDERR_FILENO, buf, strlen(buf));
}
(void)snprintf(buf, sizeof(buf),
"%llu bytes transferred in %lu.%03d secs (%llu bytes/sec)\n",
(long long) st.bytes,
(unsigned long long) st.bytes,
(long) (mS / 1000),
(int) (mS % 1000),
(long long unsigned) (st.bytes * 1000LL / mS));
(unsigned long long) (st.bytes * 1000LL / mS));
(void)write(STDERR_FILENO, buf, strlen(buf));
}

226
bin/dd/strsuftoull.c Normal file
View File

@ -0,0 +1,226 @@
/* $NetBSD: strsuftoull.c,v 1.1 2001/11/25 10:50:06 lukem Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Keith Muller of the University of California, San Diego and Lance
* Visser of Convex Computer Corporation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Luke Mewburn.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: strsuftoull.c,v 1.1 2001/11/25 10:50:06 lukem Exp $");
#endif /* not lint */
#include <sys/types.h>
#include <sys/time.h>
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "strsuftoull.h"
/*
* Convert an expression of the following forms to a u_longlong_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 1024).
* 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).
* separated by x (also * for backwards compatibility), specifying
* the product of the indicated values.
* Returns the result upon successful conversion, or exits with an
* appropriate error.
*
*/
u_longlong_t
strsuftoull(const char *desc, const char *val,
u_longlong_t min, u_longlong_t max)
{
u_longlong_t result;
char errbuf[100];
result = strsuftoullx(desc, val, min, max, errbuf, sizeof(errbuf));
if (*errbuf != '\0')
errx(1, "%s", errbuf);
return (result);
}
/*
* As strsuftoull(), but returns the error message into the provided buffer
* rather than exiting with it.
*/
u_longlong_t
strsuftoullx(const char *desc, const char *val,
u_longlong_t min, u_longlong_t max, char *ebuf, size_t ebuflen)
{
u_longlong_t num, t;
char *expr;
assert(desc != NULL);
assert(val != NULL);
assert(ebuf != NULL);
errno = 0;
if (*val == '-') /* Prevent negative numbers */
goto badnum;
num = strtoull(val, &expr, 0);
if (num == LLONG_MAX && errno == ERANGE)
goto erange; /* Overflow */
if (expr == val) /* No digits */
goto badnum;
switch (*expr) {
case 'b':
t = num;
num *= 512; /* 1 block */
if (t > num)
goto erange;
++expr;
break;
case 'k':
t = num;
num *= 1024; /* 1 kilobyte */
if (t > num)
goto erange;
++expr;
break;
case 'm':
t = num;
num *= 1048576; /* 1 megabyte */
if (t > num)
goto erange;
++expr;
break;
case 'g':
t = num;
num *= 1073741824; /* 1 gigabyte */
if (t > num)
goto erange;
++expr;
break;
case 't':
t = num;
num *= 1099511627776; /* 1 terabyte */
if (t > num)
goto erange;
++expr;
break;
case 'w':
t = num;
num *= sizeof(int); /* 1 word */
if (t > num)
goto erange;
++expr;
break;
}
switch (*expr) {
case '\0':
break;
case '*': /* Backward compatible */
case 'x':
t = num;
num *= strsuftoullx(desc, expr + 1, min, max, ebuf, ebuflen);
if (*ebuf != '\0')
return (0);
if (t > num) {
erange:
snprintf(ebuf, ebuflen,
"%s: %s", desc, strerror(ERANGE));
return (0);
}
break;
default:
badnum: snprintf(ebuf, ebuflen,
"%s `%s': illegal positive number", desc, val);
return (0);
}
if (num < min) {
snprintf(ebuf, ebuflen,
"%s %lld is less than %lld.", desc, num, min);
return (0);
}
if (num > max) {
snprintf(ebuf, ebuflen,
"%s %lld is greater than %lld.", desc, num, max);
return (0);
}
*ebuf = '\0';
return (num);
}

7
bin/dd/strsuftoull.h Normal file
View File

@ -0,0 +1,7 @@
/* $NetBSD: strsuftoull.h,v 1.1 2001/11/25 10:50:06 lukem Exp $ */
u_longlong_t strsuftoull(const char *, const char *,
u_longlong_t, u_longlong_t);
u_longlong_t strsuftoullx(const char *, const char *,
u_longlong_t, u_longlong_t, char *, size_t);