dd.c revision 249811
1/*-
2 * Copyright (c) 1991, 1993, 1994
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Keith Muller of the University of California, San Diego and Lance
7 * Visser of Convex Computer Corporation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if 0
35#ifndef lint
36static char const copyright[] =
37"@(#) Copyright (c) 1991, 1993, 1994\n\
38	The Regents of the University of California.  All rights reserved.\n";
39#endif /* not lint */
40
41#ifndef lint
42static char sccsid[] = "@(#)dd.c	8.5 (Berkeley) 4/2/94";
43#endif /* not lint */
44#endif
45#include <sys/cdefs.h>
46__FBSDID("$FreeBSD: head/bin/dd/dd.c 249811 2013-04-23 16:08:24Z kib $");
47
48#include <sys/param.h>
49#include <sys/stat.h>
50#include <sys/conf.h>
51#include <sys/disklabel.h>
52#include <sys/filio.h>
53#include <sys/time.h>
54
55#include <ctype.h>
56#include <err.h>
57#include <errno.h>
58#include <fcntl.h>
59#include <inttypes.h>
60#include <locale.h>
61#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
64#include <unistd.h>
65
66#include "dd.h"
67#include "extern.h"
68
69static void dd_close(void);
70static void dd_in(void);
71static void getfdtype(IO *);
72static void setup(void);
73
74IO	in, out;		/* input/output state */
75STAT	st;			/* statistics */
76void	(*cfunc)(void);		/* conversion function */
77uintmax_t cpy_cnt;		/* # of blocks to copy */
78static off_t	pending = 0;	/* pending seek if sparse */
79u_int	ddflags = 0;		/* conversion options */
80size_t	cbsz;			/* conversion block size */
81uintmax_t files_cnt = 1;	/* # of files to copy */
82const	u_char *ctab;		/* conversion table */
83char	fill_char;		/* Character to fill with if defined */
84
85int
86main(int argc __unused, char *argv[])
87{
88	(void)setlocale(LC_CTYPE, "");
89	jcl(argv);
90	setup();
91
92	(void)signal(SIGINFO, summaryx);
93	(void)signal(SIGINT, terminate);
94
95	atexit(summary);
96
97	while (files_cnt--)
98		dd_in();
99
100	dd_close();
101	/*
102	 * Some devices such as cfi(4) may perform significant amounts
103	 * of work when a write descriptor is closed.  Close the out
104	 * descriptor explicitly so that the summary handler (called
105	 * from an atexit() hook) includes this work.
106	 */
107	close(out.fd);
108	exit(0);
109}
110
111static int
112parity(u_char c)
113{
114	int i;
115
116	i = c ^ (c >> 1) ^ (c >> 2) ^ (c >> 3) ^
117	    (c >> 4) ^ (c >> 5) ^ (c >> 6) ^ (c >> 7);
118	return (i & 1);
119}
120
121static void
122setup(void)
123{
124	u_int cnt;
125	struct timeval tv;
126
127	if (in.name == NULL) {
128		in.name = "stdin";
129		in.fd = STDIN_FILENO;
130	} else {
131		in.fd = open(in.name, O_RDONLY, 0);
132		if (in.fd == -1)
133			err(1, "%s", in.name);
134	}
135
136	getfdtype(&in);
137
138	if (files_cnt > 1 && !(in.flags & ISTAPE))
139		errx(1, "files is not supported for non-tape devices");
140
141	if (out.name == NULL) {
142		/* No way to check for read access here. */
143		out.fd = STDOUT_FILENO;
144		out.name = "stdout";
145	} else {
146#define	OFLAGS \
147    (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
148		out.fd = open(out.name, O_RDWR | OFLAGS, DEFFILEMODE);
149		/*
150		 * May not have read access, so try again with write only.
151		 * Without read we may have a problem if output also does
152		 * not support seeks.
153		 */
154		if (out.fd == -1) {
155			out.fd = open(out.name, O_WRONLY | OFLAGS, DEFFILEMODE);
156			out.flags |= NOREAD;
157		}
158		if (out.fd == -1)
159			err(1, "%s", out.name);
160	}
161
162	getfdtype(&out);
163
164	/*
165	 * Allocate space for the input and output buffers.  If not doing
166	 * record oriented I/O, only need a single buffer.
167	 */
168	if (!(ddflags & (C_BLOCK | C_UNBLOCK))) {
169		if ((in.db = malloc(out.dbsz + in.dbsz - 1)) == NULL)
170			err(1, "input buffer");
171		out.db = in.db;
172	} else if ((in.db = malloc(MAX(in.dbsz, cbsz) + cbsz)) == NULL ||
173	    (out.db = malloc(out.dbsz + cbsz)) == NULL)
174		err(1, "output buffer");
175	in.dbp = in.db;
176	out.dbp = out.db;
177
178	/* Position the input/output streams. */
179	if (in.offset)
180		pos_in();
181	if (out.offset)
182		pos_out();
183
184	/*
185	 * Truncate the output file.  If it fails on a type of output file
186	 * that it should _not_ fail on, error out.
187	 */
188	if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK) &&
189	    out.flags & ISTRUNC)
190		if (ftruncate(out.fd, out.offset * out.dbsz) == -1)
191			err(1, "truncating %s", out.name);
192
193	if (ddflags & (C_LCASE  | C_UCASE | C_ASCII | C_EBCDIC | C_PARITY)) {
194		if (ctab != NULL) {
195			for (cnt = 0; cnt <= 0377; ++cnt)
196				casetab[cnt] = ctab[cnt];
197		} else {
198			for (cnt = 0; cnt <= 0377; ++cnt)
199				casetab[cnt] = cnt;
200		}
201		if ((ddflags & C_PARITY) && !(ddflags & C_ASCII)) {
202			/*
203			 * If the input is not EBCDIC, and we do parity
204			 * processing, strip input parity.
205			 */
206			for (cnt = 200; cnt <= 0377; ++cnt)
207				casetab[cnt] = casetab[cnt & 0x7f];
208		}
209		if (ddflags & C_LCASE) {
210			for (cnt = 0; cnt <= 0377; ++cnt)
211				casetab[cnt] = tolower(casetab[cnt]);
212		} else if (ddflags & C_UCASE) {
213			for (cnt = 0; cnt <= 0377; ++cnt)
214				casetab[cnt] = toupper(casetab[cnt]);
215		}
216		if ((ddflags & C_PARITY)) {
217			/*
218			 * This should strictly speaking be a no-op, but I
219			 * wonder what funny LANG settings could get us.
220			 */
221			for (cnt = 0; cnt <= 0377; ++cnt)
222				casetab[cnt] = casetab[cnt] & 0x7f;
223		}
224		if ((ddflags & C_PARSET)) {
225			for (cnt = 0; cnt <= 0377; ++cnt)
226				casetab[cnt] = casetab[cnt] | 0x80;
227		}
228		if ((ddflags & C_PAREVEN)) {
229			for (cnt = 0; cnt <= 0377; ++cnt)
230				if (parity(casetab[cnt]))
231					casetab[cnt] = casetab[cnt] | 0x80;
232		}
233		if ((ddflags & C_PARODD)) {
234			for (cnt = 0; cnt <= 0377; ++cnt)
235				if (!parity(casetab[cnt]))
236					casetab[cnt] = casetab[cnt] | 0x80;
237		}
238
239		ctab = casetab;
240	}
241
242	(void)gettimeofday(&tv, NULL);
243	st.start = tv.tv_sec + tv.tv_usec * 1e-6;
244}
245
246static void
247getfdtype(IO *io)
248{
249	struct stat sb;
250	int type;
251
252	if (fstat(io->fd, &sb) == -1)
253		err(1, "%s", io->name);
254	if (S_ISREG(sb.st_mode))
255		io->flags |= ISTRUNC;
256	if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) {
257		if (ioctl(io->fd, FIODTYPE, &type) == -1) {
258			err(1, "%s", io->name);
259		} else {
260			if (type & D_TAPE)
261				io->flags |= ISTAPE;
262			else if (type & (D_DISK | D_MEM))
263				io->flags |= ISSEEK;
264			if (S_ISCHR(sb.st_mode) && (type & D_TAPE) == 0)
265				io->flags |= ISCHR;
266		}
267		return;
268	}
269	errno = 0;
270	if (lseek(io->fd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE)
271		io->flags |= ISPIPE;
272	else
273		io->flags |= ISSEEK;
274}
275
276static void
277dd_in(void)
278{
279	ssize_t n;
280
281	for (;;) {
282		switch (cpy_cnt) {
283		case -1:			/* count=0 was specified */
284			return;
285		case 0:
286			break;
287		default:
288			if (st.in_full + st.in_part >= (uintmax_t)cpy_cnt)
289				return;
290			break;
291		}
292
293		/*
294		 * Zero the buffer first if sync; if doing block operations,
295		 * use spaces.
296		 */
297		if (ddflags & C_SYNC) {
298			if (ddflags & C_FILL)
299				memset(in.dbp, fill_char, in.dbsz);
300			else if (ddflags & (C_BLOCK | C_UNBLOCK))
301				memset(in.dbp, ' ', in.dbsz);
302			else
303				memset(in.dbp, 0, in.dbsz);
304		}
305
306		n = read(in.fd, in.dbp, in.dbsz);
307		if (n == 0) {
308			in.dbrcnt = 0;
309			return;
310		}
311
312		/* Read error. */
313		if (n == -1) {
314			/*
315			 * If noerror not specified, die.  POSIX requires that
316			 * the warning message be followed by an I/O display.
317			 */
318			if (!(ddflags & C_NOERROR))
319				err(1, "%s", in.name);
320			warn("%s", in.name);
321			summary();
322
323			/*
324			 * If it's a seekable file descriptor, seek past the
325			 * error.  If your OS doesn't do the right thing for
326			 * raw disks this section should be modified to re-read
327			 * in sector size chunks.
328			 */
329			if (in.flags & ISSEEK &&
330			    lseek(in.fd, (off_t)in.dbsz, SEEK_CUR))
331				warn("%s", in.name);
332
333			/* If sync not specified, omit block and continue. */
334			if (!(ddflags & C_SYNC))
335				continue;
336
337			/* Read errors count as full blocks. */
338			in.dbcnt += in.dbrcnt = in.dbsz;
339			++st.in_full;
340
341		/* Handle full input blocks. */
342		} else if ((size_t)n == in.dbsz) {
343			in.dbcnt += in.dbrcnt = n;
344			++st.in_full;
345
346		/* Handle partial input blocks. */
347		} else {
348			/* If sync, use the entire block. */
349			if (ddflags & C_SYNC)
350				in.dbcnt += in.dbrcnt = in.dbsz;
351			else
352				in.dbcnt += in.dbrcnt = n;
353			++st.in_part;
354		}
355
356		/*
357		 * POSIX states that if bs is set and no other conversions
358		 * than noerror, notrunc or sync are specified, the block
359		 * is output without buffering as it is read.
360		 */
361		if ((ddflags & ~(C_NOERROR | C_NOTRUNC | C_SYNC)) == C_BS) {
362			out.dbcnt = in.dbcnt;
363			dd_out(1);
364			in.dbcnt = 0;
365			continue;
366		}
367
368		if (ddflags & C_SWAB) {
369			if ((n = in.dbrcnt) & 1) {
370				++st.swab;
371				--n;
372			}
373			swab(in.dbp, in.dbp, (size_t)n);
374		}
375
376		in.dbp += in.dbrcnt;
377		(*cfunc)();
378	}
379}
380
381/*
382 * Clean up any remaining I/O and flush output.  If necessary, the output file
383 * is truncated.
384 */
385static void
386dd_close(void)
387{
388	if (cfunc == def)
389		def_close();
390	else if (cfunc == block)
391		block_close();
392	else if (cfunc == unblock)
393		unblock_close();
394	if (ddflags & C_OSYNC && out.dbcnt && out.dbcnt < out.dbsz) {
395		if (ddflags & C_FILL)
396			memset(out.dbp, fill_char, out.dbsz - out.dbcnt);
397		else if (ddflags & (C_BLOCK | C_UNBLOCK))
398			memset(out.dbp, ' ', out.dbsz - out.dbcnt);
399		else
400			memset(out.dbp, 0, out.dbsz - out.dbcnt);
401		out.dbcnt = out.dbsz;
402	}
403	if (out.dbcnt || pending)
404		dd_out(1);
405}
406
407void
408dd_out(int force)
409{
410	u_char *outp;
411	size_t cnt, i, n;
412	ssize_t nw;
413	static int warned;
414	int sparse;
415
416	/*
417	 * Write one or more blocks out.  The common case is writing a full
418	 * output block in a single write; increment the full block stats.
419	 * Otherwise, we're into partial block writes.  If a partial write,
420	 * and it's a character device, just warn.  If a tape device, quit.
421	 *
422	 * The partial writes represent two cases.  1: Where the input block
423	 * was less than expected so the output block was less than expected.
424	 * 2: Where the input block was the right size but we were forced to
425	 * write the block in multiple chunks.  The original versions of dd(1)
426	 * never wrote a block in more than a single write, so the latter case
427	 * never happened.
428	 *
429	 * One special case is if we're forced to do the write -- in that case
430	 * we play games with the buffer size, and it's usually a partial write.
431	 */
432	outp = out.db;
433	for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) {
434		for (cnt = n;; cnt -= nw) {
435			sparse = 0;
436			if (ddflags & C_SPARSE) {
437				sparse = 1;	/* Is buffer sparse? */
438				for (i = 0; i < cnt; i++)
439					if (outp[i] != 0) {
440						sparse = 0;
441						break;
442					}
443			}
444			if (sparse && !force) {
445				pending += cnt;
446				nw = cnt;
447			} else {
448				if (pending != 0) {
449					if (force)
450						pending--;
451					if (lseek(out.fd, pending, SEEK_CUR) ==
452					    -1)
453						err(2, "%s: seek error creating sparse file",
454						    out.name);
455					if (force)
456						write(out.fd, outp, 1);
457					pending = 0;
458				}
459				if (cnt)
460					nw = write(out.fd, outp, cnt);
461				else
462					return;
463			}
464
465			if (nw <= 0) {
466				if (nw == 0)
467					errx(1, "%s: end of device", out.name);
468				if (errno != EINTR)
469					err(1, "%s", out.name);
470				nw = 0;
471			}
472			outp += nw;
473			st.bytes += nw;
474			if ((size_t)nw == n) {
475				if (n != out.dbsz)
476					++st.out_part;
477				else
478					++st.out_full;
479				break;
480			}
481			++st.out_part;
482			if ((size_t)nw == cnt)
483				break;
484			if (out.flags & ISTAPE)
485				errx(1, "%s: short write on tape device",
486				    out.name);
487			if (out.flags & ISCHR && !warned) {
488				warned = 1;
489				warnx("%s: short write on character device",
490				    out.name);
491			}
492		}
493		if ((out.dbcnt -= n) < out.dbsz)
494			break;
495	}
496
497	/* Reassemble the output block. */
498	if (out.dbcnt)
499		(void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt);
500	out.dbp = out.db + out.dbcnt;
501}
502