dd.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323
  1. /* $NetBSD: dd.c,v 1.37 2004/01/17 21:00:16 dbj Exp $ */
  2. /*-
  3. * Copyright (c) 1991, 1993, 1994
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Keith Muller of the University of California, San Diego and Lance
  8. * Visser of Convex Computer Corporation.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. * 3. Neither the name of the University nor the names of its contributors
  19. * may be used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. * SUCH DAMAGE.
  33. */
  34. #include <sys/cdefs.h>
  35. #ifndef lint
  36. __COPYRIGHT("@(#) 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. #if 0
  41. static char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94";
  42. #else
  43. __RCSID("$NetBSD: dd.c,v 1.37 2004/01/17 21:00:16 dbj Exp $");
  44. #endif
  45. #endif /* not lint */
  46. #include <sys/param.h>
  47. #include <sys/stat.h>
  48. #include <sys/types.h>
  49. #include <sys/ioctl.h>
  50. #include <sys/time.h>
  51. #include <ctype.h>
  52. #include <err.h>
  53. #include <errno.h>
  54. #include <fcntl.h>
  55. #include <signal.h>
  56. #include <stdio.h>
  57. #include <stdlib.h>
  58. #include <string.h>
  59. #include <unistd.h>
  60. #include "dd.h"
  61. //#define NO_CONV
  62. //#include "extern.h"
  63. void block(void);
  64. void block_close(void);
  65. void dd_out(int);
  66. void def(void);
  67. void def_close(void);
  68. void jcl(char **);
  69. void pos_in(void);
  70. void pos_out(void);
  71. void summary(void);
  72. void summaryx(int);
  73. void terminate(int);
  74. void unblock(void);
  75. void unblock_close(void);
  76. ssize_t bwrite(int, const void *, size_t);
  77. extern IO in, out;
  78. extern STAT st;
  79. extern void (*cfunc)(void);
  80. extern uint64_t cpy_cnt;
  81. extern uint64_t cbsz;
  82. extern u_int ddflags;
  83. extern u_int files_cnt;
  84. extern int progress;
  85. extern const u_char *ctab;
  86. #ifndef MIN
  87. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  88. #endif
  89. #ifndef MAX
  90. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  91. #endif
  92. #ifndef DEFFILEMODE
  93. #define DEFFILEMODE (S_IRUSR | S_IWUSR)
  94. #endif
  95. static void dd_close(void);
  96. static void dd_in(void);
  97. static void getfdtype(IO *);
  98. static int redup_clean_fd(int);
  99. static void setup(void);
  100. IO in, out; /* input/output state */
  101. STAT st; /* statistics */
  102. void (*cfunc)(void); /* conversion function */
  103. uint64_t cpy_cnt; /* # of blocks to copy */
  104. static off_t pending = 0; /* pending seek if sparse */
  105. u_int ddflags; /* conversion options */
  106. uint64_t cbsz; /* conversion block size */
  107. u_int files_cnt = 1; /* # of files to copy */
  108. int progress = 0; /* display sign of life */
  109. const u_char *ctab; /* conversion table */
  110. sigset_t infoset; /* a set blocking SIGINFO */
  111. int
  112. main(int argc, char *argv[])
  113. {
  114. int ch;
  115. while ((ch = getopt(argc, argv, "")) != -1) {
  116. switch (ch) {
  117. default:
  118. fprintf(stderr, "usage: dd [operand ...]\n");
  119. exit(1);
  120. /* NOTREACHED */
  121. }
  122. }
  123. argc -= (optind - 1);
  124. argv += (optind - 1);
  125. jcl(argv);
  126. setup();
  127. // (void)signal(SIGINFO, summaryx);
  128. (void)signal(SIGINT, terminate);
  129. (void)sigemptyset(&infoset);
  130. // (void)sigaddset(&infoset, SIGINFO);
  131. (void)atexit(summary);
  132. while (files_cnt--)
  133. dd_in();
  134. dd_close();
  135. exit(0);
  136. /* NOTREACHED */
  137. }
  138. static void
  139. setup(void)
  140. {
  141. if (in.name == NULL) {
  142. in.name = "stdin";
  143. in.fd = STDIN_FILENO;
  144. } else {
  145. in.fd = open(in.name, O_RDONLY, 0);
  146. if (in.fd < 0) {
  147. fprintf(stderr, "%s: cannot open for read: %s\n",
  148. in.name, strerror(errno));
  149. exit(1);
  150. /* NOTREACHED */
  151. }
  152. /* Ensure in.fd is outside the stdio descriptor range */
  153. in.fd = redup_clean_fd(in.fd);
  154. }
  155. getfdtype(&in);
  156. if (files_cnt > 1 && !(in.flags & ISTAPE)) {
  157. fprintf(stderr,
  158. "files is not supported for non-tape devices\n");
  159. exit(1);
  160. /* NOTREACHED */
  161. }
  162. if (out.name == NULL) {
  163. /* No way to check for read access here. */
  164. out.fd = STDOUT_FILENO;
  165. out.name = "stdout";
  166. } else {
  167. #define OFLAGS \
  168. (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
  169. out.fd = open(out.name, O_RDWR | OFLAGS, DEFFILEMODE);
  170. /*
  171. * May not have read access, so try again with write only.
  172. * Without read we may have a problem if output also does
  173. * not support seeks.
  174. */
  175. if (out.fd < 0) {
  176. out.fd = open(out.name, O_WRONLY | OFLAGS, DEFFILEMODE);
  177. out.flags |= NOREAD;
  178. }
  179. if (out.fd < 0) {
  180. fprintf(stderr, "%s: cannot open for write: %s\n",
  181. out.name, strerror(errno));
  182. exit(1);
  183. /* NOTREACHED */
  184. }
  185. /* Ensure out.fd is outside the stdio descriptor range */
  186. out.fd = redup_clean_fd(out.fd);
  187. }
  188. getfdtype(&out);
  189. /*
  190. * Allocate space for the input and output buffers. If not doing
  191. * record oriented I/O, only need a single buffer.
  192. */
  193. if (!(ddflags & (C_BLOCK|C_UNBLOCK))) {
  194. if ((in.db = malloc(out.dbsz + in.dbsz - 1)) == NULL) {
  195. exit(1);
  196. /* NOTREACHED */
  197. }
  198. out.db = in.db;
  199. } else if ((in.db =
  200. malloc((u_int)(MAX(in.dbsz, cbsz) + cbsz))) == NULL ||
  201. (out.db = malloc((u_int)(out.dbsz + cbsz))) == NULL) {
  202. exit(1);
  203. /* NOTREACHED */
  204. }
  205. in.dbp = in.db;
  206. out.dbp = out.db;
  207. /* Position the input/output streams. */
  208. if (in.offset)
  209. pos_in();
  210. if (out.offset)
  211. pos_out();
  212. /*
  213. * Truncate the output file; ignore errors because it fails on some
  214. * kinds of output files, tapes, for example.
  215. */
  216. if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK))
  217. (void)ftruncate(out.fd, (off_t)out.offset * out.dbsz);
  218. (void)gettimeofday(&st.start, NULL); /* Statistics timestamp. */
  219. }
  220. static void
  221. getfdtype(IO *io)
  222. {
  223. // struct mtget mt;
  224. struct stat sb;
  225. if (fstat(io->fd, &sb)) {
  226. fprintf(stderr, "%s: cannot fstat: %s\n",
  227. io->name, strerror(errno));
  228. exit(1);
  229. /* NOTREACHED */
  230. }
  231. if (S_ISCHR(sb.st_mode))
  232. io->flags |= /*ioctl(io->fd, MTIOCGET, &mt) ? ISCHR : ISTAPE; */ ISCHR;
  233. else if (lseek(io->fd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE)
  234. io->flags |= ISPIPE; /* XXX fixed in 4.4BSD */
  235. }
  236. /*
  237. * Move the parameter file descriptor to a descriptor that is outside the
  238. * stdio descriptor range, if necessary. This is required to avoid
  239. * accidentally outputting completion or error messages into the
  240. * output file that were intended for the tty.
  241. */
  242. static int
  243. redup_clean_fd(int fd)
  244. {
  245. int newfd;
  246. if (fd != STDIN_FILENO && fd != STDOUT_FILENO &&
  247. fd != STDERR_FILENO)
  248. /* File descriptor is ok, return immediately. */
  249. return fd;
  250. /*
  251. * 3 is the first descriptor greater than STD*_FILENO. Any
  252. * free descriptor valued 3 or above is acceptable...
  253. */
  254. newfd = fcntl(fd, F_DUPFD, 3);
  255. if (newfd < 0) {
  256. fprintf(stderr, "dupfd IO: %s\n", strerror(errno));
  257. exit(1);
  258. /* NOTREACHED */
  259. }
  260. close(fd);
  261. return newfd;
  262. }
  263. static void
  264. dd_in(void)
  265. {
  266. int flags;
  267. int64_t n;
  268. for (flags = ddflags;;) {
  269. if (cpy_cnt && (st.in_full + st.in_part) >= cpy_cnt)
  270. return;
  271. /*
  272. * Clear the buffer first if doing "sync" on input.
  273. * If doing block operations use spaces. This will
  274. * affect not only the C_NOERROR case, but also the
  275. * last partial input block which should be padded
  276. * with zero and not garbage.
  277. */
  278. if (flags & C_SYNC) {
  279. if (flags & (C_BLOCK|C_UNBLOCK))
  280. (void)memset(in.dbp, ' ', in.dbsz);
  281. else
  282. (void)memset(in.dbp, 0, in.dbsz);
  283. }
  284. n = read(in.fd, in.dbp, in.dbsz);
  285. if (n == 0) {
  286. in.dbrcnt = 0;
  287. return;
  288. }
  289. /* Read error. */
  290. if (n < 0) {
  291. /*
  292. * If noerror not specified, die. POSIX requires that
  293. * the warning message be followed by an I/O display.
  294. */
  295. fprintf(stderr, "%s: read error: %s\n",
  296. in.name, strerror(errno));
  297. if (!(flags & C_NOERROR)) {
  298. exit(1);
  299. /* NOTREACHED */
  300. }
  301. summary();
  302. /*
  303. * If it's not a tape drive or a pipe, seek past the
  304. * error. If your OS doesn't do the right thing for
  305. * raw disks this section should be modified to re-read
  306. * in sector size chunks.
  307. */
  308. if (!(in.flags & (ISPIPE|ISTAPE)) &&
  309. lseek(in.fd, (off_t)in.dbsz, SEEK_CUR))
  310. fprintf(stderr, "%s: seek error: %s\n",
  311. in.name, strerror(errno));
  312. /* If sync not specified, omit block and continue. */
  313. if (!(ddflags & C_SYNC))
  314. continue;
  315. /* Read errors count as full blocks. */
  316. in.dbcnt += in.dbrcnt = in.dbsz;
  317. ++st.in_full;
  318. /* Handle full input blocks. */
  319. } else if (n == in.dbsz) {
  320. in.dbcnt += in.dbrcnt = n;
  321. ++st.in_full;
  322. /* Handle partial input blocks. */
  323. } else {
  324. /* If sync, use the entire block. */
  325. if (ddflags & C_SYNC)
  326. in.dbcnt += in.dbrcnt = in.dbsz;
  327. else
  328. in.dbcnt += in.dbrcnt = n;
  329. ++st.in_part;
  330. }
  331. /*
  332. * POSIX states that if bs is set and no other conversions
  333. * than noerror, notrunc or sync are specified, the block
  334. * is output without buffering as it is read.
  335. */
  336. if (ddflags & C_BS) {
  337. out.dbcnt = in.dbcnt;
  338. dd_out(1);
  339. in.dbcnt = 0;
  340. continue;
  341. }
  342. /* if (ddflags & C_SWAB) {
  343. if ((n = in.dbrcnt) & 1) {
  344. ++st.swab;
  345. --n;
  346. }
  347. swab(in.dbp, in.dbp, n);
  348. }
  349. */
  350. in.dbp += in.dbrcnt;
  351. (*cfunc)();
  352. }
  353. }
  354. /*
  355. * Cleanup any remaining I/O and flush output. If necesssary, output file
  356. * is truncated.
  357. */
  358. static void
  359. dd_close(void)
  360. {
  361. if (cfunc == def)
  362. def_close();
  363. else if (cfunc == block)
  364. block_close();
  365. else if (cfunc == unblock)
  366. unblock_close();
  367. if (ddflags & C_OSYNC && out.dbcnt < out.dbsz) {
  368. (void)memset(out.dbp, 0, out.dbsz - out.dbcnt);
  369. out.dbcnt = out.dbsz;
  370. }
  371. /* If there are pending sparse blocks, make sure
  372. * to write out the final block un-sparse
  373. */
  374. if ((out.dbcnt == 0) && pending) {
  375. memset(out.db, 0, out.dbsz);
  376. out.dbcnt = out.dbsz;
  377. out.dbp = out.db + out.dbcnt;
  378. pending -= out.dbsz;
  379. }
  380. if (out.dbcnt)
  381. dd_out(1);
  382. /*
  383. * Reporting nfs write error may be defered until next
  384. * write(2) or close(2) system call. So, we need to do an
  385. * extra check. If an output is stdout, the file structure
  386. * may be shared among with other processes and close(2) just
  387. * decreases the reference count.
  388. */
  389. if (out.fd == STDOUT_FILENO && fsync(out.fd) == -1 && errno != EINVAL) {
  390. fprintf(stderr, "fsync stdout: %s\n", strerror(errno));
  391. exit(1);
  392. /* NOTREACHED */
  393. }
  394. if (close(out.fd) == -1) {
  395. fprintf(stderr, "close: %s\n", strerror(errno));
  396. exit(1);
  397. /* NOTREACHED */
  398. }
  399. }
  400. void
  401. dd_out(int force)
  402. {
  403. static int warned;
  404. int64_t cnt, n, nw;
  405. u_char *outp;
  406. /*
  407. * Write one or more blocks out. The common case is writing a full
  408. * output block in a single write; increment the full block stats.
  409. * Otherwise, we're into partial block writes. If a partial write,
  410. * and it's a character device, just warn. If a tape device, quit.
  411. *
  412. * The partial writes represent two cases. 1: Where the input block
  413. * was less than expected so the output block was less than expected.
  414. * 2: Where the input block was the right size but we were forced to
  415. * write the block in multiple chunks. The original versions of dd(1)
  416. * never wrote a block in more than a single write, so the latter case
  417. * never happened.
  418. *
  419. * One special case is if we're forced to do the write -- in that case
  420. * we play games with the buffer size, and it's usually a partial write.
  421. */
  422. outp = out.db;
  423. for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) {
  424. for (cnt = n;; cnt -= nw) {
  425. if (!force && ddflags & C_SPARSE) {
  426. int sparse, i;
  427. sparse = 1; /* Is buffer sparse? */
  428. for (i = 0; i < cnt; i++)
  429. if (outp[i] != 0) {
  430. sparse = 0;
  431. break;
  432. }
  433. if (sparse) {
  434. pending += cnt;
  435. outp += cnt;
  436. nw = 0;
  437. break;
  438. }
  439. }
  440. if (pending != 0) {
  441. if (lseek(out.fd, pending, SEEK_CUR) ==
  442. -1) {
  443. fprintf(stderr,
  444. "%s: seek error creating "
  445. "sparse file: %s\n",
  446. out.name, strerror(errno));
  447. exit(1);
  448. }
  449. }
  450. nw = bwrite(out.fd, outp, cnt);
  451. if (nw <= 0) {
  452. if (nw == 0) {
  453. fprintf(stderr, "%s: end of device\n",
  454. out.name);
  455. exit(1);
  456. /* NOTREACHED */
  457. }
  458. if (errno != EINTR) {
  459. fprintf(stderr, "%s: write error: %s\n",
  460. out.name, strerror(errno));
  461. /* NOTREACHED */
  462. exit(1);
  463. }
  464. nw = 0;
  465. }
  466. if (pending) {
  467. st.bytes += pending;
  468. st.sparse += pending/out.dbsz;
  469. st.out_full += pending/out.dbsz;
  470. pending = 0;
  471. }
  472. outp += nw;
  473. st.bytes += nw;
  474. if (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 (nw == cnt)
  483. break;
  484. if (out.flags & ISCHR && !warned) {
  485. warned = 1;
  486. fprintf(stderr, "%s: short write on character "
  487. "device\n", out.name);
  488. }
  489. if (out.flags & ISTAPE) {
  490. fprintf(stderr,
  491. "%s: short write on tape device",
  492. out.name);
  493. exit(1);
  494. /* NOTREACHED */
  495. }
  496. }
  497. if ((out.dbcnt -= n) < out.dbsz)
  498. break;
  499. }
  500. /* Reassemble the output block. */
  501. if (out.dbcnt)
  502. (void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt);
  503. out.dbp = out.db + out.dbcnt;
  504. if (progress)
  505. (void)write(STDERR_FILENO, ".", 1);
  506. }
  507. /*
  508. * A protected against SIGINFO write
  509. */
  510. ssize_t
  511. bwrite(int fd, const void *buf, size_t len)
  512. {
  513. sigset_t oset;
  514. ssize_t rv;
  515. int oerrno;
  516. (void)sigprocmask(SIG_BLOCK, &infoset, &oset);
  517. rv = write(fd, buf, len);
  518. oerrno = errno;
  519. (void)sigprocmask(SIG_SETMASK, &oset, NULL);
  520. errno = oerrno;
  521. return (rv);
  522. }
  523. /*
  524. * Position input/output data streams before starting the copy. Device type
  525. * dependent. Seekable devices use lseek, and the rest position by reading.
  526. * Seeking past the end of file can cause null blocks to be written to the
  527. * output.
  528. */
  529. void
  530. pos_in(void)
  531. {
  532. int bcnt, cnt, nr, warned;
  533. /* If not a pipe or tape device, try to seek on it. */
  534. if (!(in.flags & (ISPIPE|ISTAPE))) {
  535. if (lseek64(in.fd,
  536. (off64_t)in.offset * (off64_t)in.dbsz, SEEK_CUR) == -1) {
  537. fprintf(stderr, "%s: seek error: %s",
  538. in.name, strerror(errno));
  539. exit(1);
  540. /* NOTREACHED */
  541. }
  542. return;
  543. /* NOTREACHED */
  544. }
  545. /*
  546. * Read the data. If a pipe, read until satisfy the number of bytes
  547. * being skipped. No differentiation for reading complete and partial
  548. * blocks for other devices.
  549. */
  550. for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) {
  551. if ((nr = read(in.fd, in.db, bcnt)) > 0) {
  552. if (in.flags & ISPIPE) {
  553. if (!(bcnt -= nr)) {
  554. bcnt = in.dbsz;
  555. --cnt;
  556. }
  557. } else
  558. --cnt;
  559. continue;
  560. }
  561. if (nr == 0) {
  562. if (files_cnt > 1) {
  563. --files_cnt;
  564. continue;
  565. }
  566. fprintf(stderr, "skip reached end of input\n");
  567. exit(1);
  568. /* NOTREACHED */
  569. }
  570. /*
  571. * Input error -- either EOF with no more files, or I/O error.
  572. * If noerror not set die. POSIX requires that the warning
  573. * message be followed by an I/O display.
  574. */
  575. if (ddflags & C_NOERROR) {
  576. if (!warned) {
  577. fprintf(stderr, "%s: error occurred\n",
  578. in.name);
  579. warned = 1;
  580. summary();
  581. }
  582. continue;
  583. }
  584. fprintf(stderr, "%s: read error: %s", in.name, strerror(errno));
  585. exit(1);
  586. /* NOTREACHED */
  587. }
  588. }
  589. void
  590. pos_out(void)
  591. {
  592. // struct mtop t_op;
  593. int cnt, n;
  594. /*
  595. * If not a tape, try seeking on the file. Seeking on a pipe is
  596. * going to fail, but don't protect the user -- they shouldn't
  597. * have specified the seek operand.
  598. */
  599. if (!(out.flags & ISTAPE)) {
  600. if (lseek64(out.fd,
  601. (off64_t)out.offset * (off64_t)out.dbsz, SEEK_SET) == -1) {
  602. fprintf(stderr, "%s: seek error: %s\n",
  603. out.name, strerror(errno));
  604. exit(1);
  605. /* NOTREACHED */
  606. }
  607. return;
  608. }
  609. /* If no read access, try using mtio. */
  610. if (out.flags & NOREAD) {
  611. /* t_op.mt_op = MTFSR;
  612. t_op.mt_count = out.offset;
  613. if (ioctl(out.fd, MTIOCTOP, &t_op) < 0)*/
  614. fprintf(stderr, "%s: cannot read", out.name);
  615. exit(1);
  616. /* NOTREACHED */
  617. return;
  618. }
  619. /* Read it. */
  620. for (cnt = 0; cnt < out.offset; ++cnt) {
  621. if ((n = read(out.fd, out.db, out.dbsz)) > 0)
  622. continue;
  623. if (n < 0) {
  624. fprintf(stderr, "%s: cannot position by reading: %s\n",
  625. out.name, strerror(errno));
  626. exit(1);
  627. /* NOTREACHED */
  628. }
  629. /*
  630. * If reach EOF, fill with NUL characters; first, back up over
  631. * the EOF mark. Note, cnt has not yet been incremented, so
  632. * the EOF read does not count as a seek'd block.
  633. */
  634. /* t_op.mt_op = MTBSR;
  635. t_op.mt_count = 1;
  636. if (ioctl(out.fd, MTIOCTOP, &t_op) == -1) */ {
  637. fprintf(stderr, "%s: cannot position\n", out.name);
  638. exit(1);
  639. /* NOTREACHED */
  640. }
  641. while (cnt++ < out.offset)
  642. if ((n = bwrite(out.fd, out.db, out.dbsz)) != out.dbsz) {
  643. fprintf(stderr, "%s: cannot position "
  644. "by writing: %s\n",
  645. out.name, strerror(errno));
  646. exit(1);
  647. /* NOTREACHED */
  648. }
  649. break;
  650. }
  651. }
  652. /*
  653. * def --
  654. * Copy input to output. Input is buffered until reaches obs, and then
  655. * output until less than obs remains. Only a single buffer is used.
  656. * Worst case buffer calculation is (ibs + obs - 1).
  657. */
  658. void
  659. def(void)
  660. {
  661. uint64_t cnt;
  662. u_char *inp;
  663. const u_char *t;
  664. if ((t = ctab) != NULL)
  665. for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
  666. *inp = t[*inp];
  667. /* Make the output buffer look right. */
  668. out.dbp = in.dbp;
  669. out.dbcnt = in.dbcnt;
  670. if (in.dbcnt >= out.dbsz) {
  671. /* If the output buffer is full, write it. */
  672. dd_out(0);
  673. /*
  674. * Ddout copies the leftover output to the beginning of
  675. * the buffer and resets the output buffer. Reset the
  676. * input buffer to match it.
  677. */
  678. in.dbp = out.dbp;
  679. in.dbcnt = out.dbcnt;
  680. }
  681. }
  682. void
  683. def_close(void)
  684. {
  685. if (ddflags & C_FDATASYNC) {
  686. fdatasync(out.fd);
  687. }
  688. /* Just update the count, everything is already in the buffer. */
  689. if (in.dbcnt)
  690. out.dbcnt = in.dbcnt;
  691. }
  692. #ifdef NO_CONV
  693. /* Build a smaller version (i.e. for a miniroot) */
  694. /* These can not be called, but just in case... */
  695. static const char no_block[] = "unblock and -DNO_CONV?\n";
  696. void block(void) { fprintf(stderr, "%s", no_block + 2); exit(1); }
  697. void block_close(void) { fprintf(stderr, "%s", no_block + 2); exit(1); }
  698. void unblock(void) { fprintf(stderr, "%s", no_block); exit(1); }
  699. void unblock_close(void) { fprintf(stderr, "%s", no_block); exit(1); }
  700. #else /* NO_CONV */
  701. /*
  702. * Copy variable length newline terminated records with a max size cbsz
  703. * bytes to output. Records less than cbs are padded with spaces.
  704. *
  705. * max in buffer: MAX(ibs, cbsz)
  706. * max out buffer: obs + cbsz
  707. */
  708. void
  709. block(void)
  710. {
  711. static int intrunc;
  712. int ch = 0; /* pacify gcc */
  713. uint64_t cnt, maxlen;
  714. u_char *inp, *outp;
  715. const u_char *t;
  716. /*
  717. * Record truncation can cross block boundaries. If currently in a
  718. * truncation state, keep tossing characters until reach a newline.
  719. * Start at the beginning of the buffer, as the input buffer is always
  720. * left empty.
  721. */
  722. if (intrunc) {
  723. for (inp = in.db, cnt = in.dbrcnt;
  724. cnt && *inp++ != '\n'; --cnt);
  725. if (!cnt) {
  726. in.dbcnt = 0;
  727. in.dbp = in.db;
  728. return;
  729. }
  730. intrunc = 0;
  731. /* Adjust the input buffer numbers. */
  732. in.dbcnt = cnt - 1;
  733. in.dbp = inp + cnt - 1;
  734. }
  735. /*
  736. * Copy records (max cbsz size chunks) into the output buffer. The
  737. * translation is done as we copy into the output buffer.
  738. */
  739. for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) {
  740. maxlen = MIN(cbsz, in.dbcnt);
  741. if ((t = ctab) != NULL)
  742. for (cnt = 0;
  743. cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
  744. *outp++ = t[ch];
  745. else
  746. for (cnt = 0;
  747. cnt < maxlen && (ch = *inp++) != '\n'; ++cnt)
  748. *outp++ = ch;
  749. /*
  750. * Check for short record without a newline. Reassemble the
  751. * input block.
  752. */
  753. if (ch != '\n' && in.dbcnt < cbsz) {
  754. (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
  755. break;
  756. }
  757. /* Adjust the input buffer numbers. */
  758. in.dbcnt -= cnt;
  759. if (ch == '\n')
  760. --in.dbcnt;
  761. /* Pad short records with spaces. */
  762. if (cnt < cbsz)
  763. (void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt);
  764. else {
  765. /*
  766. * If the next character wouldn't have ended the
  767. * block, it's a truncation.
  768. */
  769. if (!in.dbcnt || *inp != '\n')
  770. ++st.trunc;
  771. /* Toss characters to a newline. */
  772. for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt);
  773. if (!in.dbcnt)
  774. intrunc = 1;
  775. else
  776. --in.dbcnt;
  777. }
  778. /* Adjust output buffer numbers. */
  779. out.dbp += cbsz;
  780. if ((out.dbcnt += cbsz) >= out.dbsz)
  781. dd_out(0);
  782. outp = out.dbp;
  783. }
  784. in.dbp = in.db + in.dbcnt;
  785. }
  786. void
  787. block_close(void)
  788. {
  789. /*
  790. * Copy any remaining data into the output buffer and pad to a record.
  791. * Don't worry about truncation or translation, the input buffer is
  792. * always empty when truncating, and no characters have been added for
  793. * translation. The bottom line is that anything left in the input
  794. * buffer is a truncated record. Anything left in the output buffer
  795. * just wasn't big enough.
  796. */
  797. if (in.dbcnt) {
  798. ++st.trunc;
  799. (void)memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt);
  800. (void)memset(out.dbp + in.dbcnt,
  801. ctab ? ctab[' '] : ' ', cbsz - in.dbcnt);
  802. out.dbcnt += cbsz;
  803. }
  804. }
  805. /*
  806. * Convert fixed length (cbsz) records to variable length. Deletes any
  807. * trailing blanks and appends a newline.
  808. *
  809. * max in buffer: MAX(ibs, cbsz) + cbsz
  810. * max out buffer: obs + cbsz
  811. */
  812. void
  813. unblock(void)
  814. {
  815. uint64_t cnt;
  816. u_char *inp;
  817. const u_char *t;
  818. /* Translation and case conversion. */
  819. if ((t = ctab) != NULL)
  820. for (cnt = in.dbrcnt, inp = in.dbp - 1; cnt--; inp--)
  821. *inp = t[*inp];
  822. /*
  823. * Copy records (max cbsz size chunks) into the output buffer. The
  824. * translation has to already be done or we might not recognize the
  825. * spaces.
  826. */
  827. for (inp = in.db; in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) {
  828. for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t);
  829. if (t >= inp) {
  830. cnt = t - inp + 1;
  831. (void)memmove(out.dbp, inp, cnt);
  832. out.dbp += cnt;
  833. out.dbcnt += cnt;
  834. }
  835. ++out.dbcnt;
  836. *out.dbp++ = '\n';
  837. if (out.dbcnt >= out.dbsz)
  838. dd_out(0);
  839. }
  840. if (in.dbcnt)
  841. (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
  842. in.dbp = in.db + in.dbcnt;
  843. }
  844. void
  845. unblock_close(void)
  846. {
  847. uint64_t cnt;
  848. u_char *t;
  849. if (in.dbcnt) {
  850. warnx("%s: short input record", in.name);
  851. for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t);
  852. if (t >= in.db) {
  853. cnt = t - in.db + 1;
  854. (void)memmove(out.dbp, in.db, cnt);
  855. out.dbp += cnt;
  856. out.dbcnt += cnt;
  857. }
  858. ++out.dbcnt;
  859. *out.dbp++ = '\n';
  860. }
  861. }
  862. #endif /* NO_CONV */
  863. #define tv2mS(tv) ((tv).tv_sec * 1000LL + ((tv).tv_usec + 500) / 1000)
  864. void
  865. summary(void)
  866. {
  867. char buf[100];
  868. int64_t mS;
  869. struct timeval tv;
  870. if (progress)
  871. (void)write(STDERR_FILENO, "\n", 1);
  872. (void)gettimeofday(&tv, NULL);
  873. mS = tv2mS(tv) - tv2mS(st.start);
  874. if (mS == 0)
  875. mS = 1;
  876. /* Use snprintf(3) so that we don't reenter stdio(3). */
  877. (void)snprintf(buf, sizeof(buf),
  878. "%llu+%llu records in\n%llu+%llu records out\n",
  879. (unsigned long long)st.in_full, (unsigned long long)st.in_part,
  880. (unsigned long long)st.out_full, (unsigned long long)st.out_part);
  881. (void)write(STDERR_FILENO, buf, strlen(buf));
  882. if (st.swab) {
  883. (void)snprintf(buf, sizeof(buf), "%llu odd length swab %s\n",
  884. (unsigned long long)st.swab,
  885. (st.swab == 1) ? "block" : "blocks");
  886. (void)write(STDERR_FILENO, buf, strlen(buf));
  887. }
  888. if (st.trunc) {
  889. (void)snprintf(buf, sizeof(buf), "%llu truncated %s\n",
  890. (unsigned long long)st.trunc,
  891. (st.trunc == 1) ? "block" : "blocks");
  892. (void)write(STDERR_FILENO, buf, strlen(buf));
  893. }
  894. if (st.sparse) {
  895. (void)snprintf(buf, sizeof(buf), "%llu sparse output %s\n",
  896. (unsigned long long)st.sparse,
  897. (st.sparse == 1) ? "block" : "blocks");
  898. (void)write(STDERR_FILENO, buf, strlen(buf));
  899. }
  900. (void)snprintf(buf, sizeof(buf),
  901. "%llu bytes transferred in %lu.%03d secs (%llu bytes/sec)\n",
  902. (unsigned long long) st.bytes,
  903. (long) (mS / 1000),
  904. (int) (mS % 1000),
  905. (unsigned long long) (st.bytes * 1000LL / mS));
  906. (void)write(STDERR_FILENO, buf, strlen(buf));
  907. }
  908. void
  909. terminate(int notused)
  910. {
  911. exit(0);
  912. /* NOTREACHED */
  913. }
  914. static int c_arg(const void *, const void *);
  915. #ifndef NO_CONV
  916. static int c_conv(const void *, const void *);
  917. #endif
  918. static void f_bs(char *);
  919. static void f_cbs(char *);
  920. static void f_conv(char *);
  921. static void f_count(char *);
  922. static void f_files(char *);
  923. static void f_ibs(char *);
  924. static void f_if(char *);
  925. static void f_obs(char *);
  926. static void f_of(char *);
  927. static void f_seek(char *);
  928. static void f_skip(char *);
  929. static void f_progress(char *);
  930. static const struct arg {
  931. const char *name;
  932. void (*f)(char *);
  933. u_int set, noset;
  934. } args[] = {
  935. /* the array needs to be sorted by the first column so
  936. bsearch() can be used to find commands quickly */
  937. { "bs", f_bs, C_BS, C_BS|C_IBS|C_OBS|C_OSYNC },
  938. { "cbs", f_cbs, C_CBS, C_CBS },
  939. { "conv", f_conv, 0, 0 },
  940. { "count", f_count, C_COUNT, C_COUNT },
  941. { "files", f_files, C_FILES, C_FILES },
  942. { "ibs", f_ibs, C_IBS, C_BS|C_IBS },
  943. { "if", f_if, C_IF, C_IF },
  944. { "obs", f_obs, C_OBS, C_BS|C_OBS },
  945. { "of", f_of, C_OF, C_OF },
  946. { "progress", f_progress, 0, 0 },
  947. { "seek", f_seek, C_SEEK, C_SEEK },
  948. { "skip", f_skip, C_SKIP, C_SKIP },
  949. };
  950. /*
  951. * args -- parse JCL syntax of dd.
  952. */
  953. void
  954. jcl(char **argv)
  955. {
  956. struct arg *ap, tmp;
  957. char *oper, *arg;
  958. in.dbsz = out.dbsz = 512;
  959. while ((oper = *++argv) != NULL) {
  960. if ((arg = strchr(oper, '=')) == NULL) {
  961. fprintf(stderr, "unknown operand %s\n", oper);
  962. exit(1);
  963. /* NOTREACHED */
  964. }
  965. *arg++ = '\0';
  966. if (!*arg) {
  967. fprintf(stderr, "no value specified for %s\n", oper);
  968. exit(1);
  969. /* NOTREACHED */
  970. }
  971. tmp.name = oper;
  972. if (!(ap = (struct arg *)bsearch(&tmp, args,
  973. sizeof(args)/sizeof(struct arg), sizeof(struct arg),
  974. c_arg))) {
  975. fprintf(stderr, "unknown operand %s\n", tmp.name);
  976. exit(1);
  977. /* NOTREACHED */
  978. }
  979. if (ddflags & ap->noset) {
  980. fprintf(stderr,
  981. "%s: illegal argument combination or already set\n",
  982. tmp.name);
  983. exit(1);
  984. /* NOTREACHED */
  985. }
  986. ddflags |= ap->set;
  987. ap->f(arg);
  988. }
  989. /* Final sanity checks. */
  990. if (ddflags & C_BS) {
  991. /*
  992. * Bs is turned off by any conversion -- we assume the user
  993. * just wanted to set both the input and output block sizes
  994. * and didn't want the bs semantics, so we don't warn.
  995. */
  996. if (ddflags & (C_BLOCK | C_LCASE | C_SWAB | C_UCASE |
  997. C_UNBLOCK | C_OSYNC | C_ASCII | C_EBCDIC | C_SPARSE)) {
  998. ddflags &= ~C_BS;
  999. ddflags |= C_IBS|C_OBS;
  1000. }
  1001. /* Bs supersedes ibs and obs. */
  1002. if (ddflags & C_BS && ddflags & (C_IBS|C_OBS))
  1003. fprintf(stderr, "bs supersedes ibs and obs\n");
  1004. }
  1005. /*
  1006. * Ascii/ebcdic and cbs implies block/unblock.
  1007. * Block/unblock requires cbs and vice-versa.
  1008. */
  1009. if (ddflags & (C_BLOCK|C_UNBLOCK)) {
  1010. if (!(ddflags & C_CBS)) {
  1011. fprintf(stderr, "record operations require cbs\n");
  1012. exit(1);
  1013. /* NOTREACHED */
  1014. }
  1015. cfunc = ddflags & C_BLOCK ? block : unblock;
  1016. } else if (ddflags & C_CBS) {
  1017. if (ddflags & (C_ASCII|C_EBCDIC)) {
  1018. if (ddflags & C_ASCII) {
  1019. ddflags |= C_UNBLOCK;
  1020. cfunc = unblock;
  1021. } else {
  1022. ddflags |= C_BLOCK;
  1023. cfunc = block;
  1024. }
  1025. } else {
  1026. fprintf(stderr,
  1027. "cbs meaningless if not doing record operations\n");
  1028. exit(1);
  1029. /* NOTREACHED */
  1030. }
  1031. } else
  1032. cfunc = def;
  1033. /* Read, write and seek calls take off_t as arguments.
  1034. *
  1035. * The following check is not done because an off_t is a quad
  1036. * for current NetBSD implementations.
  1037. *
  1038. * if (in.offset > INT_MAX/in.dbsz || out.offset > INT_MAX/out.dbsz)
  1039. * errx(1, "seek offsets cannot be larger than %d", INT_MAX);
  1040. */
  1041. }
  1042. static int
  1043. c_arg(const void *a, const void *b)
  1044. {
  1045. return (strcmp(((const struct arg *)a)->name,
  1046. ((const struct arg *)b)->name));
  1047. }
  1048. static long long strsuftoll(const char* name, const char* arg, int def, unsigned long long max)
  1049. {
  1050. long long result;
  1051. if (sscanf(arg, "%lld", &result) == 0)
  1052. result = def;
  1053. return result;
  1054. }
  1055. static void
  1056. f_bs(char *arg)
  1057. {
  1058. in.dbsz = out.dbsz = strsuftoll("block size", arg, 1, UINT_MAX);
  1059. }
  1060. static void
  1061. f_cbs(char *arg)
  1062. {
  1063. cbsz = strsuftoll("conversion record size", arg, 1, UINT_MAX);
  1064. }
  1065. static void
  1066. f_count(char *arg)
  1067. {
  1068. cpy_cnt = strsuftoll("block count", arg, 0, LLONG_MAX);
  1069. if (!cpy_cnt)
  1070. terminate(0);
  1071. }
  1072. static void
  1073. f_files(char *arg)
  1074. {
  1075. files_cnt = (u_int)strsuftoll("file count", arg, 0, UINT_MAX);
  1076. if (!files_cnt)
  1077. terminate(0);
  1078. }
  1079. static void
  1080. f_ibs(char *arg)
  1081. {
  1082. if (!(ddflags & C_BS))
  1083. in.dbsz = strsuftoll("input block size", arg, 1, UINT_MAX);
  1084. }
  1085. static void
  1086. f_if(char *arg)
  1087. {
  1088. in.name = arg;
  1089. }
  1090. static void
  1091. f_obs(char *arg)
  1092. {
  1093. if (!(ddflags & C_BS))
  1094. out.dbsz = strsuftoll("output block size", arg, 1, UINT_MAX);
  1095. }
  1096. static void
  1097. f_of(char *arg)
  1098. {
  1099. out.name = arg;
  1100. }
  1101. static void
  1102. f_seek(char *arg)
  1103. {
  1104. out.offset = strsuftoll("seek blocks", arg, 0, LLONG_MAX);
  1105. }
  1106. static void
  1107. f_skip(char *arg)
  1108. {
  1109. in.offset = strsuftoll("skip blocks", arg, 0, LLONG_MAX);
  1110. }
  1111. static void
  1112. f_progress(char *arg)
  1113. {
  1114. if (*arg != '0')
  1115. progress = 1;
  1116. }
  1117. #ifdef NO_CONV
  1118. /* Build a small version (i.e. for a ramdisk root) */
  1119. static void
  1120. f_conv(char *arg)
  1121. {
  1122. fprintf(stderr, "conv option disabled\n");
  1123. exit(1);
  1124. /* NOTREACHED */
  1125. }
  1126. #else /* NO_CONV */
  1127. static const struct conv {
  1128. const char *name;
  1129. u_int set, noset;
  1130. const u_char *ctab;
  1131. } clist[] = {
  1132. { "block", C_BLOCK, C_UNBLOCK, NULL },
  1133. { "fdatasync", C_FDATASYNC, 0, NULL },
  1134. { "noerror", C_NOERROR, 0, NULL },
  1135. { "notrunc", C_NOTRUNC, 0, NULL },
  1136. { "osync", C_OSYNC, C_BS, NULL },
  1137. { "sparse", C_SPARSE, 0, NULL },
  1138. { "swab", C_SWAB, 0, NULL },
  1139. { "sync", C_SYNC, 0, NULL },
  1140. { "unblock", C_UNBLOCK, C_BLOCK, NULL },
  1141. /* If you add items to this table, be sure to add the
  1142. * conversions to the C_BS check in the jcl routine above.
  1143. */
  1144. };
  1145. static void
  1146. f_conv(char *arg)
  1147. {
  1148. struct conv *cp, tmp;
  1149. while (arg != NULL) {
  1150. tmp.name = strsep(&arg, ",");
  1151. if (!(cp = (struct conv *)bsearch(&tmp, clist,
  1152. sizeof(clist)/sizeof(struct conv), sizeof(struct conv),
  1153. c_conv))) {
  1154. errx(EXIT_FAILURE, "unknown conversion %s", tmp.name);
  1155. /* NOTREACHED */
  1156. }
  1157. if (ddflags & cp->noset) {
  1158. errx(EXIT_FAILURE, "%s: illegal conversion combination", tmp.name);
  1159. /* NOTREACHED */
  1160. }
  1161. ddflags |= cp->set;
  1162. if (cp->ctab)
  1163. ctab = cp->ctab;
  1164. }
  1165. }
  1166. static int
  1167. c_conv(const void *a, const void *b)
  1168. {
  1169. return (strcmp(((const struct conv *)a)->name,
  1170. ((const struct conv *)b)->name));
  1171. }
  1172. #endif /* NO_CONV */