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