1*3457Swnj static char *sccsid = "@(#)tar.c 4.3 (Berkeley) 03/31/81"; 21119Sbill #include <stdio.h> 31119Sbill #include <sys/types.h> 41119Sbill #include <sys/stat.h> 51119Sbill #include <sys/dir.h> 6*3457Swnj #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; 43*3457Swnj 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 220*3457Swnj 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; 3221119Sbill struct direct dbuf; 3231119Sbill int i, j; 3241119Sbill 3251119Sbill infile = open(shortname, 0); 3261119Sbill if (infile < 0) { 3271119Sbill fprintf(stderr, "tar: %s: cannot open file\n", longname); 3281119Sbill return; 3291119Sbill } 3301119Sbill 3311119Sbill fstat(infile, &stbuf); 3321119Sbill 3331119Sbill if (tfile != NULL && checkupdate(longname) == 0) { 3341119Sbill close(infile); 3351119Sbill return; 3361119Sbill } 3371119Sbill if (checkw('r', longname) == 0) { 3381119Sbill close(infile); 3391119Sbill return; 3401119Sbill } 3411119Sbill 3421119Sbill if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 3431119Sbill for (i = 0, cp = buf; *cp++ = longname[i++];); 3441119Sbill *--cp = '/'; 3451119Sbill *++cp = 0 ; 3461119Sbill i = 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); 3601119Sbill while (read(infile, (char *)&dbuf, sizeof(dbuf)) > 0 && !term) { 3611119Sbill if (dbuf.d_ino == 0) { 3621119Sbill i++; 3631119Sbill continue; 3641119Sbill } 3651119Sbill if (strcmp(".", dbuf.d_name) == 0 || strcmp("..", dbuf.d_name) == 0) { 3661119Sbill i++; 3671119Sbill continue; 3681119Sbill } 3691119Sbill cp2 = cp; 3701119Sbill for (j=0; j < DIRSIZ; j++) 3711119Sbill *cp2++ = dbuf.d_name[j]; 3721119Sbill *cp2 = '\0'; 3731119Sbill close(infile); 3741119Sbill putfile(buf, cp); 3751119Sbill infile = open(".", 0); 3761119Sbill i++; 3771119Sbill lseek(infile, (long) (sizeof(dbuf) * i), 0); 3781119Sbill } 3791119Sbill close(infile); 3801119Sbill chdir(".."); 3811119Sbill return; 3821119Sbill } 3831119Sbill if ((stbuf.st_mode & S_IFMT) != S_IFREG) { 3841119Sbill fprintf(stderr, "tar: %s is not a file. Not dumped\n", longname); 3851119Sbill return; 3861119Sbill } 3871119Sbill 3881119Sbill tomodes(&stbuf); 3891119Sbill 3901119Sbill cp2 = longname; 3911119Sbill for (cp = dblock.dbuf.name, i=0; (*cp++ = *cp2++) && i < NAMSIZ; i++); 3921119Sbill if (i >= NAMSIZ) { 3931119Sbill fprintf(stderr, "%s: file name too long\n", longname); 3941119Sbill close(infile); 3951119Sbill return; 3961119Sbill } 3971119Sbill 3981119Sbill if (stbuf.st_nlink > 1) { 3991119Sbill struct linkbuf *lp; 4001119Sbill int found = 0; 4011119Sbill 4021119Sbill for (lp = ihead; lp != NULL; lp = lp->nextp) { 4031119Sbill if (lp->inum == stbuf.st_ino && lp->devnum == stbuf.st_dev) { 4041119Sbill found++; 4051119Sbill break; 4061119Sbill } 4071119Sbill } 4081119Sbill if (found) { 4091119Sbill strcpy(dblock.dbuf.linkname, lp->pathname); 4101119Sbill dblock.dbuf.linkflag = '1'; 4111119Sbill sprintf(dblock.dbuf.chksum, "%6o", checksum()); 4121119Sbill writetape( (char *) &dblock); 4131119Sbill if (vflag) { 4141119Sbill fprintf(stderr, "a %s ", longname); 4151119Sbill fprintf(stderr, "link to %s\n", lp->pathname); 4161119Sbill } 4171119Sbill lp->count--; 4181119Sbill close(infile); 4191119Sbill return; 4201119Sbill } 4211119Sbill else { 4221119Sbill lp = (struct linkbuf *) malloc(sizeof(*lp)); 4231119Sbill if (lp == NULL) { 4241119Sbill if (freemem) { 4251119Sbill fprintf(stderr, "Out of memory. Link information lost\n"); 4261119Sbill freemem = 0; 4271119Sbill } 4281119Sbill } 4291119Sbill else { 4301119Sbill lp->nextp = ihead; 4311119Sbill ihead = lp; 4321119Sbill lp->inum = stbuf.st_ino; 4331119Sbill lp->devnum = stbuf.st_dev; 4341119Sbill lp->count = stbuf.st_nlink - 1; 4351119Sbill strcpy(lp->pathname, longname); 4361119Sbill } 4371119Sbill } 4381119Sbill } 4391119Sbill 4401119Sbill blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK; 4411119Sbill if (vflag) { 4421119Sbill fprintf(stderr, "a %s ", longname); 4431119Sbill fprintf(stderr, "%ld blocks\n", blocks); 4441119Sbill } 4451119Sbill sprintf(dblock.dbuf.chksum, "%6o", checksum()); 4461119Sbill writetape( (char *) &dblock); 4471119Sbill 4481119Sbill while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) { 4491119Sbill writetape(buf); 4501119Sbill blocks--; 4511119Sbill } 4521119Sbill close(infile); 4531119Sbill if (blocks != 0 || i != 0) 4541119Sbill fprintf(stderr, "%s: file changed size\n", longname); 4551119Sbill while (blocks-- > 0) 4561119Sbill putempty(); 4571119Sbill } 4581119Sbill 4591119Sbill 4601119Sbill 4611119Sbill doxtract(argv) 4621119Sbill char *argv[]; 4631119Sbill { 4641119Sbill long blocks, bytes; 4651119Sbill char buf[TBLOCK]; 4661119Sbill char **cp; 4671119Sbill int ofile; 4681119Sbill 4691119Sbill for (;;) { 4701119Sbill getdir(); 4711119Sbill if (endtape()) 4721119Sbill break; 4731119Sbill 4741119Sbill if (*argv == 0) 4751119Sbill goto gotit; 4761119Sbill 4771119Sbill for (cp = argv; *cp; cp++) 4781119Sbill if (prefix(*cp, dblock.dbuf.name)) 4791119Sbill goto gotit; 4801119Sbill passtape(); 4811119Sbill continue; 4821119Sbill 4831119Sbill gotit: 4841119Sbill if (checkw('x', dblock.dbuf.name) == 0) { 4851119Sbill passtape(); 4861119Sbill continue; 4871119Sbill } 4881119Sbill 4891119Sbill if(checkdir(dblock.dbuf.name)) 4901119Sbill continue; 4911119Sbill 4921119Sbill if (dblock.dbuf.linkflag == '1') { 4931119Sbill unlink(dblock.dbuf.name); 4941119Sbill if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) { 4951119Sbill fprintf(stderr, "%s: cannot link\n", dblock.dbuf.name); 4961119Sbill continue; 4971119Sbill } 4981119Sbill if (vflag) 499*3457Swnj fprintf(stderr, "%s linked to %s\n", 500*3457Swnj dblock.dbuf.name, dblock.dbuf.linkname); 5011119Sbill continue; 5021119Sbill } 5031119Sbill if ((ofile = creat(dblock.dbuf.name, stbuf.st_mode & 07777)) < 0) { 5041119Sbill fprintf(stderr, "tar: %s - cannot create\n", dblock.dbuf.name); 5051119Sbill passtape(); 5061119Sbill continue; 5071119Sbill } 5081926Swnj chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 5091119Sbill 5101119Sbill blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK; 5111119Sbill if (vflag) 512*3457Swnj fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n", 513*3457Swnj dblock.dbuf.name, bytes, blocks); 5141119Sbill while (blocks-- > 0) { 5151119Sbill readtape(buf); 5161119Sbill if (bytes > TBLOCK) { 5171119Sbill if (write(ofile, buf, TBLOCK) < 0) { 5181119Sbill fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name); 5191119Sbill done(2); 5201119Sbill } 5211119Sbill } else 5221119Sbill if (write(ofile, buf, (int) bytes) < 0) { 5231119Sbill fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name); 5241119Sbill done(2); 5251119Sbill } 5261119Sbill bytes -= TBLOCK; 5271119Sbill } 5281119Sbill close(ofile); 5291119Sbill if (mflag == 0) { 5301119Sbill time_t timep[2]; 5311119Sbill 5321119Sbill timep[0] = time(NULL); 5331119Sbill timep[1] = stbuf.st_mtime; 5341119Sbill utime(dblock.dbuf.name, timep); 5351119Sbill } 5361926Swnj if (pflag) 5371119Sbill chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 5381119Sbill } 5391119Sbill } 5401119Sbill 5411119Sbill dotable() 5421119Sbill { 5431119Sbill for (;;) { 5441119Sbill getdir(); 5451119Sbill if (endtape()) 5461119Sbill break; 5471119Sbill if (vflag) 5481119Sbill longt(&stbuf); 5491119Sbill printf("%s", dblock.dbuf.name); 5501119Sbill if (dblock.dbuf.linkflag == '1') 5511119Sbill printf(" linked to %s", dblock.dbuf.linkname); 5521119Sbill printf("\n"); 5531119Sbill passtape(); 5541119Sbill } 5551119Sbill } 5561119Sbill 5571119Sbill putempty() 5581119Sbill { 5591119Sbill char buf[TBLOCK]; 5601119Sbill char *cp; 5611119Sbill 5621119Sbill for (cp = buf; cp < &buf[TBLOCK]; ) 5631119Sbill *cp++ = '\0'; 5641119Sbill writetape(buf); 5651119Sbill } 5661119Sbill 5671119Sbill longt(st) 5681119Sbill register struct stat *st; 5691119Sbill { 5701119Sbill register char *cp; 5711119Sbill char *ctime(); 5721119Sbill 5731119Sbill pmode(st); 5741119Sbill printf("%3d/%1d", st->st_uid, st->st_gid); 5751119Sbill printf("%7D", st->st_size); 5761119Sbill cp = ctime(&st->st_mtime); 5771119Sbill printf(" %-12.12s %-4.4s ", cp+4, cp+20); 5781119Sbill } 5791119Sbill 5801119Sbill #define SUID 04000 5811119Sbill #define SGID 02000 5821119Sbill #define ROWN 0400 5831119Sbill #define WOWN 0200 5841119Sbill #define XOWN 0100 5851119Sbill #define RGRP 040 5861119Sbill #define WGRP 020 5871119Sbill #define XGRP 010 5881119Sbill #define ROTH 04 5891119Sbill #define WOTH 02 5901119Sbill #define XOTH 01 5911119Sbill #define STXT 01000 5921119Sbill int m1[] = { 1, ROWN, 'r', '-' }; 5931119Sbill int m2[] = { 1, WOWN, 'w', '-' }; 5941119Sbill int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 5951119Sbill int m4[] = { 1, RGRP, 'r', '-' }; 5961119Sbill int m5[] = { 1, WGRP, 'w', '-' }; 5971119Sbill int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 5981119Sbill int m7[] = { 1, ROTH, 'r', '-' }; 5991119Sbill int m8[] = { 1, WOTH, 'w', '-' }; 6001119Sbill int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 6011119Sbill 6021119Sbill int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 6031119Sbill 6041119Sbill pmode(st) 6051119Sbill register struct stat *st; 6061119Sbill { 6071119Sbill register int **mp; 6081119Sbill 6091119Sbill for (mp = &m[0]; mp < &m[9];) 6101119Sbill select(*mp++, st); 6111119Sbill } 6121119Sbill 6131119Sbill select(pairp, st) 6141119Sbill int *pairp; 6151119Sbill struct stat *st; 6161119Sbill { 6171119Sbill register int n, *ap; 6181119Sbill 6191119Sbill ap = pairp; 6201119Sbill n = *ap++; 6211119Sbill while (--n>=0 && (st->st_mode&*ap++)==0) 6221119Sbill ap++; 6231119Sbill printf("%c", *ap); 6241119Sbill } 6251119Sbill 6261119Sbill checkdir(name) 6271119Sbill register char *name; 6281119Sbill { 6291119Sbill register char *cp; 6301119Sbill int i; 6311119Sbill for (cp = name; *cp; cp++) { 6321119Sbill if (*cp == '/') { 6331119Sbill *cp = '\0'; 6341119Sbill if (access(name, 01) < 0) { 6351119Sbill register int pid, rp; 6361119Sbill 6371119Sbill if ((pid = fork()) == 0) { 6381119Sbill execl("/bin/mkdir", "mkdir", name, 0); 6391119Sbill execl("/usr/bin/mkdir", "mkdir", name, 0); 6401119Sbill fprintf(stderr, "tar: cannot find mkdir!\n"); 6411119Sbill done(0); 6421119Sbill } 6431119Sbill while ((rp = wait(&i)) >= 0 && rp != pid) 6441119Sbill ; 6451926Swnj chown(name, stbuf.st_uid, stbuf.st_gid); 6461926Swnj if (pflag) 6471926Swnj chmod(dblock.dbuf.name, 6481926Swnj stbuf.st_mode & 0777); 6491119Sbill } 6501119Sbill *cp = '/'; 6511119Sbill } 6521119Sbill } 6531119Sbill return(cp[-1]=='/'); 6541119Sbill } 6551119Sbill 6561119Sbill onintr() 6571119Sbill { 6581119Sbill signal(SIGINT, SIG_IGN); 6591119Sbill term++; 6601119Sbill } 6611119Sbill 6621119Sbill onquit() 6631119Sbill { 6641119Sbill signal(SIGQUIT, SIG_IGN); 6651119Sbill term++; 6661119Sbill } 6671119Sbill 6681119Sbill onhup() 6691119Sbill { 6701119Sbill signal(SIGHUP, SIG_IGN); 6711119Sbill term++; 6721119Sbill } 6731119Sbill 6741119Sbill onterm() 6751119Sbill { 6761119Sbill signal(SIGTERM, SIG_IGN); 6771119Sbill term++; 6781119Sbill } 6791119Sbill 6801119Sbill tomodes(sp) 6811119Sbill register struct stat *sp; 6821119Sbill { 6831119Sbill register char *cp; 6841119Sbill 6851119Sbill for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 6861119Sbill *cp = '\0'; 6871119Sbill sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); 6881119Sbill sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); 6891119Sbill sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); 6901119Sbill sprintf(dblock.dbuf.size, "%11lo ", sp->st_size); 6911119Sbill sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime); 6921119Sbill } 6931119Sbill 6941119Sbill checksum() 6951119Sbill { 6961119Sbill register i; 6971119Sbill register char *cp; 6981119Sbill 6991119Sbill for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++) 7001119Sbill *cp = ' '; 7011119Sbill i = 0; 7021119Sbill for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 7031119Sbill i += *cp; 7041119Sbill return(i); 7051119Sbill } 7061119Sbill 7071119Sbill checkw(c, name) 7081119Sbill char *name; 7091119Sbill { 7101119Sbill if (wflag) { 7111119Sbill printf("%c ", c); 7121119Sbill if (vflag) 7131119Sbill longt(&stbuf); 7141119Sbill printf("%s: ", name); 7151119Sbill if (response() == 'y'){ 7161119Sbill return(1); 7171119Sbill } 7181119Sbill return(0); 7191119Sbill } 7201119Sbill return(1); 7211119Sbill } 7221119Sbill 7231119Sbill response() 7241119Sbill { 7251119Sbill char c; 7261119Sbill 7271119Sbill c = getchar(); 7281119Sbill if (c != '\n') 7291119Sbill while (getchar() != '\n'); 7301119Sbill else c = 'n'; 7311119Sbill return(c); 7321119Sbill } 7331119Sbill 7341119Sbill checkupdate(arg) 7351119Sbill char *arg; 7361119Sbill { 7371119Sbill char name[100]; 7381119Sbill long mtime; 7391119Sbill daddr_t seekp; 7401119Sbill daddr_t lookup(); 7411119Sbill 7421119Sbill rewind(tfile); 7431119Sbill for (;;) { 7441119Sbill if ((seekp = lookup(arg)) < 0) 7451119Sbill return(1); 7461119Sbill fseek(tfile, seekp, 0); 7471119Sbill fscanf(tfile, "%s %lo", name, &mtime); 7481119Sbill if (stbuf.st_mtime > mtime) 7491119Sbill return(1); 7501119Sbill else 7511119Sbill return(0); 7521119Sbill } 7531119Sbill } 7541119Sbill 7551119Sbill done(n) 7561119Sbill { 7571119Sbill unlink(tname); 7581119Sbill exit(n); 7591119Sbill } 7601119Sbill 7611119Sbill prefix(s1, s2) 7621119Sbill register char *s1, *s2; 7631119Sbill { 7641119Sbill while (*s1) 7651119Sbill if (*s1++ != *s2++) 7661119Sbill return(0); 7671119Sbill if (*s2) 7681119Sbill return(*s2 == '/'); 7691119Sbill return(1); 7701119Sbill } 7711119Sbill 7721119Sbill getwdir(s) 7731119Sbill char *s; 7741119Sbill { 7751119Sbill int i; 7761119Sbill int pipdes[2]; 7771119Sbill 7781119Sbill pipe(pipdes); 7791119Sbill if ((i = fork()) == 0) { 7801119Sbill close(1); 7811119Sbill dup(pipdes[1]); 7821119Sbill execl("/bin/pwd", "pwd", 0); 7831119Sbill execl("/usr/bin/pwd", "pwd", 0); 7841119Sbill fprintf(stderr, "pwd failed!\n"); 7851119Sbill printf("/\n"); 7861119Sbill exit(1); 7871119Sbill } 7881119Sbill while (wait((int *)NULL) != -1) 7891119Sbill ; 7901119Sbill read(pipdes[0], s, 50); 7911119Sbill while(*s != '\n') 7921119Sbill s++; 7931119Sbill *s = '\0'; 7941119Sbill close(pipdes[0]); 7951119Sbill close(pipdes[1]); 7961119Sbill } 7971119Sbill 7981119Sbill #define N 200 7991119Sbill int njab; 8001119Sbill daddr_t 8011119Sbill lookup(s) 8021119Sbill char *s; 8031119Sbill { 8041119Sbill register i; 8051119Sbill daddr_t a; 8061119Sbill 8071119Sbill for(i=0; s[i]; i++) 8081119Sbill if(s[i] == ' ') 8091119Sbill break; 8101119Sbill a = bsrch(s, i, low, high); 8111119Sbill return(a); 8121119Sbill } 8131119Sbill 8141119Sbill daddr_t 8151119Sbill bsrch(s, n, l, h) 8161119Sbill daddr_t l, h; 8171119Sbill char *s; 8181119Sbill { 8191119Sbill register i, j; 8201119Sbill char b[N]; 8211119Sbill daddr_t m, m1; 8221119Sbill 8231119Sbill njab = 0; 8241119Sbill 8251119Sbill loop: 8261119Sbill if(l >= h) 8271119Sbill return(-1L); 8281119Sbill m = l + (h-l)/2 - N/2; 8291119Sbill if(m < l) 8301119Sbill m = l; 8311119Sbill fseek(tfile, m, 0); 8321119Sbill fread(b, 1, N, tfile); 8331119Sbill njab++; 8341119Sbill for(i=0; i<N; i++) { 8351119Sbill if(b[i] == '\n') 8361119Sbill break; 8371119Sbill m++; 8381119Sbill } 8391119Sbill if(m >= h) 8401119Sbill return(-1L); 8411119Sbill m1 = m; 8421119Sbill j = i; 8431119Sbill for(i++; i<N; i++) { 8441119Sbill m1++; 8451119Sbill if(b[i] == '\n') 8461119Sbill break; 8471119Sbill } 8481119Sbill i = cmp(b+j, s, n); 8491119Sbill if(i < 0) { 8501119Sbill h = m; 8511119Sbill goto loop; 8521119Sbill } 8531119Sbill if(i > 0) { 8541119Sbill l = m1; 8551119Sbill goto loop; 8561119Sbill } 8571119Sbill return(m); 8581119Sbill } 8591119Sbill 8601119Sbill cmp(b, s, n) 8611119Sbill char *b, *s; 8621119Sbill { 8631119Sbill register i; 8641119Sbill 8651119Sbill if(b[0] != '\n') 8661119Sbill exit(2); 8671119Sbill for(i=0; i<n; i++) { 8681119Sbill if(b[i+1] > s[i]) 8691119Sbill return(-1); 8701119Sbill if(b[i+1] < s[i]) 8711119Sbill return(1); 8721119Sbill } 8731119Sbill return(b[i+1] == ' '? 0 : -1); 8741119Sbill } 8751119Sbill 8761119Sbill readtape(buffer) 8771119Sbill char *buffer; 8781119Sbill { 879*3457Swnj register int i; 8801119Sbill 8811119Sbill if (recno >= nblock || first == 0) { 882*3457Swnj if ((i = read(mt, tbuf, TBLOCK*nblock)) < 0) { 8831119Sbill fprintf(stderr, "Tar: tape read error\n"); 8841119Sbill done(3); 8851119Sbill } 8861119Sbill if (first == 0) { 8871119Sbill if ((i % TBLOCK) != 0) { 8881119Sbill fprintf(stderr, "Tar: tape blocksize error\n"); 8891119Sbill done(3); 8901119Sbill } 8911119Sbill i /= TBLOCK; 892*3457Swnj if (i != nblock) { 8931119Sbill fprintf(stderr, "Tar: blocksize = %d\n", i); 8941119Sbill nblock = i; 8951119Sbill } 8961119Sbill } 8971119Sbill recno = 0; 8981119Sbill } 8991119Sbill first = 1; 9001119Sbill copy(buffer, &tbuf[recno++]); 9011119Sbill return(TBLOCK); 9021119Sbill } 9031119Sbill 9041119Sbill writetape(buffer) 9051119Sbill char *buffer; 9061119Sbill { 9071119Sbill first = 1; 9081119Sbill if (recno >= nblock) { 9091119Sbill if (write(mt, tbuf, TBLOCK*nblock) < 0) { 9101119Sbill fprintf(stderr, "Tar: tape write error\n"); 9111119Sbill done(2); 9121119Sbill } 9131119Sbill recno = 0; 9141119Sbill } 9151119Sbill copy(&tbuf[recno++], buffer); 9161119Sbill if (recno >= nblock) { 9171119Sbill if (write(mt, tbuf, TBLOCK*nblock) < 0) { 9181119Sbill fprintf(stderr, "Tar: tape write error\n"); 9191119Sbill done(2); 9201119Sbill } 9211119Sbill recno = 0; 9221119Sbill } 9231119Sbill return(TBLOCK); 9241119Sbill } 9251119Sbill 9261119Sbill backtape() 9271119Sbill { 928*3457Swnj static int mtdev = 1; 929*3457Swnj static struct mtop mtop = {MTBSR, 1}; 930*3457Swnj struct mtget mtget; 931*3457Swnj 932*3457Swnj if (mtdev == 1) 933*3457Swnj mtdev = ioctl(mt, MTIOCGET, &mtget); 934*3457Swnj if (mtdev == 0) { 935*3457Swnj if (ioctl(mt, MTIOCTOP, &mtop) < 0) { 936*3457Swnj fprintf(stderr, "Tar: tape backspace error\n"); 9371119Sbill done(4); 9381119Sbill } 939*3457Swnj } else 940*3457Swnj lseek(mt, (long) -TBLOCK*nblock, 1); 941*3457Swnj recno--; 9421119Sbill } 9431119Sbill 9441119Sbill flushtape() 9451119Sbill { 9461119Sbill write(mt, tbuf, TBLOCK*nblock); 9471119Sbill } 9481119Sbill 9491119Sbill copy(to, from) 9501119Sbill register char *to, *from; 9511119Sbill { 9521119Sbill register i; 9531119Sbill 9541119Sbill i = TBLOCK; 9551119Sbill do { 9561119Sbill *to++ = *from++; 9571119Sbill } while (--i); 9581119Sbill } 959