aboutsummaryrefslogtreecommitdiff
path: root/bin/dd
diff options
context:
space:
mode:
Diffstat (limited to 'bin/dd')
-rw-r--r--bin/dd/Makefile45
-rw-r--r--bin/dd/Makefile.depend18
-rw-r--r--bin/dd/args.c586
-rw-r--r--bin/dd/conv.c270
-rw-r--r--bin/dd/conv_tab.c292
-rw-r--r--bin/dd/dd.1506
-rw-r--r--bin/dd/dd.c644
-rw-r--r--bin/dd/dd.h115
-rw-r--r--bin/dd/extern.h71
-rw-r--r--bin/dd/gen.c24
-rw-r--r--bin/dd/misc.c157
-rw-r--r--bin/dd/position.c219
-rw-r--r--bin/dd/ref.ascii18
-rw-r--r--bin/dd/ref.ebcdic18
-rw-r--r--bin/dd/ref.ibm18
-rw-r--r--bin/dd/ref.lcase18
-rw-r--r--bin/dd/ref.obs_zeroes3
-rw-r--r--bin/dd/ref.oldascii18
-rw-r--r--bin/dd/ref.oldebcdic18
-rw-r--r--bin/dd/ref.oldibm18
-rw-r--r--bin/dd/ref.pareven18
-rw-r--r--bin/dd/ref.parnone18
-rw-r--r--bin/dd/ref.parodd18
-rw-r--r--bin/dd/ref.parset18
-rw-r--r--bin/dd/ref.swab18
-rw-r--r--bin/dd/ref.ucase18
-rw-r--r--bin/dd/tests/Makefile8
-rw-r--r--bin/dd/tests/Makefile.depend11
-rwxr-xr-xbin/dd/tests/dd2_test.sh69
29 files changed, 3272 insertions, 0 deletions
diff --git a/bin/dd/Makefile b/bin/dd/Makefile
new file mode 100644
index 000000000000..9088112536dd
--- /dev/null
+++ b/bin/dd/Makefile
@@ -0,0 +1,45 @@
+# @(#)Makefile 8.1 (Berkeley) 5/31/93
+# $FreeBSD$
+
+.include <src.opts.mk>
+
+PACKAGE=runtime
+PROG= dd
+SRCS= args.c conv.c conv_tab.c dd.c misc.c position.c
+LIBADD= util
+
+#
+# Test the character conversion functions. We have to be explicit about
+# which LC_LANG we use because the definition of upper and lower case
+# depends on it.
+#
+
+CLEANFILES= gen
+
+test: ${PROG} gen
+.for conv in ascii ebcdic ibm oldascii oldebcdic oldibm \
+ pareven parnone parodd parset \
+ swab lcase ucase
+ @${ECHO} testing conv=${conv}
+ @./gen | \
+ LC_ALL=en_US.US-ASCII ./dd conv=${conv} 2>/dev/null | \
+ LC_ALL=en_US.US-ASCII hexdump -C | \
+ diff -I FreeBSD - ${.CURDIR}/ref.${conv}
+.endfor
+ @${ECHO} "testing sparse file (obs zeroes)"
+ @./gen 189284 | ./dd ibs=16 obs=8 conv=sparse of=obs_zeroes 2> /dev/null
+ @hexdump -C obs_zeroes | diff -I FreeBSD - ${.CURDIR}/ref.obs_zeroes
+
+ @${ECHO} "testing spase file (all zeroes)"
+ @./dd if=/dev/zero of=1M_zeroes bs=1048576 count=1 2> /dev/null
+ @./dd if=1M_zeroes of=1M_zeroes.1 bs=1048576 conv=sparse 2> /dev/null
+ @./dd if=1M_zeroes of=1M_zeroes.2 bs=1048576 2> /dev/null
+ @diff 1M_zeroes 1M_zeroes.1
+ @diff 1M_zeroes 1M_zeroes.2
+
+ @rm -f gen 1M_zeroes* obs_zeroes
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
+.include <bsd.prog.mk>
diff --git a/bin/dd/Makefile.depend b/bin/dd/Makefile.depend
new file mode 100644
index 000000000000..1adfc08a54d6
--- /dev/null
+++ b/bin/dd/Makefile.depend
@@ -0,0 +1,18 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcapsicum \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/bin/dd/args.c b/bin/dd/args.c
new file mode 100644
index 000000000000..35a076175a93
--- /dev/null
+++ b/bin/dd/args.c
@@ -0,0 +1,586 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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 lint
+#if 0
+static char sccsid[] = "@(#)args.c 8.3 (Berkeley) 4/2/94";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dd.h"
+#include "extern.h"
+
+static int c_arg(const void *, const void *);
+static int c_conv(const void *, const void *);
+static int c_iflag(const void *, const void *);
+static int c_oflag(const void *, const void *);
+static void f_bs(char *);
+static void f_cbs(char *);
+static void f_conv(char *);
+static void f_count(char *);
+static void f_files(char *);
+static void f_fillchar(char *);
+static void f_ibs(char *);
+static void f_if(char *);
+static void f_iflag(char *);
+static void f_obs(char *);
+static void f_of(char *);
+static void f_oflag(char *);
+static void f_seek(char *);
+static void f_skip(char *);
+static void f_speed(char *);
+static void f_status(char *);
+static uintmax_t get_num(const char *);
+static off_t get_off_t(const char *);
+
+static const struct arg {
+ const char *name;
+ void (*f)(char *);
+ uint64_t set, noset;
+} args[] = {
+ { "bs", f_bs, C_BS, C_BS|C_IBS|C_OBS|C_OSYNC },
+ { "cbs", f_cbs, C_CBS, C_CBS },
+ { "conv", f_conv, 0, 0 },
+ { "count", f_count, C_COUNT, C_COUNT },
+ { "files", f_files, C_FILES, C_FILES },
+ { "fillchar", f_fillchar, C_FILL, C_FILL },
+ { "ibs", f_ibs, C_IBS, C_BS|C_IBS },
+ { "if", f_if, C_IF, C_IF },
+ { "iflag", f_iflag, 0, 0 },
+ { "iseek", f_skip, C_SKIP, C_SKIP },
+ { "obs", f_obs, C_OBS, C_BS|C_OBS },
+ { "of", f_of, C_OF, C_OF },
+ { "oflag", f_oflag, 0, 0 },
+ { "oseek", f_seek, C_SEEK, C_SEEK },
+ { "seek", f_seek, C_SEEK, C_SEEK },
+ { "skip", f_skip, C_SKIP, C_SKIP },
+ { "speed", f_speed, 0, 0 },
+ { "status", f_status, C_STATUS,C_STATUS },
+};
+
+static char *oper;
+
+/*
+ * args -- parse JCL syntax of dd.
+ */
+void
+jcl(char **argv)
+{
+ struct arg *ap, tmp;
+ char *arg;
+
+ in.dbsz = out.dbsz = 512;
+
+ while ((oper = *++argv) != NULL) {
+ if ((oper = strdup(oper)) == NULL)
+ errx(1, "unable to allocate space for the argument \"%s\"", *argv);
+ if ((arg = strchr(oper, '=')) == NULL)
+ errx(1, "unknown operand %s", oper);
+ *arg++ = '\0';
+ if (!*arg)
+ errx(1, "no value specified for %s", oper);
+ tmp.name = oper;
+ if (!(ap = (struct arg *)bsearch(&tmp, args,
+ sizeof(args)/sizeof(struct arg), sizeof(struct arg),
+ c_arg)))
+ errx(1, "unknown operand %s", tmp.name);
+ if (ddflags & ap->noset)
+ errx(1, "%s: illegal argument combination or already set",
+ tmp.name);
+ ddflags |= ap->set;
+ ap->f(arg);
+ }
+
+ /* Final sanity checks. */
+
+ if (ddflags & C_BS) {
+ /*
+ * Bs is turned off by any conversion -- we assume the user
+ * just wanted to set both the input and output block sizes
+ * and didn't want the bs semantics, so we don't warn.
+ */
+ if (ddflags & (C_BLOCK | C_LCASE | C_SWAB | C_UCASE |
+ C_UNBLOCK))
+ ddflags &= ~C_BS;
+
+ /* Bs supersedes ibs and obs. */
+ if (ddflags & C_BS && ddflags & (C_IBS | C_OBS))
+ warnx("bs supersedes ibs and obs");
+ }
+
+ /*
+ * Ascii/ebcdic and cbs implies block/unblock.
+ * Block/unblock requires cbs and vice-versa.
+ */
+ 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)) {
+ if (ddflags & C_ASCII) {
+ ddflags |= C_UNBLOCK;
+ cfunc = unblock;
+ } else {
+ ddflags |= C_BLOCK;
+ cfunc = block;
+ }
+ } else
+ errx(1, "cbs meaningless if not doing record operations");
+ } else
+ cfunc = def;
+}
+
+static int
+c_arg(const void *a, const void *b)
+{
+
+ return (strcmp(((const struct arg *)a)->name,
+ ((const struct arg *)b)->name));
+}
+
+static void
+f_bs(char *arg)
+{
+ uintmax_t res;
+
+ res = get_num(arg);
+ if (res < 1 || res > SSIZE_MAX)
+ errx(1, "bs must be between 1 and %zd", (ssize_t)SSIZE_MAX);
+ in.dbsz = out.dbsz = (size_t)res;
+}
+
+static void
+f_cbs(char *arg)
+{
+ uintmax_t res;
+
+ res = get_num(arg);
+ if (res < 1 || res > SSIZE_MAX)
+ errx(1, "cbs must be between 1 and %zd", (ssize_t)SSIZE_MAX);
+ cbsz = (size_t)res;
+}
+
+static void
+f_count(char *arg)
+{
+ uintmax_t res;
+
+ res = get_num(arg);
+ if (res == UINTMAX_MAX)
+ errc(1, ERANGE, "%s", oper);
+ if (res == 0)
+ cpy_cnt = UINTMAX_MAX;
+ else
+ cpy_cnt = res;
+}
+
+static void
+f_files(char *arg)
+{
+
+ files_cnt = get_num(arg);
+ if (files_cnt < 1)
+ errx(1, "files must be between 1 and %zu", SIZE_MAX);
+}
+
+static void
+f_fillchar(char *arg)
+{
+
+ if (strlen(arg) != 1)
+ errx(1, "need exactly one fill char");
+
+ fill_char = arg[0];
+}
+
+static void
+f_ibs(char *arg)
+{
+ uintmax_t res;
+
+ if (!(ddflags & C_BS)) {
+ res = get_num(arg);
+ if (res < 1 || res > SSIZE_MAX)
+ errx(1, "ibs must be between 1 and %zd",
+ (ssize_t)SSIZE_MAX);
+ in.dbsz = (size_t)res;
+ }
+}
+
+static void
+f_if(char *arg)
+{
+
+ in.name = arg;
+}
+
+static const struct iflag {
+ const char *name;
+ uint64_t set, noset;
+} ilist[] = {
+ { "direct", C_IDIRECT, 0 },
+ { "fullblock", C_IFULLBLOCK, C_SYNC },
+};
+
+static void
+f_iflag(char *arg)
+{
+ struct iflag *ip, tmp;
+
+ while (arg != NULL) {
+ tmp.name = strsep(&arg, ",");
+ ip = bsearch(&tmp, ilist, nitems(ilist), sizeof(struct iflag),
+ c_iflag);
+ if (ip == NULL)
+ errx(1, "unknown iflag %s", tmp.name);
+ if (ddflags & ip->noset)
+ errx(1, "%s: illegal conversion combination", tmp.name);
+ ddflags |= ip->set;
+ }
+}
+
+static int
+c_iflag(const void *a, const void *b)
+{
+
+ return (strcmp(((const struct iflag *)a)->name,
+ ((const struct iflag *)b)->name));
+}
+
+static void
+f_obs(char *arg)
+{
+ uintmax_t res;
+
+ if (!(ddflags & C_BS)) {
+ res = get_num(arg);
+ if (res < 1 || res > SSIZE_MAX)
+ errx(1, "obs must be between 1 and %zd",
+ (ssize_t)SSIZE_MAX);
+ out.dbsz = (size_t)res;
+ }
+}
+
+static void
+f_of(char *arg)
+{
+
+ out.name = arg;
+}
+
+static void
+f_seek(char *arg)
+{
+
+ out.offset = get_off_t(arg);
+}
+
+static void
+f_skip(char *arg)
+{
+
+ in.offset = get_off_t(arg);
+}
+
+static void
+f_speed(char *arg)
+{
+
+ speed = get_num(arg);
+}
+
+static void
+f_status(char *arg)
+{
+
+ if (strcmp(arg, "none") == 0)
+ ddflags |= C_NOINFO;
+ else if (strcmp(arg, "noxfer") == 0)
+ ddflags |= C_NOXFER;
+ else if (strcmp(arg, "progress") == 0)
+ ddflags |= C_PROGRESS;
+ else
+ errx(1, "unknown status %s", arg);
+}
+
+static const struct conv {
+ const char *name;
+ uint64_t set, noset;
+ const u_char *ctab;
+} clist[] = {
+ { "ascii", C_ASCII, C_EBCDIC, e2a_POSIX },
+ { "block", C_BLOCK, C_UNBLOCK, NULL },
+ { "ebcdic", C_EBCDIC, C_ASCII, a2e_POSIX },
+ { "fdatasync", C_FDATASYNC, 0, NULL },
+ { "fsync", C_FSYNC, 0, NULL },
+ { "ibm", C_EBCDIC, C_ASCII, a2ibm_POSIX },
+ { "lcase", C_LCASE, C_UCASE, NULL },
+ { "noerror", C_NOERROR, 0, NULL },
+ { "notrunc", C_NOTRUNC, 0, NULL },
+ { "oldascii", C_ASCII, C_EBCDIC, e2a_32V },
+ { "oldebcdic", C_EBCDIC, C_ASCII, a2e_32V },
+ { "oldibm", C_EBCDIC, C_ASCII, a2ibm_32V },
+ { "osync", C_OSYNC, C_BS, NULL },
+ { "pareven", C_PAREVEN, C_PARODD|C_PARSET|C_PARNONE, NULL},
+ { "parnone", C_PARNONE, C_PARODD|C_PARSET|C_PAREVEN, NULL},
+ { "parodd", C_PARODD, C_PAREVEN|C_PARSET|C_PARNONE, NULL},
+ { "parset", C_PARSET, C_PARODD|C_PAREVEN|C_PARNONE, NULL},
+ { "sparse", C_SPARSE, 0, NULL },
+ { "swab", C_SWAB, 0, NULL },
+ { "sync", C_SYNC, C_IFULLBLOCK, NULL },
+ { "ucase", C_UCASE, C_LCASE, NULL },
+ { "unblock", C_UNBLOCK, C_BLOCK, NULL },
+};
+
+static void
+f_conv(char *arg)
+{
+ struct conv *cp, tmp;
+
+ while (arg != NULL) {
+ tmp.name = strsep(&arg, ",");
+ cp = bsearch(&tmp, clist, nitems(clist), sizeof(struct conv),
+ c_conv);
+ if (cp == NULL)
+ errx(1, "unknown conversion %s", tmp.name);
+ if (ddflags & cp->noset)
+ errx(1, "%s: illegal conversion combination", tmp.name);
+ ddflags |= cp->set;
+ if (cp->ctab)
+ ctab = cp->ctab;
+ }
+}
+
+static int
+c_conv(const void *a, const void *b)
+{
+
+ return (strcmp(((const struct conv *)a)->name,
+ ((const struct conv *)b)->name));
+}
+
+static const struct oflag {
+ const char *name;
+ uint64_t set;
+} olist[] = {
+ { "direct", C_ODIRECT },
+ { "fsync", C_OFSYNC },
+ { "sync", C_OFSYNC },
+};
+
+static void
+f_oflag(char *arg)
+{
+ struct oflag *op, tmp;
+
+ while (arg != NULL) {
+ tmp.name = strsep(&arg, ",");
+ op = bsearch(&tmp, olist, nitems(olist), sizeof(struct oflag),
+ c_oflag);
+ if (op == NULL)
+ errx(1, "unknown open flag %s", tmp.name);
+ ddflags |= op->set;
+ }
+}
+
+static int
+c_oflag(const void *a, const void *b)
+{
+
+ return (strcmp(((const struct oflag *)a)->name,
+ ((const struct oflag *)b)->name));
+}
+
+static intmax_t
+postfix_to_mult(const char expr)
+{
+ intmax_t mult;
+
+ mult = 0;
+ switch (expr) {
+ case 'B':
+ case 'b':
+ mult = 512;
+ break;
+ case 'K':
+ case 'k':
+ mult = 1 << 10;
+ break;
+ case 'M':
+ case 'm':
+ mult = 1 << 20;
+ break;
+ case 'G':
+ case 'g':
+ mult = 1 << 30;
+ break;
+ case 'T':
+ case 't':
+ mult = (uintmax_t)1 << 40;
+ break;
+ case 'P':
+ case 'p':
+ mult = (uintmax_t)1 << 50;
+ break;
+ case 'W':
+ case 'w':
+ mult = sizeof(int);
+ break;
+ }
+
+ return (mult);
+}
+
+/*
+ * Convert an expression of the following forms to a uintmax_t.
+ * 1) A positive decimal number.
+ * 2) A positive decimal number followed by a 'b' or 'B' (mult by 512).
+ * 3) A positive decimal number followed by a 'k' or 'K' (mult by 1 << 10).
+ * 4) A positive decimal number followed by a 'm' or 'M' (mult by 1 << 20).
+ * 5) A positive decimal number followed by a 'g' or 'G' (mult by 1 << 30).
+ * 6) A positive decimal number followed by a 't' or 'T' (mult by 1 << 40).
+ * 7) A positive decimal number followed by a 'p' or 'P' (mult by 1 << 50).
+ * 8) A positive decimal number followed by a 'w' or 'W' (mult by sizeof int).
+ * 9) Two or more positive decimal numbers (with/without [BbKkMmGgWw])
+ * separated by 'x' or 'X' (also '*' for backwards compatibility),
+ * specifying the product of the indicated values.
+ */
+static uintmax_t
+get_num(const char *val)
+{
+ uintmax_t num, mult, prevnum;
+ char *expr;
+
+ errno = 0;
+ num = strtoumax(val, &expr, 0);
+ if (expr == val) /* No valid digits. */
+ errx(1, "%s: invalid numeric value", oper);
+ if (errno != 0)
+ err(1, "%s", oper);
+
+ mult = postfix_to_mult(*expr);
+
+ 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':
+ case 'x':
+ mult = get_num(expr + 1);
+ prevnum = num;
+ num *= mult;
+ if (num / mult == prevnum)
+ break;
+erange:
+ errx(1, "%s: %s", oper, strerror(ERANGE));
+ default:
+ errx(1, "%s: illegal numeric value", oper);
+ }
+ 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 intmax_t.
+ */
+static off_t
+get_off_t(const char *val)
+{
+ intmax_t num, mult, prevnum;
+ char *expr;
+
+ errno = 0;
+ num = strtoimax(val, &expr, 0);
+ if (expr == val) /* No valid digits. */
+ errx(1, "%s: invalid numeric value", oper);
+ if (errno != 0)
+ err(1, "%s", oper);
+
+ mult = postfix_to_mult(*expr);
+
+ if (mult != 0) {
+ prevnum = num;
+ num *= mult;
+ /* Check for overflow. */
+ if ((prevnum > 0) != (num > 0) || num / mult != prevnum)
+ goto erange;
+ expr++;
+ }
+
+ switch (*expr) {
+ case '\0':
+ break;
+ case '*': /* Backward compatible. */
+ case 'X':
+ case 'x':
+ mult = (intmax_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/conv.c b/bin/dd/conv.c
new file mode 100644
index 000000000000..ef5194ee1e08
--- /dev/null
+++ b/bin/dd/conv.c
@@ -0,0 +1,270 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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 lint
+#if 0
+static char sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <err.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include "dd.h"
+#include "extern.h"
+
+/*
+ * def --
+ * Copy input to output. Input is buffered until reaches obs, and then
+ * output until less than obs remains. Only a single buffer is used.
+ * Worst case buffer calculation is (ibs + obs - 1).
+ */
+void
+def(void)
+{
+ u_char *inp;
+ const u_char *t;
+ size_t cnt;
+
+ if ((t = ctab) != NULL)
+ for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
+ *inp = t[*inp];
+
+ /* Make the output buffer look right. */
+ out.dbp = in.dbp;
+ out.dbcnt = in.dbcnt;
+
+ if (in.dbcnt >= out.dbsz) {
+ /* If the output buffer is full, write it. */
+ dd_out(0);
+
+ /*
+ * dd_out copies the leftover output to the beginning of
+ * the buffer and resets the output buffer. Reset the
+ * input buffer to match it.
+ */
+ in.dbp = out.dbp;
+ in.dbcnt = out.dbcnt;
+ }
+}
+
+void
+def_close(void)
+{
+ /* Just update the count, everything is already in the buffer. */
+ if (in.dbcnt)
+ out.dbcnt = in.dbcnt;
+}
+
+/*
+ * Copy variable length newline terminated records with a max size cbsz
+ * bytes to output. Records less than cbs are padded with spaces.
+ *
+ * max in buffer: MAX(ibs, cbsz)
+ * max out buffer: obs + cbsz
+ */
+void
+block(void)
+{
+ u_char *inp, *outp;
+ const u_char *t;
+ size_t cnt, maxlen;
+ static int intrunc;
+ int ch;
+
+ /*
+ * Record truncation can cross block boundaries. If currently in a
+ * truncation state, keep tossing characters until reach a newline.
+ * Start at the beginning of the buffer, as the input buffer is always
+ * left empty.
+ */
+ if (intrunc) {
+ for (inp = in.db, cnt = in.dbrcnt; cnt && *inp++ != '\n'; --cnt)
+ ;
+ if (!cnt) {
+ in.dbcnt = 0;
+ in.dbp = in.db;
+ return;
+ }
+ intrunc = 0;
+ /* Adjust the input buffer numbers. */
+ in.dbcnt = cnt - 1;
+ in.dbp = inp + cnt - 1;
+ }
+
+ /*
+ * Copy records (max cbsz size chunks) into the output buffer. The
+ * translation is done as we copy into the output buffer.
+ */
+ ch = 0;
+ for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) {
+ maxlen = MIN(cbsz, (size_t)in.dbcnt);
+ if ((t = ctab) != NULL)
+ for (cnt = 0; cnt < maxlen && (ch = *inp++) != '\n';
+ ++cnt)
+ *outp++ = t[ch];
+ else
+ for (cnt = 0; cnt < maxlen && (ch = *inp++) != '\n';
+ ++cnt)
+ *outp++ = ch;
+ /*
+ * Check for short record without a newline. Reassemble the
+ * input block.
+ */
+ if (ch != '\n' && (size_t)in.dbcnt < cbsz) {
+ (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
+ break;
+ }
+
+ /* Adjust the input buffer numbers. */
+ in.dbcnt -= cnt;
+ if (ch == '\n')
+ --in.dbcnt;
+
+ /* Pad short records with spaces. */
+ if (cnt < cbsz)
+ (void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt);
+ else {
+ /*
+ * If the next character wouldn't have ended the
+ * block, it's a truncation.
+ */
+ if (!in.dbcnt || *inp != '\n')
+ ++st.trunc;
+
+ /* Toss characters to a newline. */
+ for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt)
+ ;
+ if (!in.dbcnt)
+ intrunc = 1;
+ else
+ --in.dbcnt;
+ }
+
+ /* Adjust output buffer numbers. */
+ out.dbp += cbsz;
+ if ((out.dbcnt += cbsz) >= out.dbsz)
+ dd_out(0);
+ outp = out.dbp;
+ }
+ in.dbp = in.db + in.dbcnt;
+}
+
+void
+block_close(void)
+{
+ /*
+ * Copy any remaining data into the output buffer and pad to a record.
+ * Don't worry about truncation or translation, the input buffer is
+ * always empty when truncating, and no characters have been added for
+ * translation. The bottom line is that anything left in the input
+ * buffer is a truncated record. Anything left in the output buffer
+ * just wasn't big enough.
+ */
+ if (in.dbcnt) {
+ ++st.trunc;
+ (void)memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt);
+ (void)memset(out.dbp + in.dbcnt, ctab ? ctab[' '] : ' ',
+ cbsz - in.dbcnt);
+ out.dbcnt += cbsz;
+ }
+}
+
+/*
+ * Convert fixed length (cbsz) records to variable length. Deletes any
+ * trailing blanks and appends a newline.
+ *
+ * max in buffer: MAX(ibs, cbsz) + cbsz
+ * max out buffer: obs + cbsz
+ */
+void
+unblock(void)
+{
+ u_char *inp;
+ const u_char *t;
+ size_t cnt;
+
+ /* Translation and case conversion. */
+ if ((t = ctab) != NULL)
+ for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
+ *inp = t[*inp];
+ /*
+ * Copy records (max cbsz size chunks) into the output buffer. The
+ * translation has to already be done or we might not recognize the
+ * spaces.
+ */
+ for (inp = in.db; (size_t)in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) {
+ for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t)
+ ;
+ if (t >= inp) {
+ cnt = t - inp + 1;
+ (void)memmove(out.dbp, inp, cnt);
+ out.dbp += cnt;
+ out.dbcnt += cnt;
+ }
+ *out.dbp++ = '\n';
+ if (++out.dbcnt >= out.dbsz)
+ dd_out(0);
+ }
+ if (in.dbcnt)
+ (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
+ in.dbp = in.db + in.dbcnt;
+}
+
+void
+unblock_close(void)
+{
+ u_char *t;
+ size_t cnt;
+
+ if (in.dbcnt) {
+ warnx("%s: short input record", in.name);
+ for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t)
+ ;
+ if (t >= in.db) {
+ cnt = t - in.db + 1;
+ (void)memmove(out.dbp, in.db, cnt);
+ out.dbp += cnt;
+ out.dbcnt += cnt;
+ }
+ ++out.dbcnt;
+ *out.dbp++ = '\n';
+ }
+}
diff --git a/bin/dd/conv_tab.c b/bin/dd/conv_tab.c
new file mode 100644
index 000000000000..36e23531bbbb
--- /dev/null
+++ b/bin/dd/conv_tab.c
@@ -0,0 +1,292 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * 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 lint
+#if 0
+static char sccsid[] = "@(#)conv_tab.c 8.1 (Berkeley) 5/31/93";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <signal.h>
+#include <stdint.h>
+
+#include "dd.h"
+#include "extern.h"
+
+/*
+ * There are currently six tables:
+ *
+ * ebcdic -> ascii 32V conv=oldascii
+ * ascii -> ebcdic 32V conv=oldebcdic
+ * ascii -> ibm ebcdic 32V conv=oldibm
+ *
+ * ebcdic -> ascii POSIX/S5 conv=ascii
+ * ascii -> ebcdic POSIX/S5 conv=ebcdic
+ * ascii -> ibm ebcdic POSIX/S5 conv=ibm
+ *
+ * Other tables are built from these if multiple conversions are being
+ * done.
+ *
+ * Tables used for conversions to/from IBM and EBCDIC to support an extension
+ * to POSIX P1003.2/D11. The tables referencing POSIX contain data extracted
+ * from tables 4-3 and 4-4 in P1003.2/Draft 11. The historic tables were
+ * constructed by running against a file with all possible byte values.
+ *
+ * More information can be obtained in "Correspondences of 8-Bit and Hollerith
+ * Codes for Computer Environments-A USASI Tutorial", Communications of the
+ * ACM, Volume 11, Number 11, November 1968, pp. 783-789.
+ */
+
+u_char casetab[256];
+
+/* EBCDIC to ASCII -- 32V compatible. */
+const u_char e2a_32V[] = {
+ 0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, /* 0000 */
+ 0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, /* 0010 */
+ 0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, /* 0020 */
+ 0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, /* 0030 */
+ 0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, /* 0040 */
+ 0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, /* 0050 */
+ 0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, /* 0060 */
+ 0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, /* 0070 */
+ 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, /* 0100 */
+ 0247, 0250, 0133, 0056, 0074, 0050, 0053, 0041, /* 0110 */
+ 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0120 */
+ 0260, 0261, 0135, 0044, 0052, 0051, 0073, 0136, /* 0130 */
+ 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, /* 0140 */
+ 0270, 0271, 0174, 0054, 0045, 0137, 0076, 0077, /* 0150 */
+ 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, /* 0160 */
+ 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, /* 0170 */
+ 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0200 */
+ 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, /* 0210 */
+ 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, /* 0220 */
+ 0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320, /* 0230 */
+ 0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170, /* 0240 */
+ 0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327, /* 0250 */
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0260 */
+ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, /* 0270 */
+ 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0300 */
+ 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, /* 0310 */
+ 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, /* 0320 */
+ 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, /* 0330 */
+ 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, /* 0340 */
+ 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, /* 0350 */
+ 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0360 */
+ 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
+};
+
+/* ASCII to EBCDIC -- 32V compatible. */
+const u_char a2e_32V[] = {
+ 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */
+ 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */
+ 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */
+ 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */
+ 0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */
+ 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */
+ 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */
+ 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */
+ 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */
+ 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */
+ 0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155, /* 0130 */
+ 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */
+ 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */
+ 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */
+ 0247, 0250, 0251, 0300, 0152, 0320, 0241, 0007, /* 0170 */
+ 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */
+ 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */
+ 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */
+ 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */
+ 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */
+ 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */
+ 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */
+ 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */
+ 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */
+ 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */
+ 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */
+ 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */
+ 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */
+ 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
+};
+
+/* ASCII to IBM EBCDIC -- 32V compatible. */
+const u_char a2ibm_32V[] = {
+ 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */
+ 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */
+ 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */
+ 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */
+ 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */
+ 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */
+ 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */
+ 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */
+ 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */
+ 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */
+ 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, /* 0130 */
+ 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */
+ 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */
+ 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */
+ 0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, /* 0170 */
+ 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */
+ 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */
+ 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */
+ 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */
+ 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */
+ 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */
+ 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */
+ 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */
+ 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */
+ 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */
+ 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */
+ 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */
+ 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */
+ 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
+};
+
+/* EBCDIC to ASCII -- POSIX and System V compatible. */
+const u_char e2a_POSIX[] = {
+ 0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, /* 0000 */
+ 0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, /* 0010 */
+ 0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, /* 0020 */
+ 0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, /* 0030 */
+ 0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, /* 0040 */
+ 0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, /* 0050 */
+ 0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, /* 0060 */
+ 0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, /* 0070 */
+ 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, /* 0100 */
+ 0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174, /* 0110 */
+ 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0120 */
+ 0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176, /* 0130 */
+ 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, /* 0140 */
+ 0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077, /* 0150 */
+ 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, /* 0160 */
+ 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, /* 0170 */
+ 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0200 */
+ 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, /* 0210 */
+ 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, /* 0220 */
+ 0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320, /* 0230 */
+ 0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170, /* 0240 */
+ 0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327, /* 0250 */
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0260 */
+ 0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347, /* 0270 */
+ 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0300 */
+ 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, /* 0310 */
+ 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, /* 0320 */
+ 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, /* 0330 */
+ 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, /* 0340 */
+ 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, /* 0350 */
+ 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0360 */
+ 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
+};
+
+/* ASCII to EBCDIC -- POSIX and System V compatible. */
+const u_char a2e_POSIX[] = {
+ 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */
+ 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */
+ 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */
+ 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */
+ 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */
+ 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */
+ 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */
+ 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */
+ 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */
+ 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */
+ 0347, 0350, 0351, 0255, 0340, 0275, 0232, 0155, /* 0130 */
+ 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */
+ 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */
+ 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */
+ 0247, 0250, 0251, 0300, 0117, 0320, 0137, 0007, /* 0170 */
+ 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */
+ 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */
+ 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */
+ 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */
+ 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */
+ 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */
+ 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */
+ 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */
+ 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */
+ 0216, 0217, 0220, 0152, 0233, 0234, 0235, 0236, /* 0310 */
+ 0237, 0240, 0252, 0253, 0254, 0112, 0256, 0257, /* 0320 */
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */
+ 0270, 0271, 0272, 0273, 0274, 0241, 0276, 0277, /* 0340 */
+ 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */
+ 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */
+ 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
+};
+
+/* ASCII to IBM EBCDIC -- POSIX and System V compatible. */
+const u_char a2ibm_POSIX[] = {
+ 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */
+ 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */
+ 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */
+ 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */
+ 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */
+ 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */
+ 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */
+ 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */
+ 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */
+ 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */
+ 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, /* 0130 */
+ 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */
+ 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */
+ 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */
+ 0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, /* 0170 */
+ 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */
+ 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */
+ 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */
+ 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */
+ 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */
+ 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */
+ 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */
+ 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */
+ 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */
+ 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */
+ 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */
+ 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */
+ 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */
+ 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */
+};
diff --git a/bin/dd/dd.1 b/bin/dd/dd.1
new file mode 100644
index 000000000000..8bd5fa662ac6
--- /dev/null
+++ b/bin/dd/dd.1
@@ -0,0 +1,506 @@
+.\"-
+.\" Copyright (c) 1990, 1993
+.\" 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.
+.\"
+.\" 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.
+.\"
+.\" @(#)dd.1 8.2 (Berkeley) 1/13/94
+.\" $FreeBSD$
+.\"
+.Dd June 4, 2020
+.Dt DD 1
+.Os
+.Sh NAME
+.Nm dd
+.Nd convert and copy a file
+.Sh SYNOPSIS
+.Nm
+.Op Ar operands ...
+.Sh DESCRIPTION
+The
+.Nm
+utility copies the standard input to the standard output.
+Input data is read and written in 512-byte blocks.
+If input reads are short, input from multiple reads are aggregated
+to form the output block.
+When finished,
+.Nm
+displays the number of complete and partial input and output blocks
+and truncated input records to the standard error output.
+.Pp
+The following operands are available:
+.Bl -tag -width "of=file"
+.It Cm bs Ns = Ns Ar n
+Set both input and output block size to
+.Ar n
+bytes, superseding the
+.Cm ibs
+and
+.Cm obs
+operands.
+If no conversion values other than
+.Cm noerror ,
+.Cm notrunc
+or
+.Cm sync
+are specified, then each input block is copied to the output as a
+single block without any aggregation of short blocks.
+.It Cm cbs Ns = Ns Ar n
+Set the conversion record size to
+.Ar n
+bytes.
+The conversion record size is required by the record oriented conversion
+values.
+.It Cm count Ns = Ns Ar n
+Copy only
+.Ar n
+input blocks.
+.It Cm files Ns = Ns Ar n
+Copy
+.Ar n
+input files before terminating.
+This operand is only applicable when the input device is a tape.
+.It Cm fillchar Ns = Ns Ar c
+When padding a block in conversion mode or due to use of
+.Cm noerror
+and
+.Cm sync
+modes, fill with the specified
+.Tn ASCII
+character, rather than using a space or
+.Dv NUL .
+.It Cm ibs Ns = Ns Ar n
+Set the input block size to
+.Ar n
+bytes instead of the default 512.
+.It Cm if Ns = Ns Ar file
+Read input from
+.Ar file
+instead of the standard input.
+.It Cm iflag Ns = Ns Ar value Ns Op , Ns Ar value ...
+Where
+.Cm value
+is one of the symbols from the following list.
+.Bl -tag -width "fullblock"
+.It Cm fullblock
+Reading from the input file may not obtain a full block.
+When a read returns short, continue reading to fill the block.
+Without this flag,
+.Cm count
+limits the number of times
+.Xr read 2
+is called on the input rather than the number of blocks copied in full.
+May not be combined with
+.Cm conv=sync .
+.It Cm direct
+Set the O_DIRECT flag on the input file to make reads bypass any local caching.
+.El
+.It Cm iseek Ns = Ns Ar n
+Seek on the input file
+.Ar n
+blocks.
+This is synonymous with
+.Cm skip Ns = Ns Ar n .
+.It Cm obs Ns = Ns Ar n
+Set the output block size to
+.Ar n
+bytes instead of the default 512.
+.It Cm of Ns = Ns Ar file
+Write output to
+.Ar file
+instead of the standard output.
+Any regular output file is truncated unless the
+.Cm notrunc
+conversion value is specified.
+If an initial portion of the output file is seeked past (see the
+.Cm oseek
+operand),
+the output file is truncated at that point.
+.It Cm oflag Ns = Ns Ar value Ns Op , Ns Ar value ...
+Where
+.Cm value
+is one of the symbols from the following list.
+.Bl -tag -width "direct"
+.It Cm fsync
+Set the O_FSYNC flag on the output file to make writes synchronous.
+.It Cm sync
+Set the O_SYNC flag on the output file to make writes synchronous.
+This is synonymous with the
+.Cm fsync
+value.
+.It Cm direct
+Set the O_DIRECT flag on the output file to make writes bypass any local caching.
+.El
+.It Cm oseek Ns = Ns Ar n
+Seek on the output file
+.Ar n
+blocks.
+This is synonymous with
+.Cm seek Ns = Ns Ar n .
+.It Cm seek Ns = Ns Ar n
+Seek
+.Ar n
+blocks from the beginning of the output before copying.
+On non-tape devices, an
+.Xr lseek 2
+operation is used.
+Otherwise, existing blocks are read and the data discarded.
+If the user does not have read permission for the tape, it is positioned
+using the tape
+.Xr ioctl 2
+function calls.
+If the seek operation is past the end of file, space from the current
+end of file to the specified offset is filled with blocks of
+.Dv NUL
+bytes.
+.It Cm skip Ns = Ns Ar n
+Skip
+.Ar n
+blocks from the beginning of the input before copying.
+On input which supports seeks, an
+.Xr lseek 2
+operation is used.
+Otherwise, input data is read and discarded.
+For pipes, the correct number of bytes is read.
+For all other devices, the correct number of blocks is read without
+distinguishing between a partial or complete block being read.
+.It Cm speed Ns = Ns Ar n
+Limit the copying speed to
+.Ar n
+bytes per second.
+.It Cm status Ns = Ns Ar value
+Where
+.Cm value
+is one of the symbols from the following list.
+.Bl -tag -width "progress"
+.It Cm noxfer
+Do not print the transfer statistics as the last line of status output.
+.It Cm none
+Do not print the status output.
+Error messages are shown; informational messages are not.
+.It Cm progress
+Print basic transfer statistics once per second.
+.El
+.It Cm conv Ns = Ns Ar value Ns Op , Ns Ar value ...
+Where
+.Cm value
+is one of the symbols from the following list.
+.Bl -tag -width "unblock"
+.It Cm ascii , oldascii
+The same as the
+.Cm unblock
+value except that characters are translated from
+.Tn EBCDIC
+to
+.Tn ASCII
+before the
+records are converted.
+(These values imply
+.Cm unblock
+if the operand
+.Cm cbs
+is also specified.)
+There are two conversion maps for
+.Tn ASCII .
+The value
+.Cm ascii
+specifies the recommended one which is compatible with
+.At V .
+The value
+.Cm oldascii
+specifies the one used in historic
+.At
+and
+.No pre- Ns Bx 4.3 reno
+systems.
+.It Cm block
+Treats the input as a sequence of newline or end-of-file terminated variable
+length records independent of input and output block boundaries.
+Any trailing newline character is discarded.
+Each input record is converted to a fixed length output record where the
+length is specified by the
+.Cm cbs
+operand.
+Input records shorter than the conversion record size are padded with spaces.
+Input records longer than the conversion record size are truncated.
+The number of truncated input records, if any, are reported to the standard
+error output at the completion of the copy.
+.It Cm ebcdic , ibm , oldebcdic , oldibm
+The same as the
+.Cm block
+value except that characters are translated from
+.Tn ASCII
+to
+.Tn EBCDIC
+after the
+records are converted.
+(These values imply
+.Cm block
+if the operand
+.Cm cbs
+is also specified.)
+There are four conversion maps for
+.Tn EBCDIC .
+The value
+.Cm ebcdic
+specifies the recommended one which is compatible with
+.At V .
+The value
+.Cm ibm
+is a slightly different mapping, which is compatible with the
+.At V
+.Cm ibm
+value.
+The values
+.Cm oldebcdic
+and
+.Cm oldibm
+are maps used in historic
+.At
+and
+.No pre- Ns Bx 4.3 reno
+systems.
+.It Cm fdatasync
+Perform an
+.Xr fdatasync 2
+on the output file before closing it.
+.It Cm fsync
+Perform an
+.Xr fsync 2
+on the output file before closing it.
+.It Cm lcase
+Transform uppercase characters into lowercase characters.
+.It Cm pareven , parnone , parodd , parset
+Output data with the specified parity.
+The parity bit on input is stripped unless
+.Tn EBCDIC
+to
+.Tn ASCII
+conversions is also specified.
+.It Cm noerror
+Do not stop processing on an input error.
+When an input error occurs, a diagnostic message followed by 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 the
+.Cm sync
+conversion is also specified, any missing input data will be replaced
+with
+.Dv NUL
+bytes (or with spaces if a block oriented conversion value was
+specified) and processed as a normal input buffer.
+If the
+.Cm fillchar
+option is specified, the fill character provided on the command line
+will override
+the automatic selection of the fill character.
+If the
+.Cm sync
+conversion is not specified, the input block is omitted from the output.
+On input files which are not tapes or pipes, the file offset
+will be positioned past the block in which the error occurred using
+.Xr lseek 2 .
+.It Cm notrunc
+Do not truncate the output file.
+This will preserve any blocks in the output file not explicitly written
+by
+.Nm .
+The
+.Cm notrunc
+value is not supported for tapes.
+.It Cm osync
+Pad the final output block to the full output block size.
+If the input file is not a multiple of the output block size
+after conversion, this conversion forces the final output block
+to be the same size as preceding blocks for use on devices that require
+regularly sized blocks to be written.
+This option is incompatible with use of the
+.Cm bs Ns = Ns Ar n
+block size specification.
+.It Cm sparse
+If one or more output blocks would consist solely of
+.Dv NUL
+bytes, try to seek the output file by the required space instead of
+filling them with
+.Dv NUL Ns s ,
+resulting in a sparse file.
+.It Cm swab
+Swap every pair of input bytes.
+If an input buffer has an odd number of bytes, the last byte will be
+ignored during swapping.
+.It Cm sync
+Pad every input block to the input buffer size.
+Spaces are used for pad bytes if a block oriented conversion value is
+specified, otherwise
+.Dv NUL
+bytes are used.
+.It Cm ucase
+Transform lowercase characters into uppercase characters.
+.It Cm unblock
+Treats the input as a sequence of fixed length records independent of input
+and output block boundaries.
+The length of the input records is specified by the
+.Cm cbs
+operand.
+Any trailing space characters are discarded and a newline character is
+appended.
+.El
+.El
+.Pp
+Where sizes or speed are specified, a decimal, octal, or hexadecimal number of
+bytes is expected.
+If the number ends with a
+.Dq Li b ,
+.Dq Li k ,
+.Dq Li m ,
+.Dq Li g ,
+.Dq Li t ,
+.Dq Li p ,
+or
+.Dq Li w ,
+the
+number is multiplied by 512, 1024 (1K), 1048576 (1M), 1073741824 (1G),
+1099511627776 (1T), 1125899906842624 (1P)
+or the number of bytes in an integer, respectively.
+Two or more numbers may be separated by an
+.Dq Li x
+to indicate a product.
+.Pp
+When finished,
+.Nm
+displays the number of complete and partial input and output blocks,
+truncated input records and odd-length byte-swapping blocks to the
+standard error output.
+A partial input block is one where less than the input block size
+was read.
+A partial output block is one where less than the output block size
+was written.
+Partial output blocks to tape devices are considered fatal errors.
+Otherwise, the rest of the block will be written.
+Partial output blocks to character devices will produce a warning message.
+A truncated input block is one where a variable length record oriented
+conversion value was specified and the input line was too long to
+fit in the conversion record or was not newline terminated.
+.Pp
+Normally, data resulting from input or conversion or both are aggregated
+into output blocks of the specified size.
+After the end of input is reached, any remaining output is written as
+a block.
+This means that the final output block may be shorter than the output
+block size.
+.Pp
+If
+.Nm
+receives a
+.Dv SIGINFO
+(see the
+.Cm status
+argument for
+.Xr stty 1 )
+signal, 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
+.Nm
+receives a
+.Dv SIGINT
+signal, the current input and output block counts will
+be written to the standard error output
+in the same format as the standard completion message and
+.Nm
+will exit.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+Check that a disk drive contains no bad blocks:
+.Pp
+.Dl "dd if=/dev/ada0 of=/dev/null bs=1m"
+.Pp
+Do a refresh of a disk drive, in order to prevent presently
+recoverable read errors from progressing into unrecoverable read errors:
+.Pp
+.Dl "dd if=/dev/ada0 of=/dev/ada0 bs=1m"
+.Pp
+Remove parity bit from a file:
+.Pp
+.Dl "dd if=file conv=parnone of=file.txt"
+.Pp
+Check for (even) parity errors on a file:
+.Pp
+.Dl "dd if=file conv=pareven | cmp -x - file"
+.Pp
+To create an image of a Mode-1 CD-ROM, which is a commonly used format
+for data CD-ROM disks, use a block size of 2048 bytes:
+.Pp
+.Dl "dd if=/dev/cd0 of=filename.iso bs=2048"
+.Pp
+Write a filesystem image to a memory stick, padding the end with zeros,
+if necessary, to a 1MiB boundary:
+.Pp
+.Dl "dd if=memstick.img of=/dev/da0 bs=1m conv=noerror,sync"
+.Sh SEE ALSO
+.Xr cp 1 ,
+.Xr mt 1 ,
+.Xr recoverdisk 1 ,
+.Xr tr 1 ,
+.Xr geom 4 ,
+.Xr trim 8
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be a superset of the
+.St -p1003.2
+standard.
+The
+.Cm files
+and
+.Cm status
+operands and the
+.Cm ascii ,
+.Cm ebcdic ,
+.Cm ibm ,
+.Cm oldascii ,
+.Cm oldebcdic
+and
+.Cm oldibm
+values are extensions to the
+.Tn POSIX
+standard.
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v5 .
+.Sh BUGS
+Protection mechanisms in the
+.Xr geom 4
+subsystem might prevent the super-user from writing blocks to a disk.
+Instructions for temporarily disabling these protection mechanisms can be
+found in the
+.Xr geom 4
+man page.
diff --git a/bin/dd/dd.c b/bin/dd/dd.c
new file mode 100644
index 000000000000..c43645fa0073
--- /dev/null
+++ b/bin/dd/dd.c
@@ -0,0 +1,644 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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.
+ */
+
+#if 0
+#ifndef lint
+static char const copyright[] =
+"@(#) Copyright (c) 1991, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94";
+#endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/capsicum.h>
+#include <sys/conf.h>
+#include <sys/disklabel.h>
+#include <sys/filio.h>
+#include <sys/mtio.h>
+#include <sys/time.h>
+
+#include <assert.h>
+#include <capsicum_helpers.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "dd.h"
+#include "extern.h"
+
+static void dd_close(void);
+static void dd_in(void);
+static void getfdtype(IO *);
+static void setup(void);
+
+IO in, out; /* input/output state */
+STAT st; /* statistics */
+void (*cfunc)(void); /* conversion function */
+uintmax_t cpy_cnt; /* # of blocks to copy */
+static off_t pending = 0; /* pending seek if sparse */
+uint64_t ddflags = 0; /* conversion options */
+size_t cbsz; /* conversion block size */
+uintmax_t files_cnt = 1; /* # of files to copy */
+const u_char *ctab; /* conversion table */
+char fill_char; /* Character to fill with if defined */
+size_t speed = 0; /* maximum speed, in bytes per second */
+volatile sig_atomic_t need_summary;
+volatile sig_atomic_t need_progress;
+
+int
+main(int argc __unused, char *argv[])
+{
+ struct itimerval itv = { { 1, 0 }, { 1, 0 } }; /* SIGALARM every second, if needed */
+
+ (void)setlocale(LC_CTYPE, "");
+ jcl(argv);
+ setup();
+
+ caph_cache_catpages();
+ if (caph_enter() < 0)
+ err(1, "unable to enter capability mode");
+
+ (void)signal(SIGINFO, siginfo_handler);
+ if (ddflags & C_PROGRESS) {
+ (void)signal(SIGALRM, sigalarm_handler);
+ setitimer(ITIMER_REAL, &itv, NULL);
+ }
+ (void)signal(SIGINT, terminate);
+
+ atexit(summary);
+
+ while (files_cnt--)
+ dd_in();
+
+ dd_close();
+ /*
+ * Some devices such as cfi(4) may perform significant amounts
+ * of work when a write descriptor is closed. Close the out
+ * descriptor explicitly so that the summary handler (called
+ * from an atexit() hook) includes this work.
+ */
+ if (close(out.fd) == -1 && errno != EINTR)
+ err(1, "close");
+ exit(0);
+}
+
+static int
+parity(u_char c)
+{
+ int i;
+
+ i = c ^ (c >> 1) ^ (c >> 2) ^ (c >> 3) ^
+ (c >> 4) ^ (c >> 5) ^ (c >> 6) ^ (c >> 7);
+ return (i & 1);
+}
+
+static void
+setup(void)
+{
+ u_int cnt;
+ int iflags, oflags;
+ cap_rights_t rights;
+ unsigned long cmds[] = { FIODTYPE, MTIOCTOP };
+
+ if (in.name == NULL) {
+ in.name = "stdin";
+ in.fd = STDIN_FILENO;
+ } else {
+ iflags = 0;
+ if (ddflags & C_IDIRECT)
+ iflags |= O_DIRECT;
+ in.fd = open(in.name, O_RDONLY | iflags, 0);
+ if (in.fd == -1)
+ err(1, "%s", in.name);
+ }
+
+ getfdtype(&in);
+
+ cap_rights_init(&rights, CAP_READ, CAP_SEEK);
+ if (caph_rights_limit(in.fd, &rights) == -1)
+ err(1, "unable to limit capability rights");
+
+ if (files_cnt > 1 && !(in.flags & ISTAPE))
+ errx(1, "files is not supported for non-tape devices");
+
+ cap_rights_set(&rights, CAP_FTRUNCATE, CAP_IOCTL, CAP_WRITE);
+ if (ddflags & (C_FDATASYNC | C_FSYNC))
+ cap_rights_set(&rights, CAP_FSYNC);
+ if (out.name == NULL) {
+ /* No way to check for read access here. */
+ out.fd = STDOUT_FILENO;
+ out.name = "stdout";
+ if (ddflags & C_OFSYNC) {
+ oflags = fcntl(out.fd, F_GETFL);
+ if (oflags == -1)
+ err(1, "unable to get fd flags for stdout");
+ oflags |= O_FSYNC;
+ if (fcntl(out.fd, F_SETFL, oflags) == -1)
+ err(1, "unable to set fd flags for stdout");
+ }
+ } else {
+ oflags = O_CREAT;
+ if (!(ddflags & (C_SEEK | C_NOTRUNC)))
+ oflags |= O_TRUNC;
+ if (ddflags & C_OFSYNC)
+ oflags |= O_FSYNC;
+ if (ddflags & C_ODIRECT)
+ oflags |= O_DIRECT;
+ out.fd = open(out.name, O_RDWR | oflags, DEFFILEMODE);
+ /*
+ * 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 == -1) {
+ out.fd = open(out.name, O_WRONLY | oflags, DEFFILEMODE);
+ out.flags |= NOREAD;
+ cap_rights_clear(&rights, CAP_READ);
+ }
+ if (out.fd == -1)
+ err(1, "%s", out.name);
+ }
+
+ getfdtype(&out);
+
+ if (caph_rights_limit(out.fd, &rights) == -1)
+ err(1, "unable to limit capability rights");
+ if (caph_ioctls_limit(out.fd, cmds, nitems(cmds)) == -1)
+ err(1, "unable to limit capability rights");
+
+ if (in.fd != STDIN_FILENO && out.fd != STDIN_FILENO) {
+ if (caph_limit_stdin() == -1)
+ err(1, "unable to limit capability rights");
+ }
+
+ if (in.fd != STDOUT_FILENO && out.fd != STDOUT_FILENO) {
+ if (caph_limit_stdout() == -1)
+ err(1, "unable to limit capability rights");
+ }
+
+ if (in.fd != STDERR_FILENO && out.fd != STDERR_FILENO) {
+ if (caph_limit_stderr() == -1)
+ err(1, "unable to limit capability rights");
+ }
+
+ /*
+ * Allocate space for the input and output buffers. If not doing
+ * record oriented I/O, only need a single buffer.
+ */
+ if (!(ddflags & (C_BLOCK | C_UNBLOCK))) {
+ if ((in.db = malloc((size_t)out.dbsz + in.dbsz - 1)) == NULL)
+ err(1, "input buffer");
+ out.db = in.db;
+ } else if ((in.db = malloc(MAX((size_t)in.dbsz, cbsz) + cbsz)) == NULL ||
+ (out.db = malloc(out.dbsz + cbsz)) == NULL)
+ err(1, "output buffer");
+
+ /* dbp is the first free position in each buffer. */
+ in.dbp = in.db;
+ out.dbp = out.db;
+
+ /* Position the input/output streams. */
+ if (in.offset)
+ pos_in();
+ if (out.offset)
+ pos_out();
+
+ /*
+ * Truncate the output file. If it fails on a type of output file
+ * that it should _not_ fail on, error out.
+ */
+ if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK) &&
+ out.flags & ISTRUNC)
+ if (ftruncate(out.fd, out.offset * out.dbsz) == -1)
+ err(1, "truncating %s", out.name);
+
+ if (ddflags & (C_LCASE | C_UCASE | C_ASCII | C_EBCDIC | C_PARITY)) {
+ if (ctab != NULL) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = ctab[cnt];
+ } else {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = cnt;
+ }
+ if ((ddflags & C_PARITY) && !(ddflags & C_ASCII)) {
+ /*
+ * If the input is not EBCDIC, and we do parity
+ * processing, strip input parity.
+ */
+ for (cnt = 200; cnt <= 0377; ++cnt)
+ casetab[cnt] = casetab[cnt & 0x7f];
+ }
+ if (ddflags & C_LCASE) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = tolower(casetab[cnt]);
+ } else if (ddflags & C_UCASE) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = toupper(casetab[cnt]);
+ }
+ if ((ddflags & C_PARITY)) {
+ /*
+ * This should strictly speaking be a no-op, but I
+ * wonder what funny LANG settings could get us.
+ */
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = casetab[cnt] & 0x7f;
+ }
+ if ((ddflags & C_PARSET)) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = casetab[cnt] | 0x80;
+ }
+ if ((ddflags & C_PAREVEN)) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ if (parity(casetab[cnt]))
+ casetab[cnt] = casetab[cnt] | 0x80;
+ }
+ if ((ddflags & C_PARODD)) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ if (!parity(casetab[cnt]))
+ casetab[cnt] = casetab[cnt] | 0x80;
+ }
+
+ ctab = casetab;
+ }
+
+ if (clock_gettime(CLOCK_MONOTONIC, &st.start))
+ err(1, "clock_gettime");
+}
+
+static void
+getfdtype(IO *io)
+{
+ struct stat sb;
+ int type;
+
+ if (fstat(io->fd, &sb) == -1)
+ err(1, "%s", io->name);
+ if (S_ISREG(sb.st_mode))
+ io->flags |= ISTRUNC;
+ if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) {
+ if (ioctl(io->fd, FIODTYPE, &type) == -1) {
+ err(1, "%s", io->name);
+ } else {
+ if (type & D_TAPE)
+ io->flags |= ISTAPE;
+ else if (type & (D_DISK | D_MEM))
+ io->flags |= ISSEEK;
+ if (S_ISCHR(sb.st_mode) && (type & D_TAPE) == 0)
+ io->flags |= ISCHR;
+ }
+ return;
+ }
+ errno = 0;
+ if (lseek(io->fd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE)
+ io->flags |= ISPIPE;
+ else
+ io->flags |= ISSEEK;
+}
+
+/*
+ * Limit the speed by adding a delay before every block read.
+ * The delay (t_usleep) is equal to the time computed from block
+ * size and the specified speed limit (t_target) minus the time
+ * spent on actual read and write operations (t_io).
+ */
+static void
+speed_limit(void)
+{
+ static double t_prev, t_usleep;
+ double t_now, t_io, t_target;
+
+ t_now = secs_elapsed();
+ t_io = t_now - t_prev - t_usleep;
+ t_target = (double)in.dbsz / (double)speed;
+ t_usleep = t_target - t_io;
+ if (t_usleep > 0)
+ usleep(t_usleep * 1000000);
+ else
+ t_usleep = 0;
+ t_prev = t_now;
+}
+
+static void
+swapbytes(void *v, size_t len)
+{
+ unsigned char *p = v;
+ unsigned char t;
+
+ while (len > 1) {
+ t = p[0];
+ p[0] = p[1];
+ p[1] = t;
+ p += 2;
+ len -= 2;
+ }
+}
+
+static void
+dd_in(void)
+{
+ ssize_t n;
+
+ for (;;) {
+ switch (cpy_cnt) {
+ case -1: /* count=0 was specified */
+ return;
+ case 0:
+ break;
+ default:
+ if (st.in_full + st.in_part >= (uintmax_t)cpy_cnt)
+ return;
+ break;
+ }
+
+ if (speed > 0)
+ speed_limit();
+
+ /*
+ * Zero the buffer first if sync; if doing block operations,
+ * use spaces.
+ */
+ if (ddflags & C_SYNC) {
+ if (ddflags & C_FILL)
+ memset(in.dbp, fill_char, in.dbsz);
+ else if (ddflags & (C_BLOCK | C_UNBLOCK))
+ memset(in.dbp, ' ', in.dbsz);
+ else
+ memset(in.dbp, 0, in.dbsz);
+ }
+
+ in.dbrcnt = 0;
+fill:
+ n = read(in.fd, in.dbp + in.dbrcnt, in.dbsz - in.dbrcnt);
+
+ /* EOF */
+ if (n == 0 && in.dbrcnt == 0)
+ return;
+
+ /* Read error */
+ if (n == -1) {
+ /*
+ * If noerror not specified, die. POSIX requires that
+ * the warning message be followed by an I/O display.
+ */
+ if (!(ddflags & C_NOERROR))
+ err(1, "%s", in.name);
+ warn("%s", in.name);
+ summary();
+
+ /*
+ * If it's a seekable file descriptor, seek past the
+ * error. If your OS doesn't do the right thing for
+ * raw disks this section should be modified to re-read
+ * in sector size chunks.
+ */
+ if (in.flags & ISSEEK &&
+ lseek(in.fd, (off_t)in.dbsz, SEEK_CUR))
+ warn("%s", in.name);
+
+ /* If sync not specified, omit block and continue. */
+ if (!(ddflags & C_SYNC))
+ continue;
+ }
+
+ /* If conv=sync, use the entire block. */
+ if (ddflags & C_SYNC)
+ n = in.dbsz;
+
+ /* Count the bytes read for this block. */
+ in.dbrcnt += n;
+
+ /* Count the number of full and partial blocks. */
+ if (in.dbrcnt == in.dbsz)
+ ++st.in_full;
+ else if (ddflags & C_IFULLBLOCK && n != 0)
+ goto fill; /* these don't count */
+ else
+ ++st.in_part;
+
+ /* Count the total bytes read for this file. */
+ in.dbcnt += in.dbrcnt;
+
+ /*
+ * POSIX states that if bs is set and no other conversions
+ * than noerror, notrunc or sync are specified, the block
+ * is output without buffering as it is read.
+ */
+ if ((ddflags & ~(C_NOERROR | C_NOTRUNC | C_SYNC)) == C_BS) {
+ out.dbcnt = in.dbcnt;
+ dd_out(1);
+ in.dbcnt = 0;
+ continue;
+ }
+
+ if (ddflags & C_SWAB) {
+ if ((n = in.dbrcnt) & 1) {
+ ++st.swab;
+ --n;
+ }
+ swapbytes(in.dbp, (size_t)n);
+ }
+
+ /* Advance to the next block. */
+ in.dbp += in.dbrcnt;
+ (*cfunc)();
+ if (need_summary)
+ summary();
+ if (need_progress)
+ progress();
+ }
+}
+
+/*
+ * Clean up any remaining I/O and flush output. If necessary, the output file
+ * is truncated.
+ */
+static void
+dd_close(void)
+{
+ if (cfunc == def)
+ def_close();
+ else if (cfunc == block)
+ block_close();
+ else if (cfunc == unblock)
+ unblock_close();
+ if (ddflags & C_OSYNC && out.dbcnt && out.dbcnt < out.dbsz) {
+ if (ddflags & C_FILL)
+ memset(out.dbp, fill_char, out.dbsz - out.dbcnt);
+ else if (ddflags & (C_BLOCK | C_UNBLOCK))
+ memset(out.dbp, ' ', out.dbsz - out.dbcnt);
+ else
+ memset(out.dbp, 0, out.dbsz - out.dbcnt);
+ out.dbcnt = out.dbsz;
+ }
+ if (out.dbcnt || pending)
+ dd_out(1);
+
+ /*
+ * If the file ends with a hole, ftruncate it to extend its size
+ * up to the end of the hole (without having to write any data).
+ */
+ if (out.seek_offset > 0 && (out.flags & ISTRUNC)) {
+ if (ftruncate(out.fd, out.seek_offset) == -1)
+ err(1, "truncating %s", out.name);
+ }
+
+ if (ddflags & C_FSYNC) {
+ if (fsync(out.fd) == -1)
+ err(1, "fsyncing %s", out.name);
+ } else if (ddflags & C_FDATASYNC) {
+ if (fdatasync(out.fd) == -1)
+ err(1, "fdatasyncing %s", out.name);
+ }
+}
+
+void
+dd_out(int force)
+{
+ u_char *outp;
+ size_t cnt, n;
+ ssize_t nw;
+ static int warned;
+ int sparse;
+
+ /*
+ * Write one or more blocks out. The common case is writing a full
+ * output block in a single write; increment the full block stats.
+ * Otherwise, we're into partial block writes. If a partial write,
+ * and it's a character device, just warn. If a tape device, quit.
+ *
+ * The partial writes represent two cases. 1: Where the input block
+ * was less than expected so the output block was less than expected.
+ * 2: Where the input block was the right size but we were forced to
+ * write the block in multiple chunks. The original versions of dd(1)
+ * never wrote a block in more than a single write, so the latter case
+ * never happened.
+ *
+ * One special case is if we're forced to do the write -- in that case
+ * we play games with the buffer size, and it's usually a partial write.
+ */
+ outp = out.db;
+
+ /*
+ * If force, first try to write all pending data, else try to write
+ * just one block. Subsequently always write data one full block at
+ * a time at most.
+ */
+ for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) {
+ cnt = n;
+ do {
+ sparse = 0;
+ if (ddflags & C_SPARSE) {
+ /* Is buffer sparse? */
+ sparse = BISZERO(outp, cnt);
+ }
+ if (sparse && !force) {
+ pending += cnt;
+ nw = cnt;
+ } else {
+ if (pending != 0) {
+ /*
+ * Seek past hole. Note that we need to record the
+ * reached offset, because we might have no more data
+ * to write, in which case we'll need to call
+ * ftruncate to extend the file size.
+ */
+ out.seek_offset = lseek(out.fd, pending, SEEK_CUR);
+ if (out.seek_offset == -1)
+ err(2, "%s: seek error creating sparse file",
+ out.name);
+ pending = 0;
+ }
+ if (cnt) {
+ nw = write(out.fd, outp, cnt);
+ out.seek_offset = 0;
+ } else {
+ return;
+ }
+ }
+
+ if (nw <= 0) {
+ if (nw == 0)
+ errx(1, "%s: end of device", out.name);
+ if (errno != EINTR)
+ err(1, "%s", out.name);
+ nw = 0;
+ }
+
+ outp += nw;
+ st.bytes += nw;
+
+ if ((size_t)nw == n && n == (size_t)out.dbsz)
+ ++st.out_full;
+ else
+ ++st.out_part;
+
+ if ((size_t) nw != cnt) {
+ if (out.flags & ISTAPE)
+ errx(1, "%s: short write on tape device",
+ out.name);
+ if (out.flags & ISCHR && !warned) {
+ warned = 1;
+ warnx("%s: short write on character device",
+ out.name);
+ }
+ }
+
+ cnt -= nw;
+ } while (cnt != 0);
+
+ if ((out.dbcnt -= n) < out.dbsz)
+ break;
+ }
+
+ /* Reassemble the output block. */
+ if (out.dbcnt)
+ (void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt);
+ out.dbp = out.db + out.dbcnt;
+}
diff --git a/bin/dd/dd.h b/bin/dd/dd.h
new file mode 100644
index 000000000000..ea606f288f3f
--- /dev/null
+++ b/bin/dd/dd.h
@@ -0,0 +1,115 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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.
+ *
+ * @(#)dd.h 8.3 (Berkeley) 4/2/94
+ * $FreeBSD$
+ */
+
+/* Input/output stream state. */
+typedef struct {
+ u_char *db; /* buffer address */
+ u_char *dbp; /* current buffer I/O address */
+ ssize_t dbcnt; /* current buffer byte count */
+ ssize_t dbrcnt; /* last read byte count */
+ ssize_t dbsz; /* block size */
+
+#define ISCHR 0x01 /* character device (warn on short) */
+#define ISPIPE 0x02 /* pipe-like (see position.c) */
+#define ISTAPE 0x04 /* tape */
+#define ISSEEK 0x08 /* valid to seek on */
+#define NOREAD 0x10 /* not readable */
+#define ISTRUNC 0x20 /* valid to ftruncate() */
+ u_int flags;
+
+ const char *name; /* name */
+ int fd; /* file descriptor */
+ off_t offset; /* # of blocks to skip */
+ off_t seek_offset; /* offset of last seek past output hole */
+} IO;
+
+typedef struct {
+ uintmax_t in_full; /* # of full input blocks */
+ uintmax_t in_part; /* # of partial input blocks */
+ uintmax_t out_full; /* # of full output blocks */
+ uintmax_t out_part; /* # of partial output blocks */
+ uintmax_t trunc; /* # of truncated records */
+ uintmax_t swab; /* # of odd-length swab blocks */
+ uintmax_t bytes; /* # of bytes written */
+ struct timespec start; /* start time of dd */
+} STAT;
+
+/* Flags (in ddflags). */
+#define C_ASCII 0x0000000000000001ULL
+#define C_BLOCK 0x0000000000000002ULL
+#define C_BS 0x0000000000000004ULL
+#define C_CBS 0x0000000000000008ULL
+#define C_COUNT 0x0000000000000010ULL
+#define C_EBCDIC 0x0000000000000020ULL
+#define C_FILES 0x0000000000000040ULL
+#define C_IBS 0x0000000000000080ULL
+#define C_IF 0x0000000000000100ULL
+#define C_LCASE 0x0000000000000200ULL
+#define C_NOERROR 0x0000000000000400ULL
+#define C_NOTRUNC 0x0000000000000800ULL
+#define C_OBS 0x0000000000001000ULL
+#define C_OF 0x0000000000002000ULL
+#define C_OSYNC 0x0000000000004000ULL
+#define C_PAREVEN 0x0000000000008000ULL
+#define C_PARNONE 0x0000000000010000ULL
+#define C_PARODD 0x0000000000020000ULL
+#define C_PARSET 0x0000000000040000ULL
+#define C_SEEK 0x0000000000080000ULL
+#define C_SKIP 0x0000000000100000ULL
+#define C_SPARSE 0x0000000000200000ULL
+#define C_SWAB 0x0000000000400000ULL
+#define C_SYNC 0x0000000000800000ULL
+#define C_UCASE 0x0000000001000000ULL
+#define C_UNBLOCK 0x0000000002000000ULL
+#define C_FILL 0x0000000004000000ULL
+#define C_STATUS 0x0000000008000000ULL
+#define C_NOXFER 0x0000000010000000ULL
+#define C_NOINFO 0x0000000020000000ULL
+#define C_PROGRESS 0x0000000040000000ULL
+#define C_FSYNC 0x0000000080000000ULL
+#define C_FDATASYNC 0x0000000100000000ULL
+#define C_OFSYNC 0x0000000200000000ULL
+#define C_IFULLBLOCK 0x0000000400000000ULL
+#define C_IDIRECT 0x0000000800000000ULL
+#define C_ODIRECT 0x0000001000000000ULL
+
+#define C_PARITY (C_PAREVEN | C_PARODD | C_PARNONE | C_PARSET)
+
+#define BISZERO(p, s) ((s) > 0 && *((const char *)p) == 0 && !memcmp( \
+ (const void *)(p), (const void *) \
+ ((const char *)p + 1), (s) - 1))
diff --git a/bin/dd/extern.h b/bin/dd/extern.h
new file mode 100644
index 000000000000..07c08e2ef8f2
--- /dev/null
+++ b/bin/dd/extern.h
@@ -0,0 +1,71 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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.
+ *
+ * @(#)extern.h 8.3 (Berkeley) 4/2/94
+ * $FreeBSD$
+ */
+
+void block(void);
+void block_close(void);
+void dd_out(int);
+void def(void);
+void def_close(void);
+void jcl(char **);
+void pos_in(void);
+void pos_out(void);
+double secs_elapsed(void);
+void progress(void);
+void summary(void);
+void sigalarm_handler(int);
+void siginfo_handler(int);
+void terminate(int);
+void unblock(void);
+void unblock_close(void);
+
+extern IO in, out;
+extern STAT st;
+extern void (*cfunc)(void);
+extern uintmax_t cpy_cnt;
+extern size_t cbsz;
+extern uint64_t ddflags;
+extern size_t speed;
+extern uintmax_t files_cnt;
+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 char fill_char;
+extern volatile sig_atomic_t need_summary;
+extern volatile sig_atomic_t need_progress;
diff --git a/bin/dd/gen.c b/bin/dd/gen.c
new file mode 100644
index 000000000000..d53d8fb2b5ac
--- /dev/null
+++ b/bin/dd/gen.c
@@ -0,0 +1,24 @@
+/*-
+ * This program is in the public domain
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+int
+main(int argc, char **argv)
+{
+ int i;
+
+ if (argc > 1 && !strcmp(argv[1], "189284")) {
+ fputs("ABCDEFGH", stdout);
+ for (i = 0; i < 8; i++)
+ putchar(0);
+ } else {
+ for (i = 0; i < 256; i++)
+ putchar(i);
+ }
+ return (0);
+}
diff --git a/bin/dd/misc.c b/bin/dd/misc.c
new file mode 100644
index 000000000000..405448eb1cb0
--- /dev/null
+++ b/bin/dd/misc.c
@@ -0,0 +1,157 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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 lint
+#if 0
+static char sccsid[] = "@(#)misc.c 8.3 (Berkeley) 4/2/94";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <libutil.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "dd.h"
+#include "extern.h"
+
+double
+secs_elapsed(void)
+{
+ struct timespec end, ts_res;
+ double secs, res;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &end))
+ err(1, "clock_gettime");
+ if (clock_getres(CLOCK_MONOTONIC, &ts_res))
+ err(1, "clock_getres");
+ secs = (end.tv_sec - st.start.tv_sec) + \
+ (end.tv_nsec - st.start.tv_nsec) * 1e-9;
+ res = ts_res.tv_sec + ts_res.tv_nsec * 1e-9;
+ if (secs < res)
+ secs = res;
+
+ return (secs);
+}
+
+void
+summary(void)
+{
+ double secs;
+
+ if (ddflags & C_NOINFO)
+ return;
+
+ if (ddflags & C_PROGRESS)
+ fprintf(stderr, "\n");
+
+ secs = secs_elapsed();
+
+ (void)fprintf(stderr,
+ "%ju+%ju records in\n%ju+%ju records out\n",
+ st.in_full, st.in_part, st.out_full, st.out_part);
+ if (st.swab)
+ (void)fprintf(stderr, "%ju odd length swab %s\n",
+ st.swab, (st.swab == 1) ? "block" : "blocks");
+ if (st.trunc)
+ (void)fprintf(stderr, "%ju truncated %s\n",
+ st.trunc, (st.trunc == 1) ? "block" : "blocks");
+ if (!(ddflags & C_NOXFER)) {
+ (void)fprintf(stderr,
+ "%ju bytes transferred in %.6f secs (%.0f bytes/sec)\n",
+ st.bytes, secs, st.bytes / secs);
+ }
+ need_summary = 0;
+}
+
+void
+progress(void)
+{
+ static int outlen;
+ char si[4 + 1 + 2 + 1]; /* 123 <space> <suffix> NUL */
+ char iec[4 + 1 + 3 + 1]; /* 123 <space> <suffix> NUL */
+ char persec[4 + 1 + 2 + 1]; /* 123 <space> <suffix> NUL */
+ char *buf;
+ double secs;
+
+ secs = secs_elapsed();
+ humanize_number(si, sizeof(si), (int64_t)st.bytes, "B", HN_AUTOSCALE,
+ HN_DECIMAL | HN_DIVISOR_1000);
+ humanize_number(iec, sizeof(iec), (int64_t)st.bytes, "B", HN_AUTOSCALE,
+ HN_DECIMAL | HN_IEC_PREFIXES);
+ humanize_number(persec, sizeof(persec), (int64_t)(st.bytes / secs), "B",
+ HN_AUTOSCALE, HN_DECIMAL | HN_DIVISOR_1000);
+ asprintf(&buf, " %'ju bytes (%s, %s) transferred %.3fs, %s/s",
+ (uintmax_t)st.bytes, si, iec, secs, persec);
+ outlen = fprintf(stderr, "%-*s\r", outlen, buf) - 1;
+ fflush(stderr);
+ free(buf);
+ need_progress = 0;
+}
+
+/* ARGSUSED */
+void
+siginfo_handler(int signo __unused)
+{
+
+ need_summary = 1;
+}
+
+/* ARGSUSED */
+void
+sigalarm_handler(int signo __unused)
+{
+
+ need_progress = 1;
+}
+
+/* ARGSUSED */
+void
+terminate(int sig)
+{
+
+ summary();
+ _exit(sig == 0 ? 0 : 1);
+}
diff --git a/bin/dd/position.c b/bin/dd/position.c
new file mode 100644
index 000000000000..21a100cd3b24
--- /dev/null
+++ b/bin/dd/position.c
@@ -0,0 +1,219 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * 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 lint
+#if 0
+static char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/mtio.h>
+
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "dd.h"
+#include "extern.h"
+
+static off_t
+seek_offset(IO *io)
+{
+ off_t n;
+ size_t sz;
+
+ n = io->offset;
+ sz = io->dbsz;
+
+ _Static_assert(sizeof(io->offset) == sizeof(int64_t), "64-bit off_t");
+
+ /*
+ * If the lseek offset will be negative, verify that this is a special
+ * device file. Some such files (e.g. /dev/kmem) permit "negative"
+ * offsets.
+ *
+ * Bail out if the calculation of a file offset would overflow.
+ */
+ if ((io->flags & ISCHR) == 0 && (n < 0 || n > OFF_MAX / (ssize_t)sz))
+ errx(1, "seek offsets cannot be larger than %jd",
+ (intmax_t)OFF_MAX);
+ else if ((io->flags & ISCHR) != 0 && (uint64_t)n > UINT64_MAX / sz)
+ errx(1, "seek offsets cannot be larger than %ju",
+ (uintmax_t)UINT64_MAX);
+
+ return ((off_t)( (uint64_t)n * sz ));
+}
+
+/*
+ * Position input/output data streams before starting the copy. Device type
+ * dependent. Seekable devices use lseek, and the rest position by reading.
+ * Seeking past the end of file can cause null blocks to be written to the
+ * output.
+ */
+void
+pos_in(void)
+{
+ off_t cnt;
+ int warned;
+ ssize_t nr;
+ size_t bcnt;
+
+ /* If known to be seekable, try to seek on it. */
+ if (in.flags & ISSEEK) {
+ errno = 0;
+ if (lseek(in.fd, seek_offset(&in), SEEK_CUR) == -1 &&
+ errno != 0)
+ err(1, "%s", in.name);
+ return;
+ }
+
+ /* Don't try to read a really weird amount (like negative). */
+ if (in.offset < 0)
+ errx(1, "%s: illegal offset", "iseek/skip");
+
+ /*
+ * Read the data. If a pipe, read until satisfy the number of bytes
+ * being skipped. No differentiation for reading complete and partial
+ * blocks for other devices.
+ */
+ for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) {
+ if ((nr = read(in.fd, in.db, bcnt)) > 0) {
+ if (in.flags & ISPIPE) {
+ if (!(bcnt -= nr)) {
+ bcnt = in.dbsz;
+ --cnt;
+ }
+ } else
+ --cnt;
+ if (need_summary)
+ summary();
+ if (need_progress)
+ progress();
+ continue;
+ }
+
+ if (nr == 0) {
+ if (files_cnt > 1) {
+ --files_cnt;
+ continue;
+ }
+ errx(1, "skip reached end of input");
+ }
+
+ /*
+ * Input error -- either EOF with no more files, or I/O error.
+ * If noerror not set die. POSIX requires that the warning
+ * message be followed by an I/O display.
+ */
+ if (ddflags & C_NOERROR) {
+ if (!warned) {
+ warn("%s", in.name);
+ warned = 1;
+ summary();
+ }
+ continue;
+ }
+ err(1, "%s", in.name);
+ }
+}
+
+void
+pos_out(void)
+{
+ struct mtop t_op;
+ off_t cnt;
+ ssize_t n;
+
+ /*
+ * If not a tape, try seeking on the file. Seeking on a pipe is
+ * going to fail, but don't protect the user -- they shouldn't
+ * have specified the seek operand.
+ */
+ if (out.flags & (ISSEEK | ISPIPE)) {
+ errno = 0;
+ if (lseek(out.fd, seek_offset(&out), SEEK_CUR) == -1 &&
+ errno != 0)
+ err(1, "%s", out.name);
+ return;
+ }
+
+ /* Don't try to read a really weird amount (like negative). */
+ if (out.offset < 0)
+ errx(1, "%s: illegal offset", "oseek/seek");
+
+ /* If no read access, try using mtio. */
+ if (out.flags & NOREAD) {
+ t_op.mt_op = MTFSR;
+ t_op.mt_count = out.offset;
+
+ if (ioctl(out.fd, MTIOCTOP, &t_op) == -1)
+ err(1, "%s", out.name);
+ return;
+ }
+
+ /* Read it. */
+ for (cnt = 0; cnt < out.offset; ++cnt) {
+ if ((n = read(out.fd, out.db, out.dbsz)) > 0)
+ continue;
+
+ if (n == -1)
+ err(1, "%s", out.name);
+
+ /*
+ * If reach EOF, fill with NUL characters; first, back up over
+ * the EOF mark. Note, cnt has not yet been incremented, so
+ * the EOF read does not count as a seek'd block.
+ */
+ t_op.mt_op = MTBSR;
+ t_op.mt_count = 1;
+ if (ioctl(out.fd, MTIOCTOP, &t_op) == -1)
+ err(1, "%s", out.name);
+
+ while (cnt++ < out.offset) {
+ n = write(out.fd, out.db, out.dbsz);
+ if (n == -1)
+ err(1, "%s", out.name);
+ if (n != out.dbsz)
+ errx(1, "%s: write failure", out.name);
+ }
+ break;
+ }
+}
diff --git a/bin/dd/ref.ascii b/bin/dd/ref.ascii
new file mode 100644
index 000000000000..7ff13e5a80ed
--- /dev/null
+++ b/bin/dd/ref.ascii
@@ -0,0 +1,18 @@
+$FreeBSD$
+00000000 00 01 02 03 9c 09 86 7f 97 8d 8e 0b 0c 0d 0e 0f |................|
+00000010 10 11 12 13 9d 85 08 87 18 19 92 8f 1c 1d 1e 1f |................|
+00000020 80 81 82 83 84 0a 17 1b 88 89 8a 8b 8c 05 06 07 |................|
+00000030 90 91 16 93 94 95 96 04 98 99 9a 9b 14 15 9e 1a |................|
+00000040 20 a0 a1 a2 a3 a4 a5 a6 a7 a8 d5 2e 3c 28 2b 7c | ...........<(+||
+00000050 26 a9 aa ab ac ad ae af b0 b1 21 24 2a 29 3b 7e |&.........!$*);~|
+00000060 2d 2f b2 b3 b4 b5 b6 b7 b8 b9 cb 2c 25 5f 3e 3f |-/.........,%_>?|
+00000070 ba bb bc bd be bf c0 c1 c2 60 3a 23 40 27 3d 22 |.........`:#@'="|
+00000080 c3 61 62 63 64 65 66 67 68 69 c4 c5 c6 c7 c8 c9 |.abcdefghi......|
+00000090 ca 6a 6b 6c 6d 6e 6f 70 71 72 5e cc cd ce cf d0 |.jklmnopqr^.....|
+000000a0 d1 e5 73 74 75 76 77 78 79 7a d2 d3 d4 5b d6 d7 |..stuvwxyz...[..|
+000000b0 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 5d e6 e7 |.............]..|
+000000c0 7b 41 42 43 44 45 46 47 48 49 e8 e9 ea eb ec ed |{ABCDEFGHI......|
+000000d0 7d 4a 4b 4c 4d 4e 4f 50 51 52 ee ef f0 f1 f2 f3 |}JKLMNOPQR......|
+000000e0 5c 9f 53 54 55 56 57 58 59 5a f4 f5 f6 f7 f8 f9 |\.STUVWXYZ......|
+000000f0 30 31 32 33 34 35 36 37 38 39 fa fb fc fd fe ff |0123456789......|
+00000100
diff --git a/bin/dd/ref.ebcdic b/bin/dd/ref.ebcdic
new file mode 100644
index 000000000000..605716552cab
--- /dev/null
+++ b/bin/dd/ref.ebcdic
@@ -0,0 +1,18 @@
+$FreeBSD$
+00000000 00 01 02 03 37 2d 2e 2f 16 05 25 0b 0c 0d 0e 0f |....7-./..%.....|
+00000010 10 11 12 13 3c 3d 32 26 18 19 3f 27 1c 1d 1e 1f |....<=2&..?'....|
+00000020 40 5a 7f 7b 5b 6c 50 7d 4d 5d 5c 4e 6b 60 4b 61 |@Z.{[lP}M]\Nk`Ka|
+00000030 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 7a 5e 4c 7e 6e 6f |..........z^L~no|
+00000040 7c c1 c2 c3 c4 c5 c6 c7 c8 c9 d1 d2 d3 d4 d5 d6 ||...............|
+00000050 d7 d8 d9 e2 e3 e4 e5 e6 e7 e8 e9 ad e0 bd 9a 6d |...............m|
+00000060 79 81 82 83 84 85 86 87 88 89 91 92 93 94 95 96 |y...............|
+00000070 97 98 99 a2 a3 a4 a5 a6 a7 a8 a9 c0 4f d0 5f 07 |............O._.|
+00000080 20 21 22 23 24 15 06 17 28 29 2a 2b 2c 09 0a 1b | !"#$...()*+,...|
+00000090 30 31 1a 33 34 35 36 08 38 39 3a 3b 04 14 3e e1 |01.3456.89:;..>.|
+000000a0 41 42 43 44 45 46 47 48 49 51 52 53 54 55 56 57 |ABCDEFGHIQRSTUVW|
+000000b0 58 59 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |XYbcdefghipqrstu|
+000000c0 76 77 78 80 8a 8b 8c 8d 8e 8f 90 6a 9b 9c 9d 9e |vwx........j....|
+000000d0 9f a0 aa ab ac 4a ae af b0 b1 b2 b3 b4 b5 b6 b7 |.....J..........|
+000000e0 b8 b9 ba bb bc a1 be bf ca cb cc cd ce cf da db |................|
+000000f0 dc dd de df ea eb ec ed ee ef fa fb fc fd fe ff |................|
+00000100
diff --git a/bin/dd/ref.ibm b/bin/dd/ref.ibm
new file mode 100644
index 000000000000..4836baf221aa
--- /dev/null
+++ b/bin/dd/ref.ibm
@@ -0,0 +1,18 @@
+$FreeBSD$
+00000000 00 01 02 03 37 2d 2e 2f 16 05 25 0b 0c 0d 0e 0f |....7-./..%.....|
+00000010 10 11 12 13 3c 3d 32 26 18 19 3f 27 1c 1d 1e 1f |....<=2&..?'....|
+00000020 40 5a 7f 7b 5b 6c 50 7d 4d 5d 5c 4e 6b 60 4b 61 |@Z.{[lP}M]\Nk`Ka|
+00000030 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 7a 5e 4c 7e 6e 6f |..........z^L~no|
+00000040 7c c1 c2 c3 c4 c5 c6 c7 c8 c9 d1 d2 d3 d4 d5 d6 ||...............|
+00000050 d7 d8 d9 e2 e3 e4 e5 e6 e7 e8 e9 ad e0 bd 5f 6d |.............._m|
+00000060 79 81 82 83 84 85 86 87 88 89 91 92 93 94 95 96 |y...............|
+00000070 97 98 99 a2 a3 a4 a5 a6 a7 a8 a9 c0 4f d0 a1 07 |............O...|
+00000080 20 21 22 23 24 15 06 17 28 29 2a 2b 2c 09 0a 1b | !"#$...()*+,...|
+00000090 30 31 1a 33 34 35 36 08 38 39 3a 3b 04 14 3e e1 |01.3456.89:;..>.|
+000000a0 41 42 43 44 45 46 47 48 49 51 52 53 54 55 56 57 |ABCDEFGHIQRSTUVW|
+000000b0 58 59 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |XYbcdefghipqrstu|
+000000c0 76 77 78 80 8a 8b 8c 8d 8e 8f 90 9a 9b 9c 9d 9e |vwx.............|
+000000d0 9f a0 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 |................|
+000000e0 b8 b9 ba bb bc bd be bf ca cb cc cd ce cf da db |................|
+000000f0 dc dd de df ea eb ec ed ee ef fa fb fc fd fe ff |................|
+00000100
diff --git a/bin/dd/ref.lcase b/bin/dd/ref.lcase
new file mode 100644
index 000000000000..9f9567296468
--- /dev/null
+++ b/bin/dd/ref.lcase
@@ -0,0 +1,18 @@
+$FreeBSD$
+00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
+00000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................|
+00000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | !"#$%&'()*+,-./|
+00000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f |0123456789:;<=>?|
+00000040 40 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f |@abcdefghijklmno|
+00000050 70 71 72 73 74 75 76 77 78 79 7a 5b 5c 5d 5e 5f |pqrstuvwxyz[\]^_|
+00000060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f |`abcdefghijklmno|
+00000070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f |pqrstuvwxyz{|}~.|
+00000080 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f |................|
+00000090 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f |................|
+000000a0 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af |................|
+000000b0 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf |................|
+000000c0 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf |................|
+000000d0 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df |................|
+000000e0 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef |................|
+000000f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff |................|
+00000100
diff --git a/bin/dd/ref.obs_zeroes b/bin/dd/ref.obs_zeroes
new file mode 100644
index 000000000000..473ff7cc4108
--- /dev/null
+++ b/bin/dd/ref.obs_zeroes
@@ -0,0 +1,3 @@
+$FreeBSD$
+00000000 41 42 43 44 45 46 47 48 00 00 00 00 00 00 00 00 |ABCDEFGH........|
+00000010
diff --git a/bin/dd/ref.oldascii b/bin/dd/ref.oldascii
new file mode 100644
index 000000000000..bb1ad0a7242b
--- /dev/null
+++ b/bin/dd/ref.oldascii
@@ -0,0 +1,18 @@
+$FreeBSD$
+00000000 00 01 02 03 9c 09 86 7f 97 8d 8e 0b 0c 0d 0e 0f |................|
+00000010 10 11 12 13 9d 85 08 87 18 19 92 8f 1c 1d 1e 1f |................|
+00000020 80 81 82 83 84 0a 17 1b 88 89 8a 8b 8c 05 06 07 |................|
+00000030 90 91 16 93 94 95 96 04 98 99 9a 9b 14 15 9e 1a |................|
+00000040 20 a0 a1 a2 a3 a4 a5 a6 a7 a8 5b 2e 3c 28 2b 21 | .........[.<(+!|
+00000050 26 a9 aa ab ac ad ae af b0 b1 5d 24 2a 29 3b 5e |&.........]$*);^|
+00000060 2d 2f b2 b3 b4 b5 b6 b7 b8 b9 7c 2c 25 5f 3e 3f |-/........|,%_>?|
+00000070 ba bb bc bd be bf c0 c1 c2 60 3a 23 40 27 3d 22 |.........`:#@'="|
+00000080 c3 61 62 63 64 65 66 67 68 69 c4 c5 c6 c7 c8 c9 |.abcdefghi......|
+00000090 ca 6a 6b 6c 6d 6e 6f 70 71 72 cb cc cd ce cf d0 |.jklmnopqr......|
+000000a0 d1 7e 73 74 75 76 77 78 79 7a d2 d3 d4 d5 d6 d7 |.~stuvwxyz......|
+000000b0 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 |................|
+000000c0 7b 41 42 43 44 45 46 47 48 49 e8 e9 ea eb ec ed |{ABCDEFGHI......|
+000000d0 7d 4a 4b 4c 4d 4e 4f 50 51 52 ee ef f0 f1 f2 f3 |}JKLMNOPQR......|
+000000e0 5c 9f 53 54 55 56 57 58 59 5a f4 f5 f6 f7 f8 f9 |\.STUVWXYZ......|
+000000f0 30 31 32 33 34 35 36 37 38 39 fa fb fc fd fe ff |0123456789......|
+00000100
diff --git a/bin/dd/ref.oldebcdic b/bin/dd/ref.oldebcdic
new file mode 100644
index 000000000000..4a7fde7e65b6
--- /dev/null
+++ b/bin/dd/ref.oldebcdic
@@ -0,0 +1,18 @@
+$FreeBSD$
+00000000 00 01 02 03 37 2d 2e 2f 16 05 25 0b 0c 0d 0e 0f |....7-./..%.....|
+00000010 10 11 12 13 3c 3d 32 26 18 19 3f 27 1c 1d 1e 1f |....<=2&..?'....|
+00000020 40 4f 7f 7b 5b 6c 50 7d 4d 5d 5c 4e 6b 60 4b 61 |@O.{[lP}M]\Nk`Ka|
+00000030 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 7a 5e 4c 7e 6e 6f |..........z^L~no|
+00000040 7c c1 c2 c3 c4 c5 c6 c7 c8 c9 d1 d2 d3 d4 d5 d6 ||...............|
+00000050 d7 d8 d9 e2 e3 e4 e5 e6 e7 e8 e9 4a e0 5a 5f 6d |...........J.Z_m|
+00000060 79 81 82 83 84 85 86 87 88 89 91 92 93 94 95 96 |y...............|
+00000070 97 98 99 a2 a3 a4 a5 a6 a7 a8 a9 c0 6a d0 a1 07 |............j...|
+00000080 20 21 22 23 24 15 06 17 28 29 2a 2b 2c 09 0a 1b | !"#$...()*+,...|
+00000090 30 31 1a 33 34 35 36 08 38 39 3a 3b 04 14 3e e1 |01.3456.89:;..>.|
+000000a0 41 42 43 44 45 46 47 48 49 51 52 53 54 55 56 57 |ABCDEFGHIQRSTUVW|
+000000b0 58 59 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |XYbcdefghipqrstu|
+000000c0 76 77 78 80 8a 8b 8c 8d 8e 8f 90 9a 9b 9c 9d 9e |vwx.............|
+000000d0 9f a0 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 |................|
+000000e0 b8 b9 ba bb bc bd be bf ca cb cc cd ce cf da db |................|
+000000f0 dc dd de df ea eb ec ed ee ef fa fb fc fd fe ff |................|
+00000100
diff --git a/bin/dd/ref.oldibm b/bin/dd/ref.oldibm
new file mode 100644
index 000000000000..4836baf221aa
--- /dev/null
+++ b/bin/dd/ref.oldibm
@@ -0,0 +1,18 @@
+$FreeBSD$
+00000000 00 01 02 03 37 2d 2e 2f 16 05 25 0b 0c 0d 0e 0f |....7-./..%.....|
+00000010 10 11 12 13 3c 3d 32 26 18 19 3f 27 1c 1d 1e 1f |....<=2&..?'....|
+00000020 40 5a 7f 7b 5b 6c 50 7d 4d 5d 5c 4e 6b 60 4b 61 |@Z.{[lP}M]\Nk`Ka|
+00000030 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 7a 5e 4c 7e 6e 6f |..........z^L~no|
+00000040 7c c1 c2 c3 c4 c5 c6 c7 c8 c9 d1 d2 d3 d4 d5 d6 ||...............|
+00000050 d7 d8 d9 e2 e3 e4 e5 e6 e7 e8 e9 ad e0 bd 5f 6d |.............._m|
+00000060 79 81 82 83 84 85 86 87 88 89 91 92 93 94 95 96 |y...............|
+00000070 97 98 99 a2 a3 a4 a5 a6 a7 a8 a9 c0 4f d0 a1 07 |............O...|
+00000080 20 21 22 23 24 15 06 17 28 29 2a 2b 2c 09 0a 1b | !"#$...()*+,...|
+00000090 30 31 1a 33 34 35 36 08 38 39 3a 3b 04 14 3e e1 |01.3456.89:;..>.|
+000000a0 41 42 43 44 45 46 47 48 49 51 52 53 54 55 56 57 |ABCDEFGHIQRSTUVW|
+000000b0 58 59 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |XYbcdefghipqrstu|
+000000c0 76 77 78 80 8a 8b 8c 8d 8e 8f 90 9a 9b 9c 9d 9e |vwx.............|
+000000d0 9f a0 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 |................|
+000000e0 b8 b9 ba bb bc bd be bf ca cb cc cd ce cf da db |................|
+000000f0 dc dd de df ea eb ec ed ee ef fa fb fc fd fe ff |................|
+00000100
diff --git a/bin/dd/ref.pareven b/bin/dd/ref.pareven
new file mode 100644
index 000000000000..c64e63e30660
--- /dev/null
+++ b/bin/dd/ref.pareven
@@ -0,0 +1,18 @@
+$FreeBSD$
+00000000 00 81 82 03 84 05 06 87 88 09 0a 8b 0c 8d 8e 0f |................|
+00000010 90 11 12 93 14 95 96 17 18 99 9a 1b 9c 1d 1e 9f |................|
+00000020 a0 21 22 a3 24 a5 a6 27 28 a9 aa 2b ac 2d 2e af |.!".$..'(..+.-..|
+00000030 30 b1 b2 33 b4 35 36 b7 b8 39 3a bb 3c bd be 3f |0..3.56..9:.<..?|
+00000040 c0 41 42 c3 44 c5 c6 47 48 c9 ca 4b cc 4d 4e cf |.AB.D..GH..K.MN.|
+00000050 50 d1 d2 53 d4 55 56 d7 d8 59 5a db 5c dd de 5f |P..S.UV..YZ.\.._|
+00000060 60 e1 e2 63 e4 65 66 e7 e8 69 6a eb 6c ed ee 6f |`..c.ef..ij.l..o|
+00000070 f0 71 72 f3 74 f5 f6 77 78 f9 fa 7b fc 7d 7e ff |.qr.t..wx..{.}~.|
+00000080 00 81 82 03 84 05 06 87 88 09 0a 8b 0c 8d 8e 0f |................|
+00000090 90 11 12 93 14 95 96 17 18 99 9a 1b 9c 1d 1e 9f |................|
+000000a0 a0 21 22 a3 24 a5 a6 27 28 a9 aa 2b ac 2d 2e af |.!".$..'(..+.-..|
+000000b0 30 b1 b2 33 b4 35 36 b7 b8 39 3a bb 3c bd be 3f |0..3.56..9:.<..?|
+000000c0 c0 41 42 c3 44 c5 c6 47 48 c9 ca 4b cc 4d 4e cf |.AB.D..GH..K.MN.|
+000000d0 50 d1 d2 53 d4 55 56 d7 d8 59 5a db 5c dd de 5f |P..S.UV..YZ.\.._|
+000000e0 60 e1 e2 63 e4 65 66 e7 e8 69 6a eb 6c ed ee 6f |`..c.ef..ij.l..o|
+000000f0 f0 71 72 f3 74 f5 f6 77 78 f9 fa 7b fc 7d 7e ff |.qr.t..wx..{.}~.|
+00000100
diff --git a/bin/dd/ref.parnone b/bin/dd/ref.parnone
new file mode 100644
index 000000000000..fba31c142448
--- /dev/null
+++ b/bin/dd/ref.parnone
@@ -0,0 +1,18 @@
+$FreeBSD$
+00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
+00000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................|
+00000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | !"#$%&'()*+,-./|
+00000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f |0123456789:;<=>?|
+00000040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f |@ABCDEFGHIJKLMNO|
+00000050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f |PQRSTUVWXYZ[\]^_|
+00000060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f |`abcdefghijklmno|
+00000070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f |pqrstuvwxyz{|}~.|
+00000080 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
+00000090 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................|
+000000a0 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | !"#$%&'()*+,-./|
+000000b0 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f |0123456789:;<=>?|
+000000c0 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f |@ABCDEFGHIJKLMNO|
+000000d0 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f |PQRSTUVWXYZ[\]^_|
+000000e0 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f |`abcdefghijklmno|
+000000f0 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f |pqrstuvwxyz{|}~.|
+00000100
diff --git a/bin/dd/ref.parodd b/bin/dd/ref.parodd
new file mode 100644
index 000000000000..f0bc449e3648
--- /dev/null
+++ b/bin/dd/ref.parodd
@@ -0,0 +1,18 @@
+$FreeBSD$
+00000000 80 01 02 83 04 85 86 07 08 89 8a 0b 8c 0d 0e 8f |................|
+00000010 10 91 92 13 94 15 16 97 98 19 1a 9b 1c 9d 9e 1f |................|
+00000020 20 a1 a2 23 a4 25 26 a7 a8 29 2a ab 2c ad ae 2f | ..#.%&..)*.,../|
+00000030 b0 31 32 b3 34 b5 b6 37 38 b9 ba 3b bc 3d 3e bf |.12.4..78..;.=>.|
+00000040 40 c1 c2 43 c4 45 46 c7 c8 49 4a cb 4c cd ce 4f |@..C.EF..IJ.L..O|
+00000050 d0 51 52 d3 54 d5 d6 57 58 d9 da 5b dc 5d 5e df |.QR.T..WX..[.]^.|
+00000060 e0 61 62 e3 64 e5 e6 67 68 e9 ea 6b ec 6d 6e ef |.ab.d..gh..k.mn.|
+00000070 70 f1 f2 73 f4 75 76 f7 f8 79 7a fb 7c fd fe 7f |p..s.uv..yz.|...|
+00000080 80 01 02 83 04 85 86 07 08 89 8a 0b 8c 0d 0e 8f |................|
+00000090 10 91 92 13 94 15 16 97 98 19 1a 9b 1c 9d 9e 1f |................|
+000000a0 20 a1 a2 23 a4 25 26 a7 a8 29 2a ab 2c ad ae 2f | ..#.%&..)*.,../|
+000000b0 b0 31 32 b3 34 b5 b6 37 38 b9 ba 3b bc 3d 3e bf |.12.4..78..;.=>.|
+000000c0 40 c1 c2 43 c4 45 46 c7 c8 49 4a cb 4c cd ce 4f |@..C.EF..IJ.L..O|
+000000d0 d0 51 52 d3 54 d5 d6 57 58 d9 da 5b dc 5d 5e df |.QR.T..WX..[.]^.|
+000000e0 e0 61 62 e3 64 e5 e6 67 68 e9 ea 6b ec 6d 6e ef |.ab.d..gh..k.mn.|
+000000f0 70 f1 f2 73 f4 75 76 f7 f8 79 7a fb 7c fd fe 7f |p..s.uv..yz.|...|
+00000100
diff --git a/bin/dd/ref.parset b/bin/dd/ref.parset
new file mode 100644
index 000000000000..baa1c57163a2
--- /dev/null
+++ b/bin/dd/ref.parset
@@ -0,0 +1,18 @@
+$FreeBSD$
+00000000 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f |................|
+00000010 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f |................|
+00000020 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af |................|
+00000030 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf |................|
+00000040 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf |................|
+00000050 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df |................|
+00000060 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef |................|
+00000070 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff |................|
+00000080 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f |................|
+00000090 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f |................|
+000000a0 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af |................|
+000000b0 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf |................|
+000000c0 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf |................|
+000000d0 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df |................|
+000000e0 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef |................|
+000000f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff |................|
+00000100
diff --git a/bin/dd/ref.swab b/bin/dd/ref.swab
new file mode 100644
index 000000000000..79e57b79b738
--- /dev/null
+++ b/bin/dd/ref.swab
@@ -0,0 +1,18 @@
+$FreeBSD$
+00000000 01 00 03 02 05 04 07 06 09 08 0b 0a 0d 0c 0f 0e |................|
+00000010 11 10 13 12 15 14 17 16 19 18 1b 1a 1d 1c 1f 1e |................|
+00000020 21 20 23 22 25 24 27 26 29 28 2b 2a 2d 2c 2f 2e |! #"%$'&)(+*-,/.|
+00000030 31 30 33 32 35 34 37 36 39 38 3b 3a 3d 3c 3f 3e |1032547698;:=<?>|
+00000040 41 40 43 42 45 44 47 46 49 48 4b 4a 4d 4c 4f 4e |A@CBEDGFIHKJMLON|
+00000050 51 50 53 52 55 54 57 56 59 58 5b 5a 5d 5c 5f 5e |QPSRUTWVYX[Z]\_^|
+00000060 61 60 63 62 65 64 67 66 69 68 6b 6a 6d 6c 6f 6e |a`cbedgfihkjmlon|
+00000070 71 70 73 72 75 74 77 76 79 78 7b 7a 7d 7c 7f 7e |qpsrutwvyx{z}|.~|
+00000080 81 80 83 82 85 84 87 86 89 88 8b 8a 8d 8c 8f 8e |................|
+00000090 91 90 93 92 95 94 97 96 99 98 9b 9a 9d 9c 9f 9e |................|
+000000a0 a1 a0 a3 a2 a5 a4 a7 a6 a9 a8 ab aa ad ac af ae |................|
+000000b0 b1 b0 b3 b2 b5 b4 b7 b6 b9 b8 bb ba bd bc bf be |................|
+000000c0 c1 c0 c3 c2 c5 c4 c7 c6 c9 c8 cb ca cd cc cf ce |................|
+000000d0 d1 d0 d3 d2 d5 d4 d7 d6 d9 d8 db da dd dc df de |................|
+000000e0 e1 e0 e3 e2 e5 e4 e7 e6 e9 e8 eb ea ed ec ef ee |................|
+000000f0 f1 f0 f3 f2 f5 f4 f7 f6 f9 f8 fb fa fd fc ff fe |................|
+00000100
diff --git a/bin/dd/ref.ucase b/bin/dd/ref.ucase
new file mode 100644
index 000000000000..70d8a903c354
--- /dev/null
+++ b/bin/dd/ref.ucase
@@ -0,0 +1,18 @@
+$FreeBSD$
+00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
+00000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................|
+00000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | !"#$%&'()*+,-./|
+00000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f |0123456789:;<=>?|
+00000040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f |@ABCDEFGHIJKLMNO|
+00000050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f |PQRSTUVWXYZ[\]^_|
+00000060 60 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f |`ABCDEFGHIJKLMNO|
+00000070 50 51 52 53 54 55 56 57 58 59 5a 7b 7c 7d 7e 7f |PQRSTUVWXYZ{|}~.|
+00000080 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f |................|
+00000090 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f |................|
+000000a0 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af |................|
+000000b0 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf |................|
+000000c0 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf |................|
+000000d0 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df |................|
+000000e0 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef |................|
+000000f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff |................|
+00000100
diff --git a/bin/dd/tests/Makefile b/bin/dd/tests/Makefile
new file mode 100644
index 000000000000..029808e6eb28
--- /dev/null
+++ b/bin/dd/tests/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+ATF_TESTS_SH= dd2_test
+NETBSD_ATF_TESTS_SH= dd_test
+
+.include <netbsd-tests.test.mk>
+
+.include <bsd.test.mk>
diff --git a/bin/dd/tests/Makefile.depend b/bin/dd/tests/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/bin/dd/tests/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/bin/dd/tests/dd2_test.sh b/bin/dd/tests/dd2_test.sh
new file mode 100755
index 000000000000..c0b33fc17226
--- /dev/null
+++ b/bin/dd/tests/dd2_test.sh
@@ -0,0 +1,69 @@
+#
+# Copyright (c) 2017 Spectra Logic Corporation
+# 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.
+#
+# $FreeBSD$
+
+
+atf_test_case max_seek
+max_seek_head()
+{
+ atf_set "descr" "dd(1) can seek by the maximum amount"
+}
+max_seek_body()
+{
+ case `df -T . | tail -n 1 | cut -wf 2` in
+ "ufs")
+ atf_skip "UFS's maximum file size is too small";;
+ "zfs") ;; # ZFS is fine
+ "tmpfs")
+ atf_skip "tmpfs can't create arbitrarily large spare files";;
+ *) atf_skip "Unknown file system";;
+ esac
+
+ touch f.in
+ seek=`echo "2^63 / 4096 - 1" | bc`
+ atf_check -s exit:0 -e ignore dd if=f.in of=f.out bs=4096 seek=$seek
+}
+
+atf_test_case seek_overflow
+seek_overflow_head()
+{
+ atf_set "descr" "dd(1) should reject too-large seek values"
+}
+seek_overflow_body()
+{
+ touch f.in
+ seek=`echo "2^63 / 4096" | bc`
+ atf_check -s not-exit:0 -e match:"seek offsets cannot be larger than" \
+ dd if=f.in of=f.out bs=4096 seek=$seek
+ atf_check -s not-exit:0 -e match:"seek offsets cannot be larger than" \
+ dd if=f.in of=f.out bs=4096 seek=-1
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case max_seek
+ atf_add_test_case seek_overflow
+}