dd.c 12 KB

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