]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - bin/dd/dd.c
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r304222, and update
[FreeBSD/FreeBSD.git] / bin / dd / dd.c
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  * 3. 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
36 static 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
42 static char sccsid[] = "@(#)dd.c        8.5 (Berkeley) 4/2/94";
43 #endif /* not lint */
44 #endif
45 #include <sys/cdefs.h>
46 __FBSDID("$FreeBSD$");
47
48 #include <sys/param.h>
49 #include <sys/stat.h>
50 #include <sys/capsicum.h>
51 #include <sys/conf.h>
52 #include <sys/disklabel.h>
53 #include <sys/filio.h>
54 #include <sys/mtio.h>
55
56 #include <assert.h>
57 #include <capsicum_helpers.h>
58 #include <ctype.h>
59 #include <err.h>
60 #include <errno.h>
61 #include <fcntl.h>
62 #include <inttypes.h>
63 #include <locale.h>
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include <time.h>
68 #include <unistd.h>
69
70 #include "dd.h"
71 #include "extern.h"
72
73 static void dd_close(void);
74 static void dd_in(void);
75 static void getfdtype(IO *);
76 static void setup(void);
77
78 IO      in, out;                /* input/output state */
79 STAT    st;                     /* statistics */
80 void    (*cfunc)(void);         /* conversion function */
81 uintmax_t cpy_cnt;              /* # of blocks to copy */
82 static off_t    pending = 0;    /* pending seek if sparse */
83 u_int   ddflags = 0;            /* conversion options */
84 size_t  cbsz;                   /* conversion block size */
85 uintmax_t files_cnt = 1;        /* # of files to copy */
86 const   u_char *ctab;           /* conversion table */
87 char    fill_char;              /* Character to fill with if defined */
88 size_t  speed = 0;              /* maximum speed, in bytes per second */
89 volatile sig_atomic_t need_summary;
90
91 int
92 main(int argc __unused, char *argv[])
93 {
94         (void)setlocale(LC_CTYPE, "");
95         jcl(argv);
96         setup();
97
98         caph_cache_catpages();
99         if (cap_enter() == -1 && errno != ENOSYS)
100                 err(1, "unable to enter capability mode");
101
102         (void)signal(SIGINFO, siginfo_handler);
103         (void)signal(SIGINT, terminate);
104
105         atexit(summary);
106
107         while (files_cnt--)
108                 dd_in();
109
110         dd_close();
111         /*
112          * Some devices such as cfi(4) may perform significant amounts
113          * of work when a write descriptor is closed.  Close the out
114          * descriptor explicitly so that the summary handler (called
115          * from an atexit() hook) includes this work.
116          */
117         close(out.fd);
118         exit(0);
119 }
120
121 static int
122 parity(u_char c)
123 {
124         int i;
125
126         i = c ^ (c >> 1) ^ (c >> 2) ^ (c >> 3) ^ 
127             (c >> 4) ^ (c >> 5) ^ (c >> 6) ^ (c >> 7);
128         return (i & 1);
129 }
130
131 static void
132 setup(void)
133 {
134         u_int cnt;
135         cap_rights_t rights;
136         unsigned long cmds[] = { FIODTYPE, MTIOCTOP };
137
138         if (in.name == NULL) {
139                 in.name = "stdin";
140                 in.fd = STDIN_FILENO;
141         } else {
142                 in.fd = open(in.name, O_RDONLY, 0);
143                 if (in.fd == -1)
144                         err(1, "%s", in.name);
145         }
146
147         getfdtype(&in);
148
149         cap_rights_init(&rights, CAP_READ, CAP_SEEK);
150         if (cap_rights_limit(in.fd, &rights) == -1 && errno != ENOSYS)
151                 err(1, "unable to limit capability rights");
152
153         if (files_cnt > 1 && !(in.flags & ISTAPE))
154                 errx(1, "files is not supported for non-tape devices");
155
156         cap_rights_set(&rights, CAP_FTRUNCATE, CAP_IOCTL, CAP_WRITE);
157         if (out.name == NULL) {
158                 /* No way to check for read access here. */
159                 out.fd = STDOUT_FILENO;
160                 out.name = "stdout";
161         } else {
162 #define OFLAGS \
163     (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
164                 out.fd = open(out.name, O_RDWR | OFLAGS, DEFFILEMODE);
165                 /*
166                  * May not have read access, so try again with write only.
167                  * Without read we may have a problem if output also does
168                  * not support seeks.
169                  */
170                 if (out.fd == -1) {
171                         out.fd = open(out.name, O_WRONLY | OFLAGS, DEFFILEMODE);
172                         out.flags |= NOREAD;
173                         cap_rights_clear(&rights, CAP_READ);
174                 }
175                 if (out.fd == -1)
176                         err(1, "%s", out.name);
177         }
178
179         getfdtype(&out);
180
181         if (cap_rights_limit(out.fd, &rights) == -1 && errno != ENOSYS)
182                 err(1, "unable to limit capability rights");
183         if (cap_ioctls_limit(out.fd, cmds, nitems(cmds)) == -1 &&
184             errno != ENOSYS)
185                 err(1, "unable to limit capability rights");
186
187         if (in.fd != STDIN_FILENO && out.fd != STDIN_FILENO) {
188                 if (caph_limit_stdin() == -1)
189                         err(1, "unable to limit capability rights");
190         }
191
192         if (in.fd != STDOUT_FILENO && out.fd != STDOUT_FILENO) {
193                 if (caph_limit_stdout() == -1)
194                         err(1, "unable to limit capability rights");
195         }
196
197         if (in.fd != STDERR_FILENO && out.fd != STDERR_FILENO) {
198                 if (caph_limit_stderr() == -1)
199                         err(1, "unable to limit capability rights");
200         }
201
202         /*
203          * Allocate space for the input and output buffers.  If not doing
204          * record oriented I/O, only need a single buffer.
205          */
206         if (!(ddflags & (C_BLOCK | C_UNBLOCK))) {
207                 if ((in.db = malloc(out.dbsz + in.dbsz - 1)) == NULL)
208                         err(1, "input buffer");
209                 out.db = in.db;
210         } else if ((in.db = malloc(MAX(in.dbsz, cbsz) + cbsz)) == NULL ||
211             (out.db = malloc(out.dbsz + cbsz)) == NULL)
212                 err(1, "output buffer");
213
214         /* dbp is the first free position in each buffer. */
215         in.dbp = in.db;
216         out.dbp = out.db;
217
218         /* Position the input/output streams. */
219         if (in.offset)
220                 pos_in();
221         if (out.offset)
222                 pos_out();
223
224         /*
225          * Truncate the output file.  If it fails on a type of output file
226          * that it should _not_ fail on, error out.
227          */
228         if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK) &&
229             out.flags & ISTRUNC)
230                 if (ftruncate(out.fd, out.offset * out.dbsz) == -1)
231                         err(1, "truncating %s", out.name);
232
233         if (ddflags & (C_LCASE  | C_UCASE | C_ASCII | C_EBCDIC | C_PARITY)) {
234                 if (ctab != NULL) {
235                         for (cnt = 0; cnt <= 0377; ++cnt)
236                                 casetab[cnt] = ctab[cnt];
237                 } else {
238                         for (cnt = 0; cnt <= 0377; ++cnt)
239                                 casetab[cnt] = cnt;
240                 }
241                 if ((ddflags & C_PARITY) && !(ddflags & C_ASCII)) {
242                         /*
243                          * If the input is not EBCDIC, and we do parity
244                          * processing, strip input parity.
245                          */
246                         for (cnt = 200; cnt <= 0377; ++cnt)
247                                 casetab[cnt] = casetab[cnt & 0x7f];
248                 }
249                 if (ddflags & C_LCASE) {
250                         for (cnt = 0; cnt <= 0377; ++cnt)
251                                 casetab[cnt] = tolower(casetab[cnt]);
252                 } else if (ddflags & C_UCASE) {
253                         for (cnt = 0; cnt <= 0377; ++cnt)
254                                 casetab[cnt] = toupper(casetab[cnt]);
255                 }
256                 if ((ddflags & C_PARITY)) {
257                         /*
258                          * This should strictly speaking be a no-op, but I
259                          * wonder what funny LANG settings could get us.
260                          */
261                         for (cnt = 0; cnt <= 0377; ++cnt)
262                                 casetab[cnt] = casetab[cnt] & 0x7f;
263                 }
264                 if ((ddflags & C_PARSET)) {
265                         for (cnt = 0; cnt <= 0377; ++cnt)
266                                 casetab[cnt] = casetab[cnt] | 0x80;
267                 }
268                 if ((ddflags & C_PAREVEN)) {
269                         for (cnt = 0; cnt <= 0377; ++cnt)
270                                 if (parity(casetab[cnt]))
271                                         casetab[cnt] = casetab[cnt] | 0x80;
272                 }
273                 if ((ddflags & C_PARODD)) {
274                         for (cnt = 0; cnt <= 0377; ++cnt)
275                                 if (!parity(casetab[cnt]))
276                                         casetab[cnt] = casetab[cnt] | 0x80;
277                 }
278
279                 ctab = casetab;
280         }
281
282         if (clock_gettime(CLOCK_MONOTONIC, &st.start))
283                 err(1, "clock_gettime");
284 }
285
286 static void
287 getfdtype(IO *io)
288 {
289         struct stat sb;
290         int type;
291
292         if (fstat(io->fd, &sb) == -1)
293                 err(1, "%s", io->name);
294         if (S_ISREG(sb.st_mode))
295                 io->flags |= ISTRUNC;
296         if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) { 
297                 if (ioctl(io->fd, FIODTYPE, &type) == -1) {
298                         err(1, "%s", io->name);
299                 } else {
300                         if (type & D_TAPE)
301                                 io->flags |= ISTAPE;
302                         else if (type & (D_DISK | D_MEM))
303                                 io->flags |= ISSEEK;
304                         if (S_ISCHR(sb.st_mode) && (type & D_TAPE) == 0)
305                                 io->flags |= ISCHR;
306                 }
307                 return;
308         }
309         errno = 0;
310         if (lseek(io->fd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE)
311                 io->flags |= ISPIPE;
312         else
313                 io->flags |= ISSEEK;
314 }
315
316 /*
317  * Limit the speed by adding a delay before every block read.
318  * The delay (t_usleep) is equal to the time computed from block
319  * size and the specified speed limit (t_target) minus the time
320  * spent on actual read and write operations (t_io).
321  */
322 static void
323 speed_limit(void)
324 {
325         static double t_prev, t_usleep;
326         double t_now, t_io, t_target;
327
328         t_now = secs_elapsed();
329         t_io = t_now - t_prev - t_usleep;
330         t_target = (double)in.dbsz / (double)speed;
331         t_usleep = t_target - t_io;
332         if (t_usleep > 0)
333                 usleep(t_usleep * 1000000);
334         else
335                 t_usleep = 0;
336         t_prev = t_now;
337 }
338
339 static void
340 dd_in(void)
341 {
342         ssize_t n;
343
344         for (;;) {
345                 switch (cpy_cnt) {
346                 case -1:                        /* count=0 was specified */
347                         return;
348                 case 0:
349                         break;
350                 default:
351                         if (st.in_full + st.in_part >= (uintmax_t)cpy_cnt)
352                                 return;
353                         break;
354                 }
355
356                 if (speed > 0)
357                         speed_limit();
358
359                 /*
360                  * Zero the buffer first if sync; if doing block operations,
361                  * use spaces.
362                  */
363                 if (ddflags & C_SYNC) {
364                         if (ddflags & C_FILL)
365                                 memset(in.dbp, fill_char, in.dbsz);
366                         else if (ddflags & (C_BLOCK | C_UNBLOCK))
367                                 memset(in.dbp, ' ', in.dbsz);
368                         else
369                                 memset(in.dbp, 0, in.dbsz);
370                 }
371
372                 n = read(in.fd, in.dbp, in.dbsz);
373                 if (n == 0) {
374                         in.dbrcnt = 0;
375                         return;
376                 }
377
378                 /* Read error. */
379                 if (n == -1) {
380                         /*
381                          * If noerror not specified, die.  POSIX requires that
382                          * the warning message be followed by an I/O display.
383                          */
384                         if (!(ddflags & C_NOERROR))
385                                 err(1, "%s", in.name);
386                         warn("%s", in.name);
387                         summary();
388
389                         /*
390                          * If it's a seekable file descriptor, seek past the
391                          * error.  If your OS doesn't do the right thing for
392                          * raw disks this section should be modified to re-read
393                          * in sector size chunks.
394                          */
395                         if (in.flags & ISSEEK &&
396                             lseek(in.fd, (off_t)in.dbsz, SEEK_CUR))
397                                 warn("%s", in.name);
398
399                         /* If sync not specified, omit block and continue. */
400                         if (!(ddflags & C_SYNC))
401                                 continue;
402
403                         /* Read errors count as full blocks. */
404                         in.dbcnt += in.dbrcnt = in.dbsz;
405                         ++st.in_full;
406
407                 /* Handle full input blocks. */
408                 } else if ((size_t)n == in.dbsz) {
409                         in.dbcnt += in.dbrcnt = n;
410                         ++st.in_full;
411
412                 /* Handle partial input blocks. */
413                 } else {
414                         /* If sync, use the entire block. */
415                         if (ddflags & C_SYNC)
416                                 in.dbcnt += in.dbrcnt = in.dbsz;
417                         else
418                                 in.dbcnt += in.dbrcnt = n;
419                         ++st.in_part;
420                 }
421
422                 /*
423                  * POSIX states that if bs is set and no other conversions
424                  * than noerror, notrunc or sync are specified, the block
425                  * is output without buffering as it is read.
426                  */
427                 if ((ddflags & ~(C_NOERROR | C_NOTRUNC | C_SYNC)) == C_BS) {
428                         out.dbcnt = in.dbcnt;
429                         dd_out(1);
430                         in.dbcnt = 0;
431                         continue;
432                 }
433
434                 if (ddflags & C_SWAB) {
435                         if ((n = in.dbrcnt) & 1) {
436                                 ++st.swab;
437                                 --n;
438                         }
439                         swab(in.dbp, in.dbp, (size_t)n);
440                 }
441
442                 in.dbp += in.dbrcnt;
443                 (*cfunc)();
444                 if (need_summary) {
445                         summary();
446                 }
447         }
448 }
449
450 /*
451  * Clean up any remaining I/O and flush output.  If necessary, the output file
452  * is truncated.
453  */
454 static void
455 dd_close(void)
456 {
457         if (cfunc == def)
458                 def_close();
459         else if (cfunc == block)
460                 block_close();
461         else if (cfunc == unblock)
462                 unblock_close();
463         if (ddflags & C_OSYNC && out.dbcnt && out.dbcnt < out.dbsz) {
464                 if (ddflags & C_FILL)
465                         memset(out.dbp, fill_char, out.dbsz - out.dbcnt);
466                 else if (ddflags & (C_BLOCK | C_UNBLOCK))
467                         memset(out.dbp, ' ', out.dbsz - out.dbcnt);
468                 else
469                         memset(out.dbp, 0, out.dbsz - out.dbcnt);
470                 out.dbcnt = out.dbsz;
471         }
472         if (out.dbcnt || pending)
473                 dd_out(1);
474
475         /*
476          * If the file ends with a hole, ftruncate it to extend its size
477          * up to the end of the hole (without having to write any data).
478          */
479         if (out.seek_offset > 0 && (out.flags & ISTRUNC)) {
480                 if (ftruncate(out.fd, out.seek_offset) == -1)
481                         err(1, "truncating %s", out.name);
482         }
483 }
484
485 void
486 dd_out(int force)
487 {
488         u_char *outp;
489         size_t cnt, i, n;
490         ssize_t nw;
491         static int warned;
492         int sparse;
493
494         /*
495          * Write one or more blocks out.  The common case is writing a full
496          * output block in a single write; increment the full block stats.
497          * Otherwise, we're into partial block writes.  If a partial write,
498          * and it's a character device, just warn.  If a tape device, quit.
499          *
500          * The partial writes represent two cases.  1: Where the input block
501          * was less than expected so the output block was less than expected.
502          * 2: Where the input block was the right size but we were forced to
503          * write the block in multiple chunks.  The original versions of dd(1)
504          * never wrote a block in more than a single write, so the latter case
505          * never happened.
506          *
507          * One special case is if we're forced to do the write -- in that case
508          * we play games with the buffer size, and it's usually a partial write.
509          */
510         outp = out.db;
511
512         /*
513          * If force, first try to write all pending data, else try to write
514          * just one block. Subsequently always write data one full block at
515          * a time at most.
516          */
517         for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) {
518                 cnt = n;
519                 do {
520                         sparse = 0;
521                         if (ddflags & C_SPARSE) {
522                                 sparse = 1;     /* Is buffer sparse? */
523                                 for (i = 0; i < cnt; i++)
524                                         if (outp[i] != 0) {
525                                                 sparse = 0;
526                                                 break;
527                                         }
528                         }
529                         if (sparse && !force) {
530                                 pending += cnt;
531                                 nw = cnt;
532                         } else {
533                                 if (pending != 0) {
534                                         /*
535                                          * Seek past hole.  Note that we need to record the
536                                          * reached offset, because we might have no more data
537                                          * to write, in which case we'll need to call
538                                          * ftruncate to extend the file size.
539                                          */
540                                         out.seek_offset = lseek(out.fd, pending, SEEK_CUR);
541                                         if (out.seek_offset == -1)
542                                                 err(2, "%s: seek error creating sparse file",
543                                                     out.name);
544                                         pending = 0;
545                                 }
546                                 if (cnt) {
547                                         nw = write(out.fd, outp, cnt);
548                                         out.seek_offset = 0;
549                                 } else {
550                                         return;
551                                 }
552                         }
553
554                         if (nw <= 0) {
555                                 if (nw == 0)
556                                         errx(1, "%s: end of device", out.name);
557                                 if (errno != EINTR)
558                                         err(1, "%s", out.name);
559                                 nw = 0;
560                         }
561
562                         outp += nw;
563                         st.bytes += nw;
564
565                         if ((size_t)nw == n && n == out.dbsz)
566                                 ++st.out_full;
567                         else
568                                 ++st.out_part;
569
570                         if ((size_t) nw != cnt) {
571                                 if (out.flags & ISTAPE)
572                                         errx(1, "%s: short write on tape device",
573                                         out.name);
574                                 if (out.flags & ISCHR && !warned) {
575                                         warned = 1;
576                                         warnx("%s: short write on character device",
577                                         out.name);
578                                 }
579                         }
580
581                         cnt -= nw;
582                 } while (cnt != 0);
583
584                 if ((out.dbcnt -= n) < out.dbsz)
585                         break;
586         }
587
588         /* Reassemble the output block. */
589         if (out.dbcnt)
590                 (void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt);
591         out.dbp = out.db + out.dbcnt;
592 }