dd.c 11 KB

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