17bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes/* $NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $ */ 27bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 37bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes/*- 47bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Copyright (c) 1991, 1993, 1994 57bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * The Regents of the University of California. All rights reserved. 67bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 77bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * This code is derived from software contributed to Berkeley by 87bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Keith Muller of the University of California, San Diego and Lance 97bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Visser of Convex Computer Corporation. 107bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 117bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Redistribution and use in source and binary forms, with or without 127bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * modification, are permitted provided that the following conditions 137bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * are met: 147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 1. Redistributions of source code must retain the above copyright 157bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * notice, this list of conditions and the following disclaimer. 167bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 2. Redistributions in binary form must reproduce the above copyright 177bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * notice, this list of conditions and the following disclaimer in the 187bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * documentation and/or other materials provided with the distribution. 197bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 3. Neither the name of the University nor the names of its contributors 207bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * may be used to endorse or promote products derived from this software 217bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * without specific prior written permission. 227bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 237bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 247bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 257bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 267bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 277bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 287bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 297bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 307bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 317bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 327bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 337bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * SUCH DAMAGE. 347bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 357bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 367bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <sys/cdefs.h> 377bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#ifndef lint 387bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes__COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\ 397bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes The Regents of the University of California. All rights reserved."); 407bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif /* not lint */ 417bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 427bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#ifndef lint 437bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#if 0 447bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94"; 457bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#else 467bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes__RCSID("$NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $"); 477bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif 487bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif /* not lint */ 497bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 507bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <sys/param.h> 517bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <sys/stat.h> 527bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <sys/ioctl.h> 537bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <sys/mtio.h> 547bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <sys/time.h> 557bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 567bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <ctype.h> 577bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <err.h> 587bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <errno.h> 597bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <fcntl.h> 607bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <locale.h> 617bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <signal.h> 627bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <stdio.h> 637bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <stdlib.h> 647bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <string.h> 657bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <unistd.h> 667bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 677bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include "dd.h" 687bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include "extern.h" 697bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 707bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void dd_close(void); 717bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void dd_in(void); 727bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void getfdtype(IO *); 737bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void redup_clean_fd(IO *); 747bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void setup(void); 757bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 767bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesint main(int, char *[]); 777bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 787bb5660647d0106f96b000c25f5690a45734c38cElliott HughesIO in, out; /* input/output state */ 797bb5660647d0106f96b000c25f5690a45734c38cElliott HughesSTAT st; /* statistics */ 807bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesvoid (*cfunc)(void); /* conversion function */ 817bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesuint64_t cpy_cnt; /* # of blocks to copy */ 827bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic off_t pending = 0; /* pending seek if sparse */ 837bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesu_int ddflags; /* conversion options */ 847bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesuint64_t cbsz; /* conversion block size */ 857bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesu_int files_cnt = 1; /* # of files to copy */ 867bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesuint64_t progress = 0; /* display sign of life */ 877bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesconst u_char *ctab; /* conversion table */ 887bb5660647d0106f96b000c25f5690a45734c38cElliott Hughessigset_t infoset; /* a set blocking SIGINFO */ 897bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesconst char *msgfmt = "posix"; /* default summary() message format */ 907bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 917bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes/* 927bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Ops for stdin/stdout and crunch'd dd. These are always host ops. 937bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 947bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic const struct ddfops ddfops_stdfd = { 957bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes .op_open = open, 967bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes .op_close = close, 977bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes .op_fcntl = fcntl, 987bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes .op_ioctl = ioctl, 997bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes .op_fstat = fstat, 1007bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes .op_fsync = fsync, 1017bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes .op_ftruncate = ftruncate, 1027bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes .op_lseek = lseek, 1037bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes .op_read = read, 1047bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes .op_write = write, 1057bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes}; 1067bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesextern const struct ddfops ddfops_prog; 1077bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1087bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesint 1097bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesmain(int argc, char *argv[]) 1107bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 1117bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int ch; 1127bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1137bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes setprogname(argv[0]); 1147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)setlocale(LC_ALL, ""); 1157bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1167bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes while ((ch = getopt(argc, argv, "")) != -1) { 1177bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes switch (ch) { 1187bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes default: 1197bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes errx(EXIT_FAILURE, "usage: dd [operand ...]"); 1207bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 1217bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 1227bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 1237bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes argc -= (optind - 1); 1247bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes argv += (optind - 1); 1257bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1267bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes jcl(argv); 1277bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#ifndef CRUNCHOPS 1287bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (ddfops_prog.op_init && ddfops_prog.op_init() == -1) 1297bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(1, "prog init"); 1307bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif 1317bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes setup(); 1327bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1337bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)signal(SIGINFO, summaryx); 1347bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)signal(SIGINT, terminate); 1357bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)sigemptyset(&infoset); 1367bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)sigaddset(&infoset, SIGINFO); 1377bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1387bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)atexit(summary); 1397bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1407bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes while (files_cnt--) 1417bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes dd_in(); 1427bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1437bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes dd_close(); 1447bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes exit(0); 1457bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 1467bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 1477bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1487bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void 1497bb5660647d0106f96b000c25f5690a45734c38cElliott Hughessetup(void) 1507bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 1517bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#ifdef CRUNCHOPS 1527bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes const struct ddfops *prog_ops = &ddfops_stdfd; 1537bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#else 1547bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes const struct ddfops *prog_ops = &ddfops_prog; 1557bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif 1567bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1577bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (in.name == NULL) { 1587bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes in.name = "stdin"; 1597bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes in.fd = STDIN_FILENO; 1607bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes in.ops = &ddfops_stdfd; 1617bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } else { 1627bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes in.ops = prog_ops; 1637bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes in.fd = ddop_open(in, in.name, O_RDONLY, 0); 1647bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (in.fd < 0) 1657bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(EXIT_FAILURE, "%s", in.name); 1667bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 1677bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1687bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* Ensure in.fd is outside the stdio descriptor range */ 1697bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes redup_clean_fd(&in); 1707bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 1717bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1727bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes getfdtype(&in); 1737bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1747bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (files_cnt > 1 && !(in.flags & ISTAPE)) { 1757bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes errx(EXIT_FAILURE, "files is not supported for non-tape devices"); 1767bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 1777bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 1787bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1797bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (out.name == NULL) { 1807bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* No way to check for read access here. */ 1817bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.fd = STDOUT_FILENO; 1827bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.name = "stdout"; 1837bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.ops = &ddfops_stdfd; 1847bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } else { 1857bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.ops = prog_ops; 1867bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#define OFLAGS \ 1877bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC)) 1887bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.fd = ddop_open(out, out.name, O_RDWR | OFLAGS, DEFFILEMODE); 1897bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 1907bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * May not have read access, so try again with write only. 1917bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Without read we may have a problem if output also does 1927bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * not support seeks. 1937bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 1947bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (out.fd < 0) { 1957bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.fd = ddop_open(out, out.name, O_WRONLY | OFLAGS, 1967bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes DEFFILEMODE); 1977bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.flags |= NOREAD; 1987bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 1997bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (out.fd < 0) { 2007bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(EXIT_FAILURE, "%s", out.name); 2017bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 2027bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2037bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2047bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* Ensure out.fd is outside the stdio descriptor range */ 2057bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes redup_clean_fd(&out); 2067bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2077bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2087bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes getfdtype(&out); 2097bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2107bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 2117bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Allocate space for the input and output buffers. If not doing 2127bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * record oriented I/O, only need a single buffer. 2137bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 2147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!(ddflags & (C_BLOCK|C_UNBLOCK))) { 2157bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes size_t dbsz = out.dbsz; 2167bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!(ddflags & C_BS)) 2177bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes dbsz += in.dbsz - 1; 2187bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if ((in.db = malloc(dbsz)) == NULL) { 2197bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(EXIT_FAILURE, NULL); 2207bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 2217bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2227bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.db = in.db; 2237bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } else if ((in.db = 2247bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes malloc((u_int)(MAX(in.dbsz, cbsz) + cbsz))) == NULL || 2257bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (out.db = malloc((u_int)(out.dbsz + cbsz))) == NULL) { 2267bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(EXIT_FAILURE, NULL); 2277bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 2287bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2297bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes in.dbp = in.db; 2307bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.dbp = out.db; 2317bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2327bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* Position the input/output streams. */ 2337bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (in.offset) 2347bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes pos_in(); 2357bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (out.offset) 2367bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes pos_out(); 2377bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2387bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 2397bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Truncate the output file; ignore errors because it fails on some 2407bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * kinds of output files, tapes, for example. 2417bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 2427bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK)) 2437bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)ddop_ftruncate(out, out.fd, (off_t)out.offset * out.dbsz); 2447bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2457bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 2467bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * If converting case at the same time as another conversion, build a 2477bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * table that does both at once. If just converting case, use the 2487bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * built-in tables. 2497bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 2507bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (ddflags & (C_LCASE|C_UCASE)) { 2517bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#ifdef NO_CONV 2527bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* Should not get here, but just in case... */ 2537bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes errx(EXIT_FAILURE, "case conv and -DNO_CONV"); 2547bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 2557bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#else /* NO_CONV */ 2567bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes u_int cnt; 2577bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2587bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (ddflags & C_ASCII || ddflags & C_EBCDIC) { 2597bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (ddflags & C_LCASE) { 2607bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes for (cnt = 0; cnt < 256; ++cnt) 2617bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes casetab[cnt] = tolower(ctab[cnt]); 2627bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } else { 2637bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes for (cnt = 0; cnt < 256; ++cnt) 2647bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes casetab[cnt] = toupper(ctab[cnt]); 2657bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2667bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } else { 2677bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (ddflags & C_LCASE) { 2687bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes for (cnt = 0; cnt < 256; ++cnt) 2697bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes casetab[cnt] = tolower(cnt); 2707bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } else { 2717bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes for (cnt = 0; cnt < 256; ++cnt) 2727bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes casetab[cnt] = toupper(cnt); 2737bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2747bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2757bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2767bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ctab = casetab; 2777bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif /* NO_CONV */ 2787bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2797bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2807bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)gettimeofday(&st.start, NULL); /* Statistics timestamp. */ 2817bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 2827bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2837bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void 2847bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesgetfdtype(IO *io) 2857bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 2867bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes struct mtget mt; 2877bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes struct stat sb; 2887bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2897bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (io->ops->op_fstat(io->fd, &sb)) { 2907bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(EXIT_FAILURE, "%s", io->name); 2917bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 2927bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2937bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (S_ISCHR(sb.st_mode)) 2947bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes io->flags |= io->ops->op_ioctl(io->fd, MTIOCGET, &mt) 2957bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ? ISCHR : ISTAPE; 2967bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes else if (io->ops->op_lseek(io->fd, (off_t)0, SEEK_CUR) == -1 2977bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes && errno == ESPIPE) 2987bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes io->flags |= ISPIPE; /* XXX fixed in 4.4BSD */ 2997bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 3007bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3017bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes/* 3027bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Move the parameter file descriptor to a descriptor that is outside the 3037bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * stdio descriptor range, if necessary. This is required to avoid 3047bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * accidentally outputting completion or error messages into the 3057bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * output file that were intended for the tty. 3067bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 3077bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void 3087bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesredup_clean_fd(IO *io) 3097bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 3107bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int fd = io->fd; 3117bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int newfd; 3127bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3137bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (fd != STDIN_FILENO && fd != STDOUT_FILENO && 3147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes fd != STDERR_FILENO) 3157bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* File descriptor is ok, return immediately. */ 3167bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes return; 3177bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3187bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 3197bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 3 is the first descriptor greater than STD*_FILENO. Any 3207bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * free descriptor valued 3 or above is acceptable... 3217bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 3227bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes newfd = io->ops->op_fcntl(fd, F_DUPFD, 3); 3237bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (newfd < 0) { 3247bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(EXIT_FAILURE, "dupfd IO"); 3257bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 3267bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 3277bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3287bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes io->ops->op_close(fd); 3297bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes io->fd = newfd; 3307bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 3317bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3327bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void 3337bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesdd_in(void) 3347bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 3357bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int flags; 3367bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int64_t n; 3377bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3387bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes for (flags = ddflags;;) { 3397bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (cpy_cnt && (st.in_full + st.in_part) >= cpy_cnt) 3407bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes return; 3417bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3427bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 3437bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Clear the buffer first if doing "sync" on input. 3447bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * If doing block operations use spaces. This will 3457bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * affect not only the C_NOERROR case, but also the 3467bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * last partial input block which should be padded 3477bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * with zero and not garbage. 3487bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 3497bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (flags & C_SYNC) { 3507bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (flags & (C_BLOCK|C_UNBLOCK)) 3517bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)memset(in.dbp, ' ', in.dbsz); 3527bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes else 3537bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)memset(in.dbp, 0, in.dbsz); 3547bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 3557bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3567bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes n = ddop_read(in, in.fd, in.dbp, in.dbsz); 3577bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (n == 0) { 3587bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes in.dbrcnt = 0; 3597bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes return; 3607bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 3617bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3627bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* Read error. */ 3637bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (n < 0) { 3647bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3657bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 3667bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * If noerror not specified, die. POSIX requires that 3677bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * the warning message be followed by an I/O display. 3687bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 3697bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!(flags & C_NOERROR)) { 3707bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(EXIT_FAILURE, "%s", in.name); 3717bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 3727bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 3737bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warn("%s", in.name); 3747bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes summary(); 3757bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3767bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 3777bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * If it's not a tape drive or a pipe, seek past the 3787bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * error. If your OS doesn't do the right thing for 3797bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * raw disks this section should be modified to re-read 3807bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * in sector size chunks. 3817bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 3827bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!(in.flags & (ISPIPE|ISTAPE)) && 3837bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ddop_lseek(in, in.fd, (off_t)in.dbsz, SEEK_CUR)) 3847bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warn("%s", in.name); 3857bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3867bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* If sync not specified, omit block and continue. */ 3877bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!(ddflags & C_SYNC)) 3887bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 3897bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3907bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* Read errors count as full blocks. */ 3917bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes in.dbcnt += in.dbrcnt = in.dbsz; 3927bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ++st.in_full; 3937bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3947bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* Handle full input blocks. */ 3957bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } else if ((uint64_t)n == in.dbsz) { 3967bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes in.dbcnt += in.dbrcnt = n; 3977bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ++st.in_full; 3987bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3997bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* Handle partial input blocks. */ 4007bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } else { 4017bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* If sync, use the entire block. */ 4027bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (ddflags & C_SYNC) 4037bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes in.dbcnt += in.dbrcnt = in.dbsz; 4047bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes else 4057bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes in.dbcnt += in.dbrcnt = n; 4067bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ++st.in_part; 4077bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 4087bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4097bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 4107bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * POSIX states that if bs is set and no other conversions 4117bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * than noerror, notrunc or sync are specified, the block 4127bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * is output without buffering as it is read. 4137bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 4147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (ddflags & C_BS) { 4157bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.dbcnt = in.dbcnt; 4167bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes dd_out(1); 4177bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes in.dbcnt = 0; 4187bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 4197bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 4207bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4217bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (ddflags & C_SWAB) { 4227bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if ((n = in.dbrcnt) & 1) { 4237bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ++st.swab; 4247bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes --n; 4257bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 4267bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes swab(in.dbp, in.dbp, n); 4277bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 4287bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4297bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes in.dbp += in.dbrcnt; 4307bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (*cfunc)(); 4317bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 4327bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 4337bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4347bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes/* 4357bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Cleanup any remaining I/O and flush output. If necessary, output file 4367bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * is truncated. 4377bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 4387bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void 4397bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesdd_close(void) 4407bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 4417bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4427bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (cfunc == def) 4437bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes def_close(); 4447bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes else if (cfunc == block) 4457bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes block_close(); 4467bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes else if (cfunc == unblock) 4477bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes unblock_close(); 4487bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (ddflags & C_OSYNC && out.dbcnt < out.dbsz) { 4497bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)memset(out.dbp, 0, out.dbsz - out.dbcnt); 4507bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.dbcnt = out.dbsz; 4517bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 4527bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* If there are pending sparse blocks, make sure 4537bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * to write out the final block un-sparse 4547bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 4557bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if ((out.dbcnt == 0) && pending) { 4567bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes memset(out.db, 0, out.dbsz); 4577bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.dbcnt = out.dbsz; 4587bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.dbp = out.db + out.dbcnt; 4597bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes pending -= out.dbsz; 4607bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 4617bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (out.dbcnt) 4627bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes dd_out(1); 4637bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4647bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 4657bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Reporting nfs write error may be deferred until next 4667bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * write(2) or close(2) system call. So, we need to do an 4677bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * extra check. If an output is stdout, the file structure 4687bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * may be shared with other processes and close(2) just 4697bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * decreases the reference count. 4707bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 4717bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (out.fd == STDOUT_FILENO && ddop_fsync(out, out.fd) == -1 4727bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes && errno != EINVAL) { 4737bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(EXIT_FAILURE, "fsync stdout"); 4747bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 4757bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 4767bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (ddop_close(out, out.fd) == -1) { 4777bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(EXIT_FAILURE, "close"); 4787bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 4797bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 4807bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 4817bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4827bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesvoid 4837bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesdd_out(int force) 4847bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 4857bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes static int warned; 4867bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int64_t cnt, n, nw; 4877bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes u_char *outp; 4887bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4897bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 4907bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Write one or more blocks out. The common case is writing a full 4917bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * output block in a single write; increment the full block stats. 4927bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Otherwise, we're into partial block writes. If a partial write, 4937bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * and it's a character device, just warn. If a tape device, quit. 4947bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 4957bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * The partial writes represent two cases. 1: Where the input block 4967bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * was less than expected so the output block was less than expected. 4977bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 2: Where the input block was the right size but we were forced to 4987bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * write the block in multiple chunks. The original versions of dd(1) 4997bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * never wrote a block in more than a single write, so the latter case 5007bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * never happened. 5017bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 5027bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * One special case is if we're forced to do the write -- in that case 5037bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * we play games with the buffer size, and it's usually a partial write. 5047bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 5057bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes outp = out.db; 5067bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) { 5077bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes for (cnt = n;; cnt -= nw) { 5087bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5097bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!force && ddflags & C_SPARSE) { 5107bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int sparse, i; 5117bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes sparse = 1; /* Is buffer sparse? */ 5127bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes for (i = 0; i < cnt; i++) 5137bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (outp[i] != 0) { 5147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes sparse = 0; 5157bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 5167bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 5177bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (sparse) { 5187bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes pending += cnt; 5197bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes outp += cnt; 5207bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes nw = 0; 5217bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 5227bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 5237bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 5247bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (pending != 0) { 5257bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (ddop_lseek(out, 5267bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.fd, pending, SEEK_CUR) == -1) 5277bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(EXIT_FAILURE, "%s: seek error creating sparse file", 5287bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.name); 5297bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 5307bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes nw = bwrite(&out, outp, cnt); 5317bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (nw <= 0) { 5327bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (nw == 0) 5337bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes errx(EXIT_FAILURE, 5347bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes "%s: end of device", out.name); 5357bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 5367bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (errno != EINTR) 5377bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(EXIT_FAILURE, "%s", out.name); 5387bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 5397bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes nw = 0; 5407bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 5417bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (pending) { 5427bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes st.bytes += pending; 5437bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes st.sparse += pending/out.dbsz; 5447bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes st.out_full += pending/out.dbsz; 5457bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes pending = 0; 5467bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 5477bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes outp += nw; 5487bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes st.bytes += nw; 5497bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (nw == n) { 5507bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if ((uint64_t)n != out.dbsz) 5517bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ++st.out_part; 5527bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes else 5537bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ++st.out_full; 5547bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 5557bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 5567bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ++st.out_part; 5577bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (nw == cnt) 5587bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 5597bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (out.flags & ISCHR && !warned) { 5607bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warned = 1; 5617bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warnx("%s: short write on character device", out.name); 5627bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 5637bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (out.flags & ISTAPE) 5647bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes errx(EXIT_FAILURE, 5657bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes "%s: short write on tape device", out.name); 5667bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 5677bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5687bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 5697bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if ((out.dbcnt -= n) < out.dbsz) 5707bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 5717bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 5727bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5737bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* Reassemble the output block. */ 5747bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (out.dbcnt) 5757bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt); 5767bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes out.dbp = out.db + out.dbcnt; 5777bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5787bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (progress && (st.out_full + st.out_part) % progress == 0) 5797bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)write(STDERR_FILENO, ".", 1); 5807bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 5817bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5827bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes/* 5837bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * A protected against SIGINFO write 5847bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 5857bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesssize_t 5867bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesbwrite(IO *io, const void *buf, size_t len) 5877bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 5887bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes sigset_t oset; 5897bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ssize_t rv; 5907bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int oerrno; 5917bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5927bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)sigprocmask(SIG_BLOCK, &infoset, &oset); 5937bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes rv = io->ops->op_write(io->fd, buf, len); 5947bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes oerrno = errno; 5957bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)sigprocmask(SIG_SETMASK, &oset, NULL); 5967bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes errno = oerrno; 5977bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes return (rv); 5987bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 599