1: #include <stdio.h>
   2: #include <sys/types.h>
   3: #include <sys/stat.h>
   4: #include <sys/dir.h>
   5: #include <signal.h>
   6: 
   7: /* If you don't have the new magtape ioctl's, define OLDMAGTAPE */
   8: /* #define OLDMAGTAPE */
   9: #ifndef OLDMAGTAPE
  10: #include <sys/mtio.h>
  11: #endif
  12: 
  13: #define YES 1
  14: #define NO  0
  15: #define min(a,b) (((a) < (b))? (a): (b))
  16: 
  17: off_t   lseek();
  18: time_t  time();
  19: char    *mktemp();
  20: char    *sprintf();
  21: char    *strcpy();
  22: char    *strcat();
  23: daddr_t bsrch();
  24: #define TBLOCK      512
  25: 
  26: #define NBLOCK      20  /* maximum tape blocking */
  27: #define BLOCKDFLT   20  /* default tape blocking */
  28: #define PIPEBLOCK   8   /* default pipe blocking; 4K */
  29: #define FILEBLOCK   2   /* default blocking for disk archives */
  30: 
  31: #define NAMSIZ  100
  32: union hblock {
  33:     char dummy[TBLOCK];
  34:     struct header {
  35:         char name[NAMSIZ];
  36:         char mode[8];
  37:         char uid[8];
  38:         char gid[8];
  39:         char size[12];
  40:         char mtime[12];
  41:         char chksum[8];
  42:         char linkflag;
  43:         char linkname[NAMSIZ];
  44:     } dbuf;
  45: } dblock, tbuf[NBLOCK];
  46: 
  47: struct linkbuf {
  48:     ino_t   inum;
  49:     dev_t   devnum;
  50:     int count;
  51:     char    pathname[NAMSIZ];
  52:     struct  linkbuf *nextp;
  53: } *ihead;
  54: 
  55: struct stat stbuf;
  56: 
  57: int work;       /* one of: */
  58: #define TABLE   1
  59: #define COMPARE 2
  60: #define EXTRACT 3
  61: #define REPLACE 4
  62: 
  63: char    lnflag;         /* -X  link from linkdir if identical */
  64: char   *linkdir;        /* link from this directory if identical */
  65: int     vflag, mt, cflag, mflag, fflag, oflag, pflag, hflag;
  66: int term, chksum, wflag, recno, first, linkerrok;
  67: int freemem = 1;
  68: int nblock = 0;
  69: FILE    *vfile = stdout;
  70: 
  71: daddr_t low;
  72: daddr_t high;
  73: 
  74: FILE    *tfile;
  75: char    tname[] = "/tmp/tarXXXXXX";
  76: 
  77: 
  78: char    *usefile;
  79: char    magtape[]   = "/dev/rmt1";
  80: int writing = 0;
  81: 
  82: char    *malloc();
  83: 
  84: main(argc, argv)
  85: int argc;
  86: char    *argv[];
  87: {
  88:     char *cp;
  89:     int onintr(), onquit(), onhup(), onterm();
  90: 
  91:     if (argc < 2)
  92:         usage();
  93: 
  94:     tfile = NULL;
  95:     usefile =  magtape;
  96:     argv[argc] = 0;
  97:     argv++;
  98:     for (cp = *argv++; *cp; cp++)
  99:         switch(*cp) {
 100:         case 'f':
 101:             usefile = *argv++;
 102:             fflag++;
 103:             break;
 104:         case 'c':
 105:             cflag++;
 106:             work = REPLACE;
 107:             break;
 108:         case 'o':
 109:             oflag++;
 110:             break;
 111:         case 'p':
 112:             pflag++;
 113:             break;
 114:         case 'u':
 115:             mktemp(tname);
 116:             if ((tfile = fopen(tname, "w")) == NULL) {
 117:                 fprintf(stderr, "tar: cannot create temporary file (%s)\n", tname);
 118:                 done(1);
 119:             }
 120:             fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n");
 121:             /* FALL THROUGH */
 122:         case 'r':
 123:             work = REPLACE;
 124:             break;
 125:         case 'v':
 126:             vflag++;
 127:             break;
 128:         case 'w':
 129:             wflag++;
 130:             break;
 131:         case 'C':
 132:             work = COMPARE;
 133:             break;
 134:         case 'X':
 135:             linkdir = *argv++;
 136:             lnflag++;
 137:             work = EXTRACT;
 138:             break;
 139:         case 'x':
 140:             work = EXTRACT;
 141:             break;
 142:         case 't':
 143:             work = TABLE;
 144:             break;
 145:         case 'm':
 146:             mflag++;
 147:             break;
 148: #ifdef  UCB_SYMLINKS
 149:         case 'h':
 150:             hflag++;
 151:             break;
 152: #endif
 153:         case '-':
 154:             break;
 155:         case '0':
 156:         case '1':
 157:         case '2':
 158:         case '3':
 159:         case '4':
 160:         case '5':
 161:         case '7':
 162:             magtape[8] = *cp;
 163:             usefile = magtape;
 164:             break;
 165:         case 'b':
 166:             nblock = atoi(*argv++);
 167:             if (nblock > NBLOCK || nblock <= 0) {
 168:                 fprintf(stderr, "tar: invalid blocksize (max %d)\n", NBLOCK);
 169:                 done(1);
 170:             }
 171:             break;
 172:         case 'l':
 173:             linkerrok++;
 174:             break;
 175:         default:
 176:             fprintf(stderr, "tar: %c: unknown option\n", *cp);
 177:             usage();
 178:         }
 179: 
 180:     if (work == REPLACE) {
 181: #ifdef OLDMAGTAPE
 182:         if (nblock == 0)
 183:             nblock = 1;
 184:         if (nblock != 1 && !cflag) {
 185:             fprintf(stderr, "tar: blocked tapes cannot be updated\n");
 186:             done(1);
 187:         }
 188: #endif
 189:         if (cflag && tfile != NULL) {
 190:             usage();
 191:             done(1);
 192:         }
 193:         if (signal(SIGINT, SIG_IGN) != SIG_IGN)
 194:             signal(SIGINT, onintr);
 195:         if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
 196:             signal(SIGHUP, onhup);
 197:         if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
 198:             signal(SIGQUIT, onquit);
 199: /*
 200: 		if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
 201: 			signal(SIGTERM, onterm);
 202: */
 203:         if (strcmp(usefile, "-") == 0) {
 204:             if (cflag == 0) {
 205:                 fprintf(stderr, "tar: can only create standard output archives\n");
 206:                 done(1);
 207:             }
 208:             vfile = stderr;
 209:             mt = dup(1);
 210:             nblock = PIPEBLOCK;
 211:         }
 212:         else if ((mt = open(usefile, 2)) < 0) {
 213:             if (cflag == 0 || (mt =  creat(usefile, 0666)) < 0) {
 214:                 fprintf(stderr, "tar: cannot open %s\n", usefile);
 215:                 done(1);
 216:             }
 217:         }
 218:         writing = 1;
 219:         dorep(argv);
 220:     }
 221:     else if (work) {
 222:         if (strcmp(usefile, "-") == 0) {
 223:             mt = dup(0);
 224:             nblock = PIPEBLOCK;
 225:         }
 226:         else if ((mt = open(usefile, 0)) < 0) {
 227:             fprintf(stderr, "tar: cannot open %s\n", usefile);
 228:             done(1);
 229:         }
 230:         switch (work) {
 231:         case EXTRACT:
 232:             doxtract(argv);
 233:             break;
 234:         case COMPARE:
 235:             docompare(argv);
 236:             break;
 237:         case TABLE:
 238:             dotable();
 239:             break;
 240:         }
 241:     }
 242:     else
 243:         usage();
 244:     done(0);
 245: }
 246: 
 247: usage()
 248: {
 249: #ifdef  UCB_SYMLINKS
 250:     fprintf(stderr, "tar: usage  tar -{txruC}[cvfblmh] [tapefile] [blocksize] file1 file2...\n");
 251: #else
 252:     fprintf(stderr, "tar: usage  tar -{txruC}[cvfblm] [tapefile] [blocksize] file1 file2...\n");
 253: #endif
 254:     done(1);
 255: }
 256: 
 257: dorep(argv)
 258: char    *argv[];
 259: {
 260:     register char *cp, *cp2;
 261:     char wdir[60];
 262: 
 263:     if (!cflag) {
 264:         getdir();
 265:         do {
 266:             passtape();
 267:             if (term)
 268:                 done(0);
 269:             getdir();
 270:         } while (!endtape());
 271:         if (tfile != NULL) {
 272:             char buf[200];
 273: 
 274:             sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX; mv %sX %s",
 275:                 tname, tname, tname, tname, tname, tname);
 276:             fflush(tfile);
 277:             system(buf);
 278:             freopen(tname, "r", tfile);
 279:             fstat(fileno(tfile), &stbuf);
 280:             high = stbuf.st_size;
 281:         }
 282:     }
 283: 
 284:     getwdir(wdir);
 285:     while (*argv && ! term) {
 286:         cp2 = *argv;
 287:         if (!strcmp(cp2, "-C") && argv[1]) {
 288:             argv++;
 289:             if (chdir(*argv) < 0)
 290:                 perror(*argv);
 291:             else
 292:                 getwdir(wdir);
 293:             argv++;
 294:             continue;
 295:         }
 296:         for (cp = *argv; *cp; cp++)
 297:             if (*cp == '/')
 298:                 cp2 = cp;
 299:         if (cp2 != *argv) {
 300:             *cp2 = '\0';
 301:             if (chdir(*argv) < 0) {
 302:                 perror(*argv);
 303:                 continue;
 304:             }
 305:             *cp2 = '/';
 306:             cp2++;
 307:         }
 308:         putfile(*argv++, cp2);
 309:         if (chdir(wdir) < 0) {
 310:             fprintf(stderr, "tar: cannot change back?: ");
 311:             perror(wdir);
 312:         }
 313:     }
 314:     putempty();
 315:     putempty();
 316:     flushtape();
 317:     if (linkerrok == 1)
 318:         for (; ihead != NULL; ihead = ihead->nextp)
 319:             if (ihead->count != 0)
 320:                 fprintf(stderr, "tar: missing links to %s\n", ihead->pathname);
 321: }
 322: 
 323: endtape()
 324: {
 325:     if (dblock.dbuf.name[0] == '\0') {
 326:         if (writing)
 327:             backtape();
 328:         return(1);
 329:     }
 330:     else
 331:         return(0);
 332: }
 333: 
 334: getdir()
 335: {
 336:     register struct stat *sp;
 337:     int i;
 338: 
 339:     readtape( (char *) &dblock);
 340:     if (dblock.dbuf.name[0] == '\0')
 341:         return;
 342:     sp = &stbuf;
 343:     sscanf(dblock.dbuf.mode, "%o", &i);
 344:     sp->st_mode = i;
 345:     sscanf(dblock.dbuf.uid, "%o", &i);
 346:     sp->st_uid = i;
 347:     sscanf(dblock.dbuf.gid, "%o", &i);
 348:     sp->st_gid = i;
 349:     sscanf(dblock.dbuf.size, "%lo", &sp->st_size);
 350:     sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime);
 351:     sscanf(dblock.dbuf.chksum, "%o", &chksum);
 352:     if (chksum != checksum()) {
 353:         fprintf(stderr, "tar: directory checksum error\n");
 354:         done(2);
 355:     }
 356:     if (tfile != NULL)
 357:         fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime);
 358: }
 359: 
 360: passtape()
 361: {
 362:     long blocks;
 363: 
 364:     if (dblock.dbuf.linkflag == '1')
 365:         return;
 366:     blocks = stbuf.st_size;
 367:     blocks += TBLOCK-1;
 368:     blocks /= TBLOCK;
 369: 
 370:     while (blocks-- > 0)
 371:         readtape((char *)NULL);
 372: }
 373: 
 374: putfile(longname, shortname)
 375: char *longname;
 376: char *shortname;
 377: {
 378:     int infile;
 379:     long blocks;
 380:     char buf[TBLOCK];
 381:     register char *cp, *cp2;
 382:     struct direct dbuf;
 383:     int i, j;
 384: 
 385:     infile = open(shortname, 0);
 386:     if (infile < 0) {
 387:         fprintf(stderr, "tar: %s: cannot open file\n", longname);
 388:         return;
 389:     }
 390: 
 391: #ifdef  UCB_SYMLINKS
 392:     if (!hflag)
 393:         lstat(shortname, &stbuf);
 394:     else
 395:         stat(shortname, &stbuf);
 396: #else
 397:     fstat(infile, &stbuf);
 398: #endif
 399: 
 400:     if (tfile != NULL && checkupdate(longname) == 0) {
 401:         close(infile);
 402:         return;
 403:     }
 404:     if (checkw('r', longname) == 0) {
 405:         close(infile);
 406:         return;
 407:     }
 408: 
 409:     if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
 410:         for (i = 0, cp = buf; *cp++ = longname[i++];);
 411:         *--cp = '/';
 412:         *++cp = 0  ;
 413:         i = 0;
 414:         if (!oflag) {
 415:             if( (cp - buf) >= NAMSIZ) {
 416:             fprintf(stderr, "tar: %s: file name too long\n", longname);
 417:             close(infile);
 418:             return;
 419:             }
 420:             stbuf.st_size = 0;
 421:             tomodes(&stbuf);
 422:             strcpy(dblock.dbuf.name,buf);
 423:             sprintf(dblock.dbuf.chksum, "%6o", checksum());
 424:             writetape( (char *) &dblock);
 425:         }
 426:         if (chdir(shortname) < 0) {
 427:             perror(shortname);
 428:             return;
 429:         }
 430:         while (read(infile, (char *)&dbuf, sizeof(dbuf)) > 0 && !term) {
 431:             if (dbuf.d_ino == 0) {
 432:                 i++;
 433:                 continue;
 434:             }
 435:             if (strcmp(".", dbuf.d_name) == 0 || strcmp("..", dbuf.d_name) == 0) {
 436:                 i++;
 437:                 continue;
 438:             }
 439:             cp2 = cp;
 440:             for (j=0; j < DIRSIZ; j++)
 441:                 *cp2++ = dbuf.d_name[j];
 442:             *cp2 = '\0';
 443:             close(infile);
 444:             putfile(buf, cp);
 445:             infile = open(".", 0);
 446:             i++;
 447:             lseek(infile, (long) (sizeof(dbuf) * i), 0);
 448:         }
 449:         close(infile);
 450:         chdir("..");
 451:         return;
 452:     }
 453:     i = stbuf.st_mode & S_IFMT;
 454: #ifdef  UCB_SYMLINKS
 455:     if (i != S_IFREG && i != S_IFLNK)
 456: #else
 457:     if (i != S_IFREG)
 458: #endif
 459:     {
 460:         fprintf(stderr, "tar: %s is not a file. Not dumped\n", longname);
 461:         close(infile);
 462:         return;
 463:     }
 464: 
 465:     tomodes(&stbuf);
 466: 
 467:     cp2 = longname;
 468:     for (cp = dblock.dbuf.name, i=0; (*cp++ = *cp2++) && i < NAMSIZ; i++);
 469:     if (i >= NAMSIZ) {
 470:         fprintf(stderr, "tar: %s: file name too long\n", longname);
 471:         close(infile);
 472:         return;
 473:     }
 474: 
 475: #ifdef  UCB_SYMLINKS
 476:     if ((stbuf.st_mode & S_IFMT) == S_IFLNK) {
 477:         if (stbuf.st_size + 1 >= NAMSIZ) {
 478:             fprintf(stderr, "tar: %s: symbolic link too long\n",
 479:                 longname);
 480:             close(infile);
 481:             return;
 482:         }
 483:         i = readlink(longname, dblock.dbuf.linkname, NAMSIZ - 1);
 484:         if (i < 0) {
 485:             perror("readlink");
 486:             close(infile);
 487:             return;
 488:         }
 489:         dblock.dbuf.linkname[i] = '\0';
 490:         dblock.dbuf.linkflag = '2';
 491:         if (vflag) {
 492:             fprintf(vfile, "a %s ", longname);
 493:             fprintf(vfile, "symbolic link to %s\n",
 494:                 dblock.dbuf.linkname);
 495:         }
 496:         sprintf(dblock.dbuf.size, "%11o", 0);
 497:         sprintf(dblock.dbuf.chksum, "%6o", checksum());
 498:         writetape((char *)&dblock);
 499:         close(infile);
 500:         return;
 501:     }
 502: #endif
 503:     if (stbuf.st_nlink > 1) {
 504:         struct linkbuf *lp;
 505:         int found = 0;
 506: 
 507:         for (lp = ihead; lp != NULL; lp = lp->nextp) {
 508:             if (lp->inum == stbuf.st_ino && lp->devnum == stbuf.st_dev) {
 509:                 found++;
 510:                 break;
 511:             }
 512:         }
 513:         if (found) {
 514:             strcpy(dblock.dbuf.linkname, lp->pathname);
 515:             dblock.dbuf.linkflag = '1';
 516:             sprintf(dblock.dbuf.chksum, "%6o", checksum());
 517:             writetape( (char *) &dblock);
 518:             if (vflag) {
 519:                 fprintf(vfile, "a %s ", longname);
 520:                 fprintf(vfile, "link to %s\n", lp->pathname);
 521:             }
 522:             lp->count--;
 523:             close(infile);
 524:             return;
 525:         }
 526:         else {
 527:             lp = (struct linkbuf *) malloc(sizeof(*lp));
 528:             if (lp == NULL) {
 529:                 if (freemem) {
 530:                     fprintf(stderr, "tar: out of memory.  Link information lost\n");
 531:                     freemem = 0;
 532:                 }
 533:             }
 534:             else {
 535:                 lp->nextp = ihead;
 536:                 ihead = lp;
 537:                 lp->inum = stbuf.st_ino;
 538:                 lp->devnum = stbuf.st_dev;
 539:                 lp->count = stbuf.st_nlink - 1;
 540:                 strcpy(lp->pathname, longname);
 541:             }
 542:         }
 543:     }
 544: 
 545:     blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK;
 546:     if (vflag) {
 547:         fprintf(vfile, "a %s ", longname);
 548:         fprintf(vfile, "%ld blocks\n", blocks);
 549:     }
 550:     sprintf(dblock.dbuf.chksum, "%6o", checksum());
 551:     writetape( (char *) &dblock);
 552: 
 553:     while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) {
 554:         writetape(buf);
 555:         blocks--;
 556:     }
 557:     close(infile);
 558:     if (blocks != 0 || i != 0)
 559:         fprintf(stderr, "tar: %s: file changed size\n", longname);
 560:     while (blocks-- >  0)
 561:         putempty();
 562: }
 563: 
 564: 
 565: 
 566: doxtract(argv)
 567: char    *argv[];
 568: {
 569:     long blocks, bytes;
 570:     char buf[TBLOCK];
 571:     char **cp;
 572:     int ifile;
 573:     int ofile;
 574:     char cmpfile[200 + NAMSIZ];
 575:     char *fcmpfile;
 576:     char tmpfile[200 + NAMSIZ];
 577:     int same;
 578: 
 579:     if (lnflag) {
 580:         strcpy (cmpfile, linkdir);
 581:         fcmpfile = &cmpfile[strlen(cmpfile)];
 582:         strcpy (fcmpfile, "/");
 583:         fcmpfile++;
 584:     }
 585:     for (;;) {
 586:         getdir();
 587:         if (endtape())
 588:             break;
 589: 
 590:         if (*argv == 0)
 591:             goto gotit;
 592: 
 593:         for (cp = argv; *cp; cp++)
 594:             if (prefix(*cp, dblock.dbuf.name))
 595:                 goto gotit;
 596:         passtape();
 597:         continue;
 598: 
 599: gotit:
 600:         if (checkw('x', dblock.dbuf.name) == 0) {
 601:             passtape();
 602:             continue;
 603:         }
 604: 
 605:         if(checkdir(dblock.dbuf.name))
 606:             continue;
 607: 
 608: #ifdef  UCB_SYMLINKS
 609:         if (dblock.dbuf.linkflag == '2') {
 610:             unlink(dblock.dbuf.name);
 611:             if (symlink(dblock.dbuf.linkname, dblock.dbuf.name)<0) {
 612:                 fprintf(stderr, "tar: %s: symbolic link failed\n",
 613:                     dblock.dbuf.name);
 614:                 continue;
 615:             }
 616:             if (vflag)
 617:                 fprintf(vfile, "x %s symbolic link to %s\n",
 618:                   dblock.dbuf.name, dblock.dbuf.linkname);
 619:             chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid);
 620:             if (mflag == 0) {
 621:                 time_t timep[2];
 622: 
 623:                 timep[0] = time(0);
 624:                 timep[1] = stbuf.st_mtime;
 625:                 utime(dblock.dbuf.name, timep);
 626:             }
 627:             if (pflag)
 628:                 chmod(dblock.dbuf.name, stbuf.st_mode & 07777);
 629:             continue;
 630:         }
 631: #else
 632:         if (dblock.dbuf.linkflag == '2') {
 633:             fprintf(stderr, "tar: %s: symbolic links not supported\n",
 634:                 dblock.dbuf.name);
 635:         }
 636: #endif
 637:         if (dblock.dbuf.linkflag == '1') {
 638:             unlink(dblock.dbuf.name);
 639:             if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) {
 640:                 fprintf(stderr, "tar: %s: cannot link\n", dblock.dbuf.name);
 641:                 continue;
 642:             }
 643:             if (vflag)
 644:                 fprintf(vfile, "%s linked to %s\n",
 645:                     dblock.dbuf.name, dblock.dbuf.linkname);
 646:             continue;
 647:         }
 648:         ifile = -1;
 649:         same = NO;
 650:         if (lnflag) {
 651:             static char tmpf[] = "TarXXXXXX";
 652:             same = YES;
 653:             if (dblock.dbuf.name[0] != '/') {
 654:                 strcpy (fcmpfile, dblock.dbuf.name);
 655:                 if ((ifile = open(cmpfile, 0)) >= 0) {
 656:                 tmpfile[0] = '\0';
 657:                 strncat (tmpfile, dblock.dbuf.name,
 658:                      dirpart (dblock.dbuf.name));
 659:                 strcat (tmpfile, tmpf);
 660:                 mktemp(tmpfile);
 661:                 }
 662:             }
 663:         }
 664:         if ((ofile = creat(ifile >= 0 ? tmpfile : dblock.dbuf.name,
 665:                    (int) stbuf.st_mode & 07777)) < 0) {
 666:             fprintf(stderr, "tar: %s - cannot create\n", dblock.dbuf.name);
 667:             passtape();
 668:             continue;
 669:         }
 670: 
 671:         blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK;
 672:         if (ifile >= 0) {
 673:             struct stat stbuf;
 674:             if (fstat(ifile, &stbuf) < 0 || bytes != stbuf.st_size)
 675:                 same = NO;
 676:         }
 677:         if (vflag)
 678:             fprintf(vfile, "x %s, %ld bytes, %ld tape blocks",
 679:                 dblock.dbuf.name, bytes, blocks);
 680:         while (blocks-- > 0) {
 681:             int nw;
 682:             readtape(buf);
 683:             nw = min(bytes, TBLOCK);
 684:             if (write(ofile, buf, nw) < nw) {
 685:                     fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name);
 686:                     done(2);
 687:                 }
 688:             if (ifile >= 0 && same)
 689:                 same = cmprd (ifile, buf, nw);
 690:             bytes -= TBLOCK;
 691:         }
 692:         close(ofile);
 693:         if (ifile >= 0) {
 694:             close(ifile);
 695:             unlink(dblock.dbuf.name);
 696:             if (vflag)
 697:                 fprintf(vfile, " (%s)", same? "same" : "new");
 698:             if (link(same? cmpfile : tmpfile, dblock.dbuf.name) < 0)
 699:                 fprintf(stderr, "tar: %s - cannot link\n",
 700:                     dblock.dbuf.name);
 701:             unlink (tmpfile);
 702:         }
 703:         if (vflag)
 704:             fprintf(vfile, "\n");
 705: 
 706:         if (ifile < 0 || !same) {
 707:             if (mflag == 0) {
 708:                 time_t timep[2];
 709: 
 710:                 timep[0] = time((time_t *) NULL);
 711:                 timep[1] = stbuf.st_mtime;
 712:                 utime(dblock.dbuf.name, timep);
 713:             }
 714:             chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid);
 715:             if(pflag)
 716:                 chmod(dblock.dbuf.name, (int)stbuf.st_mode & 07777);
 717:         }
 718:     }
 719: }
 720: 
 721: 
 722: docompare(argv)
 723: char    *argv[];
 724: {
 725:     long blocks, bytes;
 726:     char buf[TBLOCK];
 727:     char **cp;
 728:     struct stat stbuf2;
 729:     int ifile;
 730:     int same;
 731: 
 732:     for (;;) {
 733:         getdir();
 734:         if (endtape())
 735:             break;
 736: 
 737:         if (*argv == 0)
 738:             goto gotit;
 739: 
 740:         for (cp = argv; *cp; cp++)
 741:             if (prefix(*cp, dblock.dbuf.name))
 742:                 goto gotit;
 743:         passtape();
 744:         continue;
 745: 
 746: gotit:
 747:         if (dblock.dbuf.linkflag == '1') {
 748:             if (vflag) {
 749:                 printf("Link ");
 750:                 longt(&stbuf);
 751:                 printf("%s", dblock.dbuf.name);
 752:                 printf(" linked to %s\n", dblock.dbuf.linkname);
 753:             }
 754:             continue;
 755:         }
 756:         if (dblock.dbuf.linkflag == '2') {
 757:             if (vflag) {
 758:                 printf("Sym  ");
 759:                 longt(&stbuf);
 760:                 printf("%s", dblock.dbuf.name);
 761:                 printf(" symbolic link to %s\n", dblock.dbuf.linkname);
 762:             }
 763:             continue;
 764:         }
 765: 
 766:         if ((ifile = open(dblock.dbuf.name, 0)) < 0) {
 767:             printf("Err  ");
 768:             if (vflag)
 769:                 longt(&stbuf);
 770:             printf("%s: Cannot open disk file\n", dblock.dbuf.name);
 771:             passtape();
 772:             continue;
 773:         }
 774: 
 775:         same = YES;
 776:         blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK;
 777:         if (fstat(ifile, &stbuf2) < 0 || bytes != stbuf.st_size)
 778:             same = NO;
 779: 
 780:         if (same)
 781:             while (blocks-- > 0) {
 782:                 int nw;
 783:                 readtape(buf);
 784:                 nw = min(bytes, TBLOCK);
 785:                 if (same)
 786:                     same = cmprd (ifile, buf, nw);
 787:                 bytes -= TBLOCK;
 788:             }
 789:         else
 790:             passtape();
 791:         close(ifile);
 792: 
 793:         if (!same)
 794:             printf("diff ");
 795:         else if (vflag)
 796:             printf("same ");
 797:         if (vflag) {
 798:             longt(&stbuf);
 799:             printf("%s\n", dblock.dbuf.name);
 800:         }
 801:     }
 802: }
 803: 
 804: dotable()
 805: {
 806:     for (;;) {
 807:         getdir();
 808:         if (endtape())
 809:             break;
 810:         if (vflag)
 811:             longt(&stbuf);
 812:         printf("%s", dblock.dbuf.name);
 813:         if (dblock.dbuf.linkflag == '2')
 814:             printf(" symbolic link to %s", dblock.dbuf.linkname);
 815:         if (dblock.dbuf.linkflag == '1')
 816:             printf(" linked to %s", dblock.dbuf.linkname);
 817:         printf("\n");
 818:         passtape();
 819:     }
 820: }
 821: 
 822: putempty()
 823: {
 824:     char buf[TBLOCK];
 825:     char *cp;
 826: 
 827:     for (cp = buf; cp < &buf[TBLOCK]; )
 828:         *cp++ = '\0';
 829:     writetape(buf);
 830: }
 831: 
 832: longt(st)
 833: register struct stat *st;
 834: {
 835:     register char *cp;
 836:     char *ctime();
 837: 
 838:     pmode(st);
 839:     printf("%3d/%-2d", st->st_uid, st->st_gid);
 840:     printf("%7D", st->st_size);
 841:     cp = ctime(&st->st_mtime);
 842:     printf(" %-12.12s %-4.4s ", cp+4, cp+20);
 843: }
 844: 
 845: #define SUID    04000
 846: #define SGID    02000
 847: #define ROWN    0400
 848: #define WOWN    0200
 849: #define XOWN    0100
 850: #define RGRP    040
 851: #define WGRP    020
 852: #define XGRP    010
 853: #define ROTH    04
 854: #define WOTH    02
 855: #define XOTH    01
 856: #define STXT    01000
 857: int m1[] = { 1, ROWN, 'r', '-' };
 858: int m2[] = { 1, WOWN, 'w', '-' };
 859: int m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
 860: int m4[] = { 1, RGRP, 'r', '-' };
 861: int m5[] = { 1, WGRP, 'w', '-' };
 862: int m6[] = { 2, SGID, 's', XGRP, 'x', '-' };
 863: int m7[] = { 1, ROTH, 'r', '-' };
 864: int m8[] = { 1, WOTH, 'w', '-' };
 865: int m9[] = { 2, STXT, 't', XOTH, 'x', '-' };
 866: 
 867: int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
 868: 
 869: pmode(st)
 870: register struct stat *st;
 871: {
 872:     register int **mp;
 873: 
 874:     for (mp = &m[0]; mp < &m[9];)
 875:         select(*mp++, st);
 876: }
 877: 
 878: select(pairp, st)
 879: int *pairp;
 880: struct stat *st;
 881: {
 882:     register int n, *ap;
 883: 
 884:     ap = pairp;
 885:     n = *ap++;
 886:     while (--n>=0 && (st->st_mode&*ap++)==0)
 887:         ap++;
 888:     printf("%c", *ap);
 889: }
 890: 
 891: checkdir(name)
 892: register char *name;
 893: {
 894:     register char *cp;
 895:     int i;
 896:     for (cp = name; *cp; cp++) {
 897:         if (*cp == '/') {
 898:             *cp = '\0';
 899:             if (access(name, 01) < 0) {
 900:                 register int pid, rp;
 901: 
 902:                 if ((pid = fork()) == 0) {
 903:                     execl("/bin/mkdir", "mkdir", name, 0);
 904:                     execl("/usr/bin/mkdir", "mkdir", name, 0);
 905:                     fprintf(stderr, "tar: cannot find mkdir!\n");
 906:                     done(0);
 907:                 }
 908:                 while ((rp = wait(&i)) >= 0 && rp != pid)
 909:                     ;
 910:                 chown(name, stbuf.st_uid, stbuf.st_gid);
 911:                 if (pflag && cp[1] == '\0')
 912:                     chmod(dblock.dbuf.name,
 913:                       (int) stbuf.st_mode & 01777);
 914:             }
 915:             *cp = '/';
 916:         }
 917:     }
 918:     return(cp[-1]=='/');
 919: }
 920: 
 921: onintr()
 922: {
 923:     signal(SIGINT, SIG_IGN);
 924:     term++;
 925: }
 926: 
 927: onquit()
 928: {
 929:     signal(SIGQUIT, SIG_IGN);
 930:     term++;
 931: }
 932: 
 933: onhup()
 934: {
 935:     signal(SIGHUP, SIG_IGN);
 936:     term++;
 937: }
 938: 
 939: /*
 940: onterm()
 941: {
 942: 	signal(SIGTERM, SIG_IGN);
 943: 	term++;
 944: }
 945: */
 946: 
 947: tomodes(sp)
 948: register struct stat *sp;
 949: {
 950:     register char *cp;
 951: 
 952:     for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
 953:         *cp = '\0';
 954:     sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777);
 955:     sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid);
 956:     sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid);
 957:     sprintf(dblock.dbuf.size, "%11lo ", sp->st_size);
 958:     sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime);
 959: }
 960: 
 961: checksum()
 962: {
 963:     register i;
 964:     register char *cp;
 965: 
 966:     for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
 967:         *cp = ' ';
 968:     i = 0;
 969:     for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
 970:         i += *cp;
 971:     return(i);
 972: }
 973: 
 974: checkw(c, name)
 975: char *name;
 976: {
 977:     if (wflag) {
 978:         printf("%c ", c);
 979:         if (vflag)
 980:             longt(&stbuf);
 981:         printf("%s: ", name);
 982:         if (response() == 'y'){
 983:             return(1);
 984:         }
 985:         return(0);
 986:     }
 987:     return(1);
 988: }
 989: 
 990: response()
 991: {
 992:     char c;
 993: 
 994:     c = getchar();
 995:     if (c != '\n')
 996:         while (getchar() != '\n');
 997:     else c = 'n';
 998:     return(c);
 999: }
1000: 
1001: checkupdate(arg)
1002: char    *arg;
1003: {
1004:     char name[100];
1005:     long    mtime;
1006:     daddr_t seekp;
1007:     daddr_t lookup();
1008: 
1009:     rewind(tfile);
1010:     for (;;) {
1011:         if ((seekp = lookup(arg)) < 0)
1012:             return(1);
1013:         fseek(tfile, seekp, 0);
1014:         fscanf(tfile, "%s %lo", name, &mtime);
1015:         if (stbuf.st_mtime > mtime)
1016:             return(1);
1017:         else
1018:             return(0);
1019:     }
1020: }
1021: 
1022: done(n)
1023: {
1024:     unlink(tname);
1025:     exit(n);
1026: }
1027: 
1028: prefix(s1, s2)
1029: register char *s1, *s2;
1030: {
1031:     while (*s1)
1032:         if (*s1++ != *s2++)
1033:             return(0);
1034:     if (*s2)
1035:         return(*s2 == '/');
1036:     return(1);
1037: }
1038: 
1039: getwdir(s)
1040: char *s;
1041: {
1042:     int i;
1043:     int pipdes[2];
1044: 
1045:     pipe(pipdes);
1046:     if ((i = fork()) == 0) {
1047:         close(1);
1048:         dup(pipdes[1]);
1049:         execl("/bin/pwd", "pwd", 0);
1050:         execl("/usr/bin/pwd", "pwd", 0);
1051:         fprintf(stderr, "pwd failed!\n");
1052:         printf("/\n");
1053:         exit(1);
1054:     }
1055:     while (wait((int *)NULL) != -1)
1056:             ;
1057:     read(pipdes[0], s, 50);
1058:     while(*s != '\n')
1059:         s++;
1060:     *s = '\0';
1061:     close(pipdes[0]);
1062:     close(pipdes[1]);
1063: }
1064: 
1065: #define N   200
1066: int njab;
1067: daddr_t
1068: lookup(s)
1069: char *s;
1070: {
1071:     register i;
1072:     daddr_t a;
1073: 
1074:     for(i=0; s[i]; i++)
1075:         if(s[i] == ' ')
1076:             break;
1077:     a = bsrch(s, i, low, high);
1078:     return(a);
1079: }
1080: 
1081: daddr_t
1082: bsrch(s, n, l, h)
1083: daddr_t l, h;
1084: char *s;
1085: {
1086:     register i, j;
1087:     char b[N];
1088:     daddr_t m, m1;
1089: 
1090:     njab = 0;
1091: 
1092: loop:
1093:     if(l >= h)
1094:         return(-1L);
1095:     m = l + (h-l)/2 - N/2;
1096:     if(m < l)
1097:         m = l;
1098:     fseek(tfile, m, 0);
1099:     fread(b, 1, N, tfile);
1100:     njab++;
1101:     for(i=0; i<N; i++) {
1102:         if(b[i] == '\n')
1103:             break;
1104:         m++;
1105:     }
1106:     if(m >= h)
1107:         return(-1L);
1108:     m1 = m;
1109:     j = i;
1110:     for(i++; i<N; i++) {
1111:         m1++;
1112:         if(b[i] == '\n')
1113:             break;
1114:     }
1115:     i = cmp(b+j, s, n);
1116:     if(i < 0) {
1117:         h = m;
1118:         goto loop;
1119:     }
1120:     if(i > 0) {
1121:         l = m1;
1122:         goto loop;
1123:     }
1124:     return(m);
1125: }
1126: 
1127: cmp(b, s, n)
1128: char *b, *s;
1129: {
1130:     register i;
1131: 
1132:     if(b[0] != '\n')
1133:         exit(2);
1134:     for(i=0; i<n; i++) {
1135:         if(b[i+1] > s[i])
1136:             return(-1);
1137:         if(b[i+1] < s[i])
1138:             return(1);
1139:     }
1140:     return(b[i+1] == ' '? 0 : -1);
1141: }
1142: 
1143: int mtdev = 1;
1144: #ifndef OLDMAGTAPE
1145: struct mtget mtget;
1146: #else
1147: struct stat stb;
1148: #endif
1149: 
1150: readtape(buffer)
1151: char *buffer;
1152: {
1153:     register int i;
1154:     int j;
1155: 
1156:     if (recno >= nblock || first == 0) {
1157: #ifndef OLDMAGTAPE
1158:         if (mtdev == 1)
1159:             mtdev = ioctl(mt, MTIOCGET, &mtget);
1160: #else
1161:         fstat(mt, &stb);
1162:         if ((stb.st_mode & IFMT) == IFCHR)
1163:             mtdev = 0;
1164:         else
1165:             mtdev = -1;
1166: #endif
1167:         if (first==0 && nblock==0) {
1168:             if (mtdev == 0)
1169:                 j = NBLOCK;
1170:             else
1171:                 j = FILEBLOCK;
1172:         } else
1173:             j = nblock;
1174:         if ((i = read(mt, (char *) tbuf, TBLOCK*j)) < 0) {
1175:             fprintf(stderr, "tar: tape read error\n");
1176:             done(3);
1177:         }
1178:         if (first == 0) {
1179:             if ((i % TBLOCK) != 0) {
1180:                 fprintf(stderr, "tar: tape blocksize error\n");
1181:                 done(3);
1182:             }
1183:             i /= TBLOCK;
1184: #ifdef  OLDMAGTAPE
1185:             if (work == REPLACE && i != 1) {
1186:                 fprintf(stderr, "tar: cannot update blocked tapes\n");
1187:                 done(4);
1188:             }
1189: #endif
1190:             if (i != nblock ) {
1191:                 if (mtdev == 0)
1192:                    fprintf(vfile, "tar: blocksize = %d\n", i);
1193:                 nblock = i;
1194:             }
1195:         }
1196:         recno = 0;
1197:     }
1198:     first = 1;
1199:     if (buffer)
1200:         copy(buffer, (char *) &tbuf[recno]);
1201:     recno++;
1202:     return(TBLOCK);
1203: }
1204: 
1205: writetape(buffer)
1206: char *buffer;
1207: {
1208:     first = 1;
1209:     if (nblock == 0)
1210:         nblock = BLOCKDFLT;
1211:     if (recno >= nblock) {
1212:         if (write(mt, (char *) tbuf, TBLOCK*nblock) < 0) {
1213:             fprintf(stderr, "tar: tape write error\n");
1214:             done(2);
1215:         }
1216:         recno = 0;
1217:     }
1218:     copy((char *) &tbuf[recno++], buffer);
1219:     if (recno >= nblock) {
1220:         if (write(mt, (char *) tbuf, TBLOCK*nblock) < 0) {
1221:             fprintf(stderr, "tar: tape write error\n");
1222:             done(2);
1223:         }
1224:         recno = 0;
1225:     }
1226:     return(TBLOCK);
1227: }
1228: 
1229: backtape()
1230: {
1231: #ifndef OLDMAGTAPE
1232:     static struct mtop mtop = {MTBSR, 1};
1233: 
1234:     if (mtdev == 1)
1235:         mtdev = ioctl(mt, MTIOCGET, &mtget);
1236:     if (mtdev == 0) {
1237:         if (ioctl(mt, MTIOCTOP, &mtop) < 0) {
1238:             fprintf(stderr, "tar: tape backspace error\n");
1239:             done(4);
1240:         }
1241:     } else
1242:         lseek(mt, (long) -TBLOCK*nblock, 1);
1243:     recno--;
1244: #else
1245:     lseek(mt, (long) -TBLOCK, 1);
1246:     if (recno >= nblock) {
1247:         recno = nblock - 1;
1248:         if (read(mt, (char *) tbuf, TBLOCK*nblock) < 0) {
1249:             fprintf(stderr, "tar: tape read error after seek\n");
1250:             done(4);
1251:         }
1252:         lseek(mt, (long) -TBLOCK, 1);
1253:     }
1254: #endif
1255: }
1256: 
1257: flushtape()
1258: {
1259:     write(mt, (char *) tbuf, TBLOCK*nblock);
1260: }
1261: 
1262: copy(to, from)
1263: register char *to, *from;
1264: {
1265:     register i;
1266: 
1267:     i = TBLOCK;
1268:     do {
1269:         *to++ = *from++;
1270:     } while (--i);
1271: }
1272: 
1273: /*  Compare the next 'nw' characters of ifile with buf.
1274:  *   return 1 if same, else 0
1275:  */
1276: cmprd (ifile, buf, num)
1277: int ifile;
1278: char *buf;
1279: int num;
1280: {
1281:     register int nr;
1282:     char ibuf[TBLOCK];
1283: 
1284:     if (read (ifile, ibuf, num) < num)
1285:         return NO;
1286:     if (bufcmp (buf, ibuf, num))
1287:         return NO;
1288:     return YES;
1289: }
1290: 
1291: 
1292: bufcmp (cp1, cp2, num)
1293: register char *cp1;
1294: register char *cp2;
1295: register int num;
1296: {
1297:     if (num <= 0)
1298:         return 0;
1299:     do
1300:         if (*cp1++ != *cp2++)
1301:             return *--cp2 - *--cp1;
1302:     while (--num);
1303:     return 0;
1304: }
1305: 
1306: dirpart (str)
1307: char *str;
1308: {
1309:     register char *cp;
1310:     char *rindex();
1311: 
1312:     if (cp = rindex (str, '/'))
1313:         return cp - str + 1;
1314:     else
1315:         return 0;
1316: }

Defined functions

backtape defined in line 1229; used 1 times
bsrch defined in line 1081; used 2 times
bufcmp defined in line 1292; used 1 times
checkdir defined in line 891; used 1 times
checksum defined in line 961; used 5 times
checkupdate defined in line 1001; used 1 times
checkw defined in line 974; used 2 times
cmp defined in line 1127; used 1 times
cmprd defined in line 1276; used 2 times
copy defined in line 1262; used 2 times
dirpart defined in line 1306; used 1 times
docompare defined in line 722; used 1 times
done defined in line 1022; used 20 times
dorep defined in line 257; used 1 times
dotable defined in line 804; used 1 times
doxtract defined in line 566; used 1 times
endtape defined in line 323; used 4 times
flushtape defined in line 1257; used 1 times
getdir defined in line 334; used 5 times
getwdir defined in line 1039; used 2 times
longt defined in line 832; used 6 times
lookup defined in line 1067; used 2 times
main defined in line 84; never used
onhup defined in line 933; used 2 times
onintr defined in line 921; used 2 times
onquit defined in line 927; used 2 times
passtape defined in line 360; used 8 times
pmode defined in line 869; used 1 times
prefix defined in line 1028; used 2 times
putempty defined in line 822; used 3 times
putfile defined in line 374; used 2 times
readtape defined in line 1150; used 4 times
response defined in line 990; used 1 times
select defined in line 878; used 1 times
tomodes defined in line 947; used 2 times
usage defined in line 247; used 4 times
writetape defined in line 1205; used 6 times

Defined variables

cflag defined in line 65; used 6 times
chksum defined in line 66; used 11 times
dblock defined in line 45; used 93 times
fflag defined in line 65; used 1 times
first defined in line 66; used 5 times
freemem defined in line 67; used 2 times
hflag defined in line 65; used 2 times
high defined in line 72; used 2 times
ihead defined in line 53; used 8 times
linkdir defined in line 64; used 2 times
linkerrok defined in line 66; used 2 times
lnflag defined in line 63; used 3 times
low defined in line 71; used 1 times
m defined in line 867; used 12 times
m1 defined in line 857; used 5 times
m2 defined in line 858; used 1 times
m3 defined in line 859; used 1 times
m4 defined in line 860; used 1 times
m5 defined in line 861; used 1 times
m6 defined in line 862; used 1 times
m7 defined in line 863; used 1 times
m8 defined in line 864; used 1 times
m9 defined in line 865; used 1 times
magtape defined in line 79; used 3 times
mflag defined in line 65; used 3 times
mt defined in line 65; used 17 times
mtdev defined in line 1143; used 9 times
mtget defined in line 1145; used 2 times
nblock defined in line 68; used 24 times
njab defined in line 1066; used 2 times
oflag defined in line 65; used 2 times
pflag defined in line 65; used 4 times
recno defined in line 66; used 12 times
stb defined in line 1147; used 2 times
stbuf defined in line 55; used 46 times
tbuf defined in line 45; used 7 times
term defined in line 66; used 6 times
tname defined in line 75; used 11 times
usefile defined in line 78; used 10 times
vflag defined in line 65; used 16 times
wflag defined in line 66; used 2 times
work defined in line 57; used 10 times
writing defined in line 80; used 2 times

Defined struct's

header defined in line 34; never used
linkbuf defined in line 47; used 6 times

Defined union's

hblock defined in line 32; never used

Defined macros

BLOCKDFLT defined in line 27; used 1 times
COMPARE defined in line 59; used 1 times
EXTRACT defined in line 60; used 2 times
FILEBLOCK defined in line 29; used 1 times
N defined in line 1065; used 5 times
NAMSIZ defined in line 31; used 10 times
NBLOCK defined in line 26; used 4 times
NO defined in line 14; used 5 times
PIPEBLOCK defined in line 28; used 2 times
REPLACE defined in line 61; used 4 times
RGRP defined in line 850; used 1 times
ROTH defined in line 853; used 1 times
ROWN defined in line 847; used 1 times
SGID defined in line 846; used 1 times
STXT defined in line 856; used 1 times
SUID defined in line 845; used 1 times
TABLE defined in line 58; used 1 times
TBLOCK defined in line 24; used 35 times
WGRP defined in line 851; used 1 times
WOTH defined in line 854; used 1 times
WOWN defined in line 848; used 1 times
XGRP defined in line 852; used 1 times
XOTH defined in line 855; used 1 times
XOWN defined in line 849; used 1 times
YES defined in line 13; used 3 times
min defined in line 15; used 2 times
Last modified: 1983-09-26
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3594
Valid CSS Valid XHTML 1.0 Strict