1*22502Sdist /* 2*22502Sdist * Copyright (c) 1980 Regents of the University of California. 3*22502Sdist * All rights reserved. The Berkeley software License Agreement 4*22502Sdist * specifies the terms and conditions for redistribution. 5*22502Sdist */ 6*22502Sdist 712154Ssam #ifndef lint 8*22502Sdist char copyright[] = 9*22502Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10*22502Sdist All rights reserved.\n"; 11*22502Sdist #endif not lint 126250Sroot 13*22502Sdist #ifndef lint 14*22502Sdist static char sccsid[] = "@(#)tar.c 5.1 (Berkeley) 06/06/85"; 15*22502Sdist #endif not lint 16*22502Sdist 176250Sroot /* 186250Sroot * Tape Archival Program 196250Sroot */ 201119Sbill #include <stdio.h> 216413Smckusic #include <sys/param.h> 221119Sbill #include <sys/stat.h> 2312154Ssam #include <sys/dir.h> 248150Smckusick #include <sys/ioctl.h> 253457Swnj #include <sys/mtio.h> 2612983Ssam #include <sys/time.h> 271119Sbill #include <signal.h> 2812154Ssam #include <errno.h> 291119Sbill 301119Sbill #define TBLOCK 512 313355Swnj #define NBLOCK 20 321119Sbill #define NAMSIZ 100 3322353Skjd #define FILEBLOCK 20 346250Sroot 3521457Skjd #define writetape(b) writetbuf(b, 1) 3621457Skjd #define min(a,b) ((a) < (b) ? (a) : (b)) 3721457Skjd #define max(a,b) ((a) > (b) ? (a) : (b)) 3821457Skjd 391119Sbill union hblock { 401119Sbill char dummy[TBLOCK]; 411119Sbill struct header { 421119Sbill char name[NAMSIZ]; 431119Sbill char mode[8]; 441119Sbill char uid[8]; 451119Sbill char gid[8]; 461119Sbill char size[12]; 471119Sbill char mtime[12]; 481119Sbill char chksum[8]; 491119Sbill char linkflag; 501119Sbill char linkname[NAMSIZ]; 511119Sbill } dbuf; 526250Sroot }; 531119Sbill 541119Sbill struct linkbuf { 551119Sbill ino_t inum; 561119Sbill dev_t devnum; 571119Sbill int count; 581119Sbill char pathname[NAMSIZ]; 591119Sbill struct linkbuf *nextp; 606250Sroot }; 611119Sbill 626250Sroot union hblock dblock; 6313492Ssam union hblock *tbuf; 646250Sroot struct linkbuf *ihead; 656250Sroot struct stat stbuf; 661119Sbill 676250Sroot int rflag; 686250Sroot int xflag; 696250Sroot int vflag; 706250Sroot int tflag; 716250Sroot int cflag; 726250Sroot int mflag; 736250Sroot int fflag; 7412154Ssam int iflag; 756250Sroot int oflag; 766250Sroot int pflag; 776250Sroot int wflag; 786250Sroot int hflag; 798737Smckusick int Bflag; 8012154Ssam int Fflag; 816250Sroot 826250Sroot int mt; 8322353Skjd int mtdev = 1; 846250Sroot int term; 856250Sroot int chksum; 866250Sroot int recno; 8722353Skjd int first = 0; 886250Sroot int linkerrok; 891119Sbill int freemem = 1; 9022353Skjd int nblock = 0; 916250Sroot int onintr(); 926250Sroot int onquit(); 936250Sroot int onhup(); 946250Sroot int onterm(); 951119Sbill 961119Sbill daddr_t low; 971119Sbill daddr_t high; 986250Sroot daddr_t bsrch(); 991119Sbill 10021910Skjd FILE *vfile = stdout; 1011119Sbill FILE *tfile; 1021119Sbill char tname[] = "/tmp/tarXXXXXX"; 1031119Sbill char *usefile; 1046250Sroot char magtape[] = "/dev/rmt8"; 1051119Sbill char *malloc(); 1066250Sroot char *sprintf(); 1076250Sroot char *strcat(); 10812154Ssam char *rindex(); 10910165Ssam char *getcwd(); 1109844Ssam char *getwd(); 1111119Sbill 1121119Sbill main(argc, argv) 1131119Sbill int argc; 1141119Sbill char *argv[]; 1151119Sbill { 1161119Sbill char *cp; 1171119Sbill 1181119Sbill if (argc < 2) 1191119Sbill usage(); 1201119Sbill 1211119Sbill tfile = NULL; 1221119Sbill usefile = magtape; 1231119Sbill argv[argc] = 0; 1241119Sbill argv++; 1251119Sbill for (cp = *argv++; *cp; cp++) 1261119Sbill switch(*cp) { 1276250Sroot 1281119Sbill case 'f': 12912154Ssam if (*argv == 0) { 13012154Ssam fprintf(stderr, 13112154Ssam "tar: tapefile must be specified with 'f' option\n"); 13212154Ssam usage(); 13312154Ssam } 1341119Sbill usefile = *argv++; 1351119Sbill fflag++; 1361119Sbill break; 1376250Sroot 1381119Sbill case 'c': 1391119Sbill cflag++; 1401119Sbill rflag++; 1411119Sbill break; 1426250Sroot 1431119Sbill case 'o': 1441119Sbill oflag++; 1451119Sbill break; 1466250Sroot 1471119Sbill case 'p': 1481119Sbill pflag++; 1491119Sbill break; 1506250Sroot 1511119Sbill case 'u': 1521119Sbill mktemp(tname); 1531119Sbill if ((tfile = fopen(tname, "w")) == NULL) { 1546250Sroot fprintf(stderr, 1556250Sroot "Tar: cannot create temporary file (%s)\n", 1566250Sroot tname); 1571119Sbill done(1); 1581119Sbill } 1591119Sbill fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n"); 1606250Sroot /*FALL THRU*/ 1616250Sroot 1621119Sbill case 'r': 1631119Sbill rflag++; 1641119Sbill break; 1656250Sroot 1661119Sbill case 'v': 1671119Sbill vflag++; 1681119Sbill break; 1696250Sroot 1701119Sbill case 'w': 1711119Sbill wflag++; 1721119Sbill break; 1736250Sroot 1741119Sbill case 'x': 1751119Sbill xflag++; 1761119Sbill break; 1776250Sroot 1781119Sbill case 't': 1791119Sbill tflag++; 1801119Sbill break; 1816250Sroot 1821119Sbill case 'm': 1831119Sbill mflag++; 1841119Sbill break; 1856250Sroot 1861119Sbill case '-': 1871119Sbill break; 1886250Sroot 1891119Sbill case '0': 1901119Sbill case '1': 1911119Sbill case '4': 1921119Sbill case '5': 19321457Skjd case '7': 1941119Sbill case '8': 1951119Sbill magtape[8] = *cp; 1961119Sbill usefile = magtape; 1971119Sbill break; 1986250Sroot 1991119Sbill case 'b': 20013492Ssam if (*argv == 0) { 20113492Ssam fprintf(stderr, 20213492Ssam "tar: blocksize must be specified with 'b' option\n"); 20313492Ssam usage(); 20413492Ssam } 20513492Ssam nblock = atoi(*argv); 20613492Ssam if (nblock <= 0) { 20713492Ssam fprintf(stderr, 20813492Ssam "tar: invalid blocksize \"%s\"\n", *argv); 2091119Sbill done(1); 2101119Sbill } 21113492Ssam argv++; 2121119Sbill break; 2136250Sroot 2141119Sbill case 'l': 2151119Sbill linkerrok++; 2161119Sbill break; 2176250Sroot 2186250Sroot case 'h': 2196250Sroot hflag++; 2206250Sroot break; 2216250Sroot 22212154Ssam case 'i': 22312154Ssam iflag++; 22412154Ssam break; 22512154Ssam 2268737Smckusick case 'B': 2278737Smckusick Bflag++; 2288737Smckusick break; 2298737Smckusick 23012154Ssam case 'F': 23112154Ssam Fflag++; 23212154Ssam break; 23312154Ssam 2341119Sbill default: 2351119Sbill fprintf(stderr, "tar: %c: unknown option\n", *cp); 2361119Sbill usage(); 2371119Sbill } 2381119Sbill 2396250Sroot if (!rflag && !xflag && !tflag) 2406250Sroot usage(); 2411119Sbill if (rflag) { 2426250Sroot if (cflag && tfile != NULL) 2431119Sbill usage(); 2441119Sbill if (signal(SIGINT, SIG_IGN) != SIG_IGN) 2451119Sbill signal(SIGINT, onintr); 2461119Sbill if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 2471119Sbill signal(SIGHUP, onhup); 2481119Sbill if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 2491119Sbill signal(SIGQUIT, onquit); 2506250Sroot #ifdef notdef 2511119Sbill if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 2521119Sbill signal(SIGTERM, onterm); 2536250Sroot #endif 2541119Sbill if (strcmp(usefile, "-") == 0) { 2551119Sbill if (cflag == 0) { 2566250Sroot fprintf(stderr, 25713492Ssam "tar: can only create standard output archives\n"); 2581119Sbill done(1); 2591119Sbill } 26021910Skjd vfile = stderr; 26121910Skjd setlinebuf(vfile); 2621119Sbill mt = dup(1); 2636250Sroot } else if ((mt = open(usefile, 2)) < 0) { 2641119Sbill if (cflag == 0 || (mt = creat(usefile, 0666)) < 0) { 2656250Sroot fprintf(stderr, 2666250Sroot "tar: cannot open %s\n", usefile); 2671119Sbill done(1); 2681119Sbill } 2691119Sbill } 2701119Sbill dorep(argv); 2716250Sroot done(0); 2721119Sbill } 2736250Sroot if (strcmp(usefile, "-") == 0) { 2746250Sroot mt = dup(0); 2756250Sroot } else if ((mt = open(usefile, 0)) < 0) { 2766250Sroot fprintf(stderr, "tar: cannot open %s\n", usefile); 2776250Sroot done(1); 2786250Sroot } 2796250Sroot if (xflag) 2801119Sbill doxtract(argv); 2816250Sroot else 2821119Sbill dotable(); 2831119Sbill done(0); 2841119Sbill } 2851119Sbill 2861119Sbill usage() 2871119Sbill { 2886250Sroot fprintf(stderr, 28921457Skjd "tar: usage: tar -{txru}[cvfblmhopwBi] [tapefile] [blocksize] file1 file2...\n"); 2901119Sbill done(1); 2911119Sbill } 2921119Sbill 2931119Sbill dorep(argv) 2946250Sroot char *argv[]; 2951119Sbill { 2961119Sbill register char *cp, *cp2; 2979601Ssam char wdir[MAXPATHLEN], tempdir[MAXPATHLEN], *parent; 2981119Sbill 2991119Sbill if (!cflag) { 3001119Sbill getdir(); 3011119Sbill do { 3021119Sbill passtape(); 3031119Sbill if (term) 3041119Sbill done(0); 3051119Sbill getdir(); 3061119Sbill } while (!endtape()); 30713492Ssam backtape(); 3081119Sbill if (tfile != NULL) { 3091119Sbill char buf[200]; 3101119Sbill 3116250Sroot sprintf(buf, 3126250Sroot "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX; mv %sX %s", 3131119Sbill tname, tname, tname, tname, tname, tname); 3141119Sbill fflush(tfile); 3151119Sbill system(buf); 3161119Sbill freopen(tname, "r", tfile); 3171119Sbill fstat(fileno(tfile), &stbuf); 3181119Sbill high = stbuf.st_size; 3191119Sbill } 3201119Sbill } 3211119Sbill 32210165Ssam (void) getcwd(wdir); 3231119Sbill while (*argv && ! term) { 3241119Sbill cp2 = *argv; 3251119Sbill if (!strcmp(cp2, "-C") && argv[1]) { 3261119Sbill argv++; 3271119Sbill if (chdir(*argv) < 0) 3281119Sbill perror(*argv); 3291119Sbill else 33010165Ssam (void) getcwd(wdir); 3311119Sbill argv++; 3321119Sbill continue; 3331119Sbill } 3349601Ssam parent = wdir; 3351119Sbill for (cp = *argv; *cp; cp++) 3361119Sbill if (*cp == '/') 3371119Sbill cp2 = cp; 3381119Sbill if (cp2 != *argv) { 3391119Sbill *cp2 = '\0'; 3409601Ssam if (chdir(*argv) < 0) { 3419601Ssam perror(*argv); 3429601Ssam continue; 3439601Ssam } 34410165Ssam parent = getcwd(tempdir); 3451119Sbill *cp2 = '/'; 3461119Sbill cp2++; 3471119Sbill } 3489601Ssam putfile(*argv++, cp2, parent); 34915045Smckusick if (chdir(wdir) < 0) { 35021457Skjd fprintf(stderr, "cannot change back?: "); 35115045Smckusick perror(wdir); 35215045Smckusick } 3531119Sbill } 3541119Sbill putempty(); 3551119Sbill putempty(); 3561119Sbill flushtape(); 3576250Sroot if (linkerrok == 0) 3586250Sroot return; 3596250Sroot for (; ihead != NULL; ihead = ihead->nextp) { 3606250Sroot if (ihead->count == 0) 3616250Sroot continue; 36213492Ssam fprintf(stderr, "tar: missing links to %s\n", ihead->pathname); 3636250Sroot } 3641119Sbill } 3651119Sbill 3661119Sbill endtape() 3671119Sbill { 36821457Skjd return (dblock.dbuf.name[0] == '\0'); 3691119Sbill } 3701119Sbill 3711119Sbill getdir() 3721119Sbill { 3731119Sbill register struct stat *sp; 3741119Sbill int i; 3751119Sbill 37612154Ssam top: 3776250Sroot readtape((char *)&dblock); 3781119Sbill if (dblock.dbuf.name[0] == '\0') 3791119Sbill return; 3801119Sbill sp = &stbuf; 3811119Sbill sscanf(dblock.dbuf.mode, "%o", &i); 3821119Sbill sp->st_mode = i; 3831119Sbill sscanf(dblock.dbuf.uid, "%o", &i); 3841119Sbill sp->st_uid = i; 3851119Sbill sscanf(dblock.dbuf.gid, "%o", &i); 3861119Sbill sp->st_gid = i; 3871119Sbill sscanf(dblock.dbuf.size, "%lo", &sp->st_size); 3881119Sbill sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime); 3891119Sbill sscanf(dblock.dbuf.chksum, "%o", &chksum); 39012154Ssam if (chksum != (i = checksum())) { 39113492Ssam fprintf(stderr, "tar: directory checksum error (%d != %d)\n", 39212154Ssam chksum, i); 39312154Ssam if (iflag) 39412154Ssam goto top; 3951119Sbill done(2); 3961119Sbill } 3971119Sbill if (tfile != NULL) 3981119Sbill fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime); 3991119Sbill } 4001119Sbill 4011119Sbill passtape() 4021119Sbill { 4031119Sbill long blocks; 40421457Skjd char *bufp; 4051119Sbill 4061119Sbill if (dblock.dbuf.linkflag == '1') 4071119Sbill return; 4081119Sbill blocks = stbuf.st_size; 4091119Sbill blocks += TBLOCK-1; 4101119Sbill blocks /= TBLOCK; 4111119Sbill 41221457Skjd while (blocks-- > 0) 41321457Skjd readtbuf(&bufp, TBLOCK); 4141119Sbill } 4151119Sbill 4169601Ssam putfile(longname, shortname, parent) 4176250Sroot char *longname; 4186250Sroot char *shortname; 4199601Ssam char *parent; 4201119Sbill { 42121457Skjd int infile = 0; 42221457Skjd long blocks; 4231119Sbill char buf[TBLOCK]; 42421457Skjd char *origbuf; 42521457Skjd char *bigbuf; 4261119Sbill register char *cp, *cp2; 4275931Smckusic struct direct *dp; 4285931Smckusic DIR *dirp; 42921457Skjd int i, j; 4309601Ssam char newparent[NAMSIZ+64]; 43112154Ssam extern int errno; 43221457Skjd int maxread; 43321457Skjd int hint; /* amount to write to get "in sync" */ 4341119Sbill 4359601Ssam if (!hflag) 43612154Ssam i = lstat(shortname, &stbuf); 43712154Ssam else 43812154Ssam i = stat(shortname, &stbuf); 43912154Ssam if (i < 0) { 44012154Ssam switch (errno) { 44112154Ssam case EACCES: 44212154Ssam fprintf(stderr, "tar: %s: cannot open file\n", longname); 44312154Ssam break; 44412154Ssam case ENOENT: 44512154Ssam fprintf(stderr, "tar: %s: no such file or directory\n", 44612154Ssam longname); 44712154Ssam break; 44812154Ssam default: 44912154Ssam fprintf(stderr, "tar: %s: cannot stat file\n", longname); 45012154Ssam break; 45112154Ssam } 4529601Ssam return; 4539601Ssam } 45412154Ssam if (tfile != NULL && checkupdate(longname) == 0) 4551119Sbill return; 45612154Ssam if (checkw('r', longname) == 0) 4571119Sbill return; 45812154Ssam if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0) 45912154Ssam return; 4601119Sbill 46112154Ssam switch (stbuf.st_mode & S_IFMT) { 46212154Ssam case S_IFDIR: 4636250Sroot for (i = 0, cp = buf; *cp++ = longname[i++];) 4646250Sroot ; 4651119Sbill *--cp = '/'; 4661119Sbill *++cp = 0 ; 4671119Sbill if (!oflag) { 4686250Sroot if ((cp - buf) >= NAMSIZ) { 46913492Ssam fprintf(stderr, "tar: %s: file name too long\n", 47013492Ssam longname); 4716250Sroot return; 4726250Sroot } 4736250Sroot stbuf.st_size = 0; 4746250Sroot tomodes(&stbuf); 4756250Sroot strcpy(dblock.dbuf.name,buf); 4766250Sroot sprintf(dblock.dbuf.chksum, "%6o", checksum()); 4776250Sroot writetape((char *)&dblock); 4781119Sbill } 4799601Ssam sprintf(newparent, "%s/%s", parent, shortname); 48015045Smckusick if (chdir(shortname) < 0) { 48115045Smckusick perror(shortname); 48215045Smckusick return; 48315045Smckusick } 4845931Smckusic if ((dirp = opendir(".")) == NULL) { 48513492Ssam fprintf(stderr, "tar: %s: directory read error\n", 48613492Ssam longname); 48715045Smckusick if (chdir(parent) < 0) { 48821457Skjd fprintf(stderr, "cannot change back?: "); 48915045Smckusick perror(parent); 49015045Smckusick } 4915931Smckusic return; 4925931Smckusic } 4935931Smckusic while ((dp = readdir(dirp)) != NULL && !term) { 4945931Smckusic if (dp->d_ino == 0) 4951119Sbill continue; 4966250Sroot if (!strcmp(".", dp->d_name) || 4976250Sroot !strcmp("..", dp->d_name)) 4981119Sbill continue; 4995931Smckusic strcpy(cp, dp->d_name); 5005931Smckusic i = telldir(dirp); 5015931Smckusic closedir(dirp); 5029601Ssam putfile(buf, cp, newparent); 5035931Smckusic dirp = opendir("."); 5045931Smckusic seekdir(dirp, i); 5051119Sbill } 5065931Smckusic closedir(dirp); 50715045Smckusick if (chdir(parent) < 0) { 50821457Skjd fprintf(stderr, "cannot change back?: "); 50915045Smckusick perror(parent); 51015045Smckusick } 51112154Ssam break; 51212154Ssam 51312154Ssam case S_IFLNK: 51412154Ssam tomodes(&stbuf); 51512154Ssam if (strlen(longname) >= NAMSIZ) { 51613492Ssam fprintf(stderr, "tar: %s: file name too long\n", 51713492Ssam longname); 51812154Ssam return; 51912154Ssam } 52012154Ssam strcpy(dblock.dbuf.name, longname); 5216250Sroot if (stbuf.st_size + 1 >= NAMSIZ) { 52213492Ssam fprintf(stderr, "tar: %s: symbolic link too long\n", 52313492Ssam longname); 5246250Sroot return; 5256250Sroot } 5269601Ssam i = readlink(shortname, dblock.dbuf.linkname, NAMSIZ - 1); 5276250Sroot if (i < 0) { 5289601Ssam perror(longname); 5296250Sroot return; 5306250Sroot } 5316250Sroot dblock.dbuf.linkname[i] = '\0'; 5326250Sroot dblock.dbuf.linkflag = '2'; 5336250Sroot if (vflag) { 53421910Skjd fprintf(vfile, "a %s ", longname); 53521910Skjd fprintf(vfile, "symbolic link to %s\n", 53613492Ssam dblock.dbuf.linkname); 5376250Sroot } 5386250Sroot sprintf(dblock.dbuf.size, "%11lo", 0); 5396250Sroot sprintf(dblock.dbuf.chksum, "%6o", checksum()); 5406250Sroot writetape((char *)&dblock); 54112154Ssam break; 5421119Sbill 54312154Ssam case S_IFREG: 54412154Ssam if ((infile = open(shortname, 0)) < 0) { 54512154Ssam fprintf(stderr, "tar: %s: cannot open file\n", longname); 5461119Sbill return; 5471119Sbill } 54812154Ssam tomodes(&stbuf); 54912154Ssam if (strlen(longname) >= NAMSIZ) { 55013492Ssam fprintf(stderr, "tar: %s: file name too long\n", 55113492Ssam longname); 55221457Skjd close(infile); 55312154Ssam return; 55412154Ssam } 55512154Ssam strcpy(dblock.dbuf.name, longname); 55612154Ssam if (stbuf.st_nlink > 1) { 55712154Ssam struct linkbuf *lp; 55812154Ssam int found = 0; 55912154Ssam 56012154Ssam for (lp = ihead; lp != NULL; lp = lp->nextp) 56112154Ssam if (lp->inum == stbuf.st_ino && 56212154Ssam lp->devnum == stbuf.st_dev) { 56312154Ssam found++; 56412154Ssam break; 56512154Ssam } 56612154Ssam if (found) { 56712154Ssam strcpy(dblock.dbuf.linkname, lp->pathname); 56812154Ssam dblock.dbuf.linkflag = '1'; 56912154Ssam sprintf(dblock.dbuf.chksum, "%6o", checksum()); 57021457Skjd writetape( (char *) &dblock); 57112154Ssam if (vflag) { 57221910Skjd fprintf(vfile, "a %s ", longname); 57321910Skjd fprintf(vfile, "link to %s\n", 57413492Ssam lp->pathname); 57512154Ssam } 57612154Ssam lp->count--; 57712154Ssam close(infile); 57812154Ssam return; 5791119Sbill } 58012154Ssam lp = (struct linkbuf *) malloc(sizeof(*lp)); 58112154Ssam if (lp == NULL) { 58212154Ssam if (freemem) { 58312154Ssam fprintf(stderr, 58413492Ssam "tar: out of memory, link information lost\n"); 58512154Ssam freemem = 0; 58612154Ssam } 58712154Ssam } else { 58812154Ssam lp->nextp = ihead; 58912154Ssam ihead = lp; 59012154Ssam lp->inum = stbuf.st_ino; 59112154Ssam lp->devnum = stbuf.st_dev; 59212154Ssam lp->count = stbuf.st_nlink - 1; 59312154Ssam strcpy(lp->pathname, longname); 59412154Ssam } 5951119Sbill } 59621457Skjd blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK; 59712154Ssam if (vflag) { 59821910Skjd fprintf(vfile, "a %s ", longname); 59921910Skjd fprintf(vfile, "%ld blocks\n", blocks); 60012154Ssam } 60112154Ssam sprintf(dblock.dbuf.chksum, "%6o", checksum()); 60221457Skjd hint = writetape((char *)&dblock); 60321457Skjd maxread = max(stbuf.st_blksize, (nblock * TBLOCK)); 60421457Skjd if ((bigbuf = malloc(maxread)) == 0) { 60521457Skjd maxread = TBLOCK; 60621457Skjd bigbuf = buf; 60721457Skjd } 6081119Sbill 60921457Skjd while ((i = read(infile, bigbuf, min((hint*TBLOCK), maxread))) > 0 61021457Skjd && blocks > 0) { 61121457Skjd register int nblks; 61221457Skjd 61321457Skjd nblks = ((i-1)/TBLOCK)+1; 61421457Skjd if (nblks > blocks) 61521457Skjd nblks = blocks; 61621457Skjd hint = writetbuf(bigbuf, nblks); 61721457Skjd blocks -= nblks; 61821457Skjd } 61921457Skjd close(infile); 62021457Skjd if (bigbuf != buf) 62121457Skjd free(bigbuf); 62221457Skjd if (blocks != 0 || i != 0) 62313492Ssam fprintf(stderr, "tar: %s: file changed size\n", 62413492Ssam longname); 62512154Ssam while (--blocks >= 0) 62612154Ssam putempty(); 62712154Ssam break; 62812154Ssam 62912154Ssam default: 63012154Ssam fprintf(stderr, "tar: %s is not a file. Not dumped\n", 63113492Ssam longname); 63212154Ssam break; 6331119Sbill } 6341119Sbill } 6351119Sbill 6361119Sbill doxtract(argv) 6376250Sroot char *argv[]; 6381119Sbill { 6391119Sbill long blocks, bytes; 6401119Sbill char **cp; 6411119Sbill int ofile; 6421119Sbill 6431119Sbill for (;;) { 6441119Sbill getdir(); 6451119Sbill if (endtape()) 6461119Sbill break; 6471119Sbill if (*argv == 0) 6481119Sbill goto gotit; 6491119Sbill for (cp = argv; *cp; cp++) 6501119Sbill if (prefix(*cp, dblock.dbuf.name)) 6511119Sbill goto gotit; 6521119Sbill passtape(); 6531119Sbill continue; 6541119Sbill 6551119Sbill gotit: 6561119Sbill if (checkw('x', dblock.dbuf.name) == 0) { 6571119Sbill passtape(); 6581119Sbill continue; 6591119Sbill } 66012154Ssam if (Fflag) { 66112154Ssam char *s; 66212154Ssam 66312154Ssam if ((s = rindex(dblock.dbuf.name, '/')) == 0) 66412154Ssam s = dblock.dbuf.name; 66512154Ssam else 66612154Ssam s++; 66712154Ssam if (checkf(s, stbuf.st_mode, Fflag) == 0) { 66812154Ssam passtape(); 66912154Ssam continue; 67012154Ssam } 67112154Ssam } 6726250Sroot if (checkdir(dblock.dbuf.name)) 6736250Sroot continue; 6746250Sroot if (dblock.dbuf.linkflag == '2') { 6756250Sroot unlink(dblock.dbuf.name); 6766250Sroot if (symlink(dblock.dbuf.linkname, dblock.dbuf.name)<0) { 67713492Ssam fprintf(stderr, "tar: %s: symbolic link failed\n", 67813492Ssam dblock.dbuf.name); 6796250Sroot continue; 6806250Sroot } 6816250Sroot if (vflag) 68221910Skjd fprintf(vfile, "x %s symbolic link to %s\n", 68313492Ssam dblock.dbuf.name, dblock.dbuf.linkname); 68422353Skjd #ifdef notdef 68522353Skjd /* ignore alien orders */ 68622353Skjd chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 68722353Skjd if (mflag == 0) { 68822353Skjd struct timeval tv[2]; 68922353Skjd 69022353Skjd tv[0].tv_sec = time(0); 69122353Skjd tv[0].tv_usec = 0; 69222353Skjd tv[1].tv_sec = stbuf.st_mtime; 69322353Skjd tv[1].tv_usec = 0; 69422353Skjd utimes(dblock.dbuf.name, tv); 69522353Skjd } 69622353Skjd if (pflag) 69722353Skjd chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 69822353Skjd #endif 6991119Sbill continue; 7006250Sroot } 7011119Sbill if (dblock.dbuf.linkflag == '1') { 7021119Sbill unlink(dblock.dbuf.name); 7031119Sbill if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) { 70413492Ssam fprintf(stderr, "tar: %s: cannot link\n", 70513492Ssam dblock.dbuf.name); 7061119Sbill continue; 7071119Sbill } 7081119Sbill if (vflag) 70922353Skjd fprintf(vfile, "%s linked to %s", 71013492Ssam dblock.dbuf.name, dblock.dbuf.linkname); 7111119Sbill continue; 7121119Sbill } 7136250Sroot if ((ofile = creat(dblock.dbuf.name,stbuf.st_mode&0xfff)) < 0) { 7146250Sroot fprintf(stderr, "tar: %s - cannot create\n", 71513492Ssam dblock.dbuf.name); 7161119Sbill passtape(); 7171119Sbill continue; 7181119Sbill } 71921457Skjd chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 7201119Sbill blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK; 7211119Sbill if (vflag) 72222353Skjd fprintf(vfile, "x %s, %ld bytes, %ld tape blocks", 72313492Ssam dblock.dbuf.name, bytes, blocks); 72421457Skjd for (; blocks > 0;) { 72521457Skjd register int nread; 72621457Skjd char *bufp; 72721457Skjd register int nwant; 72821457Skjd 72921457Skjd nwant = NBLOCK*TBLOCK; 73021457Skjd if (nwant > (blocks*TBLOCK)) 73121457Skjd nwant = (blocks*TBLOCK); 73221457Skjd nread = readtbuf(&bufp, nwant); 73321457Skjd if (bytes > nread) { 73421457Skjd if (write(ofile, bufp, nread) < 0) { 73521457Skjd fprintf(stderr, 73621457Skjd "tar: %s: HELP - extract write error\n", 73721457Skjd dblock.dbuf.name); 73821457Skjd done(2); 73921457Skjd } 74021457Skjd } else if (write(ofile, bufp, (int) bytes) < 0) { 7416250Sroot fprintf(stderr, 74213492Ssam "tar: %s: HELP - extract write error\n", 74313492Ssam dblock.dbuf.name); 7446250Sroot done(2); 7456250Sroot } 74621457Skjd bytes -= nread; 74721457Skjd blocks -= (((nread-1)/TBLOCK)+1); 74822353Skjd fprintf(stderr,"\n"); 7491119Sbill } 7501119Sbill close(ofile); 7511119Sbill if (mflag == 0) { 75212983Ssam struct timeval tv[2]; 7531119Sbill 75412983Ssam tv[0].tv_sec = time(0); 75512983Ssam tv[0].tv_usec = 0; 75612983Ssam tv[1].tv_sec = stbuf.st_mtime; 75712983Ssam tv[1].tv_usec = 0; 75812983Ssam utimes(dblock.dbuf.name, tv); 7591119Sbill } 7601926Swnj if (pflag) 7616250Sroot chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 7621119Sbill } 7631119Sbill } 7641119Sbill 7651119Sbill dotable() 7661119Sbill { 7671119Sbill for (;;) { 7681119Sbill getdir(); 7691119Sbill if (endtape()) 7701119Sbill break; 7711119Sbill if (vflag) 7721119Sbill longt(&stbuf); 7731119Sbill printf("%s", dblock.dbuf.name); 7741119Sbill if (dblock.dbuf.linkflag == '1') 7751119Sbill printf(" linked to %s", dblock.dbuf.linkname); 7766250Sroot if (dblock.dbuf.linkflag == '2') 7776250Sroot printf(" symbolic link to %s", dblock.dbuf.linkname); 7781119Sbill printf("\n"); 7791119Sbill passtape(); 7801119Sbill } 7811119Sbill } 7821119Sbill 7831119Sbill putempty() 7841119Sbill { 7851119Sbill char buf[TBLOCK]; 7861119Sbill 78713492Ssam bzero(buf, sizeof (buf)); 7881119Sbill writetape(buf); 7891119Sbill } 7901119Sbill 7911119Sbill longt(st) 7926250Sroot register struct stat *st; 7931119Sbill { 7941119Sbill register char *cp; 7951119Sbill char *ctime(); 7961119Sbill 7971119Sbill pmode(st); 7981119Sbill printf("%3d/%1d", st->st_uid, st->st_gid); 7991119Sbill printf("%7D", st->st_size); 8001119Sbill cp = ctime(&st->st_mtime); 8011119Sbill printf(" %-12.12s %-4.4s ", cp+4, cp+20); 8021119Sbill } 8031119Sbill 8041119Sbill #define SUID 04000 8051119Sbill #define SGID 02000 8061119Sbill #define ROWN 0400 8071119Sbill #define WOWN 0200 8081119Sbill #define XOWN 0100 8091119Sbill #define RGRP 040 8101119Sbill #define WGRP 020 8111119Sbill #define XGRP 010 8121119Sbill #define ROTH 04 8131119Sbill #define WOTH 02 8141119Sbill #define XOTH 01 8151119Sbill #define STXT 01000 8161119Sbill int m1[] = { 1, ROWN, 'r', '-' }; 8171119Sbill int m2[] = { 1, WOWN, 'w', '-' }; 8181119Sbill int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 8191119Sbill int m4[] = { 1, RGRP, 'r', '-' }; 8201119Sbill int m5[] = { 1, WGRP, 'w', '-' }; 8211119Sbill int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 8221119Sbill int m7[] = { 1, ROTH, 'r', '-' }; 8231119Sbill int m8[] = { 1, WOTH, 'w', '-' }; 8241119Sbill int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 8251119Sbill 8261119Sbill int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 8271119Sbill 8281119Sbill pmode(st) 8296250Sroot register struct stat *st; 8301119Sbill { 8311119Sbill register int **mp; 8321119Sbill 8331119Sbill for (mp = &m[0]; mp < &m[9];) 8341119Sbill select(*mp++, st); 8351119Sbill } 8361119Sbill 8371119Sbill select(pairp, st) 8386250Sroot int *pairp; 8396250Sroot struct stat *st; 8401119Sbill { 8411119Sbill register int n, *ap; 8421119Sbill 8431119Sbill ap = pairp; 8441119Sbill n = *ap++; 8451119Sbill while (--n>=0 && (st->st_mode&*ap++)==0) 8461119Sbill ap++; 8471119Sbill printf("%c", *ap); 8481119Sbill } 8491119Sbill 8501119Sbill checkdir(name) 8516250Sroot register char *name; 8521119Sbill { 8531119Sbill register char *cp; 8546250Sroot 85512154Ssam /* 85612154Ssam * Quick check for existance of directory. 85712154Ssam */ 85812154Ssam if ((cp = rindex(name, '/')) == 0) 85912154Ssam return (0); 86012154Ssam *cp = '\0'; 86112154Ssam if (access(name, 0) >= 0) { 86212154Ssam *cp = '/'; 86312154Ssam return (cp[1] == '\0'); 86412154Ssam } 86512154Ssam *cp = '/'; 86612154Ssam 86712154Ssam /* 86812154Ssam * No luck, try to make all directories in path. 86912154Ssam */ 8701119Sbill for (cp = name; *cp; cp++) { 8716250Sroot if (*cp != '/') 8726250Sroot continue; 8736250Sroot *cp = '\0'; 87412154Ssam if (access(name, 0) < 0) { 8759844Ssam if (mkdir(name, 0777) < 0) { 8769844Ssam perror(name); 87712154Ssam *cp = '/'; 87812154Ssam return (0); 8791119Sbill } 88021457Skjd chown(name, stbuf.st_uid, stbuf.st_gid); 88114956Skarels if (pflag && cp[1] == '\0') 8829844Ssam chmod(name, stbuf.st_mode & 0777); 8831119Sbill } 8846250Sroot *cp = '/'; 8851119Sbill } 8866250Sroot return (cp[-1]=='/'); 8871119Sbill } 8881119Sbill 8891119Sbill onintr() 8901119Sbill { 8911119Sbill signal(SIGINT, SIG_IGN); 8921119Sbill term++; 8931119Sbill } 8941119Sbill 8951119Sbill onquit() 8961119Sbill { 8971119Sbill signal(SIGQUIT, SIG_IGN); 8981119Sbill term++; 8991119Sbill } 9001119Sbill 9011119Sbill onhup() 9021119Sbill { 9031119Sbill signal(SIGHUP, SIG_IGN); 9041119Sbill term++; 9051119Sbill } 9061119Sbill 9071119Sbill onterm() 9081119Sbill { 9091119Sbill signal(SIGTERM, SIG_IGN); 9101119Sbill term++; 9111119Sbill } 9121119Sbill 9131119Sbill tomodes(sp) 9141119Sbill register struct stat *sp; 9151119Sbill { 9161119Sbill register char *cp; 9171119Sbill 9181119Sbill for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 9191119Sbill *cp = '\0'; 9201119Sbill sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); 9211119Sbill sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); 9221119Sbill sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); 9231119Sbill sprintf(dblock.dbuf.size, "%11lo ", sp->st_size); 9241119Sbill sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime); 9251119Sbill } 9261119Sbill 9271119Sbill checksum() 9281119Sbill { 9291119Sbill register i; 9301119Sbill register char *cp; 9311119Sbill 9326250Sroot for (cp = dblock.dbuf.chksum; 9336250Sroot cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++) 9341119Sbill *cp = ' '; 9351119Sbill i = 0; 9361119Sbill for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 9371119Sbill i += *cp; 9386250Sroot return (i); 9391119Sbill } 9401119Sbill 9411119Sbill checkw(c, name) 9426250Sroot char *name; 9431119Sbill { 9446250Sroot if (!wflag) 9456250Sroot return (1); 9466250Sroot printf("%c ", c); 9476250Sroot if (vflag) 9486250Sroot longt(&stbuf); 9496250Sroot printf("%s: ", name); 9506250Sroot return (response() == 'y'); 9511119Sbill } 9521119Sbill 9531119Sbill response() 9541119Sbill { 9551119Sbill char c; 9561119Sbill 9571119Sbill c = getchar(); 9581119Sbill if (c != '\n') 9596250Sroot while (getchar() != '\n') 9606250Sroot ; 9616250Sroot else 9626250Sroot c = 'n'; 9636250Sroot return (c); 9641119Sbill } 9651119Sbill 96612154Ssam checkf(name, mode, howmuch) 96712154Ssam char *name; 96812154Ssam int mode, howmuch; 96912154Ssam { 97012154Ssam int l; 97112154Ssam 97221910Skjd if ((mode & S_IFMT) == S_IFDIR){ 97321910Skjd if ((strcmp(name, "SCCS")==0) || (strcmp(name, "RCS")==0)) 97421910Skjd return(0); 97521910Skjd return(1); 97621910Skjd } 97712154Ssam if ((l = strlen(name)) < 3) 97812154Ssam return (1); 97912154Ssam if (howmuch > 1 && name[l-2] == '.' && name[l-1] == 'o') 98012154Ssam return (0); 98112154Ssam if (strcmp(name, "core") == 0 || 98212154Ssam strcmp(name, "errs") == 0 || 98312154Ssam (howmuch > 1 && strcmp(name, "a.out") == 0)) 98412154Ssam return (0); 98512154Ssam /* SHOULD CHECK IF IT IS EXECUTABLE */ 98612154Ssam return (1); 98712154Ssam } 98812154Ssam 9891119Sbill checkupdate(arg) 9906250Sroot char *arg; 9911119Sbill { 9921119Sbill char name[100]; 9936250Sroot long mtime; 9941119Sbill daddr_t seekp; 9951119Sbill daddr_t lookup(); 9961119Sbill 9971119Sbill rewind(tfile); 9981119Sbill for (;;) { 9991119Sbill if ((seekp = lookup(arg)) < 0) 10006250Sroot return (1); 10011119Sbill fseek(tfile, seekp, 0); 10021119Sbill fscanf(tfile, "%s %lo", name, &mtime); 10036250Sroot return (stbuf.st_mtime > mtime); 10041119Sbill } 10051119Sbill } 10061119Sbill 10071119Sbill done(n) 10081119Sbill { 100921457Skjd unlink(tname); 10101119Sbill exit(n); 10111119Sbill } 10121119Sbill 10131119Sbill prefix(s1, s2) 10146250Sroot register char *s1, *s2; 10151119Sbill { 10161119Sbill while (*s1) 10171119Sbill if (*s1++ != *s2++) 10186250Sroot return (0); 10191119Sbill if (*s2) 10206250Sroot return (*s2 == '/'); 10216250Sroot return (1); 10221119Sbill } 10231119Sbill 10241119Sbill #define N 200 10251119Sbill int njab; 10266250Sroot 10271119Sbill daddr_t 10281119Sbill lookup(s) 10296250Sroot char *s; 10301119Sbill { 10311119Sbill register i; 10321119Sbill daddr_t a; 10331119Sbill 10341119Sbill for(i=0; s[i]; i++) 10356250Sroot if (s[i] == ' ') 10361119Sbill break; 10371119Sbill a = bsrch(s, i, low, high); 10386250Sroot return (a); 10391119Sbill } 10401119Sbill 10411119Sbill daddr_t 10421119Sbill bsrch(s, n, l, h) 10436250Sroot daddr_t l, h; 10446250Sroot char *s; 10451119Sbill { 10461119Sbill register i, j; 10471119Sbill char b[N]; 10481119Sbill daddr_t m, m1; 10491119Sbill 10501119Sbill njab = 0; 10511119Sbill 10521119Sbill loop: 10536250Sroot if (l >= h) 10546250Sroot return (-1L); 10551119Sbill m = l + (h-l)/2 - N/2; 10566250Sroot if (m < l) 10571119Sbill m = l; 10581119Sbill fseek(tfile, m, 0); 10591119Sbill fread(b, 1, N, tfile); 10601119Sbill njab++; 10611119Sbill for(i=0; i<N; i++) { 10626250Sroot if (b[i] == '\n') 10631119Sbill break; 10641119Sbill m++; 10651119Sbill } 10666250Sroot if (m >= h) 10676250Sroot return (-1L); 10681119Sbill m1 = m; 10691119Sbill j = i; 10701119Sbill for(i++; i<N; i++) { 10711119Sbill m1++; 10726250Sroot if (b[i] == '\n') 10731119Sbill break; 10741119Sbill } 10751119Sbill i = cmp(b+j, s, n); 10766250Sroot if (i < 0) { 10771119Sbill h = m; 10781119Sbill goto loop; 10791119Sbill } 10806250Sroot if (i > 0) { 10811119Sbill l = m1; 10821119Sbill goto loop; 10831119Sbill } 10846250Sroot return (m); 10851119Sbill } 10861119Sbill 10871119Sbill cmp(b, s, n) 10886250Sroot char *b, *s; 10891119Sbill { 10901119Sbill register i; 10911119Sbill 10926250Sroot if (b[0] != '\n') 109321457Skjd exit(2); 10941119Sbill for(i=0; i<n; i++) { 10956250Sroot if (b[i+1] > s[i]) 10966250Sroot return (-1); 10976250Sroot if (b[i+1] < s[i]) 10986250Sroot return (1); 10991119Sbill } 11006250Sroot return (b[i+1] == ' '? 0 : -1); 11011119Sbill } 11021119Sbill 110321457Skjd readtape (buffer) 11046250Sroot char *buffer; 11051119Sbill { 110621457Skjd char *bufp; 110721457Skjd int nread; 110821457Skjd 110921910Skjd if (first==0) getbuf(); 111021457Skjd readtbuf (&bufp, TBLOCK); 111121457Skjd bcopy(bufp, buffer, TBLOCK); 111221457Skjd return(TBLOCK); 111321457Skjd } 111421457Skjd 111521457Skjd readtbuf(bufpp, size) 111621457Skjd char **bufpp; 111721457Skjd int size; 111821457Skjd { 11193457Swnj register int i; 11201119Sbill 11211119Sbill if (recno >= nblock || first == 0) { 11228737Smckusick if ((i = bread(mt, tbuf, TBLOCK*nblock)) < 0) { 112313492Ssam fprintf(stderr, "tar: tape read error\n"); 11241119Sbill done(3); 11251119Sbill } 11261119Sbill if (first == 0) { 11271119Sbill if ((i % TBLOCK) != 0) { 112813492Ssam fprintf(stderr, "tar: tape blocksize error\n"); 11291119Sbill done(3); 11301119Sbill } 11311119Sbill i /= TBLOCK; 11323457Swnj if (i != nblock) { 113313492Ssam fprintf(stderr, "tar: blocksize = %d\n", i); 11341119Sbill nblock = i; 11351119Sbill } 113622353Skjd first = 1; 11371119Sbill } 11381119Sbill recno = 0; 11391119Sbill } 114021457Skjd if (size > ((nblock-recno)*TBLOCK)) 114121457Skjd size = (nblock-recno)*TBLOCK; 114221457Skjd *bufpp = (char *)&tbuf[recno]; 114321457Skjd recno += (size/TBLOCK); 114421457Skjd return (size); 11451119Sbill } 11461119Sbill 114721457Skjd writetbuf(buffer, n) 114821457Skjd register char *buffer; 114921457Skjd register int n; 11501119Sbill { 115122353Skjd int i; 115222353Skjd if (first==0) { 115322353Skjd getbuf(); 115422353Skjd first = 1; 115522353Skjd } 11561119Sbill if (recno >= nblock) { 115722353Skjd if ( write(mt, tbuf, TBLOCK*nblock) < 0) { 115822353Skjd perror("tar"); 11591119Sbill done(2); 11601119Sbill } 11611119Sbill recno = 0; 11621119Sbill } 116321457Skjd 116421457Skjd /* 116521457Skjd * Special case: We have an empty tape buffer, and the 116621457Skjd * users data size is >= the tape block size: Avoid 116721457Skjd * the bcopy and dma direct to tape. BIG WIN. Add the 116821457Skjd * residual to the tape buffer. 116921457Skjd */ 117021457Skjd while (recno == 0 && n >= nblock) { 117121457Skjd if (write(mt, buffer, TBLOCK*nblock) < 0) { 117222353Skjd perror("tar"); 11731119Sbill done(2); 11741119Sbill } 117521457Skjd n -= nblock; 117621457Skjd buffer += (nblock * TBLOCK); 11771119Sbill } 117821457Skjd 117921457Skjd while (n-- > 0) { 118021457Skjd bcopy(buffer, (char *)&tbuf[recno++], TBLOCK); 118121457Skjd buffer += TBLOCK; 118221457Skjd if (recno >= nblock) { 118321457Skjd if (write(mt, tbuf, TBLOCK*nblock) < 0) { 118422353Skjd fprintf(stderr,"tar: tape write error\n"); 118522353Skjd done(2); 118621457Skjd } 118721457Skjd recno = 0; 118821457Skjd } 118921457Skjd } 119021457Skjd 119121457Skjd /* Tell the user how much to write to get in sync */ 119221457Skjd return (nblock - recno); 11931119Sbill } 11941119Sbill 11951119Sbill backtape() 11961119Sbill { 11973457Swnj static struct mtop mtop = {MTBSR, 1}; 11983457Swnj struct mtget mtget; 11993457Swnj 12003457Swnj if (mtdev == 0) { 12013457Swnj if (ioctl(mt, MTIOCTOP, &mtop) < 0) { 120213492Ssam fprintf(stderr, "tar: tape backspace error\n"); 12031119Sbill done(4); 12041119Sbill } 12053457Swnj } else 12063457Swnj lseek(mt, (long) -TBLOCK*nblock, 1); 12073457Swnj recno--; 12081119Sbill } 12091119Sbill 12101119Sbill flushtape() 12111119Sbill { 121221457Skjd write(mt, tbuf, TBLOCK*nblock); 12131119Sbill } 12141119Sbill 12158737Smckusick bread(fd, buf, size) 12168737Smckusick int fd; 12178737Smckusick char *buf; 12188737Smckusick int size; 12198737Smckusick { 12208737Smckusick int count; 122122353Skjd int i; 12228737Smckusick static int lastread = 0; 12238737Smckusick 122422353Skjd if (!Bflag) { 122522353Skjd return (read(fd, buf, size)); 122622353Skjd } 122722353Skjd 122822353Skjd 12298737Smckusick for (count = 0; count < size; count += lastread) { 12308737Smckusick if (lastread < 0) { 12318737Smckusick if (count > 0) 12328737Smckusick return (count); 12338737Smckusick return (lastread); 12348737Smckusick } 12358737Smckusick lastread = read(fd, buf, size - count); 12368737Smckusick buf += lastread; 12378737Smckusick } 12388737Smckusick return (count); 12398737Smckusick } 124010165Ssam 124110165Ssam char * 124210165Ssam getcwd(buf) 124310165Ssam char *buf; 124410165Ssam { 124510165Ssam if (getwd(buf) == NULL) { 124610165Ssam fprintf(stderr, "tar: %s\n", buf); 124721457Skjd exit(1); 124810165Ssam } 124910165Ssam return (buf); 125010165Ssam } 125121910Skjd 125221910Skjd getbuf() 125321910Skjd { 125422353Skjd struct mtget mtget; 125522353Skjd 125621910Skjd if ( mtdev == 1) { 125721910Skjd fstat(mt, &stbuf); 125821910Skjd if ((stbuf.st_mode & S_IFMT) == S_IFCHR) 125921910Skjd mtdev = 0; 126021910Skjd else 126121910Skjd mtdev = -1; 126221910Skjd } 126322353Skjd if (nblock==0) { 126421910Skjd if (mtdev == 0) 126521910Skjd nblock = FILEBLOCK; 126621910Skjd else { 126721910Skjd fstat(mt, &stbuf); 126821910Skjd nblock = stbuf.st_blocks / TBLOCK; 126921910Skjd } 127021910Skjd } 127122353Skjd if (nblock == 0) nblock = FILEBLOCK; 127221910Skjd tbuf = (union hblock *)malloc(nblock*TBLOCK); 127321910Skjd if (tbuf == NULL) { 127421910Skjd fprintf(stderr, "tar: blocksize %d too big, can't get memory\n", 127521910Skjd nblock); 127621910Skjd done(1); 127721910Skjd } 127821910Skjd } 127922353Skjd 128022353Skjd 128122353Skjd chgreel(x, fl) 128222353Skjd int x, fl; 128322353Skjd { 128422353Skjd register int f; 128522353Skjd char str[BUFSIZ]; 128622353Skjd char *pstr; 128722353Skjd FILE *devtty; 128822353Skjd struct stat statb; 128922353Skjd 129022353Skjd perror("tar"); 129122353Skjd fprintf(stderr, "Can't %s\n", x ? "write output": "read input"); 129222353Skjd fstat(fl, &statb); 129322353Skjd if ((statb.st_mode & S_IFMT) != S_IFCHR) 129422353Skjd done(2); 129522353Skjd 129622353Skjd close(fl); 129722353Skjd devtty = fopen("/dev/tty", "r"); 129822353Skjd for (;;) { 129922353Skjd 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"); 130022353Skjd if (fgets(str, sizeof (str), devtty) == NULL) 130122353Skjd break; 130222353Skjd str[strlen(str) - 1] = '\0'; 130322353Skjd 130422353Skjd switch (*str) { 130522353Skjd case '\0': 130622353Skjd case 'N': 130722353Skjd case 'n': 130822353Skjd goto done; 130922353Skjd 131022353Skjd case 'Y': 131122353Skjd case 'y': 131222353Skjd case '\n': 131322353Skjd pstr = usefile; 131422353Skjd break; 131522353Skjd 131622353Skjd default: 131722353Skjd pstr = str; 131822353Skjd } 131922353Skjd if ((f = open(pstr, x ? 1 : 0)) >= 0) { 132022353Skjd fclose(devtty); 132122353Skjd return (f); 132222353Skjd } 132322353Skjd fprintf(stderr, "tar: open of %s failed\n", pstr); 132422353Skjd } 132522353Skjd done: 132622353Skjd fclose(devtty); 132722353Skjd return (-1); 132822353Skjd } 1329