From e3cfc8ce61f788739c66445d903f8beacb40c93d Mon Sep 17 00:00:00 2001 From: rgrimes Date: Thu, 26 May 1994 06:18:55 +0000 Subject: BSD 4.4 Lite bin Sources --- bin/dd/Makefile | 6 + bin/dd/args.c | 386 ++++++++++++++++++++++++++++++++++++++++++++++++++++ bin/dd/conv.c | 260 +++++++++++++++++++++++++++++++++++ bin/dd/conv_tab.c | 357 ++++++++++++++++++++++++++++++++++++++++++++++++ bin/dd/dd.1 | 348 +++++++++++++++++++++++++++++++++++++++++++++++ bin/dd/dd.c | 395 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ bin/dd/dd.h | 96 +++++++++++++ bin/dd/extern.h | 65 +++++++++ bin/dd/misc.c | 100 ++++++++++++++ bin/dd/position.c | 166 +++++++++++++++++++++++ 10 files changed, 2179 insertions(+) create mode 100644 bin/dd/Makefile create mode 100644 bin/dd/args.c create mode 100644 bin/dd/conv.c create mode 100644 bin/dd/conv_tab.c create mode 100644 bin/dd/dd.1 create mode 100644 bin/dd/dd.c create mode 100644 bin/dd/dd.h create mode 100644 bin/dd/extern.h create mode 100644 bin/dd/misc.c create mode 100644 bin/dd/position.c (limited to 'bin/dd') diff --git a/bin/dd/Makefile b/bin/dd/Makefile new file mode 100644 index 0000000..fc4965b --- /dev/null +++ b/bin/dd/Makefile @@ -0,0 +1,6 @@ +# @(#)Makefile 8.1 (Berkeley) 5/31/93 + +PROG= dd +SRCS= args.c conv.c conv_tab.c dd.c misc.c position.c + +.include diff --git a/bin/dd/args.c b/bin/dd/args.c new file mode 100644 index 0000000..3c2f3a2 --- /dev/null +++ b/bin/dd/args.c @@ -0,0 +1,386 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)args.c 8.3 (Berkeley) 4/2/94"; +#endif /* not lint */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "dd.h" +#include "extern.h" + +static int c_arg __P((const void *, const void *)); +static int c_conv __P((const void *, const void *)); +static void f_bs __P((char *)); +static void f_cbs __P((char *)); +static void f_conv __P((char *)); +static void f_count __P((char *)); +static void f_files __P((char *)); +static void f_ibs __P((char *)); +static void f_if __P((char *)); +static void f_obs __P((char *)); +static void f_of __P((char *)); +static void f_seek __P((char *)); +static void f_skip __P((char *)); +static u_long get_bsz __P((char *)); + +static struct arg { + char *name; + void (*f) __P((char *)); + u_int set, noset; +} args[] = { + { "bs", f_bs, C_BS, C_BS|C_IBS|C_OBS|C_OSYNC }, + { "cbs", f_cbs, C_CBS, C_CBS }, + { "conv", f_conv, 0, 0 }, + { "count", f_count, C_COUNT, C_COUNT }, + { "files", f_files, C_FILES, C_FILES }, + { "ibs", f_ibs, C_IBS, C_BS|C_IBS }, + { "if", f_if, C_IF, C_IF }, + { "obs", f_obs, C_OBS, C_BS|C_OBS }, + { "of", f_of, C_OF, C_OF }, + { "seek", f_seek, C_SEEK, C_SEEK }, + { "skip", f_skip, C_SKIP, C_SKIP }, +}; + +static char *oper; + +/* + * args -- parse JCL syntax of dd. + */ +void +jcl(argv) + char **argv; +{ + struct arg *ap, tmp; + char *arg; + + in.dbsz = out.dbsz = 512; + + while (oper = *++argv) { + if ((arg = strchr(oper, '=')) == NULL) + errx(1, "unknown operand %s", oper); + *arg++ = '\0'; + if (!*arg) + errx(1, "no value specified for %s", oper); + tmp.name = oper; + if (!(ap = (struct arg *)bsearch(&tmp, args, + sizeof(args)/sizeof(struct arg), sizeof(struct arg), + c_arg))) + errx(1, "unknown operand %s", tmp.name); + if (ddflags & ap->noset) + errx(1, "%s: illegal argument combination or already set", + tmp.name); + ddflags |= ap->set; + ap->f(arg); + } + + /* Final sanity checks. */ + + if (ddflags & C_BS) { + /* + * Bs is turned off by any conversion -- we assume the user + * just wanted to set both the input and output block sizes + * and didn't want the bs semantics, so we don't warn. + */ + if (ddflags & (C_BLOCK|C_LCASE|C_SWAB|C_UCASE|C_UNBLOCK)) + ddflags &= ~C_BS; + + /* Bs supersedes ibs and obs. */ + if (ddflags & C_BS && ddflags & (C_IBS|C_OBS)) + warnx("bs supersedes ibs and obs"); + } + + /* + * Ascii/ebcdic and cbs implies block/unblock. + * Block/unblock requires cbs and vice-versa. + */ + if (ddflags & (C_BLOCK|C_UNBLOCK)) { + if (!(ddflags & C_CBS)) + errx(1, "record operations require cbs"); + if (cbsz == 0) + errx(1, "cbs cannot be zero"); + cfunc = ddflags & C_BLOCK ? block : unblock; + } else if (ddflags & C_CBS) { + if (ddflags & (C_ASCII|C_EBCDIC)) { + if (ddflags & C_ASCII) { + ddflags |= C_UNBLOCK; + cfunc = unblock; + } else { + ddflags |= C_BLOCK; + cfunc = block; + } + } else + errx(1, "cbs meaningless if not doing record operations"); + if (cbsz == 0) + errx(1, "cbs cannot be zero"); + } else + cfunc = def; + + if (in.dbsz == 0 || out.dbsz == 0) + errx(1, "buffer sizes cannot be zero"); + + /* + * Read, write and seek calls take ints as arguments. Seek sizes + * could be larger if we wanted to do it in stages or check only + * regular files, but it's probably not worth it. + */ + if (in.dbsz > INT_MAX || out.dbsz > INT_MAX) + errx(1, "buffer sizes cannot be greater than %d", INT_MAX); + 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(a, b) + const void *a, *b; +{ + + return (strcmp(((struct arg *)a)->name, ((struct arg *)b)->name)); +} + +static void +f_bs(arg) + char *arg; +{ + + in.dbsz = out.dbsz = (int)get_bsz(arg); +} + +static void +f_cbs(arg) + char *arg; +{ + + cbsz = (int)get_bsz(arg); +} + +static void +f_count(arg) + char *arg; +{ + + cpy_cnt = (u_int)get_bsz(arg); + if (!cpy_cnt) + terminate(0); +} + +static void +f_files(arg) + char *arg; +{ + + files_cnt = (int)get_bsz(arg); +} + +static void +f_ibs(arg) + char *arg; +{ + + if (!(ddflags & C_BS)) + in.dbsz = (int)get_bsz(arg); +} + +static void +f_if(arg) + char *arg; +{ + + in.name = arg; +} + +static void +f_obs(arg) + char *arg; +{ + + if (!(ddflags & C_BS)) + out.dbsz = (int)get_bsz(arg); +} + +static void +f_of(arg) + char *arg; +{ + + out.name = arg; +} + +static void +f_seek(arg) + char *arg; +{ + + out.offset = (u_int)get_bsz(arg); +} + +static void +f_skip(arg) + char *arg; +{ + + in.offset = (u_int)get_bsz(arg); +} + +static struct conv { + char *name; + u_int set, noset; + 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 }, + { "swab", C_SWAB, 0, NULL }, + { "sync", C_SYNC, 0, NULL }, + { "ucase", C_UCASE, C_LCASE, NULL }, + { "unblock", C_UNBLOCK, C_BLOCK, NULL }, +}; + +static void +f_conv(arg) + char *arg; +{ + struct conv *cp, tmp; + + while (arg != NULL) { + tmp.name = strsep(&arg, ","); + if (!(cp = (struct conv *)bsearch(&tmp, clist, + sizeof(clist)/sizeof(struct conv), sizeof(struct conv), + c_conv))) + errx(1, "unknown conversion %s", tmp.name); + if (ddflags & cp->noset) + errx(1, "%s: illegal conversion combination", tmp.name); + ddflags |= cp->set; + if (cp->ctab) + ctab = cp->ctab; + } +} + +static int +c_conv(a, b) + const void *a, *b; +{ + + return (strcmp(((struct conv *)a)->name, ((struct conv *)b)->name)); +} + +/* + * Convert an expression of the following forms to an unsigned long. + * 1) A positive decimal number. + * 2) A positive decimal number followed by a b (mult by 512). + * 3) A positive decimal number followed by a k (mult by 1024). + * 4) A positive decimal number followed by a m (mult by 512). + * 5) A positive decimal number followed by a w (mult by sizeof int) + * 6) Two or more positive decimal numbers (with/without k,b or w). + * seperated by x (also * for backwards compatibility), specifying + * the product of the indicated values. + */ +static u_long +get_bsz(val) + char *val; +{ + u_long num, t; + char *expr; + + num = strtoul(val, &expr, 0); + if (num == ULONG_MAX) /* Overflow. */ + err(1, "%s", oper); + if (expr == val) /* No digits. */ + errx(1, "%s: illegal numeric value", oper); + + switch(*expr) { + case 'b': + t = num; + num *= 512; + if (t > num) + goto erange; + ++expr; + break; + case 'k': + t = num; + num *= 1024; + if (t > num) + goto erange; + ++expr; + break; + case 'm': + t = num; + num *= 1048576; + if (t > num) + goto erange; + ++expr; + break; + case 'w': + t = num; + num *= sizeof(int); + if (t > num) + goto erange; + ++expr; + break; + } + + switch(*expr) { + case '\0': + break; + case '*': /* Backward compatible. */ + case 'x': + t = num; + num *= get_bsz(expr + 1); + if (t > num) +erange: errx(1, "%s: %s", oper, strerror(ERANGE)); + break; + default: + errx(1, "%s: illegal numeric value", oper); + } + return (num); +} diff --git a/bin/dd/conv.c b/bin/dd/conv.c new file mode 100644 index 0000000..69fa8cf --- /dev/null +++ b/bin/dd/conv.c @@ -0,0 +1,260 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94"; +#endif /* not lint */ + +#include + +#include +#include + +#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() +{ + int cnt; + u_char *inp, *t; + + if (t = ctab) + 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() +{ + /* Just update the count, everything is already in the buffer. */ + if (in.dbcnt) + out.dbcnt = in.dbcnt; +} + +/* + * Copy variable length newline terminated records with a max size cbsz + * bytes to output. Records less than cbs are padded with spaces. + * + * max in buffer: MAX(ibs, cbsz) + * max out buffer: obs + cbsz + */ +void +block() +{ + static int intrunc; + int ch, cnt, maxlen; + u_char *inp, *outp, *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) + 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) { + 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() +{ + /* + * 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; + 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() +{ + int cnt; + u_char *inp, *t; + + /* Translation and case conversion. */ + if (t = ctab) + for (cnt = in.dbrcnt, inp = in.dbp; cnt--;) + *--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; + 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) + memmove(in.db, in.dbp - in.dbcnt, in.dbcnt); + in.dbp = in.db + in.dbcnt; +} + +void +unblock_close() +{ + int 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; + memmove(out.dbp, in.db, cnt); + out.dbp += cnt; + out.dbcnt += cnt; + } + ++out.dbcnt; + *out.dbp++ = '\n'; + } +} diff --git a/bin/dd/conv_tab.c b/bin/dd/conv_tab.c new file mode 100644 index 0000000..5d238d5 --- /dev/null +++ b/bin/dd/conv_tab.c @@ -0,0 +1,357 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)conv_tab.c 8.1 (Berkeley) 5/31/93"; +#endif /* not lint */ + +#include + +/* + * There are currently eight tables: + * + * lower-case -> upper-case conv=upper + * upper-case -> lower-case conv=lower + * + * 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. + */ + +/* Lower-case to upper-case */ +u_char l2u[] = { + 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, /* 0000 */ + 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, /* 0010 */ + 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, /* 0020 */ + 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, /* 0030 */ + 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, /* 0040 */ + 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, /* 0050 */ + 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0060 */ + 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, /* 0070 */ + 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0100 */ + 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, /* 0110 */ + 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0120 */ + 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137, /* 0130 */ + 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0140 */ + 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, /* 0150 */ + 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0160 */ + 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177, /* 0170 */ + 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0200 */ + 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, /* 0210 */ + 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, /* 0220 */ + 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, /* 0230 */ + 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, /* 0240 */ + 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0250 */ + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0260 */ + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0270 */ + 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0300 */ + 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, /* 0310 */ + 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, /* 0320 */ + 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0330 */ + 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, /* 0340 */ + 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, /* 0350 */ + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0360 */ + 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ +}; + +/* Upper-case to lower-case */ +u_char u2l[] = { + 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, /* 0000 */ + 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, /* 0010 */ + 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, /* 0020 */ + 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, /* 0030 */ + 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, /* 0040 */ + 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, /* 0050 */ + 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0060 */ + 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, /* 0070 */ + 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0100 */ + 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, /* 0110 */ + 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, /* 0120 */ + 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137, /* 0130 */ + 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0140 */ + 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, /* 0150 */ + 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, /* 0160 */ + 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177, /* 0170 */ + 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0200 */ + 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, /* 0210 */ + 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, /* 0220 */ + 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, /* 0230 */ + 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, /* 0240 */ + 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0250 */ + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0260 */ + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0270 */ + 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0300 */ + 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, /* 0310 */ + 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, /* 0320 */ + 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0330 */ + 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, /* 0340 */ + 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, /* 0350 */ + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0360 */ + 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ +}; + +/* EBCDIC to ASCII -- 32V compatible. */ +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. */ +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. */ +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. */ +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. */ +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. */ +u_char a2ibm_POSIX[] = { + 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */ + 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */ + 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */ + 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */ + 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */ + 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */ + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */ + 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */ + 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */ + 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */ + 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */ + 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, /* 0130 */ + 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */ + 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */ + 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */ + 0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, /* 0170 */ + 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */ + 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */ + 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */ + 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */ + 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */ + 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */ + 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */ + 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */ + 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */ + 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */ + 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */ + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */ + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */ + 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */ + 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */ + 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ +}; diff --git a/bin/dd/dd.1 b/bin/dd/dd.1 new file mode 100644 index 0000000..0b20781 --- /dev/null +++ b/bin/dd/dd.1 @@ -0,0 +1,348 @@ +.\" Copyright (c) 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Keith Muller of the University of California, San Diego. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)dd.1 8.2 (Berkeley) 1/13/94 +.\" +.Dd January 13, 1994 +.Dt DD 1 +.Os +.Sh NAME +.Nm dd +.Nd convert and copy a file +.Sh SYNOPSIS +.Nm dd +.Op operands ... +.Sh DESCRIPTION +The +.Nm +utility copies the standard input to the standard output. +Input data is read and written in 512-byte blocks. +If input reads are short, input from multiple reads are aggregated +to form the output block. +When finished, +.Nm dd +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 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 seek= Ns Ar n +Seek +.Va n +blocks from the beginning of the output before copying. +On non-tape devices, a +.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, a +.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 Xo +.Cm conv= +.Ns Cm value Ns Op \&, Cm value \&... +.Xc +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 ECBDIC +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 System V. +The value +.Cm oldascii +specifies the one used in historic +.Tn AT&T +and pre-4.3BSD-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&T +and pre-4.3BSD-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 dd . +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 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. +If the number ends with a ``b'', ``k'', ``m'' or ``w'', the number +is multiplied by 512, 1024 (1K), 1048576 (1M) or the number of bytes +in an integer, respectively. +Two or more numbers may be separated by an ``x'' to indicate a product. +.Pp +When finished, +.Nm dd +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 dd +receives a +.Dv SIGINFO +(see the ``status'' argument for +.Xr stty 1 ) +signal, the current input and output block counts will +be written to the standard error output +in the same format as the standard completion message. +If +.Nm dd +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 dd +will exit. +.Pp +The +.Nm dd +utility exits 0 on success and >0 if an error occurred. +.Sh SEE ALSO +.Xr cp 1 , +.Xr mt 1 , +.Xr tr 1 +.Sh STANDARDS +The +.Nm dd +utility is expected to be a superset of the +.St -p1003.2 +standard. +The +.Cm files +operand and the +.Cm ascii , +.Cm ebcdic , +.Cm ibm , +.Cm oldascii , +.Cm oldebcdic +and +.Cm oldibm +values are extensions to the +.Tn POSIX +standard. diff --git a/bin/dd/dd.c b/bin/dd/dd.c new file mode 100644 index 0000000..05ac7a9 --- /dev/null +++ b/bin/dd/dd.c @@ -0,0 +1,395 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dd.h" +#include "extern.h" + +static void dd_close __P((void)); +static void dd_in __P((void)); +static void getfdtype __P((IO *)); +static void setup __P((void)); + +IO in, out; /* input/output state */ +STAT st; /* statistics */ +void (*cfunc) __P((void)); /* conversion function */ +u_long cpy_cnt; /* # of blocks to copy */ +u_int ddflags; /* conversion options */ +u_int cbsz; /* conversion block size */ +u_int files_cnt = 1; /* # of files to copy */ +u_char *ctab; /* conversion table */ + +int +main(argc, argv) + int argc; + char *argv[]; +{ + jcl(argv); + setup(); + + (void)signal(SIGINFO, summaryx); + (void)signal(SIGINT, terminate); + + atexit(summary); + + while (files_cnt--) + dd_in(); + + dd_close(); + exit(0); +} + +static void +setup() +{ + u_int cnt; + + if (in.name == NULL) { + in.name = "stdin"; + in.fd = STDIN_FILENO; + } else { + in.fd = open(in.name, O_RDONLY, 0); + if (in.fd < 0) + err(1, "%s", in.name); + } + + getfdtype(&in); + + if (files_cnt > 1 && !(in.flags & ISTAPE)) + errx(1, "files is not supported for non-tape devices"); + + if (out.name == NULL) { + /* No way to check for read access here. */ + out.fd = STDOUT_FILENO; + out.name = "stdout"; + } else { +#define OFLAGS \ + (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC)) + out.fd = open(out.name, O_RDWR | OFLAGS, DEFFILEMODE); + /* + * May not have read access, so try again with write only. + * Without read we may have a problem if output also does + * not support seeks. + */ + if (out.fd < 0) { + out.fd = open(out.name, O_WRONLY | OFLAGS, DEFFILEMODE); + out.flags |= NOREAD; + } + if (out.fd < 0) + err(1, "%s", out.name); + } + + getfdtype(&out); + + /* + * Allocate space for the input and output buffers. If not doing + * record oriented I/O, only need a single buffer. + */ + if (!(ddflags & (C_BLOCK|C_UNBLOCK))) { + if ((in.db = malloc(out.dbsz + in.dbsz - 1)) == NULL) + err(1, NULL); + 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(1, NULL); + 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)ftruncate(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)) + if (ddflags & C_ASCII) + if (ddflags & C_LCASE) { + for (cnt = 0; cnt < 0377; ++cnt) + if (isupper(ctab[cnt])) + ctab[cnt] = tolower(ctab[cnt]); + } else { + for (cnt = 0; cnt < 0377; ++cnt) + if (islower(ctab[cnt])) + ctab[cnt] = toupper(ctab[cnt]); + } + else if (ddflags & C_EBCDIC) + if (ddflags & C_LCASE) { + for (cnt = 0; cnt < 0377; ++cnt) + if (isupper(cnt)) + ctab[cnt] = ctab[tolower(cnt)]; + } else { + for (cnt = 0; cnt < 0377; ++cnt) + if (islower(cnt)) + ctab[cnt] = ctab[toupper(cnt)]; + } + else + ctab = ddflags & C_LCASE ? u2l : l2u; + (void)time(&st.start); /* Statistics timestamp. */ +} + +static void +getfdtype(io) + IO *io; +{ + struct mtget mt; + struct stat sb; + + if (fstat(io->fd, &sb)) + err(1, "%s", io->name); + if (S_ISCHR(sb.st_mode)) + io->flags |= ioctl(io->fd, MTIOCGET, &mt) ? ISCHR : ISTAPE; + else if (lseek(io->fd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) + io->flags |= ISPIPE; /* XXX fixed in 4.4BSD */ +} + +static void +dd_in() +{ + int flags, n; + + for (flags = ddflags;;) { + if (cpy_cnt && (st.in_full + st.in_part) >= cpy_cnt) + return; + + /* + * Zero the buffer first if trying to recover from errors so + * lose the minimum amount of data. If doing block operations + * use spaces. + */ + if ((flags & (C_NOERROR|C_SYNC)) == (C_NOERROR|C_SYNC)) + if (flags & (C_BLOCK|C_UNBLOCK)) + memset(in.dbp, ' ', in.dbsz); + else + memset(in.dbp, 0, in.dbsz); + + n = read(in.fd, in.dbp, in.dbsz); + if (n == 0) { + in.dbrcnt = 0; + return; + } + + /* Read error. */ + if (n < 0) { + /* + * If noerror not specified, die. POSIX requires that + * the warning message be followed by an I/O display. + */ + if (!(flags & C_NOERROR)) + err(1, "%s", in.name); + 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)) && + lseek(in.fd, (off_t)in.dbsz, SEEK_CUR)) + warn("%s", in.name); + + /* If sync not specified, omit block and continue. */ + if (!(ddflags & C_SYNC)) + continue; + + /* Read errors count as full blocks. */ + in.dbcnt += in.dbrcnt = in.dbsz; + ++st.in_full; + + /* Handle full input blocks. */ + } else if (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.dbcnt) & 1) { + ++st.swab; + --n; + } + swab(in.dbp, in.dbp, n); + } + + in.dbp += in.dbrcnt; + (*cfunc)(); + } +} + +/* + * Cleanup any remaining I/O and flush output. If necesssary, output file + * is truncated. + */ +static void +dd_close() +{ + 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) { + memset(out.dbp, 0, out.dbsz - out.dbcnt); + out.dbcnt = out.dbsz; + } + if (out.dbcnt) + dd_out(1); +} + +void +dd_out(force) + int force; +{ + static int warned; + int 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) { + nw = write(out.fd, outp, cnt); + if (nw <= 0) { + if (nw == 0) + errx(1, "%s: end of device", out.name); + if (errno != EINTR) + err(1, "%s", out.name); + nw = 0; + } + outp += nw; + st.bytes += nw; + if (nw == n) { + if (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(1, "%s: short write on tape device", out.name); + } + if ((out.dbcnt -= n) < out.dbsz) + break; + } + + /* Reassemble the output block. */ + if (out.dbcnt) + memmove(out.db, out.dbp - out.dbcnt, out.dbcnt); + out.dbp = out.db + out.dbcnt; +} diff --git a/bin/dd/dd.h b/bin/dd/dd.h new file mode 100644 index 0000000..3b790a7 --- /dev/null +++ b/bin/dd/dd.h @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dd.h 8.3 (Berkeley) 4/2/94 + */ + +/* Input/output stream state. */ +typedef struct { + u_char *db; /* buffer address */ + u_char *dbp; /* current buffer I/O address */ + u_long dbcnt; /* current buffer byte count */ + int dbrcnt; /* last read byte count */ + u_long 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; + + char *name; /* name */ + int fd; /* file descriptor */ + u_long offset; /* # of blocks to skip */ + + u_long f_stats; /* # of full blocks processed */ + u_long p_stats; /* # of partial blocks processed */ + u_long s_stats; /* # of odd swab blocks */ + u_long t_stats; /* # of truncations */ +} IO; + +typedef struct { + u_long in_full; /* # of full input blocks */ + u_long in_part; /* # of partial input blocks */ + u_long out_full; /* # of full output blocks */ + u_long out_part; /* # of partial output blocks */ + u_long trunc; /* # of truncated records */ + u_long swab; /* # of odd-length swab blocks */ + u_long bytes; /* # of bytes written */ + time_t 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 diff --git a/bin/dd/extern.h b/bin/dd/extern.h new file mode 100644 index 0000000..e8fde63 --- /dev/null +++ b/bin/dd/extern.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.3 (Berkeley) 4/2/94 + */ + +#include + +void block __P((void)); +void block_close __P((void)); +void dd_out __P((int)); +void def __P((void)); +void def_close __P((void)); +void jcl __P((char **)); +void pos_in __P((void)); +void pos_out __P((void)); +void summary __P((void)); +void summaryx __P((int)); +void terminate __P((int)); +void unblock __P((void)); +void unblock_close __P((void)); + +extern IO in, out; +extern STAT st; +extern void (*cfunc)(); +extern u_long cpy_cnt; +extern u_int cbsz; +extern u_int ddflags; +extern u_int files_cnt; +extern u_char *ctab; +extern u_char a2e_32V[], a2e_POSIX[], a2ibm_32V[], a2ibm_POSIX[], e2a_32V[]; +extern u_char e2a_POSIX[], l2u[], u2l[]; diff --git a/bin/dd/misc.c b/bin/dd/misc.c new file mode 100644 index 0000000..db90352 --- /dev/null +++ b/bin/dd/misc.c @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)misc.c 8.3 (Berkeley) 4/2/94"; +#endif /* not lint */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "dd.h" +#include "extern.h" + +void +summary() +{ + time_t secs; + char buf[100]; + + (void)time(&secs); + if ((secs -= st.start) == 0) + secs = 1; + /* Use snprintf(3) so that we don't reenter stdio(3). */ + (void)snprintf(buf, sizeof(buf), + "%u+%u records in\n%u+%u records out\n", + st.in_full, st.in_part, st.out_full, st.out_part); + (void)write(STDERR_FILENO, buf, strlen(buf)); + if (st.swab) { + (void)snprintf(buf, sizeof(buf), "%u odd length swab %s\n", + st.swab, (st.swab == 1) ? "block" : "blocks"); + (void)write(STDERR_FILENO, buf, strlen(buf)); + } + if (st.trunc) { + (void)snprintf(buf, sizeof(buf), "%u truncated %s\n", + st.trunc, (st.trunc == 1) ? "block" : "blocks"); + (void)write(STDERR_FILENO, buf, strlen(buf)); + } + (void)snprintf(buf, sizeof(buf), + "%u bytes transferred in %u secs (%u bytes/sec)\n", + st.bytes, secs, st.bytes / secs); + (void)write(STDERR_FILENO, buf, strlen(buf)); +} + +/* ARGSUSED */ +void +summaryx(notused) + int notused; +{ + + summary(); +} + +/* ARGSUSED */ +void +terminate(notused) + int notused; +{ + + exit(0); +} diff --git a/bin/dd/position.c b/bin/dd/position.c new file mode 100644 index 0000000..9375b1e --- /dev/null +++ b/bin/dd/position.c @@ -0,0 +1,166 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Keith Muller of the University of California, San Diego and Lance + * Visser of Convex Computer Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#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() +{ + int bcnt, cnt, nr, warned; + + /* If not a character, pipe or tape device, try to seek on it. */ + if (!(in.flags & (ISCHR|ISPIPE|ISTAPE))) { + if (lseek(in.fd, (off_t)(in.offset * in.dbsz), SEEK_CUR) == -1) + err(1, "%s", in.name); + return; + } + + /* + * Read the data. If a pipe, read until satisfy the number of bytes + * being skipped. No differentiation for reading complete and partial + * blocks for other devices. + */ + for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) { + if ((nr = read(in.fd, in.db, bcnt)) > 0) { + if (in.flags & ISPIPE) { + if (!(bcnt -= nr)) { + bcnt = in.dbsz; + --cnt; + } + } else + --cnt; + continue; + } + + if (nr == 0) { + if (files_cnt > 1) { + --files_cnt; + continue; + } + errx(1, "skip reached end of input"); + } + + /* + * Input error -- either EOF with no more files, or I/O error. + * If noerror not set die. POSIX requires that the warning + * message be followed by an I/O display. + */ + if (ddflags & C_NOERROR) { + if (!warned) { + warn("%s", in.name); + warned = 1; + summary(); + } + continue; + } + err(1, "%s", in.name); + } +} + +void +pos_out() +{ + struct mtop t_op; + int cnt, n; + + /* + * If not a tape, try seeking on the file. Seeking on a pipe is + * going to fail, but don't protect the user -- they shouldn't + * have specified the seek operand. + */ + if (!(out.flags & ISTAPE)) { + if (lseek(out.fd, + (off_t)out.offset * out.dbsz, SEEK_SET) == -1) + err(1, "%s", out.name); + return; + } + + /* If no read access, try using mtio. */ + if (out.flags & NOREAD) { + t_op.mt_op = MTFSR; + t_op.mt_count = out.offset; + + if (ioctl(out.fd, MTIOCTOP, &t_op) < 0) + err(1, "%s", out.name); + return; + } + + /* Read it. */ + for (cnt = 0; cnt < out.offset; ++cnt) { + if ((n = read(out.fd, out.db, out.dbsz)) > 0) + continue; + + if (n < 0) + err(1, "%s", out.name); + + /* + * If reach EOF, fill with NUL characters; first, back up over + * the EOF mark. Note, cnt has not yet been incremented, so + * the EOF read does not count as a seek'd block. + */ + t_op.mt_op = MTBSR; + t_op.mt_count = 1; + if (ioctl(out.fd, MTIOCTOP, &t_op) == -1) + err(1, "%s", out.name); + + while (cnt++ < out.offset) + if ((n = write(out.fd, out.db, out.dbsz)) != out.dbsz) + err(1, "%s", out.name); + break; + } +} -- cgit v1.1