14610Smckusick /* Copyright (c) 1981 Regents of the University of California */ 24610Smckusick 3*5327Smckusic char version[] = "@(#)main.c 1.8 01/05/82"; 44610Smckusick 54610Smckusick /* Modified to include h option (recursively extract all files within 64610Smckusick * a subtree) and m option (recreate the heirarchical structure of 74610Smckusick * that subtree and move extracted files to their proper homes). 84610Smckusick * 8/29/80 by Mike Litzkow 94610Smckusick * 104610Smckusick * Includes the s (skip files) option for use with multiple dumps on 114610Smckusick * a single tape. 124610Smckusick */ 134610Smckusick 144611Smckusic /* static char *sccsid = "@(#)restor.c 4.3 (Berkeley) 6/3/81"; */ 154610Smckusick 164610Smckusick #define MAXINO 3000 174610Smckusick #define BITS 8 184610Smckusick #define NCACHE 3 194610Smckusick #define SIZEINC 10 204610Smckusick 214610Smckusick #ifndef STANDALONE 224610Smckusick #include <stdio.h> 234610Smckusick #include <signal.h> 244610Smckusick #endif 254700Smckusic #include "../h/param.h" 264700Smckusic #include "../h/inode.h" 274700Smckusic #include "../h/fs.h" 284700Smckusic #include "../h/buf.h" 294700Smckusic #include "../h/dir.h" 304700Smckusic #include "../h/user.h" 314700Smckusic #include "../h/dumprestor.h" 325038Smckusic #include <sys/mtio.h> 334610Smckusick 345038Smckusic struct odirect { 355038Smckusic u_short d_ino; 365038Smckusic char d_name[DIRSIZ]; 375038Smckusic }; 385038Smckusic 39*5327Smckusic #define MWORD(m,i) (m[(unsigned)(i-1)/NBBY]) 40*5327Smckusic #define MBIT(i) (1<<((unsigned)(i-1)%NBBY)) 414610Smckusick #define BIS(i,w) (MWORD(w,i) |= MBIT(i)) 424610Smckusick #define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) 434610Smckusick #define BIT(i,w) (MWORD(w,i) & MBIT(i)) 444610Smckusick 454700Smckusic ino_t ino, maxi; 465038Smckusic struct inode *cur_ip; 474610Smckusick 485038Smckusic int eflag = 0, hflag = 0, mflag = 0, cvtdir = 0; 494776Smckusic 504700Smckusic char mounted = 0; 514700Smckusic dev_t dev = 0; 524610Smckusick char tapename[] = "/dev/rmt8"; 534610Smckusick char *magtape = tapename; 545038Smckusic int mt; 555038Smckusic int dumpnum = 1; 565038Smckusic int volno = 1; 575038Smckusic int curblk = 0; 585038Smckusic int bct = NTREC+1; 595038Smckusic char tbf[NTREC*TP_BSIZE]; 604610Smckusick 614610Smckusick #ifdef STANDALONE 624610Smckusick char mbuf[50]; 634610Smckusick #endif 644610Smckusick 654610Smckusick daddr_t seekpt; 664837Smckusic FILE *df; 674837Smckusic int ofile; 684610Smckusick char dirfile[] = "rstXXXXXX"; 694610Smckusick 704837Smckusic #define INOHASH(val) (val % MAXINO) 714837Smckusic struct inotab { 724837Smckusic struct inotab *t_next; 734610Smckusick ino_t t_ino; 744610Smckusick daddr_t t_seekpt; 754837Smckusic } *inotab[MAXINO]; 764610Smckusick 774837Smckusic #define XISDIR 1 784610Smckusick #define XTRACTD 2 794610Smckusick #define XINUSE 4 804837Smckusic #define XLINKED 8 814610Smckusick struct xtrlist { 824837Smckusic struct xtrlist *x_next; 834837Smckusic struct xtrlist *x_linkedto; 844843Smckusic time_t x_timep[2]; 854837Smckusic ino_t x_ino; 864837Smckusic char x_flags; 874843Smckusic char x_name[1]; 884843Smckusic /* actually longer */ 894837Smckusic } *xtrlist[MAXINO]; 904776Smckusic int xtrcnt = 0; 914610Smckusick 92*5327Smckusic #ifdef STANDALONE 93*5327Smckusic #define msiz 8192 94*5327Smckusic char dumpmap[msiz]; 95*5327Smckusic char clrimap[msiz]; 96*5327Smckusic #else 97*5327Smckusic int msiz; 98*5327Smckusic char *dumpmap; 99*5327Smckusic char *clrimap; 100*5327Smckusic #endif 1014610Smckusick 102*5327Smckusic char clearedbuf[MAXBSIZE]; 103*5327Smckusic 1044837Smckusic extern char *ctime(); 1054843Smckusic ino_t search(); 1064700Smckusic char **envp; 1074610Smckusick 1084700Smckusic main(argc, argv, arge) 1094700Smckusic int argc; 1104700Smckusic char *argv[]; 1114700Smckusic char **arge; 1124610Smckusick { 1134610Smckusick register char *cp; 1144610Smckusick char command; 1154700Smckusic int (*signal())(); 1164610Smckusick int done(); 1174610Smckusick 1184843Smckusic if (signal(SIGINT, done) == SIG_IGN) 1194843Smckusic signal(SIGINT, SIG_IGN); 1204843Smckusic if (signal(SIGTERM, done) == SIG_IGN) 1214843Smckusic signal(SIGTERM, SIG_IGN); 1224610Smckusick #ifndef STANDALONE 1234700Smckusic envp = arge; 1244700Smckusic mktmp(dirfile); 1254610Smckusick if (argc < 2) { 1264610Smckusick usage: 1274837Smckusic fprintf(stderr, "Usage: restor x[s|m|h|v] file file..., restor r|R filesys, or restor t\n"); 1284700Smckusic done(1); 1294610Smckusick } 1304610Smckusick argv++; 1314610Smckusick argc -= 2; 1324610Smckusick for (cp = *argv++; *cp; cp++) { 1334610Smckusick switch (*cp) { 1344610Smckusick case '-': 1354610Smckusick break; 1364610Smckusick case 'f': 1374610Smckusick magtape = *argv++; 1384610Smckusick argc--; 1394610Smckusick break; 1404610Smckusick /* s dumpnum (skip to) for multifile dump tapes */ 1414610Smckusick case 's': 1424610Smckusick dumpnum = atoi(*argv++); 1434610Smckusick if(dumpnum <= 0) { 1444700Smckusic fprintf(stderr, "Dump number must be a positive integer\n"); 1454700Smckusic done(1); 1464610Smckusick } 1474610Smckusick argc--; 1484610Smckusick break; 1494610Smckusick case 'h': 1504610Smckusick hflag++; 1514610Smckusick break; 1524610Smckusick case 'm': 1534610Smckusick mflag++; 1544610Smckusick break; 1554610Smckusick case 'r': 1564610Smckusick case 'R': 1574610Smckusick case 't': 1584610Smckusick case 'x': 1594610Smckusick command = *cp; 1604610Smckusick break; 1614610Smckusick default: 1624700Smckusic fprintf(stderr, "Bad key character %c\n", *cp); 1634610Smckusick goto usage; 1644610Smckusick } 1654610Smckusick } 1664610Smckusick if (command == 'x') { 1674837Smckusic df = fopen(dirfile, "w"); 1684837Smckusic if (df == 0) { 1694700Smckusic fprintf(stderr, "restor: %s - cannot create directory temporary\n", dirfile); 1704700Smckusic done(1); 1714610Smckusick } 1724700Smckusic xmount(envp); 1734700Smckusic mounted++; 1744610Smckusick } 1754610Smckusick doit(command, argc, argv); 1764700Smckusic done(0); 1774610Smckusick #else 1784610Smckusick magtape = "tape"; 1794610Smckusick doit('r', 1, 0); 1804610Smckusick #endif 1814610Smckusick } 1824610Smckusick 1834610Smckusick doit(command, argc, argv) 1844700Smckusic char command; 1854700Smckusic int argc; 1864700Smckusic char *argv[]; 1874610Smckusick { 1885038Smckusic struct mtop tcom; 1895038Smckusic 1904610Smckusick #ifndef STANDALONE 1914610Smckusick if ((mt = open(magtape, 0)) < 0) { 1924700Smckusic fprintf(stderr, "%s: cannot open tape\n", magtape); 1934700Smckusic done(1); 1944610Smckusick } 1954843Smckusic if (dumpnum != 1) { 1964610Smckusick tcom.mt_op = MTFSF; 1974610Smckusick tcom.mt_count = dumpnum -1; 1984843Smckusic if (ioctl(mt,MTIOCTOP,&tcom) < 0) 1994610Smckusick perror("ioctl MTFSF"); 2004610Smckusick } 2014610Smckusick #else 2024610Smckusick do { 2034700Smckusic fprintf(stderr, "Tape? "); 2044610Smckusick gets(mbuf); 2054610Smckusick mt = open(mbuf, 0); 2064610Smckusick } while (mt == -1); 2074610Smckusick magtape = mbuf; 2084610Smckusick #endif 209*5327Smckusic blkclr(clearedbuf, MAXBSIZE); 2104610Smckusick switch(command) { 2114610Smckusick #ifndef STANDALONE 2124610Smckusick case 't': 2134610Smckusick if (readhdr(&spcl) == 0) { 2144700Smckusic fprintf(stderr, "Tape is not a dump tape\n"); 2154700Smckusic done(1); 2164610Smckusick } 2174843Smckusic fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date)); 2184843Smckusic fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate)); 2194610Smckusick return; 2204610Smckusick case 'x': 2214837Smckusic extractfiles(argc, argv); 2224837Smckusic return; 223*5327Smckusic #endif 2244837Smckusic case 'r': 2254837Smckusic case 'R': 2264837Smckusic restorfiles(command, argv); 2274837Smckusic return; 2284837Smckusic } 2294837Smckusic } 2304837Smckusic 2314837Smckusic #ifndef STANDALONE 2324837Smckusic extractfiles(argc, argv) 2334837Smckusic int argc; 2344837Smckusic char **argv; 2354837Smckusic { 2364843Smckusic char *ststore(); 2374837Smckusic register struct xtrlist *xp; 2384837Smckusic struct xtrlist **xpp; 239*5327Smckusic struct fs *fs; 2404837Smckusic ino_t d; 2415038Smckusic int xtrfile(), xtrskip(), xtrcvtdir(), xtrcvtskip(), null(); 2424843Smckusic int mode; 2434843Smckusic char name[BUFSIZ + 1]; 2444837Smckusic 2454837Smckusic if (readhdr(&spcl) == 0) { 2464837Smckusic fprintf(stderr, "Tape is not a dump tape\n"); 2474837Smckusic done(1); 2484837Smckusic } 2494837Smckusic if (checkvol(&spcl, 1) == 0) { 2504837Smckusic fprintf(stderr, "Tape is not volume 1 of the dump\n"); 2514837Smckusic } 252*5327Smckusic fs = getfs(dev); 253*5327Smckusic msiz = roundup(howmany(fs->fs_ipg * fs->fs_ncg, NBBY), TP_BSIZE); 254*5327Smckusic clrimap = (char *)calloc(msiz, sizeof(char)); 255*5327Smckusic dumpmap = (char *)calloc(msiz, sizeof(char)); 2565038Smckusic pass1(1); /* This sets the various maps on the way by */ 2574843Smckusic while (argc--) { 2584837Smckusic if ((d = psearch(*argv)) == 0 || BIT(d,dumpmap) == 0) { 2594843Smckusic fprintf(stdout, "%s: not on tape\n", *argv++); 2604837Smckusic continue; 2614610Smckusick } 2624843Smckusic if (mflag) 2634843Smckusic checkdir(*argv); 2644837Smckusic if(hflag) 2654837Smckusic getleaves(d, *argv++); 2664843Smckusic else 2674843Smckusic allocxtr(d, *argv++, XINUSE); 2684837Smckusic } 2694843Smckusic if (dumpnum > 1) { 2705038Smckusic /* 2715038Smckusic * if this is a multi-dump tape we always start with 2725038Smckusic * volume 1, so as to avoid accidentally restoring 2735038Smckusic * from a different dump! 2745038Smckusic */ 2755038Smckusic resetmt(); 2765038Smckusic dumpnum = 1; 2775038Smckusic volno = 1; 2785038Smckusic readhdr(&spcl); 2795038Smckusic goto rbits; 2804837Smckusic } 2815038Smckusic newvol: 2825038Smckusic resetmt(); 2834610Smckusick getvol: 2845038Smckusic fprintf(stderr, "Mount desired tape volume; Specify volume #: "); 2854837Smckusic if (gets(tbf) == NULL) 2864837Smckusic return; 2874837Smckusic volno = atoi(tbf); 2884837Smckusic if (volno <= 0) { 2894837Smckusic fprintf(stderr, "Volume numbers are positive numerics\n"); 2904837Smckusic goto getvol; 2914837Smckusic } 2924837Smckusic if (readhdr(&spcl) == 0) { 2934837Smckusic fprintf(stderr, "tape is not dump tape\n"); 2944837Smckusic goto newvol; 2954837Smckusic } 2964837Smckusic if (checkvol(&spcl, volno) == 0) { 2974837Smckusic fprintf(stderr, "Wrong volume (%d)\n", spcl.c_volume); 2984837Smckusic goto newvol; 2994837Smckusic } 3004610Smckusick rbits: 3014837Smckusic while (gethead(&spcl) == 0) 3024837Smckusic ; 3034837Smckusic if (checktype(&spcl, TS_INODE) == 1) { 3044837Smckusic fprintf(stderr, "Can't find inode mask!\n"); 3054837Smckusic goto newvol; 3064837Smckusic } 3074837Smckusic if (checktype(&spcl, TS_BITS) == 0) 3084837Smckusic goto rbits; 3094837Smckusic readbits(dumpmap); 3104837Smckusic while (xtrcnt > 0) { 3114837Smckusic again: 3124837Smckusic if (ishead(&spcl) == 0) 3134837Smckusic while(gethead(&spcl) == 0) 3144837Smckusic ; 3154837Smckusic if (checktype(&spcl, TS_END) == 1) { 3164837Smckusic fprintf(stderr, "end of tape\n"); 3174837Smckusic break; 3184610Smckusick } 3194837Smckusic if (checktype(&spcl, TS_INODE) == 0) { 3204837Smckusic gethead(&spcl); 3214837Smckusic goto again; 3224610Smckusick } 3234837Smckusic d = spcl.c_inumber; 3244837Smckusic for (xp = xtrlist[INOHASH(d)]; xp; xp = xp->x_next) { 3254837Smckusic if (d != xp->x_ino) 3264837Smckusic continue; 3274837Smckusic if (xp->x_flags & XLINKED) 3284837Smckusic continue; 3294837Smckusic xp->x_timep[0] = spcl.c_dinode.di_atime; 3304837Smckusic xp->x_timep[1] = spcl.c_dinode.di_mtime; 3314837Smckusic mode = spcl.c_dinode.di_mode; 3324837Smckusic if (mflag) 3334843Smckusic strcpy(name, xp->x_name); 3344837Smckusic else 3354837Smckusic sprintf(name, "%u", xp->x_ino); 3364837Smckusic switch (mode & IFMT) { 3374837Smckusic default: 3384843Smckusic fprintf(stderr, "%s: unknown file type\n", name); 3394837Smckusic xp->x_flags |= XTRACTD; 3404837Smckusic xtrcnt--; 3414837Smckusic goto skipfile; 3424837Smckusic case IFCHR: 3434837Smckusic case IFBLK: 3444843Smckusic fprintf(stdout, "extract special file %s\n", name); 3454837Smckusic if (xmknod(name, mode, spcl.c_dinode.di_rdev)) { 3464837Smckusic fprintf(stderr, "%s: cannot create special file\n", name); 3474837Smckusic xp->x_flags |= XTRACTD; 3484837Smckusic xtrcnt--; 3494837Smckusic goto skipfile; 3504776Smckusic } 3514837Smckusic getfile(null, null, spcl.c_dinode.di_size); 3524837Smckusic break; 3534837Smckusic case IFDIR: 3544837Smckusic if (mflag) { 3554843Smckusic fprintf(stdout, "extract directory %s\n", name); 3564837Smckusic strncat(name, "/.", BUFSIZ); 3574843Smckusic checkdir(name); 3584843Smckusic xchown(xp->x_name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 3594837Smckusic getfile(null, null, spcl.c_dinode.di_size); 3604837Smckusic break; 3614610Smckusick } 3625038Smckusic fprintf(stdout, "extract file %s\n", name); 3635038Smckusic if ((ofile = xcreat(name, 0666)) < 0) { 3645038Smckusic fprintf(stderr, "%s: cannot create file\n", name); 3655038Smckusic xp->x_flags |= XTRACTD; 3665038Smckusic xtrcnt--; 3675038Smckusic goto skipfile; 3685038Smckusic } 3695038Smckusic xchown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 3705038Smckusic if (cvtdir) 3715038Smckusic getfile(xtrcvtdir, xtrcvtskip, 3725038Smckusic spcl.c_dinode.di_size); 3735038Smckusic else 3745038Smckusic getfile(xtrfile, xtrskip, 3755038Smckusic spcl.c_dinode.di_size); 3765038Smckusic xclose(ofile); 3775038Smckusic break; 3784837Smckusic case IFREG: 3794843Smckusic fprintf(stdout, "extract file %s\n", name); 3804837Smckusic if ((ofile = xcreat(name, 0666)) < 0) { 3814837Smckusic fprintf(stderr, "%s: cannot create file\n", name); 3824837Smckusic xp->x_flags |= XTRACTD; 3834837Smckusic xtrcnt--; 3844837Smckusic goto skipfile; 3854837Smckusic } 3864837Smckusic xchown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 3875038Smckusic getfile(xtrfile, xtrskip, spcl.c_dinode.di_size); 3884837Smckusic xclose(ofile); 3894837Smckusic break; 3904610Smckusick } 3914837Smckusic xchmod(name, mode); 3924837Smckusic xutime(name, xp->x_timep); 3934837Smckusic xp->x_flags |= XTRACTD; 3944837Smckusic xtrcnt--; 3954837Smckusic goto finished; 3964837Smckusic } 3974837Smckusic skipfile: 3984837Smckusic getfile(null, null, spcl.c_dinode.di_size); 3994700Smckusic finished: 4004837Smckusic ; 4014837Smckusic } 4024837Smckusic if (xtrcnt == 0 && !mflag) 4034837Smckusic return; 4044837Smckusic for (xpp = xtrlist; xpp < &xtrlist[MAXINO]; xpp++) { 4054837Smckusic for (xp = *xpp; xp; xp = xp->x_next) { 4064837Smckusic if (mflag && (xp->x_flags & XISDIR)) 4074837Smckusic xutime(xp->x_name, xp->x_timep); 4084837Smckusic if (xp->x_flags & XTRACTD) 4094837Smckusic continue; 4104837Smckusic if ((xp->x_flags & XLINKED) == 0) { 4114837Smckusic fprintf(stderr, "cannot find file %s\n", 4124837Smckusic xp->x_name); 4134837Smckusic continue; 4144837Smckusic } 4154843Smckusic if (!mflag) 4164843Smckusic continue; 4174843Smckusic fprintf(stdout, "link %s to %s\n", 4184843Smckusic xp->x_linkedto->x_name, xp->x_name); 4194843Smckusic if (xlink(xp->x_linkedto->x_name, xp->x_name) < 0) 4204843Smckusic fprintf(stderr, "link %s to %s failed\n", 4214837Smckusic xp->x_linkedto->x_name, xp->x_name); 4224610Smckusick } 4234837Smckusic } 4244837Smckusic } 4254610Smckusick #endif 4264837Smckusic 4274837Smckusic restorfiles(command, argv) 4284837Smckusic char command; 4294837Smckusic char **argv; 4304837Smckusic { 4315038Smckusic int rstrfile(), rstrskip(), rstrcvtdir(), rstrcvtskip(); 4324837Smckusic register struct dinode *dp; 4334837Smckusic register struct inode *ip; 4344837Smckusic struct fs *fs; 4355038Smckusic int mode, type; 4364837Smckusic char mount[BUFSIZ + 1]; 4374837Smckusic char *ptr[2]; 4384837Smckusic 4394837Smckusic mount[0] = '\0'; 4404837Smckusic strcpy(mount, "MOUNT="); 441*5327Smckusic #ifndef STANDALONE 4424837Smckusic strncat(mount, *argv, BUFSIZ); 443*5327Smckusic #else 444*5327Smckusic fprintf(stderr, "Disk? "); 445*5327Smckusic gets(&mount[6]); 446*5327Smckusic #endif 4474837Smckusic ptr[0] = mount; 4484837Smckusic ptr[1] = 0; 4494837Smckusic xmount(ptr); 450*5327Smckusic mounted++; 4514837Smckusic iput(u.u_cdir); /* release root inode */ 4524837Smckusic iput(u.u_rdir); /* release root inode */ 453*5327Smckusic fs = getfs(dev); 454*5327Smckusic maxi = fs->fs_ipg * fs->fs_ncg; 4554610Smckusick #ifndef STANDALONE 456*5327Smckusic msiz = roundup(howmany(maxi, NBBY), TP_BSIZE); 457*5327Smckusic clrimap = (char *)calloc(msiz, sizeof(char)); 458*5327Smckusic dumpmap = (char *)calloc(msiz, sizeof(char)); 4594837Smckusic if (command == 'R') { 4604837Smckusic fprintf(stderr, "Enter starting volume number: "); 4614837Smckusic if (gets(tbf) == EOF) { 4624837Smckusic volno = 1; 4634837Smckusic fprintf(stderr, "\n"); 4644610Smckusick } 4654610Smckusick else 4664837Smckusic volno = atoi(tbf); 4674837Smckusic } 4684837Smckusic else 4694610Smckusick #endif 4704837Smckusic volno = 1; 4714837Smckusic fprintf(stderr, "Last chance before scribbling on %s. ", 4724610Smckusick #ifdef STANDALONE 4734837Smckusic "disk"); 4744610Smckusick #else 4754837Smckusic *argv); 4764610Smckusick #endif 4774837Smckusic while (getchar() != '\n'); 4784837Smckusic if (readhdr(&spcl) == 0) { 4794837Smckusic fprintf(stderr, "Missing volume record\n"); 4804837Smckusic done(1); 4814837Smckusic } 4824837Smckusic if (checkvol(&spcl, volno) == 0) { 4834837Smckusic fprintf(stderr, "Tape is not volume %d\n", volno); 4844837Smckusic done(1); 4854837Smckusic } 4865038Smckusic pass1(0); 4875038Smckusic gethead(&spcl); /* volume header already checked above */ 4884837Smckusic gethead(&spcl); 4894837Smckusic for (;;) { 4904837Smckusic ragain: 4914837Smckusic if (ishead(&spcl) == 0) { 4924837Smckusic fprintf(stderr, "Missing header block\n"); 4934837Smckusic while (gethead(&spcl) == 0) 4944837Smckusic ; 4954837Smckusic eflag++; 4964610Smckusick } 4974837Smckusic if (checktype(&spcl, TS_END) == 1) { 4984837Smckusic fprintf(stderr, "End of tape\n"); 4994837Smckusic close(mt); 5004837Smckusic return; 5014610Smckusick } 5024837Smckusic if (checktype(&spcl, TS_CLRI) == 1) { 5034837Smckusic readbits(clrimap); 5044837Smckusic for (ino = 1; ino <= maxi; ino++) 5054837Smckusic if (BIT(ino, clrimap) == 0) { 5064837Smckusic if (!iexist(dev, ino)) 5074837Smckusic continue; 5084837Smckusic ip = iget(dev, ino); 5094837Smckusic if (ip == NULL) { 5104837Smckusic fprintf(stderr, "can't find inode %u\n", ino); 5114837Smckusic done(1); 5124610Smckusick } 5134837Smckusic ip->i_nlink = 0; 5144837Smckusic ip->i_flag |= ICHG; 5154837Smckusic iput(ip); 5164700Smckusic } 5174837Smckusic goto ragain; 5184837Smckusic } 5194837Smckusic if (checktype(&spcl, TS_BITS) == 1) { 5204837Smckusic readbits(dumpmap); 5214837Smckusic goto ragain; 5224837Smckusic } 5234837Smckusic if (checktype(&spcl, TS_INODE) == 0) { 5244837Smckusic fprintf(stderr, "Unknown header type\n"); 5254837Smckusic eflag++; 5264837Smckusic gethead(&spcl); 5274837Smckusic goto ragain; 5284837Smckusic } 5294837Smckusic ino = spcl.c_inumber; 5304837Smckusic if (eflag) 5314837Smckusic fprintf(stderr, "Resynced at inode %u\n", ino); 5324837Smckusic eflag = 0; 5334837Smckusic if (ino > maxi) { 5344837Smckusic fprintf(stderr, "%u: ilist too small\n", ino); 5354837Smckusic gethead(&spcl); 5364837Smckusic goto ragain; 5374837Smckusic } 5384837Smckusic if (iexist(dev, ino)) { 5394837Smckusic ip = iget(dev, ino); 5404837Smckusic if (ip == NULL) { 5414837Smckusic fprintf(stderr, "can't find inode %u\n", 5424837Smckusic ino); 5434700Smckusic done(1); 5444700Smckusic } 5454837Smckusic ip->i_nlink = 0; 5464700Smckusic ip->i_flag |= ICHG; 5474700Smckusic iput(ip); 5484610Smckusick } 5494837Smckusic dp = &spcl.c_dinode; 5504837Smckusic ip = ialloc(dev, ino, dp->di_mode); 5514837Smckusic if (ip == NULL || ip->i_number != ino) { 5524837Smckusic fprintf(stderr, "can't create inode %u\n", ino); 5534837Smckusic done(1); 5544837Smckusic } 5554837Smckusic ip->i_mode = mode = dp->di_mode; 5564837Smckusic ip->i_nlink = dp->di_nlink; 5574837Smckusic ip->i_uid = dp->di_uid; 5584837Smckusic ip->i_gid = dp->di_gid; 5594837Smckusic ip->i_atime = dp->di_atime; 5604837Smckusic ip->i_mtime = dp->di_mtime; 5614837Smckusic ip->i_ctime = dp->di_ctime; 5625038Smckusic type = ip->i_mode & IFMT; 5635038Smckusic if (type == IFCHR || type == IFBLK) 5644837Smckusic ip->i_rdev = dp->di_rdev; 5654837Smckusic ip->i_size = 0; 5664837Smckusic cur_ip = ip; 5674837Smckusic u.u_offset = 0; 5684837Smckusic u.u_segflg = 1; 5695038Smckusic if (cvtdir && type == IFDIR) 5705038Smckusic getfile(rstrcvtdir, rstrcvtskip, dp->di_size); 5715038Smckusic else 5725038Smckusic getfile(rstrfile, rstrskip, dp->di_size); 5734837Smckusic ip->i_mode = mode; 5744837Smckusic ip->i_flag &= ~(IUPD|IACC); 5754837Smckusic ip->i_flag |= ICHG; 5764837Smckusic iput(ip); 5774610Smckusick } 5784610Smckusick } 5794610Smckusick 5804610Smckusick /* 5814610Smckusick * Read the tape, bulding up a directory structure for extraction 5824610Smckusick * by name 5834610Smckusick */ 5844610Smckusick #ifndef STANDALONE 5855038Smckusic pass1(savedir) 5865038Smckusic int savedir; 5874610Smckusick { 5884776Smckusic register int i; 5894837Smckusic register struct dinode *ip; 5904837Smckusic struct direct nulldir; 5915038Smckusic char buf[TP_BSIZE]; 5925038Smckusic int putdir(), null(); 5934610Smckusick 5944837Smckusic nulldir.d_ino = 0; 5954837Smckusic strncpy(nulldir.d_name, "/", DIRSIZ); 5964610Smckusick while (gethead(&spcl) == 0) { 5974700Smckusic fprintf(stderr, "Can't find directory header!\n"); 5984610Smckusick } 5994610Smckusick for (;;) { 6004610Smckusick if (checktype(&spcl, TS_BITS) == 1) { 6014610Smckusick readbits(dumpmap); 6024610Smckusick continue; 6034610Smckusick } 6044610Smckusick if (checktype(&spcl, TS_CLRI) == 1) { 6054610Smckusick readbits(clrimap); 6064610Smckusick continue; 6074610Smckusick } 6084610Smckusick if (checktype(&spcl, TS_INODE) == 0) { 6094610Smckusick finish: 6105038Smckusic if (savedir) 6115038Smckusic freopen(dirfile, "r", df); 6125038Smckusic resetmt(); 6134610Smckusick return; 6144610Smckusick } 6154610Smckusick ip = &spcl.c_dinode; 6164610Smckusick i = ip->di_mode & IFMT; 6174610Smckusick if (i != IFDIR) { 6184610Smckusick goto finish; 6194610Smckusick } 6205038Smckusic if (spcl.c_inumber == ROOTINO) { 6215038Smckusic readtape(buf); 6225038Smckusic bct--; /* push back this block */ 6235038Smckusic if (((struct direct *)buf)->d_ino != ROOTINO) { 6245038Smckusic if (((struct odirect *)buf)->d_ino != ROOTINO) { 6255038Smckusic fprintf(stderr, "bad root directory\n"); 6265038Smckusic done(1); 6275038Smckusic } 6285038Smckusic fprintf(stderr, "converting to new directory format\n"); 6295038Smckusic cvtdir = 1; 6305038Smckusic } 6315038Smckusic if (!savedir && !cvtdir) { 6325038Smckusic /* if no conversion, just return */ 6335038Smckusic goto finish; 6345038Smckusic } 6355038Smckusic } 6364843Smckusic allocinotab(spcl.c_inumber, seekpt); 6375038Smckusic if (savedir) { 6385038Smckusic getfile(putdir, null, spcl.c_dinode.di_size); 6395038Smckusic putent(&nulldir); 6405038Smckusic } else { 6415038Smckusic getfile(null, null, spcl.c_dinode.di_size); 6425038Smckusic } 6434610Smckusick } 6444610Smckusick } 6454610Smckusick #endif 6464610Smckusick 6474610Smckusick /* 6484843Smckusic * Put the directory entries in the directory file 6494843Smckusic */ 6504843Smckusic #ifndef STANDALONE 6514843Smckusic putdir(buf, size) 6524843Smckusic char *buf; 6534843Smckusic int size; 6544843Smckusic { 6555038Smckusic struct direct cvtbuf; 6565038Smckusic register struct odirect *odp; 6575038Smckusic struct odirect *eodp; 6584843Smckusic register struct direct *dp; 6595038Smckusic struct direct *edp; 6604843Smckusic 6615038Smckusic if (cvtdir) { 6625038Smckusic eodp = (struct odirect *)&buf[size]; 6635038Smckusic for (odp = (struct odirect *)buf; odp < eodp; odp++) 6645038Smckusic if (odp->d_ino != 0) { 6655038Smckusic dcvt(odp, &cvtbuf); 6665038Smckusic putent(&cvtbuf); 6675038Smckusic } 6685038Smckusic } else { 6695038Smckusic edp = (struct direct *)&buf[size]; 6705038Smckusic for (dp = (struct direct *)buf; dp < edp; dp++) 6715038Smckusic if (dp->d_ino != 0) 6725038Smckusic putent(dp); 6735038Smckusic } 6744843Smckusic } 6754843Smckusic 6764843Smckusic putent(dp) 6774843Smckusic struct direct *dp; 6784843Smckusic { 6794843Smckusic fwrite(dp, 1, sizeof(struct direct), df); 6804843Smckusic seekpt = ftell(df); 6814843Smckusic } 6824843Smckusic 6835038Smckusic dcvt(odp, ndp) 6845038Smckusic register struct odirect *odp; 6855038Smckusic register struct direct *ndp; 6865038Smckusic { 6875038Smckusic register struct inotab *itp; 6885038Smckusic 6895038Smckusic blkclr(ndp, sizeof *ndp); 6905038Smckusic ndp->d_ino = odp->d_ino; 6915038Smckusic strncpy(ndp->d_name, odp->d_name, DIRSIZ); 6925038Smckusic for (itp = inotab[INOHASH(odp->d_ino)]; itp; itp = itp->t_next) { 6935038Smckusic if (itp->t_ino != odp->d_ino) 6945038Smckusic continue; 6955038Smckusic ndp->d_mode = IFDIR; 6965038Smckusic break; 6975038Smckusic } 6985038Smckusic } 6995038Smckusic 7004843Smckusic /* 7014843Smckusic * Recursively find names and inumbers of all files in subtree 7024843Smckusic * pname and put them in xtrlist[] 7034843Smckusic */ 7044843Smckusic getleaves(ino, pname) 7054843Smckusic ino_t ino; 7064843Smckusic char *pname; 7074843Smckusic { 7084843Smckusic register struct inotab *itp; 7094843Smckusic int namelen; 7104843Smckusic daddr_t bpt; 7114843Smckusic struct direct dir; 7124843Smckusic char locname[BUFSIZ + 1]; 7134843Smckusic 7144843Smckusic if (BIT(ino, dumpmap) == 0) { 7154843Smckusic fprintf(stdout, "%s: not on the tape\n", pname); 7164843Smckusic return; 7174843Smckusic } 7184843Smckusic for (itp = inotab[INOHASH(ino)]; itp; itp = itp->t_next) { 7194843Smckusic if (itp->t_ino != ino) 7204843Smckusic continue; 7214843Smckusic /* 7224843Smckusic * pname is a directory name 7234843Smckusic */ 7244843Smckusic allocxtr(ino, pname, XISDIR); 7254843Smckusic /* 7264843Smckusic * begin search through the directory 7274843Smckusic * skipping over "." and ".." 7284843Smckusic */ 7294843Smckusic strncpy(locname, pname, BUFSIZ); 7304843Smckusic strncat(locname, "/", BUFSIZ); 7314843Smckusic namelen = strlen(locname); 7324843Smckusic fseek(df, itp->t_seekpt, 0); 7334843Smckusic fread(&dir, 1, sizeof(struct direct), df); 7344843Smckusic fread(&dir, 1, sizeof(struct direct), df); 7354843Smckusic fread(&dir, 1, sizeof(struct direct), df); 7364843Smckusic bpt = ftell(df); 7374843Smckusic /* 7384843Smckusic * "/" signals end of directory 7394843Smckusic */ 7404843Smckusic while (strncmp(dir.d_name, "/", DIRSIZ)) { 7414843Smckusic locname[namelen] = '\0'; 7424843Smckusic strncat(locname, dir.d_name, DIRSIZ); 7434843Smckusic if (strlen(locname) >= BUFSIZ) { 7444843Smckusic fprintf(stderr, "%s: name exceedes %d char\n", 7454843Smckusic locname, BUFSIZ); 7464843Smckusic continue; 7474843Smckusic } 7484843Smckusic getleaves(dir.d_ino, locname); 7494843Smckusic fseek(df, bpt, 0); 7504843Smckusic fread(&dir, 1, sizeof(struct direct), df); 7514843Smckusic bpt = ftell(df); 7524843Smckusic } 7534843Smckusic return; 7544843Smckusic } 7554843Smckusic /* 7564843Smckusic * locname is name of a simple file 7574843Smckusic */ 7584843Smckusic allocxtr(ino, pname, XINUSE); 7594843Smckusic } 7604843Smckusic 7614843Smckusic /* 7624843Smckusic * Search the directory tree rooted at inode ROOTINO 7634843Smckusic * for the path pointed at by n 7644843Smckusic */ 7654843Smckusic psearch(n) 7664843Smckusic char *n; 7674843Smckusic { 7684843Smckusic register char *cp, *cp1; 7694843Smckusic char c; 7704843Smckusic 7714843Smckusic ino = ROOTINO; 7724843Smckusic if (*(cp = n) == '/') 7734843Smckusic cp++; 7744843Smckusic next: 7754843Smckusic cp1 = cp + 1; 7764843Smckusic while (*cp1 != '/' && *cp1) 7774843Smckusic cp1++; 7784843Smckusic c = *cp1; 7794843Smckusic *cp1 = 0; 7804843Smckusic ino = search(ino, cp); 7814843Smckusic if (ino == 0) { 7824843Smckusic *cp1 = c; 7834843Smckusic return(0); 7844843Smckusic } 7854843Smckusic *cp1 = c; 7864843Smckusic if (c == '/') { 7874843Smckusic cp = cp1+1; 7884843Smckusic goto next; 7894843Smckusic } 7904843Smckusic return(ino); 7914843Smckusic } 7924843Smckusic 7934843Smckusic /* 7944843Smckusic * search the directory inode ino 7954843Smckusic * looking for entry cp 7964843Smckusic */ 7974843Smckusic ino_t 7984843Smckusic search(inum, cp) 7994843Smckusic ino_t inum; 8004843Smckusic char *cp; 8014843Smckusic { 8024843Smckusic struct direct dir; 8034843Smckusic register struct inotab *itp; 8044843Smckusic 8054843Smckusic for (itp = inotab[INOHASH(inum)]; itp; itp = itp->t_next) 8064843Smckusic if (itp->t_ino == inum) 8074843Smckusic goto found; 8084843Smckusic return(0); 8094843Smckusic found: 8104843Smckusic fseek(df, itp->t_seekpt, 0); 8114843Smckusic do { 8124843Smckusic fread(&dir, 1, sizeof(struct direct), df); 8134843Smckusic if (!strncmp(dir.d_name, "/", DIRSIZ)) 8144843Smckusic return(0); 8154843Smckusic } while (strncmp(dir.d_name, cp, DIRSIZ)); 8164843Smckusic return(dir.d_ino); 8174843Smckusic } 8184843Smckusic #endif 8194843Smckusic 8204843Smckusic /* 8214610Smckusick * Do the file extraction, calling the supplied functions 8224610Smckusick * with the blocks 8234610Smckusick */ 8244700Smckusic getfile(f1, f2, size) 8254700Smckusic int (*f2)(), (*f1)(); 8264700Smckusic long size; 8274610Smckusick { 8284776Smckusic register int i; 829*5327Smckusic char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; 8304837Smckusic union u_spcl addrblk; 831*5327Smckusic register struct fs *fs; 8324837Smckusic # define addrblock addrblk.s_spcl 8334610Smckusick 8344837Smckusic addrblock = spcl; 835*5327Smckusic fs = getfs(dev); 8364610Smckusick for (;;) { 8374837Smckusic for (i = 0; i < addrblock.c_count; i++) { 8384837Smckusic if (addrblock.c_addr[i]) { 8394776Smckusic readtape(&buf[curblk++][0]); 840*5327Smckusic if (curblk == BLKING(fs) * fs->fs_frag) { 8414776Smckusic (*f1)(buf, size > TP_BSIZE ? 842*5327Smckusic (long) (BLKING(fs) * fs->fs_frag * TP_BSIZE) : 8434776Smckusic (curblk - 1) * TP_BSIZE + size); 8444776Smckusic curblk = 0; 8454776Smckusic } 846*5327Smckusic } else { 8474776Smckusic if (curblk > 0) { 8484776Smckusic (*f1)(buf, size > TP_BSIZE ? 8494776Smckusic (long) (curblk * TP_BSIZE) : 8504776Smckusic (curblk - 1) * TP_BSIZE + size); 8514776Smckusic curblk = 0; 8524776Smckusic } 853*5327Smckusic (*f2)(clearedbuf, size > TP_BSIZE ? 854*5327Smckusic (long) TP_BSIZE : size); 8554610Smckusick } 8564776Smckusic if ((size -= TP_BSIZE) <= 0) { 8574610Smckusick eloop: 8584610Smckusick while (gethead(&spcl) == 0) 8594610Smckusick ; 8604610Smckusick if (checktype(&spcl, TS_ADDR) == 1) 8614610Smckusick goto eloop; 8624776Smckusic goto out; 8634610Smckusick } 8644610Smckusick } 8654837Smckusic if (gethead(&addrblock) == 0) { 8664776Smckusic fprintf(stderr, "Missing address (header) block, ino%u\n", ino); 8674700Smckusic goto eloop; 8684700Smckusic } 8694837Smckusic if (checktype(&addrblock, TS_ADDR) == 0) { 8704837Smckusic spcl = addrblock; 8714776Smckusic goto out; 8724700Smckusic } 8734610Smckusick } 8744776Smckusic out: 8754776Smckusic if (curblk > 0) { 8764776Smckusic (*f1)(buf, (curblk * TP_BSIZE) + size); 8774776Smckusic curblk = 0; 8784776Smckusic } 8794610Smckusick } 8804610Smckusick 8814610Smckusick /* 8824843Smckusic * The next routines are called during file extraction to 8834843Smckusic * put the data into the right form and place. 8844843Smckusic */ 8854843Smckusic #ifndef STANDALONE 8864843Smckusic xtrfile(buf, size) 8874843Smckusic char *buf; 8884843Smckusic long size; 8894843Smckusic { 8904843Smckusic if (xwrite(ofile, buf, (int) size) == -1) { 8915038Smckusic perror("extract write"); 8924843Smckusic done(1); 8934843Smckusic } 8944843Smckusic } 8954843Smckusic 8965038Smckusic xtrskip(buf, size) 8974843Smckusic char *buf; 8984843Smckusic long size; 8994843Smckusic { 9004843Smckusic if (xseek(ofile, size, 1) == -1) { 9015038Smckusic perror("extract seek"); 9024843Smckusic done(1); 9034843Smckusic } 9044843Smckusic } 9055038Smckusic 9065038Smckusic xtrcvtdir(buf, size) 9075038Smckusic struct odirect *buf; 9085038Smckusic long size; 9095038Smckusic { 910*5327Smckusic struct direct 911*5327Smckusic cvtbuf[MAXBSIZE / sizeof(struct odirect)]; 9125038Smckusic struct odirect *odp, *edp; 9135038Smckusic struct direct *dp; 9145038Smckusic 9155038Smckusic edp = &buf[size / sizeof(struct odirect)]; 9165038Smckusic for (odp = buf, dp = cvtbuf; odp < edp; odp++, dp++) 9175038Smckusic dcvt(odp, dp); 9185038Smckusic size = size * sizeof(struct direct) / sizeof(struct odirect); 9195038Smckusic if (xwrite(ofile, cvtbuf, (int) size) == -1) { 9205038Smckusic perror("extract write"); 9215038Smckusic done(1); 9225038Smckusic } 9235038Smckusic } 9245038Smckusic 9255038Smckusic xtrcvtskip(buf, size) 9265038Smckusic char *buf; 9275038Smckusic long size; 9285038Smckusic { 9295038Smckusic fprintf(stderr, "unallocated block in directory\n"); 9305038Smckusic if (xseek(ofile, size, 1) == -1) { 9315038Smckusic perror("extract seek"); 9325038Smckusic done(1); 9335038Smckusic } 9345038Smckusic } 9354843Smckusic #endif 9364843Smckusic 9374843Smckusic rstrfile(buf, size) 9384843Smckusic char *buf; 9394843Smckusic long size; 9404843Smckusic { 9414843Smckusic u.u_base = buf; 9424843Smckusic u.u_count = size; 9434843Smckusic writei(cur_ip); 9444843Smckusic if (u.u_error) { 9455038Smckusic perror("restor write"); 9464843Smckusic done(1); 9474843Smckusic } 9484843Smckusic } 9494843Smckusic 9504843Smckusic rstrskip(buf, size) 9514843Smckusic char *buf; 9524843Smckusic long size; 9534843Smckusic { 9544843Smckusic u.u_offset += size; 9554843Smckusic } 9564843Smckusic 9575038Smckusic rstrcvtdir(buf, size) 9585038Smckusic struct odirect *buf; 9595038Smckusic long size; 9605038Smckusic { 961*5327Smckusic struct direct 962*5327Smckusic cvtbuf[MAXBSIZE / sizeof(struct odirect)]; 9635038Smckusic struct odirect *odp, *edp; 9645038Smckusic struct direct *dp; 9655038Smckusic 9665038Smckusic edp = &buf[size / sizeof(struct odirect)]; 9675038Smckusic for (odp = buf, dp = cvtbuf; odp < edp; odp++, dp++) 9685038Smckusic dcvt(odp, dp); 9695038Smckusic u.u_base = (char *)cvtbuf; 9705038Smckusic u.u_count = size * sizeof(struct direct) / sizeof(struct odirect); 9715038Smckusic writei(cur_ip); 9725038Smckusic if (u.u_error) { 9735038Smckusic perror("restor write"); 9745038Smckusic done(1); 9755038Smckusic } 9765038Smckusic } 9775038Smckusic 9785038Smckusic rstrcvtskip(buf, size) 9795038Smckusic char *buf; 9805038Smckusic long size; 9815038Smckusic { 9825038Smckusic fprintf(stderr, "unallocated block in directory\n"); 9835038Smckusic u.u_offset += size; 9845038Smckusic } 9855038Smckusic 9864843Smckusic null() {;} 9874843Smckusic 9884843Smckusic /* 9894776Smckusic * Do the tape i/o, dealing with volume changes 9904610Smckusick * etc.. 9914610Smckusick */ 9924610Smckusick readtape(b) 9934700Smckusic char *b; 9944610Smckusick { 9954776Smckusic register int i; 9964837Smckusic struct s_spcl tmpbuf; 9974610Smckusick 9984610Smckusick if (bct >= NTREC) { 9994610Smckusick for (i = 0; i < NTREC; i++) 10004776Smckusic ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0; 10014610Smckusick bct = 0; 10024776Smckusic if ((i = read(mt, tbf, NTREC*TP_BSIZE)) < 0) { 10034700Smckusic perror("Tape read error"); 10044610Smckusick eflag++; 10054700Smckusic done(1); 10064610Smckusick } 10074610Smckusick if (i == 0) { 10084610Smckusick bct = NTREC + 1; 10094610Smckusick volno++; 10104610Smckusick loop: 10114610Smckusick flsht(); 10124610Smckusick close(mt); 10134700Smckusic fprintf(stderr, "Mount volume %d\n", volno); 10144610Smckusick while (getchar() != '\n') 10154610Smckusick ; 10164610Smckusick if ((mt = open(magtape, 0)) == -1) { 10174700Smckusic fprintf(stderr, "Cannot open tape!\n"); 10184610Smckusick goto loop; 10194610Smckusick } 10204610Smckusick if (readhdr(&tmpbuf) == 0) { 10214700Smckusic fprintf(stderr, "Not a dump tape.Try again\n"); 10224610Smckusick goto loop; 10234610Smckusick } 10244610Smckusick if (checkvol(&tmpbuf, volno) == 0) { 10254700Smckusic fprintf(stderr, "Wrong tape. Try again\n"); 10264610Smckusick goto loop; 10274610Smckusick } 10284610Smckusick readtape(b); 10294610Smckusick return; 10304610Smckusick } 10314610Smckusick } 10324776Smckusic copy(&tbf[(bct++*TP_BSIZE)], b, TP_BSIZE); 10334610Smckusick } 10344610Smckusick 10354610Smckusick flsht() 10364610Smckusick { 10374610Smckusick bct = NTREC+1; 10384610Smckusick } 10394610Smckusick 10404610Smckusick copy(f, t, s) 10414700Smckusic register char *f, *t; 10424610Smckusick { 10434776Smckusic register int i; 10444610Smckusick 10454610Smckusick i = s; 10464610Smckusick do 10474610Smckusick *t++ = *f++; 10484610Smckusick while (--i); 10494610Smckusick } 10504610Smckusick 10515038Smckusic blkclr(buf, size) 10525038Smckusic char *buf; 10535038Smckusic int size; 10545038Smckusic { 10555038Smckusic asm("movc5 $0,(r0),$0,8(ap),*4(ap)"); 10565038Smckusic } 10575038Smckusic 10585038Smckusic resetmt() 10595038Smckusic { 10605038Smckusic struct mtop tcom; 10615038Smckusic 10625038Smckusic if(dumpnum > 1) 10635038Smckusic tcom.mt_op = MTBSF; 10645038Smckusic else 10655038Smckusic tcom.mt_op = MTREW; 10665038Smckusic tcom.mt_count = 1; 10675038Smckusic flsht(); 10685038Smckusic if (ioctl(mt,MTIOCTOP,&tcom) == -1) { 10695038Smckusic /* kludge for disk dumps */ 10705038Smckusic lseek(mt, (long)0, 0); 10715038Smckusic } 10725038Smckusic if (dumpnum > 1) { 10735038Smckusic tcom.mt_op = MTFSF; 10745038Smckusic tcom.mt_count = 1; 10755038Smckusic ioctl(mt,MTIOCTOP,&tcom); 10765038Smckusic } 10775038Smckusic } 10785038Smckusic 10794843Smckusic checkvol(b, t) 10804843Smckusic struct s_spcl *b; 10814843Smckusic int t; 10824610Smckusick { 10834843Smckusic if (b->c_volume == t) 10844843Smckusic return(1); 10854610Smckusick return(0); 10864610Smckusick } 10874610Smckusick 10884843Smckusic readhdr(b) 10894843Smckusic struct s_spcl *b; 10904610Smckusick { 10914843Smckusic if (gethead(b) == 0) 10924610Smckusick return(0); 10934843Smckusic if (checktype(b, TS_TAPE) == 0) 10944843Smckusic return(0); 10954843Smckusic return(1); 10964610Smckusick } 10974610Smckusick 10984610Smckusick /* 10994610Smckusick * read the tape into buf, then return whether or 11004610Smckusick * or not it is a header block. 11014610Smckusick */ 11024610Smckusick gethead(buf) 11034837Smckusic struct s_spcl *buf; 11044610Smckusick { 11054610Smckusick readtape((char *)buf); 11064837Smckusic if (buf->c_magic != MAGIC || checksum((int *)buf) == 0) 11074610Smckusick return(0); 11084610Smckusick return(1); 11094610Smckusick } 11104610Smckusick 11114610Smckusick /* 11124610Smckusick * return whether or not the buffer contains a header block 11134610Smckusick */ 11144610Smckusick ishead(buf) 11154837Smckusic struct s_spcl *buf; 11164610Smckusick { 11174837Smckusic if (buf->c_magic != MAGIC || checksum((int *)buf) == 0) 11184610Smckusick return(0); 11194610Smckusick return(1); 11204610Smckusick } 11214610Smckusick 11224610Smckusick checktype(b, t) 11234837Smckusic struct s_spcl *b; 11244700Smckusic int t; 11254610Smckusick { 11264837Smckusic return(b->c_type == t); 11274610Smckusick } 11284610Smckusick 11295038Smckusic /* 11305038Smckusic * read a bit mask from the tape into m. 11315038Smckusic */ 11325038Smckusic readbits(m) 1133*5327Smckusic char *m; 11345038Smckusic { 11355038Smckusic register int i; 11364610Smckusick 11375038Smckusic i = spcl.c_count; 11385038Smckusic 11395038Smckusic while (i--) { 11405038Smckusic readtape((char *) m); 1141*5327Smckusic m += (TP_BSIZE/(NBBY/BITS)); 11425038Smckusic } 11435038Smckusic while (gethead(&spcl) == 0) 11445038Smckusic ; 11455038Smckusic } 11465038Smckusic 11474610Smckusick checksum(b) 11484700Smckusic int *b; 11494610Smckusick { 11504776Smckusic register int i, j; 11514610Smckusick 11524776Smckusic j = sizeof(union u_spcl) / sizeof(int); 11534610Smckusick i = 0; 11544610Smckusick do 11554610Smckusick i += *b++; 11564610Smckusick while (--j); 11574610Smckusick if (i != CHECKSUM) { 11584776Smckusic fprintf(stderr, "Checksum error %o, ino %u\n", i, ino); 11594610Smckusick return(0); 11604610Smckusick } 11614610Smckusick return(1); 11624610Smckusick } 11634610Smckusick 11644610Smckusick /* 11655038Smckusic * Check for access into each directory in the pathname of an extracted 11665038Smckusic * file and create such a directory if needed in preparation for moving 11675038Smckusic * the file to its proper home. 11685038Smckusic */ 11695038Smckusic checkdir(name) 11705038Smckusic register char *name; 11715038Smckusic { 11725038Smckusic register char *cp; 11735038Smckusic int i; 11745038Smckusic 11755038Smckusic for (cp = name; *cp; cp++) { 11765038Smckusic if (*cp == '/') { 11775038Smckusic *cp = '\0'; 11785038Smckusic if (xaccess(name, 01) < 0) { 11795038Smckusic register int pid, rp; 11805038Smckusic 11815038Smckusic xumount(); 11825038Smckusic if ((pid = fork()) == 0) { 11835038Smckusic execl("/bin/xmkdir", "xmkdir", name, 0); 11845038Smckusic execl("/usr/bin/xmkdir", "xmkdir", name, 0); 11855038Smckusic execl("./xmkdir", "xmkdir", name, 0); 11865038Smckusic fprintf(stderr, "xrestor: cannot find xmkdir!\n"); 11875038Smckusic done(0); 11885038Smckusic } 11895038Smckusic while ((rp = wait(&i)) >= 0 && rp != pid) 11905038Smckusic ; 11915038Smckusic xmount(envp); 11925038Smckusic } 11935038Smckusic *cp = '/'; 11945038Smckusic } 11955038Smckusic } 11965038Smckusic } 11975038Smckusic 11985038Smckusic /* 11994700Smckusic * tell whether an inode is allocated 12004700Smckusic * this is drawn from ialloccg in sys/alloc.c 12014700Smckusic */ 12024700Smckusic iexist(dev, ino) 12034700Smckusic dev_t dev; 12044700Smckusic ino_t ino; 12054610Smckusick { 12064700Smckusic register struct fs *fs; 12074700Smckusic register struct cg *cgp; 12084700Smckusic register struct buf *bp; 12094700Smckusic int cg; 12104700Smckusic 12114700Smckusic fs = getfs(dev); 12124700Smckusic if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg) 12134700Smckusic return (0); 12144700Smckusic cg = itog(ino, fs); 1215*5327Smckusic bp = bread(dev, fsbtodb(fs, cgtod(cg, fs)), fs->fs_bsize); 12164700Smckusic if (bp->b_flags & B_ERROR) 12174700Smckusic return(0); 12184700Smckusic cgp = bp->b_un.b_cg; 12194700Smckusic ino %= fs->fs_ipg; 12204700Smckusic if (isclr(cgp->cg_iused, ino)) { 12214700Smckusic brelse(bp); 12224700Smckusic return(0); 12234700Smckusic } 12244700Smckusic brelse(bp); 12254700Smckusic return (1); 12264610Smckusick } 12274610Smckusick 12284843Smckusic allocinotab(ino, seekpt) 12294837Smckusic ino_t ino; 12304843Smckusic daddr_t seekpt; 12314610Smckusick { 12324837Smckusic register struct inotab *itp; 12334776Smckusic 12344837Smckusic itp = (struct inotab *)calloc(1, sizeof(struct inotab)); 12354837Smckusic itp->t_next = inotab[INOHASH(ino)]; 12364837Smckusic inotab[INOHASH(ino)] = itp; 12374837Smckusic itp->t_ino = ino; 12384843Smckusic itp->t_seekpt = seekpt; 12394610Smckusick } 12404610Smckusick 12414843Smckusic allocxtr(ino, name, flags) 12424837Smckusic ino_t ino; 12434843Smckusic char *name; 12444843Smckusic char flags; 12454610Smckusick { 12464843Smckusic register struct xtrlist *xp, *pxp; 12474776Smckusic 12484843Smckusic xp = (struct xtrlist *)calloc(1, sizeof(struct xtrlist) + strlen(name)); 12494837Smckusic xp->x_next = xtrlist[INOHASH(ino)]; 12504837Smckusic xtrlist[INOHASH(ino)] = xp; 12514837Smckusic xp->x_ino = ino; 12524843Smckusic strcpy(xp->x_name, name); 12534837Smckusic xtrcnt++; 12544843Smckusic xp->x_flags = flags; 12554843Smckusic for (pxp = xp->x_next; pxp; pxp = pxp->x_next) 12564843Smckusic if (pxp->x_ino == ino && (pxp->x_flags & XLINKED) == 0) { 12574843Smckusic xp->x_flags |= XLINKED; 12584843Smckusic xp->x_linkedto = pxp; 12594843Smckusic xtrcnt--; 12604843Smckusic break; 12614843Smckusic } 12624843Smckusic if (xp->x_flags & XLINKED) 12634843Smckusic fprintf(stdout, "%s: linked to %s\n", xp->x_name, pxp->x_name); 12644843Smckusic else if (xp->x_flags & XISDIR) 12654843Smckusic fprintf(stdout, "%s: directory inode %u\n", xp->x_name, ino); 12664843Smckusic else 12674843Smckusic fprintf(stdout, "%s: inode %u\n", xp->x_name, ino); 12684610Smckusick } 12694610Smckusick 12705038Smckusic done(exitcode) 12715038Smckusic int exitcode; 12724610Smckusick { 12735038Smckusic #ifndef STANDALONE 12745038Smckusic unlink(dirfile); 12755038Smckusic #endif 12765038Smckusic if (mounted) 12775038Smckusic xumount(); 12785038Smckusic exit(exitcode); 12794610Smckusick } 1280