16847Smckusick /* Copyright (c) 1982 Regents of the University of California */ 24610Smckusick 36846Smckusick #ifndef lint 4*10202Smckusick char version[] = "@(#)main.c 2.17 01/08/83"; 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 #include <sys/param.h> 286847Smckusick #include <sys/inode.h> 296847Smckusick #include <sys/fs.h> 306847Smckusick #include <dir.h> 316847Smckusick #include <stat.h> 326847Smckusick #include <dumprestor.h> 338296Smckusick #include <sys/ioctl.h> 345038Smckusic #include <sys/mtio.h> 354610Smckusick 365943Smckusic #define ODIRSIZ 14 375038Smckusic struct odirect { 385038Smckusic u_short d_ino; 395943Smckusic char d_name[ODIRSIZ]; 405038Smckusic }; 415038Smckusic 425327Smckusic #define MWORD(m,i) (m[(unsigned)(i-1)/NBBY]) 435327Smckusic #define MBIT(i) (1<<((unsigned)(i-1)%NBBY)) 444610Smckusick #define BIS(i,w) (MWORD(w,i) |= MBIT(i)) 454610Smckusick #define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) 464610Smckusick #define BIT(i,w) (MWORD(w,i) & MBIT(i)) 474610Smckusick 486846Smckusick ino_t ino; 494610Smckusick 50*10202Smckusick int eflag = 0, hflag = 1, mflag = 1, tflag = 0, vflag = 0, yflag = 0; 51*10202Smckusick int cvtflag = 0; 52*10202Smckusick #define vprintf if (vflag) fprintf 534776Smckusic 546844Smckusick long fssize; 554610Smckusick char tapename[] = "/dev/rmt8"; 564610Smckusick char *magtape = tapename; 575038Smckusic int mt; 585038Smckusic int dumpnum = 1; 595038Smckusic int volno = 1; 605038Smckusic int curblk = 0; 615038Smckusic int bct = NTREC+1; 625038Smckusic char tbf[NTREC*TP_BSIZE]; 634610Smckusick 644610Smckusick daddr_t seekpt; 654837Smckusic FILE *df; 665943Smckusic DIR *dirp; 674837Smckusic int ofile; 688485Smckusick char dirfile[] = "/tmp/rstaXXXXXX"; 696289Smckusick char lnkbuf[MAXPATHLEN + 1]; 706289Smckusick int pathlen; 714610Smckusick 724837Smckusic #define INOHASH(val) (val % MAXINO) 734837Smckusic struct inotab { 744837Smckusic struct inotab *t_next; 754610Smckusick ino_t t_ino; 764610Smckusick daddr_t t_seekpt; 77*10202Smckusick time_t t_timep[2]; 784837Smckusic } *inotab[MAXINO]; 798485Smckusick int maxino = 0; 804610Smckusick 814837Smckusic #define XISDIR 1 824610Smckusick #define XTRACTD 2 834610Smckusick #define XINUSE 4 844837Smckusic #define XLINKED 8 854610Smckusick struct xtrlist { 864837Smckusic struct xtrlist *x_next; 874837Smckusic struct xtrlist *x_linkedto; 884837Smckusic ino_t x_ino; 894837Smckusic char x_flags; 904843Smckusic char x_name[1]; 914843Smckusic /* actually longer */ 924837Smckusic } *xtrlist[MAXINO]; 934776Smckusic int xtrcnt = 0; 948505Smckusick struct xtrlist *entry; 958505Smckusick struct xtrlist *unknown; 968505Smckusick struct xtrlist *allocxtr(); 974610Smckusick 985327Smckusic char *dumpmap; 995327Smckusic char *clrimap; 1004610Smckusick 1015327Smckusic char clearedbuf[MAXBSIZE]; 1025327Smckusic 1034837Smckusic extern char *ctime(); 1046846Smckusick extern int seek(); 1054843Smckusic ino_t search(); 1065943Smckusic int dirwrite(); 1076849Smckusick #ifdef RRESTOR 1086849Smckusick char *host; 1096849Smckusick #endif 1104610Smckusick 1116846Smckusick main(argc, argv) 1124700Smckusic int argc; 1134700Smckusic char *argv[]; 1144610Smckusick { 1154610Smckusick register char *cp; 1164610Smckusick char command; 1174700Smckusic int (*signal())(); 1184610Smckusick int done(); 1194610Smckusick 1204843Smckusic if (signal(SIGINT, done) == SIG_IGN) 1214843Smckusic signal(SIGINT, SIG_IGN); 1224843Smckusic if (signal(SIGTERM, done) == SIG_IGN) 1234843Smckusic signal(SIGTERM, SIG_IGN); 1246844Smckusick mktemp(dirfile); 1254610Smckusick if (argc < 2) { 1264610Smckusick usage: 127*10202Smckusick fprintf(stderr, "Usage: restor xfhmsvy file file... or restor tf\n"); 1284700Smckusic done(1); 1294610Smckusick } 1304610Smckusick argv++; 1314610Smckusick argc -= 2; 132*10202Smckusick command = '\0'; 1334610Smckusick for (cp = *argv++; *cp; cp++) { 1344610Smckusick switch (*cp) { 1354610Smckusick case '-': 1364610Smckusick break; 1378302Smckusick case 'c': 1388302Smckusick cvtflag++; 1398302Smckusick break; 1404610Smckusick case 'f': 1414610Smckusick magtape = *argv++; 1426849Smckusick #ifdef RRESTOR 1436849Smckusick { char *index(); 1446849Smckusick host = magtape; 1456849Smckusick magtape = index(host, ':'); 1466849Smckusick if (magtape == 0) { 1476849Smckusick nohost: 1486849Smckusick msg("need keyletter ``f'' and device ``host:tape''"); 1496849Smckusick done(1); 1506849Smckusick } 1516849Smckusick *magtape++ = 0; 1526849Smckusick if (rmthost(host) == 0) 1536849Smckusick done(1); 1546849Smckusick } 1556849Smckusick #endif 1564610Smckusick argc--; 1574610Smckusick break; 1584610Smckusick /* s dumpnum (skip to) for multifile dump tapes */ 1594610Smckusick case 's': 1604610Smckusick dumpnum = atoi(*argv++); 1616847Smckusick if (dumpnum <= 0) { 1624700Smckusic fprintf(stderr, "Dump number must be a positive integer\n"); 1634700Smckusic done(1); 1644610Smckusick } 1654610Smckusick argc--; 1664610Smckusick break; 1674610Smckusick case 'h': 168*10202Smckusick hflag = 0; 1694610Smckusick break; 1704610Smckusick case 'm': 171*10202Smckusick mflag = 0; 1724610Smckusick break; 1738374Smckusick case 'x': 174*10202Smckusick if (command != '\0') { 175*10202Smckusick fprintf(stderr, "x and t are exclusive\n"); 176*10202Smckusick goto usage; 177*10202Smckusick } 178*10202Smckusick command = 'x'; 179*10202Smckusick break; 1808374Smckusick case 'v': 1818374Smckusick vflag++; 1828374Smckusick break; 1838374Smckusick case 'y': 1848374Smckusick yflag++; 1858374Smckusick break; 1864610Smckusick case 't': 187*10202Smckusick if (command != '\0') { 188*10202Smckusick fprintf(stderr, "x and t are exclusive\n"); 189*10202Smckusick goto usage; 190*10202Smckusick } 191*10202Smckusick command = 't'; 192*10202Smckusick tflag++; 193*10202Smckusick vflag++; 1944610Smckusick break; 1954610Smckusick default: 1964700Smckusic fprintf(stderr, "Bad key character %c\n", *cp); 1974610Smckusick goto usage; 1984610Smckusick } 1994610Smckusick } 200*10202Smckusick if (command == '\0') { 201*10202Smckusick fprintf(stderr, "must specify x or t\n"); 202*10202Smckusick goto usage; 203*10202Smckusick } 2046849Smckusick #ifdef RRESTOR 2056849Smckusick if (host == 0) 2066849Smckusick goto nohost; 2076849Smckusick #endif 2089405Smckusick setuid(getuid()); /* no longer need or want root privileges */ 2094610Smckusick doit(command, argc, argv); 2104700Smckusic done(0); 2114610Smckusick } 2124610Smckusick 2134610Smckusick doit(command, argc, argv) 2144700Smckusic char command; 2154700Smckusic int argc; 2164700Smckusic char *argv[]; 2174610Smckusick { 2185038Smckusic struct mtop tcom; 219*10202Smckusick char *ststore(); 220*10202Smckusick register struct inotab *itp; 221*10202Smckusick register struct xtrlist *xp; 222*10202Smckusick struct xtrlist **xpp; 223*10202Smckusick ino_t d; 224*10202Smckusick int xtrfile(), xtrskip(), xtrcvtdir(), xtrcvtskip(), 225*10202Smckusick xtrlnkfile(), xtrlnkskip(), null(); 226*10202Smckusick int mode, uid, gid, i; 227*10202Smckusick struct stat stbuf; 228*10202Smckusick time_t timep[2]; 229*10202Smckusick char name[BUFSIZ + 1]; 2305038Smckusic 231*10202Smckusick if (argc == 0) { 232*10202Smckusick argc++; 233*10202Smckusick *--argv = "."; 234*10202Smckusick } 2356849Smckusick #ifdef RRESTOR 2366849Smckusick if ((mt = rmtopen(magtape, 0)) < 0) { 2376849Smckusick #else 2384610Smckusick if ((mt = open(magtape, 0)) < 0) { 2396849Smckusick #endif 2404700Smckusic fprintf(stderr, "%s: cannot open tape\n", magtape); 2414700Smckusic done(1); 2424610Smckusick } 2434843Smckusic if (dumpnum != 1) { 2444610Smckusick tcom.mt_op = MTFSF; 2454610Smckusick tcom.mt_count = dumpnum -1; 2466849Smckusick #ifdef RRESTOR 2476849Smckusick rmtioctl(MTFSF,dumpnum - 1); 2486849Smckusick #else 2494843Smckusic if (ioctl(mt,MTIOCTOP,&tcom) < 0) 2504610Smckusick perror("ioctl MTFSF"); 2516849Smckusick #endif 2524610Smckusick } 253*10202Smckusick bzero(clearedbuf, (long)MAXBSIZE); 2548369Smckusick if (readhdr(&spcl) == 0) { 2558369Smckusick bct--; /* push back this block */ 2568369Smckusick cvtflag++; 2574610Smckusick if (readhdr(&spcl) == 0) { 2584700Smckusic fprintf(stderr, "Tape is not a dump tape\n"); 2594700Smckusic done(1); 2604610Smckusick } 2618369Smckusick fprintf(stderr, "Converting to new file system format.\n"); 2628369Smckusick } 263*10202Smckusick if (vflag) { 2644843Smckusic fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date)); 2654843Smckusic fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate)); 2664837Smckusic } 267*10202Smckusick df = fopen(dirfile, "w"); 268*10202Smckusick if (df == 0) { 269*10202Smckusick fprintf(stderr, 270*10202Smckusick "restor: %s - cannot create directory temporary\n", 271*10202Smckusick dirfile); 272*10202Smckusick done(1); 273*10202Smckusick } 2746844Smckusick if (stat(".", &stbuf) < 0) { 2756844Smckusick fprintf(stderr, "cannot stat .\n"); 2766844Smckusick done(1); 2776844Smckusick } 2786844Smckusick fssize = stbuf.st_blksize; 2798485Smckusick if (fssize <= 0 || ((fssize - 1) & fssize) != 0) { 2808485Smckusick fprintf(stderr, "bad block size %d\n", fssize); 2818485Smckusick done(1); 2828485Smckusick } 2834837Smckusic if (checkvol(&spcl, 1) == 0) { 2844837Smckusic fprintf(stderr, "Tape is not volume 1 of the dump\n"); 2854837Smckusic } 2866844Smckusick clrimap = 0; 2876844Smckusick dumpmap = 0; 2888505Smckusick unknown = allocxtr(0, "name unknown - not extracted", 0); 289*10202Smckusick pass1(); /* This sets the various maps on the way by */ 2904843Smckusic while (argc--) { 2914837Smckusic if ((d = psearch(*argv)) == 0 || BIT(d,dumpmap) == 0) { 2928374Smckusick fprintf(stderr, "%s: not on tape\n", *argv++); 2934837Smckusic continue; 2944610Smckusick } 295*10202Smckusick if (mflag && !tflag) 2964843Smckusic checkdir(*argv); 2976847Smckusick if (hflag) 2984837Smckusic getleaves(d, *argv++); 2994843Smckusic else 3008505Smckusick (void)allocxtr(d, *argv++, XINUSE); 3014837Smckusic } 3024843Smckusic if (dumpnum > 1) { 3035038Smckusic /* 3045038Smckusic * if this is a multi-dump tape we always start with 3055038Smckusic * volume 1, so as to avoid accidentally restoring 3065038Smckusic * from a different dump! 3075038Smckusic */ 3085038Smckusic resetmt(); 3095038Smckusic dumpnum = 1; 3105038Smckusic volno = 1; 3115038Smckusic readhdr(&spcl); 3125038Smckusic goto rbits; 3134837Smckusic } 3145038Smckusic newvol: 3156849Smckusick #ifdef RRESTOR 3166849Smckusick rmtclose(); 3176849Smckusick #else 3186847Smckusick close(mt); 3196849Smckusick #endif 320*10202Smckusick if (tflag) 321*10202Smckusick return; 3224610Smckusick getvol: 3235038Smckusic fprintf(stderr, "Mount desired tape volume; Specify volume #: "); 3244837Smckusic if (gets(tbf) == NULL) 3254837Smckusic return; 3264837Smckusic volno = atoi(tbf); 3274837Smckusic if (volno <= 0) { 3284837Smckusic fprintf(stderr, "Volume numbers are positive numerics\n"); 3294837Smckusic goto getvol; 3304837Smckusic } 3316849Smckusick #ifdef RRESTOR 3326849Smckusick if ((mt = rmtopen(magtape, 0)) == -1) { 3336849Smckusick #else 3346847Smckusick if ((mt = open(magtape, 0)) == -1) { 3356849Smckusick #endif 3366847Smckusick fprintf(stderr, "Cannot open tape!\n"); 3376847Smckusick goto getvol; 3386847Smckusick } 3396847Smckusick if (dumpnum > 1) 3406847Smckusick resetmt(); 3414837Smckusic if (readhdr(&spcl) == 0) { 3424837Smckusic fprintf(stderr, "tape is not dump tape\n"); 3434837Smckusic goto newvol; 3444837Smckusic } 3454837Smckusic if (checkvol(&spcl, volno) == 0) { 3464837Smckusic fprintf(stderr, "Wrong volume (%d)\n", spcl.c_volume); 3474837Smckusic goto newvol; 3484837Smckusic } 3494610Smckusick rbits: 3504837Smckusic while (gethead(&spcl) == 0) 3514837Smckusic ; 3524837Smckusic if (checktype(&spcl, TS_INODE) == 1) { 3534837Smckusic fprintf(stderr, "Can't find inode mask!\n"); 3544837Smckusic goto newvol; 3554837Smckusic } 3564837Smckusic if (checktype(&spcl, TS_BITS) == 0) 3574837Smckusic goto rbits; 3586844Smckusick readbits(&dumpmap); 3594837Smckusic while (xtrcnt > 0) { 3604837Smckusic again: 3616845Smckusick if (ishead(&spcl) == 0) { 3626845Smckusick i = 0; 3636847Smckusick while (gethead(&spcl) == 0) 3646845Smckusick i++; 3658485Smckusick fprintf(stderr, "resync restor, skipped %d blocks\n", 3666845Smckusick i); 3676845Smckusick } 3684837Smckusic if (checktype(&spcl, TS_END) == 1) { 3694837Smckusic fprintf(stderr, "end of tape\n"); 3704837Smckusic break; 3714610Smckusick } 3724837Smckusic if (checktype(&spcl, TS_INODE) == 0) { 3734837Smckusic gethead(&spcl); 3744837Smckusic goto again; 3754610Smckusick } 3764837Smckusic d = spcl.c_inumber; 3778505Smckusick entry = unknown; 3788505Smckusick entry->x_ino = d; 3798505Smckusick for (xp = xtrlist[INOHASH(d)]; xp; xp = xp->x_next) { 3808505Smckusick if (d != xp->x_ino || (xp->x_flags & XLINKED)) 3818505Smckusick continue; 3828505Smckusick entry = xp; 383*10202Smckusick timep[0] = spcl.c_dinode.di_atime; 384*10202Smckusick timep[1] = spcl.c_dinode.di_mtime; 3854837Smckusic mode = spcl.c_dinode.di_mode; 3864837Smckusic if (mflag) 3874843Smckusic strcpy(name, xp->x_name); 3884837Smckusic else 3894837Smckusic sprintf(name, "%u", xp->x_ino); 3904837Smckusic switch (mode & IFMT) { 3914837Smckusic default: 3926847Smckusick fprintf(stderr, "%s: unknown file mode 0%o\n", 3936847Smckusick name, mode); 3948505Smckusick xp->x_flags |= XTRACTD; 3954837Smckusic xtrcnt--; 3964837Smckusic goto skipfile; 3974837Smckusic case IFCHR: 3984837Smckusic case IFBLK: 399*10202Smckusick vprintf(stdout, "extract special file %s\n", name); 4006844Smckusick if (mknod(name, mode, spcl.c_dinode.di_rdev)) { 4014837Smckusic fprintf(stderr, "%s: cannot create special file\n", name); 4028505Smckusick xp->x_flags |= XTRACTD; 4034837Smckusic xtrcnt--; 4044837Smckusic goto skipfile; 4054776Smckusic } 4064837Smckusic getfile(null, null, spcl.c_dinode.di_size); 4074837Smckusic break; 4084837Smckusic case IFDIR: 4094837Smckusic if (mflag) { 410*10202Smckusick for (itp = inotab[INOHASH(d)]; 411*10202Smckusick itp; itp = itp->t_next) { 412*10202Smckusick if (itp->t_ino != d) 413*10202Smckusick continue; 414*10202Smckusick itp->t_timep[0] = timep[0]; 415*10202Smckusick itp->t_timep[1] = timep[1]; 416*10202Smckusick break; 417*10202Smckusick } 418*10202Smckusick if (itp == 0) 419*10202Smckusick fprintf(stderr, "missing directory entry\n"); 420*10202Smckusick vprintf(stdout, "extract directory %s\n", name); 4214837Smckusic strncat(name, "/.", BUFSIZ); 4224843Smckusic checkdir(name); 4236844Smckusick chown(xp->x_name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 4244837Smckusic getfile(null, null, spcl.c_dinode.di_size); 4254837Smckusic break; 4264610Smckusick } 427*10202Smckusick vprintf(stdout, "extract file %s\n", name); 4286844Smckusick if ((ofile = creat(name, 0666)) < 0) { 4295038Smckusic fprintf(stderr, "%s: cannot create file\n", name); 4308505Smckusick xp->x_flags |= XTRACTD; 4315038Smckusic xtrcnt--; 4325038Smckusic goto skipfile; 4335038Smckusic } 4346844Smckusick chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 435*10202Smckusick if (cvtflag) { 4365038Smckusic getfile(xtrcvtdir, xtrcvtskip, 4375038Smckusic spcl.c_dinode.di_size); 4385943Smckusic flushent(xtrfile); 4395943Smckusic } else 4405038Smckusic getfile(xtrfile, xtrskip, 4415038Smckusic spcl.c_dinode.di_size); 4426844Smckusick close(ofile); 4435038Smckusic break; 4446289Smckusick case IFLNK: 4459402Ssam /* 4469402Ssam * Some early dump tapes have symbolic links 4479402Ssam * present without the associated data blocks. 4489402Ssam * This hack avoids trashing a file system with 4499402Ssam * inodes with missing data blocks. 4509402Ssam */ 4519402Ssam if (spcl.c_count == 0) { 452*10202Smckusick vprintf(stdout, "%s: 0 length symbolic link (ignored)\n", name); 4539402Ssam xp->x_flags |= XTRACTD; 4549402Ssam xtrcnt--; 4559402Ssam goto skipfile; 4569402Ssam } 457*10202Smckusick vprintf(stdout, "extract symbolic link %s\n", name); 4586289Smckusick uid = spcl.c_dinode.di_uid; 4596289Smckusick gid = spcl.c_dinode.di_gid; 4606289Smckusick lnkbuf[0] = '\0'; 4616289Smckusick pathlen = 0; 4626289Smckusick getfile(xtrlnkfile, xtrlnkskip, spcl.c_dinode.di_size); 4636844Smckusick if (symlink(lnkbuf, name) < 0) { 4646289Smckusick fprintf(stderr, "%s: cannot create symbolic link\n", name); 4658505Smckusick xp->x_flags |= XTRACTD; 4666289Smckusick xtrcnt--; 4676289Smckusick goto finished; 4686289Smckusick } 4696844Smckusick chown(name, uid, gid); 4706289Smckusick break; 4714837Smckusic case IFREG: 472*10202Smckusick vprintf(stdout, "extract file %s\n", name); 4736844Smckusick if ((ofile = creat(name, 0666)) < 0) { 4744837Smckusic fprintf(stderr, "%s: cannot create file\n", name); 4758505Smckusick xp->x_flags |= XTRACTD; 4764837Smckusic xtrcnt--; 4774837Smckusic goto skipfile; 4784837Smckusic } 4796844Smckusick chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid); 4805038Smckusic getfile(xtrfile, xtrskip, spcl.c_dinode.di_size); 4816844Smckusick close(ofile); 4824837Smckusic break; 4834610Smckusick } 4846844Smckusick chmod(name, mode); 485*10202Smckusick utime(name, timep); 4868505Smckusick xp->x_flags |= XTRACTD; 4874837Smckusic xtrcnt--; 4884837Smckusic goto finished; 4894837Smckusic } 4904837Smckusic skipfile: 4914837Smckusic getfile(null, null, spcl.c_dinode.di_size); 4924700Smckusic finished: 4934837Smckusic ; 4944837Smckusic } 4954837Smckusic if (xtrcnt == 0 && !mflag) 4964837Smckusic return; 4974837Smckusic for (xpp = xtrlist; xpp < &xtrlist[MAXINO]; xpp++) { 4984837Smckusic for (xp = *xpp; xp; xp = xp->x_next) { 499*10202Smckusick if (mflag && (xp->x_flags & XISDIR)) { 500*10202Smckusick for (itp = inotab[INOHASH(xp->x_ino)]; 501*10202Smckusick itp; itp = itp->t_next) { 502*10202Smckusick if (itp->t_ino != xp->x_ino) 503*10202Smckusick continue; 504*10202Smckusick utime(xp->x_name, itp->t_timep); 505*10202Smckusick break; 506*10202Smckusick } 507*10202Smckusick if (itp == 0) 508*10202Smckusick fprintf(stderr, "missing dir entry\n"); 509*10202Smckusick } 5104837Smckusic if (xp->x_flags & XTRACTD) 5114837Smckusic continue; 5124837Smckusic if ((xp->x_flags & XLINKED) == 0) { 5134837Smckusic fprintf(stderr, "cannot find file %s\n", 5144837Smckusic xp->x_name); 5154837Smckusic continue; 5164837Smckusic } 5174843Smckusic if (!mflag) 5184843Smckusic continue; 519*10202Smckusick vprintf(stdout, "link %s to %s\n", 5208374Smckusick xp->x_linkedto->x_name, xp->x_name); 5216844Smckusick if (link(xp->x_linkedto->x_name, xp->x_name) < 0) 5224843Smckusic fprintf(stderr, "link %s to %s failed\n", 5234837Smckusic xp->x_linkedto->x_name, xp->x_name); 5244610Smckusick } 5254837Smckusic } 5264837Smckusic } 5274837Smckusic 5284610Smckusick /* 5294610Smckusick * Read the tape, bulding up a directory structure for extraction 5304610Smckusick * by name 5314610Smckusick */ 532*10202Smckusick pass1() 5334610Smckusick { 5344776Smckusic register int i; 5354837Smckusic register struct dinode *ip; 5364837Smckusic struct direct nulldir; 5375038Smckusic char buf[TP_BSIZE]; 5385943Smckusic int putdir(), null(), dirwrite(); 5394610Smckusick 5405943Smckusic nulldir.d_ino = 1; 5415943Smckusic nulldir.d_namlen = 1; 5425943Smckusic strncpy(nulldir.d_name, "/", nulldir.d_namlen); 5435943Smckusic nulldir.d_reclen = DIRSIZ(&nulldir); 5444610Smckusick while (gethead(&spcl) == 0) { 5454700Smckusic fprintf(stderr, "Can't find directory header!\n"); 5464610Smckusick } 5474610Smckusick for (;;) { 5484610Smckusick if (checktype(&spcl, TS_BITS) == 1) { 5496844Smckusick readbits(&dumpmap); 5504610Smckusick continue; 5514610Smckusick } 5524610Smckusick if (checktype(&spcl, TS_CLRI) == 1) { 5536844Smckusick readbits(&clrimap); 5544610Smckusick continue; 5554610Smckusick } 5564610Smckusick if (checktype(&spcl, TS_INODE) == 0) { 5574610Smckusick finish: 558*10202Smckusick fclose(df); 559*10202Smckusick dirp = opendir(dirfile); 560*10202Smckusick if (dirp == NULL) 561*10202Smckusick perror("opendir"); 5625038Smckusic resetmt(); 5634610Smckusick return; 5644610Smckusick } 5654610Smckusick ip = &spcl.c_dinode; 5664610Smckusick i = ip->di_mode & IFMT; 5674610Smckusick if (i != IFDIR) { 5684610Smckusick goto finish; 5694610Smckusick } 5704843Smckusic allocinotab(spcl.c_inumber, seekpt); 571*10202Smckusick getfile(putdir, null, spcl.c_dinode.di_size); 572*10202Smckusick putent(&nulldir, dirwrite); 573*10202Smckusick flushent(dirwrite); 5744610Smckusick } 5754610Smckusick } 5764610Smckusick 5774610Smckusick /* 5784843Smckusic * Put the directory entries in the directory file 5794843Smckusic */ 5804843Smckusic putdir(buf, size) 5814843Smckusic char *buf; 5824843Smckusic int size; 5834843Smckusic { 5845038Smckusic struct direct cvtbuf; 5855038Smckusic register struct odirect *odp; 5865038Smckusic struct odirect *eodp; 5874843Smckusic register struct direct *dp; 5886289Smckusick long loc, i; 5894843Smckusic 590*10202Smckusick if (cvtflag) { 5915038Smckusic eodp = (struct odirect *)&buf[size]; 5925038Smckusic for (odp = (struct odirect *)buf; odp < eodp; odp++) 5935038Smckusic if (odp->d_ino != 0) { 5945038Smckusic dcvt(odp, &cvtbuf); 5955943Smckusic putent(&cvtbuf, dirwrite); 5965038Smckusic } 5975038Smckusic } else { 5985943Smckusic for (loc = 0; loc < size; ) { 5995943Smckusic dp = (struct direct *)(buf + loc); 6006289Smckusick i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); 6016289Smckusick if (dp->d_reclen <= 0 || dp->d_reclen > i) { 6026289Smckusick loc += i; 6036289Smckusick continue; 6046289Smckusick } 6056289Smckusick loc += dp->d_reclen; 6066847Smckusick if (dp->d_ino != 0) { 6075943Smckusic putent(dp, dirwrite); 6086847Smckusick } 6095943Smckusic } 6105038Smckusic } 6114843Smckusic } 6124843Smckusic 6134843Smckusic /* 6144843Smckusic * Recursively find names and inumbers of all files in subtree 6154843Smckusic * pname and put them in xtrlist[] 6164843Smckusic */ 6174843Smckusic getleaves(ino, pname) 6184843Smckusic ino_t ino; 6194843Smckusic char *pname; 6204843Smckusic { 6214843Smckusic register struct inotab *itp; 6224843Smckusic int namelen; 6236846Smckusick daddr_t bpt; 6245943Smckusic register struct direct *dp; 6255943Smckusic char locname[BUFSIZ + 1]; 6264843Smckusic 6274843Smckusic if (BIT(ino, dumpmap) == 0) { 628*10202Smckusick vprintf(stdout, "%s: not on the tape\n", pname); 6294843Smckusic return; 6304843Smckusic } 6314843Smckusic for (itp = inotab[INOHASH(ino)]; itp; itp = itp->t_next) { 6324843Smckusic if (itp->t_ino != ino) 6334843Smckusic continue; 6344843Smckusic /* 6354843Smckusic * pname is a directory name 6364843Smckusic */ 6378505Smckusick (void)allocxtr(ino, pname, XISDIR); 6384843Smckusic /* 6394843Smckusic * begin search through the directory 6404843Smckusic * skipping over "." and ".." 6414843Smckusic */ 6424843Smckusic strncpy(locname, pname, BUFSIZ); 6434843Smckusic strncat(locname, "/", BUFSIZ); 6444843Smckusic namelen = strlen(locname); 6455943Smckusic seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 6465943Smckusic dp = readdir(dirp); 6475943Smckusic dp = readdir(dirp); 6485943Smckusic dp = readdir(dirp); 6495943Smckusic bpt = telldir(dirp); 6504843Smckusic /* 6514843Smckusic * "/" signals end of directory 6524843Smckusic */ 653*10202Smckusick while (dp != NULL && 654*10202Smckusick !(dp->d_namlen == 1 && dp->d_name[0] == '/')) { 6554843Smckusic locname[namelen] = '\0'; 6565943Smckusic if (namelen + dp->d_namlen >= BUFSIZ) { 657*10202Smckusick fprintf(stderr, "%s%s: name exceeds %d char\n", 6585943Smckusic locname, dp->d_name, BUFSIZ); 659*10202Smckusick } else { 660*10202Smckusick strncat(locname, dp->d_name, dp->d_namlen); 661*10202Smckusick getleaves(dp->d_ino, locname); 662*10202Smckusick seekdir(dirp, bpt, itp->t_seekpt); 6634843Smckusic } 6645943Smckusic dp = readdir(dirp); 6655943Smckusic bpt = telldir(dirp); 6664843Smckusic } 6674843Smckusic return; 6684843Smckusic } 6694843Smckusic /* 6704843Smckusic * locname is name of a simple file 6714843Smckusic */ 6728505Smckusick (void)allocxtr(ino, pname, XINUSE); 6734843Smckusic } 6744843Smckusic 6754843Smckusic /* 6764843Smckusic * Search the directory tree rooted at inode ROOTINO 6774843Smckusic * for the path pointed at by n 6784843Smckusic */ 6794843Smckusic psearch(n) 6804843Smckusic char *n; 6814843Smckusic { 6824843Smckusic register char *cp, *cp1; 6834843Smckusic char c; 6844843Smckusic 6854843Smckusic ino = ROOTINO; 6864843Smckusic if (*(cp = n) == '/') 6874843Smckusic cp++; 6884843Smckusic next: 6894843Smckusic cp1 = cp + 1; 6904843Smckusic while (*cp1 != '/' && *cp1) 6914843Smckusic cp1++; 6924843Smckusic c = *cp1; 6934843Smckusic *cp1 = 0; 6944843Smckusic ino = search(ino, cp); 6954843Smckusic if (ino == 0) { 6964843Smckusic *cp1 = c; 6974843Smckusic return(0); 6984843Smckusic } 6994843Smckusic *cp1 = c; 7004843Smckusic if (c == '/') { 7014843Smckusic cp = cp1+1; 7024843Smckusic goto next; 7034843Smckusic } 7044843Smckusic return(ino); 7054843Smckusic } 7064843Smckusic 7074843Smckusic /* 7084843Smckusic * search the directory inode ino 7094843Smckusic * looking for entry cp 7104843Smckusic */ 7114843Smckusic ino_t 7124843Smckusic search(inum, cp) 7134843Smckusic ino_t inum; 7144843Smckusic char *cp; 7154843Smckusic { 7165943Smckusic register struct direct *dp; 7174843Smckusic register struct inotab *itp; 7185943Smckusic int len; 7194843Smckusic 7204843Smckusic for (itp = inotab[INOHASH(inum)]; itp; itp = itp->t_next) 7214843Smckusic if (itp->t_ino == inum) 7224843Smckusic goto found; 7234843Smckusic return(0); 7244843Smckusic found: 7255943Smckusic seekdir(dirp, itp->t_seekpt, itp->t_seekpt); 7265943Smckusic len = strlen(cp); 7274843Smckusic do { 7285943Smckusic dp = readdir(dirp); 7295943Smckusic if (dp->d_namlen == 1 && dp->d_name[0] == '/') 7304843Smckusic return(0); 7315943Smckusic } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len)); 7325943Smckusic return(dp->d_ino); 7334843Smckusic } 7344843Smckusic 7354843Smckusic /* 7364610Smckusick * Do the file extraction, calling the supplied functions 7374610Smckusick * with the blocks 7384610Smckusick */ 7394700Smckusic getfile(f1, f2, size) 7404700Smckusic int (*f2)(), (*f1)(); 7416846Smckusick off_t size; 7424610Smckusick { 7434776Smckusic register int i; 7445327Smckusic char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; 7454837Smckusic union u_spcl addrblk; 7464837Smckusic # define addrblock addrblk.s_spcl 7474610Smckusick 7484837Smckusic addrblock = spcl; 7494610Smckusick for (;;) { 7504837Smckusic for (i = 0; i < addrblock.c_count; i++) { 7514837Smckusic if (addrblock.c_addr[i]) { 7524776Smckusic readtape(&buf[curblk++][0]); 7536844Smckusick if (curblk == fssize / TP_BSIZE) { 7544776Smckusic (*f1)(buf, size > TP_BSIZE ? 7556844Smckusick (long) (fssize) : 7564776Smckusic (curblk - 1) * TP_BSIZE + size); 7574776Smckusic curblk = 0; 7584776Smckusic } 7595327Smckusic } else { 7604776Smckusic if (curblk > 0) { 7614776Smckusic (*f1)(buf, size > TP_BSIZE ? 7624776Smckusic (long) (curblk * TP_BSIZE) : 7634776Smckusic (curblk - 1) * TP_BSIZE + size); 7644776Smckusic curblk = 0; 7654776Smckusic } 7665327Smckusic (*f2)(clearedbuf, size > TP_BSIZE ? 7675327Smckusic (long) TP_BSIZE : size); 7684610Smckusick } 7694776Smckusic if ((size -= TP_BSIZE) <= 0) { 7708485Smckusick gethead(&spcl); 7714776Smckusic goto out; 7724610Smckusick } 7734610Smckusick } 7744837Smckusic if (gethead(&addrblock) == 0) { 7758485Smckusick fprintf(stderr, "Missing address (header) block for %s\n", 7768505Smckusick entry->x_name); 7778485Smckusick spcl.c_magic = 0; 7788485Smckusick goto out; 7794700Smckusic } 7804837Smckusic if (checktype(&addrblock, TS_ADDR) == 0) { 7814837Smckusic spcl = addrblock; 7824776Smckusic goto out; 7834700Smckusic } 7844610Smckusick } 7854776Smckusic out: 7864776Smckusic if (curblk > 0) { 7874776Smckusic (*f1)(buf, (curblk * TP_BSIZE) + size); 7884776Smckusic curblk = 0; 7894776Smckusic } 7904610Smckusick } 7914610Smckusick 7924610Smckusick /* 7934843Smckusic * The next routines are called during file extraction to 7944843Smckusic * put the data into the right form and place. 7954843Smckusic */ 7964843Smckusic xtrfile(buf, size) 7974843Smckusic char *buf; 7984843Smckusic long size; 7994843Smckusic { 8006847Smckusick 8016844Smckusick if (write(ofile, buf, (int) size) == -1) { 8025038Smckusic perror("extract write"); 8034843Smckusic done(1); 8044843Smckusic } 8054843Smckusic } 8064843Smckusic 8075038Smckusic xtrskip(buf, size) 8084843Smckusic char *buf; 8094843Smckusic long size; 8104843Smckusic { 8116847Smckusick 8126846Smckusick #ifdef lint 8136846Smckusick buf = buf; 8146846Smckusick #endif 8156844Smckusick if (lseek(ofile, size, 1) == -1) { 8165038Smckusic perror("extract seek"); 8174843Smckusic done(1); 8184843Smckusic } 8194843Smckusic } 8205038Smckusic 8215038Smckusic xtrcvtdir(buf, size) 8225038Smckusic struct odirect *buf; 8235038Smckusic long size; 8245038Smckusic { 8255038Smckusic struct odirect *odp, *edp; 8266846Smckusick struct direct cvtbuf; 8275038Smckusic 8285038Smckusic edp = &buf[size / sizeof(struct odirect)]; 8295943Smckusic for (odp = buf; odp < edp; odp++) { 8305943Smckusic dcvt(odp, &cvtbuf); 8315943Smckusic putent(&cvtbuf, xtrfile); 8325038Smckusic } 8335038Smckusic } 8345038Smckusic 8355038Smckusic xtrcvtskip(buf, size) 8365038Smckusic char *buf; 8375038Smckusic long size; 8385038Smckusic { 8396847Smckusick 8408485Smckusick fprintf(stderr, "unallocated block in directory %s\n", 8418505Smckusick entry->x_name); 8425943Smckusic xtrskip(buf, size); 8435038Smckusic } 8446289Smckusick 8456289Smckusick xtrlnkfile(buf, size) 8466289Smckusick char *buf; 8476289Smckusick long size; 8486289Smckusick { 8496847Smckusick 8506289Smckusick pathlen += size; 8516289Smckusick if (pathlen > MAXPATHLEN) { 8526289Smckusick fprintf(stderr, "symbolic link name: %s; too long %d\n", 8536289Smckusick buf, size); 8546289Smckusick done(1); 8556289Smckusick } 8566289Smckusick strcat(lnkbuf, buf); 8576289Smckusick } 8586289Smckusick 8596289Smckusick xtrlnkskip(buf, size) 8606289Smckusick char *buf; 8616289Smckusick long size; 8626289Smckusick { 8636847Smckusick 8646846Smckusick #ifdef lint 8656846Smckusick buf = buf, size = size; 8666846Smckusick #endif 8678485Smckusick fprintf(stderr, "unallocated block in symbolic link %s\n", 8688505Smckusick entry->x_name); 8696289Smckusick done(1); 8706289Smckusick } 8714843Smckusic 8724843Smckusic null() {;} 8734843Smckusic 8744843Smckusic /* 8754776Smckusic * Do the tape i/o, dealing with volume changes 8764610Smckusick * etc.. 8774610Smckusick */ 8784610Smckusick readtape(b) 8794700Smckusic char *b; 8804610Smckusick { 8816846Smckusick register long i; 8826847Smckusick struct u_spcl tmpbuf; 8836845Smckusick char c; 8844610Smckusick 8854610Smckusick if (bct >= NTREC) { 8864610Smckusick for (i = 0; i < NTREC; i++) 8874776Smckusic ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0; 8884610Smckusick bct = 0; 8896849Smckusick #ifdef RRESTOR 8906849Smckusick if ((i = rmtread(tbf, NTREC*TP_BSIZE)) < 0) { 8916849Smckusick #else 8924776Smckusic if ((i = read(mt, tbf, NTREC*TP_BSIZE)) < 0) { 8936849Smckusick #endif 8948485Smckusick fprintf(stderr, "Tape read error while restoring %s\n", 8958505Smckusick entry->x_name); 8968374Smckusick if (!yflag) { 8978485Smckusick fprintf(stderr, "continue? "); 8988374Smckusick do { 8998485Smckusick fprintf(stderr, "[yn] "); 9008374Smckusick c = getchar(); 9018374Smckusick while (getchar() != '\n') 9028374Smckusick /* void */; 9038374Smckusick } while (c != 'y' && c != 'n'); 9048374Smckusick if (c == 'n') 9058374Smckusick done(1); 9068374Smckusick } 9074610Smckusick eflag++; 9086845Smckusick i = NTREC*TP_BSIZE; 909*10202Smckusick bzero(tbf, i); 9106849Smckusick #ifdef RRESTOR 9116849Smckusick if (rmtseek(i, 1) < 0) { 9126849Smckusick #else 9136846Smckusick if (lseek(mt, i, 1) < 0) { 9146849Smckusick #endif 9156846Smckusick fprintf(stderr, "continuation failed\n"); 9166846Smckusick done(1); 9176846Smckusick } 9184610Smckusick } 9194610Smckusick if (i == 0) { 9204610Smckusick bct = NTREC + 1; 9214610Smckusick volno++; 9224610Smckusick loop: 9234610Smckusick flsht(); 9246849Smckusick #ifdef RRESTOR 9256849Smckusick rmtclose(); 9266849Smckusick #else 9274610Smckusick close(mt); 9286849Smckusick #endif 9294700Smckusic fprintf(stderr, "Mount volume %d\n", volno); 9304610Smckusick while (getchar() != '\n') 9314610Smckusick ; 9326849Smckusick #ifdef RRESTOR 9336849Smckusick if ((mt = rmtopen(magtape, 0)) == -1) { 9346849Smckusick #else 9354610Smckusick if ((mt = open(magtape, 0)) == -1) { 9366849Smckusick #endif 9374700Smckusic fprintf(stderr, "Cannot open tape!\n"); 9384610Smckusick goto loop; 9394610Smckusick } 9404610Smckusick if (readhdr(&tmpbuf) == 0) { 9414700Smckusic fprintf(stderr, "Not a dump tape.Try again\n"); 9424610Smckusick goto loop; 9434610Smckusick } 9444610Smckusick if (checkvol(&tmpbuf, volno) == 0) { 9454700Smckusic fprintf(stderr, "Wrong tape. Try again\n"); 9464610Smckusick goto loop; 9474610Smckusick } 9484610Smckusick readtape(b); 9494610Smckusick return; 9504610Smckusick } 9514610Smckusick } 952*10202Smckusick bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE); 9534610Smckusick } 9544610Smckusick 9554610Smckusick flsht() 9564610Smckusick { 9576847Smckusick 9584610Smckusick bct = NTREC+1; 9594610Smckusick } 9604610Smckusick 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 { 10218302Smckusick union u_ospcl { 10228302Smckusick char dummy[TP_BSIZE]; 10238302Smckusick struct s_ospcl { 10248302Smckusick int c_type; 10258302Smckusick time_t c_date; 10268302Smckusick time_t c_ddate; 10278302Smckusick int c_volume; 10288302Smckusick daddr_t c_tapea; 10298302Smckusick ino_t c_inumber; 10308302Smckusick int c_magic; 10318302Smckusick int c_checksum; 10328302Smckusick struct odinode { 10338302Smckusick unsigned short odi_mode; 10348302Smckusick short odi_nlink; 10358302Smckusick short odi_uid; 10368302Smckusick short odi_gid; 10378302Smckusick off_t odi_size; 10388302Smckusick daddr_t odi_rdev; 10398302Smckusick char odi_addr[36]; 10408302Smckusick time_t odi_atime; 10418302Smckusick time_t odi_mtime; 10428302Smckusick time_t odi_ctime; 10438302Smckusick } c_dinode; 10448302Smckusick int c_count; 10458302Smckusick char c_addr[TP_NINDIR]; 10468302Smckusick } s_ospcl; 10478302Smckusick } u_ospcl; 10486847Smckusick 10498302Smckusick if (!cvtflag) { 10508302Smckusick readtape((char *)buf); 10518369Smckusick if (buf->c_magic != NFS_MAGIC || checksum((int *)buf) == 0) 10528302Smckusick return(0); 10538302Smckusick return(1); 10548302Smckusick } 10558302Smckusick readtape((char *)(&u_ospcl.s_ospcl)); 1056*10202Smckusick bzero((char *)buf, TP_BSIZE); 10578302Smckusick buf->c_type = u_ospcl.s_ospcl.c_type; 10588302Smckusick buf->c_date = u_ospcl.s_ospcl.c_date; 10598302Smckusick buf->c_ddate = u_ospcl.s_ospcl.c_ddate; 10608302Smckusick buf->c_volume = u_ospcl.s_ospcl.c_volume; 10618302Smckusick buf->c_tapea = u_ospcl.s_ospcl.c_tapea; 10628302Smckusick buf->c_inumber = u_ospcl.s_ospcl.c_inumber; 10638302Smckusick buf->c_checksum = u_ospcl.s_ospcl.c_checksum; 10648485Smckusick buf->c_magic = u_ospcl.s_ospcl.c_magic; 10658302Smckusick buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode; 10668302Smckusick buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink; 10678302Smckusick buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid; 10688302Smckusick buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; 10698302Smckusick buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size; 10708302Smckusick buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev; 10718302Smckusick buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; 10728302Smckusick buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; 10738302Smckusick buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; 10748302Smckusick buf->c_count = u_ospcl.s_ospcl.c_count; 1075*10202Smckusick bcopy(u_ospcl.s_ospcl.c_addr, buf->c_addr, TP_NINDIR); 10768485Smckusick if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC || 10778485Smckusick checksum((int *)(&u_ospcl.s_ospcl)) == 0) 10788485Smckusick return(0); 10798485Smckusick buf->c_magic = NFS_MAGIC; 10804610Smckusick return(1); 10814610Smckusick } 10824610Smckusick 10834610Smckusick /* 10844610Smckusick * return whether or not the buffer contains a header block 10854610Smckusick */ 10864610Smckusick ishead(buf) 10874837Smckusic struct s_spcl *buf; 10884610Smckusick { 10896847Smckusick 10908369Smckusick if (buf->c_magic != NFS_MAGIC) 10914610Smckusick return(0); 10924610Smckusick return(1); 10934610Smckusick } 10944610Smckusick 10954610Smckusick checktype(b, t) 10964837Smckusic struct s_spcl *b; 10974700Smckusic int t; 10984610Smckusick { 10996847Smckusick 11004837Smckusic return(b->c_type == t); 11014610Smckusick } 11024610Smckusick 11035038Smckusic /* 11045038Smckusic * read a bit mask from the tape into m. 11055038Smckusic */ 11066844Smckusick readbits(mapp) 11076844Smckusick char **mapp; 11085038Smckusic { 11095038Smckusic register int i; 11106844Smckusick char *m; 11114610Smckusick 11125038Smckusic i = spcl.c_count; 11135038Smckusic 11146844Smckusick if (*mapp == 0) 11156846Smckusick *mapp = (char *)calloc(i, (TP_BSIZE/(NBBY/BITS))); 11166844Smckusick m = *mapp; 11175038Smckusic while (i--) { 11185038Smckusic readtape((char *) m); 11195327Smckusic m += (TP_BSIZE/(NBBY/BITS)); 11205038Smckusic } 11215038Smckusic while (gethead(&spcl) == 0) 11225038Smckusic ; 11235038Smckusic } 11245038Smckusic 11254610Smckusick checksum(b) 11268302Smckusick register int *b; 11274610Smckusick { 11284776Smckusic register int i, j; 11294610Smckusick 11304776Smckusic j = sizeof(union u_spcl) / sizeof(int); 11314610Smckusick i = 0; 11324610Smckusick do 11334610Smckusick i += *b++; 11344610Smckusick while (--j); 11354610Smckusick if (i != CHECKSUM) { 11368485Smckusick fprintf(stderr, "Checksum error %o, file %s\n", i, 11378505Smckusick entry->x_name); 11384610Smckusick return(0); 11394610Smckusick } 11404610Smckusick return(1); 11414610Smckusick } 11424610Smckusick 11434610Smckusick /* 11445038Smckusic * Check for access into each directory in the pathname of an extracted 11455038Smckusic * file and create such a directory if needed in preparation for moving 11465038Smckusic * the file to its proper home. 11475038Smckusic */ 11485038Smckusic checkdir(name) 11495038Smckusic register char *name; 11505038Smckusic { 11515038Smckusic register char *cp; 11525038Smckusic int i; 11535038Smckusic 11545038Smckusic for (cp = name; *cp; cp++) { 11559871Ssam if (*cp != '/') 11569871Ssam continue; 11579871Ssam *cp = '\0'; 11589871Ssam if (access(name, 01) < 0 && mkdir(name, 0777) < 0) 11599871Ssam fprintf(stderr, "restor: "), perror(name); 11609871Ssam *cp = '/'; 11615038Smckusic } 11625038Smckusic } 11635038Smckusic 11646844Smckusick setdir(dev) 11656844Smckusick char *dev; 11666844Smckusick { 11676844Smckusick struct fstab *fsp; 11686844Smckusick 11696844Smckusick if (setfsent() == 0) { 11706844Smckusick fprintf(stderr, "Can't open checklist file: %s\n", FSTAB); 11716844Smckusick done(1); 11726844Smckusick } 11736844Smckusick while ((fsp = getfsent()) != 0) { 11746844Smckusick if (strcmp(fsp->fs_spec, dev) == 0) { 11758374Smckusick fprintf(stderr, "%s mounted on %s\n", dev, fsp->fs_file); 11766844Smckusick if (chdir(fsp->fs_file) >= 0) 11776844Smckusick return; 11786844Smckusick fprintf(stderr, "%s cannot chdir to %s\n", 11796844Smckusick fsp->fs_file); 11806844Smckusick done(1); 11816844Smckusick } 11826844Smckusick } 11836844Smckusick fprintf(stderr, "%s not mounted\n", dev); 11846844Smckusick done(1); 11856844Smckusick } 11866844Smckusick 11875038Smckusic /* 11885943Smckusic * These variables are "local" to the following two functions. 11895943Smckusic */ 11905943Smckusic char dirbuf[DIRBLKSIZ]; 11915943Smckusic long dirloc = 0; 11925943Smckusic long prev = 0; 11935943Smckusic 11945943Smckusic /* 11955943Smckusic * add a new directory entry to a file. 11965943Smckusic */ 11975943Smckusic putent(dp, wrtfunc) 11985943Smckusic struct direct *dp; 11995943Smckusic int (*wrtfunc)(); 12005943Smckusic { 12016847Smckusick 12025943Smckusic if (dp->d_ino == 0) 12035943Smckusic return; 12046847Smckusick if (dirloc + dp->d_reclen > DIRBLKSIZ) { 12056847Smckusick ((struct direct *)(dirbuf + prev))->d_reclen = 12066847Smckusick DIRBLKSIZ - prev; 12075943Smckusic (*wrtfunc)(dirbuf, DIRBLKSIZ); 12085943Smckusic dirloc = 0; 12095943Smckusic } 1210*10202Smckusick bcopy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen); 12116847Smckusick prev = dirloc; 12126847Smckusick dirloc += dp->d_reclen; 12135943Smckusic } 12145943Smckusic 12155943Smckusic /* 12165943Smckusic * flush out a directory that is finished. 12175943Smckusic */ 12185943Smckusic flushent(wrtfunc) 12195943Smckusic int (*wrtfunc)(); 12205943Smckusic { 12216847Smckusick 12225943Smckusic ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; 12235943Smckusic (*wrtfunc)(dirbuf, dirloc); 12245943Smckusic dirloc = 0; 12255943Smckusic } 12265943Smckusic 12275943Smckusic dirwrite(buf, size) 12285943Smckusic char *buf; 12295943Smckusic int size; 12305943Smckusic { 12316847Smckusick 12325943Smckusic fwrite(buf, 1, size, df); 12335943Smckusic seekpt = ftell(df); 12345943Smckusic } 12355943Smckusic 12365943Smckusic dcvt(odp, ndp) 12375943Smckusic register struct odirect *odp; 12385943Smckusic register struct direct *ndp; 12395943Smckusic { 12406847Smckusick 1241*10202Smckusick bzero((char *)ndp, (long)(sizeof *ndp)); 12425943Smckusic ndp->d_ino = odp->d_ino; 12435943Smckusic strncpy(ndp->d_name, odp->d_name, ODIRSIZ); 12445943Smckusic ndp->d_namlen = strlen(ndp->d_name); 12455943Smckusic ndp->d_reclen = DIRSIZ(ndp); 12465943Smckusic /* 12475943Smckusic * this quickly calculates if this inode is a directory. 12485943Smckusic * Currently not maintained. 12495943Smckusic * 12505943Smckusic for (itp = inotab[INOHASH(odp->d_ino)]; itp; itp = itp->t_next) { 12515943Smckusic if (itp->t_ino != odp->d_ino) 12525943Smckusic continue; 12535943Smckusic ndp->d_fmt = IFDIR; 12545943Smckusic break; 12555943Smckusic } 12565943Smckusic */ 12575943Smckusic } 12585943Smckusic 12595943Smckusic /* 12606289Smckusick * Open a directory. 12616289Smckusick * Modified to allow any random file to be a legal directory. 12626289Smckusick */ 12636289Smckusick DIR * 12646289Smckusick opendir(name) 12656289Smckusick char *name; 12666289Smckusick { 12676289Smckusick register DIR *dirp; 12686289Smckusick 12696289Smckusick dirp = (DIR *)malloc(sizeof(DIR)); 12706289Smckusick dirp->dd_fd = open(name, 0); 12716289Smckusick if (dirp->dd_fd == -1) { 12726846Smckusick free((char *)dirp); 12736289Smckusick return NULL; 12746289Smckusick } 12756289Smckusick dirp->dd_loc = 0; 12766289Smckusick return dirp; 12776289Smckusick } 12786289Smckusick 12796289Smckusick /* 12806289Smckusick * Seek to an entry in a directory. 12815943Smckusic * Only values returned by ``telldir'' should be passed to seekdir. 12825943Smckusic * Modified to have many directories based in one file. 12835943Smckusic */ 12845943Smckusic void 12855943Smckusic seekdir(dirp, loc, base) 12865943Smckusic register DIR *dirp; 12876846Smckusick daddr_t loc, base; 12885943Smckusic { 12896847Smckusick 12905943Smckusic if (loc == telldir(dirp)) 12915943Smckusic return; 12925943Smckusic loc -= base; 12935943Smckusic if (loc < 0) 12945943Smckusic fprintf(stderr, "bad seek pointer to seekdir %d\n", loc); 12956846Smckusick (void)lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0); 12965943Smckusic dirp->dd_loc = loc & (DIRBLKSIZ - 1); 12975943Smckusic if (dirp->dd_loc != 0) 12985943Smckusic dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); 12995943Smckusic } 13005943Smckusic 13015943Smckusic /* 13026844Smckusick * get next entry in a directory. 13034700Smckusic */ 13046844Smckusick struct direct * 13056844Smckusick readdir(dirp) 13066844Smckusick register DIR *dirp; 13074610Smckusick { 13086844Smckusick register struct direct *dp; 13094700Smckusic 13106844Smckusick for (;;) { 13116844Smckusick if (dirp->dd_loc == 0) { 13126844Smckusick dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 13136844Smckusick DIRBLKSIZ); 13146844Smckusick if (dirp->dd_size <= 0) 13156844Smckusick return NULL; 13166844Smckusick } 13176844Smckusick if (dirp->dd_loc >= dirp->dd_size) { 13186844Smckusick dirp->dd_loc = 0; 13196844Smckusick continue; 13206844Smckusick } 13216844Smckusick dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); 13226844Smckusick if (dp->d_reclen <= 0 || 13236844Smckusick dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) 13246844Smckusick return NULL; 13256844Smckusick dirp->dd_loc += dp->d_reclen; 13266844Smckusick if (dp->d_ino == 0) 13276844Smckusick continue; 13286844Smckusick return (dp); 13295948Smckusic } 13304610Smckusick } 13314610Smckusick 13324843Smckusic allocinotab(ino, seekpt) 13334837Smckusic ino_t ino; 13344843Smckusic daddr_t seekpt; 13354610Smckusick { 13364837Smckusic register struct inotab *itp; 13374776Smckusic 13384837Smckusic itp = (struct inotab *)calloc(1, sizeof(struct inotab)); 13394837Smckusic itp->t_next = inotab[INOHASH(ino)]; 13404837Smckusic inotab[INOHASH(ino)] = itp; 13414837Smckusic itp->t_ino = ino; 13424843Smckusic itp->t_seekpt = seekpt; 13434610Smckusick } 13444610Smckusick 13458505Smckusick struct xtrlist * 13464843Smckusic allocxtr(ino, name, flags) 13474837Smckusic ino_t ino; 13484843Smckusic char *name; 13494843Smckusic char flags; 13504610Smckusick { 13514843Smckusic register struct xtrlist *xp, *pxp; 13528485Smckusick int size; 13534776Smckusic 13548485Smckusick size = sizeof(struct xtrlist) + strlen(name); 13558485Smckusick xp = (struct xtrlist *)calloc(1, size); 13568505Smckusick xp->x_ino = ino; 13578505Smckusick xp->x_flags = flags; 13588505Smckusick strcpy(xp->x_name, name); 13598505Smckusick if (flags == 0) 13608505Smckusick return (xp); 13614837Smckusic xp->x_next = xtrlist[INOHASH(ino)]; 13624837Smckusic xtrlist[INOHASH(ino)] = xp; 13634837Smckusic xtrcnt++; 13644843Smckusic for (pxp = xp->x_next; pxp; pxp = pxp->x_next) 13654843Smckusic if (pxp->x_ino == ino && (pxp->x_flags & XLINKED) == 0) { 13664843Smckusic xp->x_flags |= XLINKED; 13674843Smckusic xp->x_linkedto = pxp; 13684843Smckusic xtrcnt--; 13694843Smckusic break; 13704843Smckusic } 1371*10202Smckusick if (!vflag && !tflag) 13728505Smckusick return (xp); 13734843Smckusic if (xp->x_flags & XLINKED) 13744843Smckusic fprintf(stdout, "%s: linked to %s\n", xp->x_name, pxp->x_name); 13754843Smckusic else if (xp->x_flags & XISDIR) 13764843Smckusic fprintf(stdout, "%s: directory inode %u\n", xp->x_name, ino); 13774843Smckusic else 13784843Smckusic fprintf(stdout, "%s: inode %u\n", xp->x_name, ino); 13798505Smckusick return (xp); 13804610Smckusick } 13814610Smckusick 13828505Smckusick #ifdef RRESTOR 13838505Smckusick msg(cp, a1, a2, a3) 13848505Smckusick char *cp; 13858505Smckusick { 13868505Smckusick 13878505Smckusick fprintf(stderr, cp, a1, a2, a3); 13888505Smckusick } 13898505Smckusick #endif RRESTOR 13908505Smckusick 13915038Smckusic done(exitcode) 13925038Smckusic int exitcode; 13934610Smckusick { 13946847Smckusick 13955038Smckusic unlink(dirfile); 13965038Smckusic exit(exitcode); 13974610Smckusick } 1398