16847Smckusick /* Copyright (c) 1982 Regents of the University of California */ 24610Smckusick 36846Smckusick #ifndef lint 4*8302Smckusick char version[] = "@(#)main.c 2.8 10/04/82"; 56846Smckusick #endif 64610Smckusick 74610Smckusick /* Modified to include h option (recursively extract all files within 84610Smckusick * a subtree) and m option (recreate the heirarchical structure of 94610Smckusick * that subtree and move extracted files to their proper homes). 104610Smckusick * 8/29/80 by Mike Litzkow 114610Smckusick * 126846Smckusick * Modified to work on the new file system 136846Smckusick * 1/19/82 by Kirk McKusick 146846Smckusick * 154610Smckusick * Includes the s (skip files) option for use with multiple dumps on 164610Smckusick * a single tape. 174610Smckusick */ 184610Smckusick 194610Smckusick #define MAXINO 3000 204610Smckusick #define BITS 8 214610Smckusick #define NCACHE 3 224610Smckusick #define SIZEINC 10 234610Smckusick 244610Smckusick #include <stdio.h> 254610Smckusick #include <signal.h> 266844Smckusick #include <fstab.h> 276847Smckusick #ifndef SIMFS 286847Smckusick #include <sys/param.h> 296847Smckusick #include <sys/inode.h> 306847Smckusick #include <sys/fs.h> 316847Smckusick #include <dir.h> 326847Smckusick #include <stat.h> 336847Smckusick #include <dumprestor.h> 346847Smckusick #else 356844Smckusick #include "../h/param.h" 366844Smckusick #include "../h/dir.h" 376844Smckusick #include "../h/stat.h" 386844Smckusick #include "../h/inode.h" 396844Smckusick #include "../h/fs.h" 406844Smckusick #include "../h/dumprestor.h" 416847Smckusick #endif 428296Smckusick #include <sys/ioctl.h> 435038Smckusic #include <sys/mtio.h> 444610Smckusick 455943Smckusic #define ODIRSIZ 14 465038Smckusic struct odirect { 475038Smckusic u_short d_ino; 485943Smckusic char d_name[ODIRSIZ]; 495038Smckusic }; 505038Smckusic 515327Smckusic #define MWORD(m,i) (m[(unsigned)(i-1)/NBBY]) 525327Smckusic #define MBIT(i) (1<<((unsigned)(i-1)%NBBY)) 534610Smckusick #define BIS(i,w) (MWORD(w,i) |= MBIT(i)) 544610Smckusick #define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) 554610Smckusick #define BIT(i,w) (MWORD(w,i) & MBIT(i)) 564610Smckusick 576846Smckusick ino_t ino; 584610Smckusick 59*8302Smckusick int eflag = 0, hflag = 0, mflag = 0, cvtflag = 0, cvtdir = 0; 604776Smckusic 616844Smckusick long fssize; 624610Smckusick char tapename[] = "/dev/rmt8"; 634610Smckusick char *magtape = tapename; 645038Smckusic int mt; 655038Smckusic int dumpnum = 1; 665038Smckusic int volno = 1; 675038Smckusic int curblk = 0; 685038Smckusic int bct = NTREC+1; 695038Smckusic char tbf[NTREC*TP_BSIZE]; 704610Smckusick 714610Smckusick daddr_t seekpt; 724837Smckusic FILE *df; 735943Smckusic DIR *dirp; 744837Smckusic int ofile; 756847Smckusick char dirfile[] = "/tmp/rstXXXXXX"; 766289Smckusick char lnkbuf[MAXPATHLEN + 1]; 776289Smckusick int pathlen; 784610Smckusick 794837Smckusic #define INOHASH(val) (val % MAXINO) 804837Smckusic struct inotab { 814837Smckusic struct inotab *t_next; 824610Smckusick ino_t t_ino; 834610Smckusick daddr_t t_seekpt; 844837Smckusic } *inotab[MAXINO]; 854610Smckusick 864837Smckusic #define XISDIR 1 874610Smckusick #define XTRACTD 2 884610Smckusick #define XINUSE 4 894837Smckusic #define XLINKED 8 904610Smckusick struct xtrlist { 914837Smckusic struct xtrlist *x_next; 924837Smckusic struct xtrlist *x_linkedto; 934843Smckusic time_t x_timep[2]; 944837Smckusic ino_t x_ino; 954837Smckusic char x_flags; 964843Smckusic char x_name[1]; 974843Smckusic /* actually longer */ 984837Smckusic } *xtrlist[MAXINO]; 994776Smckusic int xtrcnt = 0; 1004610Smckusick 1015327Smckusic char *dumpmap; 1025327Smckusic char *clrimap; 1034610Smckusick 1045327Smckusic char clearedbuf[MAXBSIZE]; 1055327Smckusic 1064837Smckusic extern char *ctime(); 1076846Smckusick extern int seek(); 1084843Smckusic ino_t search(); 1095943Smckusic int dirwrite(); 1106849Smckusick #ifdef RRESTOR 1116849Smckusick char *host; 1126849Smckusick #endif 1134610Smckusick 1146846Smckusick main(argc, argv) 1154700Smckusic int argc; 1164700Smckusic char *argv[]; 1174610Smckusick { 1184610Smckusick register char *cp; 1194610Smckusick char command; 1204700Smckusic int (*signal())(); 1214610Smckusick int done(); 1224610Smckusick 1234843Smckusic if (signal(SIGINT, done) == SIG_IGN) 1244843Smckusic signal(SIGINT, SIG_IGN); 1254843Smckusic if (signal(SIGTERM, done) == SIG_IGN) 1264843Smckusic signal(SIGTERM, SIG_IGN); 1276844Smckusick mktemp(dirfile); 1284610Smckusick if (argc < 2) { 1294610Smckusick usage: 1304837Smckusic fprintf(stderr, "Usage: restor x[s|m|h|v] file file..., restor r|R filesys, or restor t\n"); 1314700Smckusic done(1); 1324610Smckusick } 1334610Smckusick argv++; 1344610Smckusick argc -= 2; 1354610Smckusick for (cp = *argv++; *cp; cp++) { 1364610Smckusick switch (*cp) { 1374610Smckusick case '-': 1384610Smckusick break; 139*8302Smckusick case 'c': 140*8302Smckusick cvtflag++; 141*8302Smckusick break; 1424610Smckusick case 'f': 1434610Smckusick magtape = *argv++; 1446849Smckusick #ifdef RRESTOR 1456849Smckusick { char *index(); 1466849Smckusick host = magtape; 1476849Smckusick magtape = index(host, ':'); 1486849Smckusick if (magtape == 0) { 1496849Smckusick nohost: 1506849Smckusick msg("need keyletter ``f'' and device ``host:tape''"); 1516849Smckusick done(1); 1526849Smckusick } 1536849Smckusick *magtape++ = 0; 1546849Smckusick if (rmthost(host) == 0) 1556849Smckusick done(1); 1566849Smckusick } 1576849Smckusick #endif 1584610Smckusick argc--; 1594610Smckusick break; 1604610Smckusick /* s dumpnum (skip to) for multifile dump tapes */ 1614610Smckusick case 's': 1624610Smckusick dumpnum = atoi(*argv++); 1636847Smckusick if (dumpnum <= 0) { 1644700Smckusic fprintf(stderr, "Dump number must be a positive integer\n"); 1654700Smckusic done(1); 1664610Smckusick } 1674610Smckusick argc--; 1684610Smckusick break; 1694610Smckusick case 'h': 1704610Smckusick hflag++; 1714610Smckusick break; 1724610Smckusick case 'm': 1734610Smckusick mflag++; 1744610Smckusick break; 1754610Smckusick case 'r': 1764610Smckusick case 'R': 1776844Smckusick hflag++; 1786844Smckusick mflag++; 1794610Smckusick case 't': 1804610Smckusick case 'x': 1814610Smckusick command = *cp; 1824610Smckusick break; 1834610Smckusick default: 1844700Smckusic fprintf(stderr, "Bad key character %c\n", *cp); 1854610Smckusick goto usage; 1864610Smckusick } 1874610Smckusick } 1886849Smckusick #ifdef RRESTOR 1896849Smckusick if (host == 0) 1906849Smckusick goto nohost; 1916849Smckusick #endif 1924610Smckusick doit(command, argc, argv); 1934700Smckusic done(0); 1944610Smckusick } 1954610Smckusick 1964610Smckusick doit(command, argc, argv) 1974700Smckusic char command; 1984700Smckusic int argc; 1994700Smckusic char *argv[]; 2004610Smckusick { 2015038Smckusic struct mtop tcom; 2025038Smckusic 2036849Smckusick #ifdef RRESTOR 2046849Smckusick if ((mt = rmtopen(magtape, 0)) < 0) { 2056849Smckusick #else 2064610Smckusick if ((mt = open(magtape, 0)) < 0) { 2076849Smckusick #endif 2084700Smckusic fprintf(stderr, "%s: cannot open tape\n", magtape); 2094700Smckusic done(1); 2104610Smckusick } 2114843Smckusic if (dumpnum != 1) { 2124610Smckusick tcom.mt_op = MTFSF; 2134610Smckusick tcom.mt_count = dumpnum -1; 2146849Smckusick #ifdef RRESTOR 2156849Smckusick rmtioctl(MTFSF,dumpnum - 1); 2166849Smckusick #else 2174843Smckusic if (ioctl(mt,MTIOCTOP,&tcom) < 0) 2184610Smckusick perror("ioctl MTFSF"); 2196849Smckusick #endif 2204610Smckusick } 2216846Smckusick blkclr(clearedbuf, (long)MAXBSIZE); 2224610Smckusick switch(command) { 2234610Smckusick case 't': 2244610Smckusick if (readhdr(&spcl) == 0) { 2254700Smckusic fprintf(stderr, "Tape is not a dump tape\n"); 2264700Smckusic done(1); 2274610Smckusick } 2284843Smckusic fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date)); 2294843Smckusic fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate)); 2304610Smckusick return; 2316844Smckusick case 'R': 2326844Smckusick case 'r': 2336844Smckusick setdir(*argv); 2346844Smckusick argc = 1; 2356844Smckusick *argv = "."; 2366844Smckusick /* and then extract it all */ 2374610Smckusick case 'x': 2386844Smckusick df = fopen(dirfile, "w"); 2396844Smckusick if (df == 0) { 2406844Smckusick fprintf(stderr, "restor: %s - cannot create directory temporary\n", dirfile); 2416844Smckusick done(1); 2426844Smckusick } 2434837Smckusic extractfiles(argc, argv); 2444837Smckusic return; 2454837Smckusic } 2464837Smckusic } 2474837Smckusic 2484837Smckusic extractfiles(argc, argv) 2494837Smckusic int argc; 2504837Smckusic char **argv; 2514837Smckusic { 2524843Smckusic char *ststore(); 2534837Smckusic register struct xtrlist *xp; 2544837Smckusic struct xtrlist **xpp; 2554837Smckusic ino_t d; 2566289Smckusick int xtrfile(), xtrskip(), xtrcvtdir(), xtrcvtskip(), 2576289Smckusick xtrlnkfile(), xtrlnkskip(), null(); 2586845Smckusick int mode, uid, gid, i; 2594843Smckusic char name[BUFSIZ + 1]; 2606844Smckusick struct stat stbuf; 2614837Smckusic 2626844Smckusick if (stat(".", &stbuf) < 0) { 2636844Smckusick fprintf(stderr, "cannot stat .\n"); 2646844Smckusick done(1); 2656844Smckusick } 2666844Smckusick /* 2676844Smckusick * should be!!! 2686844Smckusick * 2696844Smckusick fssize = stbuf.st_blksize; 2706844Smckusick */ 2716844Smckusick fssize = MAXBSIZE; 2724837Smckusic if (readhdr(&spcl) == 0) { 2734837Smckusic fprintf(stderr, "Tape is not a dump tape\n"); 2744837Smckusic done(1); 2754837Smckusic } 2764837Smckusic if (checkvol(&spcl, 1) == 0) { 2774837Smckusic fprintf(stderr, "Tape is not volume 1 of the dump\n"); 2784837Smckusic } 2796844Smckusick clrimap = 0; 2806844Smckusick dumpmap = 0; 2815038Smckusic pass1(1); /* This sets the various maps on the way by */ 2824843Smckusic while (argc--) { 2834837Smckusic if ((d = psearch(*argv)) == 0 || BIT(d,dumpmap) == 0) { 2846844Smckusick printf("d = %d\n", d); 2854843Smckusic fprintf(stdout, "%s: not on tape\n", *argv++); 2864837Smckusic continue; 2874610Smckusick } 2884843Smckusic if (mflag) 2894843Smckusic checkdir(*argv); 2906847Smckusick if (hflag) 2914837Smckusic getleaves(d, *argv++); 2924843Smckusic else 2934843Smckusic allocxtr(d, *argv++, XINUSE); 2944837Smckusic } 2954843Smckusic if (dumpnum > 1) { 2965038Smckusic /* 2975038Smckusic * if this is a multi-dump tape we always start with 2985038Smckusic * volume 1, so as to avoid accidentally restoring 2995038Smckusic * from a different dump! 3005038Smckusic */ 3015038Smckusic resetmt(); 3025038Smckusic dumpnum = 1; 3035038Smckusic volno = 1; 3045038Smckusic readhdr(&spcl); 3055038Smckusic goto rbits; 3064837Smckusic } 3075038Smckusic newvol: 3086849Smckusick #ifdef RRESTOR 3096849Smckusick rmtclose(); 3106849Smckusick #else 3116847Smckusick close(mt); 3126849Smckusick #endif 3134610Smckusick getvol: 3145038Smckusic fprintf(stderr, "Mount desired tape volume; Specify volume #: "); 3154837Smckusic if (gets(tbf) == NULL) 3164837Smckusic return; 3174837Smckusic volno = atoi(tbf); 3184837Smckusic if (volno <= 0) { 3194837Smckusic fprintf(stderr, "Volume numbers are positive numerics\n"); 3204837Smckusic goto getvol; 3214837Smckusic } 3226849Smckusick #ifdef RRESTOR 3236849Smckusick if ((mt = rmtopen(magtape, 0)) == -1) { 3246849Smckusick #else 3256847Smckusick if ((mt = open(magtape, 0)) == -1) { 3266849Smckusick #endif 3276847Smckusick fprintf(stderr, "Cannot open tape!\n"); 3286847Smckusick goto getvol; 3296847Smckusick } 3306847Smckusick if (dumpnum > 1) 3316847Smckusick resetmt(); 3324837Smckusic if (readhdr(&spcl) == 0) { 3334837Smckusic fprintf(stderr, "tape is not dump tape\n"); 3344837Smckusic goto newvol; 3354837Smckusic } 3364837Smckusic if (checkvol(&spcl, volno) == 0) { 3374837Smckusic fprintf(stderr, "Wrong volume (%d)\n", spcl.c_volume); 3384837Smckusic goto newvol; 3394837Smckusic } 3404610Smckusick rbits: 3414837Smckusic while (gethead(&spcl) == 0) 3424837Smckusic ; 3434837Smckusic if (checktype(&spcl, TS_INODE) == 1) { 3444837Smckusic fprintf(stderr, "Can't find inode mask!\n"); 3454837Smckusic goto newvol; 3464837Smckusic } 3474837Smckusic if (checktype(&spcl, TS_BITS) == 0) 3484837Smckusic goto rbits; 3496844Smckusick readbits(&dumpmap); 3504837Smckusic while (xtrcnt > 0) { 3514837Smckusic again: 3526845Smckusick if (ishead(&spcl) == 0) { 3536845Smckusick i = 0; 3546847Smckusick while (gethead(&spcl) == 0) 3556845Smckusick i++; 3566845Smckusick fprintf(stderr, "resync restor, skipped %i blocks\n", 3576845Smckusick i); 3586845Smckusick } 3594837Smckusic if (checktype(&spcl, TS_END) == 1) { 3604837Smckusic fprintf(stderr, "end of tape\n"); 3614837Smckusic break; 3624610Smckusick } 3634837Smckusic if (checktype(&spcl, TS_INODE) == 0) { 3644837Smckusic gethead(&spcl); 3654837Smckusic goto again; 3664610Smckusick } 3674837Smckusic d = spcl.c_inumber; 3684837Smckusic for (xp = xtrlist[INOHASH(d)]; xp; xp = xp->x_next) { 3694837Smckusic if (d != xp->x_ino) 3704837Smckusic continue; 3714837Smckusic if (xp->x_flags & XLINKED) 3724837Smckusic continue; 3734837Smckusic xp->x_timep[0] = spcl.c_dinode.di_atime; 3744837Smckusic xp->x_timep[1] = spcl.c_dinode.di_mtime; 3754837Smckusic mode = spcl.c_dinode.di_mode; 3764837Smckusic if (mflag) 3774843Smckusic strcpy(name, xp->x_name); 3784837Smckusic else 3794837Smckusic sprintf(name, "%u", xp->x_ino); 3804837Smckusic switch (mode & IFMT) { 3814837Smckusic default: 3826847Smckusick fprintf(stderr, "%s: unknown file mode 0%o\n", 3836847Smckusick name, mode); 3844837Smckusic xp->x_flags |= XTRACTD; 3854837Smckusic xtrcnt--; 3864837Smckusic goto skipfile; 3874837Smckusic case IFCHR: 3884837Smckusic case IFBLK: 3894843Smckusic fprintf(stdout, "extract special file %s\n", name); 3906844Smckusick if (mknod(name, mode, spcl.c_dinode.di_rdev)) { 3914837Smckusic fprintf(stderr, "%s: cannot create special file\n", name); 3924837Smckusic xp->x_flags |= XTRACTD; 3934837Smckusic xtrcnt--; 3944837Smckusic goto skipfile; 3954776Smckusic } 3964837Smckusic getfile(null, null, spcl.c_dinode.di_size); 3974837Smckusic break; 3984837Smckusic case IFDIR: 3994837Smckusic if (mflag) { 4004843Smckusic fprintf(stdout, "extract directory %s\n", name); 4014837Smckusic strncat(name, "/.", BUFSIZ); 4024843Smckusic checkdir(name); 4036844Smckusick chown(xp->x_name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 4044837Smckusic getfile(null, null, spcl.c_dinode.di_size); 4054837Smckusic break; 4064610Smckusick } 4075038Smckusic fprintf(stdout, "extract file %s\n", name); 4086844Smckusick if ((ofile = creat(name, 0666)) < 0) { 4095038Smckusic fprintf(stderr, "%s: cannot create file\n", name); 4105038Smckusic xp->x_flags |= XTRACTD; 4115038Smckusic xtrcnt--; 4125038Smckusic goto skipfile; 4135038Smckusic } 4146844Smckusick chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 4155943Smckusic if (cvtdir) { 4165038Smckusic getfile(xtrcvtdir, xtrcvtskip, 4175038Smckusic spcl.c_dinode.di_size); 4185943Smckusic flushent(xtrfile); 4195943Smckusic } else 4205038Smckusic getfile(xtrfile, xtrskip, 4215038Smckusic spcl.c_dinode.di_size); 4226844Smckusick close(ofile); 4235038Smckusic break; 4246289Smckusick case IFLNK: 4256289Smckusick fprintf(stdout, "extract symbolic link %s\n", name); 4266289Smckusick uid = spcl.c_dinode.di_uid; 4276289Smckusick gid = spcl.c_dinode.di_gid; 4286289Smckusick lnkbuf[0] = '\0'; 4296289Smckusick pathlen = 0; 4306289Smckusick getfile(xtrlnkfile, xtrlnkskip, spcl.c_dinode.di_size); 4316844Smckusick if (symlink(lnkbuf, name) < 0) { 4326289Smckusick fprintf(stderr, "%s: cannot create symbolic link\n", name); 4336289Smckusick xp->x_flags |= XTRACTD; 4346289Smckusick xtrcnt--; 4356289Smckusick goto finished; 4366289Smckusick } 4376844Smckusick chown(name, uid, gid); 4386289Smckusick break; 4394837Smckusic case IFREG: 4404843Smckusic fprintf(stdout, "extract file %s\n", name); 4416844Smckusick if ((ofile = creat(name, 0666)) < 0) { 4424837Smckusic fprintf(stderr, "%s: cannot create file\n", name); 4434837Smckusic xp->x_flags |= XTRACTD; 4444837Smckusic xtrcnt--; 4454837Smckusic goto skipfile; 4464837Smckusic } 4476844Smckusick chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 4485038Smckusic getfile(xtrfile, xtrskip, spcl.c_dinode.di_size); 4496844Smckusick close(ofile); 4504837Smckusic break; 4514610Smckusick } 4526844Smckusick chmod(name, mode); 4536844Smckusick utime(name, xp->x_timep); 4544837Smckusic xp->x_flags |= XTRACTD; 4554837Smckusic xtrcnt--; 4564837Smckusic goto finished; 4574837Smckusic } 4584837Smckusic skipfile: 4594837Smckusic getfile(null, null, spcl.c_dinode.di_size); 4604700Smckusic finished: 4614837Smckusic ; 4624837Smckusic } 4634837Smckusic if (xtrcnt == 0 && !mflag) 4644837Smckusic return; 4654837Smckusic for (xpp = xtrlist; xpp < &xtrlist[MAXINO]; xpp++) { 4664837Smckusic for (xp = *xpp; xp; xp = xp->x_next) { 4674837Smckusic if (mflag && (xp->x_flags & XISDIR)) 4686844Smckusick utime(xp->x_name, xp->x_timep); 4694837Smckusic if (xp->x_flags & XTRACTD) 4704837Smckusic continue; 4714837Smckusic if ((xp->x_flags & XLINKED) == 0) { 4724837Smckusic fprintf(stderr, "cannot find file %s\n", 4734837Smckusic xp->x_name); 4744837Smckusic continue; 4754837Smckusic } 4764843Smckusic if (!mflag) 4774843Smckusic continue; 4784843Smckusic fprintf(stdout, "link %s to %s\n", 4794843Smckusic xp->x_linkedto->x_name, xp->x_name); 4806844Smckusick if (link(xp->x_linkedto->x_name, xp->x_name) < 0) 4814843Smckusic fprintf(stderr, "link %s to %s failed\n", 4824837Smckusic xp->x_linkedto->x_name, xp->x_name); 4834610Smckusick } 4844837Smckusic } 4854837Smckusic } 4864837Smckusic 4874610Smckusick /* 4884610Smckusick * Read the tape, bulding up a directory structure for extraction 4894610Smckusick * by name 4904610Smckusick */ 4915038Smckusic pass1(savedir) 4925038Smckusic int savedir; 4934610Smckusick { 4944776Smckusic register int i; 4954837Smckusic register struct dinode *ip; 4964837Smckusic struct direct nulldir; 4975038Smckusic char buf[TP_BSIZE]; 4985943Smckusic int putdir(), null(), dirwrite(); 4994610Smckusick 5005943Smckusic nulldir.d_ino = 1; 5015943Smckusic nulldir.d_namlen = 1; 5025943Smckusic strncpy(nulldir.d_name, "/", nulldir.d_namlen); 5035943Smckusic nulldir.d_reclen = DIRSIZ(&nulldir); 5044610Smckusick while (gethead(&spcl) == 0) { 5054700Smckusic fprintf(stderr, "Can't find directory header!\n"); 5064610Smckusick } 5074610Smckusick for (;;) { 5084610Smckusick if (checktype(&spcl, TS_BITS) == 1) { 5096844Smckusick readbits(&dumpmap); 5104610Smckusick continue; 5114610Smckusick } 5124610Smckusick if (checktype(&spcl, TS_CLRI) == 1) { 5136844Smckusick readbits(&clrimap); 5144610Smckusick continue; 5154610Smckusick } 5164610Smckusick if (checktype(&spcl, TS_INODE) == 0) { 5174610Smckusick finish: 5185943Smckusic if (savedir) { 5195943Smckusic fclose(df); 5205943Smckusic dirp = opendir(dirfile); 5215943Smckusic if (dirp == NULL) 5225943Smckusic perror("opendir"); 5235943Smckusic } 5245038Smckusic resetmt(); 5254610Smckusick return; 5264610Smckusick } 5274610Smckusick ip = &spcl.c_dinode; 5284610Smckusick i = ip->di_mode & IFMT; 5294610Smckusick if (i != IFDIR) { 5304610Smckusick goto finish; 5314610Smckusick } 5325038Smckusic if (spcl.c_inumber == ROOTINO) { 5335038Smckusic readtape(buf); 5345038Smckusic bct--; /* push back this block */ 5355038Smckusic if (((struct direct *)buf)->d_ino != ROOTINO) { 5365038Smckusic if (((struct odirect *)buf)->d_ino != ROOTINO) { 5375038Smckusic fprintf(stderr, "bad root directory\n"); 5385038Smckusic done(1); 5395038Smckusic } 5405038Smckusic fprintf(stderr, "converting to new directory format\n"); 5415038Smckusic cvtdir = 1; 542*8302Smckusick cvtflag = 1; 5435038Smckusic } 5445038Smckusic if (!savedir && !cvtdir) { 5455038Smckusic /* if no conversion, just return */ 5465038Smckusic goto finish; 5475038Smckusic } 5485038Smckusic } 5494843Smckusic allocinotab(spcl.c_inumber, seekpt); 5505038Smckusic if (savedir) { 5515038Smckusic getfile(putdir, null, spcl.c_dinode.di_size); 5525943Smckusic putent(&nulldir, dirwrite); 5535943Smckusic flushent(dirwrite); 5545038Smckusic } else { 5555038Smckusic getfile(null, null, spcl.c_dinode.di_size); 5565038Smckusic } 5574610Smckusick } 5584610Smckusick } 5594610Smckusick 5604610Smckusick /* 5614843Smckusic * Put the directory entries in the directory file 5624843Smckusic */ 5634843Smckusic putdir(buf, size) 5644843Smckusic char *buf; 5654843Smckusic int size; 5664843Smckusic { 5675038Smckusic struct direct cvtbuf; 5685038Smckusic register struct odirect *odp; 5695038Smckusic struct odirect *eodp; 5704843Smckusic register struct direct *dp; 5716289Smckusick long loc, i; 5724843Smckusic 5735038Smckusic if (cvtdir) { 5745038Smckusic eodp = (struct odirect *)&buf[size]; 5755038Smckusic for (odp = (struct odirect *)buf; odp < eodp; odp++) 5765038Smckusic if (odp->d_ino != 0) { 5775038Smckusic dcvt(odp, &cvtbuf); 5785943Smckusic putent(&cvtbuf, dirwrite); 5795038Smckusic } 5805038Smckusic } else { 5815943Smckusic for (loc = 0; loc < size; ) { 5825943Smckusic dp = (struct direct *)(buf + loc); 5836289Smckusick i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); 5846289Smckusick if (dp->d_reclen <= 0 || dp->d_reclen > i) { 5856289Smckusick loc += i; 5866289Smckusick continue; 5876289Smckusick } 5886289Smckusick loc += dp->d_reclen; 5896847Smckusick if (dp->d_ino != 0) { 5905943Smckusic putent(dp, dirwrite); 5916847Smckusick } 5925943Smckusic } 5935038Smckusic } 5944843Smckusic } 5954843Smckusic 5964843Smckusic /* 5974843Smckusic * Recursively find names and inumbers of all files in subtree 5984843Smckusic * pname and put them in xtrlist[] 5994843Smckusic */ 6004843Smckusic getleaves(ino, pname) 6014843Smckusic ino_t ino; 6024843Smckusic char *pname; 6034843Smckusic { 6044843Smckusic register struct inotab *itp; 6054843Smckusic int namelen; 6066846Smckusick daddr_t bpt; 6075943Smckusic register struct direct *dp; 6085943Smckusic char locname[BUFSIZ + 1]; 6094843Smckusic 6104843Smckusic if (BIT(ino, dumpmap) == 0) { 6114843Smckusic fprintf(stdout, "%s: not on the tape\n", pname); 6124843Smckusic return; 6134843Smckusic } 6144843Smckusic for (itp = inotab[INOHASH(ino)]; itp; itp = itp->t_next) { 6154843Smckusic if (itp->t_ino != ino) 6164843Smckusic continue; 6174843Smckusic /* 6184843Smckusic * pname is a directory name 6194843Smckusic */ 6204843Smckusic allocxtr(ino, pname, XISDIR); 6214843Smckusic /* 6224843Smckusic * begin search through the directory 6234843Smckusic * skipping over "." and ".." 6244843Smckusic */ 6254843Smckusic strncpy(locname, pname, BUFSIZ); 6264843Smckusic strncat(locname, "/", BUFSIZ); 6274843Smckusic namelen = strlen(locname); 6285943Smckusic seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 6295943Smckusic dp = readdir(dirp); 6305943Smckusic dp = readdir(dirp); 6315943Smckusic dp = readdir(dirp); 6325943Smckusic bpt = telldir(dirp); 6334843Smckusic /* 6344843Smckusic * "/" signals end of directory 6354843Smckusic */ 6365943Smckusic while (dp->d_namlen != 1 || dp->d_name[0] != '/') { 6374843Smckusic locname[namelen] = '\0'; 6385943Smckusic if (namelen + dp->d_namlen >= BUFSIZ) { 6395943Smckusic fprintf(stderr, "%s%s: name exceedes %d char\n", 6405943Smckusic locname, dp->d_name, BUFSIZ); 6414843Smckusic continue; 6424843Smckusic } 6435943Smckusic strncat(locname, dp->d_name, dp->d_namlen); 6445943Smckusic getleaves(dp->d_ino, locname); 6455943Smckusic seekdir(dirp, bpt, itp->t_seekpt); 6465943Smckusic dp = readdir(dirp); 6475943Smckusic bpt = telldir(dirp); 6484843Smckusic } 6494843Smckusic return; 6504843Smckusic } 6514843Smckusic /* 6524843Smckusic * locname is name of a simple file 6534843Smckusic */ 6544843Smckusic allocxtr(ino, pname, XINUSE); 6554843Smckusic } 6564843Smckusic 6574843Smckusic /* 6584843Smckusic * Search the directory tree rooted at inode ROOTINO 6594843Smckusic * for the path pointed at by n 6604843Smckusic */ 6614843Smckusic psearch(n) 6624843Smckusic char *n; 6634843Smckusic { 6644843Smckusic register char *cp, *cp1; 6654843Smckusic char c; 6664843Smckusic 6674843Smckusic ino = ROOTINO; 6684843Smckusic if (*(cp = n) == '/') 6694843Smckusic cp++; 6704843Smckusic next: 6714843Smckusic cp1 = cp + 1; 6724843Smckusic while (*cp1 != '/' && *cp1) 6734843Smckusic cp1++; 6744843Smckusic c = *cp1; 6754843Smckusic *cp1 = 0; 6764843Smckusic ino = search(ino, cp); 6774843Smckusic if (ino == 0) { 6784843Smckusic *cp1 = c; 6794843Smckusic return(0); 6804843Smckusic } 6814843Smckusic *cp1 = c; 6824843Smckusic if (c == '/') { 6834843Smckusic cp = cp1+1; 6844843Smckusic goto next; 6854843Smckusic } 6864843Smckusic return(ino); 6874843Smckusic } 6884843Smckusic 6894843Smckusic /* 6904843Smckusic * search the directory inode ino 6914843Smckusic * looking for entry cp 6924843Smckusic */ 6934843Smckusic ino_t 6944843Smckusic search(inum, cp) 6954843Smckusic ino_t inum; 6964843Smckusic char *cp; 6974843Smckusic { 6985943Smckusic register struct direct *dp; 6994843Smckusic register struct inotab *itp; 7005943Smckusic int len; 7014843Smckusic 7024843Smckusic for (itp = inotab[INOHASH(inum)]; itp; itp = itp->t_next) 7034843Smckusic if (itp->t_ino == inum) 7044843Smckusic goto found; 7054843Smckusic return(0); 7064843Smckusic found: 7075943Smckusic seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 7085943Smckusic len = strlen(cp); 7094843Smckusic do { 7105943Smckusic dp = readdir(dirp); 7115943Smckusic if (dp->d_namlen == 1 && dp->d_name[0] == '/') 7124843Smckusic return(0); 7135943Smckusic } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len)); 7145943Smckusic return(dp->d_ino); 7154843Smckusic } 7164843Smckusic 7174843Smckusic /* 7184610Smckusick * Do the file extraction, calling the supplied functions 7194610Smckusick * with the blocks 7204610Smckusick */ 7214700Smckusic getfile(f1, f2, size) 7224700Smckusic int (*f2)(), (*f1)(); 7236846Smckusick off_t size; 7244610Smckusick { 7254776Smckusic register int i; 7265327Smckusic char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; 7274837Smckusic union u_spcl addrblk; 7284837Smckusic # define addrblock addrblk.s_spcl 7294610Smckusick 7304837Smckusic addrblock = spcl; 7314610Smckusick for (;;) { 7324837Smckusic for (i = 0; i < addrblock.c_count; i++) { 7334837Smckusic if (addrblock.c_addr[i]) { 7344776Smckusic readtape(&buf[curblk++][0]); 7356844Smckusick if (curblk == fssize / TP_BSIZE) { 7364776Smckusic (*f1)(buf, size > TP_BSIZE ? 7376844Smckusick (long) (fssize) : 7384776Smckusic (curblk - 1) * TP_BSIZE + size); 7394776Smckusic curblk = 0; 7404776Smckusic } 7415327Smckusic } else { 7424776Smckusic if (curblk > 0) { 7434776Smckusic (*f1)(buf, size > TP_BSIZE ? 7444776Smckusic (long) (curblk * TP_BSIZE) : 7454776Smckusic (curblk - 1) * TP_BSIZE + size); 7464776Smckusic curblk = 0; 7474776Smckusic } 7485327Smckusic (*f2)(clearedbuf, size > TP_BSIZE ? 7495327Smckusic (long) TP_BSIZE : size); 7504610Smckusick } 7514776Smckusic if ((size -= TP_BSIZE) <= 0) { 7524610Smckusick eloop: 7534610Smckusick while (gethead(&spcl) == 0) 7544610Smckusick ; 7554610Smckusick if (checktype(&spcl, TS_ADDR) == 1) 7564610Smckusick goto eloop; 7574776Smckusic goto out; 7584610Smckusick } 7594610Smckusick } 7604837Smckusic if (gethead(&addrblock) == 0) { 7614776Smckusic fprintf(stderr, "Missing address (header) block, ino%u\n", ino); 7624700Smckusic goto eloop; 7634700Smckusic } 7644837Smckusic if (checktype(&addrblock, TS_ADDR) == 0) { 7654837Smckusic spcl = addrblock; 7664776Smckusic goto out; 7674700Smckusic } 7684610Smckusick } 7694776Smckusic out: 7704776Smckusic if (curblk > 0) { 7714776Smckusic (*f1)(buf, (curblk * TP_BSIZE) + size); 7724776Smckusic curblk = 0; 7734776Smckusic } 7744610Smckusick } 7754610Smckusick 7764610Smckusick /* 7774843Smckusic * The next routines are called during file extraction to 7784843Smckusic * put the data into the right form and place. 7794843Smckusic */ 7804843Smckusic xtrfile(buf, size) 7814843Smckusic char *buf; 7824843Smckusic long size; 7834843Smckusic { 7846847Smckusick 7856844Smckusick if (write(ofile, buf, (int) size) == -1) { 7865038Smckusic perror("extract write"); 7874843Smckusic done(1); 7884843Smckusic } 7894843Smckusic } 7904843Smckusic 7915038Smckusic xtrskip(buf, size) 7924843Smckusic char *buf; 7934843Smckusic long size; 7944843Smckusic { 7956847Smckusick 7966846Smckusick #ifdef lint 7976846Smckusick buf = buf; 7986846Smckusick #endif 7996844Smckusick if (lseek(ofile, size, 1) == -1) { 8005038Smckusic perror("extract seek"); 8014843Smckusic done(1); 8024843Smckusic } 8034843Smckusic } 8045038Smckusic 8055038Smckusic xtrcvtdir(buf, size) 8065038Smckusic struct odirect *buf; 8075038Smckusic long size; 8085038Smckusic { 8095038Smckusic struct odirect *odp, *edp; 8106846Smckusick struct direct cvtbuf; 8115038Smckusic 8125038Smckusic edp = &buf[size / sizeof(struct odirect)]; 8135943Smckusic for (odp = buf; odp < edp; odp++) { 8145943Smckusic dcvt(odp, &cvtbuf); 8155943Smckusic putent(&cvtbuf, xtrfile); 8165038Smckusic } 8175038Smckusic } 8185038Smckusic 8195038Smckusic xtrcvtskip(buf, size) 8205038Smckusic char *buf; 8215038Smckusic long size; 8225038Smckusic { 8236847Smckusick 8245038Smckusic fprintf(stderr, "unallocated block in directory\n"); 8255943Smckusic xtrskip(buf, size); 8265038Smckusic } 8276289Smckusick 8286289Smckusick xtrlnkfile(buf, size) 8296289Smckusick char *buf; 8306289Smckusick long size; 8316289Smckusick { 8326847Smckusick 8336289Smckusick pathlen += size; 8346289Smckusick if (pathlen > MAXPATHLEN) { 8356289Smckusick fprintf(stderr, "symbolic link name: %s; too long %d\n", 8366289Smckusick buf, size); 8376289Smckusick done(1); 8386289Smckusick } 8396289Smckusick strcat(lnkbuf, buf); 8406289Smckusick } 8416289Smckusick 8426289Smckusick xtrlnkskip(buf, size) 8436289Smckusick char *buf; 8446289Smckusick long size; 8456289Smckusick { 8466847Smckusick 8476846Smckusick #ifdef lint 8486846Smckusick buf = buf, size = size; 8496846Smckusick #endif 8506289Smckusick fprintf(stderr, "unallocated block in symbolic link\n"); 8516289Smckusick done(1); 8526289Smckusick } 8534843Smckusic 8544843Smckusic null() {;} 8554843Smckusic 8564843Smckusic /* 8574776Smckusic * Do the tape i/o, dealing with volume changes 8584610Smckusick * etc.. 8594610Smckusick */ 8604610Smckusick readtape(b) 8614700Smckusic char *b; 8624610Smckusick { 8636846Smckusick register long i; 8646847Smckusick struct u_spcl tmpbuf; 8656845Smckusick char c; 8664610Smckusick 8674610Smckusick if (bct >= NTREC) { 8684610Smckusick for (i = 0; i < NTREC; i++) 8694776Smckusic ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0; 8704610Smckusick bct = 0; 8716849Smckusick #ifdef RRESTOR 8726849Smckusick if ((i = rmtread(tbf, NTREC*TP_BSIZE)) < 0) { 8736849Smckusick #else 8744776Smckusic if ((i = read(mt, tbf, NTREC*TP_BSIZE)) < 0) { 8756849Smckusick #endif 8766845Smckusick fprintf(stderr, "Tape read error, continue?"); 8776845Smckusick do { 8786845Smckusick fprintf(stderr, "[yn]\n"); 8796845Smckusick c = getchar(); 8806845Smckusick while (getchar() != '\n') 8816845Smckusick /* void */; 8826845Smckusick } while (c != 'y' && c != 'n'); 8834610Smckusick eflag++; 8846845Smckusick if (c == 'n') 8856845Smckusick done(1); 8866845Smckusick i = NTREC*TP_BSIZE; 8876845Smckusick blkclr(tbf, i); 8886849Smckusick #ifdef RRESTOR 8896849Smckusick if (rmtseek(i, 1) < 0) { 8906849Smckusick #else 8916846Smckusick if (lseek(mt, i, 1) < 0) { 8926849Smckusick #endif 8936846Smckusick fprintf(stderr, "continuation failed\n"); 8946846Smckusick done(1); 8956846Smckusick } 8964610Smckusick } 8974610Smckusick if (i == 0) { 8984610Smckusick bct = NTREC + 1; 8994610Smckusick volno++; 9004610Smckusick loop: 9014610Smckusick flsht(); 9026849Smckusick #ifdef RRESTOR 9036849Smckusick rmtclose(); 9046849Smckusick #else 9054610Smckusick close(mt); 9066849Smckusick #endif 9074700Smckusic fprintf(stderr, "Mount volume %d\n", volno); 9084610Smckusick while (getchar() != '\n') 9094610Smckusick ; 9106849Smckusick #ifdef RRESTOR 9116849Smckusick if ((mt = rmtopen(magtape, 0)) == -1) { 9126849Smckusick #else 9134610Smckusick if ((mt = open(magtape, 0)) == -1) { 9146849Smckusick #endif 9154700Smckusic fprintf(stderr, "Cannot open tape!\n"); 9164610Smckusick goto loop; 9174610Smckusick } 9184610Smckusick if (readhdr(&tmpbuf) == 0) { 9194700Smckusic fprintf(stderr, "Not a dump tape.Try again\n"); 9204610Smckusick goto loop; 9214610Smckusick } 9224610Smckusick if (checkvol(&tmpbuf, volno) == 0) { 9234700Smckusic fprintf(stderr, "Wrong tape. Try again\n"); 9244610Smckusick goto loop; 9254610Smckusick } 9264610Smckusick readtape(b); 9274610Smckusick return; 9284610Smckusick } 9294610Smckusick } 9306846Smckusick blkcpy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE); 9314610Smckusick } 9324610Smckusick 9334610Smckusick flsht() 9344610Smckusick { 9356847Smckusick 9364610Smckusick bct = NTREC+1; 9374610Smckusick } 9384610Smckusick 9395943Smckusic blkcpy(from, to, size) 9405943Smckusic char *from, *to; 9416846Smckusick long size; 9424610Smckusick { 9436847Smckusick 9446846Smckusick #ifdef lint 9456846Smckusick from = from, to = to, size = size; 9466846Smckusick #endif 9475943Smckusic asm(" movc3 12(ap),*4(ap),*8(ap)"); 9484610Smckusick } 9494610Smckusick 9505038Smckusic blkclr(buf, size) 9515038Smckusic char *buf; 9526846Smckusick long size; 9535038Smckusic { 9546847Smckusick 9556846Smckusick #ifdef lint 9566846Smckusick buf = buf, size = size; 9576846Smckusick #endif 9585038Smckusic asm("movc5 $0,(r0),$0,8(ap),*4(ap)"); 9595038Smckusic } 9605038Smckusic 9615038Smckusic resetmt() 9625038Smckusic { 9635038Smckusic struct mtop tcom; 9645038Smckusic 9656847Smckusick if (dumpnum > 1) 9665038Smckusic tcom.mt_op = MTBSF; 9675038Smckusic else 9685038Smckusic tcom.mt_op = MTREW; 9695038Smckusic tcom.mt_count = 1; 9705038Smckusic flsht(); 9716849Smckusick #ifdef RRESTOR 9726849Smckusick if (rmtioctl(tcom.mt_op, 1) == -1) { 9736849Smckusick /* kludge for disk dumps */ 9746849Smckusick rmtseek((long)0, 0); 9756849Smckusick } 9766849Smckusick #else 9775038Smckusic if (ioctl(mt,MTIOCTOP,&tcom) == -1) { 9785038Smckusic /* kludge for disk dumps */ 9795038Smckusic lseek(mt, (long)0, 0); 9805038Smckusic } 9816849Smckusick #endif 9825038Smckusic if (dumpnum > 1) { 9836849Smckusick #ifdef RRESTOR 9846849Smckusick rmtioctl(MTFSF, 1); 9856849Smckusick #else 9865038Smckusic tcom.mt_op = MTFSF; 9875038Smckusic tcom.mt_count = 1; 9885038Smckusic ioctl(mt,MTIOCTOP,&tcom); 9896849Smckusick #endif 9905038Smckusic } 9915038Smckusic } 9925038Smckusic 9934843Smckusic checkvol(b, t) 9944843Smckusic struct s_spcl *b; 9954843Smckusic int t; 9964610Smckusick { 9976847Smckusick 9984843Smckusic if (b->c_volume == t) 9994843Smckusic return(1); 10004610Smckusick return(0); 10014610Smckusick } 10024610Smckusick 10034843Smckusic readhdr(b) 10044843Smckusic struct s_spcl *b; 10054610Smckusick { 10066847Smckusick 10074843Smckusic if (gethead(b) == 0) 10084610Smckusick return(0); 10094843Smckusic if (checktype(b, TS_TAPE) == 0) 10104843Smckusic return(0); 10114843Smckusic return(1); 10124610Smckusick } 10134610Smckusick 10144610Smckusick /* 10154610Smckusick * read the tape into buf, then return whether or 10164610Smckusick * or not it is a header block. 10174610Smckusick */ 10184610Smckusick gethead(buf) 10194837Smckusic struct s_spcl *buf; 10204610Smckusick { 1021*8302Smckusick union u_ospcl { 1022*8302Smckusick char dummy[TP_BSIZE]; 1023*8302Smckusick struct s_ospcl { 1024*8302Smckusick int c_type; 1025*8302Smckusick time_t c_date; 1026*8302Smckusick time_t c_ddate; 1027*8302Smckusick int c_volume; 1028*8302Smckusick daddr_t c_tapea; 1029*8302Smckusick ino_t c_inumber; 1030*8302Smckusick int c_magic; 1031*8302Smckusick int c_checksum; 1032*8302Smckusick struct odinode { 1033*8302Smckusick unsigned short odi_mode; 1034*8302Smckusick short odi_nlink; 1035*8302Smckusick short odi_uid; 1036*8302Smckusick short odi_gid; 1037*8302Smckusick off_t odi_size; 1038*8302Smckusick daddr_t odi_rdev; 1039*8302Smckusick char odi_addr[36]; 1040*8302Smckusick time_t odi_atime; 1041*8302Smckusick time_t odi_mtime; 1042*8302Smckusick time_t odi_ctime; 1043*8302Smckusick } c_dinode; 1044*8302Smckusick int c_count; 1045*8302Smckusick char c_addr[TP_NINDIR]; 1046*8302Smckusick } s_ospcl; 1047*8302Smckusick } u_ospcl; 10486847Smckusick 1049*8302Smckusick if (!cvtflag) { 1050*8302Smckusick readtape((char *)buf); 1051*8302Smckusick if (buf->c_magic != MAGIC || checksum((int *)buf) == 0) 1052*8302Smckusick return(0); 1053*8302Smckusick return(1); 1054*8302Smckusick } 1055*8302Smckusick readtape((char *)(&u_ospcl.s_ospcl)); 1056*8302Smckusick if (u_ospcl.s_ospcl.c_magic != MAGIC || 1057*8302Smckusick checksum((int *)(&u_ospcl.s_ospcl)) == 0) 10584610Smckusick return(0); 1059*8302Smckusick blkclr((char *)buf, TP_BSIZE); 1060*8302Smckusick buf->c_type = u_ospcl.s_ospcl.c_type; 1061*8302Smckusick buf->c_date = u_ospcl.s_ospcl.c_date; 1062*8302Smckusick buf->c_ddate = u_ospcl.s_ospcl.c_ddate; 1063*8302Smckusick buf->c_volume = u_ospcl.s_ospcl.c_volume; 1064*8302Smckusick buf->c_tapea = u_ospcl.s_ospcl.c_tapea; 1065*8302Smckusick buf->c_inumber = u_ospcl.s_ospcl.c_inumber; 1066*8302Smckusick buf->c_magic = u_ospcl.s_ospcl.c_magic; 1067*8302Smckusick buf->c_checksum = u_ospcl.s_ospcl.c_checksum; 1068*8302Smckusick buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode; 1069*8302Smckusick buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink; 1070*8302Smckusick buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid; 1071*8302Smckusick buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; 1072*8302Smckusick buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size; 1073*8302Smckusick buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev; 1074*8302Smckusick buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; 1075*8302Smckusick buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; 1076*8302Smckusick buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; 1077*8302Smckusick buf->c_count = u_ospcl.s_ospcl.c_count; 1078*8302Smckusick blkcpy(u_ospcl.s_ospcl.c_addr, buf->c_addr, TP_NINDIR); 10794610Smckusick return(1); 10804610Smckusick } 10814610Smckusick 10824610Smckusick /* 10834610Smckusick * return whether or not the buffer contains a header block 10844610Smckusick */ 10854610Smckusick ishead(buf) 10864837Smckusic struct s_spcl *buf; 10874610Smckusick { 10886847Smckusick 1089*8302Smckusick if (buf->c_magic != MAGIC) 10904610Smckusick return(0); 10914610Smckusick return(1); 10924610Smckusick } 10934610Smckusick 10944610Smckusick checktype(b, t) 10954837Smckusic struct s_spcl *b; 10964700Smckusic int t; 10974610Smckusick { 10986847Smckusick 10994837Smckusic return(b->c_type == t); 11004610Smckusick } 11014610Smckusick 11025038Smckusic /* 11035038Smckusic * read a bit mask from the tape into m. 11045038Smckusic */ 11056844Smckusick readbits(mapp) 11066844Smckusick char **mapp; 11075038Smckusic { 11085038Smckusic register int i; 11096844Smckusick char *m; 11104610Smckusick 11115038Smckusic i = spcl.c_count; 11125038Smckusic 11136844Smckusick if (*mapp == 0) 11146846Smckusick *mapp = (char *)calloc(i, (TP_BSIZE/(NBBY/BITS))); 11156844Smckusick m = *mapp; 11165038Smckusic while (i--) { 11175038Smckusic readtape((char *) m); 11185327Smckusic m += (TP_BSIZE/(NBBY/BITS)); 11195038Smckusic } 11205038Smckusic while (gethead(&spcl) == 0) 11215038Smckusic ; 11225038Smckusic } 11235038Smckusic 11244610Smckusick checksum(b) 1125*8302Smckusick register int *b; 11264610Smckusick { 11274776Smckusic register int i, j; 11284610Smckusick 11294776Smckusic j = sizeof(union u_spcl) / sizeof(int); 11304610Smckusick i = 0; 11314610Smckusick do 11324610Smckusick i += *b++; 11334610Smckusick while (--j); 11344610Smckusick if (i != CHECKSUM) { 11354776Smckusic fprintf(stderr, "Checksum error %o, ino %u\n", i, ino); 11364610Smckusick return(0); 11374610Smckusick } 11384610Smckusick return(1); 11394610Smckusick } 11404610Smckusick 11414610Smckusick /* 11425038Smckusic * Check for access into each directory in the pathname of an extracted 11435038Smckusic * file and create such a directory if needed in preparation for moving 11445038Smckusic * the file to its proper home. 11455038Smckusic */ 11465038Smckusic checkdir(name) 11475038Smckusic register char *name; 11485038Smckusic { 11495038Smckusic register char *cp; 11505038Smckusic int i; 11515038Smckusic 11525038Smckusic for (cp = name; *cp; cp++) { 11535038Smckusic if (*cp == '/') { 11545038Smckusic *cp = '\0'; 11556844Smckusick if (access(name, 01) < 0) { 11565038Smckusic register int pid, rp; 11575038Smckusic 11585038Smckusic if ((pid = fork()) == 0) { 11596844Smckusick execl("/bin/mkdir", "mkdir", name, 0); 11606844Smckusick execl("/usr/bin/mkdir", "mkdir", name, 0); 11616844Smckusick fprintf(stderr, "restor: cannot find mkdir!\n"); 11625038Smckusic done(0); 11635038Smckusic } 11645038Smckusic while ((rp = wait(&i)) >= 0 && rp != pid) 11655038Smckusic ; 11665038Smckusic } 11675038Smckusic *cp = '/'; 11685038Smckusic } 11695038Smckusic } 11705038Smckusic } 11715038Smckusic 11726844Smckusick setdir(dev) 11736844Smckusick char *dev; 11746844Smckusick { 11756844Smckusick struct fstab *fsp; 11766844Smckusick 11776844Smckusick if (setfsent() == 0) { 11786844Smckusick fprintf(stderr, "Can't open checklist file: %s\n", FSTAB); 11796844Smckusick done(1); 11806844Smckusick } 11816844Smckusick while ((fsp = getfsent()) != 0) { 11826844Smckusick if (strcmp(fsp->fs_spec, dev) == 0) { 11836844Smckusick printf("%s mounted on %s\n", dev, fsp->fs_file); 11846844Smckusick if (chdir(fsp->fs_file) >= 0) 11856844Smckusick return; 11866844Smckusick fprintf(stderr, "%s cannot chdir to %s\n", 11876844Smckusick fsp->fs_file); 11886844Smckusick done(1); 11896844Smckusick } 11906844Smckusick } 11916844Smckusick fprintf(stderr, "%s not mounted\n", dev); 11926844Smckusick done(1); 11936844Smckusick } 11946844Smckusick 11955038Smckusic /* 11965943Smckusic * These variables are "local" to the following two functions. 11975943Smckusic */ 11985943Smckusic char dirbuf[DIRBLKSIZ]; 11995943Smckusic long dirloc = 0; 12005943Smckusic long prev = 0; 12015943Smckusic 12025943Smckusic /* 12035943Smckusic * add a new directory entry to a file. 12045943Smckusic */ 12055943Smckusic putent(dp, wrtfunc) 12065943Smckusic struct direct *dp; 12075943Smckusic int (*wrtfunc)(); 12085943Smckusic { 12096847Smckusick 12105943Smckusic if (dp->d_ino == 0) 12115943Smckusic return; 12126847Smckusick if (dirloc + dp->d_reclen > DIRBLKSIZ) { 12136847Smckusick ((struct direct *)(dirbuf + prev))->d_reclen = 12146847Smckusick DIRBLKSIZ - prev; 12155943Smckusic (*wrtfunc)(dirbuf, DIRBLKSIZ); 12165943Smckusic dirloc = 0; 12175943Smckusic } 12186847Smckusick blkcpy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); 12196847Smckusick prev = dirloc; 12206847Smckusick dirloc += dp->d_reclen; 12215943Smckusic } 12225943Smckusic 12235943Smckusic /* 12245943Smckusic * flush out a directory that is finished. 12255943Smckusic */ 12265943Smckusic flushent(wrtfunc) 12275943Smckusic int (*wrtfunc)(); 12285943Smckusic { 12296847Smckusick 12305943Smckusic ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; 12315943Smckusic (*wrtfunc)(dirbuf, dirloc); 12325943Smckusic dirloc = 0; 12335943Smckusic } 12345943Smckusic 12355943Smckusic dirwrite(buf, size) 12365943Smckusic char *buf; 12375943Smckusic int size; 12385943Smckusic { 12396847Smckusick 12405943Smckusic fwrite(buf, 1, size, df); 12415943Smckusic seekpt = ftell(df); 12425943Smckusic } 12435943Smckusic 12445943Smckusic dcvt(odp, ndp) 12455943Smckusic register struct odirect *odp; 12465943Smckusic register struct direct *ndp; 12475943Smckusic { 12486847Smckusick 12496846Smckusick blkclr((char *)ndp, (long)(sizeof *ndp)); 12505943Smckusic ndp->d_ino = odp->d_ino; 12515943Smckusic strncpy(ndp->d_name, odp->d_name, ODIRSIZ); 12525943Smckusic ndp->d_namlen = strlen(ndp->d_name); 12535943Smckusic ndp->d_reclen = DIRSIZ(ndp); 12545943Smckusic /* 12555943Smckusic * this quickly calculates if this inode is a directory. 12565943Smckusic * Currently not maintained. 12575943Smckusic * 12585943Smckusic for (itp = inotab[INOHASH(odp->d_ino)]; itp; itp = itp->t_next) { 12595943Smckusic if (itp->t_ino != odp->d_ino) 12605943Smckusic continue; 12615943Smckusic ndp->d_fmt = IFDIR; 12625943Smckusic break; 12635943Smckusic } 12645943Smckusic */ 12655943Smckusic } 12665943Smckusic 12675943Smckusic /* 12686289Smckusick * Open a directory. 12696289Smckusick * Modified to allow any random file to be a legal directory. 12706289Smckusick */ 12716289Smckusick DIR * 12726289Smckusick opendir(name) 12736289Smckusick char *name; 12746289Smckusick { 12756289Smckusick register DIR *dirp; 12766289Smckusick 12776289Smckusick dirp = (DIR *)malloc(sizeof(DIR)); 12786289Smckusick dirp->dd_fd = open(name, 0); 12796289Smckusick if (dirp->dd_fd == -1) { 12806846Smckusick free((char *)dirp); 12816289Smckusick return NULL; 12826289Smckusick } 12836289Smckusick dirp->dd_loc = 0; 12846289Smckusick return dirp; 12856289Smckusick } 12866289Smckusick 12876289Smckusick /* 12886289Smckusick * Seek to an entry in a directory. 12895943Smckusic * Only values returned by ``telldir'' should be passed to seekdir. 12905943Smckusic * Modified to have many directories based in one file. 12915943Smckusic */ 12925943Smckusic void 12935943Smckusic seekdir(dirp, loc, base) 12945943Smckusic register DIR *dirp; 12956846Smckusick daddr_t loc, base; 12965943Smckusic { 12976847Smckusick 12985943Smckusic if (loc == telldir(dirp)) 12995943Smckusic return; 13005943Smckusic loc -= base; 13015943Smckusic if (loc < 0) 13025943Smckusic fprintf(stderr, "bad seek pointer to seekdir %d\n", loc); 13036846Smckusick (void)lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0); 13045943Smckusic dirp->dd_loc = loc & (DIRBLKSIZ - 1); 13055943Smckusic if (dirp->dd_loc != 0) 13065943Smckusic dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); 13075943Smckusic } 13085943Smckusic 13095943Smckusic /* 13106844Smckusick * get next entry in a directory. 13114700Smckusic */ 13126844Smckusick struct direct * 13136844Smckusick readdir(dirp) 13146844Smckusick register DIR *dirp; 13154610Smckusick { 13166844Smckusick register struct direct *dp; 13174700Smckusic 13186844Smckusick for (;;) { 13196844Smckusick if (dirp->dd_loc == 0) { 13206844Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 13216844Smckusick DIRBLKSIZ); 13226844Smckusick if (dirp->dd_size <= 0) 13236844Smckusick return NULL; 13246844Smckusick } 13256844Smckusick if (dirp->dd_loc >= dirp->dd_size) { 13266844Smckusick dirp->dd_loc = 0; 13276844Smckusick continue; 13286844Smckusick } 13296844Smckusick dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); 13306844Smckusick if (dp->d_reclen <= 0 || 13316844Smckusick dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) 13326844Smckusick return NULL; 13336844Smckusick dirp->dd_loc += dp->d_reclen; 13346844Smckusick if (dp->d_ino == 0) 13356844Smckusick continue; 13366844Smckusick return (dp); 13375948Smckusic } 13384610Smckusick } 13394610Smckusick 13404843Smckusic allocinotab(ino, seekpt) 13414837Smckusic ino_t ino; 13424843Smckusic daddr_t seekpt; 13434610Smckusick { 13444837Smckusic register struct inotab *itp; 13454776Smckusic 13464837Smckusic itp = (struct inotab *)calloc(1, sizeof(struct inotab)); 13474837Smckusic itp->t_next = inotab[INOHASH(ino)]; 13484837Smckusic inotab[INOHASH(ino)] = itp; 13494837Smckusic itp->t_ino = ino; 13504843Smckusic itp->t_seekpt = seekpt; 13514610Smckusick } 13524610Smckusick 13534843Smckusic allocxtr(ino, name, flags) 13544837Smckusic ino_t ino; 13554843Smckusic char *name; 13564843Smckusic char flags; 13574610Smckusick { 13584843Smckusic register struct xtrlist *xp, *pxp; 13594776Smckusic 13604843Smckusic xp = (struct xtrlist *)calloc(1, sizeof(struct xtrlist) + strlen(name)); 13614837Smckusic xp->x_next = xtrlist[INOHASH(ino)]; 13624837Smckusic xtrlist[INOHASH(ino)] = xp; 13634837Smckusic xp->x_ino = ino; 13644843Smckusic strcpy(xp->x_name, name); 13654837Smckusic xtrcnt++; 13664843Smckusic xp->x_flags = flags; 13674843Smckusic for (pxp = xp->x_next; pxp; pxp = pxp->x_next) 13684843Smckusic if (pxp->x_ino == ino && (pxp->x_flags & XLINKED) == 0) { 13694843Smckusic xp->x_flags |= XLINKED; 13704843Smckusic xp->x_linkedto = pxp; 13714843Smckusic xtrcnt--; 13724843Smckusic break; 13734843Smckusic } 13744843Smckusic if (xp->x_flags & XLINKED) 13754843Smckusic fprintf(stdout, "%s: linked to %s\n", xp->x_name, pxp->x_name); 13764843Smckusic else if (xp->x_flags & XISDIR) 13774843Smckusic fprintf(stdout, "%s: directory inode %u\n", xp->x_name, ino); 13784843Smckusic else 13794843Smckusic fprintf(stdout, "%s: inode %u\n", xp->x_name, ino); 13804610Smckusick } 13814610Smckusick 13825038Smckusic done(exitcode) 13835038Smckusic int exitcode; 13844610Smckusick { 13856847Smckusick 13865038Smckusic unlink(dirfile); 13875038Smckusic exit(exitcode); 13884610Smckusick } 1389