1fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes/* $NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $ */ 2fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 3fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes/*- 4fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Copyright (c) 1991, 1993, 1994 5fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * The Regents of the University of California. All rights reserved. 6fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * 7fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * This code is derived from software contributed to Berkeley by 8fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Keith Muller of the University of California, San Diego and Lance 9fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Visser of Convex Computer Corporation. 10fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * 11fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Redistribution and use in source and binary forms, with or without 12fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * modification, are permitted provided that the following conditions 13fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * are met: 14fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * 1. Redistributions of source code must retain the above copyright 15fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * notice, this list of conditions and the following disclaimer. 16fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * 2. Redistributions in binary form must reproduce the above copyright 17fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * notice, this list of conditions and the following disclaimer in the 18fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * documentation and/or other materials provided with the distribution. 19fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * 3. Neither the name of the University nor the names of its contributors 20fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * may be used to endorse or promote products derived from this software 21fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * without specific prior written permission. 22fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * 23fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * SUCH DAMAGE. 34fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 35fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 36fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <sys/cdefs.h> 37fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#ifndef lint 38fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes__COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\ 39fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes The Regents of the University of California. All rights reserved."); 40fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#endif /* not lint */ 41fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 42fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#ifndef lint 43fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#if 0 44fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesstatic char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94"; 45fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#else 46fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes__RCSID("$NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $"); 47fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#endif 48fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#endif /* not lint */ 49fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 50fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <sys/param.h> 51fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <sys/stat.h> 52fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <sys/ioctl.h> 53fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <sys/mtio.h> 54fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <sys/time.h> 55fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 56fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <ctype.h> 57fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <err.h> 58fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <errno.h> 59fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <fcntl.h> 60fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <locale.h> 61fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <signal.h> 62fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <stdio.h> 63fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <stdlib.h> 64fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <string.h> 65fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include <unistd.h> 66fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 67fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include "dd.h" 68fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#include "extern.h" 69fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 70fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesstatic void dd_close(void); 71fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesstatic void dd_in(void); 72fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesstatic void getfdtype(IO *); 73fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesstatic void redup_clean_fd(IO *); 74fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesstatic void setup(void); 75fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 76fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesint main(int, char *[]); 77fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 78fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott HughesIO in, out; /* input/output state */ 79fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott HughesSTAT st; /* statistics */ 80fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesvoid (*cfunc)(void); /* conversion function */ 81fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesuint64_t cpy_cnt; /* # of blocks to copy */ 82fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesstatic off_t pending = 0; /* pending seek if sparse */ 83fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesu_int ddflags; /* conversion options */ 84fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesuint64_t cbsz; /* conversion block size */ 85fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesu_int files_cnt = 1; /* # of files to copy */ 86fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesuint64_t progress = 0; /* display sign of life */ 87fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesconst u_char *ctab; /* conversion table */ 88fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughessigset_t infoset; /* a set blocking SIGINFO */ 89fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesconst char *msgfmt = "posix"; /* default summary() message format */ 90fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 91fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes/* 92fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Ops for stdin/stdout and crunch'd dd. These are always host ops. 93fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 94fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesstatic const struct ddfops ddfops_stdfd = { 95fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes .op_open = open, 96fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes .op_close = close, 97fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes .op_fcntl = fcntl, 98fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes .op_ioctl = ioctl, 99fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes .op_fstat = fstat, 100fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes .op_fsync = fsync, 101fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes .op_ftruncate = ftruncate, 102fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes .op_lseek = lseek, 103fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes .op_read = read, 104fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes .op_write = write, 105fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes}; 106fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesextern const struct ddfops ddfops_prog; 107fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 108fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesint 109fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesmain(int argc, char *argv[]) 110fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes{ 111fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes int ch; 112fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 113fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes setprogname(argv[0]); 114fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)setlocale(LC_ALL, ""); 115fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 116fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes while ((ch = getopt(argc, argv, "")) != -1) { 117fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes switch (ch) { 118fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes default: 119fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes errx(EXIT_FAILURE, "usage: dd [operand ...]"); 120fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 121fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 122fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 123fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes argc -= (optind - 1); 124fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes argv += (optind - 1); 125fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 126fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes jcl(argv); 127fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#ifndef CRUNCHOPS 128fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (ddfops_prog.op_init && ddfops_prog.op_init() == -1) 129fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes err(1, "prog init"); 130fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#endif 131fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes setup(); 132fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 133fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)signal(SIGINFO, summaryx); 134fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)signal(SIGINT, terminate); 135fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)sigemptyset(&infoset); 136fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)sigaddset(&infoset, SIGINFO); 137fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 138fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)atexit(summary); 139fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 140fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes while (files_cnt--) 141fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes dd_in(); 142fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 143fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes dd_close(); 144fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes exit(0); 145fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 146fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes} 147fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 148fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesstatic void 149fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughessetup(void) 150fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes{ 151fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#ifdef CRUNCHOPS 152fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes const struct ddfops *prog_ops = &ddfops_stdfd; 153fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#else 154fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes const struct ddfops *prog_ops = &ddfops_prog; 155fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#endif 156fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 157fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (in.name == NULL) { 158fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes in.name = "stdin"; 159fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes in.fd = STDIN_FILENO; 160fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes in.ops = &ddfops_stdfd; 161fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } else { 162fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes in.ops = prog_ops; 163fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes in.fd = ddop_open(in, in.name, O_RDONLY, 0); 164fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (in.fd < 0) 165fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes err(EXIT_FAILURE, "%s", in.name); 166fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 167fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 168fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* Ensure in.fd is outside the stdio descriptor range */ 169fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes redup_clean_fd(&in); 170fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 171fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 172fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes getfdtype(&in); 173fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 174fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (files_cnt > 1 && !(in.flags & ISTAPE)) { 175fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes errx(EXIT_FAILURE, "files is not supported for non-tape devices"); 176fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 177fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 178fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 179fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (out.name == NULL) { 180fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* No way to check for read access here. */ 181fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.fd = STDOUT_FILENO; 182fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.name = "stdout"; 183fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.ops = &ddfops_stdfd; 184fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } else { 185fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.ops = prog_ops; 186fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#define OFLAGS \ 187fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC)) 188fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.fd = ddop_open(out, out.name, O_RDWR | OFLAGS, DEFFILEMODE); 189fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* 190fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * May not have read access, so try again with write only. 191fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Without read we may have a problem if output also does 192fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * not support seeks. 193fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 194fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (out.fd < 0) { 195fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.fd = ddop_open(out, out.name, O_WRONLY | OFLAGS, 196fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes DEFFILEMODE); 197fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.flags |= NOREAD; 198fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 199fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (out.fd < 0) { 200fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes err(EXIT_FAILURE, "%s", out.name); 201fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 202fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 203fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 204fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* Ensure out.fd is outside the stdio descriptor range */ 205fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes redup_clean_fd(&out); 206fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 207fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 208fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes getfdtype(&out); 209fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 210fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* 211fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Allocate space for the input and output buffers. If not doing 212fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * record oriented I/O, only need a single buffer. 213fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 214fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (!(ddflags & (C_BLOCK|C_UNBLOCK))) { 215fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes size_t dbsz = out.dbsz; 216fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (!(ddflags & C_BS)) 217fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes dbsz += in.dbsz - 1; 218fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if ((in.db = malloc(dbsz)) == NULL) { 219fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes err(EXIT_FAILURE, NULL); 220fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 221fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 222fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.db = in.db; 223fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } else if ((in.db = 224fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes malloc((u_int)(MAX(in.dbsz, cbsz) + cbsz))) == NULL || 225fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (out.db = malloc((u_int)(out.dbsz + cbsz))) == NULL) { 226fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes err(EXIT_FAILURE, NULL); 227fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 228fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 229fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes in.dbp = in.db; 230fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.dbp = out.db; 231fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 232fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* Position the input/output streams. */ 233fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (in.offset) 234fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes pos_in(); 235fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (out.offset) 236fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes pos_out(); 237fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 238fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* 239fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Truncate the output file; ignore errors because it fails on some 240fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * kinds of output files, tapes, for example. 241fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 242fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK)) 243fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)ddop_ftruncate(out, out.fd, (off_t)out.offset * out.dbsz); 244fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 245fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* 246fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * If converting case at the same time as another conversion, build a 247fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * table that does both at once. If just converting case, use the 248fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * built-in tables. 249fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 250fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (ddflags & (C_LCASE|C_UCASE)) { 251fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#ifdef NO_CONV 252fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* Should not get here, but just in case... */ 253fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes errx(EXIT_FAILURE, "case conv and -DNO_CONV"); 254fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 255fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#else /* NO_CONV */ 256fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes u_int cnt; 257fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 258fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (ddflags & C_ASCII || ddflags & C_EBCDIC) { 259fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (ddflags & C_LCASE) { 260fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes for (cnt = 0; cnt < 256; ++cnt) 261fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes casetab[cnt] = tolower(ctab[cnt]); 262fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } else { 263fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes for (cnt = 0; cnt < 256; ++cnt) 264fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes casetab[cnt] = toupper(ctab[cnt]); 265fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 266fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } else { 267fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (ddflags & C_LCASE) { 268fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes for (cnt = 0; cnt < 256; ++cnt) 269fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes casetab[cnt] = tolower(cnt); 270fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } else { 271fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes for (cnt = 0; cnt < 256; ++cnt) 272fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes casetab[cnt] = toupper(cnt); 273fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 274fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 275fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 276fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes ctab = casetab; 277fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes#endif /* NO_CONV */ 278fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 279fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 280fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)gettimeofday(&st.start, NULL); /* Statistics timestamp. */ 281fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes} 282fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 283fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesstatic void 284fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesgetfdtype(IO *io) 285fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes{ 286fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes struct mtget mt; 287fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes struct stat sb; 288fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 289fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (io->ops->op_fstat(io->fd, &sb)) { 290fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes err(EXIT_FAILURE, "%s", io->name); 291fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 292fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 293fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (S_ISCHR(sb.st_mode)) 294fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes io->flags |= io->ops->op_ioctl(io->fd, MTIOCGET, &mt) 295fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes ? ISCHR : ISTAPE; 296fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes else if (io->ops->op_lseek(io->fd, (off_t)0, SEEK_CUR) == -1 297fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes && errno == ESPIPE) 298fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes io->flags |= ISPIPE; /* XXX fixed in 4.4BSD */ 299fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes} 300fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 301fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes/* 302fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Move the parameter file descriptor to a descriptor that is outside the 303fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * stdio descriptor range, if necessary. This is required to avoid 304fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * accidentally outputting completion or error messages into the 305fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * output file that were intended for the tty. 306fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 307fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesstatic void 308fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesredup_clean_fd(IO *io) 309fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes{ 310fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes int fd = io->fd; 311fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes int newfd; 312fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 313fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (fd != STDIN_FILENO && fd != STDOUT_FILENO && 314fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes fd != STDERR_FILENO) 315fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* File descriptor is ok, return immediately. */ 316fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes return; 317fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 318fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* 319fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * 3 is the first descriptor greater than STD*_FILENO. Any 320fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * free descriptor valued 3 or above is acceptable... 321fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 322fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes newfd = io->ops->op_fcntl(fd, F_DUPFD, 3); 323fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (newfd < 0) { 324fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes err(EXIT_FAILURE, "dupfd IO"); 325fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 326fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 327fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 328fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes io->ops->op_close(fd); 329fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes io->fd = newfd; 330fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes} 331fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 332fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesstatic void 333fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesdd_in(void) 334fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes{ 335fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes int flags; 336fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes int64_t n; 337fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 338fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes for (flags = ddflags;;) { 339fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (cpy_cnt && (st.in_full + st.in_part) >= cpy_cnt) 340fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes return; 341fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 342fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* 343fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Clear the buffer first if doing "sync" on input. 344fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * If doing block operations use spaces. This will 345fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * affect not only the C_NOERROR case, but also the 346fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * last partial input block which should be padded 347fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * with zero and not garbage. 348fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 349fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (flags & C_SYNC) { 350fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (flags & (C_BLOCK|C_UNBLOCK)) 351fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)memset(in.dbp, ' ', in.dbsz); 352fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes else 353fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)memset(in.dbp, 0, in.dbsz); 354fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 355fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 356fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes n = ddop_read(in, in.fd, in.dbp, in.dbsz); 357fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (n == 0) { 358fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes in.dbrcnt = 0; 359fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes return; 360fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 361fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 362fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* Read error. */ 363fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (n < 0) { 364fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 365fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* 366fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * If noerror not specified, die. POSIX requires that 367fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * the warning message be followed by an I/O display. 368fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 369fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (!(flags & C_NOERROR)) { 370fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes err(EXIT_FAILURE, "%s", in.name); 371fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 372fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 373fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes warn("%s", in.name); 374fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes summary(); 375fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 376fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* 377fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * If it's not a tape drive or a pipe, seek past the 378fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * error. If your OS doesn't do the right thing for 379fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * raw disks this section should be modified to re-read 380fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * in sector size chunks. 381fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 382fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (!(in.flags & (ISPIPE|ISTAPE)) && 383fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes ddop_lseek(in, in.fd, (off_t)in.dbsz, SEEK_CUR)) 384fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes warn("%s", in.name); 385fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 386fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* If sync not specified, omit block and continue. */ 387fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (!(ddflags & C_SYNC)) 388fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes continue; 389fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 390fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* Read errors count as full blocks. */ 391fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes in.dbcnt += in.dbrcnt = in.dbsz; 392fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes ++st.in_full; 393fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 394fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* Handle full input blocks. */ 395fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } else if ((uint64_t)n == in.dbsz) { 396fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes in.dbcnt += in.dbrcnt = n; 397fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes ++st.in_full; 398fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 399fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* Handle partial input blocks. */ 400fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } else { 401fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* If sync, use the entire block. */ 402fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (ddflags & C_SYNC) 403fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes in.dbcnt += in.dbrcnt = in.dbsz; 404fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes else 405fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes in.dbcnt += in.dbrcnt = n; 406fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes ++st.in_part; 407fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 408fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 409fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* 410fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * POSIX states that if bs is set and no other conversions 411fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * than noerror, notrunc or sync are specified, the block 412fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * is output without buffering as it is read. 413fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 414fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (ddflags & C_BS) { 415fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.dbcnt = in.dbcnt; 416fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes dd_out(1); 417fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes in.dbcnt = 0; 418fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes continue; 419fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 420fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 421fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (ddflags & C_SWAB) { 422fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if ((n = in.dbrcnt) & 1) { 423fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes ++st.swab; 424fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes --n; 425fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 426fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes swab(in.dbp, in.dbp, n); 427fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 428fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 429fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes in.dbp += in.dbrcnt; 430fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (*cfunc)(); 431fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 432fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes} 433fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 434fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes/* 435fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Cleanup any remaining I/O and flush output. If necessary, output file 436fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * is truncated. 437fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 438fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesstatic void 439fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesdd_close(void) 440fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes{ 441fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 442fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (cfunc == def) 443fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes def_close(); 444fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes else if (cfunc == block) 445fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes block_close(); 446fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes else if (cfunc == unblock) 447fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes unblock_close(); 448fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (ddflags & C_OSYNC && out.dbcnt < out.dbsz) { 449fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)memset(out.dbp, 0, out.dbsz - out.dbcnt); 450fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.dbcnt = out.dbsz; 451fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 452fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* If there are pending sparse blocks, make sure 453fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * to write out the final block un-sparse 454fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 455fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if ((out.dbcnt == 0) && pending) { 456fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes memset(out.db, 0, out.dbsz); 457fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.dbcnt = out.dbsz; 458fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.dbp = out.db + out.dbcnt; 459fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes pending -= out.dbsz; 460fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 461fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (out.dbcnt) 462fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes dd_out(1); 463fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 464fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* 465fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Reporting nfs write error may be deferred until next 466fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * write(2) or close(2) system call. So, we need to do an 467fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * extra check. If an output is stdout, the file structure 468fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * may be shared with other processes and close(2) just 469fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * decreases the reference count. 470fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 471fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (out.fd == STDOUT_FILENO && ddop_fsync(out, out.fd) == -1 472fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes && errno != EINVAL) { 473fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes err(EXIT_FAILURE, "fsync stdout"); 474fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 475fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 476fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (ddop_close(out, out.fd) == -1) { 477fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes err(EXIT_FAILURE, "close"); 478fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 479fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 480fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes} 481fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 482fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesvoid 483fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesdd_out(int force) 484fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes{ 485fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes static int warned; 486fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes int64_t cnt, n, nw; 487fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes u_char *outp; 488fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 489fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* 490fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Write one or more blocks out. The common case is writing a full 491fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * output block in a single write; increment the full block stats. 492fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * Otherwise, we're into partial block writes. If a partial write, 493fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * and it's a character device, just warn. If a tape device, quit. 494fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * 495fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * The partial writes represent two cases. 1: Where the input block 496fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * was less than expected so the output block was less than expected. 497fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * 2: Where the input block was the right size but we were forced to 498fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * write the block in multiple chunks. The original versions of dd(1) 499fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * never wrote a block in more than a single write, so the latter case 500fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * never happened. 501fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * 502fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * One special case is if we're forced to do the write -- in that case 503fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * we play games with the buffer size, and it's usually a partial write. 504fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 505fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes outp = out.db; 506fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) { 507fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes for (cnt = n;; cnt -= nw) { 508fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 509fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (!force && ddflags & C_SPARSE) { 510fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes int sparse, i; 511fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes sparse = 1; /* Is buffer sparse? */ 512fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes for (i = 0; i < cnt; i++) 513fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (outp[i] != 0) { 514fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes sparse = 0; 515fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes break; 516fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 517fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (sparse) { 518fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes pending += cnt; 519fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes outp += cnt; 520fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes nw = 0; 521fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes break; 522fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 523fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 524fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (pending != 0) { 525fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (ddop_lseek(out, 526fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.fd, pending, SEEK_CUR) == -1) 527fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes err(EXIT_FAILURE, "%s: seek error creating sparse file", 528fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.name); 529fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 530fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes nw = bwrite(&out, outp, cnt); 531fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (nw <= 0) { 532fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (nw == 0) 533fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes errx(EXIT_FAILURE, 534fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes "%s: end of device", out.name); 535fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 536fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (errno != EINTR) 537fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes err(EXIT_FAILURE, "%s", out.name); 538fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 539fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes nw = 0; 540fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 541fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (pending) { 542fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes st.bytes += pending; 543fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes st.sparse += pending/out.dbsz; 544fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes st.out_full += pending/out.dbsz; 545fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes pending = 0; 546fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 547fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes outp += nw; 548fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes st.bytes += nw; 549fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (nw == n) { 550fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if ((uint64_t)n != out.dbsz) 551fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes ++st.out_part; 552fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes else 553fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes ++st.out_full; 554fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes break; 555fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 556fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes ++st.out_part; 557fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (nw == cnt) 558fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes break; 559fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (out.flags & ISCHR && !warned) { 560fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes warned = 1; 561fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes warnx("%s: short write on character device", out.name); 562fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 563fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (out.flags & ISTAPE) 564fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes errx(EXIT_FAILURE, 565fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes "%s: short write on tape device", out.name); 566fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* NOTREACHED */ 567fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 568fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 569fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if ((out.dbcnt -= n) < out.dbsz) 570fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes break; 571fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes } 572fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 573fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes /* Reassemble the output block. */ 574fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (out.dbcnt) 575fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt); 576fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes out.dbp = out.db + out.dbcnt; 577fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 578fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes if (progress && (st.out_full + st.out_part) % progress == 0) 579fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)write(STDERR_FILENO, ".", 1); 580fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes} 581fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 582fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes/* 583fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes * A protected against SIGINFO write 584fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes */ 585fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesssize_t 586fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughesbwrite(IO *io, const void *buf, size_t len) 587fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes{ 588fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes sigset_t oset; 589fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes ssize_t rv; 590fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes int oerrno; 591fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes 592fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)sigprocmask(SIG_BLOCK, &infoset, &oset); 593fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes rv = io->ops->op_write(io->fd, buf, len); 594fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes oerrno = errno; 595fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes (void)sigprocmask(SIG_SETMASK, &oset, NULL); 596fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes errno = oerrno; 597fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes return (rv); 598fd4c6b0a3a25921a9fe24691a695d715aecb6afeElliott Hughes} 599