dd.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  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. }
  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("errors");
  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(nil);
  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. /* don't perror dregs of previous errors on a short write */
  290. werrstr("");
  291. c = write(obf, obuf, obc);
  292. if(c != obc) {
  293. if(c > 0)
  294. ++nopr;
  295. perror("write");
  296. term("errors");
  297. }
  298. if(obc == obs)
  299. nofr++;
  300. else
  301. nopr++;
  302. obc = 0;
  303. }
  304. }
  305. int
  306. match(char *s)
  307. {
  308. char *cs;
  309. cs = string;
  310. while(*cs++ == *s)
  311. if(*s++ == '\0')
  312. goto true;
  313. if(*s != '\0')
  314. return 0;
  315. true:
  316. cs--;
  317. string = cs;
  318. return 1;
  319. }
  320. vlong
  321. number(long big)
  322. {
  323. char *cs;
  324. vlong n;
  325. cs = string;
  326. n = 0;
  327. while(*cs >= '0' && *cs <= '9')
  328. n = n*10 + *cs++ - '0';
  329. for(;;)
  330. switch(*cs++) {
  331. case 'k':
  332. n *= 1024;
  333. continue;
  334. /* case 'w':
  335. n *= sizeof(int);
  336. continue;
  337. */
  338. case 'b':
  339. n *= 512;
  340. continue;
  341. /* case '*':*/
  342. case 'x':
  343. string = cs;
  344. n *= number(BIG);
  345. case '\0':
  346. if(n>=big || n<0) {
  347. fprint(2, "dd: argument %lld out of range\n", n);
  348. exits("range");
  349. }
  350. return n;
  351. }
  352. /* never gets here */
  353. }
  354. void
  355. cnull(int cc)
  356. {
  357. int c;
  358. c = cc;
  359. if((cflag&UCASE) && c>='a' && c<='z')
  360. c += 'A'-'a';
  361. if((cflag&LCASE) && c>='A' && c<='Z')
  362. c += 'a'-'A';
  363. null(c);
  364. }
  365. void
  366. null(int c)
  367. {
  368. *op = c;
  369. op++;
  370. if(++obc >= obs) {
  371. flsh();
  372. op = obuf;
  373. }
  374. }
  375. void
  376. ascii(int cc)
  377. {
  378. int c;
  379. c = etoa[cc];
  380. if(cbs == 0) {
  381. cnull(c);
  382. return;
  383. }
  384. if(c == ' ') {
  385. nspace++;
  386. goto out;
  387. }
  388. while(nspace > 0) {
  389. null(' ');
  390. nspace--;
  391. }
  392. cnull(c);
  393. out:
  394. if(++cbc >= cbs) {
  395. null('\n');
  396. cbc = 0;
  397. nspace = 0;
  398. }
  399. }
  400. void
  401. unblock(int cc)
  402. {
  403. int c;
  404. c = cc & 0377;
  405. if(cbs == 0) {
  406. cnull(c);
  407. return;
  408. }
  409. if(c == ' ') {
  410. nspace++;
  411. goto out;
  412. }
  413. while(nspace > 0) {
  414. null(' ');
  415. nspace--;
  416. }
  417. cnull(c);
  418. out:
  419. if(++cbc >= cbs) {
  420. null('\n');
  421. cbc = 0;
  422. nspace = 0;
  423. }
  424. }
  425. void
  426. ebcdic(int cc)
  427. {
  428. int c;
  429. c = cc;
  430. if(cflag&UCASE && c>='a' && c<='z')
  431. c += 'A'-'a';
  432. if(cflag&LCASE && c>='A' && c<='Z')
  433. c += 'a'-'A';
  434. c = atoe[c];
  435. if(cbs == 0) {
  436. null(c);
  437. return;
  438. }
  439. if(cc == '\n') {
  440. while(cbc < cbs) {
  441. null(atoe[' ']);
  442. cbc++;
  443. }
  444. cbc = 0;
  445. return;
  446. }
  447. if(cbc == cbs)
  448. ntrunc++;
  449. cbc++;
  450. if(cbc <= cbs)
  451. null(c);
  452. }
  453. void
  454. ibm(int cc)
  455. {
  456. int c;
  457. c = cc;
  458. if(cflag&UCASE && c>='a' && c<='z')
  459. c += 'A'-'a';
  460. if(cflag&LCASE && c>='A' && c<='Z')
  461. c += 'a'-'A';
  462. c = atoibm[c] & 0377;
  463. if(cbs == 0) {
  464. null(c);
  465. return;
  466. }
  467. if(cc == '\n') {
  468. while(cbc < cbs) {
  469. null(atoibm[' ']);
  470. cbc++;
  471. }
  472. cbc = 0;
  473. return;
  474. }
  475. if(cbc == cbs)
  476. ntrunc++;
  477. cbc++;
  478. if(cbc <= cbs)
  479. null(c);
  480. }
  481. void
  482. block(int cc)
  483. {
  484. int c;
  485. c = cc;
  486. if(cflag&UCASE && c>='a' && c<='z')
  487. c += 'A'-'a';
  488. if(cflag&LCASE && c>='A' && c<='Z')
  489. c += 'a'-'A';
  490. c &= 0377;
  491. if(cbs == 0) {
  492. null(c);
  493. return;
  494. }
  495. if(cc == '\n') {
  496. while(cbc < cbs) {
  497. null(' ');
  498. cbc++;
  499. }
  500. cbc = 0;
  501. return;
  502. }
  503. if(cbc == cbs)
  504. ntrunc++;
  505. cbc++;
  506. if(cbc <= cbs)
  507. null(c);
  508. }
  509. void
  510. term(char *status)
  511. {
  512. stats();
  513. exits(status);
  514. }
  515. void
  516. stats(void)
  517. {
  518. if(quiet)
  519. return;
  520. fprint(2, "%lud+%lud records in\n", nifr, nipr);
  521. fprint(2, "%lud+%lud records out\n", nofr, nopr);
  522. if(ntrunc)
  523. fprint(2, "%lud truncated records\n", ntrunc);
  524. }
  525. uchar etoa[] =
  526. {
  527. 0000,0001,0002,0003,0234,0011,0206,0177,
  528. 0227,0215,0216,0013,0014,0015,0016,0017,
  529. 0020,0021,0022,0023,0235,0205,0010,0207,
  530. 0030,0031,0222,0217,0034,0035,0036,0037,
  531. 0200,0201,0202,0203,0204,0012,0027,0033,
  532. 0210,0211,0212,0213,0214,0005,0006,0007,
  533. 0220,0221,0026,0223,0224,0225,0226,0004,
  534. 0230,0231,0232,0233,0024,0025,0236,0032,
  535. 0040,0240,0241,0242,0243,0244,0245,0246,
  536. 0247,0250,0133,0056,0074,0050,0053,0041,
  537. 0046,0251,0252,0253,0254,0255,0256,0257,
  538. 0260,0261,0135,0044,0052,0051,0073,0136,
  539. 0055,0057,0262,0263,0264,0265,0266,0267,
  540. 0270,0271,0174,0054,0045,0137,0076,0077,
  541. 0272,0273,0274,0275,0276,0277,0300,0301,
  542. 0302,0140,0072,0043,0100,0047,0075,0042,
  543. 0303,0141,0142,0143,0144,0145,0146,0147,
  544. 0150,0151,0304,0305,0306,0307,0310,0311,
  545. 0312,0152,0153,0154,0155,0156,0157,0160,
  546. 0161,0162,0313,0314,0315,0316,0317,0320,
  547. 0321,0176,0163,0164,0165,0166,0167,0170,
  548. 0171,0172,0322,0323,0324,0325,0326,0327,
  549. 0330,0331,0332,0333,0334,0335,0336,0337,
  550. 0340,0341,0342,0343,0344,0345,0346,0347,
  551. 0173,0101,0102,0103,0104,0105,0106,0107,
  552. 0110,0111,0350,0351,0352,0353,0354,0355,
  553. 0175,0112,0113,0114,0115,0116,0117,0120,
  554. 0121,0122,0356,0357,0360,0361,0362,0363,
  555. 0134,0237,0123,0124,0125,0126,0127,0130,
  556. 0131,0132,0364,0365,0366,0367,0370,0371,
  557. 0060,0061,0062,0063,0064,0065,0066,0067,
  558. 0070,0071,0372,0373,0374,0375,0376,0377,
  559. };
  560. uchar atoe[] =
  561. {
  562. 0000,0001,0002,0003,0067,0055,0056,0057,
  563. 0026,0005,0045,0013,0014,0015,0016,0017,
  564. 0020,0021,0022,0023,0074,0075,0062,0046,
  565. 0030,0031,0077,0047,0034,0035,0036,0037,
  566. 0100,0117,0177,0173,0133,0154,0120,0175,
  567. 0115,0135,0134,0116,0153,0140,0113,0141,
  568. 0360,0361,0362,0363,0364,0365,0366,0367,
  569. 0370,0371,0172,0136,0114,0176,0156,0157,
  570. 0174,0301,0302,0303,0304,0305,0306,0307,
  571. 0310,0311,0321,0322,0323,0324,0325,0326,
  572. 0327,0330,0331,0342,0343,0344,0345,0346,
  573. 0347,0350,0351,0112,0340,0132,0137,0155,
  574. 0171,0201,0202,0203,0204,0205,0206,0207,
  575. 0210,0211,0221,0222,0223,0224,0225,0226,
  576. 0227,0230,0231,0242,0243,0244,0245,0246,
  577. 0247,0250,0251,0300,0152,0320,0241,0007,
  578. 0040,0041,0042,0043,0044,0025,0006,0027,
  579. 0050,0051,0052,0053,0054,0011,0012,0033,
  580. 0060,0061,0032,0063,0064,0065,0066,0010,
  581. 0070,0071,0072,0073,0004,0024,0076,0341,
  582. 0101,0102,0103,0104,0105,0106,0107,0110,
  583. 0111,0121,0122,0123,0124,0125,0126,0127,
  584. 0130,0131,0142,0143,0144,0145,0146,0147,
  585. 0150,0151,0160,0161,0162,0163,0164,0165,
  586. 0166,0167,0170,0200,0212,0213,0214,0215,
  587. 0216,0217,0220,0232,0233,0234,0235,0236,
  588. 0237,0240,0252,0253,0254,0255,0256,0257,
  589. 0260,0261,0262,0263,0264,0265,0266,0267,
  590. 0270,0271,0272,0273,0274,0275,0276,0277,
  591. 0312,0313,0314,0315,0316,0317,0332,0333,
  592. 0334,0335,0336,0337,0352,0353,0354,0355,
  593. 0356,0357,0372,0373,0374,0375,0376,0377,
  594. };
  595. uchar atoibm[] =
  596. {
  597. 0000,0001,0002,0003,0067,0055,0056,0057,
  598. 0026,0005,0045,0013,0014,0015,0016,0017,
  599. 0020,0021,0022,0023,0074,0075,0062,0046,
  600. 0030,0031,0077,0047,0034,0035,0036,0037,
  601. 0100,0132,0177,0173,0133,0154,0120,0175,
  602. 0115,0135,0134,0116,0153,0140,0113,0141,
  603. 0360,0361,0362,0363,0364,0365,0366,0367,
  604. 0370,0371,0172,0136,0114,0176,0156,0157,
  605. 0174,0301,0302,0303,0304,0305,0306,0307,
  606. 0310,0311,0321,0322,0323,0324,0325,0326,
  607. 0327,0330,0331,0342,0343,0344,0345,0346,
  608. 0347,0350,0351,0255,0340,0275,0137,0155,
  609. 0171,0201,0202,0203,0204,0205,0206,0207,
  610. 0210,0211,0221,0222,0223,0224,0225,0226,
  611. 0227,0230,0231,0242,0243,0244,0245,0246,
  612. 0247,0250,0251,0300,0117,0320,0241,0007,
  613. 0040,0041,0042,0043,0044,0025,0006,0027,
  614. 0050,0051,0052,0053,0054,0011,0012,0033,
  615. 0060,0061,0032,0063,0064,0065,0066,0010,
  616. 0070,0071,0072,0073,0004,0024,0076,0341,
  617. 0101,0102,0103,0104,0105,0106,0107,0110,
  618. 0111,0121,0122,0123,0124,0125,0126,0127,
  619. 0130,0131,0142,0143,0144,0145,0146,0147,
  620. 0150,0151,0160,0161,0162,0163,0164,0165,
  621. 0166,0167,0170,0200,0212,0213,0214,0215,
  622. 0216,0217,0220,0232,0233,0234,0235,0236,
  623. 0237,0240,0252,0253,0254,0255,0256,0257,
  624. 0260,0261,0262,0263,0264,0265,0266,0267,
  625. 0270,0271,0272,0273,0274,0275,0276,0277,
  626. 0312,0313,0314,0315,0316,0317,0332,0333,
  627. 0334,0335,0336,0337,0352,0353,0354,0355,
  628. 0356,0357,0372,0373,0374,0375,0376,0377,
  629. };