/bin/dd/dd.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 494 lines · 347 code · 46 blank · 101 comment · 139 complexity · b19186900826ffcf14dffd34202d5e2a MD5 · raw file

  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. #if 0
  34. #ifndef lint
  35. static char const copyright[] =
  36. "@(#) Copyright (c) 1991, 1993, 1994\n\
  37. The Regents of the University of California. All rights reserved.\n";
  38. #endif /* not lint */
  39. #ifndef lint
  40. static char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94";
  41. #endif /* not lint */
  42. #endif
  43. #include <sys/cdefs.h>
  44. __FBSDID("$FreeBSD$");
  45. #include <sys/param.h>
  46. #include <sys/stat.h>
  47. #include <sys/conf.h>
  48. #include <sys/disklabel.h>
  49. #include <sys/filio.h>
  50. #include <sys/time.h>
  51. #include <ctype.h>
  52. #include <err.h>
  53. #include <errno.h>
  54. #include <fcntl.h>
  55. #include <inttypes.h>
  56. #include <locale.h>
  57. #include <stdio.h>
  58. #include <stdlib.h>
  59. #include <string.h>
  60. #include <unistd.h>
  61. #include "dd.h"
  62. #include "extern.h"
  63. static void dd_close(void);
  64. static void dd_in(void);
  65. static void getfdtype(IO *);
  66. static void setup(void);
  67. IO in, out; /* input/output state */
  68. STAT st; /* statistics */
  69. void (*cfunc)(void); /* conversion function */
  70. uintmax_t cpy_cnt; /* # of blocks to copy */
  71. static off_t pending = 0; /* pending seek if sparse */
  72. u_int ddflags = 0; /* conversion options */
  73. size_t cbsz; /* conversion block size */
  74. uintmax_t files_cnt = 1; /* # of files to copy */
  75. const u_char *ctab; /* conversion table */
  76. char fill_char; /* Character to fill with if defined */
  77. int
  78. main(int argc __unused, char *argv[])
  79. {
  80. (void)setlocale(LC_CTYPE, "");
  81. jcl(argv);
  82. setup();
  83. (void)signal(SIGINFO, summaryx);
  84. (void)signal(SIGINT, terminate);
  85. atexit(summary);
  86. while (files_cnt--)
  87. dd_in();
  88. dd_close();
  89. exit(0);
  90. }
  91. static int
  92. parity(u_char c)
  93. {
  94. int i;
  95. i = c ^ (c >> 1) ^ (c >> 2) ^ (c >> 3) ^
  96. (c >> 4) ^ (c >> 5) ^ (c >> 6) ^ (c >> 7);
  97. return (i & 1);
  98. }
  99. static void
  100. setup(void)
  101. {
  102. u_int cnt;
  103. struct timeval tv;
  104. if (in.name == NULL) {
  105. in.name = "stdin";
  106. in.fd = STDIN_FILENO;
  107. } else {
  108. in.fd = open(in.name, O_RDONLY, 0);
  109. if (in.fd == -1)
  110. err(1, "%s", in.name);
  111. }
  112. getfdtype(&in);
  113. if (files_cnt > 1 && !(in.flags & ISTAPE))
  114. errx(1, "files is not supported for non-tape devices");
  115. if (out.name == NULL) {
  116. /* No way to check for read access here. */
  117. out.fd = STDOUT_FILENO;
  118. out.name = "stdout";
  119. } else {
  120. #define OFLAGS \
  121. (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
  122. out.fd = open(out.name, O_RDWR | OFLAGS, DEFFILEMODE);
  123. /*
  124. * May not have read access, so try again with write only.
  125. * Without read we may have a problem if output also does
  126. * not support seeks.
  127. */
  128. if (out.fd == -1) {
  129. out.fd = open(out.name, O_WRONLY | OFLAGS, DEFFILEMODE);
  130. out.flags |= NOREAD;
  131. }
  132. if (out.fd == -1)
  133. err(1, "%s", out.name);
  134. }
  135. getfdtype(&out);
  136. /*
  137. * Allocate space for the input and output buffers. If not doing
  138. * record oriented I/O, only need a single buffer.
  139. */
  140. if (!(ddflags & (C_BLOCK | C_UNBLOCK))) {
  141. if ((in.db = malloc(out.dbsz + in.dbsz - 1)) == NULL)
  142. err(1, "input buffer");
  143. out.db = in.db;
  144. } else if ((in.db = malloc(MAX(in.dbsz, cbsz) + cbsz)) == NULL ||
  145. (out.db = malloc(out.dbsz + cbsz)) == NULL)
  146. err(1, "output buffer");
  147. in.dbp = in.db;
  148. out.dbp = out.db;
  149. /* Position the input/output streams. */
  150. if (in.offset)
  151. pos_in();
  152. if (out.offset)
  153. pos_out();
  154. /*
  155. * Truncate the output file. If it fails on a type of output file
  156. * that it should _not_ fail on, error out.
  157. */
  158. if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK) &&
  159. out.flags & ISTRUNC)
  160. if (ftruncate(out.fd, out.offset * out.dbsz) == -1)
  161. err(1, "truncating %s", out.name);
  162. if (ddflags & (C_LCASE | C_UCASE | C_ASCII | C_EBCDIC | C_PARITY)) {
  163. if (ctab != NULL) {
  164. for (cnt = 0; cnt <= 0377; ++cnt)
  165. casetab[cnt] = ctab[cnt];
  166. } else {
  167. for (cnt = 0; cnt <= 0377; ++cnt)
  168. casetab[cnt] = cnt;
  169. }
  170. if ((ddflags & C_PARITY) && !(ddflags & C_ASCII)) {
  171. /*
  172. * If the input is not EBCDIC, and we do parity
  173. * processing, strip input parity.
  174. */
  175. for (cnt = 200; cnt <= 0377; ++cnt)
  176. casetab[cnt] = casetab[cnt & 0x7f];
  177. }
  178. if (ddflags & C_LCASE) {
  179. for (cnt = 0; cnt <= 0377; ++cnt)
  180. casetab[cnt] = tolower(casetab[cnt]);
  181. } else if (ddflags & C_UCASE) {
  182. for (cnt = 0; cnt <= 0377; ++cnt)
  183. casetab[cnt] = toupper(casetab[cnt]);
  184. }
  185. if ((ddflags & C_PARITY)) {
  186. /*
  187. * This should strictly speaking be a no-op, but I
  188. * wonder what funny LANG settings could get us.
  189. */
  190. for (cnt = 0; cnt <= 0377; ++cnt)
  191. casetab[cnt] = casetab[cnt] & 0x7f;
  192. }
  193. if ((ddflags & C_PARSET)) {
  194. for (cnt = 0; cnt <= 0377; ++cnt)
  195. casetab[cnt] = casetab[cnt] | 0x80;
  196. }
  197. if ((ddflags & C_PAREVEN)) {
  198. for (cnt = 0; cnt <= 0377; ++cnt)
  199. if (parity(casetab[cnt]))
  200. casetab[cnt] = casetab[cnt] | 0x80;
  201. }
  202. if ((ddflags & C_PARODD)) {
  203. for (cnt = 0; cnt <= 0377; ++cnt)
  204. if (!parity(casetab[cnt]))
  205. casetab[cnt] = casetab[cnt] | 0x80;
  206. }
  207. ctab = casetab;
  208. }
  209. (void)gettimeofday(&tv, NULL);
  210. st.start = tv.tv_sec + tv.tv_usec * 1e-6;
  211. }
  212. static void
  213. getfdtype(IO *io)
  214. {
  215. struct stat sb;
  216. int type;
  217. if (fstat(io->fd, &sb) == -1)
  218. err(1, "%s", io->name);
  219. if (S_ISREG(sb.st_mode))
  220. io->flags |= ISTRUNC;
  221. if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) {
  222. if (ioctl(io->fd, FIODTYPE, &type) == -1) {
  223. err(1, "%s", io->name);
  224. } else {
  225. if (type & D_TAPE)
  226. io->flags |= ISTAPE;
  227. else if (type & (D_DISK | D_MEM))
  228. io->flags |= ISSEEK;
  229. if (S_ISCHR(sb.st_mode) && (type & D_TAPE) == 0)
  230. io->flags |= ISCHR;
  231. }
  232. return;
  233. }
  234. errno = 0;
  235. if (lseek(io->fd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE)
  236. io->flags |= ISPIPE;
  237. else
  238. io->flags |= ISSEEK;
  239. }
  240. static void
  241. dd_in(void)
  242. {
  243. ssize_t n;
  244. for (;;) {
  245. switch (cpy_cnt) {
  246. case -1: /* count=0 was specified */
  247. return;
  248. case 0:
  249. break;
  250. default:
  251. if (st.in_full + st.in_part >= (uintmax_t)cpy_cnt)
  252. return;
  253. break;
  254. }
  255. /*
  256. * Zero the buffer first if sync; if doing block operations,
  257. * use spaces.
  258. */
  259. if (ddflags & C_SYNC) {
  260. if (ddflags & C_FILL)
  261. memset(in.dbp, fill_char, in.dbsz);
  262. else if (ddflags & (C_BLOCK | C_UNBLOCK))
  263. memset(in.dbp, ' ', in.dbsz);
  264. else
  265. memset(in.dbp, 0, in.dbsz);
  266. }
  267. n = read(in.fd, in.dbp, in.dbsz);
  268. if (n == 0) {
  269. in.dbrcnt = 0;
  270. return;
  271. }
  272. /* Read error. */
  273. if (n == -1) {
  274. /*
  275. * If noerror not specified, die. POSIX requires that
  276. * the warning message be followed by an I/O display.
  277. */
  278. if (!(ddflags & C_NOERROR))
  279. err(1, "%s", in.name);
  280. warn("%s", in.name);
  281. summary();
  282. /*
  283. * If it's a seekable file descriptor, seek past the
  284. * error. If your OS doesn't do the right thing for
  285. * raw disks this section should be modified to re-read
  286. * in sector size chunks.
  287. */
  288. if (in.flags & ISSEEK &&
  289. lseek(in.fd, (off_t)in.dbsz, SEEK_CUR))
  290. warn("%s", in.name);
  291. /* If sync not specified, omit block and continue. */
  292. if (!(ddflags & C_SYNC))
  293. continue;
  294. /* Read errors count as full blocks. */
  295. in.dbcnt += in.dbrcnt = in.dbsz;
  296. ++st.in_full;
  297. /* Handle full input blocks. */
  298. } else if ((size_t)n == in.dbsz) {
  299. in.dbcnt += in.dbrcnt = n;
  300. ++st.in_full;
  301. /* Handle partial input blocks. */
  302. } else {
  303. /* If sync, use the entire block. */
  304. if (ddflags & C_SYNC)
  305. in.dbcnt += in.dbrcnt = in.dbsz;
  306. else
  307. in.dbcnt += in.dbrcnt = n;
  308. ++st.in_part;
  309. }
  310. /*
  311. * POSIX states that if bs is set and no other conversions
  312. * than noerror, notrunc or sync are specified, the block
  313. * is output without buffering as it is read.
  314. */
  315. if (ddflags & C_BS) {
  316. out.dbcnt = in.dbcnt;
  317. dd_out(1);
  318. in.dbcnt = 0;
  319. continue;
  320. }
  321. if (ddflags & C_SWAB) {
  322. if ((n = in.dbrcnt) & 1) {
  323. ++st.swab;
  324. --n;
  325. }
  326. swab(in.dbp, in.dbp, (size_t)n);
  327. }
  328. in.dbp += in.dbrcnt;
  329. (*cfunc)();
  330. }
  331. }
  332. /*
  333. * Clean up any remaining I/O and flush output. If necessary, the output file
  334. * is truncated.
  335. */
  336. static void
  337. dd_close(void)
  338. {
  339. if (cfunc == def)
  340. def_close();
  341. else if (cfunc == block)
  342. block_close();
  343. else if (cfunc == unblock)
  344. unblock_close();
  345. if (ddflags & C_OSYNC && out.dbcnt && out.dbcnt < out.dbsz) {
  346. if (ddflags & C_FILL)
  347. memset(out.dbp, fill_char, out.dbsz - out.dbcnt);
  348. else if (ddflags & (C_BLOCK | C_UNBLOCK))
  349. memset(out.dbp, ' ', out.dbsz - out.dbcnt);
  350. else
  351. memset(out.dbp, 0, out.dbsz - out.dbcnt);
  352. out.dbcnt = out.dbsz;
  353. }
  354. if (out.dbcnt || pending)
  355. dd_out(1);
  356. }
  357. void
  358. dd_out(int force)
  359. {
  360. u_char *outp;
  361. size_t cnt, i, n;
  362. ssize_t nw;
  363. static int warned;
  364. int sparse;
  365. /*
  366. * Write one or more blocks out. The common case is writing a full
  367. * output block in a single write; increment the full block stats.
  368. * Otherwise, we're into partial block writes. If a partial write,
  369. * and it's a character device, just warn. If a tape device, quit.
  370. *
  371. * The partial writes represent two cases. 1: Where the input block
  372. * was less than expected so the output block was less than expected.
  373. * 2: Where the input block was the right size but we were forced to
  374. * write the block in multiple chunks. The original versions of dd(1)
  375. * never wrote a block in more than a single write, so the latter case
  376. * never happened.
  377. *
  378. * One special case is if we're forced to do the write -- in that case
  379. * we play games with the buffer size, and it's usually a partial write.
  380. */
  381. outp = out.db;
  382. for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) {
  383. for (cnt = n;; cnt -= nw) {
  384. sparse = 0;
  385. if (ddflags & C_SPARSE) {
  386. sparse = 1; /* Is buffer sparse? */
  387. for (i = 0; i < cnt; i++)
  388. if (outp[i] != 0) {
  389. sparse = 0;
  390. break;
  391. }
  392. }
  393. if (sparse && !force) {
  394. pending += cnt;
  395. nw = cnt;
  396. } else {
  397. if (pending != 0) {
  398. if (force)
  399. pending--;
  400. if (lseek(out.fd, pending, SEEK_CUR) ==
  401. -1)
  402. err(2, "%s: seek error creating sparse file",
  403. out.name);
  404. if (force)
  405. write(out.fd, outp, 1);
  406. pending = 0;
  407. }
  408. if (cnt)
  409. nw = write(out.fd, outp, cnt);
  410. else
  411. return;
  412. }
  413. if (nw <= 0) {
  414. if (nw == 0)
  415. errx(1, "%s: end of device", out.name);
  416. if (errno != EINTR)
  417. err(1, "%s", out.name);
  418. nw = 0;
  419. }
  420. outp += nw;
  421. st.bytes += nw;
  422. if ((size_t)nw == n) {
  423. if (n != out.dbsz)
  424. ++st.out_part;
  425. else
  426. ++st.out_full;
  427. break;
  428. }
  429. ++st.out_part;
  430. if ((size_t)nw == cnt)
  431. break;
  432. if (out.flags & ISTAPE)
  433. errx(1, "%s: short write on tape device",
  434. out.name);
  435. if (out.flags & ISCHR && !warned) {
  436. warned = 1;
  437. warnx("%s: short write on character device",
  438. out.name);
  439. }
  440. }
  441. if ((out.dbcnt -= n) < out.dbsz)
  442. break;
  443. }
  444. /* Reassemble the output block. */
  445. if (out.dbcnt)
  446. (void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt);
  447. out.dbp = out.db + out.dbcnt;
  448. }