summaryrefslogtreecommitdiffstats
path: root/file_cmds/dd
diff options
context:
space:
mode:
authorCameron Katri <me@cameronkatri.com>2021-05-09 14:20:58 -0400
committerCameron Katri <me@cameronkatri.com>2021-05-09 14:20:58 -0400
commit5fd83771641d15c418f747bd343ba6738d3875f7 (patch)
tree5abf0f78f680d9837dbd93d4d4c3933bb7509599 /file_cmds/dd
downloadapple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.gz
apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.zst
apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.zip
Import macOS userland
adv_cmds-176 basic_cmds-55 bootstrap_cmds-116.100.1 developer_cmds-66 diskdev_cmds-667.40.1 doc_cmds-53.60.1 file_cmds-321.40.3 mail_cmds-35 misc_cmds-34 network_cmds-606.40.1 patch_cmds-17 remote_cmds-63 shell_cmds-216.60.1 system_cmds-880.60.2 text_cmds-106
Diffstat (limited to 'file_cmds/dd')
-rw-r--r--file_cmds/dd/args.c421
-rw-r--r--file_cmds/dd/conv.c273
-rw-r--r--file_cmds/dd/conv_tab.c289
-rw-r--r--file_cmds/dd/dd.1382
-rw-r--r--file_cmds/dd/dd.c481
-rw-r--r--file_cmds/dd/dd.entitlements9
-rw-r--r--file_cmds/dd/dd.h102
-rw-r--r--file_cmds/dd/extern.h73
-rw-r--r--file_cmds/dd/install_symlink.sh16
-rw-r--r--file_cmds/dd/misc.c108
-rw-r--r--file_cmds/dd/position.c169
11 files changed, 2323 insertions, 0 deletions
diff --git a/file_cmds/dd/args.c b/file_cmds/dd/args.c
new file mode 100644
index 0000000..463bd46
--- /dev/null
+++ b/file_cmds/dd/args.c
@@ -0,0 +1,421 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)args.c 8.3 (Berkeley) 4/2/94";
+#endif
+__used static const char rcsid[] =
+ "$FreeBSD: src/bin/dd/args.c,v 1.31 2002/02/22 20:51:00 markm Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <limits.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 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_ibs(char *);
+static void f_if(char *);
+static void f_obs(char *);
+static void f_of(char *);
+static void f_seek(char *);
+static void f_skip(char *);
+static quad_t get_num(char *);
+static off_t get_offset(char *);
+
+static const struct arg {
+ const char *name;
+ void (*f)(char *);
+ u_int set, noset;
+} args[] = {
+ { "bs", f_bs, C_BS, C_BS|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 },
+ { "ibs", f_ibs, C_IBS, C_IBS },
+ { "if", f_if, C_IF, C_IF },
+ { "iseek", f_skip, C_SKIP, C_SKIP },
+ { "obs", f_obs, C_OBS, C_OBS },
+ { "of", f_of, C_OF, C_OF },
+ { "oseek", f_seek, C_SEEK, C_SEEK },
+ { "seek", f_seek, C_SEEK, C_SEEK },
+ { "skip", f_skip, C_SKIP, C_SKIP },
+};
+
+static char *oper;
+
+/*
+ * args -- parse JCL syntax of dd.
+ */
+void
+jcl(char **argv)
+{
+ struct arg *ap, tmp;
+ char *arg;
+
+ in.dbsz = out.dbsz = 512;
+
+ if (argv[1] && !strcmp(argv[1], "--")) /* skip delimiter before operands */
+ argv++;
+ 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;
+
+ /*
+ * Bail out if the calculation of a file offset would overflow.
+ */
+ if (in.offset > QUAD_MAX / in.dbsz || out.offset > QUAD_MAX / out.dbsz)
+ errx(1, "seek offsets cannot be larger than %qd", QUAD_MAX);
+}
+
+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)
+{
+ quad_t res;
+
+ res = get_num(arg);
+ if (res < 1 || res > SSIZE_MAX)
+ errx(1, "bs must be between 1 and %ld", SSIZE_MAX);
+ in.dbsz = out.dbsz = (size_t)res;
+}
+
+static void
+f_cbs(char *arg)
+{
+ quad_t res;
+
+ res = get_num(arg);
+ if (res < 1 || res > SSIZE_MAX)
+ errx(1, "cbs must be between 1 and %ld", SSIZE_MAX);
+ cbsz = (size_t)res;
+}
+
+static void
+f_count(char *arg)
+{
+
+ cpy_cnt = get_num(arg);
+ if (cpy_cnt < 0)
+ errx(1, "count cannot be negative");
+ if (cpy_cnt == 0)
+ cpy_cnt = -1;
+}
+
+static void
+f_files(char *arg)
+{
+
+ files_cnt = get_num(arg);
+ if (files_cnt < 1)
+ errx(1, "files must be between 1 and %qd", QUAD_MAX);
+}
+
+static void
+f_ibs(char *arg)
+{
+ quad_t res;
+
+ if (!(ddflags & C_BS)) {
+ res = get_num(arg);
+ if (res < 1 || res > SSIZE_MAX)
+ errx(1, "ibs must be between 1 and %ld", SSIZE_MAX);
+ in.dbsz = (size_t)res;
+ }
+}
+
+static void
+f_if(char *arg)
+{
+
+ in.name = arg;
+}
+
+static void
+f_obs(char *arg)
+{
+ quad_t res;
+
+ if (!(ddflags & C_BS)) {
+ res = get_num(arg);
+ if (res < 1 || res > SSIZE_MAX)
+ errx(1, "obs must be between 1 and %ld", 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_offset(arg);
+}
+
+static void
+f_skip(char *arg)
+{
+
+ in.offset = get_offset(arg);
+}
+
+static const struct conv {
+ const char *name;
+ u_int 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 },
+ { "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 },
+ { "sparse", C_SPARSE, 0, NULL },
+ { "swab", C_SWAB, 0, NULL },
+ { "sync", C_SYNC, 0, 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, sizeof(clist) / sizeof(struct conv),
+ 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));
+}
+
+/*
+ * Convert an expression of the following forms to a quad_t.
+ * 1) A positive decimal number.
+ * 2) A positive decimal number followed by a b (mult by 512).
+ * 3) A positive decimal number followed by a k (mult by 1 << 10).
+ * 4) A positive decimal number followed by a m (mult by 1 << 20).
+ * 5) A positive decimal number followed by a g (mult by 1 << 30).
+ * 5) A positive decimal number followed by a w (mult by sizeof int).
+ * 6) Two or more positive decimal numbers (with/without [bkmgw])
+ * separated by x (also * for backwards compatibility), specifying
+ * the product of the indicated values.
+ */
+static quad_t
+get_num(char *val)
+{
+ quad_t num, t;
+ char *expr;
+
+ errno = 0;
+ num = strtoq(val, &expr, 0);
+ if (errno != 0) /* Overflow or underflow. */
+ err(1, "%s", oper);
+
+ if (expr == val) /* No valid digits. */
+ errx(1, "%s: illegal numeric value", oper);
+
+ switch (*expr) {
+ case 'b':
+ t = num;
+ num *= 512;
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'k':
+ t = num;
+ num *= 1 << 10;
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'm':
+ t = num;
+ num *= 1 << 20;
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'g':
+ t = num;
+ num *= 1 << 30;
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'w':
+ t = num;
+ num *= sizeof(int);
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ }
+
+ switch (*expr) {
+ case '\0':
+ break;
+ case '*': /* Backward compatible. */
+ case 'x':
+ t = num;
+ num *= get_num(expr + 1);
+ if (t <= num)
+ break;
+erange:
+ errx(1, "%s: %s", oper, strerror(ERANGE));
+ default:
+ errx(1, "%s: illegal numeric value", oper);
+ }
+ return (num);
+}
+
+static off_t
+get_offset(char *val)
+{
+ quad_t num;
+
+ num = get_num(val);
+ if (num > QUAD_MAX) /* XXX can't happen && quad_t != off_t */
+ errx(1, "%s: illegal offset", oper); /* Too big. */
+ return ((off_t)num);
+}
diff --git a/file_cmds/dd/conv.c b/file_cmds/dd/conv.c
new file mode 100644
index 0000000..59c7b01
--- /dev/null
+++ b/file_cmds/dd/conv.c
@@ -0,0 +1,273 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94";
+#endif
+__used static const char rcsid[] =
+ "$FreeBSD: src/bin/dd/conv.c,v 1.16 2002/02/02 06:24:12 imp Exp $";
+#endif /* not lint */
+
+#include <sys/param.h>
+
+#include <err.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);
+
+ /*
+ * Ddout 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, 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' && 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 (cnt = in.dbrcnt, inp = in.dbp; cnt--;) {
+ *inp = t[*inp];
+ --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; 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/file_cmds/dd/conv_tab.c b/file_cmds/dd/conv_tab.c
new file mode 100644
index 0000000..a9f091e
--- /dev/null
+++ b/file_cmds/dd/conv_tab.c
@@ -0,0 +1,289 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)conv_tab.c 8.1 (Berkeley) 5/31/93";
+#endif
+__used static const char rcsid[] =
+ "$FreeBSD: src/bin/dd/conv_tab.c,v 1.10 1999/09/12 16:51:53 green Exp $";
+#endif /* not lint */
+
+#include <sys/types.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/file_cmds/dd/dd.1 b/file_cmds/dd/dd.1
new file mode 100644
index 0000000..8460813
--- /dev/null
+++ b/file_cmds/dd/dd.1
@@ -0,0 +1,382 @@
+.\" 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)dd.1 8.2 (Berkeley) 1/13/94
+.\" $FreeBSD: src/bin/dd/dd.1,v 1.19 2002/03/31 20:49:37 keramida Exp $
+.\"
+.Dd January 13, 1994
+.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:
+.\" XXX
+.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 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 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 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 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 ".Cm 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 lcase
+Transform uppercase characters into lowercase characters.
+.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 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 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 ,
+or
+.Dq Li w ,
+the
+number is multiplied by 512, 1024 (1K), 1048576 (1M), 1073741824 (1G)
+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 DIAGNOSTICS
+.Ex -std
+.Sh SEE ALSO
+.Xr cp 1 ,
+.Xr tr 1
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be a superset of the
+.St -p1003.2
+standard.
+The
+.Cm files
+operand and the
+.Cm ascii ,
+.Cm ebcdic ,
+.Cm ibm ,
+.Cm oldascii ,
+.Cm oldebcdic
+and
+.Cm oldibm
+values are extensions to the
+\*[Px]
+standard.
diff --git a/file_cmds/dd/dd.c b/file_cmds/dd/dd.c
new file mode 100644
index 0000000..5731186
--- /dev/null
+++ b/file_cmds/dd/dd.c
@@ -0,0 +1,481 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__used 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
+#if 0
+static char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94";
+#endif
+__used static const char rcsid[] =
+ "$FreeBSD: src/bin/dd/dd.c,v 1.36 2002/03/07 14:00:33 markm Exp $";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/conf.h>
+#include <sys/filio.h>
+#include <sys/time.h>
+
+#ifdef __APPLE__
+#include <sys/ioctl.h>
+#else
+#include <sys/disklabel.h>
+#endif
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.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 */
+quad_t cpy_cnt; /* # of blocks to copy */
+off_t pending = 0; /* pending seek if sparse */
+u_int ddflags; /* conversion options */
+size_t cbsz; /* conversion block size */
+quad_t files_cnt = 1; /* # of files to copy */
+const u_char *ctab; /* conversion table */
+
+int
+main(int argc, char *argv[])
+{
+ (void)setlocale(LC_CTYPE, "");
+ jcl(argv);
+ setup();
+
+ (void)signal(SIGINFO, summaryx);
+ (void)signal(SIGINT, terminate);
+
+ atexit(summary);
+
+ while (files_cnt--)
+ dd_in();
+
+ dd_close();
+ exit(0);
+}
+
+static void
+setup(void)
+{
+ u_int cnt;
+ struct timeval tv;
+
+ if (in.name == NULL) {
+ in.name = "stdin";
+ in.fd = STDIN_FILENO;
+ } else {
+ in.fd = open(in.name, O_RDONLY, 0);
+ if (in.fd == -1)
+ err(1, "%s", in.name);
+ }
+
+ getfdtype(&in);
+
+ if (files_cnt > 1 && !(in.flags & ISTAPE))
+ errx(1, "files is not supported for non-tape devices");
+
+ if (out.name == NULL) {
+ /* No way to check for read access here. */
+ out.fd = STDOUT_FILENO;
+ out.name = "stdout";
+ } else {
+#define OFLAGS \
+ (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
+ 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;
+ }
+ if (out.fd == -1)
+ err(1, "%s", out.name);
+ }
+
+ getfdtype(&out);
+
+ /*
+ * 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(out.dbsz + in.dbsz - 1)) == NULL)
+ err(1, "input buffer");
+ out.db = in.db;
+ } else if ((in.db = malloc(MAX(in.dbsz, cbsz) + cbsz)) == NULL ||
+ (out.db = malloc(out.dbsz + cbsz)) == NULL)
+ err(1, "output 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 converting case at the same time as another conversion, build a
+ * table that does both at once. If just converting case, use the
+ * built-in tables.
+ */
+ if (ddflags & (C_LCASE | C_UCASE)) {
+ if (ddflags & (C_ASCII | C_EBCDIC)) {
+ if (ddflags & C_LCASE) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = tolower(ctab[cnt]);
+ } else {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = toupper(ctab[cnt]);
+ }
+ } else {
+ if (ddflags & C_LCASE) {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = tolower((int)cnt);
+ } else {
+ for (cnt = 0; cnt <= 0377; ++cnt)
+ casetab[cnt] = toupper((int)cnt);
+ }
+ }
+ ctab = casetab;
+ }
+
+ (void)gettimeofday(&tv, (struct timezone *)NULL);
+ st.start = tv.tv_sec + tv.tv_usec * 1e-6;
+}
+
+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 {
+#ifdef __APPLE__ /* MacOSX uses enumeration for type not a bitmask */
+ if (type == D_TAPE)
+ io->flags |= ISTAPE;
+ else if (type == D_DISK || type == D_TTY) {
+#else /* !__APPLE__ */
+ if (type & D_TAPE)
+ io->flags |= ISTAPE;
+ else if (type & (D_DISK | D_MEM)) {
+ if (type & D_DISK) {
+ const int one = 1;
+
+ (void)ioctl(io->fd, DIOCWLABEL, &one);
+ }
+#endif /* __APPLE__ */
+ io->flags |= ISSEEK;
+ }
+#ifdef __APPLE__
+ if (S_ISCHR(sb.st_mode) && (type != D_TAPE))
+#else /* !__APPLE__ */
+ if (S_ISCHR(sb.st_mode) && (type & D_TAPE) == 0)
+#endif /* __APPLE__ */
+ 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;
+}
+
+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 >= (u_quad_t)cpy_cnt)
+ return;
+ break;
+ }
+
+ /*
+ * Zero the buffer first if sync; if doing block operations,
+ * use spaces.
+ */
+ if (ddflags & C_SYNC) {
+ if (ddflags & (C_BLOCK | C_UNBLOCK))
+ memset(in.dbp, ' ', in.dbsz);
+ else
+ memset(in.dbp, 0, in.dbsz);
+ }
+
+ n = read(in.fd, in.dbp, in.dbsz);
+ 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;
+
+ /* Read errors count as full blocks. */
+ in.dbcnt += in.dbrcnt = in.dbsz;
+ ++st.in_full;
+
+ /* Handle full input blocks. */
+ } else if ((size_t)n == in.dbsz) {
+ in.dbcnt += in.dbrcnt = n;
+ ++st.in_full;
+
+ /* Handle partial input blocks. */
+ } else {
+ /* If sync, use the entire block. */
+ if (ddflags & C_SYNC)
+ in.dbcnt += in.dbrcnt = in.dbsz;
+ else
+ in.dbcnt += in.dbrcnt = n;
+ ++st.in_part;
+ }
+
+ /*
+ * 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_BS) {
+ out.dbcnt = in.dbcnt;
+ dd_out(1);
+ in.dbcnt = 0;
+ continue;
+ }
+
+ if (ddflags & C_SWAB) {
+ if ((n = in.dbrcnt) & 1) {
+ ++st.swab;
+ --n;
+ }
+ swab(in.dbp, in.dbp, (size_t)n);
+ }
+
+ in.dbp += in.dbrcnt;
+ (*cfunc)();
+ }
+}
+
+/*
+ * 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_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);
+}
+
+void
+dd_out(int force)
+{
+ u_char *outp;
+ size_t cnt, i, 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;
+ for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) {
+ for (cnt = n;; cnt -= nw) {
+ sparse = 0;
+ if (ddflags & C_SPARSE) {
+ sparse = 1; /* Is buffer sparse? */
+ for (i = 0; i < cnt; i++)
+ if (outp[i] != 0) {
+ sparse = 0;
+ break;
+ }
+ }
+ if (sparse && !force) {
+ pending += cnt;
+ nw = cnt;
+ } else {
+ if (pending != 0) {
+ if (force)
+ pending--;
+ if (lseek(out.fd, pending, SEEK_CUR) ==
+ -1)
+ err(2, "%s: seek error creating sparse file",
+ out.name);
+ if (force)
+ write(out.fd, outp, 1);
+ pending = 0;
+ }
+ if (cnt)
+ nw = write(out.fd, outp, cnt);
+ 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) {
+ if (n != out.dbsz)
+ ++st.out_part;
+ else
+ ++st.out_full;
+ break;
+ }
+ ++st.out_part;
+ if ((size_t)nw == cnt)
+ break;
+ 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);
+ }
+ }
+ 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/file_cmds/dd/dd.entitlements b/file_cmds/dd/dd.entitlements
new file mode 100644
index 0000000..abb8bc5
--- /dev/null
+++ b/file_cmds/dd/dd.entitlements
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.private.security.disk-device-access</key>
+ <true/>
+</dict>
+</plist>
+
diff --git a/file_cmds/dd/dd.h b/file_cmds/dd/dd.h
new file mode 100644
index 0000000..c516ad2
--- /dev/null
+++ b/file_cmds/dd/dd.h
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)dd.h 8.3 (Berkeley) 4/2/94
+ * $FreeBSD: src/bin/dd/dd.h,v 1.17 2002/02/22 20:51:00 markm Exp $
+ */
+
+#ifndef _DD_H_
+#define _DD_H_
+
+/* Input/output stream state. */
+typedef struct {
+ u_char *db; /* buffer address */
+ u_char *dbp; /* current buffer I/O address */
+ /* XXX ssize_t? */
+ size_t dbcnt; /* current buffer byte count */
+ size_t dbrcnt; /* last read byte count */
+ size_t dbsz; /* buffer 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 */
+
+} IO;
+
+typedef struct {
+ u_quad_t in_full; /* # of full input blocks */
+ u_quad_t in_part; /* # of partial input blocks */
+ u_quad_t out_full; /* # of full output blocks */
+ u_quad_t out_part; /* # of partial output blocks */
+ u_quad_t trunc; /* # of truncated records */
+ u_quad_t swab; /* # of odd-length swab blocks */
+ u_quad_t bytes; /* # of bytes written */
+ double start; /* start time of dd */
+} STAT;
+
+/* Flags (in ddflags). */
+#define C_ASCII 0x00001
+#define C_BLOCK 0x00002
+#define C_BS 0x00004
+#define C_CBS 0x00008
+#define C_COUNT 0x00010
+#define C_EBCDIC 0x00020
+#define C_FILES 0x00040
+#define C_IBS 0x00080
+#define C_IF 0x00100
+#define C_LCASE 0x00200
+#define C_NOERROR 0x00400
+#define C_NOTRUNC 0x00800
+#define C_OBS 0x01000
+#define C_OF 0x02000
+#define C_SEEK 0x04000
+#define C_SKIP 0x08000
+#define C_SWAB 0x10000
+#define C_SYNC 0x20000
+#define C_UCASE 0x40000
+#define C_UNBLOCK 0x80000
+#define C_OSYNC 0x100000
+#define C_SPARSE 0x200000
+
+#endif /* _DD_H_ */
diff --git a/file_cmds/dd/extern.h b/file_cmds/dd/extern.h
new file mode 100644
index 0000000..0ae6330
--- /dev/null
+++ b/file_cmds/dd/extern.h
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.3 (Berkeley) 4/2/94
+ * $FreeBSD: src/bin/dd/extern.h,v 1.12 2002/02/02 06:24:12 imp Exp $
+ */
+
+#ifndef _DD_EXTERN_H_
+#define _DD_EXTERN_H_
+
+#include <sys/cdefs.h>
+
+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);
+void summary(void);
+void summaryx(int);
+void terminate(int);
+void unblock(void);
+void unblock_close(void);
+
+extern IO in, out;
+extern STAT st;
+extern void (*cfunc)(void);
+extern quad_t cpy_cnt;
+extern size_t cbsz;
+extern u_int ddflags;
+extern quad_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[];
+
+#endif /* _DD_EXTERN_H_ */
diff --git a/file_cmds/dd/install_symlink.sh b/file_cmds/dd/install_symlink.sh
new file mode 100644
index 0000000..7e8665f
--- /dev/null
+++ b/file_cmds/dd/install_symlink.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+set -e
+set -x
+
+case "$PLATFORM_NAME" in
+iphoneos|appletvos|watchos|bridgeos)
+ ln -hfs /usr/local/bin/dd "$DSTROOT"/bin/dd
+ ;;
+macosx)
+ ;;
+*)
+ echo "Unsupported platform: $PLATFORM_NAME"
+ exit 1
+ ;;
+esac
+
diff --git a/file_cmds/dd/misc.c b/file_cmds/dd/misc.c
new file mode 100644
index 0000000..b220334
--- /dev/null
+++ b/file_cmds/dd/misc.c
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)misc.c 8.3 (Berkeley) 4/2/94";
+#endif
+__used static const char rcsid[] =
+ "$FreeBSD: src/bin/dd/misc.c,v 1.23 2002/02/02 06:24:12 imp Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include "dd.h"
+#include "extern.h"
+
+void
+summary(void)
+{
+ struct timeval tv;
+ double secs;
+ char buf[100];
+
+ (void)gettimeofday(&tv, (struct timezone *)NULL);
+ secs = tv.tv_sec + tv.tv_usec * 1e-6 - st.start;
+ if (secs < 1e-6)
+ secs = 1e-6;
+ /* Use snprintf(3) so that we don't reenter stdio(3). */
+ (void)snprintf(buf, sizeof(buf),
+ "%qu+%qu records in\n%qu+%qu records out\n",
+ st.in_full, st.in_part, st.out_full, st.out_part);
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ if (st.swab) {
+ (void)snprintf(buf, sizeof(buf), "%qu odd length swab %s\n",
+ st.swab, (st.swab == 1) ? "block" : "blocks");
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ }
+ if (st.trunc) {
+ (void)snprintf(buf, sizeof(buf), "%qu truncated %s\n",
+ st.trunc, (st.trunc == 1) ? "record" : "records");
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+ }
+ (void)snprintf(buf, sizeof(buf),
+ "%qu bytes transferred in %.6f secs (%.0f bytes/sec)\n",
+ st.bytes, secs, st.bytes / secs);
+ (void)write(STDERR_FILENO, buf, strlen(buf));
+}
+
+/* ARGSUSED */
+void
+summaryx(int notused)
+{
+ int save_errno = errno;
+
+ summary();
+ errno = save_errno;
+}
+
+/* ARGSUSED */
+void
+terminate(int sig)
+{
+
+ summary();
+ _exit(sig == 0 ? 0 : 1);
+}
diff --git a/file_cmds/dd/position.c b/file_cmds/dd/position.c
new file mode 100644
index 0000000..c110cd3
--- /dev/null
+++ b/file_cmds/dd/position.c
@@ -0,0 +1,169 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94";
+#endif
+__used static const char rcsid[] =
+ "$FreeBSD: src/bin/dd/position.c,v 1.20 2002/02/02 06:24:12 imp Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#ifdef __APPLE__
+#include <sys/ioctl.h>
+#endif
+
+#include <err.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "dd.h"
+#include "extern.h"
+
+/*
+ * 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, in.offset * in.dbsz, 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;
+ 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)
+{
+ 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, out.offset * out.dbsz, 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");
+
+ /* 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);
+
+ while (cnt++ < out.offset) {
+ n = write(out.fd, out.db, out.dbsz);
+ if (n == -1)
+ err(1, "%s", out.name);
+ if ((size_t)n != out.dbsz)
+ errx(1, "%s: write failure", out.name);
+ }
+ break;
+ }
+}