112154Ssam #ifndef lint 2*22353Skjd static char *sccsid = "@(#)tar.c 4.23 (Berkeley) 06/05/85"; 312154Ssam #endif 46250Sroot 56250Sroot /* 66250Sroot * Tape Archival Program 76250Sroot */ 81119Sbill #include <stdio.h> 96413Smckusic #include <sys/param.h> 101119Sbill #include <sys/stat.h> 1112154Ssam #include <sys/dir.h> 128150Smckusick #include <sys/ioctl.h> 133457Swnj #include <sys/mtio.h> 1412983Ssam #include <sys/time.h> 151119Sbill #include <signal.h> 1612154Ssam #include <errno.h> 171119Sbill 181119Sbill #define TBLOCK 512 193355Swnj #define NBLOCK 20 201119Sbill #define NAMSIZ 100 21*22353Skjd #define FILEBLOCK 20 226250Sroot 2321457Skjd #define writetape(b) writetbuf(b, 1) 2421457Skjd #define min(a,b) ((a) < (b) ? (a) : (b)) 2521457Skjd #define max(a,b) ((a) > (b) ? (a) : (b)) 2621457Skjd 271119Sbill union hblock { 281119Sbill char dummy[TBLOCK]; 291119Sbill struct header { 301119Sbill char name[NAMSIZ]; 311119Sbill char mode[8]; 321119Sbill char uid[8]; 331119Sbill char gid[8]; 341119Sbill char size[12]; 351119Sbill char mtime[12]; 361119Sbill char chksum[8]; 371119Sbill char linkflag; 381119Sbill char linkname[NAMSIZ]; 391119Sbill } dbuf; 406250Sroot }; 411119Sbill 421119Sbill struct linkbuf { 431119Sbill ino_t inum; 441119Sbill dev_t devnum; 451119Sbill int count; 461119Sbill char pathname[NAMSIZ]; 471119Sbill struct linkbuf *nextp; 486250Sroot }; 491119Sbill 506250Sroot union hblock dblock; 5113492Ssam union hblock *tbuf; 526250Sroot struct linkbuf *ihead; 536250Sroot struct stat stbuf; 541119Sbill 556250Sroot int rflag; 566250Sroot int xflag; 576250Sroot int vflag; 586250Sroot int tflag; 596250Sroot int cflag; 606250Sroot int mflag; 616250Sroot int fflag; 6212154Ssam int iflag; 636250Sroot int oflag; 646250Sroot int pflag; 656250Sroot int wflag; 666250Sroot int hflag; 678737Smckusick int Bflag; 6812154Ssam int Fflag; 696250Sroot 706250Sroot int mt; 71*22353Skjd int mtdev = 1; 726250Sroot int term; 736250Sroot int chksum; 746250Sroot int recno; 75*22353Skjd int first = 0; 766250Sroot int linkerrok; 771119Sbill int freemem = 1; 78*22353Skjd int nblock = 0; 796250Sroot int onintr(); 806250Sroot int onquit(); 816250Sroot int onhup(); 826250Sroot int onterm(); 831119Sbill 841119Sbill daddr_t low; 851119Sbill daddr_t high; 866250Sroot daddr_t bsrch(); 871119Sbill 8821910Skjd FILE *vfile = stdout; 891119Sbill FILE *tfile; 901119Sbill char tname[] = "/tmp/tarXXXXXX"; 911119Sbill char *usefile; 926250Sroot char magtape[] = "/dev/rmt8"; 931119Sbill char *malloc(); 946250Sroot char *sprintf(); 956250Sroot char *strcat(); 9612154Ssam char *rindex(); 9710165Ssam char *getcwd(); 989844Ssam char *getwd(); 991119Sbill 1001119Sbill main(argc, argv) 1011119Sbill int argc; 1021119Sbill char *argv[]; 1031119Sbill { 1041119Sbill char *cp; 1051119Sbill 1061119Sbill if (argc < 2) 1071119Sbill usage(); 1081119Sbill 1091119Sbill tfile = NULL; 1101119Sbill usefile = magtape; 1111119Sbill argv[argc] = 0; 1121119Sbill argv++; 1131119Sbill for (cp = *argv++; *cp; cp++) 1141119Sbill switch(*cp) { 1156250Sroot 1161119Sbill case 'f': 11712154Ssam if (*argv == 0) { 11812154Ssam fprintf(stderr, 11912154Ssam "tar: tapefile must be specified with 'f' option\n"); 12012154Ssam usage(); 12112154Ssam } 1221119Sbill usefile = *argv++; 1231119Sbill fflag++; 1241119Sbill break; 1256250Sroot 1261119Sbill case 'c': 1271119Sbill cflag++; 1281119Sbill rflag++; 1291119Sbill break; 1306250Sroot 1311119Sbill case 'o': 1321119Sbill oflag++; 1331119Sbill break; 1346250Sroot 1351119Sbill case 'p': 1361119Sbill pflag++; 1371119Sbill break; 1386250Sroot 1391119Sbill case 'u': 1401119Sbill mktemp(tname); 1411119Sbill if ((tfile = fopen(tname, "w")) == NULL) { 1426250Sroot fprintf(stderr, 1436250Sroot "Tar: cannot create temporary file (%s)\n", 1446250Sroot tname); 1451119Sbill done(1); 1461119Sbill } 1471119Sbill fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n"); 1486250Sroot /*FALL THRU*/ 1496250Sroot 1501119Sbill case 'r': 1511119Sbill rflag++; 1521119Sbill break; 1536250Sroot 1541119Sbill case 'v': 1551119Sbill vflag++; 1561119Sbill break; 1576250Sroot 1581119Sbill case 'w': 1591119Sbill wflag++; 1601119Sbill break; 1616250Sroot 1621119Sbill case 'x': 1631119Sbill xflag++; 1641119Sbill break; 1656250Sroot 1661119Sbill case 't': 1671119Sbill tflag++; 1681119Sbill break; 1696250Sroot 1701119Sbill case 'm': 1711119Sbill mflag++; 1721119Sbill break; 1736250Sroot 1741119Sbill case '-': 1751119Sbill break; 1766250Sroot 1771119Sbill case '0': 1781119Sbill case '1': 1791119Sbill case '4': 1801119Sbill case '5': 18121457Skjd case '7': 1821119Sbill case '8': 1831119Sbill magtape[8] = *cp; 1841119Sbill usefile = magtape; 1851119Sbill break; 1866250Sroot 1871119Sbill case 'b': 18813492Ssam if (*argv == 0) { 18913492Ssam fprintf(stderr, 19013492Ssam "tar: blocksize must be specified with 'b' option\n"); 19113492Ssam usage(); 19213492Ssam } 19313492Ssam nblock = atoi(*argv); 19413492Ssam if (nblock <= 0) { 19513492Ssam fprintf(stderr, 19613492Ssam "tar: invalid blocksize \"%s\"\n", *argv); 1971119Sbill done(1); 1981119Sbill } 19913492Ssam argv++; 2001119Sbill break; 2016250Sroot 2021119Sbill case 'l': 2031119Sbill linkerrok++; 2041119Sbill break; 2056250Sroot 2066250Sroot case 'h': 2076250Sroot hflag++; 2086250Sroot break; 2096250Sroot 21012154Ssam case 'i': 21112154Ssam iflag++; 21212154Ssam break; 21312154Ssam 2148737Smckusick case 'B': 2158737Smckusick Bflag++; 2168737Smckusick break; 2178737Smckusick 21812154Ssam case 'F': 21912154Ssam Fflag++; 22012154Ssam break; 22112154Ssam 2221119Sbill default: 2231119Sbill fprintf(stderr, "tar: %c: unknown option\n", *cp); 2241119Sbill usage(); 2251119Sbill } 2261119Sbill 2276250Sroot if (!rflag && !xflag && !tflag) 2286250Sroot usage(); 2291119Sbill if (rflag) { 2306250Sroot if (cflag && tfile != NULL) 2311119Sbill usage(); 2321119Sbill if (signal(SIGINT, SIG_IGN) != SIG_IGN) 2331119Sbill signal(SIGINT, onintr); 2341119Sbill if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 2351119Sbill signal(SIGHUP, onhup); 2361119Sbill if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 2371119Sbill signal(SIGQUIT, onquit); 2386250Sroot #ifdef notdef 2391119Sbill if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 2401119Sbill signal(SIGTERM, onterm); 2416250Sroot #endif 2421119Sbill if (strcmp(usefile, "-") == 0) { 2431119Sbill if (cflag == 0) { 2446250Sroot fprintf(stderr, 24513492Ssam "tar: can only create standard output archives\n"); 2461119Sbill done(1); 2471119Sbill } 24821910Skjd vfile = stderr; 24921910Skjd setlinebuf(vfile); 2501119Sbill mt = dup(1); 2516250Sroot } else if ((mt = open(usefile, 2)) < 0) { 2521119Sbill if (cflag == 0 || (mt = creat(usefile, 0666)) < 0) { 2536250Sroot fprintf(stderr, 2546250Sroot "tar: cannot open %s\n", usefile); 2551119Sbill done(1); 2561119Sbill } 2571119Sbill } 2581119Sbill dorep(argv); 2596250Sroot done(0); 2601119Sbill } 2616250Sroot if (strcmp(usefile, "-") == 0) { 2626250Sroot mt = dup(0); 2636250Sroot } else if ((mt = open(usefile, 0)) < 0) { 2646250Sroot fprintf(stderr, "tar: cannot open %s\n", usefile); 2656250Sroot done(1); 2666250Sroot } 2676250Sroot if (xflag) 2681119Sbill doxtract(argv); 2696250Sroot else 2701119Sbill dotable(); 2711119Sbill done(0); 2721119Sbill } 2731119Sbill 2741119Sbill usage() 2751119Sbill { 2766250Sroot fprintf(stderr, 27721457Skjd "tar: usage: tar -{txru}[cvfblmhopwBi] [tapefile] [blocksize] file1 file2...\n"); 2781119Sbill done(1); 2791119Sbill } 2801119Sbill 2811119Sbill dorep(argv) 2826250Sroot char *argv[]; 2831119Sbill { 2841119Sbill register char *cp, *cp2; 2859601Ssam char wdir[MAXPATHLEN], tempdir[MAXPATHLEN], *parent; 2861119Sbill 2871119Sbill if (!cflag) { 2881119Sbill getdir(); 2891119Sbill do { 2901119Sbill passtape(); 2911119Sbill if (term) 2921119Sbill done(0); 2931119Sbill getdir(); 2941119Sbill } while (!endtape()); 29513492Ssam backtape(); 2961119Sbill if (tfile != NULL) { 2971119Sbill char buf[200]; 2981119Sbill 2996250Sroot sprintf(buf, 3006250Sroot "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX; mv %sX %s", 3011119Sbill tname, tname, tname, tname, tname, tname); 3021119Sbill fflush(tfile); 3031119Sbill system(buf); 3041119Sbill freopen(tname, "r", tfile); 3051119Sbill fstat(fileno(tfile), &stbuf); 3061119Sbill high = stbuf.st_size; 3071119Sbill } 3081119Sbill } 3091119Sbill 31010165Ssam (void) getcwd(wdir); 3111119Sbill while (*argv && ! term) { 3121119Sbill cp2 = *argv; 3131119Sbill if (!strcmp(cp2, "-C") && argv[1]) { 3141119Sbill argv++; 3151119Sbill if (chdir(*argv) < 0) 3161119Sbill perror(*argv); 3171119Sbill else 31810165Ssam (void) getcwd(wdir); 3191119Sbill argv++; 3201119Sbill continue; 3211119Sbill } 3229601Ssam parent = wdir; 3231119Sbill for (cp = *argv; *cp; cp++) 3241119Sbill if (*cp == '/') 3251119Sbill cp2 = cp; 3261119Sbill if (cp2 != *argv) { 3271119Sbill *cp2 = '\0'; 3289601Ssam if (chdir(*argv) < 0) { 3299601Ssam perror(*argv); 3309601Ssam continue; 3319601Ssam } 33210165Ssam parent = getcwd(tempdir); 3331119Sbill *cp2 = '/'; 3341119Sbill cp2++; 3351119Sbill } 3369601Ssam putfile(*argv++, cp2, parent); 33715045Smckusick if (chdir(wdir) < 0) { 33821457Skjd fprintf(stderr, "cannot change back?: "); 33915045Smckusick perror(wdir); 34015045Smckusick } 3411119Sbill } 3421119Sbill putempty(); 3431119Sbill putempty(); 3441119Sbill flushtape(); 3456250Sroot if (linkerrok == 0) 3466250Sroot return; 3476250Sroot for (; ihead != NULL; ihead = ihead->nextp) { 3486250Sroot if (ihead->count == 0) 3496250Sroot continue; 35013492Ssam fprintf(stderr, "tar: missing links to %s\n", ihead->pathname); 3516250Sroot } 3521119Sbill } 3531119Sbill 3541119Sbill endtape() 3551119Sbill { 35621457Skjd return (dblock.dbuf.name[0] == '\0'); 3571119Sbill } 3581119Sbill 3591119Sbill getdir() 3601119Sbill { 3611119Sbill register struct stat *sp; 3621119Sbill int i; 3631119Sbill 36412154Ssam top: 3656250Sroot readtape((char *)&dblock); 3661119Sbill if (dblock.dbuf.name[0] == '\0') 3671119Sbill return; 3681119Sbill sp = &stbuf; 3691119Sbill sscanf(dblock.dbuf.mode, "%o", &i); 3701119Sbill sp->st_mode = i; 3711119Sbill sscanf(dblock.dbuf.uid, "%o", &i); 3721119Sbill sp->st_uid = i; 3731119Sbill sscanf(dblock.dbuf.gid, "%o", &i); 3741119Sbill sp->st_gid = i; 3751119Sbill sscanf(dblock.dbuf.size, "%lo", &sp->st_size); 3761119Sbill sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime); 3771119Sbill sscanf(dblock.dbuf.chksum, "%o", &chksum); 37812154Ssam if (chksum != (i = checksum())) { 37913492Ssam fprintf(stderr, "tar: directory checksum error (%d != %d)\n", 38012154Ssam chksum, i); 38112154Ssam if (iflag) 38212154Ssam goto top; 3831119Sbill done(2); 3841119Sbill } 3851119Sbill if (tfile != NULL) 3861119Sbill fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime); 3871119Sbill } 3881119Sbill 3891119Sbill passtape() 3901119Sbill { 3911119Sbill long blocks; 39221457Skjd char *bufp; 3931119Sbill 3941119Sbill if (dblock.dbuf.linkflag == '1') 3951119Sbill return; 3961119Sbill blocks = stbuf.st_size; 3971119Sbill blocks += TBLOCK-1; 3981119Sbill blocks /= TBLOCK; 3991119Sbill 40021457Skjd while (blocks-- > 0) 40121457Skjd readtbuf(&bufp, TBLOCK); 4021119Sbill } 4031119Sbill 4049601Ssam putfile(longname, shortname, parent) 4056250Sroot char *longname; 4066250Sroot char *shortname; 4079601Ssam char *parent; 4081119Sbill { 40921457Skjd int infile = 0; 41021457Skjd long blocks; 4111119Sbill char buf[TBLOCK]; 41221457Skjd char *origbuf; 41321457Skjd char *bigbuf; 4141119Sbill register char *cp, *cp2; 4155931Smckusic struct direct *dp; 4165931Smckusic DIR *dirp; 41721457Skjd int i, j; 4189601Ssam char newparent[NAMSIZ+64]; 41912154Ssam extern int errno; 42021457Skjd int maxread; 42121457Skjd int hint; /* amount to write to get "in sync" */ 4221119Sbill 4239601Ssam if (!hflag) 42412154Ssam i = lstat(shortname, &stbuf); 42512154Ssam else 42612154Ssam i = stat(shortname, &stbuf); 42712154Ssam if (i < 0) { 42812154Ssam switch (errno) { 42912154Ssam case EACCES: 43012154Ssam fprintf(stderr, "tar: %s: cannot open file\n", longname); 43112154Ssam break; 43212154Ssam case ENOENT: 43312154Ssam fprintf(stderr, "tar: %s: no such file or directory\n", 43412154Ssam longname); 43512154Ssam break; 43612154Ssam default: 43712154Ssam fprintf(stderr, "tar: %s: cannot stat file\n", longname); 43812154Ssam break; 43912154Ssam } 4409601Ssam return; 4419601Ssam } 44212154Ssam if (tfile != NULL && checkupdate(longname) == 0) 4431119Sbill return; 44412154Ssam if (checkw('r', longname) == 0) 4451119Sbill return; 44612154Ssam if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0) 44712154Ssam return; 4481119Sbill 44912154Ssam switch (stbuf.st_mode & S_IFMT) { 45012154Ssam case S_IFDIR: 4516250Sroot for (i = 0, cp = buf; *cp++ = longname[i++];) 4526250Sroot ; 4531119Sbill *--cp = '/'; 4541119Sbill *++cp = 0 ; 4551119Sbill if (!oflag) { 4566250Sroot if ((cp - buf) >= NAMSIZ) { 45713492Ssam fprintf(stderr, "tar: %s: file name too long\n", 45813492Ssam longname); 4596250Sroot return; 4606250Sroot } 4616250Sroot stbuf.st_size = 0; 4626250Sroot tomodes(&stbuf); 4636250Sroot strcpy(dblock.dbuf.name,buf); 4646250Sroot sprintf(dblock.dbuf.chksum, "%6o", checksum()); 4656250Sroot writetape((char *)&dblock); 4661119Sbill } 4679601Ssam sprintf(newparent, "%s/%s", parent, shortname); 46815045Smckusick if (chdir(shortname) < 0) { 46915045Smckusick perror(shortname); 47015045Smckusick return; 47115045Smckusick } 4725931Smckusic if ((dirp = opendir(".")) == NULL) { 47313492Ssam fprintf(stderr, "tar: %s: directory read error\n", 47413492Ssam longname); 47515045Smckusick if (chdir(parent) < 0) { 47621457Skjd fprintf(stderr, "cannot change back?: "); 47715045Smckusick perror(parent); 47815045Smckusick } 4795931Smckusic return; 4805931Smckusic } 4815931Smckusic while ((dp = readdir(dirp)) != NULL && !term) { 4825931Smckusic if (dp->d_ino == 0) 4831119Sbill continue; 4846250Sroot if (!strcmp(".", dp->d_name) || 4856250Sroot !strcmp("..", dp->d_name)) 4861119Sbill continue; 4875931Smckusic strcpy(cp, dp->d_name); 4885931Smckusic i = telldir(dirp); 4895931Smckusic closedir(dirp); 4909601Ssam putfile(buf, cp, newparent); 4915931Smckusic dirp = opendir("."); 4925931Smckusic seekdir(dirp, i); 4931119Sbill } 4945931Smckusic closedir(dirp); 49515045Smckusick if (chdir(parent) < 0) { 49621457Skjd fprintf(stderr, "cannot change back?: "); 49715045Smckusick perror(parent); 49815045Smckusick } 49912154Ssam break; 50012154Ssam 50112154Ssam case S_IFLNK: 50212154Ssam tomodes(&stbuf); 50312154Ssam if (strlen(longname) >= NAMSIZ) { 50413492Ssam fprintf(stderr, "tar: %s: file name too long\n", 50513492Ssam longname); 50612154Ssam return; 50712154Ssam } 50812154Ssam strcpy(dblock.dbuf.name, longname); 5096250Sroot if (stbuf.st_size + 1 >= NAMSIZ) { 51013492Ssam fprintf(stderr, "tar: %s: symbolic link too long\n", 51113492Ssam longname); 5126250Sroot return; 5136250Sroot } 5149601Ssam i = readlink(shortname, dblock.dbuf.linkname, NAMSIZ - 1); 5156250Sroot if (i < 0) { 5169601Ssam perror(longname); 5176250Sroot return; 5186250Sroot } 5196250Sroot dblock.dbuf.linkname[i] = '\0'; 5206250Sroot dblock.dbuf.linkflag = '2'; 5216250Sroot if (vflag) { 52221910Skjd fprintf(vfile, "a %s ", longname); 52321910Skjd fprintf(vfile, "symbolic link to %s\n", 52413492Ssam dblock.dbuf.linkname); 5256250Sroot } 5266250Sroot sprintf(dblock.dbuf.size, "%11lo", 0); 5276250Sroot sprintf(dblock.dbuf.chksum, "%6o", checksum()); 5286250Sroot writetape((char *)&dblock); 52912154Ssam break; 5301119Sbill 53112154Ssam case S_IFREG: 53212154Ssam if ((infile = open(shortname, 0)) < 0) { 53312154Ssam fprintf(stderr, "tar: %s: cannot open file\n", longname); 5341119Sbill return; 5351119Sbill } 53612154Ssam tomodes(&stbuf); 53712154Ssam if (strlen(longname) >= NAMSIZ) { 53813492Ssam fprintf(stderr, "tar: %s: file name too long\n", 53913492Ssam longname); 54021457Skjd close(infile); 54112154Ssam return; 54212154Ssam } 54312154Ssam strcpy(dblock.dbuf.name, longname); 54412154Ssam if (stbuf.st_nlink > 1) { 54512154Ssam struct linkbuf *lp; 54612154Ssam int found = 0; 54712154Ssam 54812154Ssam for (lp = ihead; lp != NULL; lp = lp->nextp) 54912154Ssam if (lp->inum == stbuf.st_ino && 55012154Ssam lp->devnum == stbuf.st_dev) { 55112154Ssam found++; 55212154Ssam break; 55312154Ssam } 55412154Ssam if (found) { 55512154Ssam strcpy(dblock.dbuf.linkname, lp->pathname); 55612154Ssam dblock.dbuf.linkflag = '1'; 55712154Ssam sprintf(dblock.dbuf.chksum, "%6o", checksum()); 55821457Skjd writetape( (char *) &dblock); 55912154Ssam if (vflag) { 56021910Skjd fprintf(vfile, "a %s ", longname); 56121910Skjd fprintf(vfile, "link to %s\n", 56213492Ssam lp->pathname); 56312154Ssam } 56412154Ssam lp->count--; 56512154Ssam close(infile); 56612154Ssam return; 5671119Sbill } 56812154Ssam lp = (struct linkbuf *) malloc(sizeof(*lp)); 56912154Ssam if (lp == NULL) { 57012154Ssam if (freemem) { 57112154Ssam fprintf(stderr, 57213492Ssam "tar: out of memory, link information lost\n"); 57312154Ssam freemem = 0; 57412154Ssam } 57512154Ssam } else { 57612154Ssam lp->nextp = ihead; 57712154Ssam ihead = lp; 57812154Ssam lp->inum = stbuf.st_ino; 57912154Ssam lp->devnum = stbuf.st_dev; 58012154Ssam lp->count = stbuf.st_nlink - 1; 58112154Ssam strcpy(lp->pathname, longname); 58212154Ssam } 5831119Sbill } 58421457Skjd blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK; 58512154Ssam if (vflag) { 58621910Skjd fprintf(vfile, "a %s ", longname); 58721910Skjd fprintf(vfile, "%ld blocks\n", blocks); 58812154Ssam } 58912154Ssam sprintf(dblock.dbuf.chksum, "%6o", checksum()); 59021457Skjd hint = writetape((char *)&dblock); 59121457Skjd maxread = max(stbuf.st_blksize, (nblock * TBLOCK)); 59221457Skjd if ((bigbuf = malloc(maxread)) == 0) { 59321457Skjd maxread = TBLOCK; 59421457Skjd bigbuf = buf; 59521457Skjd } 5961119Sbill 59721457Skjd while ((i = read(infile, bigbuf, min((hint*TBLOCK), maxread))) > 0 59821457Skjd && blocks > 0) { 59921457Skjd register int nblks; 60021457Skjd 60121457Skjd nblks = ((i-1)/TBLOCK)+1; 60221457Skjd if (nblks > blocks) 60321457Skjd nblks = blocks; 60421457Skjd hint = writetbuf(bigbuf, nblks); 60521457Skjd blocks -= nblks; 60621457Skjd } 60721457Skjd close(infile); 60821457Skjd if (bigbuf != buf) 60921457Skjd free(bigbuf); 61021457Skjd if (blocks != 0 || i != 0) 61113492Ssam fprintf(stderr, "tar: %s: file changed size\n", 61213492Ssam longname); 61312154Ssam while (--blocks >= 0) 61412154Ssam putempty(); 61512154Ssam break; 61612154Ssam 61712154Ssam default: 61812154Ssam fprintf(stderr, "tar: %s is not a file. Not dumped\n", 61913492Ssam longname); 62012154Ssam break; 6211119Sbill } 6221119Sbill } 6231119Sbill 6241119Sbill doxtract(argv) 6256250Sroot char *argv[]; 6261119Sbill { 6271119Sbill long blocks, bytes; 6281119Sbill char **cp; 6291119Sbill int ofile; 6301119Sbill 6311119Sbill for (;;) { 6321119Sbill getdir(); 6331119Sbill if (endtape()) 6341119Sbill break; 6351119Sbill if (*argv == 0) 6361119Sbill goto gotit; 6371119Sbill for (cp = argv; *cp; cp++) 6381119Sbill if (prefix(*cp, dblock.dbuf.name)) 6391119Sbill goto gotit; 6401119Sbill passtape(); 6411119Sbill continue; 6421119Sbill 6431119Sbill gotit: 6441119Sbill if (checkw('x', dblock.dbuf.name) == 0) { 6451119Sbill passtape(); 6461119Sbill continue; 6471119Sbill } 64812154Ssam if (Fflag) { 64912154Ssam char *s; 65012154Ssam 65112154Ssam if ((s = rindex(dblock.dbuf.name, '/')) == 0) 65212154Ssam s = dblock.dbuf.name; 65312154Ssam else 65412154Ssam s++; 65512154Ssam if (checkf(s, stbuf.st_mode, Fflag) == 0) { 65612154Ssam passtape(); 65712154Ssam continue; 65812154Ssam } 65912154Ssam } 6606250Sroot if (checkdir(dblock.dbuf.name)) 6616250Sroot continue; 6626250Sroot if (dblock.dbuf.linkflag == '2') { 6636250Sroot unlink(dblock.dbuf.name); 6646250Sroot if (symlink(dblock.dbuf.linkname, dblock.dbuf.name)<0) { 66513492Ssam fprintf(stderr, "tar: %s: symbolic link failed\n", 66613492Ssam dblock.dbuf.name); 6676250Sroot continue; 6686250Sroot } 6696250Sroot if (vflag) 67021910Skjd fprintf(vfile, "x %s symbolic link to %s\n", 67113492Ssam dblock.dbuf.name, dblock.dbuf.linkname); 672*22353Skjd #ifdef notdef 673*22353Skjd /* ignore alien orders */ 674*22353Skjd chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 675*22353Skjd if (mflag == 0) { 676*22353Skjd struct timeval tv[2]; 677*22353Skjd 678*22353Skjd tv[0].tv_sec = time(0); 679*22353Skjd tv[0].tv_usec = 0; 680*22353Skjd tv[1].tv_sec = stbuf.st_mtime; 681*22353Skjd tv[1].tv_usec = 0; 682*22353Skjd utimes(dblock.dbuf.name, tv); 683*22353Skjd } 684*22353Skjd if (pflag) 685*22353Skjd chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 686*22353Skjd #endif 6871119Sbill continue; 6886250Sroot } 6891119Sbill if (dblock.dbuf.linkflag == '1') { 6901119Sbill unlink(dblock.dbuf.name); 6911119Sbill if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) { 69213492Ssam fprintf(stderr, "tar: %s: cannot link\n", 69313492Ssam dblock.dbuf.name); 6941119Sbill continue; 6951119Sbill } 6961119Sbill if (vflag) 697*22353Skjd fprintf(vfile, "%s linked to %s", 69813492Ssam dblock.dbuf.name, dblock.dbuf.linkname); 6991119Sbill continue; 7001119Sbill } 7016250Sroot if ((ofile = creat(dblock.dbuf.name,stbuf.st_mode&0xfff)) < 0) { 7026250Sroot fprintf(stderr, "tar: %s - cannot create\n", 70313492Ssam dblock.dbuf.name); 7041119Sbill passtape(); 7051119Sbill continue; 7061119Sbill } 70721457Skjd chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 7081119Sbill blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK; 7091119Sbill if (vflag) 710*22353Skjd fprintf(vfile, "x %s, %ld bytes, %ld tape blocks", 71113492Ssam dblock.dbuf.name, bytes, blocks); 71221457Skjd for (; blocks > 0;) { 71321457Skjd register int nread; 71421457Skjd char *bufp; 71521457Skjd register int nwant; 71621457Skjd 71721457Skjd nwant = NBLOCK*TBLOCK; 71821457Skjd if (nwant > (blocks*TBLOCK)) 71921457Skjd nwant = (blocks*TBLOCK); 72021457Skjd nread = readtbuf(&bufp, nwant); 72121457Skjd if (bytes > nread) { 72221457Skjd if (write(ofile, bufp, nread) < 0) { 72321457Skjd fprintf(stderr, 72421457Skjd "tar: %s: HELP - extract write error\n", 72521457Skjd dblock.dbuf.name); 72621457Skjd done(2); 72721457Skjd } 72821457Skjd } else if (write(ofile, bufp, (int) bytes) < 0) { 7296250Sroot fprintf(stderr, 73013492Ssam "tar: %s: HELP - extract write error\n", 73113492Ssam dblock.dbuf.name); 7326250Sroot done(2); 7336250Sroot } 73421457Skjd bytes -= nread; 73521457Skjd blocks -= (((nread-1)/TBLOCK)+1); 736*22353Skjd fprintf(stderr,"\n"); 7371119Sbill } 7381119Sbill close(ofile); 7391119Sbill if (mflag == 0) { 74012983Ssam struct timeval tv[2]; 7411119Sbill 74212983Ssam tv[0].tv_sec = time(0); 74312983Ssam tv[0].tv_usec = 0; 74412983Ssam tv[1].tv_sec = stbuf.st_mtime; 74512983Ssam tv[1].tv_usec = 0; 74612983Ssam utimes(dblock.dbuf.name, tv); 7471119Sbill } 7481926Swnj if (pflag) 7496250Sroot chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 7501119Sbill } 7511119Sbill } 7521119Sbill 7531119Sbill dotable() 7541119Sbill { 7551119Sbill for (;;) { 7561119Sbill getdir(); 7571119Sbill if (endtape()) 7581119Sbill break; 7591119Sbill if (vflag) 7601119Sbill longt(&stbuf); 7611119Sbill printf("%s", dblock.dbuf.name); 7621119Sbill if (dblock.dbuf.linkflag == '1') 7631119Sbill printf(" linked to %s", dblock.dbuf.linkname); 7646250Sroot if (dblock.dbuf.linkflag == '2') 7656250Sroot printf(" symbolic link to %s", dblock.dbuf.linkname); 7661119Sbill printf("\n"); 7671119Sbill passtape(); 7681119Sbill } 7691119Sbill } 7701119Sbill 7711119Sbill putempty() 7721119Sbill { 7731119Sbill char buf[TBLOCK]; 7741119Sbill 77513492Ssam bzero(buf, sizeof (buf)); 7761119Sbill writetape(buf); 7771119Sbill } 7781119Sbill 7791119Sbill longt(st) 7806250Sroot register struct stat *st; 7811119Sbill { 7821119Sbill register char *cp; 7831119Sbill char *ctime(); 7841119Sbill 7851119Sbill pmode(st); 7861119Sbill printf("%3d/%1d", st->st_uid, st->st_gid); 7871119Sbill printf("%7D", st->st_size); 7881119Sbill cp = ctime(&st->st_mtime); 7891119Sbill printf(" %-12.12s %-4.4s ", cp+4, cp+20); 7901119Sbill } 7911119Sbill 7921119Sbill #define SUID 04000 7931119Sbill #define SGID 02000 7941119Sbill #define ROWN 0400 7951119Sbill #define WOWN 0200 7961119Sbill #define XOWN 0100 7971119Sbill #define RGRP 040 7981119Sbill #define WGRP 020 7991119Sbill #define XGRP 010 8001119Sbill #define ROTH 04 8011119Sbill #define WOTH 02 8021119Sbill #define XOTH 01 8031119Sbill #define STXT 01000 8041119Sbill int m1[] = { 1, ROWN, 'r', '-' }; 8051119Sbill int m2[] = { 1, WOWN, 'w', '-' }; 8061119Sbill int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 8071119Sbill int m4[] = { 1, RGRP, 'r', '-' }; 8081119Sbill int m5[] = { 1, WGRP, 'w', '-' }; 8091119Sbill int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 8101119Sbill int m7[] = { 1, ROTH, 'r', '-' }; 8111119Sbill int m8[] = { 1, WOTH, 'w', '-' }; 8121119Sbill int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 8131119Sbill 8141119Sbill int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 8151119Sbill 8161119Sbill pmode(st) 8176250Sroot register struct stat *st; 8181119Sbill { 8191119Sbill register int **mp; 8201119Sbill 8211119Sbill for (mp = &m[0]; mp < &m[9];) 8221119Sbill select(*mp++, st); 8231119Sbill } 8241119Sbill 8251119Sbill select(pairp, st) 8266250Sroot int *pairp; 8276250Sroot struct stat *st; 8281119Sbill { 8291119Sbill register int n, *ap; 8301119Sbill 8311119Sbill ap = pairp; 8321119Sbill n = *ap++; 8331119Sbill while (--n>=0 && (st->st_mode&*ap++)==0) 8341119Sbill ap++; 8351119Sbill printf("%c", *ap); 8361119Sbill } 8371119Sbill 8381119Sbill checkdir(name) 8396250Sroot register char *name; 8401119Sbill { 8411119Sbill register char *cp; 8426250Sroot 84312154Ssam /* 84412154Ssam * Quick check for existance of directory. 84512154Ssam */ 84612154Ssam if ((cp = rindex(name, '/')) == 0) 84712154Ssam return (0); 84812154Ssam *cp = '\0'; 84912154Ssam if (access(name, 0) >= 0) { 85012154Ssam *cp = '/'; 85112154Ssam return (cp[1] == '\0'); 85212154Ssam } 85312154Ssam *cp = '/'; 85412154Ssam 85512154Ssam /* 85612154Ssam * No luck, try to make all directories in path. 85712154Ssam */ 8581119Sbill for (cp = name; *cp; cp++) { 8596250Sroot if (*cp != '/') 8606250Sroot continue; 8616250Sroot *cp = '\0'; 86212154Ssam if (access(name, 0) < 0) { 8639844Ssam if (mkdir(name, 0777) < 0) { 8649844Ssam perror(name); 86512154Ssam *cp = '/'; 86612154Ssam return (0); 8671119Sbill } 86821457Skjd chown(name, stbuf.st_uid, stbuf.st_gid); 86914956Skarels if (pflag && cp[1] == '\0') 8709844Ssam chmod(name, stbuf.st_mode & 0777); 8711119Sbill } 8726250Sroot *cp = '/'; 8731119Sbill } 8746250Sroot return (cp[-1]=='/'); 8751119Sbill } 8761119Sbill 8771119Sbill onintr() 8781119Sbill { 8791119Sbill signal(SIGINT, SIG_IGN); 8801119Sbill term++; 8811119Sbill } 8821119Sbill 8831119Sbill onquit() 8841119Sbill { 8851119Sbill signal(SIGQUIT, SIG_IGN); 8861119Sbill term++; 8871119Sbill } 8881119Sbill 8891119Sbill onhup() 8901119Sbill { 8911119Sbill signal(SIGHUP, SIG_IGN); 8921119Sbill term++; 8931119Sbill } 8941119Sbill 8951119Sbill onterm() 8961119Sbill { 8971119Sbill signal(SIGTERM, SIG_IGN); 8981119Sbill term++; 8991119Sbill } 9001119Sbill 9011119Sbill tomodes(sp) 9021119Sbill register struct stat *sp; 9031119Sbill { 9041119Sbill register char *cp; 9051119Sbill 9061119Sbill for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 9071119Sbill *cp = '\0'; 9081119Sbill sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); 9091119Sbill sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); 9101119Sbill sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); 9111119Sbill sprintf(dblock.dbuf.size, "%11lo ", sp->st_size); 9121119Sbill sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime); 9131119Sbill } 9141119Sbill 9151119Sbill checksum() 9161119Sbill { 9171119Sbill register i; 9181119Sbill register char *cp; 9191119Sbill 9206250Sroot for (cp = dblock.dbuf.chksum; 9216250Sroot cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++) 9221119Sbill *cp = ' '; 9231119Sbill i = 0; 9241119Sbill for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 9251119Sbill i += *cp; 9266250Sroot return (i); 9271119Sbill } 9281119Sbill 9291119Sbill checkw(c, name) 9306250Sroot char *name; 9311119Sbill { 9326250Sroot if (!wflag) 9336250Sroot return (1); 9346250Sroot printf("%c ", c); 9356250Sroot if (vflag) 9366250Sroot longt(&stbuf); 9376250Sroot printf("%s: ", name); 9386250Sroot return (response() == 'y'); 9391119Sbill } 9401119Sbill 9411119Sbill response() 9421119Sbill { 9431119Sbill char c; 9441119Sbill 9451119Sbill c = getchar(); 9461119Sbill if (c != '\n') 9476250Sroot while (getchar() != '\n') 9486250Sroot ; 9496250Sroot else 9506250Sroot c = 'n'; 9516250Sroot return (c); 9521119Sbill } 9531119Sbill 95412154Ssam checkf(name, mode, howmuch) 95512154Ssam char *name; 95612154Ssam int mode, howmuch; 95712154Ssam { 95812154Ssam int l; 95912154Ssam 96021910Skjd if ((mode & S_IFMT) == S_IFDIR){ 96121910Skjd if ((strcmp(name, "SCCS")==0) || (strcmp(name, "RCS")==0)) 96221910Skjd return(0); 96321910Skjd return(1); 96421910Skjd } 96512154Ssam if ((l = strlen(name)) < 3) 96612154Ssam return (1); 96712154Ssam if (howmuch > 1 && name[l-2] == '.' && name[l-1] == 'o') 96812154Ssam return (0); 96912154Ssam if (strcmp(name, "core") == 0 || 97012154Ssam strcmp(name, "errs") == 0 || 97112154Ssam (howmuch > 1 && strcmp(name, "a.out") == 0)) 97212154Ssam return (0); 97312154Ssam /* SHOULD CHECK IF IT IS EXECUTABLE */ 97412154Ssam return (1); 97512154Ssam } 97612154Ssam 9771119Sbill checkupdate(arg) 9786250Sroot char *arg; 9791119Sbill { 9801119Sbill char name[100]; 9816250Sroot long mtime; 9821119Sbill daddr_t seekp; 9831119Sbill daddr_t lookup(); 9841119Sbill 9851119Sbill rewind(tfile); 9861119Sbill for (;;) { 9871119Sbill if ((seekp = lookup(arg)) < 0) 9886250Sroot return (1); 9891119Sbill fseek(tfile, seekp, 0); 9901119Sbill fscanf(tfile, "%s %lo", name, &mtime); 9916250Sroot return (stbuf.st_mtime > mtime); 9921119Sbill } 9931119Sbill } 9941119Sbill 9951119Sbill done(n) 9961119Sbill { 99721457Skjd unlink(tname); 9981119Sbill exit(n); 9991119Sbill } 10001119Sbill 10011119Sbill prefix(s1, s2) 10026250Sroot register char *s1, *s2; 10031119Sbill { 10041119Sbill while (*s1) 10051119Sbill if (*s1++ != *s2++) 10066250Sroot return (0); 10071119Sbill if (*s2) 10086250Sroot return (*s2 == '/'); 10096250Sroot return (1); 10101119Sbill } 10111119Sbill 10121119Sbill #define N 200 10131119Sbill int njab; 10146250Sroot 10151119Sbill daddr_t 10161119Sbill lookup(s) 10176250Sroot char *s; 10181119Sbill { 10191119Sbill register i; 10201119Sbill daddr_t a; 10211119Sbill 10221119Sbill for(i=0; s[i]; i++) 10236250Sroot if (s[i] == ' ') 10241119Sbill break; 10251119Sbill a = bsrch(s, i, low, high); 10266250Sroot return (a); 10271119Sbill } 10281119Sbill 10291119Sbill daddr_t 10301119Sbill bsrch(s, n, l, h) 10316250Sroot daddr_t l, h; 10326250Sroot char *s; 10331119Sbill { 10341119Sbill register i, j; 10351119Sbill char b[N]; 10361119Sbill daddr_t m, m1; 10371119Sbill 10381119Sbill njab = 0; 10391119Sbill 10401119Sbill loop: 10416250Sroot if (l >= h) 10426250Sroot return (-1L); 10431119Sbill m = l + (h-l)/2 - N/2; 10446250Sroot if (m < l) 10451119Sbill m = l; 10461119Sbill fseek(tfile, m, 0); 10471119Sbill fread(b, 1, N, tfile); 10481119Sbill njab++; 10491119Sbill for(i=0; i<N; i++) { 10506250Sroot if (b[i] == '\n') 10511119Sbill break; 10521119Sbill m++; 10531119Sbill } 10546250Sroot if (m >= h) 10556250Sroot return (-1L); 10561119Sbill m1 = m; 10571119Sbill j = i; 10581119Sbill for(i++; i<N; i++) { 10591119Sbill m1++; 10606250Sroot if (b[i] == '\n') 10611119Sbill break; 10621119Sbill } 10631119Sbill i = cmp(b+j, s, n); 10646250Sroot if (i < 0) { 10651119Sbill h = m; 10661119Sbill goto loop; 10671119Sbill } 10686250Sroot if (i > 0) { 10691119Sbill l = m1; 10701119Sbill goto loop; 10711119Sbill } 10726250Sroot return (m); 10731119Sbill } 10741119Sbill 10751119Sbill cmp(b, s, n) 10766250Sroot char *b, *s; 10771119Sbill { 10781119Sbill register i; 10791119Sbill 10806250Sroot if (b[0] != '\n') 108121457Skjd exit(2); 10821119Sbill for(i=0; i<n; i++) { 10836250Sroot if (b[i+1] > s[i]) 10846250Sroot return (-1); 10856250Sroot if (b[i+1] < s[i]) 10866250Sroot return (1); 10871119Sbill } 10886250Sroot return (b[i+1] == ' '? 0 : -1); 10891119Sbill } 10901119Sbill 109121457Skjd readtape (buffer) 10926250Sroot char *buffer; 10931119Sbill { 109421457Skjd char *bufp; 109521457Skjd int nread; 109621457Skjd 109721910Skjd if (first==0) getbuf(); 109821457Skjd readtbuf (&bufp, TBLOCK); 109921457Skjd bcopy(bufp, buffer, TBLOCK); 110021457Skjd return(TBLOCK); 110121457Skjd } 110221457Skjd 110321457Skjd readtbuf(bufpp, size) 110421457Skjd char **bufpp; 110521457Skjd int size; 110621457Skjd { 11073457Swnj register int i; 11081119Sbill 11091119Sbill if (recno >= nblock || first == 0) { 11108737Smckusick if ((i = bread(mt, tbuf, TBLOCK*nblock)) < 0) { 111113492Ssam fprintf(stderr, "tar: tape read error\n"); 11121119Sbill done(3); 11131119Sbill } 11141119Sbill if (first == 0) { 11151119Sbill if ((i % TBLOCK) != 0) { 111613492Ssam fprintf(stderr, "tar: tape blocksize error\n"); 11171119Sbill done(3); 11181119Sbill } 11191119Sbill i /= TBLOCK; 11203457Swnj if (i != nblock) { 112113492Ssam fprintf(stderr, "tar: blocksize = %d\n", i); 11221119Sbill nblock = i; 11231119Sbill } 1124*22353Skjd first = 1; 11251119Sbill } 11261119Sbill recno = 0; 11271119Sbill } 112821457Skjd if (size > ((nblock-recno)*TBLOCK)) 112921457Skjd size = (nblock-recno)*TBLOCK; 113021457Skjd *bufpp = (char *)&tbuf[recno]; 113121457Skjd recno += (size/TBLOCK); 113221457Skjd return (size); 11331119Sbill } 11341119Sbill 113521457Skjd writetbuf(buffer, n) 113621457Skjd register char *buffer; 113721457Skjd register int n; 11381119Sbill { 1139*22353Skjd int i; 1140*22353Skjd if (first==0) { 1141*22353Skjd getbuf(); 1142*22353Skjd first = 1; 1143*22353Skjd } 11441119Sbill if (recno >= nblock) { 1145*22353Skjd if ( write(mt, tbuf, TBLOCK*nblock) < 0) { 1146*22353Skjd perror("tar"); 11471119Sbill done(2); 11481119Sbill } 11491119Sbill recno = 0; 11501119Sbill } 115121457Skjd 115221457Skjd /* 115321457Skjd * Special case: We have an empty tape buffer, and the 115421457Skjd * users data size is >= the tape block size: Avoid 115521457Skjd * the bcopy and dma direct to tape. BIG WIN. Add the 115621457Skjd * residual to the tape buffer. 115721457Skjd */ 115821457Skjd while (recno == 0 && n >= nblock) { 115921457Skjd if (write(mt, buffer, TBLOCK*nblock) < 0) { 1160*22353Skjd perror("tar"); 11611119Sbill done(2); 11621119Sbill } 116321457Skjd n -= nblock; 116421457Skjd buffer += (nblock * TBLOCK); 11651119Sbill } 116621457Skjd 116721457Skjd while (n-- > 0) { 116821457Skjd bcopy(buffer, (char *)&tbuf[recno++], TBLOCK); 116921457Skjd buffer += TBLOCK; 117021457Skjd if (recno >= nblock) { 117121457Skjd if (write(mt, tbuf, TBLOCK*nblock) < 0) { 1172*22353Skjd fprintf(stderr,"tar: tape write error\n"); 1173*22353Skjd done(2); 117421457Skjd } 117521457Skjd recno = 0; 117621457Skjd } 117721457Skjd } 117821457Skjd 117921457Skjd /* Tell the user how much to write to get in sync */ 118021457Skjd return (nblock - recno); 11811119Sbill } 11821119Sbill 11831119Sbill backtape() 11841119Sbill { 11853457Swnj static struct mtop mtop = {MTBSR, 1}; 11863457Swnj struct mtget mtget; 11873457Swnj 11883457Swnj if (mtdev == 0) { 11893457Swnj if (ioctl(mt, MTIOCTOP, &mtop) < 0) { 119013492Ssam fprintf(stderr, "tar: tape backspace error\n"); 11911119Sbill done(4); 11921119Sbill } 11933457Swnj } else 11943457Swnj lseek(mt, (long) -TBLOCK*nblock, 1); 11953457Swnj recno--; 11961119Sbill } 11971119Sbill 11981119Sbill flushtape() 11991119Sbill { 120021457Skjd write(mt, tbuf, TBLOCK*nblock); 12011119Sbill } 12021119Sbill 12038737Smckusick bread(fd, buf, size) 12048737Smckusick int fd; 12058737Smckusick char *buf; 12068737Smckusick int size; 12078737Smckusick { 12088737Smckusick int count; 1209*22353Skjd int i; 12108737Smckusick static int lastread = 0; 12118737Smckusick 1212*22353Skjd if (!Bflag) { 1213*22353Skjd return (read(fd, buf, size)); 1214*22353Skjd } 1215*22353Skjd 1216*22353Skjd 12178737Smckusick for (count = 0; count < size; count += lastread) { 12188737Smckusick if (lastread < 0) { 12198737Smckusick if (count > 0) 12208737Smckusick return (count); 12218737Smckusick return (lastread); 12228737Smckusick } 12238737Smckusick lastread = read(fd, buf, size - count); 12248737Smckusick buf += lastread; 12258737Smckusick } 12268737Smckusick return (count); 12278737Smckusick } 122810165Ssam 122910165Ssam char * 123010165Ssam getcwd(buf) 123110165Ssam char *buf; 123210165Ssam { 123310165Ssam if (getwd(buf) == NULL) { 123410165Ssam fprintf(stderr, "tar: %s\n", buf); 123521457Skjd exit(1); 123610165Ssam } 123710165Ssam return (buf); 123810165Ssam } 123921910Skjd 124021910Skjd getbuf() 124121910Skjd { 1242*22353Skjd struct mtget mtget; 1243*22353Skjd 124421910Skjd if ( mtdev == 1) { 124521910Skjd fstat(mt, &stbuf); 124621910Skjd if ((stbuf.st_mode & S_IFMT) == S_IFCHR) 124721910Skjd mtdev = 0; 124821910Skjd else 124921910Skjd mtdev = -1; 125021910Skjd } 1251*22353Skjd if (nblock==0) { 125221910Skjd if (mtdev == 0) 125321910Skjd nblock = FILEBLOCK; 125421910Skjd else { 125521910Skjd fstat(mt, &stbuf); 125621910Skjd nblock = stbuf.st_blocks / TBLOCK; 125721910Skjd } 125821910Skjd } 1259*22353Skjd if (nblock == 0) nblock = FILEBLOCK; 126021910Skjd tbuf = (union hblock *)malloc(nblock*TBLOCK); 126121910Skjd if (tbuf == NULL) { 126221910Skjd fprintf(stderr, "tar: blocksize %d too big, can't get memory\n", 126321910Skjd nblock); 126421910Skjd done(1); 126521910Skjd } 126621910Skjd } 1267*22353Skjd 1268*22353Skjd 1269*22353Skjd chgreel(x, fl) 1270*22353Skjd int x, fl; 1271*22353Skjd { 1272*22353Skjd register int f; 1273*22353Skjd char str[BUFSIZ]; 1274*22353Skjd char *pstr; 1275*22353Skjd FILE *devtty; 1276*22353Skjd struct stat statb; 1277*22353Skjd 1278*22353Skjd perror("tar"); 1279*22353Skjd fprintf(stderr, "Can't %s\n", x ? "write output": "read input"); 1280*22353Skjd fstat(fl, &statb); 1281*22353Skjd if ((statb.st_mode & S_IFMT) != S_IFCHR) 1282*22353Skjd done(2); 1283*22353Skjd 1284*22353Skjd close(fl); 1285*22353Skjd devtty = fopen("/dev/tty", "r"); 1286*22353Skjd for (;;) { 1287*22353Skjd fprintf(stderr, "tar: If you want to go on, type \"yes\" or a new\npathname of a device/file name when you are ready\n"); 1288*22353Skjd if (fgets(str, sizeof (str), devtty) == NULL) 1289*22353Skjd break; 1290*22353Skjd str[strlen(str) - 1] = '\0'; 1291*22353Skjd 1292*22353Skjd switch (*str) { 1293*22353Skjd case '\0': 1294*22353Skjd case 'N': 1295*22353Skjd case 'n': 1296*22353Skjd goto done; 1297*22353Skjd 1298*22353Skjd case 'Y': 1299*22353Skjd case 'y': 1300*22353Skjd case '\n': 1301*22353Skjd pstr = usefile; 1302*22353Skjd break; 1303*22353Skjd 1304*22353Skjd default: 1305*22353Skjd pstr = str; 1306*22353Skjd } 1307*22353Skjd if ((f = open(pstr, x ? 1 : 0)) >= 0) { 1308*22353Skjd fclose(devtty); 1309*22353Skjd return (f); 1310*22353Skjd } 1311*22353Skjd fprintf(stderr, "tar: open of %s failed\n", pstr); 1312*22353Skjd } 1313*22353Skjd done: 1314*22353Skjd fclose(devtty); 1315*22353Skjd return (-1); 1316*22353Skjd } 1317