]> Zhao Yanbai Git Server - minix.git/commitdiff
Importing bin/dd 86/2986/1
authorJacob Adams <tookmund@gmail.com>
Sun, 5 Apr 2015 01:00:10 +0000 (21:00 -0400)
committerLionel Sambuc <lionel@minix3.org>
Wed, 15 Apr 2015 11:50:57 +0000 (13:50 +0200)
Change-Id: Ibdfed821aa834419c9713dc80f698c8ed74ff269

19 files changed:
bin/Makefile
bin/dd/Makefile [new file with mode: 0644]
bin/dd/args.c [new file with mode: 0644]
bin/dd/conv.c [new file with mode: 0644]
bin/dd/conv_tab.c [new file with mode: 0644]
bin/dd/dd.1 [new file with mode: 0644]
bin/dd/dd.c [new file with mode: 0644]
bin/dd/dd.h [new file with mode: 0644]
bin/dd/dd_hostops.c [new file with mode: 0644]
bin/dd/dd_rumpops.c [new file with mode: 0644]
bin/dd/extern.h [new file with mode: 0644]
bin/dd/misc.c [new file with mode: 0644]
bin/dd/position.c [new file with mode: 0644]
distrib/sets/lists/minix/mi
minix/commands/Makefile
minix/commands/dd/Makefile [deleted file]
minix/commands/dd/dd.c [deleted file]
minix/man/man1/Makefile
minix/man/man1/dd.1 [deleted file]

index 2215fdb5b2b1aede763b1d5603feae3044d0c3c3..183971f567480293d67d5bbdd7a437672bc94056 100644 (file)
@@ -1,7 +1,7 @@
 #      $NetBSD: Makefile,v 1.22 2007/12/31 15:31:24 ad Exp $
 #      @(#)Makefile    8.1 (Berkeley) 5/31/93
 
-SUBDIR=        cat chmod cp date df echo ed expr hostname \
+SUBDIR=        cat chmod cp date dd df echo ed expr hostname \
        kill ksh ln ls mkdir mv pax pwd rm rmdir sh \
        sleep stty sync test
 
diff --git a/bin/dd/Makefile b/bin/dd/Makefile
new file mode 100644 (file)
index 0000000..bb06576
--- /dev/null
@@ -0,0 +1,21 @@
+#      $NetBSD: Makefile,v 1.17 2012/08/08 14:09:14 christos Exp $
+#      @(#)Makefile    8.1 (Berkeley) 5/31/93
+
+.include <bsd.own.mk>
+
+RUMPPRG=dd
+SRCS=  args.c conv.c dd.c misc.c position.c
+
+DPADD+=        ${LIBUTIL}
+LDADD+=        -lutil
+
+.ifdef SMALLPROG
+CPPFLAGS+=     -DNO_CONV -DNO_MSGFMT -DSMALL
+.else
+SRCS+=         conv_tab.c
+.ifdef CRUNCHEDPROG
+CPPFLAGS+=     -DSMALL
+.endif
+.endif
+
+.include <bsd.prog.mk>
diff --git a/bin/dd/args.c b/bin/dd/args.c
new file mode 100644 (file)
index 0000000..207e300
--- /dev/null
@@ -0,0 +1,391 @@
+/*     $NetBSD: args.c,v 1.38 2013/07/17 12:55:48 christos Exp $       */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. 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";
+#else
+__RCSID("$NetBSD: args.c,v 1.38 2013/07/17 12:55:48 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dd.h"
+#include "extern.h"
+
+static int     c_arg(const void *, const void *);
+
+#ifdef NO_MSGFMT
+static void    f_msgfmt(char *) __dead;
+#else
+static void    f_msgfmt(char *);
+#endif /* NO_MSGFMT */
+
+#ifdef NO_CONV
+static void    f_conv(char *) __dead;
+#else
+static void    f_conv(char *);
+static int     c_conv(const void *, const void *);
+#endif /* NO_CONV */
+
+static void    f_bs(char *);
+static void    f_cbs(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 void    f_progress(char *);
+
+static const struct arg {
+       const char *name;
+       void (*f)(char *);
+       u_int set, noset;
+} args[] = {
+     /* the array needs to be sorted by the first column so
+       bsearch() can be used to find commands quickly */
+       { "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 },
+       { "ibs",        f_ibs,          C_IBS,   C_BS|C_IBS },
+       { "if",         f_if,           C_IF,    C_IF },
+       { "iseek",      f_skip,         C_SKIP,  C_SKIP },
+       { "msgfmt",     f_msgfmt,       0,       0 },
+       { "obs",        f_obs,          C_OBS,   C_BS|C_OBS },
+       { "of",         f_of,           C_OF,    C_OF },
+       { "oseek",      f_seek,         C_SEEK,  C_SEEK },
+       { "progress",   f_progress,     0,       0 },
+       { "seek",       f_seek,         C_SEEK,  C_SEEK },
+       { "skip",       f_skip,         C_SKIP,  C_SKIP },
+};
+
+/*
+ * args -- parse JCL syntax of dd.
+ */
+void
+jcl(char **argv)
+{
+       struct arg *ap, tmp;
+       char *oper, *arg;
+
+       in.dbsz = out.dbsz = 512;
+
+       while ((oper = *++argv) != NULL) {
+               if ((oper = strdup(oper)) == NULL) {
+                       errx(EXIT_FAILURE,
+                           "unable to allocate space for the argument %s",
+                           *argv);
+                       /* NOTREACHED */
+               }
+               if ((arg = strchr(oper, '=')) == NULL) {
+                       errx(EXIT_FAILURE, "unknown operand %s", oper);
+                       /* NOTREACHED */
+               }
+               *arg++ = '\0';
+               if (!*arg) {
+                       errx(EXIT_FAILURE, "no value specified for %s", oper);
+                       /* NOTREACHED */
+               }
+               tmp.name = oper;
+               if (!(ap = bsearch(&tmp, args,
+                   __arraycount(args), sizeof(*args), c_arg))) {
+                       errx(EXIT_FAILURE, "unknown operand %s", tmp.name);
+                       /* NOTREACHED */
+               }
+               if (ddflags & ap->noset) {
+                       errx(EXIT_FAILURE,
+                           "%s: illegal argument combination or already set",
+                           tmp.name);
+                       /* NOTREACHED */
+               }
+               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 | C_OSYNC | C_ASCII | C_EBCDIC | C_SPARSE)) {
+                       ddflags &= ~C_BS;
+                       ddflags |= C_IBS|C_OBS;
+               }
+
+               /* 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(EXIT_FAILURE, "record operations require cbs");
+                       /* NOTREACHED */
+               }
+               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(EXIT_FAILURE,
+                           "cbs meaningless if not doing record operations");
+                       /* NOTREACHED */
+               }
+       } else
+               cfunc = def;
+
+       /* Read, write and seek calls take off_t as arguments.
+        *
+        * The following check is not done because an off_t is a quad
+        *  for current NetBSD implementations.
+        *
+        * if (in.offset > INT_MAX/in.dbsz || out.offset > INT_MAX/out.dbsz)
+        *      errx(1, "seek offsets cannot be larger than %d", INT_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)
+{
+
+       in.dbsz = out.dbsz = strsuftoll("block size", arg, 1, UINT_MAX);
+}
+
+static void
+f_cbs(char *arg)
+{
+
+       cbsz = strsuftoll("conversion record size", arg, 1, UINT_MAX);
+}
+
+static void
+f_count(char *arg)
+{
+
+       cpy_cnt = strsuftoll("block count", arg, 0, LLONG_MAX);
+       if (!cpy_cnt)
+               terminate(0);
+}
+
+static void
+f_files(char *arg)
+{
+
+       files_cnt = (u_int)strsuftoll("file count", arg, 0, UINT_MAX);
+       if (!files_cnt)
+               terminate(0);
+}
+
+static void
+f_ibs(char *arg)
+{
+
+       if (!(ddflags & C_BS))
+               in.dbsz = strsuftoll("input block size", arg, 1, UINT_MAX);
+}
+
+static void
+f_if(char *arg)
+{
+
+       in.name = arg;
+}
+
+#ifdef NO_MSGFMT
+/* Build a small version (i.e. for a ramdisk root) */
+static void
+f_msgfmt(char *arg)
+{
+
+       errx(EXIT_FAILURE, "msgfmt option disabled");
+       /* NOTREACHED */
+}
+#else  /* NO_MSGFMT */
+static void
+f_msgfmt(char *arg)
+{
+
+       /*
+        * If the format string is not valid, dd_write_msg() will print
+        * an error and exit.
+        */
+       dd_write_msg(arg, 0);
+
+       msgfmt = arg;
+}
+#endif /* NO_MSGFMT */
+
+static void
+f_obs(char *arg)
+{
+
+       if (!(ddflags & C_BS))
+               out.dbsz = strsuftoll("output block size", arg, 1, UINT_MAX);
+}
+
+static void
+f_of(char *arg)
+{
+
+       out.name = arg;
+}
+
+static void
+f_seek(char *arg)
+{
+
+       out.offset = strsuftoll("seek blocks", arg, 0, LLONG_MAX);
+}
+
+static void
+f_skip(char *arg)
+{
+
+       in.offset = strsuftoll("skip blocks", arg, 0, LLONG_MAX);
+}
+
+static void
+f_progress(char *arg)
+{
+
+       progress = strsuftoll("progress blocks", arg, 0, LLONG_MAX);
+}
+
+#ifdef NO_CONV
+/* Build a small version (i.e. for a ramdisk root) */
+static void
+f_conv(char *arg)
+{
+
+       errx(EXIT_FAILURE, "conv option disabled");
+       /* NOTREACHED */
+}
+#else  /* NO_CONV */
+
+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 },
+       /* If you add items to this table, be sure to add the
+        * conversions to the C_BS check in the jcl routine above.
+        */
+};
+
+static void
+f_conv(char *arg)
+{
+       struct conv *cp, tmp;
+
+       while (arg != NULL) {
+               tmp.name = strsep(&arg, ",");
+               if (!(cp = bsearch(&tmp, clist,
+                   __arraycount(clist), sizeof(*clist), c_conv))) {
+                       errx(EXIT_FAILURE, "unknown conversion %s", tmp.name);
+                       /* NOTREACHED */
+               }
+               if (ddflags & cp->noset) {
+                       errx(EXIT_FAILURE,
+                           "%s: illegal conversion combination", tmp.name);
+                       /* NOTREACHED */
+               }
+               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));
+}
+
+#endif /* NO_CONV */
diff --git a/bin/dd/conv.c b/bin/dd/conv.c
new file mode 100644 (file)
index 0000000..d4a8a09
--- /dev/null
@@ -0,0 +1,283 @@
+/*     $NetBSD: conv.c,v 1.17 2003/08/07 09:05:10 agc Exp $    */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. 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";
+#else
+__RCSID("$NetBSD: conv.c,v 1.17 2003/08/07 09:05:10 agc Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <string.h>
+#include <stdlib.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)
+{
+       uint64_t cnt;
+       u_char *inp;
+       const u_char *t;
+
+       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;
+}
+
+#ifdef NO_CONV
+/* Build a smaller version (i.e. for a miniroot) */
+/* These can not be called, but just in case...  */
+static const char no_block[] = "unblock and -DNO_CONV?";
+void block(void)               { errx(EXIT_FAILURE, "%s", no_block + 2); }
+void block_close(void)         { errx(EXIT_FAILURE, "%s", no_block + 2); }
+void unblock(void)             { errx(EXIT_FAILURE, "%s", no_block); }
+void unblock_close(void)       { errx(EXIT_FAILURE, "%s", no_block); }
+#else  /* NO_CONV */
+
+/*
+ * 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)
+{
+       static int intrunc;
+       int ch = 0;     /* pacify gcc */
+       uint64_t cnt, maxlen;
+       u_char *inp, *outp;
+       const u_char *t;
+
+       /*
+        * 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.
+        */
+       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)
+{
+       uint64_t cnt;
+       u_char *inp;
+       const u_char *t;
+
+       /* Translation and case conversion. */
+       if ((t = ctab) != NULL)
+               for (cnt = in.dbrcnt, inp = in.dbp - 1; 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; 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.dbcnt;
+               *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)
+{
+       uint64_t cnt;
+       u_char *t;
+
+       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';
+       }
+}
+
+#endif /* NO_CONV */
diff --git a/bin/dd/conv_tab.c b/bin/dd/conv_tab.c
new file mode 100644 (file)
index 0000000..89d32da
--- /dev/null
@@ -0,0 +1,287 @@
+/*     $NetBSD: conv_tab.c,v 1.9 2003/08/07 09:05:10 agc Exp $ */
+
+/*-
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)conv_tab.c 8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: conv_tab.c,v 1.9 2003/08/07 09:05:10 agc Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+
+/*
+ * 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 (file)
index 0000000..d629696
--- /dev/null
@@ -0,0 +1,477 @@
+.\"    $NetBSD: dd.1,v 1.25 2012/06/20 17:54:16 wiz Exp $
+.\"
+.\" 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
+.\"
+.Dd November 6, 2011
+.Dt DD 1
+.Os
+.Sh NAME
+.Nm dd
+.Nd convert and copy a file
+.Sh SYNOPSIS
+.Nm
+.Op operand ...
+.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 Ar n
+Set both input and output block size, 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 Ar n
+Set the conversion record size to
+.Va n
+bytes.
+The conversion record size is required by the record oriented conversion
+values.
+.It Cm count= Ns Ar n
+Copy only
+.Va n
+input blocks.
+.It Cm files= Ns Ar n
+Copy
+.Va n
+input files before terminating.
+This operand is only applicable when the input device is a tape.
+.It Cm ibs= Ns Ar n
+Set the input block size to
+.Va n
+bytes instead of the default 512.
+.It Cm if= Ns Ar file
+Read input from
+.Ar file
+instead of the standard input.
+.It Cm iseek= Ns Ar n
+Seek on the input file
+.Ar n
+blocks.
+This is synonymous with
+.Cm skip= Ns Ar n .
+.It Cm msgfmt= Ns Ar fmt
+Specify the message format
+.Ar fmt
+to be used when writing information to standard output.
+Possible values are:
+.Bl -tag -width xxxxx -offset indent -compact
+.It quiet
+turns off information summary report except for errors and
+.Cm progress .
+.It posix
+default information summary report as specified by POSIX.
+.It human
+default information summary report extended with human-readable
+values.
+.El
+.Pp
+When
+.Ar fmt
+does not correspond to any value given above,
+it contains a string that will be used as format specifier
+for the information summary output.
+Each conversion specification is introduced by the character
+.Cm % .
+The following ones are available:
+.Bl -tag -width xx -offset indent -compact
+.It b
+total number of bytes transferred
+.It B
+total number of bytes transferred in
+.Xr humanize_number 3
+format
+.It e
+speed transfer
+.It E
+speed transfer in
+.Xr humanize_number 3
+format
+.It i
+number of partial input block(s)
+.It I
+number of full input block(s)
+.It o
+number of partial output block(s)
+.It O
+number of full output block(s)
+.It s
+time elapsed since the beginning in
+.Do seconds.ms Dc
+format
+.It p
+number of sparse output blocks
+.It t
+number of truncated blocks
+.It w
+number of odd-length swab blocks
+.It P
+singular/plural of
+.Do block Dc
+depending on number of sparse blocks
+.It T
+singular/plural of
+.Do block Dc
+depending on number of truncated blocks
+.It W
+singular/plural of
+.Do block Dc
+depending on number of swab blocks
+.El
+.It Cm obs= Ns Ar n
+Set the output block size to
+.Va n
+bytes instead of the default 512.
+.It Cm of= 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 skipped (see the
+.Cm seek
+operand)
+the output file is truncated at that point.
+.It Cm oseek= Ns Ar n
+Seek on the output file
+.Ar n
+blocks.
+This is synonymous with
+.Cm seek= Ns Ar n .
+.It Cm seek= Ns Ar n
+Seek
+.Va 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
+.Tn NUL
+bytes.
+.It Cm skip= Ns Ar n
+Skip
+.Va 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 progress= Ns Ar n
+Switch on display of progress if
+.Va n
+is set to any non-zero value.
+This will cause a
+.Dq \&.
+to be printed (to the standard error output) for every
+.Va n
+full or partial blocks written to the output file.
+.Sm off
+.It Cm conv= Cm value Op \&, Cm value \&...
+.Sm on
+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
+.Tn AT\*[Am]T
+and pre-
+.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
+.Tn AT\*[Am]T
+and pre
+.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
+.Tn 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 Ar n
+block size specification.
+.It Cm sparse
+If one or more non-final 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 .
+This results in a sparse file on some file systems.
+.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
+.Tn 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 number of bytes is expected.
+Two or more numbers may be separated by an
+.Dq x
+to indicate a product.
+Each number may have one of the following optional suffixes:
+.Bl -tag -width 3n -offset indent -compact
+.It b
+Block; multiply by 512
+.It k
+Kibi; multiply by 1024 (1 KiB)
+.It m
+Mebi; multiply by 1048576 (1 MiB)
+.It g
+Gibi; multiply by 1073741824 (1 GiB)
+.It t
+Tebi; multiply by 1099511627776 (1 TiB)
+.It w
+Word; multiply by the number of bytes in an integer
+.El
+.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
+signal
+(see the
+.Ic status
+argument for
+.Xr stty 1 ) ,
+the current input and output block counts will
+be written to the standard error output
+in the same format as the standard completion message.
+If
+.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
+The
+.Nm
+utility exits 0 on success and \*[Gt]0 if an error occurred.
+.Sh EXAMPLES
+To print summary information in human-readable form:
+.Pp
+.Dl dd if=/dev/zero of=/dev/null count=1 msgfmt=human
+.Pp
+To customize the information summary output and print it through
+.Xr unvis 3 :
+.Pp
+.Bd -literal -offset indent
+dd if=/dev/zero of=/dev/null count=1 \e
+     msgfmt='speed:%E, in %s seconds\en' 2\*[Gt]\*[Am]1 | unvis
+.Ed
+.Sh SEE ALSO
+.Xr cp 1 ,
+.Xr mt 1 ,
+.Xr tr 1
+.Sh STANDARDS
+The
+.Nm
+utility is expected to be a superset of the
+.St -p1003.2
+standard.
+The
+.Cm files
+and
+.Cm msgfmt
+operands and the
+.Cm ascii ,
+.Cm ebcdic ,
+.Cm ibm ,
+.Cm oldascii ,
+.Cm oldebcdic
+and
+.Cm oldibm
+values are extensions to the
+.Tn POSIX
+standard.
diff --git a/bin/dd/dd.c b/bin/dd/dd.c
new file mode 100644 (file)
index 0000000..03d080c
--- /dev/null
@@ -0,0 +1,598 @@
+/*     $NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $     */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. 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
+__COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\
+ The Regents of the University of California.  All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)dd.c       8.5 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mtio.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <signal.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 redup_clean_fd(IO *);
+static void setup(void);
+
+int main(int, char *[]);
+
+IO             in, out;                /* input/output state */
+STAT           st;                     /* statistics */
+void           (*cfunc)(void);         /* conversion function */
+uint64_t       cpy_cnt;                /* # of blocks to copy */
+static off_t   pending = 0;            /* pending seek if sparse */
+u_int          ddflags;                /* conversion options */
+uint64_t       cbsz;                   /* conversion block size */
+u_int          files_cnt = 1;          /* # of files to copy */
+uint64_t       progress = 0;           /* display sign of life */
+const u_char   *ctab;                  /* conversion table */
+sigset_t       infoset;                /* a set blocking SIGINFO */
+const char     *msgfmt = "posix";      /* default summary() message format */
+
+/*
+ * Ops for stdin/stdout and crunch'd dd.  These are always host ops.
+ */
+static const struct ddfops ddfops_stdfd = {
+       .op_open = open,
+       .op_close = close,
+       .op_fcntl = fcntl,
+       .op_ioctl = ioctl,
+       .op_fstat = fstat,
+       .op_fsync = fsync,
+       .op_ftruncate = ftruncate,
+       .op_lseek = lseek,
+       .op_read = read,
+       .op_write = write,
+};
+extern const struct ddfops ddfops_prog;
+
+int
+main(int argc, char *argv[])
+{
+       int ch;
+
+       setprogname(argv[0]);
+       (void)setlocale(LC_ALL, "");
+
+       while ((ch = getopt(argc, argv, "")) != -1) {
+               switch (ch) {
+               default:
+                       errx(EXIT_FAILURE, "usage: dd [operand ...]");
+                       /* NOTREACHED */
+               }
+       }
+       argc -= (optind - 1);
+       argv += (optind - 1);
+
+       jcl(argv);
+#ifndef CRUNCHOPS
+       if (ddfops_prog.op_init && ddfops_prog.op_init() == -1)
+               err(1, "prog init");
+#endif
+       setup();
+
+       (void)signal(SIGINFO, summaryx);
+       (void)signal(SIGINT, terminate);
+       (void)sigemptyset(&infoset);
+       (void)sigaddset(&infoset, SIGINFO);
+
+       (void)atexit(summary);
+
+       while (files_cnt--)
+               dd_in();
+
+       dd_close();
+       exit(0);
+       /* NOTREACHED */
+}
+
+static void
+setup(void)
+{
+#ifdef CRUNCHOPS
+       const struct ddfops *prog_ops = &ddfops_stdfd;
+#else
+       const struct ddfops *prog_ops = &ddfops_prog;
+#endif
+
+       if (in.name == NULL) {
+               in.name = "stdin";
+               in.fd = STDIN_FILENO;
+               in.ops = &ddfops_stdfd;
+       } else {
+               in.ops = prog_ops;
+               in.fd = ddop_open(in, in.name, O_RDONLY, 0);
+               if (in.fd < 0)
+                       err(EXIT_FAILURE, "%s", in.name);
+                       /* NOTREACHED */
+
+               /* Ensure in.fd is outside the stdio descriptor range */
+               redup_clean_fd(&in);
+       }
+
+       getfdtype(&in);
+
+       if (files_cnt > 1 && !(in.flags & ISTAPE)) {
+               errx(EXIT_FAILURE, "files is not supported for non-tape devices");
+               /* NOTREACHED */
+       }
+
+       if (out.name == NULL) {
+               /* No way to check for read access here. */
+               out.fd = STDOUT_FILENO;
+               out.name = "stdout";
+               out.ops = &ddfops_stdfd;
+       } else {
+               out.ops = prog_ops;
+#define        OFLAGS \
+    (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
+               out.fd = ddop_open(out, 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 < 0) {
+                       out.fd = ddop_open(out, out.name, O_WRONLY | OFLAGS,
+                           DEFFILEMODE);
+                       out.flags |= NOREAD;
+               }
+               if (out.fd < 0) {
+                       err(EXIT_FAILURE, "%s", out.name);
+                       /* NOTREACHED */
+               }
+
+               /* Ensure out.fd is outside the stdio descriptor range */
+               redup_clean_fd(&out);
+       }
+
+       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))) {
+               size_t dbsz = out.dbsz;
+               if (!(ddflags & C_BS))
+                       dbsz += in.dbsz - 1;
+               if ((in.db = malloc(dbsz)) == NULL) {
+                       err(EXIT_FAILURE, NULL);
+                       /* NOTREACHED */
+               }
+               out.db = in.db;
+       } else if ((in.db =
+           malloc((u_int)(MAX(in.dbsz, cbsz) + cbsz))) == NULL ||
+           (out.db = malloc((u_int)(out.dbsz + cbsz))) == NULL) {
+               err(EXIT_FAILURE, NULL);
+               /* NOTREACHED */
+       }
+       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; ignore errors because it fails on some
+        * kinds of output files, tapes, for example.
+        */
+       if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK))
+               (void)ddop_ftruncate(out, out.fd, (off_t)out.offset * out.dbsz);
+
+       /*
+        * 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)) {
+#ifdef NO_CONV
+               /* Should not get here, but just in case... */
+               errx(EXIT_FAILURE, "case conv and -DNO_CONV");
+               /* NOTREACHED */
+#else  /* NO_CONV */
+               u_int cnt;
+
+               if (ddflags & C_ASCII || ddflags & C_EBCDIC) {
+                       if (ddflags & C_LCASE) {
+                               for (cnt = 0; cnt < 256; ++cnt)
+                                       casetab[cnt] = tolower(ctab[cnt]);
+                       } else {
+                               for (cnt = 0; cnt < 256; ++cnt)
+                                       casetab[cnt] = toupper(ctab[cnt]);
+                       }
+               } else {
+                       if (ddflags & C_LCASE) {
+                               for (cnt = 0; cnt < 256; ++cnt)
+                                       casetab[cnt] = tolower(cnt);
+                       } else {
+                               for (cnt = 0; cnt < 256; ++cnt)
+                                       casetab[cnt] = toupper(cnt);
+                       }
+               }
+
+               ctab = casetab;
+#endif /* NO_CONV */
+       }
+
+       (void)gettimeofday(&st.start, NULL);    /* Statistics timestamp. */
+}
+
+static void
+getfdtype(IO *io)
+{
+       struct mtget mt;
+       struct stat sb;
+
+       if (io->ops->op_fstat(io->fd, &sb)) {
+               err(EXIT_FAILURE, "%s", io->name);
+               /* NOTREACHED */
+       }
+       if (S_ISCHR(sb.st_mode))
+               io->flags |= io->ops->op_ioctl(io->fd, MTIOCGET, &mt)
+                   ? ISCHR : ISTAPE;
+       else if (io->ops->op_lseek(io->fd, (off_t)0, SEEK_CUR) == -1
+           && errno == ESPIPE)
+               io->flags |= ISPIPE;            /* XXX fixed in 4.4BSD */
+}
+
+/*
+ * Move the parameter file descriptor to a descriptor that is outside the
+ * stdio descriptor range, if necessary.  This is required to avoid
+ * accidentally outputting completion or error messages into the
+ * output file that were intended for the tty.
+ */
+static void
+redup_clean_fd(IO *io)
+{
+       int fd = io->fd;
+       int newfd;
+
+       if (fd != STDIN_FILENO && fd != STDOUT_FILENO &&
+           fd != STDERR_FILENO)
+               /* File descriptor is ok, return immediately. */
+               return;
+
+       /*
+        * 3 is the first descriptor greater than STD*_FILENO.  Any
+        * free descriptor valued 3 or above is acceptable...
+        */
+       newfd = io->ops->op_fcntl(fd, F_DUPFD, 3);
+       if (newfd < 0) {
+               err(EXIT_FAILURE, "dupfd IO");
+               /* NOTREACHED */
+       }
+
+       io->ops->op_close(fd);
+       io->fd = newfd;
+}
+
+static void
+dd_in(void)
+{
+       int flags;
+       int64_t n;
+
+       for (flags = ddflags;;) {
+               if (cpy_cnt && (st.in_full + st.in_part) >= cpy_cnt)
+                       return;
+
+               /*
+                * Clear the buffer first if doing "sync" on input.
+                * If doing block operations use spaces.  This will
+                * affect not only the C_NOERROR case, but also the
+                * last partial input block which should be padded
+                * with zero and not garbage.
+                */
+               if (flags & C_SYNC) {
+                       if (flags & (C_BLOCK|C_UNBLOCK))
+                               (void)memset(in.dbp, ' ', in.dbsz);
+                       else
+                               (void)memset(in.dbp, 0, in.dbsz);
+               }
+
+               n = ddop_read(in, in.fd, in.dbp, in.dbsz);
+               if (n == 0) {
+                       in.dbrcnt = 0;
+                       return;
+               }
+
+               /* Read error. */
+               if (n < 0) {
+
+                       /*
+                        * If noerror not specified, die.  POSIX requires that
+                        * the warning message be followed by an I/O display.
+                        */
+                       if (!(flags & C_NOERROR)) {
+                               err(EXIT_FAILURE, "%s", in.name);
+                               /* NOTREACHED */
+                       }
+                       warn("%s", in.name);
+                       summary();
+
+                       /*
+                        * If it's not a tape drive or a pipe, 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 & (ISPIPE|ISTAPE)) &&
+                           ddop_lseek(in, 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 ((uint64_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, n);
+               }
+
+               in.dbp += in.dbrcnt;
+               (*cfunc)();
+       }
+}
+
+/*
+ * Cleanup any remaining I/O and flush output.  If necessary, 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.dbsz) {
+               (void)memset(out.dbp, 0, out.dbsz - out.dbcnt);
+               out.dbcnt = out.dbsz;
+       }
+       /* If there are pending sparse blocks, make sure
+        * to write out the final block un-sparse
+        */
+       if ((out.dbcnt == 0) && pending) {
+               memset(out.db, 0, out.dbsz);
+               out.dbcnt = out.dbsz;
+               out.dbp = out.db + out.dbcnt;
+               pending -= out.dbsz;
+       }
+       if (out.dbcnt)
+               dd_out(1);
+
+       /*
+        * Reporting nfs write error may be deferred until next
+        * write(2) or close(2) system call.  So, we need to do an
+        * extra check.  If an output is stdout, the file structure
+        * may be shared with other processes and close(2) just
+        * decreases the reference count.
+        */
+       if (out.fd == STDOUT_FILENO && ddop_fsync(out, out.fd) == -1
+           && errno != EINVAL) {
+               err(EXIT_FAILURE, "fsync stdout");
+               /* NOTREACHED */
+       }
+       if (ddop_close(out, out.fd) == -1) {
+               err(EXIT_FAILURE, "close");
+               /* NOTREACHED */
+       }
+}
+
+void
+dd_out(int force)
+{
+       static int warned;
+       int64_t cnt, n, nw;
+       u_char *outp;
+
+       /*
+        * 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) {
+
+                       if (!force && ddflags & C_SPARSE) {
+                               int sparse, i;
+                               sparse = 1;     /* Is buffer sparse? */
+                               for (i = 0; i < cnt; i++)
+                                       if (outp[i] != 0) {
+                                               sparse = 0;
+                                               break;
+                                       }
+                               if (sparse) {
+                                       pending += cnt;
+                                       outp += cnt;
+                                       nw = 0;
+                                       break;
+                               }
+                       }
+                       if (pending != 0) {
+                               if (ddop_lseek(out,
+                                   out.fd, pending, SEEK_CUR) == -1)
+                                       err(EXIT_FAILURE, "%s: seek error creating sparse file",
+                                           out.name);
+                       }
+                       nw = bwrite(&out, outp, cnt);
+                       if (nw <= 0) {
+                               if (nw == 0)
+                                       errx(EXIT_FAILURE,
+                                               "%s: end of device", out.name);
+                                       /* NOTREACHED */
+                               if (errno != EINTR)
+                                       err(EXIT_FAILURE, "%s", out.name);
+                                       /* NOTREACHED */
+                               nw = 0;
+                       }
+                       if (pending) {
+                               st.bytes += pending;
+                               st.sparse += pending/out.dbsz;
+                               st.out_full += pending/out.dbsz;
+                               pending = 0;
+                       }
+                       outp += nw;
+                       st.bytes += nw;
+                       if (nw == n) {
+                               if ((uint64_t)n != out.dbsz)
+                                       ++st.out_part;
+                               else
+                                       ++st.out_full;
+                               break;
+                       }
+                       ++st.out_part;
+                       if (nw == cnt)
+                               break;
+                       if (out.flags & ISCHR && !warned) {
+                               warned = 1;
+                               warnx("%s: short write on character device", out.name);
+                       }
+                       if (out.flags & ISTAPE)
+                               errx(EXIT_FAILURE,
+                                       "%s: short write on tape device", out.name);
+                               /* NOTREACHED */
+
+               }
+               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;
+
+       if (progress && (st.out_full + st.out_part) % progress == 0)
+               (void)write(STDERR_FILENO, ".", 1);
+}
+
+/*
+ * A protected against SIGINFO write
+ */
+ssize_t
+bwrite(IO *io, const void *buf, size_t len)
+{
+       sigset_t oset;
+       ssize_t rv;
+       int oerrno;
+
+       (void)sigprocmask(SIG_BLOCK, &infoset, &oset);
+       rv = io->ops->op_write(io->fd, buf, len);
+       oerrno = errno;
+       (void)sigprocmask(SIG_SETMASK, &oset, NULL);
+       errno = oerrno;
+       return (rv);
+}
diff --git a/bin/dd/dd.h b/bin/dd/dd.h
new file mode 100644 (file)
index 0000000..4aea519
--- /dev/null
@@ -0,0 +1,123 @@
+/*     $NetBSD: dd.h,v 1.15 2011/02/04 19:42:12 pooka Exp $    */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. 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
+ */
+
+#include <sys/stat.h>
+
+struct ddfops {
+       int (*op_init)(void);
+
+       int (*op_open)(const char *, int, ...);
+       int (*op_close)(int);
+
+       int (*op_fcntl)(int, int, ...);
+       int (*op_ioctl)(int, unsigned long, ...);
+
+       int (*op_fstat)(int, struct stat *);
+       int (*op_fsync)(int);
+       int (*op_ftruncate)(int, off_t);
+
+       off_t (*op_lseek)(int, off_t, int);
+
+       ssize_t (*op_read)(int, void *, size_t);
+       ssize_t (*op_write)(int, const void *, size_t);
+};
+
+#define ddop_open(dir, a1, a2, ...)    dir.ops->op_open(a1, a2, __VA_ARGS__)
+#define ddop_close(dir, a1)            dir.ops->op_close(a1)
+#define ddop_fcntl(dir, a1, a2, ...)   dir.ops->op_fcntl(a1, a2, __VA_ARGS__)
+#define ddop_ioctl(dir, a1, a2, ...)   dir.ops->op_ioctl(a1, a2, __VA_ARGS__)
+#define ddop_fsync(dir, a1)            dir.ops->op_fsync(a1)
+#define ddop_ftruncate(dir, a1, a2)    dir.ops->op_ftruncate(a1, a2)
+#define ddop_lseek(dir, a1, a2, a3)    dir.ops->op_lseek(a1, a2, a3)
+#define ddop_read(dir, a1, a2, a3)     dir.ops->op_read(a1, a2, a3)
+#define ddop_write(dir, a1, a2, a3)    dir.ops->op_write(a1, a2, a3)
+
+/* Input/output stream state. */
+typedef struct {
+       u_char          *db;            /* buffer address */
+       u_char          *dbp;           /* current buffer I/O address */
+       uint64_t        dbcnt;          /* current buffer byte count */
+       int64_t         dbrcnt;         /* last read byte count */
+       uint64_t        dbsz;           /* buffer size */
+
+#define        ISCHR           0x01            /* character device (warn on short) */
+#define        ISPIPE          0x02            /* pipe (not truncatable) */
+#define        ISTAPE          0x04            /* tape (not seekable) */
+#define        NOREAD          0x08            /* not readable */
+       u_int           flags;
+
+       const char      *name;          /* name */
+       int             fd;             /* file descriptor */
+       uint64_t        offset;         /* # of blocks to skip */
+       struct ddfops   const *ops;     /* ops to use with fd */
+} IO;
+
+typedef struct {
+       uint64_t        in_full;        /* # of full input blocks */
+       uint64_t        in_part;        /* # of partial input blocks */
+       uint64_t        out_full;       /* # of full output blocks */
+       uint64_t        out_part;       /* # of partial output blocks */
+       uint64_t        trunc;          /* # of truncated records */
+       uint64_t        swab;           /* # of odd-length swab blocks */
+       uint64_t        sparse;         /* # of sparse output blocks */
+       uint64_t        bytes;          /* # of bytes written */
+       struct timeval  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
diff --git a/bin/dd/dd_hostops.c b/bin/dd/dd_hostops.c
new file mode 100644 (file)
index 0000000..d6e7a89
--- /dev/null
@@ -0,0 +1,53 @@
+/*      $NetBSD: dd_hostops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $    */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: dd_hostops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $");
+#endif /* !lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "dd.h"
+
+const struct ddfops ddfops_prog = {
+       .op_open = open,
+       .op_close = close,
+       .op_fcntl = fcntl,
+       .op_ioctl = ioctl,
+       .op_fstat = fstat,
+       .op_fsync = fsync,
+       .op_ftruncate = ftruncate,
+       .op_lseek = lseek,
+       .op_read = read,
+       .op_write = write,
+};
diff --git a/bin/dd/dd_rumpops.c b/bin/dd/dd_rumpops.c
new file mode 100644 (file)
index 0000000..71f7db4
--- /dev/null
@@ -0,0 +1,52 @@
+/*      $NetBSD: dd_rumpops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $    */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: dd_rumpops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $");
+#endif /* !lint */
+
+#include <rump/rump_syscalls.h>
+#include <rump/rumpclient.h>
+
+#include "dd.h"
+
+const struct ddfops ddfops_prog = {
+       .op_init = rumpclient_init,
+
+       .op_open = rump_sys_open,
+       .op_close = rump_sys_close,
+       .op_fcntl = rump_sys_fcntl,
+       .op_ioctl = rump_sys_ioctl,
+       .op_fstat = rump_sys_fstat,
+       .op_fsync = rump_sys_fsync,
+       .op_ftruncate = rump_sys_ftruncate,
+       .op_lseek = rump_sys_lseek,
+       .op_read = rump_sys_read,
+       .op_write = rump_sys_write,
+};
diff --git a/bin/dd/extern.h b/bin/dd/extern.h
new file mode 100644 (file)
index 0000000..9c59021
--- /dev/null
@@ -0,0 +1,82 @@
+/*     $NetBSD: extern.h,v 1.22 2011/11/07 22:24:23 jym Exp $  */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. 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
+ */
+
+#include <sys/cdefs.h>
+
+#ifdef NO_CONV
+__dead void block(void);
+__dead void block_close(void);
+__dead void unblock(void);
+__dead void unblock_close(void);
+#else
+void block(void);
+void block_close(void);
+void unblock(void);
+void unblock_close(void);
+#endif
+
+#ifndef NO_MSGFMT
+int dd_write_msg(const char *, int);
+#endif
+
+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);
+__dead void terminate(int);
+void unblock(void);
+void unblock_close(void);
+ssize_t bwrite(IO *, const void *, size_t);
+
+extern IO              in, out;
+extern STAT            st;
+extern void            (*cfunc)(void);
+extern uint64_t                cpy_cnt;
+extern uint64_t                cbsz;
+extern u_int           ddflags;
+extern u_int           files_cnt;
+extern uint64_t                progress;
+extern const u_char    *ctab;
+extern const u_char    a2e_32V[], a2e_POSIX[];
+extern const u_char    e2a_32V[], e2a_POSIX[];
+extern const u_char    a2ibm_32V[], a2ibm_POSIX[];
+extern u_char          casetab[];
+extern const char      *msgfmt;
diff --git a/bin/dd/misc.c b/bin/dd/misc.c
new file mode 100644 (file)
index 0000000..0fac98b
--- /dev/null
@@ -0,0 +1,342 @@
+/*     $NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $    */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. 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";
+#else
+__RCSID("$NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+#include <inttypes.h>
+
+#include "dd.h"
+#include "extern.h"
+
+#define        tv2mS(tv) ((tv).tv_sec * 1000LL + ((tv).tv_usec + 500) / 1000)
+
+static void posix_summary(void);
+#ifndef NO_MSGFMT
+static void custom_summary(void);
+static void human_summary(void);
+static void quiet_summary(void);
+
+static void buffer_write(const char *, size_t, int);
+#endif /* NO_MSGFMT */
+
+void
+summary(void)
+{
+
+       if (progress)
+               (void)write(STDERR_FILENO, "\n", 1);
+
+#ifdef NO_MSGFMT
+       return posix_summary();
+#else /* NO_MSGFMT */
+       if (strncmp(msgfmt, "human", sizeof("human")) == 0)
+               return human_summary();
+
+       if (strncmp(msgfmt, "posix", sizeof("posix")) == 0)
+               return posix_summary();
+
+       if (strncmp(msgfmt, "quiet", sizeof("quiet")) == 0)
+               return quiet_summary();
+
+       return custom_summary();
+#endif /* NO_MSGFMT */
+}
+
+static void
+posix_summary(void)
+{
+       char buf[100];
+       int64_t mS;
+       struct timeval tv;
+
+       if (progress)
+               (void)write(STDERR_FILENO, "\n", 1);
+
+       (void)gettimeofday(&tv, NULL);
+       mS = tv2mS(tv) - tv2mS(st.start);
+       if (mS == 0)
+               mS = 1;
+
+       /* Use snprintf(3) so that we don't reenter stdio(3). */
+       (void)snprintf(buf, sizeof(buf),
+           "%llu+%llu records in\n%llu+%llu records out\n",
+           (unsigned long long)st.in_full,  (unsigned long long)st.in_part,
+           (unsigned long long)st.out_full, (unsigned long long)st.out_part);
+       (void)write(STDERR_FILENO, buf, strlen(buf));
+       if (st.swab) {
+               (void)snprintf(buf, sizeof(buf), "%llu odd length swab %s\n",
+                   (unsigned long long)st.swab,
+                   (st.swab == 1) ? "block" : "blocks");
+               (void)write(STDERR_FILENO, buf, strlen(buf));
+       }
+       if (st.trunc) {
+               (void)snprintf(buf, sizeof(buf), "%llu truncated %s\n",
+                   (unsigned long long)st.trunc,
+                   (st.trunc == 1) ? "block" : "blocks");
+               (void)write(STDERR_FILENO, buf, strlen(buf));
+       }
+       if (st.sparse) {
+               (void)snprintf(buf, sizeof(buf), "%llu sparse output %s\n",
+                   (unsigned long long)st.sparse,
+                   (st.sparse == 1) ? "block" : "blocks");
+               (void)write(STDERR_FILENO, buf, strlen(buf));
+       }
+       (void)snprintf(buf, sizeof(buf),
+           "%llu bytes transferred in %lu.%03d secs (%llu bytes/sec)\n",
+           (unsigned long long) st.bytes,
+           (long) (mS / 1000),
+           (int) (mS % 1000),
+           (unsigned long long) (st.bytes * 1000LL / mS));
+       (void)write(STDERR_FILENO, buf, strlen(buf));
+}
+
+/* ARGSUSED */
+void
+summaryx(int notused)
+{
+
+       summary();
+}
+
+/* ARGSUSED */
+void
+terminate(int signo)
+{
+
+       summary();
+       (void)raise_default_signal(signo);
+       _exit(127);
+}
+
+#ifndef NO_MSGFMT
+/*
+ * Buffer write(2) calls
+ */
+static void
+buffer_write(const char *str, size_t size, int flush)
+{
+       static char wbuf[128];
+       static size_t cnt = 0; /* Internal counter to allow wbuf to wrap */
+       
+       unsigned int i;
+
+       for (i = 0; i < size; i++) {
+               if (str != NULL) {
+                       wbuf[cnt++] = str[i];
+               }
+               if (cnt >= sizeof(wbuf)) {
+                       (void)write(STDERR_FILENO, wbuf, cnt);
+                       cnt = 0;
+               }
+       }
+
+       if (flush != 0) {
+               (void)write(STDERR_FILENO, wbuf, cnt);
+               cnt = 0;
+       }
+}
+
+/*
+ * Write summary to stderr according to format 'fmt'. If 'enable' is 0, it
+ * will not attempt to write anything. Can be used to validate the
+ * correctness of the 'fmt' string.
+ */
+int
+dd_write_msg(const char *fmt, int enable)
+{
+       char hbuf[7], nbuf[32];
+       const char *ptr;
+       int64_t mS;
+       struct timeval tv;
+
+       (void)gettimeofday(&tv, NULL);
+       mS = tv2mS(tv) - tv2mS(st.start);
+       if (mS == 0)
+               mS = 1;
+
+#define ADDC(c) do { if (enable != 0) buffer_write(&c, 1, 0); } \
+       while (/*CONSTCOND*/0)
+#define ADDS(p) do { if (enable != 0) buffer_write(p, strlen(p), 0); } \
+       while (/*CONSTCOND*/0)
+
+       for (ptr = fmt; *ptr; ptr++) {
+               if (*ptr != '%') {
+                       ADDC(*ptr);
+                       continue;
+               }
+
+               switch (*++ptr) {
+               case 'b':
+                       (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+                           (unsigned long long)st.bytes);
+                       ADDS(nbuf);
+                       break;
+               case 'B':
+                       if (humanize_number(hbuf, sizeof(hbuf),
+                           st.bytes, "B",
+                           HN_AUTOSCALE, HN_DECIMAL) == -1)
+                               warnx("humanize_number (bytes transferred)");
+                       ADDS(hbuf);
+                       break;
+               case 'e':
+                       (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+                           (unsigned long long) (st.bytes * 1000LL / mS));
+                       ADDS(nbuf);
+                       break;
+               case 'E':
+                       if (humanize_number(hbuf, sizeof(hbuf),
+                           st.bytes * 1000LL / mS, "B",
+                           HN_AUTOSCALE, HN_DECIMAL) == -1)
+                               warnx("humanize_number (bytes per second)");
+                       ADDS(hbuf); ADDS("/sec");
+                       break;
+               case 'i':
+                       (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+                           (unsigned long long)st.in_part);
+                       ADDS(nbuf);
+                       break;
+               case 'I':
+                       (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+                           (unsigned long long)st.in_full);
+                       ADDS(nbuf);
+                       break;
+               case 'o':
+                       (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+                           (unsigned long long)st.out_part);
+                       ADDS(nbuf);
+                       break;
+               case 'O':
+                       (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+                           (unsigned long long)st.out_full);
+                       ADDS(nbuf);
+                       break;
+               case 's':
+                       (void)snprintf(nbuf, sizeof(nbuf), "%li.%03d",
+                           (long) (mS / 1000), (int) (mS % 1000));
+                       ADDS(nbuf);
+                       break;
+               case 'p':
+                       (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+                           (unsigned long long)st.sparse);
+                       ADDS(nbuf);
+                       break;
+               case 't':
+                       (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+                           (unsigned long long)st.trunc);
+                       ADDS(nbuf);
+                       break;
+               case 'w':
+                       (void)snprintf(nbuf, sizeof(nbuf), "%llu",
+                           (unsigned long long)st.swab);
+                       ADDS(nbuf);
+                       break;
+               case 'P':
+                       ADDS("block");
+                       if (st.sparse != 1) ADDS("s");
+                       break;
+               case 'T':
+                       ADDS("block");
+                       if (st.trunc != 1) ADDS("s");
+                       break;
+               case 'W':
+                       ADDS("block");
+                       if (st.swab != 1) ADDS("s");
+                       break;
+               case '%':
+                       ADDC(*ptr);
+                       break;
+               default:
+                       if (*ptr == '\0')
+                               goto done;
+                       errx(EXIT_FAILURE, "unknown specifier '%c' in "
+                           "msgfmt string", *ptr);
+                       /* NOTREACHED */
+               }
+       }
+
+done:
+       /* flush buffer */
+       buffer_write(NULL, 0, 1);
+       return 0;
+}
+
+static void
+custom_summary(void)
+{
+
+       dd_write_msg(msgfmt, 1);
+}
+
+static void
+human_summary(void)
+{
+       (void)dd_write_msg("%I+%i records in\n%O+%o records out\n", 1);
+       if (st.swab) {
+               (void)dd_write_msg("%w odd length swab %W\n", 1);
+       }
+       if (st.trunc) {
+               (void)dd_write_msg("%t truncated %T\n", 1);
+       }
+       if (st.sparse) {
+               (void)dd_write_msg("%p sparse output %P\n", 1);
+       }
+       (void)dd_write_msg("%b bytes (%B) transferred in %s secs "
+           "(%e bytes/sec - %E)\n", 1);
+}
+
+static void
+quiet_summary(void)
+{
+
+       /* stay quiet */
+}
+#endif /* NO_MSGFMT */
diff --git a/bin/dd/position.c b/bin/dd/position.c
new file mode 100644 (file)
index 0000000..36dd580
--- /dev/null
@@ -0,0 +1,185 @@
+/*     $NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $      */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. 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";
+#else
+__RCSID("$NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mtio.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.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)
+{
+       int bcnt, cnt, nr, warned;
+
+       /* If not a pipe or tape device, try to seek on it. */
+       if (!(in.flags & (ISPIPE|ISTAPE))) {
+               if (ddop_lseek(in, in.fd,
+                   (off_t)in.offset * (off_t)in.dbsz, SEEK_CUR) == -1) {
+                       err(EXIT_FAILURE, "%s", in.name);
+                       /* NOTREACHED */
+               }
+               return;
+               /* NOTREACHED */
+       }
+
+       /*
+        * 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 = ddop_read(in, 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(EXIT_FAILURE, "skip reached end of input");
+                       /* NOTREACHED */
+               }
+
+               /*
+                * 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(EXIT_FAILURE, "%s", in.name);
+               /* NOTREACHED */
+       }
+}
+
+void
+pos_out(void)
+{
+       struct mtop t_op;
+       int n;
+       uint64_t cnt;
+
+       /*
+        * 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 & ISTAPE)) {
+               if (ddop_lseek(out, out.fd,
+                   (off_t)out.offset * (off_t)out.dbsz, SEEK_SET) == -1)
+                       err(EXIT_FAILURE, "%s", out.name);
+                       /* NOTREACHED */
+               return;
+       }
+
+       /* If no read access, try using mtio. */
+       if (out.flags & NOREAD) {
+               t_op.mt_op = MTFSR;
+               t_op.mt_count = out.offset;
+
+               if (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) < 0)
+                       err(EXIT_FAILURE, "%s", out.name);
+                       /* NOTREACHED */
+               return;
+       }
+
+       /* Read it. */
+       for (cnt = 0; cnt < out.offset; ++cnt) {
+               if ((n = ddop_read(out, out.fd, out.db, out.dbsz)) > 0)
+                       continue;
+
+               if (n < 0)
+                       err(EXIT_FAILURE, "%s", out.name);
+                       /* NOTREACHED */
+
+               /*
+                * 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 (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) == -1)
+                       err(EXIT_FAILURE, "%s", out.name);
+                       /* NOTREACHED */
+
+               while (cnt++ < out.offset)
+                       if ((uint64_t)(n = bwrite(&out,
+                           out.db, out.dbsz)) != out.dbsz)
+                               err(EXIT_FAILURE, "%s", out.name);
+                               /* NOTREACHED */
+               break;
+       }
+}
index 54cfc7cac75916908d99e5d5e1076181b9dc399d..0df3cdd89245ac9f9bbd1a4650acc324460351a4 100644 (file)
@@ -17,6 +17,7 @@
 ./bin/cp                               minix-sys
 ./bin/cpio                             minix-sys
 ./bin/date                             minix-sys
+./bin/dd                               minix-sys
 ./bin/df                               minix-sys
 ./bin/echo                             minix-sys
 ./bin/ed                               minix-sys
 ./usr/bin/ctags                                minix-sys
 ./usr/bin/cut                          minix-sys
 ./usr/bin/datasizes                    minix-sys       obsolete
-./usr/bin/dd                           minix-sys
+./usr/bin/dd                           minix-sys       obsolete
 ./usr/bin/decomp16                     minix-sys
 ./usr/bin/del_route                    minix-sys
 ./usr/bin/deroff                       minix-sys
index 4b845747d5dc1dc02bf4f178ae3b961ddf7d52a7..ab521ff8636f6378e52bcf95f93b6d8b224fa144 100644 (file)
@@ -6,7 +6,7 @@ SUBDIR= add_route arp at backup btrace \
        cawf cdprobe \
        ci cleantmp cmp co \
        compress crc cron crontab \
-       dd decomp16 DESCRIBE devmand devsize dhcpd \
+       decomp16 DESCRIBE devmand devsize dhcpd \
        dhrystone diff diskctl \
        eject fbdctl \
        find fix format fsck.mfs \
diff --git a/minix/commands/dd/Makefile b/minix/commands/dd/Makefile
deleted file mode 100644 (file)
index d1177c8..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# LSC For now
-NOGCCERROR:=yes
-PROG=  dd
-MAN=
-
-.include <bsd.prog.mk>
diff --git a/minix/commands/dd/dd.c b/minix/commands/dd/dd.c
deleted file mode 100644 (file)
index 0f30cde..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-/* dd - disk dumper */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#define EOS '\0'
-#define BOOLEAN int
-#define TRUE 1
-#define FALSE 0
-
-char *pch, *errorp;
-
-int main(int argc, char **argv);
-BOOLEAN is(char *pc);
-int num(void);
-void puto(void);
-void statistics(void);
-int ulcase(int c);
-void cnull(int c);
-void null(int c);
-void extra(void);
-void over(int dummy);
-
-BOOLEAN is(pc)
-char *pc;
-{
-  register char *ps = pch;
-
-  while (*ps++ == *pc++)
-       if (*pc == EOS) {
-               pch = ps;
-               return(TRUE);
-       }
-  return(FALSE);
-}
-
-#define BIGNUM  2147483647
-
-int num()
-{
-  long ans;
-  register char *pc;
-
-  pc = pch;
-  ans = 0L;
-  while ((*pc >= '0') && (*pc <= '9'))
-       ans = (long) ((*pc++ - '0') + (ans * 10));
-  while (TRUE) switch (*pc++) {
-           case 'w':
-               ans *= 2L;
-               continue;
-           case 'b':
-               ans *= 512L;
-               continue;
-           case 'k':
-               ans *= 1024L;
-               continue;
-           case 'x':
-               pch = pc;
-               ans *= (long) num();
-           case EOS:
-               if ((ans >= BIGNUM) || (ans < 0)) {
-                       fprintf(stderr, "dd: argument %s out of range\n",
-                               errorp);
-                       exit(1);
-               }
-               return((int) ans);
-       }
-}
-
-#define SWAB 0x0001
-#define LCASE 0x0002
-#define UCASE 0x0004
-#define NOERROR 0x0008
-#define SYNC 0x0010
-#define SILENT 0x0020
-#define NOTRUNC 0x0040
-#define BLANK ' '
-#define DEFAULT 512
-
-unsigned cbs, bs, skip, nseek, count;
-int seekseen = FALSE;
-unsigned ibs = DEFAULT;
-unsigned obs = DEFAULT;
-unsigned files = 1;
-char *ifilename = NULL;
-char *ofilename = NULL;
-
-int convflag = 0;
-int flag = 0;
-int ifd, ofd, ibc;
-char *ibuf, *obuf, *op;
-unsigned nifull, nipartial, nofull, nopartial;
-int cbc;
-unsigned ntr, obc;
-int ns;
-char mlen[] = {64, 45, 82, 45, 83, 96, 109, 100, 109, 97, 96, 116, 108, 9};
-
-void puto()
-{
-  int n;
-
-  if (obc == 0) return;
-  if (obc == obs)
-       nofull++;
-  else
-       nopartial++;
-  if ((n = write(ofd, obuf, obc)) != obc) {
-       if (n == -1) {
-               fprintf(stderr, "dd: Write error: %s\n", strerror(errno));
-       } else {
-               fprintf(stderr, "dd: Short write, %d instead of %d\n", n, obc);
-       }
-       exit(1);
-  }
-  obc = 0;
-}
-
-void statistics()
-{
-  if (convflag & SILENT) return;
-  fprintf(stderr, "%u+%u records in\n", nifull, nipartial);
-  fprintf(stderr, "%u+%u records out\n", nofull, nopartial);
-  if (ntr) fprintf(stderr, "%d truncated records\n", ntr);
-}
-
-
-int main(argc, argv)
-int argc;
-char *argv[];
-{
-#ifdef __STDC__
-  void (*convert) (int);
-#else
-  void (*convert) ();
-#endif
-  char *iptr;
-  int i, j, oflags;
-
-  convert = null;
-  argc--;
-  argv++;
-  while (argc-- > 0) {
-       pch = *(argv++);
-       if (is("ibs=")) {
-               errorp = pch;
-               ibs = num();
-               continue;
-       }
-       if (is("obs=")) {
-               errorp = pch;
-               obs = num();
-               continue;
-       }
-       if (is("bs=")) {
-               errorp = pch;
-               bs = num();
-               continue;
-       }
-       if (is("if=")) {
-               ifilename = pch;
-               continue;
-       }
-       if (is("of=")) {
-               ofilename = pch;
-               continue;
-       }
-       if (is("skip=")) {
-               errorp = pch;
-               skip = num();
-               continue;
-       }
-       if (is("seek=")) {
-               errorp = pch;
-               nseek = num();
-               seekseen = TRUE;
-               continue;
-       }
-       if (is("count=")) {
-               errorp = pch;
-               count = num();
-               continue;
-       }
-       if (is("files=")) {
-               errorp = pch;
-               files = num();
-               continue;
-       }
-       if (is("length=")) {
-               errorp = pch;
-               for (j = 0; j < 13; j++) mlen[j]++;
-               write(2, mlen, 14);
-               continue;
-       }
-       if (is("conv=")) {
-               while (*pch != EOS) {
-                       if (is("lcase")) {
-                               convflag |= LCASE;
-                               continue;
-                       }
-                       if (is("ucase")) {
-                               convflag |= UCASE;
-                               continue;
-                       }
-                       if (is("noerror")) {
-                               convflag |= NOERROR;
-                               continue;
-                       }
-                       if (is("notrunc")) {
-                               convflag |= NOTRUNC;
-                               continue;
-                       }
-                       if (is("sync")) {
-                               convflag |= SYNC;
-                               continue;
-                       }
-                       if (is("swab")) {
-                               convflag |= SWAB;
-                               continue;
-                       }
-                       if (is("silent")) {
-                               convflag |= SILENT;
-                               continue;
-                       }
-                       if (is(",")) continue;
-                       fprintf(stderr, "dd: bad argument: %s\n",
-                               pch);
-                       exit(1);
-               }
-               if (*pch == EOS) continue;
-       }
-       fprintf(stderr, "dd: bad argument: %s\n", pch);
-       exit(1);
-  }
-  if ((convert == null) && (convflag & (UCASE | LCASE))) convert = cnull;
-  if ((ifd = ((ifilename) ? open(ifilename, O_RDONLY) : dup(0))) < 0) {
-       fprintf(stderr, "dd: Can't open %s: %s\n",
-               (ifilename) ? ifilename : "stdin", strerror(errno));
-       exit(1);
-  }
-  oflags = O_WRONLY | O_CREAT;
-  if (!seekseen && (convflag & NOTRUNC) != NOTRUNC)
-       oflags |= O_TRUNC;
-  if ((ofd = ((ofilename) ? open(ofilename, oflags, 0666)
-                       : dup(1))) < 0) {
-       fprintf(stderr, "dd: Can't open %s: %s\n",
-               (ofilename) ? ofilename : "stdout", strerror(errno));
-       exit(1);
-  }
-  if (bs) {
-       ibs = obs = bs;
-       if (convert == null) flag++;
-  }
-  if (ibs == 0) {
-       fprintf(stderr, "dd: ibs cannot be zero\n");
-       exit(1);
-  }
-  if (obs == 0) {
-       fprintf(stderr, "dd: obs cannot be zero\n");
-       exit(1);
-  }
-  if ((ibuf = sbrk(ibs)) == (char *) -1) {
-       fprintf(stderr, "dd: not enough memory\n");
-       exit(1);
-  }
-  if ((obuf = (flag) ? ibuf : sbrk(obs)) == (char *) -1) {
-       fprintf(stderr, "dd: not enough memory\n");
-       exit(1);
-  }
-  ibc = obc = cbc = 0;
-  op = obuf;
-  if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, over);
-  if (skip != 0) {
-       struct stat st;
-       if (fstat(ifd,&st) < 0 || !(S_ISREG(st.st_mode) || S_ISBLK(st.st_mode))
-          || lseek(ifd, (off_t) ibs * (off_t) skip, SEEK_SET) == (off_t) -1) {
-               do {
-                       if (read(ifd, ibuf, ibs) == -1) {
-                               fprintf(stderr,
-                                       "dd: Error skipping input: %s\n",
-                                       strerror(errno));
-                               exit(1);
-                       }
-               } while (--skip != 0);
-       }
-  }
-  if (nseek != 0) {
-       if (lseek(ofd, (off_t) obs * (off_t) nseek, SEEK_SET) == (off_t) -1) {
-               fprintf(stderr, "dd: Seeking on output failed: %s\n",
-                       strerror(errno));
-               exit(1);
-       }
-  }
-
-outputall:
-  if (ibc-- == 0) {
-       ibc = 0;
-       if ((count == 0) || ((nifull + nipartial) != count)) {
-               if (convflag & (NOERROR | SYNC))
-                       for (iptr = ibuf + ibs; iptr > ibuf;) *--iptr = 0;
-               ibc = read(ifd, ibuf, ibs);
-       }
-       if (ibc == -1) {
-               fprintf(stderr, "dd: Read error: %s\n", strerror(errno));
-               if ((convflag & NOERROR) == 0) {
-                       puto();
-                       over(0);
-               }
-               ibc = 0;
-               for (i = 0; i < ibs; i++)
-                       if (ibuf[i] != 0) ibc = i;
-               statistics();
-       }
-       if ((ibc == 0) && (--files <= 0)) {
-               puto();
-               over(0);
-       }
-       if (ibc != ibs) {
-               nipartial++;
-               if (convflag & SYNC) ibc = ibs;
-       } else
-               nifull++;
-       iptr = ibuf;
-       i = ibc >> 1;
-       if ((convflag & SWAB) && i) do {
-                       int temp;
-                       temp = *iptr++;
-                       iptr[-1] = *iptr;
-                       *iptr++ = temp;
-               } while (--i);
-       iptr = ibuf;
-       if (flag) {
-               obc = ibc;
-               puto();
-               ibc = 0;
-       }
-       goto outputall;
-  }
-  i = *iptr++ & 0377;
-  (*convert) (i);
-  goto outputall;
-}
-
-int ulcase(c)
-int c;
-{
-  int ans = c;
-
-  if ((convflag & UCASE) && (c >= 'a') &&
-      (c <= 'z'))
-       ans += 'A' - 'a';
-  if ((convflag & LCASE) && (c >= 'A') &&
-      (c <= 'Z'))
-       ans += 'a' - 'A';
-  return(ans);
-}
-
-void cnull(c)
-int c;
-{
-  c = ulcase(c);
-  null(c);
-}
-
-void null(c)
-int c;
-{
-  *op++ = c;
-  if (++obc >= obs) {
-       puto();
-       op = obuf;
-  }
-}
-
-void extra()
-{
-  if (++cbc >= cbs) {
-       null('\n');
-       cbc = 0;
-       ns = 0;
-  }
-}
-
-void over(sig)
-int sig;
-{
-  statistics();
-  if (sig != 0) {
-       signal(sig, SIG_DFL);
-       raise(sig);
-  }
-  exit(0);
-}
index 4a4d52dbcdde266fbd04c0c9d6d1a64be21674b2..48d0af70606ac684dc211808a752a63ec97f3f41 100644 (file)
@@ -1,7 +1,7 @@
 MAN=   at.1 \
        bsfilt.1 cawf.1 chgrp.1 \
        cmp.1 compress.1 \
-       crc.1 crontab.1 dd.1 \
+       crc.1 crontab.1 \
        dhrystone.1 dosdir.1 dosread.1 doswrite.1 \
        eject.1 \
        flexdoc.1 format.1 \
diff --git a/minix/man/man1/dd.1 b/minix/man/man1/dd.1
deleted file mode 100644 (file)
index fcf15e2..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-.TH DD 1
-.SH NAME
-dd \- convert and copy a file
-.SH SYNOPSIS
-\fBdd\fR [\fIoption = value\fR] ...\fR
-.br
-.de FL
-.TP
-\\fB\\$1\\fR
-\\$2
-..
-.de EX
-.TP 20
-\\fB\\$1\\fR
-# \\$2
-..
-.SH EXAMPLES
-.TP 20
-.B dd if=/dev/fd0 of=/dev/fd1
-# Copy disk 0 to disk 1
-.TP 20
-.B dd if=x of=y bs=1w skip=4
-# Copy \fIx\fP to \fIy\fP, skipping 4 words
-.TP 20
-.B dd if=x of=y count=3
-# Copy three 512\-byte blocks
-.SH DESCRIPTION
-.PP
-This command is intended for copying partial files.
-The block size, skip count, and number of blocks to copy can be specified.
-The options are:
-.PP
-.ta 0.25i 1.5i
-       \fBif\fR = file \- Input file (default is \fIstdin\fR)
-.br
-       \fBof\fR = file \- Output file (default is standard output)
-.br
-       \fBibs\fR = n   \- Input block size (default 512 bytes)
-.br
-       \fBobs\fR = n   \- Output block size (default is 512 bytes)
-.br
-       \fBbs\fR = n    \- Block size; sets \fIibs\fP and \fIobs\fP (default is 512 bytes)
-.br
-       \fBskip\fR = n  \- Skip \fIn\fP input blocks before reading
-.br
-       \fBseek\fR = n  \- Skip \fIn\fP output blocks before writing
-.br
-       \fBcount\fR = n \- Copy only \fIn\fP input blocks
-.br
-       \fBconv = lcase\fR      \- Convert upper case letters to lower case
-.br
-       \fBconv = ucase\fR      \- Convert lower case letters to upper case
-.br
-       \fBconv = swab\fR       \- Swap every pair of bytes
-.br
-       \fBconv = noerror\fR    \- Ignore errors and just keep going
-.br
-       \fBconv = notrunc\fR    \- Do not truncate unmodified blocks
-.br
-       \fBconv = silent\fR     \- Suppress statistics (MINIX 3 specific flag)
-.PP
-Where sizes are expected, they are in bytes.
-However, the letters \fBw\fR, \fBb\fR, or \fBk\fR may be appended to the
-number to indicate words (2 bytes), blocks (512 bytes), or K
-(1024 bytes), respectively.
-When
-.I dd
-is finished, it reports the number of full and partial blocks read and written.
-.SH "SEE ALSO"
-.BR vol (1).