dd.c (11559B)
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 43 void flsh(void); 44 int match(char *s); 45 vlong number(long big); 46 void cnull(int cc); 47 void null(int c); 48 void ascii(int cc); 49 void unblock(int cc); 50 void ebcdic(int cc); 51 void ibm(int cc); 52 void block(int cc); 53 void term(void); 54 void stats(void); 55 56 #define iskey(s) ((key[0] == '-') && (strcmp(key+1, s) == 0)) 57 58 void 59 main(int argc, char *argv[]) 60 { 61 void (*conv)(int); 62 char *ip; 63 char *key; 64 int a, c; 65 66 conv = null; 67 for(c=1; c<argc; c++) { 68 key = argv[c++]; 69 if(c >= argc){ 70 fprint(2, "dd: arg %s needs a value\n", key); 71 exits("arg"); 72 } 73 string = argv[c]; 74 if(iskey("ibs")) { 75 ibs = number(BIG); 76 continue; 77 } 78 if(iskey("obs")) { 79 obs = number(BIG); 80 continue; 81 } 82 if(iskey("cbs")) { 83 cbs = number(BIG); 84 continue; 85 } 86 if(iskey("bs")) { 87 bs = number(BIG); 88 continue; 89 } 90 if(iskey("if")) { 91 ifile = string; 92 continue; 93 } 94 if(iskey("of")) { 95 ofile = string; 96 continue; 97 } 98 if(iskey("trunc")) { 99 dotrunc = 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 = malloc(ibs); 207 if(fflag) 208 obuf = ibuf; 209 else 210 obuf = malloc(obs); 211 if(ibuf == NULL || obuf == NULL) { 212 fprint(2, "dd: not enough memory: %r\n"); 213 exits("memory"); 214 } 215 ibc = 0; 216 obc = 0; 217 cbc = 0; 218 op = obuf; 219 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 231 ip = 0; 232 loop: 233 if(ibc-- == 0) { 234 ibc = 0; 235 if(count==0 || nifr+nipr!=count) { 236 if(cflag&(NERR|SYNC)) 237 for(ip=ibuf+ibs; ip>ibuf;) 238 *--ip = 0; 239 ibc = read(ibf, ibuf, ibs); 240 } 241 if(ibc == -1) { 242 perror("read"); 243 if((cflag&NERR) == 0) { 244 flsh(); 245 term(); 246 } 247 ibc = 0; 248 for(c=0; c<ibs; c++) 249 if(ibuf[c] != 0) 250 ibc = c; 251 stats(); 252 } 253 if(ibc == 0 && --files<=0) { 254 flsh(); 255 term(); 256 } 257 if(ibc != ibs) { 258 nipr++; 259 if(cflag&SYNC) 260 ibc = ibs; 261 } else 262 nifr++; 263 ip = ibuf; 264 c = (ibc>>1) & ~1; 265 if(cflag&SWAB && c) 266 do { 267 a = *ip++; 268 ip[-1] = *ip; 269 *ip++ = a; 270 } while(--c); 271 ip = ibuf; 272 if(fflag) { 273 obc = ibc; 274 flsh(); 275 ibc = 0; 276 } 277 goto loop; 278 } 279 c = 0; 280 c |= *ip++; 281 c &= 0377; 282 (*conv)(c); 283 goto loop; 284 } 285 286 void 287 flsh(void) 288 { 289 int c; 290 291 if(obc) { 292 c = write(obf, obuf, obc); 293 if(c != obc) { 294 if(c > 0) 295 ++nopr; 296 perror("write"); 297 term(); 298 } 299 if(obc == obs) 300 nofr++; 301 else 302 nopr++; 303 obc = 0; 304 } 305 } 306 307 int 308 match(char *s) 309 { 310 char *cs; 311 312 cs = string; 313 while(*cs++ == *s) 314 if(*s++ == '\0') 315 goto true; 316 if(*s != '\0') 317 return 0; 318 319 true: 320 cs--; 321 string = cs; 322 return 1; 323 } 324 325 vlong 326 number(long big) 327 { 328 char *cs; 329 vlong n; 330 331 cs = string; 332 n = 0; 333 while(*cs >= '0' && *cs <= '9') 334 n = n*10 + *cs++ - '0'; 335 for(;;) 336 switch(*cs++) { 337 338 case 'k': 339 n *= 1024; 340 continue; 341 342 /* case 'w': 343 n *= sizeof(int); 344 continue; 345 */ 346 347 case 'b': 348 n *= 512; 349 continue; 350 351 /* case '*':*/ 352 case 'x': 353 string = cs; 354 n *= number(BIG); 355 356 case '\0': 357 if(n>=big || n<0) { 358 fprint(2, "dd: argument %lld out of range\n", n); 359 exits("range"); 360 } 361 return n; 362 } 363 /* never gets here */ 364 } 365 366 void 367 cnull(int cc) 368 { 369 int c; 370 371 c = cc; 372 if((cflag&UCASE) && c>='a' && c<='z') 373 c += 'A'-'a'; 374 if((cflag&LCASE) && c>='A' && c<='Z') 375 c += 'a'-'A'; 376 null(c); 377 } 378 379 void 380 null(int c) 381 { 382 383 *op = c; 384 op++; 385 if(++obc >= obs) { 386 flsh(); 387 op = obuf; 388 } 389 } 390 391 void 392 ascii(int cc) 393 { 394 int c; 395 396 c = etoa[cc]; 397 if(cbs == 0) { 398 cnull(c); 399 return; 400 } 401 if(c == ' ') { 402 nspace++; 403 goto out; 404 } 405 while(nspace > 0) { 406 null(' '); 407 nspace--; 408 } 409 cnull(c); 410 411 out: 412 if(++cbc >= cbs) { 413 null('\n'); 414 cbc = 0; 415 nspace = 0; 416 } 417 } 418 419 void 420 unblock(int cc) 421 { 422 int c; 423 424 c = cc & 0377; 425 if(cbs == 0) { 426 cnull(c); 427 return; 428 } 429 if(c == ' ') { 430 nspace++; 431 goto out; 432 } 433 while(nspace > 0) { 434 null(' '); 435 nspace--; 436 } 437 cnull(c); 438 439 out: 440 if(++cbc >= cbs) { 441 null('\n'); 442 cbc = 0; 443 nspace = 0; 444 } 445 } 446 447 void 448 ebcdic(int cc) 449 { 450 int c; 451 452 c = cc; 453 if(cflag&UCASE && c>='a' && c<='z') 454 c += 'A'-'a'; 455 if(cflag&LCASE && c>='A' && c<='Z') 456 c += 'a'-'A'; 457 c = atoe[c]; 458 if(cbs == 0) { 459 null(c); 460 return; 461 } 462 if(cc == '\n') { 463 while(cbc < cbs) { 464 null(atoe[' ']); 465 cbc++; 466 } 467 cbc = 0; 468 return; 469 } 470 if(cbc == cbs) 471 ntrunc++; 472 cbc++; 473 if(cbc <= cbs) 474 null(c); 475 } 476 477 void 478 ibm(int cc) 479 { 480 int c; 481 482 c = cc; 483 if(cflag&UCASE && c>='a' && c<='z') 484 c += 'A'-'a'; 485 if(cflag&LCASE && c>='A' && c<='Z') 486 c += 'a'-'A'; 487 c = atoibm[c] & 0377; 488 if(cbs == 0) { 489 null(c); 490 return; 491 } 492 if(cc == '\n') { 493 while(cbc < cbs) { 494 null(atoibm[' ']); 495 cbc++; 496 } 497 cbc = 0; 498 return; 499 } 500 if(cbc == cbs) 501 ntrunc++; 502 cbc++; 503 if(cbc <= cbs) 504 null(c); 505 } 506 507 void 508 block(int cc) 509 { 510 int c; 511 512 c = cc; 513 if(cflag&UCASE && c>='a' && c<='z') 514 c += 'A'-'a'; 515 if(cflag&LCASE && c>='A' && c<='Z') 516 c += 'a'-'A'; 517 c &= 0377; 518 if(cbs == 0) { 519 null(c); 520 return; 521 } 522 if(cc == '\n') { 523 while(cbc < cbs) { 524 null(' '); 525 cbc++; 526 } 527 cbc = 0; 528 return; 529 } 530 if(cbc == cbs) 531 ntrunc++; 532 cbc++; 533 if(cbc <= cbs) 534 null(c); 535 } 536 537 void 538 term(void) 539 { 540 541 stats(); 542 exits(0); 543 } 544 545 void 546 stats(void) 547 { 548 549 fprint(2, "%lud+%lud records in\n", nifr, nipr); 550 fprint(2, "%lud+%lud records out\n", nofr, nopr); 551 if(ntrunc) 552 fprint(2, "%lud truncated records\n", ntrunc); 553 } 554 555 uchar etoa[] = 556 { 557 0000,0001,0002,0003,0234,0011,0206,0177, 558 0227,0215,0216,0013,0014,0015,0016,0017, 559 0020,0021,0022,0023,0235,0205,0010,0207, 560 0030,0031,0222,0217,0034,0035,0036,0037, 561 0200,0201,0202,0203,0204,0012,0027,0033, 562 0210,0211,0212,0213,0214,0005,0006,0007, 563 0220,0221,0026,0223,0224,0225,0226,0004, 564 0230,0231,0232,0233,0024,0025,0236,0032, 565 0040,0240,0241,0242,0243,0244,0245,0246, 566 0247,0250,0133,0056,0074,0050,0053,0041, 567 0046,0251,0252,0253,0254,0255,0256,0257, 568 0260,0261,0135,0044,0052,0051,0073,0136, 569 0055,0057,0262,0263,0264,0265,0266,0267, 570 0270,0271,0174,0054,0045,0137,0076,0077, 571 0272,0273,0274,0275,0276,0277,0300,0301, 572 0302,0140,0072,0043,0100,0047,0075,0042, 573 0303,0141,0142,0143,0144,0145,0146,0147, 574 0150,0151,0304,0305,0306,0307,0310,0311, 575 0312,0152,0153,0154,0155,0156,0157,0160, 576 0161,0162,0313,0314,0315,0316,0317,0320, 577 0321,0176,0163,0164,0165,0166,0167,0170, 578 0171,0172,0322,0323,0324,0325,0326,0327, 579 0330,0331,0332,0333,0334,0335,0336,0337, 580 0340,0341,0342,0343,0344,0345,0346,0347, 581 0173,0101,0102,0103,0104,0105,0106,0107, 582 0110,0111,0350,0351,0352,0353,0354,0355, 583 0175,0112,0113,0114,0115,0116,0117,0120, 584 0121,0122,0356,0357,0360,0361,0362,0363, 585 0134,0237,0123,0124,0125,0126,0127,0130, 586 0131,0132,0364,0365,0366,0367,0370,0371, 587 0060,0061,0062,0063,0064,0065,0066,0067, 588 0070,0071,0372,0373,0374,0375,0376,0377, 589 }; 590 uchar atoe[] = 591 { 592 0000,0001,0002,0003,0067,0055,0056,0057, 593 0026,0005,0045,0013,0014,0015,0016,0017, 594 0020,0021,0022,0023,0074,0075,0062,0046, 595 0030,0031,0077,0047,0034,0035,0036,0037, 596 0100,0117,0177,0173,0133,0154,0120,0175, 597 0115,0135,0134,0116,0153,0140,0113,0141, 598 0360,0361,0362,0363,0364,0365,0366,0367, 599 0370,0371,0172,0136,0114,0176,0156,0157, 600 0174,0301,0302,0303,0304,0305,0306,0307, 601 0310,0311,0321,0322,0323,0324,0325,0326, 602 0327,0330,0331,0342,0343,0344,0345,0346, 603 0347,0350,0351,0112,0340,0132,0137,0155, 604 0171,0201,0202,0203,0204,0205,0206,0207, 605 0210,0211,0221,0222,0223,0224,0225,0226, 606 0227,0230,0231,0242,0243,0244,0245,0246, 607 0247,0250,0251,0300,0152,0320,0241,0007, 608 0040,0041,0042,0043,0044,0025,0006,0027, 609 0050,0051,0052,0053,0054,0011,0012,0033, 610 0060,0061,0032,0063,0064,0065,0066,0010, 611 0070,0071,0072,0073,0004,0024,0076,0341, 612 0101,0102,0103,0104,0105,0106,0107,0110, 613 0111,0121,0122,0123,0124,0125,0126,0127, 614 0130,0131,0142,0143,0144,0145,0146,0147, 615 0150,0151,0160,0161,0162,0163,0164,0165, 616 0166,0167,0170,0200,0212,0213,0214,0215, 617 0216,0217,0220,0232,0233,0234,0235,0236, 618 0237,0240,0252,0253,0254,0255,0256,0257, 619 0260,0261,0262,0263,0264,0265,0266,0267, 620 0270,0271,0272,0273,0274,0275,0276,0277, 621 0312,0313,0314,0315,0316,0317,0332,0333, 622 0334,0335,0336,0337,0352,0353,0354,0355, 623 0356,0357,0372,0373,0374,0375,0376,0377, 624 }; 625 uchar atoibm[] = 626 { 627 0000,0001,0002,0003,0067,0055,0056,0057, 628 0026,0005,0045,0013,0014,0015,0016,0017, 629 0020,0021,0022,0023,0074,0075,0062,0046, 630 0030,0031,0077,0047,0034,0035,0036,0037, 631 0100,0132,0177,0173,0133,0154,0120,0175, 632 0115,0135,0134,0116,0153,0140,0113,0141, 633 0360,0361,0362,0363,0364,0365,0366,0367, 634 0370,0371,0172,0136,0114,0176,0156,0157, 635 0174,0301,0302,0303,0304,0305,0306,0307, 636 0310,0311,0321,0322,0323,0324,0325,0326, 637 0327,0330,0331,0342,0343,0344,0345,0346, 638 0347,0350,0351,0255,0340,0275,0137,0155, 639 0171,0201,0202,0203,0204,0205,0206,0207, 640 0210,0211,0221,0222,0223,0224,0225,0226, 641 0227,0230,0231,0242,0243,0244,0245,0246, 642 0247,0250,0251,0300,0117,0320,0241,0007, 643 0040,0041,0042,0043,0044,0025,0006,0027, 644 0050,0051,0052,0053,0054,0011,0012,0033, 645 0060,0061,0032,0063,0064,0065,0066,0010, 646 0070,0071,0072,0073,0004,0024,0076,0341, 647 0101,0102,0103,0104,0105,0106,0107,0110, 648 0111,0121,0122,0123,0124,0125,0126,0127, 649 0130,0131,0142,0143,0144,0145,0146,0147, 650 0150,0151,0160,0161,0162,0163,0164,0165, 651 0166,0167,0170,0200,0212,0213,0214,0215, 652 0216,0217,0220,0232,0233,0234,0235,0236, 653 0237,0240,0252,0253,0254,0255,0256,0257, 654 0260,0261,0262,0263,0264,0265,0266,0267, 655 0270,0271,0272,0273,0274,0275,0276,0277, 656 0312,0313,0314,0315,0316,0317,0332,0333, 657 0334,0335,0336,0337,0352,0353,0354,0355, 658 0356,0357,0372,0373,0374,0375,0376,0377, 659 };