Importing bin/dd
Change-Id: Ibdfed821aa834419c9713dc80f698c8ed74ff269
This commit is contained in:
parent
9cf6cc5098
commit
c19d619d42
19 changed files with 2899 additions and 481 deletions
|
@ -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
|
||||
|
||||
|
|
21
bin/dd/Makefile
Normal file
21
bin/dd/Makefile
Normal file
|
@ -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>
|
391
bin/dd/args.c
Normal file
391
bin/dd/args.c
Normal file
|
@ -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 */
|
283
bin/dd/conv.c
Normal file
283
bin/dd/conv.c
Normal file
|
@ -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 */
|
287
bin/dd/conv_tab.c
Normal file
287
bin/dd/conv_tab.c
Normal file
|
@ -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 */
|
||||
};
|
477
bin/dd/dd.1
Normal file
477
bin/dd/dd.1
Normal file
|
@ -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.
|
598
bin/dd/dd.c
Normal file
598
bin/dd/dd.c
Normal file
|
@ -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);
|
||||
}
|
123
bin/dd/dd.h
Normal file
123
bin/dd/dd.h
Normal file
|
@ -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
|
53
bin/dd/dd_hostops.c
Normal file
53
bin/dd/dd_hostops.c
Normal file
|
@ -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,
|
||||
};
|
52
bin/dd/dd_rumpops.c
Normal file
52
bin/dd/dd_rumpops.c
Normal file
|
@ -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,
|
||||
};
|
82
bin/dd/extern.h
Normal file
82
bin/dd/extern.h
Normal file
|
@ -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;
|
342
bin/dd/misc.c
Normal file
342
bin/dd/misc.c
Normal file
|
@ -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 */
|
185
bin/dd/position.c
Normal file
185
bin/dd/position.c
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
@ -326,7 +327,7 @@
|
|||
./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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
# LSC For now
|
||||
NOGCCERROR:=yes
|
||||
PROG= dd
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -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);
|
||||
}
|
|
@ -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 \
|
||||
|
|
|
@ -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).
|
Loading…
Reference in a new issue