dd.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #define BIG ((1UL<<31)-1)
  12. #define VBIG ((1ULL<<63)-1)
  13. #define LCASE (1<<0)
  14. #define UCASE (1<<1)
  15. #define SWAB (1<<2)
  16. #define NERR (1<<3)
  17. #define SYNC (1<<4)
  18. int cflag;
  19. int fflag;
  20. char *string;
  21. char *ifile;
  22. char *ofile;
  23. char *ibuf;
  24. char *obuf;
  25. int64_t skip;
  26. int64_t oseekn;
  27. int64_t iseekn;
  28. int64_t oseekb;
  29. int64_t iseekb;
  30. int64_t count;
  31. int32_t files = 1;
  32. int32_t ibs = 512;
  33. int32_t obs = 512;
  34. int32_t bs;
  35. int32_t cbs;
  36. int32_t ibc;
  37. int32_t obc;
  38. int32_t cbc;
  39. int32_t nifr;
  40. int32_t nipr;
  41. int32_t nofr;
  42. int32_t nopr;
  43. int32_t ntrunc;
  44. int dotrunc = 1;
  45. int ibf;
  46. int obf;
  47. char *op;
  48. int nspace;
  49. uint8_t etoa[256];
  50. uint8_t atoe[256];
  51. uint8_t atoibm[256];
  52. int quiet;
  53. void flsh(void);
  54. int match(char *s);
  55. int64_t number(int64_t big);
  56. void cnull(int cc);
  57. void null(int c);
  58. void ascii(int cc);
  59. void unblock(int cc);
  60. void ebcdic(int cc);
  61. void ibm(int cc);
  62. void block(int cc);
  63. void term(char*);
  64. void stats(void);
  65. #define iskey(s) ((key[0] == '-') && (strcmp(key+1, s) == 0))
  66. int
  67. main(int argc, char *argv[])
  68. {
  69. void (*conv)(int);
  70. char *ip;
  71. char *key;
  72. int a, c;
  73. conv = null;
  74. for(c=1; c<argc; c++) {
  75. key = argv[c++];
  76. if(c >= argc){
  77. fprint(2, "dd: arg %s needs a value\n", key);
  78. exits("arg");
  79. }
  80. string = argv[c];
  81. if(iskey("ibs")) {
  82. ibs = number(BIG);
  83. continue;
  84. }
  85. if(iskey("obs")) {
  86. obs = number(BIG);
  87. continue;
  88. }
  89. if(iskey("cbs")) {
  90. cbs = number(BIG);
  91. continue;
  92. }
  93. if(iskey("bs")) {
  94. bs = number(BIG);
  95. continue;
  96. }
  97. if(iskey("if")) {
  98. ifile = string;
  99. continue;
  100. }
  101. if(iskey("of")) {
  102. ofile = string;
  103. continue;
  104. }
  105. if(iskey("trunc")) {
  106. dotrunc = number(BIG);
  107. continue;
  108. }
  109. if(iskey("quiet")) {
  110. quiet = number(BIG);
  111. continue;
  112. }
  113. if(iskey("skip")) {
  114. skip = number(VBIG);
  115. continue;
  116. }
  117. if(iskey("seek") || iskey("oseek")) {
  118. oseekn = number(VBIG);
  119. continue;
  120. }
  121. if(iskey("iseek")) {
  122. iseekn = number(VBIG);
  123. continue;
  124. }
  125. if(iskey("iseekb")) {
  126. iseekb = number(VBIG);
  127. continue;
  128. }
  129. if(iskey("oseekb")) {
  130. oseekb = number(VBIG);
  131. continue;
  132. }
  133. if(iskey("count")) {
  134. count = number(VBIG);
  135. continue;
  136. }
  137. if(iskey("files")) {
  138. files = number(BIG);
  139. continue;
  140. }
  141. if(iskey("conv")) {
  142. cloop:
  143. if(match(","))
  144. goto cloop;
  145. if(*string == '\0')
  146. continue;
  147. if(match("ebcdic")) {
  148. conv = ebcdic;
  149. goto cloop;
  150. }
  151. if(match("ibm")) {
  152. conv = ibm;
  153. goto cloop;
  154. }
  155. if(match("ascii")) {
  156. conv = ascii;
  157. goto cloop;
  158. }
  159. if(match("block")) {
  160. conv = block;
  161. goto cloop;
  162. }
  163. if(match("unblock")) {
  164. conv = unblock;
  165. goto cloop;
  166. }
  167. if(match("lcase")) {
  168. cflag |= LCASE;
  169. goto cloop;
  170. }
  171. if(match("ucase")) {
  172. cflag |= UCASE;
  173. goto cloop;
  174. }
  175. if(match("swab")) {
  176. cflag |= SWAB;
  177. goto cloop;
  178. }
  179. if(match("noerror")) {
  180. cflag |= NERR;
  181. goto cloop;
  182. }
  183. if(match("sync")) {
  184. cflag |= SYNC;
  185. goto cloop;
  186. }
  187. fprint(2, "dd: bad conv %s\n", argv[c]);
  188. exits("arg");
  189. }
  190. fprint(2, "dd: bad arg: %s\n", key);
  191. exits("arg");
  192. }
  193. if(conv == null && cflag&(LCASE|UCASE))
  194. conv = cnull;
  195. if(ifile)
  196. ibf = open(ifile, 0);
  197. else
  198. ibf = dup(0, -1);
  199. if(ibf < 0) {
  200. fprint(2, "dd: open %s: %r\n", ifile);
  201. exits("open");
  202. }
  203. if(ofile){
  204. if(dotrunc)
  205. obf = create(ofile, 1, 0664);
  206. else
  207. obf = open(ofile, 1);
  208. if(obf < 0) {
  209. fprint(2, "dd: create %s: %r\n", ofile);
  210. exits("create");
  211. }
  212. }else{
  213. obf = dup(1, -1);
  214. if(obf < 0) {
  215. fprint(2, "dd: can't dup file descriptor: %s: %r\n", ofile);
  216. exits("dup");
  217. }
  218. }
  219. if(bs)
  220. ibs = obs = bs;
  221. if(ibs == obs && conv == null)
  222. fflag++;
  223. if(ibs == 0 || obs == 0) {
  224. fprint(2, "dd: counts: cannot be zero\n");
  225. exits("counts");
  226. }
  227. ibuf = sbrk(ibs);
  228. if(fflag)
  229. obuf = ibuf;
  230. else
  231. obuf = sbrk(obs);
  232. sbrk(64); /* For good measure */
  233. if(ibuf == (char *)-1 || obuf == (char *)-1) {
  234. fprint(2, "dd: not enough memory: %r\n");
  235. exits("memory");
  236. }
  237. ibc = 0;
  238. obc = 0;
  239. cbc = 0;
  240. op = obuf;
  241. /*
  242. if(signal(SIGINT, SIG_IGN) != SIG_IGN)
  243. signal(SIGINT, term);
  244. */
  245. seek(obf, obs*oseekn, 1);
  246. seek(ibf, ibs*iseekn, 1);
  247. if(iseekb)
  248. seek(ibf, iseekb, 0);
  249. if(oseekb)
  250. seek(obf, oseekb, 0);
  251. while(skip) {
  252. read(ibf, ibuf, ibs);
  253. skip--;
  254. }
  255. ip = 0;
  256. loop:
  257. if(ibc-- == 0) {
  258. ibc = 0;
  259. if(count==0 || nifr+nipr!=count) {
  260. if(cflag&(NERR|SYNC))
  261. for(ip=ibuf+ibs; ip>ibuf;)
  262. *--ip = 0;
  263. ibc = read(ibf, ibuf, ibs);
  264. }
  265. if(ibc == -1) {
  266. perror("read");
  267. if((cflag&NERR) == 0) {
  268. flsh();
  269. term("errors");
  270. }
  271. ibc = 0;
  272. for(c=0; c<ibs; c++)
  273. if(ibuf[c] != 0)
  274. ibc = c+1;
  275. seek(ibf, ibs, 1);
  276. stats();
  277. }else if(ibc == 0 && --files<=0) {
  278. flsh();
  279. term(nil);
  280. }
  281. if(ibc != ibs) {
  282. nipr++;
  283. if(cflag&SYNC)
  284. ibc = ibs;
  285. } else
  286. nifr++;
  287. ip = ibuf;
  288. c = (ibc>>1) & ~1;
  289. if(cflag&SWAB && c)
  290. do {
  291. a = *ip++;
  292. ip[-1] = *ip;
  293. *ip++ = a;
  294. } while(--c);
  295. ip = ibuf;
  296. if(fflag) {
  297. obc = ibc;
  298. flsh();
  299. ibc = 0;
  300. }
  301. goto loop;
  302. }
  303. c = 0;
  304. c |= *ip++;
  305. c &= 0377;
  306. (*conv)(c);
  307. goto loop;
  308. }
  309. void
  310. flsh(void)
  311. {
  312. int c;
  313. if(obc) {
  314. /* don't perror dregs of previous errors on a short write */
  315. werrstr("");
  316. c = write(obf, obuf, obc);
  317. if(c != obc) {
  318. if(c > 0)
  319. ++nopr;
  320. perror("write");
  321. term("errors");
  322. }
  323. if(obc == obs)
  324. nofr++;
  325. else
  326. nopr++;
  327. obc = 0;
  328. }
  329. }
  330. int
  331. match(char *s)
  332. {
  333. char *cs;
  334. cs = string;
  335. while(*cs++ == *s)
  336. if(*s++ == '\0')
  337. goto true;
  338. if(*s != '\0')
  339. return 0;
  340. true:
  341. cs--;
  342. string = cs;
  343. return 1;
  344. }
  345. int64_t
  346. number(int64_t big)
  347. {
  348. char *cs;
  349. uint64_t n;
  350. cs = string;
  351. n = 0;
  352. while(*cs >= '0' && *cs <= '9')
  353. n = n*10 + *cs++ - '0';
  354. for(;;)
  355. switch(*cs++) {
  356. case 'k':
  357. n *= 1024;
  358. continue;
  359. case 'b':
  360. n *= 512;
  361. continue;
  362. /* case '*':*/
  363. case 'x':
  364. string = cs;
  365. n *= number(VBIG);
  366. case '\0':
  367. if(n > big) {
  368. fprint(2, "dd: argument %llu out of range\n", n);
  369. exits("range");
  370. }
  371. return n;
  372. }
  373. /* never gets here */
  374. }
  375. void
  376. cnull(int cc)
  377. {
  378. int c;
  379. c = cc;
  380. if((cflag&UCASE) && c>='a' && c<='z')
  381. c += 'A'-'a';
  382. if((cflag&LCASE) && c>='A' && c<='Z')
  383. c += 'a'-'A';
  384. null(c);
  385. }
  386. void
  387. null(int c)
  388. {
  389. *op = c;
  390. op++;
  391. if(++obc >= obs) {
  392. flsh();
  393. op = obuf;
  394. }
  395. }
  396. void
  397. ascii(int cc)
  398. {
  399. int c;
  400. c = etoa[cc];
  401. if(cbs == 0) {
  402. cnull(c);
  403. return;
  404. }
  405. if(c == ' ') {
  406. nspace++;
  407. goto out;
  408. }
  409. while(nspace > 0) {
  410. null(' ');
  411. nspace--;
  412. }
  413. cnull(c);
  414. out:
  415. if(++cbc >= cbs) {
  416. null('\n');
  417. cbc = 0;
  418. nspace = 0;
  419. }
  420. }
  421. void
  422. unblock(int cc)
  423. {
  424. int c;
  425. c = cc & 0377;
  426. if(cbs == 0) {
  427. cnull(c);
  428. return;
  429. }
  430. if(c == ' ') {
  431. nspace++;
  432. goto out;
  433. }
  434. while(nspace > 0) {
  435. null(' ');
  436. nspace--;
  437. }
  438. cnull(c);
  439. out:
  440. if(++cbc >= cbs) {
  441. null('\n');
  442. cbc = 0;
  443. nspace = 0;
  444. }
  445. }
  446. void
  447. ebcdic(int cc)
  448. {
  449. int c;
  450. c = cc;
  451. if(cflag&UCASE && c>='a' && c<='z')
  452. c += 'A'-'a';
  453. if(cflag&LCASE && c>='A' && c<='Z')
  454. c += 'a'-'A';
  455. c = atoe[c];
  456. if(cbs == 0) {
  457. null(c);
  458. return;
  459. }
  460. if(cc == '\n') {
  461. while(cbc < cbs) {
  462. null(atoe[' ']);
  463. cbc++;
  464. }
  465. cbc = 0;
  466. return;
  467. }
  468. if(cbc == cbs)
  469. ntrunc++;
  470. cbc++;
  471. if(cbc <= cbs)
  472. null(c);
  473. }
  474. void
  475. ibm(int cc)
  476. {
  477. int c;
  478. c = cc;
  479. if(cflag&UCASE && c>='a' && c<='z')
  480. c += 'A'-'a';
  481. if(cflag&LCASE && c>='A' && c<='Z')
  482. c += 'a'-'A';
  483. c = atoibm[c] & 0377;
  484. if(cbs == 0) {
  485. null(c);
  486. return;
  487. }
  488. if(cc == '\n') {
  489. while(cbc < cbs) {
  490. null(atoibm[' ']);
  491. cbc++;
  492. }
  493. cbc = 0;
  494. return;
  495. }
  496. if(cbc == cbs)
  497. ntrunc++;
  498. cbc++;
  499. if(cbc <= cbs)
  500. null(c);
  501. }
  502. void
  503. block(int cc)
  504. {
  505. int c;
  506. c = cc;
  507. if(cflag&UCASE && c>='a' && c<='z')
  508. c += 'A'-'a';
  509. if(cflag&LCASE && c>='A' && c<='Z')
  510. c += 'a'-'A';
  511. c &= 0377;
  512. if(cbs == 0) {
  513. null(c);
  514. return;
  515. }
  516. if(cc == '\n') {
  517. while(cbc < cbs) {
  518. null(' ');
  519. cbc++;
  520. }
  521. cbc = 0;
  522. return;
  523. }
  524. if(cbc == cbs)
  525. ntrunc++;
  526. cbc++;
  527. if(cbc <= cbs)
  528. null(c);
  529. }
  530. void
  531. term(char *status)
  532. {
  533. stats();
  534. exits(status);
  535. }
  536. void
  537. stats(void)
  538. {
  539. if(quiet)
  540. return;
  541. fprint(2, "%lu+%lu records in\n", nifr, nipr);
  542. fprint(2, "%lu+%lu records out\n", nofr, nopr);
  543. if(ntrunc)
  544. fprint(2, "%lu truncated records\n", ntrunc);
  545. }
  546. uint8_t etoa[] =
  547. {
  548. 0000,0001,0002,0003,0234,0011,0206,0177,
  549. 0227,0215,0216,0013,0014,0015,0016,0017,
  550. 0020,0021,0022,0023,0235,0205,0010,0207,
  551. 0030,0031,0222,0217,0034,0035,0036,0037,
  552. 0200,0201,0202,0203,0204,0012,0027,0033,
  553. 0210,0211,0212,0213,0214,0005,0006,0007,
  554. 0220,0221,0026,0223,0224,0225,0226,0004,
  555. 0230,0231,0232,0233,0024,0025,0236,0032,
  556. 0040,0240,0241,0242,0243,0244,0245,0246,
  557. 0247,0250,0133,0056,0074,0050,0053,0041,
  558. 0046,0251,0252,0253,0254,0255,0256,0257,
  559. 0260,0261,0135,0044,0052,0051,0073,0136,
  560. 0055,0057,0262,0263,0264,0265,0266,0267,
  561. 0270,0271,0174,0054,0045,0137,0076,0077,
  562. 0272,0273,0274,0275,0276,0277,0300,0301,
  563. 0302,0140,0072,0043,0100,0047,0075,0042,
  564. 0303,0141,0142,0143,0144,0145,0146,0147,
  565. 0150,0151,0304,0305,0306,0307,0310,0311,
  566. 0312,0152,0153,0154,0155,0156,0157,0160,
  567. 0161,0162,0313,0314,0315,0316,0317,0320,
  568. 0321,0176,0163,0164,0165,0166,0167,0170,
  569. 0171,0172,0322,0323,0324,0325,0326,0327,
  570. 0330,0331,0332,0333,0334,0335,0336,0337,
  571. 0340,0341,0342,0343,0344,0345,0346,0347,
  572. 0173,0101,0102,0103,0104,0105,0106,0107,
  573. 0110,0111,0350,0351,0352,0353,0354,0355,
  574. 0175,0112,0113,0114,0115,0116,0117,0120,
  575. 0121,0122,0356,0357,0360,0361,0362,0363,
  576. 0134,0237,0123,0124,0125,0126,0127,0130,
  577. 0131,0132,0364,0365,0366,0367,0370,0371,
  578. 0060,0061,0062,0063,0064,0065,0066,0067,
  579. 0070,0071,0372,0373,0374,0375,0376,0377,
  580. };
  581. uint8_t atoe[] =
  582. {
  583. 0000,0001,0002,0003,0067,0055,0056,0057,
  584. 0026,0005,0045,0013,0014,0015,0016,0017,
  585. 0020,0021,0022,0023,0074,0075,0062,0046,
  586. 0030,0031,0077,0047,0034,0035,0036,0037,
  587. 0100,0117,0177,0173,0133,0154,0120,0175,
  588. 0115,0135,0134,0116,0153,0140,0113,0141,
  589. 0360,0361,0362,0363,0364,0365,0366,0367,
  590. 0370,0371,0172,0136,0114,0176,0156,0157,
  591. 0174,0301,0302,0303,0304,0305,0306,0307,
  592. 0310,0311,0321,0322,0323,0324,0325,0326,
  593. 0327,0330,0331,0342,0343,0344,0345,0346,
  594. 0347,0350,0351,0112,0340,0132,0137,0155,
  595. 0171,0201,0202,0203,0204,0205,0206,0207,
  596. 0210,0211,0221,0222,0223,0224,0225,0226,
  597. 0227,0230,0231,0242,0243,0244,0245,0246,
  598. 0247,0250,0251,0300,0152,0320,0241,0007,
  599. 0040,0041,0042,0043,0044,0025,0006,0027,
  600. 0050,0051,0052,0053,0054,0011,0012,0033,
  601. 0060,0061,0032,0063,0064,0065,0066,0010,
  602. 0070,0071,0072,0073,0004,0024,0076,0341,
  603. 0101,0102,0103,0104,0105,0106,0107,0110,
  604. 0111,0121,0122,0123,0124,0125,0126,0127,
  605. 0130,0131,0142,0143,0144,0145,0146,0147,
  606. 0150,0151,0160,0161,0162,0163,0164,0165,
  607. 0166,0167,0170,0200,0212,0213,0214,0215,
  608. 0216,0217,0220,0232,0233,0234,0235,0236,
  609. 0237,0240,0252,0253,0254,0255,0256,0257,
  610. 0260,0261,0262,0263,0264,0265,0266,0267,
  611. 0270,0271,0272,0273,0274,0275,0276,0277,
  612. 0312,0313,0314,0315,0316,0317,0332,0333,
  613. 0334,0335,0336,0337,0352,0353,0354,0355,
  614. 0356,0357,0372,0373,0374,0375,0376,0377,
  615. };
  616. uint8_t atoibm[] =
  617. {
  618. 0000,0001,0002,0003,0067,0055,0056,0057,
  619. 0026,0005,0045,0013,0014,0015,0016,0017,
  620. 0020,0021,0022,0023,0074,0075,0062,0046,
  621. 0030,0031,0077,0047,0034,0035,0036,0037,
  622. 0100,0132,0177,0173,0133,0154,0120,0175,
  623. 0115,0135,0134,0116,0153,0140,0113,0141,
  624. 0360,0361,0362,0363,0364,0365,0366,0367,
  625. 0370,0371,0172,0136,0114,0176,0156,0157,
  626. 0174,0301,0302,0303,0304,0305,0306,0307,
  627. 0310,0311,0321,0322,0323,0324,0325,0326,
  628. 0327,0330,0331,0342,0343,0344,0345,0346,
  629. 0347,0350,0351,0255,0340,0275,0137,0155,
  630. 0171,0201,0202,0203,0204,0205,0206,0207,
  631. 0210,0211,0221,0222,0223,0224,0225,0226,
  632. 0227,0230,0231,0242,0243,0244,0245,0246,
  633. 0247,0250,0251,0300,0117,0320,0241,0007,
  634. 0040,0041,0042,0043,0044,0025,0006,0027,
  635. 0050,0051,0052,0053,0054,0011,0012,0033,
  636. 0060,0061,0032,0063,0064,0065,0066,0010,
  637. 0070,0071,0072,0073,0004,0024,0076,0341,
  638. 0101,0102,0103,0104,0105,0106,0107,0110,
  639. 0111,0121,0122,0123,0124,0125,0126,0127,
  640. 0130,0131,0142,0143,0144,0145,0146,0147,
  641. 0150,0151,0160,0161,0162,0163,0164,0165,
  642. 0166,0167,0170,0200,0212,0213,0214,0215,
  643. 0216,0217,0220,0232,0233,0234,0235,0236,
  644. 0237,0240,0252,0253,0254,0255,0256,0257,
  645. 0260,0261,0262,0263,0264,0265,0266,0267,
  646. 0270,0271,0272,0273,0274,0275,0276,0277,
  647. 0312,0313,0314,0315,0316,0317,0332,0333,
  648. 0334,0335,0336,0337,0352,0353,0354,0355,
  649. 0356,0357,0372,0373,0374,0375,0376,0377,
  650. };