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