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