dd.c 12 KB

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