1*5931Smckusic static char *sccsid = "@(#)tar.c 4.6 (Berkeley) 82/02/21"; 21119Sbill #include <stdio.h> 31119Sbill #include <sys/types.h> 41119Sbill #include <sys/stat.h> 5*5931Smckusic #include <ndir.h> 63457Swnj #include <sys/mtio.h> 71119Sbill #include <signal.h> 81119Sbill 91119Sbill char *sprintf(); 101119Sbill char *strcat(); 111119Sbill daddr_t bsrch(); 121119Sbill #define TBLOCK 512 133355Swnj #define NBLOCK 20 141119Sbill #define NAMSIZ 100 151119Sbill union hblock { 161119Sbill char dummy[TBLOCK]; 171119Sbill struct header { 181119Sbill char name[NAMSIZ]; 191119Sbill char mode[8]; 201119Sbill char uid[8]; 211119Sbill char gid[8]; 221119Sbill char size[12]; 231119Sbill char mtime[12]; 241119Sbill char chksum[8]; 251119Sbill char linkflag; 261119Sbill char linkname[NAMSIZ]; 271119Sbill } dbuf; 281119Sbill } dblock, tbuf[NBLOCK]; 291119Sbill 301119Sbill struct linkbuf { 311119Sbill ino_t inum; 321119Sbill dev_t devnum; 331119Sbill int count; 341119Sbill char pathname[NAMSIZ]; 351119Sbill struct linkbuf *nextp; 361119Sbill } *ihead; 371119Sbill 381119Sbill struct stat stbuf; 391119Sbill 401119Sbill int rflag, xflag, vflag, tflag, mt, cflag, mflag, fflag, oflag, pflag; 411119Sbill int term, chksum, wflag, recno, first, linkerrok; 421119Sbill int freemem = 1; 433457Swnj int nblock = NBLOCK; 441119Sbill 451119Sbill daddr_t low; 461119Sbill daddr_t high; 471119Sbill 481119Sbill FILE *tfile; 491119Sbill char tname[] = "/tmp/tarXXXXXX"; 501119Sbill 511119Sbill 521119Sbill char *usefile; 531119Sbill char magtape[] = "/dev/rmt8"; 541119Sbill 551119Sbill char *malloc(); 561119Sbill 571119Sbill main(argc, argv) 581119Sbill int argc; 591119Sbill char *argv[]; 601119Sbill { 611119Sbill char *cp; 621119Sbill int onintr(), onquit(), onhup(), onterm(); 631119Sbill 641119Sbill if (argc < 2) 651119Sbill usage(); 661119Sbill 671119Sbill tfile = NULL; 681119Sbill usefile = magtape; 691119Sbill argv[argc] = 0; 701119Sbill argv++; 711119Sbill for (cp = *argv++; *cp; cp++) 721119Sbill switch(*cp) { 731119Sbill case 'f': 741119Sbill usefile = *argv++; 751119Sbill fflag++; 761119Sbill break; 771119Sbill case 'c': 781119Sbill cflag++; 791119Sbill rflag++; 801119Sbill break; 811119Sbill case 'o': 821119Sbill oflag++; 831119Sbill break; 841119Sbill case 'p': 851119Sbill pflag++; 861119Sbill break; 871119Sbill case 'u': 881119Sbill mktemp(tname); 891119Sbill if ((tfile = fopen(tname, "w")) == NULL) { 901119Sbill fprintf(stderr, "Tar: cannot create temporary file (%s)\n", tname); 911119Sbill done(1); 921119Sbill } 931119Sbill fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n"); 941119Sbill /* FALL THROUGH */ 951119Sbill case 'r': 961119Sbill rflag++; 971119Sbill break; 981119Sbill case 'v': 991119Sbill vflag++; 1001119Sbill break; 1011119Sbill case 'w': 1021119Sbill wflag++; 1031119Sbill break; 1041119Sbill case 'x': 1051119Sbill xflag++; 1061119Sbill break; 1071119Sbill case 't': 1081119Sbill tflag++; 1091119Sbill break; 1101119Sbill case 'm': 1111119Sbill mflag++; 1121119Sbill break; 1131119Sbill case '-': 1141119Sbill break; 1151119Sbill case '0': 1161119Sbill case '1': 1171119Sbill case '4': 1181119Sbill case '5': 1191119Sbill case '7': 1201119Sbill case '8': 1211119Sbill magtape[8] = *cp; 1221119Sbill usefile = magtape; 1231119Sbill break; 1241119Sbill case 'b': 1251119Sbill nblock = atoi(*argv++); 1261119Sbill if (nblock > NBLOCK || nblock <= 0) { 1271119Sbill fprintf(stderr, "Invalid blocksize. (Max %d)\n", NBLOCK); 1281119Sbill done(1); 1291119Sbill } 1301119Sbill break; 1311119Sbill case 'l': 1321119Sbill linkerrok++; 1331119Sbill break; 1341119Sbill default: 1351119Sbill fprintf(stderr, "tar: %c: unknown option\n", *cp); 1361119Sbill usage(); 1371119Sbill } 1381119Sbill 1391119Sbill if (rflag) { 1401119Sbill if (cflag && tfile != NULL) { 1411119Sbill usage(); 1421119Sbill done(1); 1431119Sbill } 1441119Sbill if (signal(SIGINT, SIG_IGN) != SIG_IGN) 1451119Sbill signal(SIGINT, onintr); 1461119Sbill if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 1471119Sbill signal(SIGHUP, onhup); 1481119Sbill if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 1491119Sbill signal(SIGQUIT, onquit); 1501119Sbill /* 1511119Sbill if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 1521119Sbill signal(SIGTERM, onterm); 1531119Sbill */ 1541119Sbill if (strcmp(usefile, "-") == 0) { 1551119Sbill if (cflag == 0) { 1561119Sbill fprintf(stderr, "Can only create standard output archives\n"); 1571119Sbill done(1); 1581119Sbill } 1591119Sbill mt = dup(1); 1601119Sbill nblock = 1; 1611119Sbill } 1621119Sbill else if ((mt = open(usefile, 2)) < 0) { 1631119Sbill if (cflag == 0 || (mt = creat(usefile, 0666)) < 0) { 1641119Sbill fprintf(stderr, "tar: cannot open %s\n", usefile); 1651119Sbill done(1); 1661119Sbill } 1671119Sbill } 1681119Sbill dorep(argv); 1691119Sbill } 1701119Sbill else if (xflag) { 1711119Sbill if (strcmp(usefile, "-") == 0) { 1721119Sbill mt = dup(0); 1731119Sbill nblock = 1; 1741119Sbill } 1751119Sbill else if ((mt = open(usefile, 0)) < 0) { 1761119Sbill fprintf(stderr, "tar: cannot open %s\n", usefile); 1771119Sbill done(1); 1781119Sbill } 1791119Sbill doxtract(argv); 1801119Sbill } 1811119Sbill else if (tflag) { 1821119Sbill if (strcmp(usefile, "-") == 0) { 1831119Sbill mt = dup(0); 1841119Sbill nblock = 1; 1851119Sbill } 1861119Sbill else if ((mt = open(usefile, 0)) < 0) { 1871119Sbill fprintf(stderr, "tar: cannot open %s\n", usefile); 1881119Sbill done(1); 1891119Sbill } 1901119Sbill dotable(); 1911119Sbill } 1921119Sbill else 1931119Sbill usage(); 1941119Sbill done(0); 1951119Sbill } 1961119Sbill 1971119Sbill usage() 1981119Sbill { 1991119Sbill fprintf(stderr, "tar: usage tar -{txru}[cvfblm] [tapefile] [blocksize] file1 file2...\n"); 2001119Sbill done(1); 2011119Sbill } 2021119Sbill 2031119Sbill dorep(argv) 2041119Sbill char *argv[]; 2051119Sbill { 2061119Sbill register char *cp, *cp2; 2071119Sbill char wdir[60]; 2081119Sbill 2091119Sbill if (!cflag) { 2101119Sbill getdir(); 2111119Sbill do { 2121119Sbill passtape(); 2131119Sbill if (term) 2141119Sbill done(0); 2151119Sbill getdir(); 2161119Sbill } while (!endtape()); 2171119Sbill if (tfile != NULL) { 2181119Sbill char buf[200]; 2191119Sbill 2203457Swnj sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX; mv %sX %s", 2211119Sbill tname, tname, tname, tname, tname, tname); 2221119Sbill fflush(tfile); 2231119Sbill system(buf); 2241119Sbill freopen(tname, "r", tfile); 2251119Sbill fstat(fileno(tfile), &stbuf); 2261119Sbill high = stbuf.st_size; 2271119Sbill } 2281119Sbill } 2291119Sbill 2301119Sbill getwdir(wdir); 2311119Sbill while (*argv && ! term) { 2321119Sbill cp2 = *argv; 2331119Sbill if (!strcmp(cp2, "-C") && argv[1]) { 2341119Sbill argv++; 2351119Sbill if (chdir(*argv) < 0) 2361119Sbill perror(*argv); 2371119Sbill else 2381119Sbill getwdir(wdir); 2391119Sbill argv++; 2401119Sbill continue; 2411119Sbill } 2421119Sbill for (cp = *argv; *cp; cp++) 2431119Sbill if (*cp == '/') 2441119Sbill cp2 = cp; 2451119Sbill if (cp2 != *argv) { 2461119Sbill *cp2 = '\0'; 2471119Sbill chdir(*argv); 2481119Sbill *cp2 = '/'; 2491119Sbill cp2++; 2501119Sbill } 2511119Sbill putfile(*argv++, cp2); 2521119Sbill chdir(wdir); 2531119Sbill } 2541119Sbill putempty(); 2551119Sbill putempty(); 2561119Sbill flushtape(); 2571119Sbill if (linkerrok == 1) 2581119Sbill for (; ihead != NULL; ihead = ihead->nextp) 2591119Sbill if (ihead->count != 0) 2601119Sbill fprintf(stderr, "Missing links to %s\n", ihead->pathname); 2611119Sbill } 2621119Sbill 2631119Sbill endtape() 2641119Sbill { 2651119Sbill if (dblock.dbuf.name[0] == '\0') { 2661119Sbill backtape(); 2671119Sbill return(1); 2681119Sbill } 2691119Sbill else 2701119Sbill return(0); 2711119Sbill } 2721119Sbill 2731119Sbill getdir() 2741119Sbill { 2751119Sbill register struct stat *sp; 2761119Sbill int i; 2771119Sbill 2781119Sbill readtape( (char *) &dblock); 2791119Sbill if (dblock.dbuf.name[0] == '\0') 2801119Sbill return; 2811119Sbill sp = &stbuf; 2821119Sbill sscanf(dblock.dbuf.mode, "%o", &i); 2831119Sbill sp->st_mode = i; 2841119Sbill sscanf(dblock.dbuf.uid, "%o", &i); 2851119Sbill sp->st_uid = i; 2861119Sbill sscanf(dblock.dbuf.gid, "%o", &i); 2871119Sbill sp->st_gid = i; 2881119Sbill sscanf(dblock.dbuf.size, "%lo", &sp->st_size); 2891119Sbill sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime); 2901119Sbill sscanf(dblock.dbuf.chksum, "%o", &chksum); 2911119Sbill if (chksum != checksum()) { 2921119Sbill fprintf(stderr, "directory checksum error\n"); 2931119Sbill done(2); 2941119Sbill } 2951119Sbill if (tfile != NULL) 2961119Sbill fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime); 2971119Sbill } 2981119Sbill 2991119Sbill passtape() 3001119Sbill { 3011119Sbill long blocks; 3021119Sbill char buf[TBLOCK]; 3031119Sbill 3041119Sbill if (dblock.dbuf.linkflag == '1') 3051119Sbill return; 3061119Sbill blocks = stbuf.st_size; 3071119Sbill blocks += TBLOCK-1; 3081119Sbill blocks /= TBLOCK; 3091119Sbill 3101119Sbill while (blocks-- > 0) 3111119Sbill readtape(buf); 3121119Sbill } 3131119Sbill 3141119Sbill putfile(longname, shortname) 3151119Sbill char *longname; 3161119Sbill char *shortname; 3171119Sbill { 3181119Sbill int infile; 3191119Sbill long blocks; 3201119Sbill char buf[TBLOCK]; 3211119Sbill register char *cp, *cp2; 322*5931Smckusic struct direct *dp; 323*5931Smckusic DIR *dirp; 3241119Sbill int i, j; 3251119Sbill 3261119Sbill infile = open(shortname, 0); 3271119Sbill if (infile < 0) { 3281119Sbill fprintf(stderr, "tar: %s: cannot open file\n", longname); 3291119Sbill return; 3301119Sbill } 3311119Sbill 3321119Sbill fstat(infile, &stbuf); 3331119Sbill 3341119Sbill if (tfile != NULL && checkupdate(longname) == 0) { 3351119Sbill close(infile); 3361119Sbill return; 3371119Sbill } 3381119Sbill if (checkw('r', longname) == 0) { 3391119Sbill close(infile); 3401119Sbill return; 3411119Sbill } 3421119Sbill 3431119Sbill if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 3441119Sbill for (i = 0, cp = buf; *cp++ = longname[i++];); 3451119Sbill *--cp = '/'; 3461119Sbill *++cp = 0 ; 3471119Sbill if (!oflag) { 3481119Sbill if( (cp - buf) >= NAMSIZ) { 3491119Sbill fprintf(stderr, "%s: file name too long\n", longname); 3501119Sbill close(infile); 3511119Sbill return; 3521119Sbill } 3531119Sbill stbuf.st_size = 0; 3541119Sbill tomodes(&stbuf); 3551119Sbill strcpy(dblock.dbuf.name,buf); 3561119Sbill sprintf(dblock.dbuf.chksum, "%6o", checksum()); 3571119Sbill writetape( (char *) &dblock); 3581119Sbill } 3591119Sbill chdir(shortname); 360*5931Smckusic close(infile); 361*5931Smckusic if ((dirp = opendir(".")) == NULL) { 362*5931Smckusic fprintf(stderr, "%s: directory read error\n", longname); 363*5931Smckusic return; 364*5931Smckusic } 365*5931Smckusic while ((dp = readdir(dirp)) != NULL && !term) { 366*5931Smckusic if (dp->d_ino == 0) 3671119Sbill continue; 368*5931Smckusic if (!strcmp(".", dp->d_name) || !strcmp("..", dp->d_name)) 3691119Sbill continue; 370*5931Smckusic strcpy(cp, dp->d_name); 371*5931Smckusic i = telldir(dirp); 372*5931Smckusic closedir(dirp); 3731119Sbill putfile(buf, cp); 374*5931Smckusic dirp = opendir("."); 375*5931Smckusic seekdir(dirp, i); 3761119Sbill } 377*5931Smckusic closedir(dirp); 3781119Sbill chdir(".."); 3791119Sbill return; 3801119Sbill } 3811119Sbill if ((stbuf.st_mode & S_IFMT) != S_IFREG) { 3821119Sbill fprintf(stderr, "tar: %s is not a file. Not dumped\n", longname); 3831119Sbill return; 3841119Sbill } 3851119Sbill 3861119Sbill tomodes(&stbuf); 3871119Sbill 3881119Sbill cp2 = longname; 3891119Sbill for (cp = dblock.dbuf.name, i=0; (*cp++ = *cp2++) && i < NAMSIZ; i++); 3901119Sbill if (i >= NAMSIZ) { 3911119Sbill fprintf(stderr, "%s: file name too long\n", longname); 3921119Sbill close(infile); 3931119Sbill return; 3941119Sbill } 3951119Sbill 3961119Sbill if (stbuf.st_nlink > 1) { 3971119Sbill struct linkbuf *lp; 3981119Sbill int found = 0; 3991119Sbill 4001119Sbill for (lp = ihead; lp != NULL; lp = lp->nextp) { 4011119Sbill if (lp->inum == stbuf.st_ino && lp->devnum == stbuf.st_dev) { 4021119Sbill found++; 4031119Sbill break; 4041119Sbill } 4051119Sbill } 4061119Sbill if (found) { 4071119Sbill strcpy(dblock.dbuf.linkname, lp->pathname); 4081119Sbill dblock.dbuf.linkflag = '1'; 4091119Sbill sprintf(dblock.dbuf.chksum, "%6o", checksum()); 4101119Sbill writetape( (char *) &dblock); 4111119Sbill if (vflag) { 4121119Sbill fprintf(stderr, "a %s ", longname); 4131119Sbill fprintf(stderr, "link to %s\n", lp->pathname); 4141119Sbill } 4151119Sbill lp->count--; 4161119Sbill close(infile); 4171119Sbill return; 4181119Sbill } 4191119Sbill else { 4201119Sbill lp = (struct linkbuf *) malloc(sizeof(*lp)); 4211119Sbill if (lp == NULL) { 4221119Sbill if (freemem) { 4231119Sbill fprintf(stderr, "Out of memory. Link information lost\n"); 4241119Sbill freemem = 0; 4251119Sbill } 4261119Sbill } 4271119Sbill else { 4281119Sbill lp->nextp = ihead; 4291119Sbill ihead = lp; 4301119Sbill lp->inum = stbuf.st_ino; 4311119Sbill lp->devnum = stbuf.st_dev; 4321119Sbill lp->count = stbuf.st_nlink - 1; 4331119Sbill strcpy(lp->pathname, longname); 4341119Sbill } 4351119Sbill } 4361119Sbill } 4371119Sbill 4381119Sbill blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK; 4391119Sbill if (vflag) { 4401119Sbill fprintf(stderr, "a %s ", longname); 4411119Sbill fprintf(stderr, "%ld blocks\n", blocks); 4421119Sbill } 4431119Sbill sprintf(dblock.dbuf.chksum, "%6o", checksum()); 4441119Sbill writetape( (char *) &dblock); 4451119Sbill 4461119Sbill while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) { 4471119Sbill writetape(buf); 4481119Sbill blocks--; 4491119Sbill } 4501119Sbill close(infile); 4511119Sbill if (blocks != 0 || i != 0) 4521119Sbill fprintf(stderr, "%s: file changed size\n", longname); 4531119Sbill while (blocks-- > 0) 4541119Sbill putempty(); 4551119Sbill } 4561119Sbill 4571119Sbill 4581119Sbill 4591119Sbill doxtract(argv) 4601119Sbill char *argv[]; 4611119Sbill { 4621119Sbill long blocks, bytes; 4631119Sbill char buf[TBLOCK]; 4641119Sbill char **cp; 4651119Sbill int ofile; 4661119Sbill 4671119Sbill for (;;) { 4681119Sbill getdir(); 4691119Sbill if (endtape()) 4701119Sbill break; 4711119Sbill 4721119Sbill if (*argv == 0) 4731119Sbill goto gotit; 4741119Sbill 4751119Sbill for (cp = argv; *cp; cp++) 4761119Sbill if (prefix(*cp, dblock.dbuf.name)) 4771119Sbill goto gotit; 4781119Sbill passtape(); 4791119Sbill continue; 4801119Sbill 4811119Sbill gotit: 4821119Sbill if (checkw('x', dblock.dbuf.name) == 0) { 4831119Sbill passtape(); 4841119Sbill continue; 4851119Sbill } 4861119Sbill 4871119Sbill if(checkdir(dblock.dbuf.name)) 4881119Sbill continue; 4891119Sbill 4901119Sbill if (dblock.dbuf.linkflag == '1') { 4911119Sbill unlink(dblock.dbuf.name); 4921119Sbill if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) { 4931119Sbill fprintf(stderr, "%s: cannot link\n", dblock.dbuf.name); 4941119Sbill continue; 4951119Sbill } 4961119Sbill if (vflag) 4973457Swnj fprintf(stderr, "%s linked to %s\n", 4983457Swnj dblock.dbuf.name, dblock.dbuf.linkname); 4991119Sbill continue; 5001119Sbill } 5011119Sbill if ((ofile = creat(dblock.dbuf.name, stbuf.st_mode & 07777)) < 0) { 5021119Sbill fprintf(stderr, "tar: %s - cannot create\n", dblock.dbuf.name); 5031119Sbill passtape(); 5041119Sbill continue; 5051119Sbill } 5061926Swnj chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 5071119Sbill 5081119Sbill blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK; 5091119Sbill if (vflag) 5103457Swnj fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n", 5113457Swnj dblock.dbuf.name, bytes, blocks); 5121119Sbill while (blocks-- > 0) { 5131119Sbill readtape(buf); 5141119Sbill if (bytes > TBLOCK) { 5151119Sbill if (write(ofile, buf, TBLOCK) < 0) { 5161119Sbill fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name); 5171119Sbill done(2); 5181119Sbill } 5191119Sbill } else 5201119Sbill if (write(ofile, buf, (int) bytes) < 0) { 5211119Sbill fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name); 5221119Sbill done(2); 5231119Sbill } 5241119Sbill bytes -= TBLOCK; 5251119Sbill } 5261119Sbill close(ofile); 5271119Sbill if (mflag == 0) { 5281119Sbill time_t timep[2]; 5291119Sbill 5301119Sbill timep[0] = time(NULL); 5311119Sbill timep[1] = stbuf.st_mtime; 5321119Sbill utime(dblock.dbuf.name, timep); 5331119Sbill } 5341926Swnj if (pflag) 5351119Sbill chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 5361119Sbill } 5371119Sbill } 5381119Sbill 5391119Sbill dotable() 5401119Sbill { 5411119Sbill for (;;) { 5421119Sbill getdir(); 5431119Sbill if (endtape()) 5441119Sbill break; 5451119Sbill if (vflag) 5461119Sbill longt(&stbuf); 5471119Sbill printf("%s", dblock.dbuf.name); 5481119Sbill if (dblock.dbuf.linkflag == '1') 5491119Sbill printf(" linked to %s", dblock.dbuf.linkname); 5501119Sbill printf("\n"); 5511119Sbill passtape(); 5521119Sbill } 5531119Sbill } 5541119Sbill 5551119Sbill putempty() 5561119Sbill { 5571119Sbill char buf[TBLOCK]; 5581119Sbill char *cp; 5591119Sbill 5601119Sbill for (cp = buf; cp < &buf[TBLOCK]; ) 5611119Sbill *cp++ = '\0'; 5621119Sbill writetape(buf); 5631119Sbill } 5641119Sbill 5651119Sbill longt(st) 5661119Sbill register struct stat *st; 5671119Sbill { 5681119Sbill register char *cp; 5691119Sbill char *ctime(); 5701119Sbill 5711119Sbill pmode(st); 5721119Sbill printf("%3d/%1d", st->st_uid, st->st_gid); 5731119Sbill printf("%7D", st->st_size); 5741119Sbill cp = ctime(&st->st_mtime); 5751119Sbill printf(" %-12.12s %-4.4s ", cp+4, cp+20); 5761119Sbill } 5771119Sbill 5781119Sbill #define SUID 04000 5791119Sbill #define SGID 02000 5801119Sbill #define ROWN 0400 5811119Sbill #define WOWN 0200 5821119Sbill #define XOWN 0100 5831119Sbill #define RGRP 040 5841119Sbill #define WGRP 020 5851119Sbill #define XGRP 010 5861119Sbill #define ROTH 04 5871119Sbill #define WOTH 02 5881119Sbill #define XOTH 01 5891119Sbill #define STXT 01000 5901119Sbill int m1[] = { 1, ROWN, 'r', '-' }; 5911119Sbill int m2[] = { 1, WOWN, 'w', '-' }; 5921119Sbill int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 5931119Sbill int m4[] = { 1, RGRP, 'r', '-' }; 5941119Sbill int m5[] = { 1, WGRP, 'w', '-' }; 5951119Sbill int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 5961119Sbill int m7[] = { 1, ROTH, 'r', '-' }; 5971119Sbill int m8[] = { 1, WOTH, 'w', '-' }; 5981119Sbill int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 5991119Sbill 6001119Sbill int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 6011119Sbill 6021119Sbill pmode(st) 6031119Sbill register struct stat *st; 6041119Sbill { 6051119Sbill register int **mp; 6061119Sbill 6071119Sbill for (mp = &m[0]; mp < &m[9];) 6081119Sbill select(*mp++, st); 6091119Sbill } 6101119Sbill 6111119Sbill select(pairp, st) 6121119Sbill int *pairp; 6131119Sbill struct stat *st; 6141119Sbill { 6151119Sbill register int n, *ap; 6161119Sbill 6171119Sbill ap = pairp; 6181119Sbill n = *ap++; 6191119Sbill while (--n>=0 && (st->st_mode&*ap++)==0) 6201119Sbill ap++; 6211119Sbill printf("%c", *ap); 6221119Sbill } 6231119Sbill 6241119Sbill checkdir(name) 6251119Sbill register char *name; 6261119Sbill { 6271119Sbill register char *cp; 6281119Sbill int i; 6291119Sbill for (cp = name; *cp; cp++) { 6301119Sbill if (*cp == '/') { 6311119Sbill *cp = '\0'; 6321119Sbill if (access(name, 01) < 0) { 6331119Sbill register int pid, rp; 6341119Sbill 6351119Sbill if ((pid = fork()) == 0) { 6361119Sbill execl("/bin/mkdir", "mkdir", name, 0); 6371119Sbill execl("/usr/bin/mkdir", "mkdir", name, 0); 6381119Sbill fprintf(stderr, "tar: cannot find mkdir!\n"); 6391119Sbill done(0); 6401119Sbill } 6411119Sbill while ((rp = wait(&i)) >= 0 && rp != pid) 6421119Sbill ; 6431926Swnj chown(name, stbuf.st_uid, stbuf.st_gid); 6441926Swnj if (pflag) 6451926Swnj chmod(dblock.dbuf.name, 6461926Swnj stbuf.st_mode & 0777); 6471119Sbill } 6481119Sbill *cp = '/'; 6491119Sbill } 6501119Sbill } 6511119Sbill return(cp[-1]=='/'); 6521119Sbill } 6531119Sbill 6541119Sbill onintr() 6551119Sbill { 6561119Sbill signal(SIGINT, SIG_IGN); 6571119Sbill term++; 6581119Sbill } 6591119Sbill 6601119Sbill onquit() 6611119Sbill { 6621119Sbill signal(SIGQUIT, SIG_IGN); 6631119Sbill term++; 6641119Sbill } 6651119Sbill 6661119Sbill onhup() 6671119Sbill { 6681119Sbill signal(SIGHUP, SIG_IGN); 6691119Sbill term++; 6701119Sbill } 6711119Sbill 6721119Sbill onterm() 6731119Sbill { 6741119Sbill signal(SIGTERM, SIG_IGN); 6751119Sbill term++; 6761119Sbill } 6771119Sbill 6781119Sbill tomodes(sp) 6791119Sbill register struct stat *sp; 6801119Sbill { 6811119Sbill register char *cp; 6821119Sbill 6831119Sbill for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 6841119Sbill *cp = '\0'; 6851119Sbill sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); 6861119Sbill sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); 6871119Sbill sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); 6881119Sbill sprintf(dblock.dbuf.size, "%11lo ", sp->st_size); 6891119Sbill sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime); 6901119Sbill } 6911119Sbill 6921119Sbill checksum() 6931119Sbill { 6941119Sbill register i; 6951119Sbill register char *cp; 6961119Sbill 6971119Sbill for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++) 6981119Sbill *cp = ' '; 6991119Sbill i = 0; 7001119Sbill for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 7011119Sbill i += *cp; 7021119Sbill return(i); 7031119Sbill } 7041119Sbill 7051119Sbill checkw(c, name) 7061119Sbill char *name; 7071119Sbill { 7081119Sbill if (wflag) { 7091119Sbill printf("%c ", c); 7101119Sbill if (vflag) 7111119Sbill longt(&stbuf); 7121119Sbill printf("%s: ", name); 7131119Sbill if (response() == 'y'){ 7141119Sbill return(1); 7151119Sbill } 7161119Sbill return(0); 7171119Sbill } 7181119Sbill return(1); 7191119Sbill } 7201119Sbill 7211119Sbill response() 7221119Sbill { 7231119Sbill char c; 7241119Sbill 7251119Sbill c = getchar(); 7261119Sbill if (c != '\n') 7271119Sbill while (getchar() != '\n'); 7281119Sbill else c = 'n'; 7291119Sbill return(c); 7301119Sbill } 7311119Sbill 7321119Sbill checkupdate(arg) 7331119Sbill char *arg; 7341119Sbill { 7351119Sbill char name[100]; 7361119Sbill long mtime; 7371119Sbill daddr_t seekp; 7381119Sbill daddr_t lookup(); 7391119Sbill 7401119Sbill rewind(tfile); 7411119Sbill for (;;) { 7421119Sbill if ((seekp = lookup(arg)) < 0) 7431119Sbill return(1); 7441119Sbill fseek(tfile, seekp, 0); 7451119Sbill fscanf(tfile, "%s %lo", name, &mtime); 7461119Sbill if (stbuf.st_mtime > mtime) 7471119Sbill return(1); 7481119Sbill else 7491119Sbill return(0); 7501119Sbill } 7511119Sbill } 7521119Sbill 7531119Sbill done(n) 7541119Sbill { 7551119Sbill unlink(tname); 7561119Sbill exit(n); 7571119Sbill } 7581119Sbill 7591119Sbill prefix(s1, s2) 7601119Sbill register char *s1, *s2; 7611119Sbill { 7621119Sbill while (*s1) 7631119Sbill if (*s1++ != *s2++) 7641119Sbill return(0); 7651119Sbill if (*s2) 7661119Sbill return(*s2 == '/'); 7671119Sbill return(1); 7681119Sbill } 7691119Sbill 7701119Sbill getwdir(s) 7711119Sbill char *s; 7721119Sbill { 7731119Sbill int i; 7741119Sbill int pipdes[2]; 7751119Sbill 7761119Sbill pipe(pipdes); 7771119Sbill if ((i = fork()) == 0) { 7781119Sbill close(1); 7791119Sbill dup(pipdes[1]); 7801119Sbill execl("/bin/pwd", "pwd", 0); 7811119Sbill execl("/usr/bin/pwd", "pwd", 0); 7821119Sbill fprintf(stderr, "pwd failed!\n"); 7831119Sbill printf("/\n"); 7841119Sbill exit(1); 7851119Sbill } 7861119Sbill while (wait((int *)NULL) != -1) 7871119Sbill ; 7881119Sbill read(pipdes[0], s, 50); 7891119Sbill while(*s != '\n') 7901119Sbill s++; 7911119Sbill *s = '\0'; 7921119Sbill close(pipdes[0]); 7931119Sbill close(pipdes[1]); 7941119Sbill } 7951119Sbill 7961119Sbill #define N 200 7971119Sbill int njab; 7981119Sbill daddr_t 7991119Sbill lookup(s) 8001119Sbill char *s; 8011119Sbill { 8021119Sbill register i; 8031119Sbill daddr_t a; 8041119Sbill 8051119Sbill for(i=0; s[i]; i++) 8061119Sbill if(s[i] == ' ') 8071119Sbill break; 8081119Sbill a = bsrch(s, i, low, high); 8091119Sbill return(a); 8101119Sbill } 8111119Sbill 8121119Sbill daddr_t 8131119Sbill bsrch(s, n, l, h) 8141119Sbill daddr_t l, h; 8151119Sbill char *s; 8161119Sbill { 8171119Sbill register i, j; 8181119Sbill char b[N]; 8191119Sbill daddr_t m, m1; 8201119Sbill 8211119Sbill njab = 0; 8221119Sbill 8231119Sbill loop: 8241119Sbill if(l >= h) 8251119Sbill return(-1L); 8261119Sbill m = l + (h-l)/2 - N/2; 8271119Sbill if(m < l) 8281119Sbill m = l; 8291119Sbill fseek(tfile, m, 0); 8301119Sbill fread(b, 1, N, tfile); 8311119Sbill njab++; 8321119Sbill for(i=0; i<N; i++) { 8331119Sbill if(b[i] == '\n') 8341119Sbill break; 8351119Sbill m++; 8361119Sbill } 8371119Sbill if(m >= h) 8381119Sbill return(-1L); 8391119Sbill m1 = m; 8401119Sbill j = i; 8411119Sbill for(i++; i<N; i++) { 8421119Sbill m1++; 8431119Sbill if(b[i] == '\n') 8441119Sbill break; 8451119Sbill } 8461119Sbill i = cmp(b+j, s, n); 8471119Sbill if(i < 0) { 8481119Sbill h = m; 8491119Sbill goto loop; 8501119Sbill } 8511119Sbill if(i > 0) { 8521119Sbill l = m1; 8531119Sbill goto loop; 8541119Sbill } 8551119Sbill return(m); 8561119Sbill } 8571119Sbill 8581119Sbill cmp(b, s, n) 8591119Sbill char *b, *s; 8601119Sbill { 8611119Sbill register i; 8621119Sbill 8631119Sbill if(b[0] != '\n') 8641119Sbill exit(2); 8651119Sbill for(i=0; i<n; i++) { 8661119Sbill if(b[i+1] > s[i]) 8671119Sbill return(-1); 8681119Sbill if(b[i+1] < s[i]) 8691119Sbill return(1); 8701119Sbill } 8711119Sbill return(b[i+1] == ' '? 0 : -1); 8721119Sbill } 8731119Sbill 8741119Sbill readtape(buffer) 8751119Sbill char *buffer; 8761119Sbill { 8773457Swnj register int i; 8781119Sbill 8791119Sbill if (recno >= nblock || first == 0) { 8803457Swnj if ((i = read(mt, tbuf, TBLOCK*nblock)) < 0) { 8811119Sbill fprintf(stderr, "Tar: tape read error\n"); 8821119Sbill done(3); 8831119Sbill } 8841119Sbill if (first == 0) { 8851119Sbill if ((i % TBLOCK) != 0) { 8861119Sbill fprintf(stderr, "Tar: tape blocksize error\n"); 8871119Sbill done(3); 8881119Sbill } 8891119Sbill i /= TBLOCK; 8903457Swnj if (i != nblock) { 8911119Sbill fprintf(stderr, "Tar: blocksize = %d\n", i); 8921119Sbill nblock = i; 8931119Sbill } 8941119Sbill } 8951119Sbill recno = 0; 8961119Sbill } 8971119Sbill first = 1; 8981119Sbill copy(buffer, &tbuf[recno++]); 8991119Sbill return(TBLOCK); 9001119Sbill } 9011119Sbill 9021119Sbill writetape(buffer) 9031119Sbill char *buffer; 9041119Sbill { 9051119Sbill first = 1; 9061119Sbill if (recno >= nblock) { 9071119Sbill if (write(mt, tbuf, TBLOCK*nblock) < 0) { 9081119Sbill fprintf(stderr, "Tar: tape write error\n"); 9091119Sbill done(2); 9101119Sbill } 9111119Sbill recno = 0; 9121119Sbill } 9131119Sbill copy(&tbuf[recno++], buffer); 9141119Sbill if (recno >= nblock) { 9151119Sbill if (write(mt, tbuf, TBLOCK*nblock) < 0) { 9161119Sbill fprintf(stderr, "Tar: tape write error\n"); 9171119Sbill done(2); 9181119Sbill } 9191119Sbill recno = 0; 9201119Sbill } 9211119Sbill return(TBLOCK); 9221119Sbill } 9231119Sbill 9241119Sbill backtape() 9251119Sbill { 9263457Swnj static int mtdev = 1; 9273457Swnj static struct mtop mtop = {MTBSR, 1}; 9283457Swnj struct mtget mtget; 9293457Swnj 9303457Swnj if (mtdev == 1) 9313457Swnj mtdev = ioctl(mt, MTIOCGET, &mtget); 9323457Swnj if (mtdev == 0) { 9333457Swnj if (ioctl(mt, MTIOCTOP, &mtop) < 0) { 9343457Swnj fprintf(stderr, "Tar: tape backspace error\n"); 9351119Sbill done(4); 9361119Sbill } 9373457Swnj } else 9383457Swnj lseek(mt, (long) -TBLOCK*nblock, 1); 9393457Swnj recno--; 9401119Sbill } 9411119Sbill 9421119Sbill flushtape() 9431119Sbill { 9441119Sbill write(mt, tbuf, TBLOCK*nblock); 9451119Sbill } 9461119Sbill 9471119Sbill copy(to, from) 9481119Sbill register char *to, *from; 9491119Sbill { 9501119Sbill register i; 9511119Sbill 9521119Sbill i = TBLOCK; 9531119Sbill do { 9541119Sbill *to++ = *from++; 9551119Sbill } while (--i); 9561119Sbill } 957