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