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