1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1991, 1993, 1994
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Keith Muller of the University of California, San Diego and Lance
9 * Visser of Convex Computer Corporation.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#if 0
37#ifndef lint
38static char const copyright[] =
39"@(#) Copyright (c) 1991, 1993, 1994\n\
40	The Regents of the University of California.  All rights reserved.\n";
41#endif /* not lint */
42
43#ifndef lint
44static char sccsid[] = "@(#)dd.c	8.5 (Berkeley) 4/2/94";
45#endif /* not lint */
46#endif
47#include <sys/cdefs.h>
48__FBSDID("$FreeBSD$");
49
50#include <sys/param.h>
51#include <sys/stat.h>
52#include <sys/capsicum.h>
53#include <sys/conf.h>
54#include <sys/disklabel.h>
55#include <sys/filio.h>
56#include <sys/mtio.h>
57#include <sys/time.h>
58
59#include <assert.h>
60#include <capsicum_helpers.h>
61#include <ctype.h>
62#include <err.h>
63#include <errno.h>
64#include <fcntl.h>
65#include <inttypes.h>
66#include <locale.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70#include <time.h>
71#include <unistd.h>
72
73#include "dd.h"
74#include "extern.h"
75
76static void dd_close(void);
77static void dd_in(void);
78static void getfdtype(IO *);
79static void setup(void);
80
81IO	in, out;		/* input/output state */
82STAT	st;			/* statistics */
83void	(*cfunc)(void);		/* conversion function */
84uintmax_t cpy_cnt;		/* # of blocks to copy */
85static off_t	pending = 0;	/* pending seek if sparse */
86uint64_t	ddflags = 0;	/* conversion options */
87size_t	cbsz;			/* conversion block size */
88uintmax_t files_cnt = 1;	/* # of files to copy */
89const	u_char *ctab;		/* conversion table */
90char	fill_char;		/* Character to fill with if defined */
91size_t	speed = 0;		/* maximum speed, in bytes per second */
92volatile sig_atomic_t need_summary;
93volatile sig_atomic_t need_progress;
94
95int
96main(int argc __unused, char *argv[])
97{
98	struct itimerval itv = { { 1, 0 }, { 1, 0 } }; /* SIGALARM every second, if needed */
99
100	(void)setlocale(LC_CTYPE, "");
101	jcl(argv);
102	setup();
103
104	caph_cache_catpages();
105	if (caph_enter() < 0)
106		err(1, "unable to enter capability mode");
107
108	(void)signal(SIGINFO, siginfo_handler);
109	if (ddflags & C_PROGRESS) {
110		(void)signal(SIGALRM, sigalarm_handler);
111		setitimer(ITIMER_REAL, &itv, NULL);
112	}
113	(void)signal(SIGINT, terminate);
114
115	atexit(summary);
116
117	while (files_cnt--)
118		dd_in();
119
120	dd_close();
121	/*
122	 * Some devices such as cfi(4) may perform significant amounts
123	 * of work when a write descriptor is closed.  Close the out
124	 * descriptor explicitly so that the summary handler (called
125	 * from an atexit() hook) includes this work.
126	 */
127	if (close(out.fd) == -1 && errno != EINTR)
128		err(1, "close");
129	exit(0);
130}
131
132static int
133parity(u_char c)
134{
135	int i;
136
137	i = c ^ (c >> 1) ^ (c >> 2) ^ (c >> 3) ^
138	    (c >> 4) ^ (c >> 5) ^ (c >> 6) ^ (c >> 7);
139	return (i & 1);
140}
141
142static void
143setup(void)
144{
145	u_int cnt;
146	int iflags, oflags;
147	cap_rights_t rights;
148	unsigned long cmds[] = { FIODTYPE, MTIOCTOP };
149
150	if (in.name == NULL) {
151		in.name = "stdin";
152		in.fd = STDIN_FILENO;
153	} else {
154		iflags = 0;
155		if (ddflags & C_IDIRECT)
156			iflags |= O_DIRECT;
157		in.fd = open(in.name, O_RDONLY | iflags, 0);
158		if (in.fd == -1)
159			err(1, "%s", in.name);
160	}
161
162	getfdtype(&in);
163
164	cap_rights_init(&rights, CAP_READ, CAP_SEEK);
165	if (caph_rights_limit(in.fd, &rights) == -1)
166		err(1, "unable to limit capability rights");
167
168	if (files_cnt > 1 && !(in.flags & ISTAPE))
169		errx(1, "files is not supported for non-tape devices");
170
171	cap_rights_set(&rights, CAP_FTRUNCATE, CAP_IOCTL, CAP_WRITE);
172	if (ddflags & (C_FDATASYNC | C_FSYNC))
173		cap_rights_set(&rights, CAP_FSYNC);
174	if (out.name == NULL) {
175		/* No way to check for read access here. */
176		out.fd = STDOUT_FILENO;
177		out.name = "stdout";
178		if (ddflags & C_OFSYNC) {
179			oflags = fcntl(out.fd, F_GETFL);
180			if (oflags == -1)
181				err(1, "unable to get fd flags for stdout");
182			oflags |= O_FSYNC;
183			if (fcntl(out.fd, F_SETFL, oflags) == -1)
184				err(1, "unable to set fd flags for stdout");
185		}
186	} else {
187		oflags = O_CREAT;
188		if (!(ddflags & (C_SEEK | C_NOTRUNC)))
189			oflags |= O_TRUNC;
190		if (ddflags & C_OFSYNC)
191			oflags |= O_FSYNC;
192		if (ddflags & C_ODIRECT)
193			oflags |= O_DIRECT;
194		out.fd = open(out.name, O_RDWR | oflags, DEFFILEMODE);
195		/*
196		 * May not have read access, so try again with write only.
197		 * Without read we may have a problem if output also does
198		 * not support seeks.
199		 */
200		if (out.fd == -1) {
201			out.fd = open(out.name, O_WRONLY | oflags, DEFFILEMODE);
202			out.flags |= NOREAD;
203			cap_rights_clear(&rights, CAP_READ);
204		}
205		if (out.fd == -1)
206			err(1, "%s", out.name);
207	}
208
209	getfdtype(&out);
210
211	if (caph_rights_limit(out.fd, &rights) == -1)
212		err(1, "unable to limit capability rights");
213	if (caph_ioctls_limit(out.fd, cmds, nitems(cmds)) == -1)
214		err(1, "unable to limit capability rights");
215
216	if (in.fd != STDIN_FILENO && out.fd != STDIN_FILENO) {
217		if (caph_limit_stdin() == -1)
218			err(1, "unable to limit capability rights");
219	}
220
221	if (in.fd != STDOUT_FILENO && out.fd != STDOUT_FILENO) {
222		if (caph_limit_stdout() == -1)
223			err(1, "unable to limit capability rights");
224	}
225
226	if (in.fd != STDERR_FILENO && out.fd != STDERR_FILENO) {
227		if (caph_limit_stderr() == -1)
228			err(1, "unable to limit capability rights");
229	}
230
231	/*
232	 * Allocate space for the input and output buffers.  If not doing
233	 * record oriented I/O, only need a single buffer.
234	 */
235	if (!(ddflags & (C_BLOCK | C_UNBLOCK))) {
236		if ((in.db = malloc((size_t)out.dbsz + in.dbsz - 1)) == NULL)
237			err(1, "input buffer");
238		out.db = in.db;
239	} else if ((in.db = malloc(MAX((size_t)in.dbsz, cbsz) + cbsz)) == NULL ||
240	    (out.db = malloc(out.dbsz + cbsz)) == NULL)
241		err(1, "output buffer");
242
243	/* dbp is the first free position in each buffer. */
244	in.dbp = in.db;
245	out.dbp = out.db;
246
247	/* Position the input/output streams. */
248	if (in.offset)
249		pos_in();
250	if (out.offset)
251		pos_out();
252
253	/*
254	 * Truncate the output file.  If it fails on a type of output file
255	 * that it should _not_ fail on, error out.
256	 */
257	if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK) &&
258	    out.flags & ISTRUNC)
259		if (ftruncate(out.fd, out.offset * out.dbsz) == -1)
260			err(1, "truncating %s", out.name);
261
262	if (ddflags & (C_LCASE  | C_UCASE | C_ASCII | C_EBCDIC | C_PARITY)) {
263		if (ctab != NULL) {
264			for (cnt = 0; cnt <= 0377; ++cnt)
265				casetab[cnt] = ctab[cnt];
266		} else {
267			for (cnt = 0; cnt <= 0377; ++cnt)
268				casetab[cnt] = cnt;
269		}
270		if ((ddflags & C_PARITY) && !(ddflags & C_ASCII)) {
271			/*
272			 * If the input is not EBCDIC, and we do parity
273			 * processing, strip input parity.
274			 */
275			for (cnt = 200; cnt <= 0377; ++cnt)
276				casetab[cnt] = casetab[cnt & 0x7f];
277		}
278		if (ddflags & C_LCASE) {
279			for (cnt = 0; cnt <= 0377; ++cnt)
280				casetab[cnt] = tolower(casetab[cnt]);
281		} else if (ddflags & C_UCASE) {
282			for (cnt = 0; cnt <= 0377; ++cnt)
283				casetab[cnt] = toupper(casetab[cnt]);
284		}
285		if ((ddflags & C_PARITY)) {
286			/*
287			 * This should strictly speaking be a no-op, but I
288			 * wonder what funny LANG settings could get us.
289			 */
290			for (cnt = 0; cnt <= 0377; ++cnt)
291				casetab[cnt] = casetab[cnt] & 0x7f;
292		}
293		if ((ddflags & C_PARSET)) {
294			for (cnt = 0; cnt <= 0377; ++cnt)
295				casetab[cnt] = casetab[cnt] | 0x80;
296		}
297		if ((ddflags & C_PAREVEN)) {
298			for (cnt = 0; cnt <= 0377; ++cnt)
299				if (parity(casetab[cnt]))
300					casetab[cnt] = casetab[cnt] | 0x80;
301		}
302		if ((ddflags & C_PARODD)) {
303			for (cnt = 0; cnt <= 0377; ++cnt)
304				if (!parity(casetab[cnt]))
305					casetab[cnt] = casetab[cnt] | 0x80;
306		}
307
308		ctab = casetab;
309	}
310
311	if (clock_gettime(CLOCK_MONOTONIC, &st.start))
312		err(1, "clock_gettime");
313}
314
315static void
316getfdtype(IO *io)
317{
318	struct stat sb;
319	int type;
320
321	if (fstat(io->fd, &sb) == -1)
322		err(1, "%s", io->name);
323	if (S_ISREG(sb.st_mode))
324		io->flags |= ISTRUNC;
325	if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) {
326		if (ioctl(io->fd, FIODTYPE, &type) == -1) {
327			err(1, "%s", io->name);
328		} else {
329			if (type & D_TAPE)
330				io->flags |= ISTAPE;
331			else if (type & (D_DISK | D_MEM))
332				io->flags |= ISSEEK;
333			if (S_ISCHR(sb.st_mode) && (type & D_TAPE) == 0)
334				io->flags |= ISCHR;
335		}
336		return;
337	}
338	errno = 0;
339	if (lseek(io->fd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE)
340		io->flags |= ISPIPE;
341	else
342		io->flags |= ISSEEK;
343}
344
345/*
346 * Limit the speed by adding a delay before every block read.
347 * The delay (t_usleep) is equal to the time computed from block
348 * size and the specified speed limit (t_target) minus the time
349 * spent on actual read and write operations (t_io).
350 */
351static void
352speed_limit(void)
353{
354	static double t_prev, t_usleep;
355	double t_now, t_io, t_target;
356
357	t_now = secs_elapsed();
358	t_io = t_now - t_prev - t_usleep;
359	t_target = (double)in.dbsz / (double)speed;
360	t_usleep = t_target - t_io;
361	if (t_usleep > 0)
362		usleep(t_usleep * 1000000);
363	else
364		t_usleep = 0;
365	t_prev = t_now;
366}
367
368static void
369swapbytes(void *v, size_t len)
370{
371	unsigned char *p = v;
372	unsigned char t;
373
374	while (len > 1) {
375		t = p[0];
376		p[0] = p[1];
377		p[1] = t;
378		p += 2;
379		len -= 2;
380	}
381}
382
383static void
384dd_in(void)
385{
386	ssize_t n;
387
388	for (;;) {
389		switch (cpy_cnt) {
390		case -1:			/* count=0 was specified */
391			return;
392		case 0:
393			break;
394		default:
395			if (st.in_full + st.in_part >= (uintmax_t)cpy_cnt)
396				return;
397			break;
398		}
399
400		if (speed > 0)
401			speed_limit();
402
403		/*
404		 * Zero the buffer first if sync; if doing block operations,
405		 * use spaces.
406		 */
407		if (ddflags & C_SYNC) {
408			if (ddflags & C_FILL)
409				memset(in.dbp, fill_char, in.dbsz);
410			else if (ddflags & (C_BLOCK | C_UNBLOCK))
411				memset(in.dbp, ' ', in.dbsz);
412			else
413				memset(in.dbp, 0, in.dbsz);
414		}
415
416		in.dbrcnt = 0;
417fill:
418		n = read(in.fd, in.dbp + in.dbrcnt, in.dbsz - in.dbrcnt);
419
420		/* EOF */
421		if (n == 0 && in.dbrcnt == 0)
422			return;
423
424		/* Read error */
425		if (n == -1) {
426			/*
427			 * If noerror not specified, die.  POSIX requires that
428			 * the warning message be followed by an I/O display.
429			 */
430			if (!(ddflags & C_NOERROR))
431				err(1, "%s", in.name);
432			warn("%s", in.name);
433			summary();
434
435			/*
436			 * If it's a seekable file descriptor, seek past the
437			 * error.  If your OS doesn't do the right thing for
438			 * raw disks this section should be modified to re-read
439			 * in sector size chunks.
440			 */
441			if (in.flags & ISSEEK &&
442			    lseek(in.fd, (off_t)in.dbsz, SEEK_CUR))
443				warn("%s", in.name);
444
445			/* If sync not specified, omit block and continue. */
446			if (!(ddflags & C_SYNC))
447				continue;
448		}
449
450		/* If conv=sync, use the entire block. */
451		if (ddflags & C_SYNC)
452			n = in.dbsz;
453
454		/* Count the bytes read for this block. */
455		in.dbrcnt += n;
456
457		/* Count the number of full and partial blocks. */
458		if (in.dbrcnt == in.dbsz)
459			++st.in_full;
460		else if (ddflags & C_IFULLBLOCK && n != 0)
461			goto fill; /* these don't count */
462		else
463			++st.in_part;
464
465		/* Count the total bytes read for this file. */
466		in.dbcnt += in.dbrcnt;
467
468		/*
469		 * POSIX states that if bs is set and no other conversions
470		 * than noerror, notrunc or sync are specified, the block
471		 * is output without buffering as it is read.
472		 */
473		if ((ddflags & ~(C_NOERROR | C_NOTRUNC | C_SYNC)) == C_BS) {
474			out.dbcnt = in.dbcnt;
475			dd_out(1);
476			in.dbcnt = 0;
477			continue;
478		}
479
480		if (ddflags & C_SWAB) {
481			if ((n = in.dbrcnt) & 1) {
482				++st.swab;
483				--n;
484			}
485			swapbytes(in.dbp, (size_t)n);
486		}
487
488		/* Advance to the next block. */
489		in.dbp += in.dbrcnt;
490		(*cfunc)();
491		if (need_summary)
492			summary();
493		if (need_progress)
494			progress();
495	}
496}
497
498/*
499 * Clean up any remaining I/O and flush output.  If necessary, the output file
500 * is truncated.
501 */
502static void
503dd_close(void)
504{
505	if (cfunc == def)
506		def_close();
507	else if (cfunc == block)
508		block_close();
509	else if (cfunc == unblock)
510		unblock_close();
511	if (ddflags & C_OSYNC && out.dbcnt && out.dbcnt < out.dbsz) {
512		if (ddflags & C_FILL)
513			memset(out.dbp, fill_char, out.dbsz - out.dbcnt);
514		else if (ddflags & (C_BLOCK | C_UNBLOCK))
515			memset(out.dbp, ' ', out.dbsz - out.dbcnt);
516		else
517			memset(out.dbp, 0, out.dbsz - out.dbcnt);
518		out.dbcnt = out.dbsz;
519	}
520	if (out.dbcnt || pending)
521		dd_out(1);
522
523	/*
524	 * If the file ends with a hole, ftruncate it to extend its size
525	 * up to the end of the hole (without having to write any data).
526	 */
527	if (out.seek_offset > 0 && (out.flags & ISTRUNC)) {
528		if (ftruncate(out.fd, out.seek_offset) == -1)
529			err(1, "truncating %s", out.name);
530	}
531
532	if (ddflags & C_FSYNC) {
533		if (fsync(out.fd) == -1)
534			err(1, "fsyncing %s", out.name);
535	} else if (ddflags & C_FDATASYNC) {
536		if (fdatasync(out.fd) == -1)
537			err(1, "fdatasyncing %s", out.name);
538	}
539}
540
541void
542dd_out(int force)
543{
544	u_char *outp;
545	size_t cnt, n;
546	ssize_t nw;
547	static int warned;
548	int sparse;
549
550	/*
551	 * Write one or more blocks out.  The common case is writing a full
552	 * output block in a single write; increment the full block stats.
553	 * Otherwise, we're into partial block writes.  If a partial write,
554	 * and it's a character device, just warn.  If a tape device, quit.
555	 *
556	 * The partial writes represent two cases.  1: Where the input block
557	 * was less than expected so the output block was less than expected.
558	 * 2: Where the input block was the right size but we were forced to
559	 * write the block in multiple chunks.  The original versions of dd(1)
560	 * never wrote a block in more than a single write, so the latter case
561	 * never happened.
562	 *
563	 * One special case is if we're forced to do the write -- in that case
564	 * we play games with the buffer size, and it's usually a partial write.
565	 */
566	outp = out.db;
567
568	/*
569	 * If force, first try to write all pending data, else try to write
570	 * just one block. Subsequently always write data one full block at
571	 * a time at most.
572	 */
573	for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) {
574		cnt = n;
575		do {
576			sparse = 0;
577			if (ddflags & C_SPARSE) {
578				/* Is buffer sparse? */
579				sparse = BISZERO(outp, cnt);
580			}
581			if (sparse && !force) {
582				pending += cnt;
583				nw = cnt;
584			} else {
585				if (pending != 0) {
586					/*
587					 * Seek past hole.  Note that we need to record the
588					 * reached offset, because we might have no more data
589					 * to write, in which case we'll need to call
590					 * ftruncate to extend the file size.
591					 */
592					out.seek_offset = lseek(out.fd, pending, SEEK_CUR);
593					if (out.seek_offset == -1)
594						err(2, "%s: seek error creating sparse file",
595						    out.name);
596					pending = 0;
597				}
598				if (cnt) {
599					nw = write(out.fd, outp, cnt);
600					out.seek_offset = 0;
601				} else {
602					return;
603				}
604			}
605
606			if (nw <= 0) {
607				if (nw == 0)
608					errx(1, "%s: end of device", out.name);
609				if (errno != EINTR)
610					err(1, "%s", out.name);
611				nw = 0;
612			}
613
614			outp += nw;
615			st.bytes += nw;
616
617			if ((size_t)nw == n && n == (size_t)out.dbsz)
618				++st.out_full;
619			else
620				++st.out_part;
621
622			if ((size_t) nw != cnt) {
623				if (out.flags & ISTAPE)
624					errx(1, "%s: short write on tape device",
625				    	out.name);
626				if (out.flags & ISCHR && !warned) {
627					warned = 1;
628					warnx("%s: short write on character device",
629				    	out.name);
630				}
631			}
632
633			cnt -= nw;
634		} while (cnt != 0);
635
636		if ((out.dbcnt -= n) < out.dbsz)
637			break;
638	}
639
640	/* Reassemble the output block. */
641	if (out.dbcnt)
642		(void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt);
643	out.dbp = out.db + out.dbcnt;
644}
645