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