1 static char *sccsid = "@(#)tar.c 4.5 (Berkeley) 81/04/02"; 2 #include <stdio.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <sys/dir.h> 6 #include <sys/mtio.h> 7 #include <signal.h> 8 9 char *sprintf(); 10 char *strcat(); 11 daddr_t bsrch(); 12 #define TBLOCK 512 13 #define NBLOCK 20 14 #define NAMSIZ 100 15 union hblock { 16 char dummy[TBLOCK]; 17 struct header { 18 char name[NAMSIZ]; 19 char mode[8]; 20 char uid[8]; 21 char gid[8]; 22 char size[12]; 23 char mtime[12]; 24 char chksum[8]; 25 char linkflag; 26 char linkname[NAMSIZ]; 27 } dbuf; 28 } dblock, tbuf[NBLOCK]; 29 30 struct linkbuf { 31 ino_t inum; 32 dev_t devnum; 33 int count; 34 char pathname[NAMSIZ]; 35 struct linkbuf *nextp; 36 } *ihead; 37 38 struct stat stbuf; 39 40 int rflag, xflag, vflag, tflag, mt, cflag, mflag, fflag, oflag, pflag; 41 int term, chksum, wflag, recno, first, linkerrok; 42 int freemem = 1; 43 int nblock = NBLOCK; 44 45 daddr_t low; 46 daddr_t high; 47 48 FILE *tfile; 49 char tname[] = "/tmp/tarXXXXXX"; 50 51 52 char *usefile; 53 char magtape[] = "/dev/rmt8"; 54 55 char *malloc(); 56 57 main(argc, argv) 58 int argc; 59 char *argv[]; 60 { 61 char *cp; 62 int onintr(), onquit(), onhup(), onterm(); 63 64 if (argc < 2) 65 usage(); 66 67 tfile = NULL; 68 usefile = magtape; 69 argv[argc] = 0; 70 argv++; 71 for (cp = *argv++; *cp; cp++) 72 switch(*cp) { 73 case 'f': 74 usefile = *argv++; 75 fflag++; 76 break; 77 case 'c': 78 cflag++; 79 rflag++; 80 break; 81 case 'o': 82 oflag++; 83 break; 84 case 'p': 85 pflag++; 86 break; 87 case 'u': 88 mktemp(tname); 89 if ((tfile = fopen(tname, "w")) == NULL) { 90 fprintf(stderr, "Tar: cannot create temporary file (%s)\n", tname); 91 done(1); 92 } 93 fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n"); 94 /* FALL THROUGH */ 95 case 'r': 96 rflag++; 97 break; 98 case 'v': 99 vflag++; 100 break; 101 case 'w': 102 wflag++; 103 break; 104 case 'x': 105 xflag++; 106 break; 107 case 't': 108 tflag++; 109 break; 110 case 'm': 111 mflag++; 112 break; 113 case '-': 114 break; 115 case '0': 116 case '1': 117 case '4': 118 case '5': 119 case '7': 120 case '8': 121 magtape[8] = *cp; 122 usefile = magtape; 123 break; 124 case 'b': 125 nblock = atoi(*argv++); 126 if (nblock > NBLOCK || nblock <= 0) { 127 fprintf(stderr, "Invalid blocksize. (Max %d)\n", NBLOCK); 128 done(1); 129 } 130 break; 131 case 'l': 132 linkerrok++; 133 break; 134 default: 135 fprintf(stderr, "tar: %c: unknown option\n", *cp); 136 usage(); 137 } 138 139 if (rflag) { 140 if (cflag && tfile != NULL) { 141 usage(); 142 done(1); 143 } 144 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 145 signal(SIGINT, onintr); 146 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 147 signal(SIGHUP, onhup); 148 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 149 signal(SIGQUIT, onquit); 150 /* 151 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 152 signal(SIGTERM, onterm); 153 */ 154 if (strcmp(usefile, "-") == 0) { 155 if (cflag == 0) { 156 fprintf(stderr, "Can only create standard output archives\n"); 157 done(1); 158 } 159 mt = dup(1); 160 nblock = 1; 161 } 162 else if ((mt = open(usefile, 2)) < 0) { 163 if (cflag == 0 || (mt = creat(usefile, 0666)) < 0) { 164 fprintf(stderr, "tar: cannot open %s\n", usefile); 165 done(1); 166 } 167 } 168 dorep(argv); 169 } 170 else if (xflag) { 171 if (strcmp(usefile, "-") == 0) { 172 mt = dup(0); 173 nblock = 1; 174 } 175 else if ((mt = open(usefile, 0)) < 0) { 176 fprintf(stderr, "tar: cannot open %s\n", usefile); 177 done(1); 178 } 179 doxtract(argv); 180 } 181 else if (tflag) { 182 if (strcmp(usefile, "-") == 0) { 183 mt = dup(0); 184 nblock = 1; 185 } 186 else if ((mt = open(usefile, 0)) < 0) { 187 fprintf(stderr, "tar: cannot open %s\n", usefile); 188 done(1); 189 } 190 dotable(); 191 } 192 else 193 usage(); 194 done(0); 195 } 196 197 usage() 198 { 199 fprintf(stderr, "tar: usage tar -{txru}[cvfblm] [tapefile] [blocksize] file1 file2...\n"); 200 done(1); 201 } 202 203 dorep(argv) 204 char *argv[]; 205 { 206 register char *cp, *cp2; 207 char wdir[60]; 208 209 if (!cflag) { 210 getdir(); 211 do { 212 passtape(); 213 if (term) 214 done(0); 215 getdir(); 216 } while (!endtape()); 217 if (tfile != NULL) { 218 char buf[200]; 219 220 sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX; mv %sX %s", 221 tname, tname, tname, tname, tname, tname); 222 fflush(tfile); 223 system(buf); 224 freopen(tname, "r", tfile); 225 fstat(fileno(tfile), &stbuf); 226 high = stbuf.st_size; 227 } 228 } 229 230 getwdir(wdir); 231 while (*argv && ! term) { 232 cp2 = *argv; 233 if (!strcmp(cp2, "-C") && argv[1]) { 234 argv++; 235 if (chdir(*argv) < 0) 236 perror(*argv); 237 else 238 getwdir(wdir); 239 argv++; 240 continue; 241 } 242 for (cp = *argv; *cp; cp++) 243 if (*cp == '/') 244 cp2 = cp; 245 if (cp2 != *argv) { 246 *cp2 = '\0'; 247 chdir(*argv); 248 *cp2 = '/'; 249 cp2++; 250 } 251 putfile(*argv++, cp2); 252 chdir(wdir); 253 } 254 putempty(); 255 putempty(); 256 flushtape(); 257 if (linkerrok == 1) 258 for (; ihead != NULL; ihead = ihead->nextp) 259 if (ihead->count != 0) 260 fprintf(stderr, "Missing links to %s\n", ihead->pathname); 261 } 262 263 endtape() 264 { 265 if (dblock.dbuf.name[0] == '\0') { 266 backtape(); 267 return(1); 268 } 269 else 270 return(0); 271 } 272 273 getdir() 274 { 275 register struct stat *sp; 276 int i; 277 278 readtape( (char *) &dblock); 279 if (dblock.dbuf.name[0] == '\0') 280 return; 281 sp = &stbuf; 282 sscanf(dblock.dbuf.mode, "%o", &i); 283 sp->st_mode = i; 284 sscanf(dblock.dbuf.uid, "%o", &i); 285 sp->st_uid = i; 286 sscanf(dblock.dbuf.gid, "%o", &i); 287 sp->st_gid = i; 288 sscanf(dblock.dbuf.size, "%lo", &sp->st_size); 289 sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime); 290 sscanf(dblock.dbuf.chksum, "%o", &chksum); 291 if (chksum != checksum()) { 292 fprintf(stderr, "directory checksum error\n"); 293 done(2); 294 } 295 if (tfile != NULL) 296 fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime); 297 } 298 299 passtape() 300 { 301 long blocks; 302 char buf[TBLOCK]; 303 304 if (dblock.dbuf.linkflag == '1') 305 return; 306 blocks = stbuf.st_size; 307 blocks += TBLOCK-1; 308 blocks /= TBLOCK; 309 310 while (blocks-- > 0) 311 readtape(buf); 312 } 313 314 putfile(longname, shortname) 315 char *longname; 316 char *shortname; 317 { 318 int infile; 319 long blocks; 320 char buf[TBLOCK]; 321 register char *cp, *cp2; 322 struct direct dbuf; 323 int i, j; 324 325 infile = open(shortname, 0); 326 if (infile < 0) { 327 fprintf(stderr, "tar: %s: cannot open file\n", longname); 328 return; 329 } 330 331 fstat(infile, &stbuf); 332 333 if (tfile != NULL && checkupdate(longname) == 0) { 334 close(infile); 335 return; 336 } 337 if (checkw('r', longname) == 0) { 338 close(infile); 339 return; 340 } 341 342 if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 343 for (i = 0, cp = buf; *cp++ = longname[i++];); 344 *--cp = '/'; 345 *++cp = 0 ; 346 i = 0; 347 if (!oflag) { 348 if( (cp - buf) >= NAMSIZ) { 349 fprintf(stderr, "%s: file name too long\n", longname); 350 close(infile); 351 return; 352 } 353 stbuf.st_size = 0; 354 tomodes(&stbuf); 355 strcpy(dblock.dbuf.name,buf); 356 sprintf(dblock.dbuf.chksum, "%6o", checksum()); 357 writetape( (char *) &dblock); 358 } 359 chdir(shortname); 360 while (read(infile, (char *)&dbuf, sizeof(dbuf)) > 0 && !term) { 361 if (dbuf.d_ino == 0) { 362 i++; 363 continue; 364 } 365 if (strcmp(".", dbuf.d_name) == 0 || strcmp("..", dbuf.d_name) == 0) { 366 i++; 367 continue; 368 } 369 cp2 = cp; 370 for (j=0; j < DIRSIZ; j++) 371 *cp2++ = dbuf.d_name[j]; 372 *cp2 = '\0'; 373 close(infile); 374 putfile(buf, cp); 375 infile = open(".", 0); 376 i++; 377 lseek(infile, (long) (sizeof(dbuf) * i), 0); 378 } 379 close(infile); 380 chdir(".."); 381 return; 382 } 383 if ((stbuf.st_mode & S_IFMT) != S_IFREG) { 384 fprintf(stderr, "tar: %s is not a file. Not dumped\n", longname); 385 return; 386 } 387 388 tomodes(&stbuf); 389 390 cp2 = longname; 391 for (cp = dblock.dbuf.name, i=0; (*cp++ = *cp2++) && i < NAMSIZ; i++); 392 if (i >= NAMSIZ) { 393 fprintf(stderr, "%s: file name too long\n", longname); 394 close(infile); 395 return; 396 } 397 398 if (stbuf.st_nlink > 1) { 399 struct linkbuf *lp; 400 int found = 0; 401 402 for (lp = ihead; lp != NULL; lp = lp->nextp) { 403 if (lp->inum == stbuf.st_ino && lp->devnum == stbuf.st_dev) { 404 found++; 405 break; 406 } 407 } 408 if (found) { 409 strcpy(dblock.dbuf.linkname, lp->pathname); 410 dblock.dbuf.linkflag = '1'; 411 sprintf(dblock.dbuf.chksum, "%6o", checksum()); 412 writetape( (char *) &dblock); 413 if (vflag) { 414 fprintf(stderr, "a %s ", longname); 415 fprintf(stderr, "link to %s\n", lp->pathname); 416 } 417 lp->count--; 418 close(infile); 419 return; 420 } 421 else { 422 lp = (struct linkbuf *) malloc(sizeof(*lp)); 423 if (lp == NULL) { 424 if (freemem) { 425 fprintf(stderr, "Out of memory. Link information lost\n"); 426 freemem = 0; 427 } 428 } 429 else { 430 lp->nextp = ihead; 431 ihead = lp; 432 lp->inum = stbuf.st_ino; 433 lp->devnum = stbuf.st_dev; 434 lp->count = stbuf.st_nlink - 1; 435 strcpy(lp->pathname, longname); 436 } 437 } 438 } 439 440 blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK; 441 if (vflag) { 442 fprintf(stderr, "a %s ", longname); 443 fprintf(stderr, "%ld blocks\n", blocks); 444 } 445 sprintf(dblock.dbuf.chksum, "%6o", checksum()); 446 writetape( (char *) &dblock); 447 448 while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) { 449 writetape(buf); 450 blocks--; 451 } 452 close(infile); 453 if (blocks != 0 || i != 0) 454 fprintf(stderr, "%s: file changed size\n", longname); 455 while (blocks-- > 0) 456 putempty(); 457 } 458 459 460 461 doxtract(argv) 462 char *argv[]; 463 { 464 long blocks, bytes; 465 char buf[TBLOCK]; 466 char **cp; 467 int ofile; 468 469 for (;;) { 470 getdir(); 471 if (endtape()) 472 break; 473 474 if (*argv == 0) 475 goto gotit; 476 477 for (cp = argv; *cp; cp++) 478 if (prefix(*cp, dblock.dbuf.name)) 479 goto gotit; 480 passtape(); 481 continue; 482 483 gotit: 484 if (checkw('x', dblock.dbuf.name) == 0) { 485 passtape(); 486 continue; 487 } 488 489 if(checkdir(dblock.dbuf.name)) 490 continue; 491 492 if (dblock.dbuf.linkflag == '1') { 493 unlink(dblock.dbuf.name); 494 if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) { 495 fprintf(stderr, "%s: cannot link\n", dblock.dbuf.name); 496 continue; 497 } 498 if (vflag) 499 fprintf(stderr, "%s linked to %s\n", 500 dblock.dbuf.name, dblock.dbuf.linkname); 501 continue; 502 } 503 if ((ofile = creat(dblock.dbuf.name, stbuf.st_mode & 07777)) < 0) { 504 fprintf(stderr, "tar: %s - cannot create\n", dblock.dbuf.name); 505 passtape(); 506 continue; 507 } 508 chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 509 510 blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK; 511 if (vflag) 512 fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n", 513 dblock.dbuf.name, bytes, blocks); 514 while (blocks-- > 0) { 515 readtape(buf); 516 if (bytes > TBLOCK) { 517 if (write(ofile, buf, TBLOCK) < 0) { 518 fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name); 519 done(2); 520 } 521 } else 522 if (write(ofile, buf, (int) bytes) < 0) { 523 fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name); 524 done(2); 525 } 526 bytes -= TBLOCK; 527 } 528 close(ofile); 529 if (mflag == 0) { 530 time_t timep[2]; 531 532 timep[0] = time(NULL); 533 timep[1] = stbuf.st_mtime; 534 utime(dblock.dbuf.name, timep); 535 } 536 if (pflag) 537 chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 538 } 539 } 540 541 dotable() 542 { 543 for (;;) { 544 getdir(); 545 if (endtape()) 546 break; 547 if (vflag) 548 longt(&stbuf); 549 printf("%s", dblock.dbuf.name); 550 if (dblock.dbuf.linkflag == '1') 551 printf(" linked to %s", dblock.dbuf.linkname); 552 printf("\n"); 553 passtape(); 554 } 555 } 556 557 putempty() 558 { 559 char buf[TBLOCK]; 560 char *cp; 561 562 for (cp = buf; cp < &buf[TBLOCK]; ) 563 *cp++ = '\0'; 564 writetape(buf); 565 } 566 567 longt(st) 568 register struct stat *st; 569 { 570 register char *cp; 571 char *ctime(); 572 573 pmode(st); 574 printf("%3d/%1d", st->st_uid, st->st_gid); 575 printf("%7D", st->st_size); 576 cp = ctime(&st->st_mtime); 577 printf(" %-12.12s %-4.4s ", cp+4, cp+20); 578 } 579 580 #define SUID 04000 581 #define SGID 02000 582 #define ROWN 0400 583 #define WOWN 0200 584 #define XOWN 0100 585 #define RGRP 040 586 #define WGRP 020 587 #define XGRP 010 588 #define ROTH 04 589 #define WOTH 02 590 #define XOTH 01 591 #define STXT 01000 592 int m1[] = { 1, ROWN, 'r', '-' }; 593 int m2[] = { 1, WOWN, 'w', '-' }; 594 int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 595 int m4[] = { 1, RGRP, 'r', '-' }; 596 int m5[] = { 1, WGRP, 'w', '-' }; 597 int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 598 int m7[] = { 1, ROTH, 'r', '-' }; 599 int m8[] = { 1, WOTH, 'w', '-' }; 600 int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 601 602 int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 603 604 pmode(st) 605 register struct stat *st; 606 { 607 register int **mp; 608 609 for (mp = &m[0]; mp < &m[9];) 610 select(*mp++, st); 611 } 612 613 select(pairp, st) 614 int *pairp; 615 struct stat *st; 616 { 617 register int n, *ap; 618 619 ap = pairp; 620 n = *ap++; 621 while (--n>=0 && (st->st_mode&*ap++)==0) 622 ap++; 623 printf("%c", *ap); 624 } 625 626 checkdir(name) 627 register char *name; 628 { 629 register char *cp; 630 int i; 631 for (cp = name; *cp; cp++) { 632 if (*cp == '/') { 633 *cp = '\0'; 634 if (access(name, 01) < 0) { 635 register int pid, rp; 636 637 if ((pid = fork()) == 0) { 638 execl("/bin/mkdir", "mkdir", name, 0); 639 execl("/usr/bin/mkdir", "mkdir", name, 0); 640 fprintf(stderr, "tar: cannot find mkdir!\n"); 641 done(0); 642 } 643 while ((rp = wait(&i)) >= 0 && rp != pid) 644 ; 645 chown(name, stbuf.st_uid, stbuf.st_gid); 646 if (pflag) 647 chmod(dblock.dbuf.name, 648 stbuf.st_mode & 0777); 649 } 650 *cp = '/'; 651 } 652 } 653 return(cp[-1]=='/'); 654 } 655 656 onintr() 657 { 658 signal(SIGINT, SIG_IGN); 659 term++; 660 } 661 662 onquit() 663 { 664 signal(SIGQUIT, SIG_IGN); 665 term++; 666 } 667 668 onhup() 669 { 670 signal(SIGHUP, SIG_IGN); 671 term++; 672 } 673 674 onterm() 675 { 676 signal(SIGTERM, SIG_IGN); 677 term++; 678 } 679 680 tomodes(sp) 681 register struct stat *sp; 682 { 683 register char *cp; 684 685 for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 686 *cp = '\0'; 687 sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); 688 sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); 689 sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); 690 sprintf(dblock.dbuf.size, "%11lo ", sp->st_size); 691 sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime); 692 } 693 694 checksum() 695 { 696 register i; 697 register char *cp; 698 699 for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++) 700 *cp = ' '; 701 i = 0; 702 for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 703 i += *cp; 704 return(i); 705 } 706 707 checkw(c, name) 708 char *name; 709 { 710 if (wflag) { 711 printf("%c ", c); 712 if (vflag) 713 longt(&stbuf); 714 printf("%s: ", name); 715 if (response() == 'y'){ 716 return(1); 717 } 718 return(0); 719 } 720 return(1); 721 } 722 723 response() 724 { 725 char c; 726 727 c = getchar(); 728 if (c != '\n') 729 while (getchar() != '\n'); 730 else c = 'n'; 731 return(c); 732 } 733 734 checkupdate(arg) 735 char *arg; 736 { 737 char name[100]; 738 long mtime; 739 daddr_t seekp; 740 daddr_t lookup(); 741 742 rewind(tfile); 743 for (;;) { 744 if ((seekp = lookup(arg)) < 0) 745 return(1); 746 fseek(tfile, seekp, 0); 747 fscanf(tfile, "%s %lo", name, &mtime); 748 if (stbuf.st_mtime > mtime) 749 return(1); 750 else 751 return(0); 752 } 753 } 754 755 done(n) 756 { 757 unlink(tname); 758 exit(n); 759 } 760 761 prefix(s1, s2) 762 register char *s1, *s2; 763 { 764 while (*s1) 765 if (*s1++ != *s2++) 766 return(0); 767 if (*s2) 768 return(*s2 == '/'); 769 return(1); 770 } 771 772 getwdir(s) 773 char *s; 774 { 775 int i; 776 int pipdes[2]; 777 778 pipe(pipdes); 779 if ((i = fork()) == 0) { 780 close(1); 781 dup(pipdes[1]); 782 execl("/bin/pwd", "pwd", 0); 783 execl("/usr/bin/pwd", "pwd", 0); 784 fprintf(stderr, "pwd failed!\n"); 785 printf("/\n"); 786 exit(1); 787 } 788 while (wait((int *)NULL) != -1) 789 ; 790 read(pipdes[0], s, 50); 791 while(*s != '\n') 792 s++; 793 *s = '\0'; 794 close(pipdes[0]); 795 close(pipdes[1]); 796 } 797 798 #define N 200 799 int njab; 800 daddr_t 801 lookup(s) 802 char *s; 803 { 804 register i; 805 daddr_t a; 806 807 for(i=0; s[i]; i++) 808 if(s[i] == ' ') 809 break; 810 a = bsrch(s, i, low, high); 811 return(a); 812 } 813 814 daddr_t 815 bsrch(s, n, l, h) 816 daddr_t l, h; 817 char *s; 818 { 819 register i, j; 820 char b[N]; 821 daddr_t m, m1; 822 823 njab = 0; 824 825 loop: 826 if(l >= h) 827 return(-1L); 828 m = l + (h-l)/2 - N/2; 829 if(m < l) 830 m = l; 831 fseek(tfile, m, 0); 832 fread(b, 1, N, tfile); 833 njab++; 834 for(i=0; i<N; i++) { 835 if(b[i] == '\n') 836 break; 837 m++; 838 } 839 if(m >= h) 840 return(-1L); 841 m1 = m; 842 j = i; 843 for(i++; i<N; i++) { 844 m1++; 845 if(b[i] == '\n') 846 break; 847 } 848 i = cmp(b+j, s, n); 849 if(i < 0) { 850 h = m; 851 goto loop; 852 } 853 if(i > 0) { 854 l = m1; 855 goto loop; 856 } 857 return(m); 858 } 859 860 cmp(b, s, n) 861 char *b, *s; 862 { 863 register i; 864 865 if(b[0] != '\n') 866 exit(2); 867 for(i=0; i<n; i++) { 868 if(b[i+1] > s[i]) 869 return(-1); 870 if(b[i+1] < s[i]) 871 return(1); 872 } 873 return(b[i+1] == ' '? 0 : -1); 874 } 875 876 readtape(buffer) 877 char *buffer; 878 { 879 register int i; 880 881 if (recno >= nblock || first == 0) { 882 if ((i = read(mt, tbuf, TBLOCK*nblock)) < 0) { 883 fprintf(stderr, "Tar: tape read error\n"); 884 done(3); 885 } 886 if (first == 0) { 887 if ((i % TBLOCK) != 0) { 888 fprintf(stderr, "Tar: tape blocksize error\n"); 889 done(3); 890 } 891 i /= TBLOCK; 892 if (i != nblock) { 893 fprintf(stderr, "Tar: blocksize = %d\n", i); 894 nblock = i; 895 } 896 } 897 recno = 0; 898 } 899 first = 1; 900 copy(buffer, &tbuf[recno++]); 901 return(TBLOCK); 902 } 903 904 writetape(buffer) 905 char *buffer; 906 { 907 first = 1; 908 if (recno >= nblock) { 909 if (write(mt, tbuf, TBLOCK*nblock) < 0) { 910 fprintf(stderr, "Tar: tape write error\n"); 911 done(2); 912 } 913 recno = 0; 914 } 915 copy(&tbuf[recno++], buffer); 916 if (recno >= nblock) { 917 if (write(mt, tbuf, TBLOCK*nblock) < 0) { 918 fprintf(stderr, "Tar: tape write error\n"); 919 done(2); 920 } 921 recno = 0; 922 } 923 return(TBLOCK); 924 } 925 926 backtape() 927 { 928 static int mtdev = 1; 929 static struct mtop mtop = {MTBSR, 1}; 930 struct mtget mtget; 931 932 if (mtdev == 1) 933 mtdev = ioctl(mt, MTIOCGET, &mtget); 934 if (mtdev == 0) { 935 if (ioctl(mt, MTIOCTOP, &mtop) < 0) { 936 fprintf(stderr, "Tar: tape backspace error\n"); 937 done(4); 938 } 939 } else 940 lseek(mt, (long) -TBLOCK*nblock, 1); 941 recno--; 942 } 943 944 flushtape() 945 { 946 write(mt, tbuf, TBLOCK*nblock); 947 } 948 949 copy(to, from) 950 register char *to, *from; 951 { 952 register i; 953 954 i = TBLOCK; 955 do { 956 *to++ = *from++; 957 } while (--i); 958 } 959