112154Ssam #ifndef lint 2*21910Skjd static char *sccsid = "@(#)tar.c 4.22 (Berkeley) 06/03/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 216250Sroot 2221457Skjd #define writetape(b) writetbuf(b, 1) 2321457Skjd #define min(a,b) ((a) < (b) ? (a) : (b)) 2421457Skjd #define max(a,b) ((a) > (b) ? (a) : (b)) 2521457Skjd 261119Sbill union hblock { 271119Sbill char dummy[TBLOCK]; 281119Sbill struct header { 291119Sbill char name[NAMSIZ]; 301119Sbill char mode[8]; 311119Sbill char uid[8]; 321119Sbill char gid[8]; 331119Sbill char size[12]; 341119Sbill char mtime[12]; 351119Sbill char chksum[8]; 361119Sbill char linkflag; 371119Sbill char linkname[NAMSIZ]; 381119Sbill } dbuf; 396250Sroot }; 401119Sbill 411119Sbill struct linkbuf { 421119Sbill ino_t inum; 431119Sbill dev_t devnum; 441119Sbill int count; 451119Sbill char pathname[NAMSIZ]; 461119Sbill struct linkbuf *nextp; 476250Sroot }; 481119Sbill 496250Sroot union hblock dblock; 5013492Ssam union hblock *tbuf; 516250Sroot struct linkbuf *ihead; 526250Sroot struct stat stbuf; 531119Sbill 546250Sroot int rflag; 556250Sroot int xflag; 566250Sroot int vflag; 576250Sroot int tflag; 586250Sroot int cflag; 596250Sroot int mflag; 606250Sroot int fflag; 6112154Ssam int iflag; 626250Sroot int oflag; 636250Sroot int pflag; 646250Sroot int wflag; 656250Sroot int hflag; 668737Smckusick int Bflag; 6712154Ssam int Fflag; 686250Sroot 696250Sroot int mt; 706250Sroot int term; 716250Sroot int chksum; 726250Sroot int recno; 736250Sroot int first; 746250Sroot int linkerrok; 751119Sbill int freemem = 1; 763457Swnj int nblock = NBLOCK; 776250Sroot int onintr(); 786250Sroot int onquit(); 796250Sroot int onhup(); 806250Sroot int onterm(); 811119Sbill 821119Sbill daddr_t low; 831119Sbill daddr_t high; 846250Sroot daddr_t bsrch(); 851119Sbill 86*21910Skjd FILE *vfile = stdout; 871119Sbill FILE *tfile; 881119Sbill char tname[] = "/tmp/tarXXXXXX"; 891119Sbill char *usefile; 906250Sroot char magtape[] = "/dev/rmt8"; 911119Sbill char *malloc(); 926250Sroot char *sprintf(); 936250Sroot char *strcat(); 9412154Ssam char *rindex(); 9510165Ssam char *getcwd(); 969844Ssam char *getwd(); 971119Sbill 981119Sbill main(argc, argv) 991119Sbill int argc; 1001119Sbill char *argv[]; 1011119Sbill { 1021119Sbill char *cp; 1031119Sbill 1041119Sbill if (argc < 2) 1051119Sbill usage(); 1061119Sbill 1071119Sbill tfile = NULL; 1081119Sbill usefile = magtape; 1091119Sbill argv[argc] = 0; 1101119Sbill argv++; 1111119Sbill for (cp = *argv++; *cp; cp++) 1121119Sbill switch(*cp) { 1136250Sroot 1141119Sbill case 'f': 11512154Ssam if (*argv == 0) { 11612154Ssam fprintf(stderr, 11712154Ssam "tar: tapefile must be specified with 'f' option\n"); 11812154Ssam usage(); 11912154Ssam } 1201119Sbill usefile = *argv++; 1211119Sbill fflag++; 1221119Sbill break; 1236250Sroot 1241119Sbill case 'c': 1251119Sbill cflag++; 1261119Sbill rflag++; 1271119Sbill break; 1286250Sroot 1291119Sbill case 'o': 1301119Sbill oflag++; 1311119Sbill break; 1326250Sroot 1331119Sbill case 'p': 1341119Sbill pflag++; 1351119Sbill break; 1366250Sroot 1371119Sbill case 'u': 1381119Sbill mktemp(tname); 1391119Sbill if ((tfile = fopen(tname, "w")) == NULL) { 1406250Sroot fprintf(stderr, 1416250Sroot "Tar: cannot create temporary file (%s)\n", 1426250Sroot tname); 1431119Sbill done(1); 1441119Sbill } 1451119Sbill fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n"); 1466250Sroot /*FALL THRU*/ 1476250Sroot 1481119Sbill case 'r': 1491119Sbill rflag++; 1501119Sbill break; 1516250Sroot 1521119Sbill case 'v': 1531119Sbill vflag++; 1541119Sbill break; 1556250Sroot 1561119Sbill case 'w': 1571119Sbill wflag++; 1581119Sbill break; 1596250Sroot 1601119Sbill case 'x': 1611119Sbill xflag++; 1621119Sbill break; 1636250Sroot 1641119Sbill case 't': 1651119Sbill tflag++; 1661119Sbill break; 1676250Sroot 1681119Sbill case 'm': 1691119Sbill mflag++; 1701119Sbill break; 1716250Sroot 1721119Sbill case '-': 1731119Sbill break; 1746250Sroot 1751119Sbill case '0': 1761119Sbill case '1': 1771119Sbill case '4': 1781119Sbill case '5': 17921457Skjd case '7': 1801119Sbill case '8': 1811119Sbill magtape[8] = *cp; 1821119Sbill usefile = magtape; 1831119Sbill break; 1846250Sroot 1851119Sbill case 'b': 18613492Ssam if (*argv == 0) { 18713492Ssam fprintf(stderr, 18813492Ssam "tar: blocksize must be specified with 'b' option\n"); 18913492Ssam usage(); 19013492Ssam } 19113492Ssam nblock = atoi(*argv); 19213492Ssam if (nblock <= 0) { 19313492Ssam fprintf(stderr, 19413492Ssam "tar: invalid blocksize \"%s\"\n", *argv); 1951119Sbill done(1); 1961119Sbill } 19713492Ssam argv++; 1981119Sbill break; 1996250Sroot 2001119Sbill case 'l': 2011119Sbill linkerrok++; 2021119Sbill break; 2036250Sroot 2046250Sroot case 'h': 2056250Sroot hflag++; 2066250Sroot break; 2076250Sroot 20812154Ssam case 'i': 20912154Ssam iflag++; 21012154Ssam break; 21112154Ssam 2128737Smckusick case 'B': 2138737Smckusick Bflag++; 2148737Smckusick break; 2158737Smckusick 21612154Ssam case 'F': 21712154Ssam Fflag++; 21812154Ssam break; 21912154Ssam 2201119Sbill default: 2211119Sbill fprintf(stderr, "tar: %c: unknown option\n", *cp); 2221119Sbill usage(); 2231119Sbill } 2241119Sbill 2256250Sroot if (!rflag && !xflag && !tflag) 2266250Sroot usage(); 2271119Sbill if (rflag) { 2286250Sroot if (cflag && tfile != NULL) 2291119Sbill usage(); 2301119Sbill if (signal(SIGINT, SIG_IGN) != SIG_IGN) 2311119Sbill signal(SIGINT, onintr); 2321119Sbill if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 2331119Sbill signal(SIGHUP, onhup); 2341119Sbill if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 2351119Sbill signal(SIGQUIT, onquit); 2366250Sroot #ifdef notdef 2371119Sbill if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 2381119Sbill signal(SIGTERM, onterm); 2396250Sroot #endif 2401119Sbill if (strcmp(usefile, "-") == 0) { 2411119Sbill if (cflag == 0) { 2426250Sroot fprintf(stderr, 24313492Ssam "tar: can only create standard output archives\n"); 2441119Sbill done(1); 2451119Sbill } 246*21910Skjd vfile = stderr; 247*21910Skjd setlinebuf(vfile); 2481119Sbill mt = dup(1); 2491119Sbill nblock = 1; 2506250Sroot } else if ((mt = open(usefile, 2)) < 0) { 2511119Sbill if (cflag == 0 || (mt = creat(usefile, 0666)) < 0) { 2526250Sroot fprintf(stderr, 2536250Sroot "tar: cannot open %s\n", usefile); 2541119Sbill done(1); 2551119Sbill } 2561119Sbill } 2571119Sbill dorep(argv); 2586250Sroot done(0); 2591119Sbill } 2606250Sroot if (strcmp(usefile, "-") == 0) { 2616250Sroot mt = dup(0); 2626250Sroot nblock = 1; 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) { 522*21910Skjd fprintf(vfile, "a %s ", longname); 523*21910Skjd 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) { 560*21910Skjd fprintf(vfile, "a %s ", longname); 561*21910Skjd 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) { 586*21910Skjd fprintf(vfile, "a %s ", longname); 587*21910Skjd 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) 670*21910Skjd fprintf(vfile, "x %s symbolic link to %s\n", 67113492Ssam dblock.dbuf.name, dblock.dbuf.linkname); 6721119Sbill continue; 6736250Sroot } 6741119Sbill if (dblock.dbuf.linkflag == '1') { 6751119Sbill unlink(dblock.dbuf.name); 6761119Sbill if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) { 67713492Ssam fprintf(stderr, "tar: %s: cannot link\n", 67813492Ssam dblock.dbuf.name); 6791119Sbill continue; 6801119Sbill } 6811119Sbill if (vflag) 682*21910Skjd fprintf(vfile, "%s linked to %s\n", 68313492Ssam dblock.dbuf.name, dblock.dbuf.linkname); 6841119Sbill continue; 6851119Sbill } 6866250Sroot if ((ofile = creat(dblock.dbuf.name,stbuf.st_mode&0xfff)) < 0) { 6876250Sroot fprintf(stderr, "tar: %s - cannot create\n", 68813492Ssam dblock.dbuf.name); 6891119Sbill passtape(); 6901119Sbill continue; 6911119Sbill } 69221457Skjd chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); 6931119Sbill blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK; 6941119Sbill if (vflag) 695*21910Skjd fprintf(vfile, "x %s, %ld bytes, %ld tape blocks\n", 69613492Ssam dblock.dbuf.name, bytes, blocks); 69721457Skjd for (; blocks > 0;) { 69821457Skjd register int nread; 69921457Skjd char *bufp; 70021457Skjd register int nwant; 70121457Skjd 70221457Skjd nwant = NBLOCK*TBLOCK; 70321457Skjd if (nwant > (blocks*TBLOCK)) 70421457Skjd nwant = (blocks*TBLOCK); 70521457Skjd nread = readtbuf(&bufp, nwant); 70621457Skjd if (bytes > nread) { 70721457Skjd if (write(ofile, bufp, nread) < 0) { 70821457Skjd fprintf(stderr, 70921457Skjd "tar: %s: HELP - extract write error\n", 71021457Skjd dblock.dbuf.name); 71121457Skjd done(2); 71221457Skjd } 71321457Skjd } else if (write(ofile, bufp, (int) bytes) < 0) { 7146250Sroot fprintf(stderr, 71513492Ssam "tar: %s: HELP - extract write error\n", 71613492Ssam dblock.dbuf.name); 7176250Sroot done(2); 7186250Sroot } 71921457Skjd bytes -= nread; 72021457Skjd blocks -= (((nread-1)/TBLOCK)+1); 7211119Sbill } 7221119Sbill close(ofile); 7231119Sbill if (mflag == 0) { 72412983Ssam struct timeval tv[2]; 7251119Sbill 72612983Ssam tv[0].tv_sec = time(0); 72712983Ssam tv[0].tv_usec = 0; 72812983Ssam tv[1].tv_sec = stbuf.st_mtime; 72912983Ssam tv[1].tv_usec = 0; 73012983Ssam utimes(dblock.dbuf.name, tv); 7311119Sbill } 7321926Swnj if (pflag) 7336250Sroot chmod(dblock.dbuf.name, stbuf.st_mode & 07777); 7341119Sbill } 7351119Sbill } 7361119Sbill 7371119Sbill dotable() 7381119Sbill { 7391119Sbill for (;;) { 7401119Sbill getdir(); 7411119Sbill if (endtape()) 7421119Sbill break; 7431119Sbill if (vflag) 7441119Sbill longt(&stbuf); 7451119Sbill printf("%s", dblock.dbuf.name); 7461119Sbill if (dblock.dbuf.linkflag == '1') 7471119Sbill printf(" linked to %s", dblock.dbuf.linkname); 7486250Sroot if (dblock.dbuf.linkflag == '2') 7496250Sroot printf(" symbolic link to %s", dblock.dbuf.linkname); 7501119Sbill printf("\n"); 7511119Sbill passtape(); 7521119Sbill } 7531119Sbill } 7541119Sbill 7551119Sbill putempty() 7561119Sbill { 7571119Sbill char buf[TBLOCK]; 7581119Sbill 75913492Ssam bzero(buf, sizeof (buf)); 7601119Sbill writetape(buf); 7611119Sbill } 7621119Sbill 7631119Sbill longt(st) 7646250Sroot register struct stat *st; 7651119Sbill { 7661119Sbill register char *cp; 7671119Sbill char *ctime(); 7681119Sbill 7691119Sbill pmode(st); 7701119Sbill printf("%3d/%1d", st->st_uid, st->st_gid); 7711119Sbill printf("%7D", st->st_size); 7721119Sbill cp = ctime(&st->st_mtime); 7731119Sbill printf(" %-12.12s %-4.4s ", cp+4, cp+20); 7741119Sbill } 7751119Sbill 7761119Sbill #define SUID 04000 7771119Sbill #define SGID 02000 7781119Sbill #define ROWN 0400 7791119Sbill #define WOWN 0200 7801119Sbill #define XOWN 0100 7811119Sbill #define RGRP 040 7821119Sbill #define WGRP 020 7831119Sbill #define XGRP 010 7841119Sbill #define ROTH 04 7851119Sbill #define WOTH 02 7861119Sbill #define XOTH 01 7871119Sbill #define STXT 01000 7881119Sbill int m1[] = { 1, ROWN, 'r', '-' }; 7891119Sbill int m2[] = { 1, WOWN, 'w', '-' }; 7901119Sbill int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; 7911119Sbill int m4[] = { 1, RGRP, 'r', '-' }; 7921119Sbill int m5[] = { 1, WGRP, 'w', '-' }; 7931119Sbill int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; 7941119Sbill int m7[] = { 1, ROTH, 'r', '-' }; 7951119Sbill int m8[] = { 1, WOTH, 'w', '-' }; 7961119Sbill int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; 7971119Sbill 7981119Sbill int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; 7991119Sbill 8001119Sbill pmode(st) 8016250Sroot register struct stat *st; 8021119Sbill { 8031119Sbill register int **mp; 8041119Sbill 8051119Sbill for (mp = &m[0]; mp < &m[9];) 8061119Sbill select(*mp++, st); 8071119Sbill } 8081119Sbill 8091119Sbill select(pairp, st) 8106250Sroot int *pairp; 8116250Sroot struct stat *st; 8121119Sbill { 8131119Sbill register int n, *ap; 8141119Sbill 8151119Sbill ap = pairp; 8161119Sbill n = *ap++; 8171119Sbill while (--n>=0 && (st->st_mode&*ap++)==0) 8181119Sbill ap++; 8191119Sbill printf("%c", *ap); 8201119Sbill } 8211119Sbill 8221119Sbill checkdir(name) 8236250Sroot register char *name; 8241119Sbill { 8251119Sbill register char *cp; 8266250Sroot 82712154Ssam /* 82812154Ssam * Quick check for existance of directory. 82912154Ssam */ 83012154Ssam if ((cp = rindex(name, '/')) == 0) 83112154Ssam return (0); 83212154Ssam *cp = '\0'; 83312154Ssam if (access(name, 0) >= 0) { 83412154Ssam *cp = '/'; 83512154Ssam return (cp[1] == '\0'); 83612154Ssam } 83712154Ssam *cp = '/'; 83812154Ssam 83912154Ssam /* 84012154Ssam * No luck, try to make all directories in path. 84112154Ssam */ 8421119Sbill for (cp = name; *cp; cp++) { 8436250Sroot if (*cp != '/') 8446250Sroot continue; 8456250Sroot *cp = '\0'; 84612154Ssam if (access(name, 0) < 0) { 8479844Ssam if (mkdir(name, 0777) < 0) { 8489844Ssam perror(name); 84912154Ssam *cp = '/'; 85012154Ssam return (0); 8511119Sbill } 85221457Skjd chown(name, stbuf.st_uid, stbuf.st_gid); 85314956Skarels if (pflag && cp[1] == '\0') 8549844Ssam chmod(name, stbuf.st_mode & 0777); 8551119Sbill } 8566250Sroot *cp = '/'; 8571119Sbill } 8586250Sroot return (cp[-1]=='/'); 8591119Sbill } 8601119Sbill 8611119Sbill onintr() 8621119Sbill { 8631119Sbill signal(SIGINT, SIG_IGN); 8641119Sbill term++; 8651119Sbill } 8661119Sbill 8671119Sbill onquit() 8681119Sbill { 8691119Sbill signal(SIGQUIT, SIG_IGN); 8701119Sbill term++; 8711119Sbill } 8721119Sbill 8731119Sbill onhup() 8741119Sbill { 8751119Sbill signal(SIGHUP, SIG_IGN); 8761119Sbill term++; 8771119Sbill } 8781119Sbill 8791119Sbill onterm() 8801119Sbill { 8811119Sbill signal(SIGTERM, SIG_IGN); 8821119Sbill term++; 8831119Sbill } 8841119Sbill 8851119Sbill tomodes(sp) 8861119Sbill register struct stat *sp; 8871119Sbill { 8881119Sbill register char *cp; 8891119Sbill 8901119Sbill for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 8911119Sbill *cp = '\0'; 8921119Sbill sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); 8931119Sbill sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); 8941119Sbill sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); 8951119Sbill sprintf(dblock.dbuf.size, "%11lo ", sp->st_size); 8961119Sbill sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime); 8971119Sbill } 8981119Sbill 8991119Sbill checksum() 9001119Sbill { 9011119Sbill register i; 9021119Sbill register char *cp; 9031119Sbill 9046250Sroot for (cp = dblock.dbuf.chksum; 9056250Sroot cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++) 9061119Sbill *cp = ' '; 9071119Sbill i = 0; 9081119Sbill for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) 9091119Sbill i += *cp; 9106250Sroot return (i); 9111119Sbill } 9121119Sbill 9131119Sbill checkw(c, name) 9146250Sroot char *name; 9151119Sbill { 9166250Sroot if (!wflag) 9176250Sroot return (1); 9186250Sroot printf("%c ", c); 9196250Sroot if (vflag) 9206250Sroot longt(&stbuf); 9216250Sroot printf("%s: ", name); 9226250Sroot return (response() == 'y'); 9231119Sbill } 9241119Sbill 9251119Sbill response() 9261119Sbill { 9271119Sbill char c; 9281119Sbill 9291119Sbill c = getchar(); 9301119Sbill if (c != '\n') 9316250Sroot while (getchar() != '\n') 9326250Sroot ; 9336250Sroot else 9346250Sroot c = 'n'; 9356250Sroot return (c); 9361119Sbill } 9371119Sbill 93812154Ssam checkf(name, mode, howmuch) 93912154Ssam char *name; 94012154Ssam int mode, howmuch; 94112154Ssam { 94212154Ssam int l; 94312154Ssam 944*21910Skjd if ((mode & S_IFMT) == S_IFDIR){ 945*21910Skjd if ((strcmp(name, "SCCS")==0) || (strcmp(name, "RCS")==0)) 946*21910Skjd return(0); 947*21910Skjd return(1); 948*21910Skjd } 94912154Ssam if ((l = strlen(name)) < 3) 95012154Ssam return (1); 95112154Ssam if (howmuch > 1 && name[l-2] == '.' && name[l-1] == 'o') 95212154Ssam return (0); 95312154Ssam if (strcmp(name, "core") == 0 || 95412154Ssam strcmp(name, "errs") == 0 || 95512154Ssam (howmuch > 1 && strcmp(name, "a.out") == 0)) 95612154Ssam return (0); 95712154Ssam /* SHOULD CHECK IF IT IS EXECUTABLE */ 95812154Ssam return (1); 95912154Ssam } 96012154Ssam 9611119Sbill checkupdate(arg) 9626250Sroot char *arg; 9631119Sbill { 9641119Sbill char name[100]; 9656250Sroot long mtime; 9661119Sbill daddr_t seekp; 9671119Sbill daddr_t lookup(); 9681119Sbill 9691119Sbill rewind(tfile); 9701119Sbill for (;;) { 9711119Sbill if ((seekp = lookup(arg)) < 0) 9726250Sroot return (1); 9731119Sbill fseek(tfile, seekp, 0); 9741119Sbill fscanf(tfile, "%s %lo", name, &mtime); 9756250Sroot return (stbuf.st_mtime > mtime); 9761119Sbill } 9771119Sbill } 9781119Sbill 9791119Sbill done(n) 9801119Sbill { 98121457Skjd unlink(tname); 9821119Sbill exit(n); 9831119Sbill } 9841119Sbill 9851119Sbill prefix(s1, s2) 9866250Sroot register char *s1, *s2; 9871119Sbill { 9881119Sbill while (*s1) 9891119Sbill if (*s1++ != *s2++) 9906250Sroot return (0); 9911119Sbill if (*s2) 9926250Sroot return (*s2 == '/'); 9936250Sroot return (1); 9941119Sbill } 9951119Sbill 9961119Sbill #define N 200 9971119Sbill int njab; 9986250Sroot 9991119Sbill daddr_t 10001119Sbill lookup(s) 10016250Sroot char *s; 10021119Sbill { 10031119Sbill register i; 10041119Sbill daddr_t a; 10051119Sbill 10061119Sbill for(i=0; s[i]; i++) 10076250Sroot if (s[i] == ' ') 10081119Sbill break; 10091119Sbill a = bsrch(s, i, low, high); 10106250Sroot return (a); 10111119Sbill } 10121119Sbill 10131119Sbill daddr_t 10141119Sbill bsrch(s, n, l, h) 10156250Sroot daddr_t l, h; 10166250Sroot char *s; 10171119Sbill { 10181119Sbill register i, j; 10191119Sbill char b[N]; 10201119Sbill daddr_t m, m1; 10211119Sbill 10221119Sbill njab = 0; 10231119Sbill 10241119Sbill loop: 10256250Sroot if (l >= h) 10266250Sroot return (-1L); 10271119Sbill m = l + (h-l)/2 - N/2; 10286250Sroot if (m < l) 10291119Sbill m = l; 10301119Sbill fseek(tfile, m, 0); 10311119Sbill fread(b, 1, N, tfile); 10321119Sbill njab++; 10331119Sbill for(i=0; i<N; i++) { 10346250Sroot if (b[i] == '\n') 10351119Sbill break; 10361119Sbill m++; 10371119Sbill } 10386250Sroot if (m >= h) 10396250Sroot return (-1L); 10401119Sbill m1 = m; 10411119Sbill j = i; 10421119Sbill for(i++; i<N; i++) { 10431119Sbill m1++; 10446250Sroot if (b[i] == '\n') 10451119Sbill break; 10461119Sbill } 10471119Sbill i = cmp(b+j, s, n); 10486250Sroot if (i < 0) { 10491119Sbill h = m; 10501119Sbill goto loop; 10511119Sbill } 10526250Sroot if (i > 0) { 10531119Sbill l = m1; 10541119Sbill goto loop; 10551119Sbill } 10566250Sroot return (m); 10571119Sbill } 10581119Sbill 10591119Sbill cmp(b, s, n) 10606250Sroot char *b, *s; 10611119Sbill { 10621119Sbill register i; 10631119Sbill 10646250Sroot if (b[0] != '\n') 106521457Skjd exit(2); 10661119Sbill for(i=0; i<n; i++) { 10676250Sroot if (b[i+1] > s[i]) 10686250Sroot return (-1); 10696250Sroot if (b[i+1] < s[i]) 10706250Sroot return (1); 10711119Sbill } 10726250Sroot return (b[i+1] == ' '? 0 : -1); 10731119Sbill } 10741119Sbill 107521457Skjd readtape (buffer) 10766250Sroot char *buffer; 10771119Sbill { 107821457Skjd char *bufp; 107921457Skjd int nread; 108021457Skjd 1081*21910Skjd if (first==0) getbuf(); 108221457Skjd readtbuf (&bufp, TBLOCK); 108321457Skjd bcopy(bufp, buffer, TBLOCK); 108421457Skjd return(TBLOCK); 108521457Skjd } 108621457Skjd 108721457Skjd readtbuf(bufpp, size) 108821457Skjd char **bufpp; 108921457Skjd int size; 109021457Skjd { 10913457Swnj register int i; 10921119Sbill 10931119Sbill if (recno >= nblock || first == 0) { 10948737Smckusick if ((i = bread(mt, tbuf, TBLOCK*nblock)) < 0) { 109513492Ssam fprintf(stderr, "tar: tape read error\n"); 10961119Sbill done(3); 10971119Sbill } 10981119Sbill if (first == 0) { 10991119Sbill if ((i % TBLOCK) != 0) { 110013492Ssam fprintf(stderr, "tar: tape blocksize error\n"); 11011119Sbill done(3); 11021119Sbill } 11031119Sbill i /= TBLOCK; 11043457Swnj if (i != nblock) { 110513492Ssam fprintf(stderr, "tar: blocksize = %d\n", i); 11061119Sbill nblock = i; 11071119Sbill } 11081119Sbill } 11091119Sbill recno = 0; 11101119Sbill } 11111119Sbill first = 1; 111221457Skjd if (size > ((nblock-recno)*TBLOCK)) 111321457Skjd size = (nblock-recno)*TBLOCK; 111421457Skjd *bufpp = (char *)&tbuf[recno]; 111521457Skjd recno += (size/TBLOCK); 111621457Skjd return (size); 11171119Sbill } 11181119Sbill 111921457Skjd writetbuf(buffer, n) 112021457Skjd register char *buffer; 112121457Skjd register int n; 11221119Sbill { 1123*21910Skjd if (first==0) getbuf(); 11241119Sbill first = 1; 11251119Sbill if (recno >= nblock) { 112621457Skjd if (write(mt, tbuf, TBLOCK*nblock) < 0) { 112713492Ssam fprintf(stderr, "tar: tape write error\n"); 11281119Sbill done(2); 11291119Sbill } 11301119Sbill recno = 0; 11311119Sbill } 113221457Skjd 113321457Skjd /* 113421457Skjd * Special case: We have an empty tape buffer, and the 113521457Skjd * users data size is >= the tape block size: Avoid 113621457Skjd * the bcopy and dma direct to tape. BIG WIN. Add the 113721457Skjd * residual to the tape buffer. 113821457Skjd */ 113921457Skjd while (recno == 0 && n >= nblock) { 114021457Skjd if (write(mt, buffer, TBLOCK*nblock) < 0) { 114113492Ssam fprintf(stderr, "tar: tape write error\n"); 11421119Sbill done(2); 11431119Sbill } 114421457Skjd n -= nblock; 114521457Skjd buffer += (nblock * TBLOCK); 11461119Sbill } 114721457Skjd 114821457Skjd while (n-- > 0) { 114921457Skjd bcopy(buffer, (char *)&tbuf[recno++], TBLOCK); 115021457Skjd buffer += TBLOCK; 115121457Skjd if (recno >= nblock) { 115221457Skjd if (write(mt, tbuf, TBLOCK*nblock) < 0) { 115321457Skjd fprintf(stderr, "tar: tape write error\n"); 115421457Skjd done(2); 115521457Skjd } 115621457Skjd recno = 0; 115721457Skjd } 115821457Skjd } 115921457Skjd 116021457Skjd /* Tell the user how much to write to get in sync */ 116121457Skjd return (nblock - recno); 11621119Sbill } 11631119Sbill 11641119Sbill backtape() 11651119Sbill { 11663457Swnj static int mtdev = 1; 11673457Swnj static struct mtop mtop = {MTBSR, 1}; 11683457Swnj struct mtget mtget; 11693457Swnj 11703457Swnj if (mtdev == 1) 11713457Swnj mtdev = ioctl(mt, MTIOCGET, &mtget); 11723457Swnj if (mtdev == 0) { 11733457Swnj if (ioctl(mt, MTIOCTOP, &mtop) < 0) { 117413492Ssam fprintf(stderr, "tar: tape backspace error\n"); 11751119Sbill done(4); 11761119Sbill } 11773457Swnj } else 11783457Swnj lseek(mt, (long) -TBLOCK*nblock, 1); 11793457Swnj recno--; 11801119Sbill } 11811119Sbill 11821119Sbill flushtape() 11831119Sbill { 118421457Skjd write(mt, tbuf, TBLOCK*nblock); 11851119Sbill } 11861119Sbill 11878737Smckusick bread(fd, buf, size) 11888737Smckusick int fd; 11898737Smckusick char *buf; 11908737Smckusick int size; 11918737Smckusick { 11928737Smckusick int count; 11938737Smckusick static int lastread = 0; 11948737Smckusick 119521457Skjd if (!Bflag) 119621457Skjd return (read(fd, buf, size)); 11978737Smckusick for (count = 0; count < size; count += lastread) { 11988737Smckusick if (lastread < 0) { 11998737Smckusick if (count > 0) 12008737Smckusick return (count); 12018737Smckusick return (lastread); 12028737Smckusick } 12038737Smckusick lastread = read(fd, buf, size - count); 12048737Smckusick buf += lastread; 12058737Smckusick } 12068737Smckusick return (count); 12078737Smckusick } 120810165Ssam 120910165Ssam char * 121010165Ssam getcwd(buf) 121110165Ssam char *buf; 121210165Ssam { 121310165Ssam 121410165Ssam if (getwd(buf) == NULL) { 121510165Ssam fprintf(stderr, "tar: %s\n", buf); 121621457Skjd exit(1); 121710165Ssam } 121810165Ssam return (buf); 121910165Ssam } 1220*21910Skjd 1221*21910Skjd getbuf() 1222*21910Skjd { 1223*21910Skjd #ifdef nodef 1224*21910Skjd if ( mtdev == 1) { 1225*21910Skjd fstat(mt, &stbuf); 1226*21910Skjd if ((stbuf.st_mode & S_IFMT) == S_IFCHR) 1227*21910Skjd mtdev = 0; 1228*21910Skjd else 1229*21910Skjd mtdev = -1; 1230*21910Skjd } 1231*21910Skjd if (first==0 && nblock==0) { 1232*21910Skjd if (mtdev == 0) 1233*21910Skjd nblock = FILEBLOCK; 1234*21910Skjd else { 1235*21910Skjd fstat(mt, &stbuf); 1236*21910Skjd nblock = stbuf.st_blocks / TBLOCK; 1237*21910Skjd } 1238*21910Skjd } 1239*21910Skjd if (nblock ==0) nblock = FILEBLOCK; 1240*21910Skjd #endif nodef 1241*21910Skjd tbuf = (union hblock *)malloc(nblock*TBLOCK); 1242*21910Skjd if (tbuf == NULL) { 1243*21910Skjd fprintf(stderr, "tar: blocksize %d too big, can't get memory\n", 1244*21910Skjd nblock); 1245*21910Skjd done(1); 1246*21910Skjd } 1247*21910Skjd } 1248