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