1 static char *sccsid = "@(#)tar.c 4.1 (Berkeley) 10/01/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 522 blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK; 523 if (vflag) 524 fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n", dblock.dbuf.name, bytes, blocks); 525 while (blocks-- > 0) { 526 readtape(buf); 527 if (bytes > TBLOCK) { 528 if (write(ofile, buf, TBLOCK) < 0) { 529 fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name); 530 done(2); 531 } 532 } else 533 if (write(ofile, buf, (int) bytes) < 0) { 534 fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name); 535 done(2); 536 } 537 bytes -= TBLOCK; 538 } 539 close(ofile); 540 if (mflag == 0) { 541 time_t timep[2]; 542 543 timep[0] = time(NULL); 544 timep[1] = stbuf.st_mtime; 545 utime(dblock.dbuf.name, timep); 546 } 547 if(pflag) { 548 chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 549 chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 550 } 551 } 552 } 553 554 dotable() 555 { 556 for (;;) { 557 getdir(); 558 if (endtape()) 559 break; 560 if (vflag) 561 longt(&stbuf); 562 printf("%s", dblock.dbuf.name); 563 if (dblock.dbuf.linkflag == '1') 564 printf(" linked to %s", dblock.dbuf.linkname); 565 printf("\n"); 566 passtape(); 567 } 568 } 569 570 putempty() 571 { 572 char buf[TBLOCK]; 573 char *cp; 574 575 for (cp = buf; cp < &buf[TBLOCK]; ) 576 *cp++ = '\0'; 577 writetape(buf); 578 } 579 580 longt(st) 581 register struct stat *st; 582 { 583 register char *cp; 584 char *ctime(); 585 586 pmode(st); 587 printf("%3d/%1d", st->st_uid, st->st_gid); 588 printf("%7D", st->st_size); 589 cp = ctime(&st->st_mtime); 590 printf(" %-12.12s %-4.4s ", cp+4, cp+20); 591 } 592 593 #define SUID 04000 594 #define SGID 02000 595 #define ROWN 0400 596 #define WOWN 0200 597 #define XOWN 0100 598 #define RGRP 040 599 #define WGRP 020 600 #define XGRP 010 601 #define ROTH 04 602 #define WOTH 02 603 #define XOTH 01 604 #define STXT 01000 605 int m1[] = { 1, ROWN, 'r', '-' }; 606 int m2[] = { 1, WOWN, 'w', '-' }; 607 int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 608 int m4[] = { 1, RGRP, 'r', '-' }; 609 int m5[] = { 1, WGRP, 'w', '-' }; 610 int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 611 int m7[] = { 1, ROTH, 'r', '-' }; 612 int m8[] = { 1, WOTH, 'w', '-' }; 613 int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 614 615 int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 616 617 pmode(st) 618 register struct stat *st; 619 { 620 register int **mp; 621 622 for (mp = &m[0]; mp < &m[9];) 623 select(*mp++, st); 624 } 625 626 select(pairp, st) 627 int *pairp; 628 struct stat *st; 629 { 630 register int n, *ap; 631 632 ap = pairp; 633 n = *ap++; 634 while (--n>=0 && (st->st_mode&*ap++)==0) 635 ap++; 636 printf("%c", *ap); 637 } 638 639 checkdir(name) 640 register char *name; 641 { 642 register char *cp; 643 int i; 644 for (cp = name; *cp; cp++) { 645 if (*cp == '/') { 646 *cp = '\0'; 647 if (access(name, 01) < 0) { 648 register int pid, rp; 649 650 if ((pid = fork()) == 0) { 651 execl("/bin/mkdir", "mkdir", name, 0); 652 execl("/usr/bin/mkdir", "mkdir", name, 0); 653 fprintf(stderr, "tar: cannot find mkdir!\n"); 654 done(0); 655 } 656 while ((rp = wait(&i)) >= 0 && rp != pid) 657 ; 658 if(pflag) { 659 chown(name, stbuf.st_uid, stbuf.st_gid); 660 chmod(dblock.dbuf.name, stbuf.st_mode & 0777); 661 } 662 } 663 *cp = '/'; 664 } 665 } 666 return(cp[-1]=='/'); 667 } 668 669 onintr() 670 { 671 signal(SIGINT, SIG_IGN); 672 term++; 673 } 674 675 onquit() 676 { 677 signal(SIGQUIT, SIG_IGN); 678 term++; 679 } 680 681 onhup() 682 { 683 signal(SIGHUP, SIG_IGN); 684 term++; 685 } 686 687 onterm() 688 { 689 signal(SIGTERM, SIG_IGN); 690 term++; 691 } 692 693 tomodes(sp) 694 register struct stat *sp; 695 { 696 register char *cp; 697 698 for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 699 *cp = '\0'; 700 sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); 701 sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); 702 sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); 703 sprintf(dblock.dbuf.size, "%11lo ", sp->st_size); 704 sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime); 705 } 706 707 checksum() 708 { 709 register i; 710 register char *cp; 711 712 for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++) 713 *cp = ' '; 714 i = 0; 715 for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 716 i += *cp; 717 return(i); 718 } 719 720 checkw(c, name) 721 char *name; 722 { 723 if (wflag) { 724 printf("%c ", c); 725 if (vflag) 726 longt(&stbuf); 727 printf("%s: ", name); 728 if (response() == 'y'){ 729 return(1); 730 } 731 return(0); 732 } 733 return(1); 734 } 735 736 response() 737 { 738 char c; 739 740 c = getchar(); 741 if (c != '\n') 742 while (getchar() != '\n'); 743 else c = 'n'; 744 return(c); 745 } 746 747 checkupdate(arg) 748 char *arg; 749 { 750 char name[100]; 751 long mtime; 752 daddr_t seekp; 753 daddr_t lookup(); 754 755 rewind(tfile); 756 for (;;) { 757 if ((seekp = lookup(arg)) < 0) 758 return(1); 759 fseek(tfile, seekp, 0); 760 fscanf(tfile, "%s %lo", name, &mtime); 761 if (stbuf.st_mtime > mtime) 762 return(1); 763 else 764 return(0); 765 } 766 } 767 768 done(n) 769 { 770 unlink(tname); 771 exit(n); 772 } 773 774 prefix(s1, s2) 775 register char *s1, *s2; 776 { 777 while (*s1) 778 if (*s1++ != *s2++) 779 return(0); 780 if (*s2) 781 return(*s2 == '/'); 782 return(1); 783 } 784 785 getwdir(s) 786 char *s; 787 { 788 int i; 789 int pipdes[2]; 790 791 pipe(pipdes); 792 if ((i = fork()) == 0) { 793 close(1); 794 dup(pipdes[1]); 795 execl("/bin/pwd", "pwd", 0); 796 execl("/usr/bin/pwd", "pwd", 0); 797 fprintf(stderr, "pwd failed!\n"); 798 printf("/\n"); 799 exit(1); 800 } 801 while (wait((int *)NULL) != -1) 802 ; 803 read(pipdes[0], s, 50); 804 while(*s != '\n') 805 s++; 806 *s = '\0'; 807 close(pipdes[0]); 808 close(pipdes[1]); 809 } 810 811 #define N 200 812 int njab; 813 daddr_t 814 lookup(s) 815 char *s; 816 { 817 register i; 818 daddr_t a; 819 820 for(i=0; s[i]; i++) 821 if(s[i] == ' ') 822 break; 823 a = bsrch(s, i, low, high); 824 return(a); 825 } 826 827 daddr_t 828 bsrch(s, n, l, h) 829 daddr_t l, h; 830 char *s; 831 { 832 register i, j; 833 char b[N]; 834 daddr_t m, m1; 835 836 njab = 0; 837 838 loop: 839 if(l >= h) 840 return(-1L); 841 m = l + (h-l)/2 - N/2; 842 if(m < l) 843 m = l; 844 fseek(tfile, m, 0); 845 fread(b, 1, N, tfile); 846 njab++; 847 for(i=0; i<N; i++) { 848 if(b[i] == '\n') 849 break; 850 m++; 851 } 852 if(m >= h) 853 return(-1L); 854 m1 = m; 855 j = i; 856 for(i++; i<N; i++) { 857 m1++; 858 if(b[i] == '\n') 859 break; 860 } 861 i = cmp(b+j, s, n); 862 if(i < 0) { 863 h = m; 864 goto loop; 865 } 866 if(i > 0) { 867 l = m1; 868 goto loop; 869 } 870 return(m); 871 } 872 873 cmp(b, s, n) 874 char *b, *s; 875 { 876 register i; 877 878 if(b[0] != '\n') 879 exit(2); 880 for(i=0; i<n; i++) { 881 if(b[i+1] > s[i]) 882 return(-1); 883 if(b[i+1] < s[i]) 884 return(1); 885 } 886 return(b[i+1] == ' '? 0 : -1); 887 } 888 889 readtape(buffer) 890 char *buffer; 891 { 892 int i, j; 893 894 if (recno >= nblock || first == 0) { 895 if (first == 0 && nblock == 0) 896 j = fflag ? NBLOCK : 1; /* orignally, NBLOCK; */ 897 else 898 j = nblock; 899 if ((i = read(mt, tbuf, TBLOCK*j)) < 0) { 900 fprintf(stderr, "Tar: tape read error\n"); 901 done(3); 902 } 903 if (first == 0) { 904 if ((i % TBLOCK) != 0) { 905 fprintf(stderr, "Tar: tape blocksize error\n"); 906 done(3); 907 } 908 i /= TBLOCK; 909 if (rflag && i != 1) { 910 fprintf(stderr, "Tar: Cannot update blocked tapes (yet)\n"); 911 done(4); 912 } 913 if (i != nblock && (i != 1 || nblock == 0)) { 914 fprintf(stderr, "Tar: blocksize = %d\n", i); 915 nblock = i; 916 } 917 } 918 recno = 0; 919 } 920 first = 1; 921 copy(buffer, &tbuf[recno++]); 922 return(TBLOCK); 923 } 924 925 writetape(buffer) 926 char *buffer; 927 { 928 first = 1; 929 if (nblock == 0) 930 nblock = 1; 931 if (recno >= nblock) { 932 if (write(mt, tbuf, TBLOCK*nblock) < 0) { 933 fprintf(stderr, "Tar: tape write error\n"); 934 done(2); 935 } 936 recno = 0; 937 } 938 copy(&tbuf[recno++], buffer); 939 if (recno >= nblock) { 940 if (write(mt, tbuf, TBLOCK*nblock) < 0) { 941 fprintf(stderr, "Tar: tape write error\n"); 942 done(2); 943 } 944 recno = 0; 945 } 946 return(TBLOCK); 947 } 948 949 backtape() 950 { 951 lseek(mt, (long) -TBLOCK, 1); 952 if (recno >= nblock) { 953 recno = nblock - 1; 954 if (read(mt, tbuf, TBLOCK*nblock) < 0) { 955 fprintf(stderr, "Tar: tape read error after seek\n"); 956 done(4); 957 } 958 lseek(mt, (long) -TBLOCK, 1); 959 } 960 } 961 962 flushtape() 963 { 964 write(mt, tbuf, TBLOCK*nblock); 965 } 966 967 copy(to, from) 968 register char *to, *from; 969 { 970 register i; 971 972 i = TBLOCK; 973 do { 974 *to++ = *from++; 975 } while (--i); 976 } 977