- case 'R':
-#ifndef STANDALONE
- {
- char mount[80];
- char *ptr[2];
-
- strcpy(mount, "MOUNT=");
- strcat(mount, *argv);
- ptr[0] = mount;
- ptr[1] = 0;
- xmount(ptr);
- iput(u.u_cdir); /* release root inode */
- iput(u.u_rdir); /* release root inode */
- mounted++;
- }
-#else
- do {
- char charbuf[50];
-
- fprintf(stderr, "Disk? ");
- gets(charbuf);
- fi = open(charbuf, 2);
- } while (fi == -1);
-#endif
-#ifndef STANDALONE
- if (command == 'R') {
- fprintf(stderr, "Enter starting volume number: ");
- if (gets(tbf) == EOF) {
- volno = 1;
- fprintf(stderr, "\n");
- }
- else
- volno = atoi(tbf);
- }
- else
-#endif
- volno = 1;
- fprintf(stderr, "Last chance before scribbling on %s. ",
-#ifdef STANDALONE
- "disk");
-#else
- *argv);
-#endif
- while (getchar() != '\n');
- fs = getfs(dev);
- maxi = fs->fs_ipg * fs->fs_ncg;
- if (readhdr(&spcl) == 0) {
- fprintf(stderr, "Missing volume record\n");
- done(1);
- }
- if (checkvol(&spcl, volno) == 0) {
- fprintf(stderr, "Tape is not volume %d\n", volno);
- done(1);
- }
- gethead(&spcl);
- for (;;) {
-ragain:
- if (ishead(&spcl) == 0) {
- fprintf(stderr, "Missing header block\n");
- while (gethead(&spcl) == 0)
- ;
- eflag++;
- }
- if (checktype(&spcl, TS_END) == 1) {
- fprintf(stderr, "End of tape\n");
- close(mt);
- return;
- }
- if (checktype(&spcl, TS_CLRI) == 1) {
- readbits(clrimap);
- for (ino = 1; ino <= maxi; ino++)
- if (BIT(ino, clrimap) == 0) {
- if (!iexist(dev, ino))
- continue;
- ip = iget(dev, ino);
- if (ip == NULL) {
- fprintf(stderr, "can't find inode %u\n", ino);
- done(1);
- }
- ip->i_nlink = 0;
- ip->i_flag |= ICHG;
- iput(ip);
- }
- goto ragain;
- }
- if (checktype(&spcl, TS_BITS) == 1) {
- readbits(dumpmap);
- goto ragain;
- }
- if (checktype(&spcl, TS_INODE) == 0) {
- fprintf(stderr, "Unknown header type\n");
- eflag++;
- gethead(&spcl);
- goto ragain;
- }
- ino = spcl.c_inumber;
- if (eflag)
- fprintf(stderr, "Resynced at inode %u\n", ino);
- eflag = 0;
- if (ino > maxi) {
- fprintf(stderr, "%u: ilist too small\n", ino);
- gethead(&spcl);
- goto ragain;
- }
- if (iexist(dev, ino)) {
- ip = iget(dev, ino);
- if (ip == NULL) {
- fprintf(stderr, "can't find inode %u\n",
- ino);
- done(1);
- }
- ip->i_nlink = 0;
- ip->i_flag |= ICHG;
- iput(ip);
- }
- dp = &spcl.c_dinode;
- ip = ialloc(dev, ino, dp->di_mode);
- if (ip == NULL || ip->i_number != ino) {
- fprintf(stderr, "can't create inode %u\n", ino);
- done(1);
- }
- ip->i_mode = mode = dp->di_mode;
- ip->i_nlink = dp->di_nlink;
- ip->i_uid = dp->di_uid;
- ip->i_gid = dp->di_gid;
- ip->i_atime = dp->di_atime;
- ip->i_mtime = dp->di_mtime;
- ip->i_ctime = dp->di_ctime;
- if ((ip->i_mode & IFMT) == IFCHR ||
- (ip->i_mode & IFMT) == IFBLK)
- ip->i_rdev = dp->di_rdev;
- ip->i_size = 0;
- cur_ip = ip;
- u.u_offset = 0;
- u.u_segflg = 1;
- getfile(rstrfile, rstrskip, dp->di_size);
- ip->i_mode = mode;
- ip->i_flag &= ~(IUPD|IACC);
- ip->i_flag |= ICHG;
- iput(ip);
- }
- }
-}
-
-/*
- * Read the tape, bulding up a directory structure for extraction
- * by name
- */
-#ifndef STANDALONE
-pass1()
-{
- register int i;
- struct dinode *ip;
- int putdir(), null();
-
- while (gethead(&spcl) == 0) {
- fprintf(stderr, "Can't find directory header!\n");
- }
- for (;;) {
- if (checktype(&spcl, TS_BITS) == 1) {
- readbits(dumpmap);
- continue;
- }
- if (checktype(&spcl, TS_CLRI) == 1) {
- readbits(clrimap);
- continue;
- }
- if (checktype(&spcl, TS_INODE) == 0) {
-finish:
- flsh();
-/*
- close(mt);
-*/
- return;
- }
- ip = &spcl.c_dinode;
- i = ip->di_mode & IFMT;
- if (i != IFDIR) {
- goto finish;
- }
- inotab[ipos].t_ino = spcl.c_inumber;
- inotab[ipos++].t_seekpt = seekpt;
- getfile(putdir, null, spcl.c_dinode.di_size);
- putent("\000\000/");
- }
-}
-#endif
-
-/*
- * Do the file extraction, calling the supplied functions
- * with the blocks
- */
-getfile(f1, f2, size)
- int (*f2)(), (*f1)();
- long size;
-{
- register int i;
- union u_spcl addrblock;
- char buf[BLKING * FRAG][TP_BSIZE];
-
- addrblock.s_spcl = spcl;
- for (;;) {
- for (i = 0; i < addrblock.s_spcl.c_count; i++) {
- if (addrblock.s_spcl.c_addr[i]) {
- readtape(&buf[curblk++][0]);
- if (curblk == BLKING * FRAG) {
- (*f1)(buf, size > TP_BSIZE ?
- (long) (BLKING * FRAG * TP_BSIZE) :
- (curblk - 1) * TP_BSIZE + size);
- curblk = 0;
- }
- }
- else {
- if (curblk > 0) {
- (*f1)(buf, size > TP_BSIZE ?
- (long) (curblk * TP_BSIZE) :
- (curblk - 1) * TP_BSIZE + size);
- curblk = 0;
- }
- (*f2)(clearedbuf, size > TP_BSIZE ? (long) TP_BSIZE : size);
- }
- if ((size -= TP_BSIZE) <= 0) {
-eloop:
- while (gethead(&spcl) == 0)
- ;
- if (checktype(&spcl, TS_ADDR) == 1)
- goto eloop;
- goto out;
- }
- }
- if (gethead(&addrblock.s_spcl) == 0) {
- fprintf(stderr, "Missing address (header) block, ino%u\n", ino);
- goto eloop;
- }
- if (checktype(&addrblock.s_spcl, TS_ADDR) == 0) {
- spcl = addrblock.s_spcl;
- goto out;
- }
- }
-out:
- if (curblk > 0) {
- (*f1)(buf, (curblk * TP_BSIZE) + size);
- curblk = 0;
- }
-}
-
-/*
- * Do the tape i/o, dealing with volume changes
- * etc..
- */
-readtape(b)
- char *b;
-{
- register int i;
- union u_spcl tmpbuf;
-
- if (bct >= NTREC) {
- for (i = 0; i < NTREC; i++)
- ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0;
- bct = 0;
- if ((i = read(mt, tbf, NTREC*TP_BSIZE)) < 0) {
- perror("Tape read error");
- eflag++;
- done(1);
- }
- if (i == 0) {
- bct = NTREC + 1;
- volno++;
-loop:
- flsht();
- close(mt);
- fprintf(stderr, "Mount volume %d\n", volno);
- while (getchar() != '\n')
- ;
- if ((mt = open(magtape, 0)) == -1) {
- fprintf(stderr, "Cannot open tape!\n");
- goto loop;
- }
- if (readhdr(&tmpbuf) == 0) {
- fprintf(stderr, "Not a dump tape.Try again\n");
- goto loop;
- }
- if (checkvol(&tmpbuf, volno) == 0) {
- fprintf(stderr, "Wrong tape. Try again\n");
- goto loop;
- }
- readtape(b);
- return;
- }
- }
- copy(&tbf[(bct++*TP_BSIZE)], b, TP_BSIZE);
-}
-
-flsht()
-{
- bct = NTREC+1;
-}
-
-copy(f, t, s)
- register char *f, *t;
-{
- register int i;
-
- i = s;
- do
- *t++ = *f++;
- while (--i);
-}
-
-clearbuf(cp)
- register char *cp;
-{
- register int i;
-
- i = BSIZE;
- do
- *cp++ = 0;
- while (--i);
-}
-
-/*
- * Put and get the directory entries from the compressed
- * directory file
- */
-#ifndef STANDALONE
-putent(cp)
- char *cp;
-{
- register int i;
-
- for (i = 0; i < sizeof(ino_t); i++)
- writec(*cp++);
- for (i = 0; i < DIRSIZ; i++) {
- writec(*cp);
- if (*cp++ == 0)
- return;
- }
- return;
-}
-
-getent(bf)
- register char *bf;
-{
- register int i;
-
- for (i = 0; i < sizeof(ino_t); i++)
- *bf++ = readc();
- for (i = 0; i < DIRSIZ; i++)
- if ((*bf++ = readc()) == 0)
- return;
- return;
-}
-
-/*
- * read/write the directory file
- */
-writec(c)
- char c;
-{
- drblock[bpt++] = c;
- seekpt++;
- if (bpt >= BSIZE) {
- bpt = 0;
- write(df, drblock, BSIZE);
- }
-}
-
-readc()
-{
- if (bpt >= BSIZE) {
- nread = read(df, drblock, BSIZE);
- bpt = 0;
- }
- return(drblock[bpt++]);
-}
-
-mseek(pt)
- daddr_t pt;
-{
- bpt = BSIZE;
- lseek(df, pt, 0);
-}
-
-flsh()
-{
- write(df, drblock, bpt+1);
-}
-
-/*
- * search the directory inode ino
- * looking for entry cp
- */
-ino_t
-search(inum, cp)
- ino_t inum;
- char *cp;
-{
- register int i;
-
- for (i = 0; i < MAXINO; i++)
- if (inotab[i].t_ino == inum) {
- goto found;
- }
- return(0);
-found:
- mseek(inotab[i].t_seekpt);
- do {
- getent((char *)&dir);
- if (direq(dir.d_name, "/"))
- return(0);
- } while (direq(dir.d_name, cp) == 0);
- return(dir.d_ino);
-}
-
-/*
- * Search the directory tree rooted at inode ROOTINO
- * for the path pointed at by n
- */
-psearch(n)
- char *n;
-{
- register char *cp, *cp1;
- char c;
-
- ino = ROOTINO;
- if (*(cp = n) == '/')
- cp++;
-next:
- cp1 = cp + 1;
- while (*cp1 != '/' && *cp1)
- cp1++;
- c = *cp1;
- *cp1 = 0;
- ino = search(ino, cp);
- if (ino == 0) {
- *cp1 = c;
- return(0);
- }
- *cp1 = c;
- if (c == '/') {
- cp = cp1+1;
- goto next;
- }
- return(ino);
-}
-
-direq(s1, s2)
- register char *s1, *s2;
-{
- register int i;
-
- for (i = 0; i < DIRSIZ; i++)
- if (*s1++ == *s2) {
- if (*s2++ == 0)
- return(1);
- } else
- return(0);
- return(1);
-}
-#endif
-
-/*
- * read the tape into buf, then return whether or
- * or not it is a header block.
- */
-gethead(buf)
- union u_spcl *buf;
-{
- int i;
-
- readtape((char *)buf);
- if (buf->s_spcl.c_magic != MAGIC || checksum((int *) &buf->s_spcl) == 0)
- return(0);
- return(1);
-}
-
-/*
- * return whether or not the buffer contains a header block
- */
-ishead(buf)
- union u_spcl *buf;
-{
- if (buf->s_spcl.c_magic != MAGIC || checksum((int *) &buf->s_spcl) == 0)
- return(0);
- return(1);
-}
-
-checktype(b, t)
- union u_spcl *b;
- int t;
-{
- return(b->s_spcl.c_type == t);
-}
-
-
-checksum(b)
- int *b;
-{
- register int i, j;
-
- j = sizeof(union u_spcl) / sizeof(int);
- i = 0;
- do
- i += *b++;
- while (--j);
- if (i != CHECKSUM) {
- fprintf(stderr, "Checksum error %o, ino %u\n", i, ino);
- return(0);
- }
- return(1);
-}
-
-checkvol(b, t)
- union u_spcl *b;
- int t;
-{
- if (b->s_spcl.c_volume == t)
- return(1);
- return(0);
-}
-
-readhdr(b)
- union u_spcl *b;
-{
- if (gethead(b) == 0)
- return(0);
- if (checktype(b, TS_TAPE) == 0)
- return(0);
- return(1);
-}
-
-/*
- * The next routines are called during file extraction to
- * put the data into the right form and place.
- */
-#ifndef STANDALONE
-xtrfile(buf, size)
- char *buf;
- long size;
-{
- xwrite(ofile, buf, (int) size);
-}
-
-null() {;}
-
-skip(buf, size)
- char *buf;
- long size;
-{
- xseek(ofile, size, 1);
-}
-#endif
-
-
-rstrfile(buf, size)
- char *buf;
- long size;
-{
- u.u_base = buf;
- u.u_count = size;
- writei(cur_ip);
-}
-
-rstrskip(buf, size)
- char *buf;
- long size;
-{
- u.u_offset += size;
-}
-
-/*
- * tell whether an inode is allocated
- * this is drawn from ialloccg in sys/alloc.c
- */
-iexist(dev, ino)
- dev_t dev;
- ino_t ino;
-{
- register struct fs *fs;
- register struct cg *cgp;
- register struct buf *bp;
- int cg;
-
- fs = getfs(dev);
- if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg)
- return (0);
- cg = itog(ino, fs);
- bp = bread(dev, cgtod(cg, fs), BSIZE);
- if (bp->b_flags & B_ERROR)
- return(0);
- cgp = bp->b_un.b_cg;
- ino %= fs->fs_ipg;
- if (isclr(cgp->cg_iused, ino)) {
- brelse(bp);
- return(0);
- }
- brelse(bp);
- return (1);
-}
-
-#ifndef STANDALONE
-putdir(buf, size)
- char *buf;
- int size;
-{
- register struct direct *dp;
- register int i;
-
- for (dp = (struct direct *) buf, i = 0; i < size; dp++, i += sizeof(*dp)) {
- if (dp->d_ino == 0)
- continue;
- putent((char *) dp);
- }
-}
-#endif
-
-/*
- * read a bit mask from the tape into m.
- */
-readbits(m)
- short *m;
-{
- register int i;
-
- i = spcl.c_count;
-
- while (i--) {
- readtape((char *) m);
- m += (TP_BSIZE/(MLEN/BITS));
- }
- while (gethead(&spcl) == 0)
- ;
-}
-
-done(exitcode)
- int exitcode;
-{
-#ifndef STANDALONE
- unlink(dirfile);
-#endif
- if (mounted)
- xumount();
- exit(exitcode);
-}
-
-stcopy( sourcep, destp, max )
- char *sourcep, *destp;
- int max;
-{
- int i;
-
- for( i = 1; i <= max && (*destp++ = *sourcep++); i++ )
- ;
- if( i > max ) return( 0 );
- else return( 1 );
-}
-
-append( sourcep, destp, max )
- char *sourcep, *destp;
- int max;
-{
- int i;
-
- for( i=0; *destp; i++ )
- *destp++;
- if( ++i <= max ) *destp++ = '/';
- while( ++i<=max && (*destp++ = *sourcep++) )
- ;
- if( i > max ) return( 0 );
- else return( 1 );
-}
-/*
- * Truncate the rightmost file or directory name from a pathname
- */
-
-trunc( cp )
- char *cp;
-{
- char *lstslsh;
- lstslsh = 0;
- while( *cp++ )
- if( *cp == '/' ) lstslsh = cp;
- if( lstslsh == 0 )
- return( 0 );
- else {
- *lstslsh = '\0';
- return( 1 );
- }
-}
-getxtrlist() {
- struct xtrlist *malloc(),
- *realloc();
-
- if( init ) {
- init = 0;
- xtrlist = malloc( SIZEINC*sizeof(struct xtrlist) );
- xsize = SIZEINC;
- }
- else {
- xtrlist = realloc( xtrlist, (SIZEINC+xsize) *
- sizeof(struct xtrlist) );
- xsize += SIZEINC;
- }
-
-}
-
-/*
- * Check for access into each directory in the pathname of an extracted
- * file and create such a directory if needed in preparation for moving
- * the file to its proper home.
- */
-checkdir(name)
- register char *name;
-{
- register char *cp;
- int i;
-
- for (cp = name; *cp; cp++) {
- if (*cp == '/') {
- *cp = '\0';
- if (xaccess(name, 01) < 0) {
- register int pid, rp;
-
- xumount();
- if ((pid = fork()) == 0) {
- execl("/bin/xmkdir", "xmkdir", name, 0);
- execl("/usr/bin/xmkdir", "xmkdir", name, 0);
- execl("./xmkdir", "xmkdir", name, 0);
- fprintf(stderr, "xrestor: cannot find xmkdir!\n");
- done(0);
- }
- while ((rp = wait(&i)) >= 0 && rp != pid)
- ;
- xmount(envp);
- xchown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
- }
- *cp = '/';
- }
- }
-}
-
-/*
- * Store a string in core returning a pointer to it. Allocate space
- * as needed.
- */
-char *
-ststore( stringp )
- char *stringp;
-{
- static char *spacep;
- static int spaceleft;
- char *rtnp, *savep;
-
- rtnp = spacep;
- savep = stringp;
- while( spaceleft-- && (*spacep++ = *stringp++) );
- if( spaceleft >= 0 )
- return( rtnp );
- else {
- spaceleft = 10 * NSIZE;
- spacep = (char *)malloc( spaceleft );
- return( ststore(savep) );
- }
-}
-
-/*
- * Recursively find names and inumbers of all files in subtree
- * pname and put them in xtrlist[]
- */
-getleaves( pname )
- char *pname;
-{
- static int xtrcnt = 0; /* number of entries to extract */
- int n, /* loop counter */
- bptsave, /* placeholder for pointer into drblock */
- readsize; /* nbytes read into drblock at cur level
- of recursion */
- char locname[NSIZE]; /* pname + an entry from drblock */
- daddr_t dptsave, /* disk loc where cur drblock came from */
- disk_loc; /* used to see if getent() causes a phys read */
- ino_t d; /* inode no of pname */
-
- stcopy( pname, locname, NSIZE );
- if( (d = psearch(locname)) == 0 || BIT( d, dumpmap) == 0 ) {
- fprintf(stderr, "%s: not on the tape\n", locname );
- return;
- }
-
- for( n=0; n<MAXINO; n++ ) {
- if( inotab[n].t_ino == d ) {