summaryrefslogtreecommitdiff
path: root/bin/dd
diff options
context:
space:
mode:
authorKiyoshi Aman <kiyoshi.aman+adelie@gmail.com>2019-05-16 11:47:54 -0500
committerKiyoshi Aman <kiyoshi.aman+adelie@gmail.com>2019-05-16 11:47:54 -0500
commit5fa3142cdbb67cbb8287b2ec4fc35ee6532b3c6d (patch)
tree6abb866f965d62c64868a01950e53e0e6c21f06a /bin/dd
parent5aef04248e45a1a0ce74d96e78abd871048369bf (diff)
downloaduserland-5fa3142cdbb67cbb8287b2ec4fc35ee6532b3c6d.tar.gz
userland-5fa3142cdbb67cbb8287b2ec4fc35ee6532b3c6d.tar.bz2
userland-5fa3142cdbb67cbb8287b2ec4fc35ee6532b3c6d.tar.xz
userland-5fa3142cdbb67cbb8287b2ec4fc35ee6532b3c6d.zip
bin/dd: make buildable with libbsd
Diffstat (limited to 'bin/dd')
-rw-r--r--bin/dd/args.c33
-rw-r--r--bin/dd/conv.c23
-rw-r--r--bin/dd/conv_tab.c9
-rw-r--r--bin/dd/dd.c24
-rw-r--r--bin/dd/dd.h18
-rw-r--r--bin/dd/dd_hostops.c6
-rw-r--r--bin/dd/dd_rumpops.c52
-rw-r--r--bin/dd/extern.h32
-rw-r--r--bin/dd/misc.c13
-rw-r--r--bin/dd/position.c10
-rw-r--r--bin/dd/strsuftoll.c234
11 files changed, 287 insertions, 167 deletions
diff --git a/bin/dd/args.c b/bin/dd/args.c
index 748f52c..ff4cc58 100644
--- a/bin/dd/args.c
+++ b/bin/dd/args.c
@@ -33,15 +33,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)args.c 8.3 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: args.c,v 1.40 2019/01/30 01:40:02 mrg Exp $");
-#endif
-#endif /* not lint */
-
#include <sys/types.h>
#include <sys/time.h>
@@ -60,22 +51,18 @@ __RCSID("$NetBSD: args.c,v 1.40 2019/01/30 01:40:02 mrg Exp $");
static int c_arg(const void *, const void *);
-#ifdef NO_MSGFMT
-static void f_msgfmt(char *) __dead;
-#else
static void f_msgfmt(char *);
-#endif /* NO_MSGFMT */
#ifdef NO_CONV
-static void f_conv(char *) __dead;
+static void f_conv(char *);
#else
static void f_conv(char *);
static int c_conv(const void *, const void *);
#endif /* NO_CONV */
#ifdef NO_IOFLAG
-static void f_iflag(char *) __dead;
-static void f_oflag(char *) __dead;
+static void f_iflag(char *);
+static void f_oflag(char *);
#else
static void f_iflag(char *);
static void f_oflag(char *);
@@ -120,6 +107,8 @@ static const struct arg {
{ "seek", f_seek, C_SEEK, C_SEEK },
{ "skip", f_skip, C_SKIP, C_SKIP },
};
+/* number of entries in the above */
+const int args_count = 17;
/*
* args -- parse JCL syntax of dd.
@@ -149,8 +138,7 @@ jcl(char **argv)
/* NOTREACHED */
}
tmp.name = oper;
- if (!(ap = bsearch(&tmp, args,
- __arraycount(args), sizeof(*args), c_arg))) {
+ if (!(ap = bsearch(&tmp, args, args_count, sizeof(*args), c_arg))) {
errx(EXIT_FAILURE, "unknown operand %s", tmp.name);
/* NOTREACHED */
}
@@ -371,6 +359,8 @@ static const struct conv {
* conversions to the C_BS check in the jcl routine above.
*/
};
+/* number of entries in the above table */
+const int clist_count = 16;
static void
f_conv(char *arg)
@@ -379,8 +369,7 @@ f_conv(char *arg)
while (arg != NULL) {
tmp.name = strsep(&arg, ",");
- if (!(cp = bsearch(&tmp, clist,
- __arraycount(clist), sizeof(*clist), c_conv))) {
+ if (!(cp = bsearch(&tmp, clist, clist_count, sizeof(*clist), c_conv))) {
errx(EXIT_FAILURE, "unknown conversion %s", tmp.name);
/* NOTREACHED */
}
@@ -434,8 +423,8 @@ f_oflag(char *arg)
#ifndef NO_IOFLAG
static const struct ioflag {
const char *name;
- u_int set;
- u_int allowed;
+ uint32_t set;
+ uint32_t allowed;
} olist[] = {
/* the array needs to be sorted by the first column so
bsearch() can be used to find commands quickly */
diff --git a/bin/dd/conv.c b/bin/dd/conv.c
index d4a8a09..4c85c9d 100644
--- a/bin/dd/conv.c
+++ b/bin/dd/conv.c
@@ -33,15 +33,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: conv.c,v 1.17 2003/08/07 09:05:10 agc Exp $");
-#endif
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/time.h>
@@ -62,8 +53,8 @@ void
def(void)
{
uint64_t cnt;
- u_char *inp;
- const u_char *t;
+ uint8_t *inp;
+ const uint8_t *t;
if ((t = ctab) != NULL)
for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
@@ -119,8 +110,8 @@ block(void)
static int intrunc;
int ch = 0; /* pacify gcc */
uint64_t cnt, maxlen;
- u_char *inp, *outp;
- const u_char *t;
+ uint8_t *inp, *outp;
+ const uint8_t *t;
/*
* Record truncation can cross block boundaries. If currently in a
@@ -230,8 +221,8 @@ void
unblock(void)
{
uint64_t cnt;
- u_char *inp;
- const u_char *t;
+ uint8_t *inp;
+ const uint8_t *t;
/* Translation and case conversion. */
if ((t = ctab) != NULL)
@@ -264,7 +255,7 @@ void
unblock_close(void)
{
uint64_t cnt;
- u_char *t;
+ uint8_t *t;
if (in.dbcnt) {
warnx("%s: short input record", in.name);
diff --git a/bin/dd/conv_tab.c b/bin/dd/conv_tab.c
index 89d32da..549df80 100644
--- a/bin/dd/conv_tab.c
+++ b/bin/dd/conv_tab.c
@@ -33,15 +33,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)conv_tab.c 8.1 (Berkeley) 5/31/93";
-#else
-__RCSID("$NetBSD: conv_tab.c,v 1.9 2003/08/07 09:05:10 agc Exp $");
-#endif
-#endif /* not lint */
-
#include <sys/types.h>
/*
diff --git a/bin/dd/dd.c b/bin/dd/dd.c
index c4fb1e8..aa2897d 100644
--- a/bin/dd/dd.c
+++ b/bin/dd/dd.c
@@ -33,20 +33,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-#ifndef lint
-__COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\
- The Regents of the University of California. All rights reserved.");
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: dd.c,v 1.51 2016/09/05 01:00:07 sevan Exp $");
-#endif
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
@@ -61,6 +47,7 @@ __RCSID("$NetBSD: dd.c,v 1.51 2016/09/05 01:00:07 sevan Exp $");
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
+#include <bsd/stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -135,10 +122,10 @@ main(int argc, char *argv[])
#endif
setup();
- (void)signal(SIGINFO, summaryx);
+ (void)signal(SIGHUP, summaryx);
(void)signal(SIGINT, terminate);
(void)sigemptyset(&infoset);
- (void)sigaddset(&infoset, SIGINFO);
+ (void)sigaddset(&infoset, SIGHUP);
(void)atexit(summary);
@@ -203,15 +190,14 @@ setup(void)
#endif /* NO_IOFLAG */
#define OFLAGS \
(oflag | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
- out.fd = ddop_open(out, out.name, O_RDWR | OFLAGS, DEFFILEMODE);
+ out.fd = ddop_open(out, out.name, O_RDWR | OFLAGS);
/*
* May not have read access, so try again with write only.
* Without read we may have a problem if output also does
* not support seeks.
*/
if (out.fd < 0) {
- out.fd = ddop_open(out, out.name, O_WRONLY | OFLAGS,
- DEFFILEMODE);
+ out.fd = ddop_open(out, out.name, O_WRONLY | OFLAGS);
out.flags |= NOREAD;
}
if (out.fd < 0) {
diff --git a/bin/dd/dd.h b/bin/dd/dd.h
index 2b2712d..c630c0a 100644
--- a/bin/dd/dd.h
+++ b/bin/dd/dd.h
@@ -36,6 +36,10 @@
*/
#include <sys/stat.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <stdarg.h>
struct ddfops {
int (*op_init)(void);
@@ -44,7 +48,7 @@ struct ddfops {
int (*op_close)(int);
int (*op_fcntl)(int, int, ...);
- int (*op_ioctl)(int, unsigned long, ...);
+ int (*op_ioctl)(int, int, ...);
int (*op_fstat)(int, struct stat *);
int (*op_fsync)(int);
@@ -56,10 +60,10 @@ struct ddfops {
ssize_t (*op_write)(int, const void *, size_t);
};
-#define ddop_open(dir, a1, a2, ...) dir.ops->op_open(a1, a2, __VA_ARGS__)
+#define ddop_open(dir, a1, a2, ...) dir.ops->op_open(a1, a2, ##__VA_ARGS__)
#define ddop_close(dir, a1) dir.ops->op_close(a1)
-#define ddop_fcntl(dir, a1, a2, ...) dir.ops->op_fcntl(a1, a2, __VA_ARGS__)
-#define ddop_ioctl(dir, a1, a2, ...) dir.ops->op_ioctl(a1, a2, __VA_ARGS__)
+#define ddop_fcntl(dir, a1, a2, ...) dir.ops->op_fcntl(a1, a2, ##__VA_ARGS__)
+#define ddop_ioctl(dir, a1, a2, ...) dir.ops->op_ioctl(a1, a2, ##__VA_ARGS__)
#define ddop_fsync(dir, a1) dir.ops->op_fsync(a1)
#define ddop_ftruncate(dir, a1, a2) dir.ops->op_ftruncate(a1, a2)
#define ddop_lseek(dir, a1, a2, a3) dir.ops->op_lseek(a1, a2, a3)
@@ -68,8 +72,8 @@ struct ddfops {
/* Input/output stream state. */
typedef struct {
- u_char *db; /* buffer address */
- u_char *dbp; /* current buffer I/O address */
+ unsigned char *db; /* buffer address */
+ unsigned char *dbp; /* current buffer I/O address */
uint64_t dbcnt; /* current buffer byte count */
int64_t dbrcnt; /* last read byte count */
uint64_t dbsz; /* buffer size */
@@ -78,7 +82,7 @@ typedef struct {
#define ISPIPE 0x02 /* pipe (not truncatable) */
#define ISTAPE 0x04 /* tape (not seekable) */
#define NOREAD 0x08 /* not readable */
- u_int flags;
+ unsigned int flags;
const char *name; /* name */
int fd; /* file descriptor */
diff --git a/bin/dd/dd_hostops.c b/bin/dd/dd_hostops.c
index d6e7a89..b9a2fd4 100644
--- a/bin/dd/dd_hostops.c
+++ b/bin/dd/dd_hostops.c
@@ -26,12 +26,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-#ifndef lint
-__RCSID("$NetBSD: dd_hostops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $");
-#endif /* !lint */
-
-#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
diff --git a/bin/dd/dd_rumpops.c b/bin/dd/dd_rumpops.c
deleted file mode 100644
index 71f7db4..0000000
--- a/bin/dd/dd_rumpops.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* $NetBSD: dd_rumpops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $ */
-
-/*-
- * Copyright (c) 2010 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * 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.
- *
- * 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: dd_rumpops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $");
-#endif /* !lint */
-
-#include <rump/rump_syscalls.h>
-#include <rump/rumpclient.h>
-
-#include "dd.h"
-
-const struct ddfops ddfops_prog = {
- .op_init = rumpclient_init,
-
- .op_open = rump_sys_open,
- .op_close = rump_sys_close,
- .op_fcntl = rump_sys_fcntl,
- .op_ioctl = rump_sys_ioctl,
- .op_fstat = rump_sys_fstat,
- .op_fsync = rump_sys_fsync,
- .op_ftruncate = rump_sys_ftruncate,
- .op_lseek = rump_sys_lseek,
- .op_read = rump_sys_read,
- .op_write = rump_sys_write,
-};
diff --git a/bin/dd/extern.h b/bin/dd/extern.h
index 27b51a0..6185f4d 100644
--- a/bin/dd/extern.h
+++ b/bin/dd/extern.h
@@ -35,13 +35,14 @@
* @(#)extern.h 8.3 (Berkeley) 4/2/94
*/
-#include <sys/cdefs.h>
+#define NO_IOFLAG
+#define NO_MSGFMT
#ifdef NO_CONV
-__dead void block(void);
-__dead void block_close(void);
-__dead void unblock(void);
-__dead void unblock_close(void);
+void block(void);
+void block_close(void);
+void unblock(void);
+void unblock_close(void);
#else
void block(void);
void block_close(void);
@@ -61,7 +62,7 @@ void pos_in(void);
void pos_out(void);
void summary(void);
void summaryx(int);
-__dead void terminate(int);
+void terminate(int);
void unblock(void);
void unblock_close(void);
ssize_t bwrite(IO *, const void *, size_t);
@@ -71,16 +72,17 @@ extern STAT st;
extern void (*cfunc)(void);
extern uint64_t cpy_cnt;
extern uint64_t cbsz;
-extern u_int ddflags;
+extern uint32_t ddflags;
#ifndef NO_IOFLAG
-extern u_int iflag;
-extern u_int oflag;
+extern uint32_t iflag;
+extern uint32_t oflag;
#endif /* NO_IOFLAG */
-extern u_int files_cnt;
+extern unsigned int files_cnt;
extern uint64_t 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 const uint8_t *ctab;
+extern const uint8_t a2e_32V[], a2e_POSIX[];
+extern const uint8_t e2a_32V[], e2a_POSIX[];
+extern const uint8_t a2ibm_32V[], a2ibm_POSIX[];
+extern uint8_t casetab[];
extern const char *msgfmt;
+extern long long strsuftoll(const char *, const char *, long long, long long);
diff --git a/bin/dd/misc.c b/bin/dd/misc.c
index 0fac98b..b32ccc7 100644
--- a/bin/dd/misc.c
+++ b/bin/dd/misc.c
@@ -33,15 +33,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)misc.c 8.3 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $");
-#endif
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
@@ -51,8 +42,8 @@ __RCSID("$NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $");
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <util.h>
#include <inttypes.h>
+#include <signal.h>
#include "dd.h"
#include "extern.h"
@@ -153,7 +144,7 @@ terminate(int signo)
{
summary();
- (void)raise_default_signal(signo);
+ (void)raise(signo);
_exit(127);
}
diff --git a/bin/dd/position.c b/bin/dd/position.c
index 36dd580..f70008b 100644
--- a/bin/dd/position.c
+++ b/bin/dd/position.c
@@ -33,16 +33,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94";
-#else
-__RCSID("$NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mtio.h>
diff --git a/bin/dd/strsuftoll.c b/bin/dd/strsuftoll.c
new file mode 100644
index 0000000..e031ff3
--- /dev/null
+++ b/bin/dd/strsuftoll.c
@@ -0,0 +1,234 @@
+/* $NetBSD: strsuftoll.c,v 1.9 2011/10/22 22:08:47 christos Exp $ */
+/*-
+ * Copyright (c) 2001-2002,2004 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.
+ *
+ * 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.
+ */
+/*-
+ * 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. 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.
+ */
+
+#ifndef HAVE_STRSUFTOLL
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Convert an expression of the following forms to a (u)int64_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 g (mult by 1073741824).
+ * 6) A positive decimal number followed by a t (mult by 1099511627776).
+ * 7) A positive decimal number followed by a w (mult by sizeof int)
+ * 8) 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.
+ *
+ */
+/* LONGLONG */
+
+long long strsuftollx(const char *, const char *, long long, long long, char *, size_t);
+
+long long
+strsuftoll(const char *desc, const char *val,
+ long long min, long long max)
+{
+ long long result;
+ char errbuf[100];
+
+ result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf));
+ if (*errbuf != '\0')
+ errx(EXIT_FAILURE, "%s", errbuf);
+ return result;
+}
+
+/*
+ * As strsuftoll(), but returns the error message into the provided buffer
+ * rather than exiting with it.
+ */
+/* LONGLONG */
+static long long
+__strsuftollx(const char *desc, const char *val,
+ long long min, long long max, char *ebuf, size_t ebuflen, size_t depth)
+{
+ long long num, t;
+ char *expr;
+
+#ifndef NDEBUG
+ assert(desc != NULL);
+ assert(val != NULL);
+ assert(ebuf != NULL);
+#endif
+
+ if (depth > 16) {
+ snprintf(ebuf, ebuflen, "%s: Recursion limit exceeded", desc);
+ return 0;
+ }
+
+ while (isspace((unsigned char)*val)) /* Skip leading space */
+ val++;
+
+ errno = 0;
+ num = strtoll(val, &expr, 10);
+ if (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 kibibyte */
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'm':
+ t = num;
+ num *= 1048576; /* 1 mebibyte */
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'g':
+ t = num;
+ num *= 1073741824; /* 1 gibibyte */
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 't':
+ t = num;
+ num *= 1099511627776LL; /* 1 tebibyte */
+ 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 *= __strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen,
+ depth + 1);
+ if (*ebuf != '\0')
+ return 0;
+ if (t > num) {
+ erange:
+ errno = ERANGE;
+ snprintf(ebuf, ebuflen, "%s: %s", desc, strerror(errno));
+ return 0;
+ }
+ break;
+ default:
+ badnum:
+ snprintf(ebuf, ebuflen, "%s `%s': illegal number", desc, val);
+ return 0;
+ }
+ if (num < min) {
+ /* LONGLONG */
+ snprintf(ebuf, ebuflen, "%s %lld is less than %lld.",
+ desc, (long long)num, (long long)min);
+ return 0;
+ }
+ if (num > max) {
+ /* LONGLONG */
+ snprintf(ebuf, ebuflen, "%s %lld is greater than %lld.",
+ desc, (long long)num, (long long)max);
+ return 0;
+ }
+ *ebuf = '\0';
+ return num;
+}
+
+
+long long
+strsuftollx(const char *desc, const char *val,
+ long long min, long long max, char *ebuf, size_t ebuflen)
+{
+ return __strsuftollx(desc, val, min, max, ebuf, ebuflen, 0);
+}
+#endif /* !HAVE_STRSUFTOLL */