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