dd.c 11 KB

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