-#ifdef RRESTOR
- if ((mt = rmtopen(magtape, 0)) < 0) {
-#else
- if ((mt = open(magtape, 0)) < 0) {
-#endif
- fprintf(stderr, "%s: cannot open tape\n", magtape);
- done(1);
- }
- if (dumpnum != 1) {
- tcom.mt_op = MTFSF;
- tcom.mt_count = dumpnum -1;
-#ifdef RRESTOR
- rmtioctl(MTFSF,dumpnum - 1);
-#else
- if (ioctl(mt,MTIOCTOP,&tcom) < 0)
- perror("ioctl MTFSF");
-#endif
- }
- bzero(clearedbuf, (long)MAXBSIZE);
- if (readhdr(&spcl) == 0) {
- bct--; /* push back this block */
- cvtflag++;
- if (readhdr(&spcl) == 0) {
- fprintf(stderr, "Tape is not a dump tape\n");
- done(1);
- }
- fprintf(stderr, "Converting to new file system format.\n");
- }
- if (vflag) {
- fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date));
- fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate));
- }
- df = fopen(dirfile, "w");
- if (df == 0) {
- fprintf(stderr,
- "restor: %s - cannot create directory temporary\n",
- dirfile);
- done(1);
- }
- if (stat(".", &stbuf) < 0) {
- fprintf(stderr, "cannot stat .\n");
- done(1);
- }
- fssize = stbuf.st_blksize;
- if (fssize <= 0 || ((fssize - 1) & fssize) != 0) {
- fprintf(stderr, "bad block size %d\n", fssize);
- done(1);
- }
- if (checkvol(&spcl, 1) == 0) {
- fprintf(stderr, "Tape is not volume 1 of the dump\n");
- }
- clrimap = 0;
- dumpmap = 0;
- unknown = allocxtr(0, "name unknown - not extracted", 0);
- pass1(); /* This sets the various maps on the way by */
- while (argc--) {
- if ((d = psearch(*argv)) == 0 || BIT(d,dumpmap) == 0) {
- fprintf(stderr, "%s: not on tape\n", *argv++);
- continue;
- }
- if (mflag && !tflag)
- checkdir(*argv);
- if (hflag)
- getleaves(d, *argv++);
- else
- (void)allocxtr(d, *argv++, XINUSE);
- }
- if (dumpnum > 1) {
- /*
- * if this is a multi-dump tape we always start with
- * volume 1, so as to avoid accidentally restoring
- * from a different dump!
- */
- resetmt();
- dumpnum = 1;
- volno = 1;
- readhdr(&spcl);
- goto rbits;
- }
-newvol:
-#ifdef RRESTOR
- rmtclose();
-#else
- close(mt);
-#endif
- if (tflag)
- return;
-getvol:
- fprintf(stderr, "Mount desired tape volume; Specify volume #: ");
- if (gets(tbf) == NULL)
- return;
- volno = atoi(tbf);
- if (volno <= 0) {
- fprintf(stderr, "Volume numbers are positive numerics\n");
- goto getvol;
- }
-#ifdef RRESTOR
- if ((mt = rmtopen(magtape, 0)) == -1) {
-#else
- if ((mt = open(magtape, 0)) == -1) {
-#endif
- fprintf(stderr, "Cannot open tape!\n");
- goto getvol;
- }
- if (dumpnum > 1)
- resetmt();
- if (readhdr(&spcl) == 0) {
- fprintf(stderr, "tape is not dump tape\n");
- goto newvol;
- }
- if (checkvol(&spcl, volno) == 0) {
- fprintf(stderr, "Wrong volume (%d)\n", spcl.c_volume);
- goto newvol;
- }
-rbits:
- while (gethead(&spcl) == 0)
- ;
- if (checktype(&spcl, TS_INODE) == 1) {
- fprintf(stderr, "Can't find inode mask!\n");
- goto newvol;
- }
- if (checktype(&spcl, TS_BITS) == 0)
- goto rbits;
- readbits(&dumpmap);
- while (xtrcnt > 0) {
-again:
- if (ishead(&spcl) == 0) {
- i = 0;
- while (gethead(&spcl) == 0)
- i++;
- fprintf(stderr, "resync restor, skipped %d blocks\n",
- i);
- }
- if (checktype(&spcl, TS_END) == 1) {
- fprintf(stderr, "end of tape\n");
- break;
- }
- if (checktype(&spcl, TS_INODE) == 0) {
- gethead(&spcl);
- goto again;
- }
- d = spcl.c_inumber;
- entry = unknown;
- entry->x_ino = d;
- for (xp = xtrlist[INOHASH(d)]; xp; xp = xp->x_next) {
- if (d != xp->x_ino || (xp->x_flags & XLINKED))
- continue;
- entry = xp;
- timep[0] = spcl.c_dinode.di_atime;
- timep[1] = spcl.c_dinode.di_mtime;
- mode = spcl.c_dinode.di_mode;
- if (mflag)
- strcpy(name, xp->x_name);
- else
- sprintf(name, "%u", xp->x_ino);
- switch (mode & IFMT) {
- default:
- fprintf(stderr, "%s: unknown file mode 0%o\n",
- name, mode);
- xp->x_flags |= XTRACTD;
- xtrcnt--;
- goto skipfile;
- case IFCHR:
- case IFBLK:
- vprintf(stdout, "extract special file %s\n", name);
- if (mknod(name, mode, spcl.c_dinode.di_rdev)) {
- fprintf(stderr, "%s: cannot create special file\n", name);
- xp->x_flags |= XTRACTD;
- xtrcnt--;
- goto skipfile;
- }
- getfile(null, null, spcl.c_dinode.di_size);
- break;
- case IFDIR:
- if (mflag) {
- for (itp = inotab[INOHASH(d)];
- itp; itp = itp->t_next) {
- if (itp->t_ino != d)
- continue;
- itp->t_timep[0] = timep[0];
- itp->t_timep[1] = timep[1];
- break;
- }
- if (itp == 0)
- fprintf(stderr, "missing directory entry\n");
- vprintf(stdout, "extract directory %s\n", name);
- strncat(name, "/.", BUFSIZ);
- checkdir(name);
- chown(xp->x_name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
- getfile(null, null, spcl.c_dinode.di_size);
- break;
- }
- vprintf(stdout, "extract file %s\n", name);
- if ((ofile = creat(name, 0666)) < 0) {
- fprintf(stderr, "%s: cannot create file\n", name);
- xp->x_flags |= XTRACTD;
- xtrcnt--;
- goto skipfile;
- }
- chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
- if (cvtflag) {
- getfile(xtrcvtdir, xtrcvtskip,
- spcl.c_dinode.di_size);
- flushent(xtrfile);
- } else
- getfile(xtrfile, xtrskip,
- spcl.c_dinode.di_size);
- close(ofile);
- break;
- case IFLNK:
- /*
- * Some early dump tapes have symbolic links
- * present without the associated data blocks.
- * This hack avoids trashing a file system with
- * inodes with missing data blocks.
- */
- if (spcl.c_count == 0) {
- vprintf(stdout, "%s: 0 length symbolic link (ignored)\n", name);
- xp->x_flags |= XTRACTD;
- xtrcnt--;
- goto skipfile;
- }
- vprintf(stdout, "extract symbolic link %s\n", name);
- uid = spcl.c_dinode.di_uid;
- gid = spcl.c_dinode.di_gid;
- lnkbuf[0] = '\0';
- pathlen = 0;
- getfile(xtrlnkfile, xtrlnkskip, spcl.c_dinode.di_size);
- if (symlink(lnkbuf, name) < 0) {
- fprintf(stderr, "%s: cannot create symbolic link\n", name);
- xp->x_flags |= XTRACTD;
- xtrcnt--;
- goto finished;
- }
- chown(name, uid, gid);
- break;
- case IFREG:
- vprintf(stdout, "extract file %s\n", name);
- if ((ofile = creat(name, 0666)) < 0) {
- fprintf(stderr, "%s: cannot create file\n", name);
- xp->x_flags |= XTRACTD;
- xtrcnt--;
- goto skipfile;
- }
- chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
- getfile(xtrfile, xtrskip, spcl.c_dinode.di_size);
- close(ofile);
- break;
- }
- chmod(name, mode);
- utime(name, timep);
- xp->x_flags |= XTRACTD;
- xtrcnt--;
- goto finished;
- }
-skipfile:
- getfile(null, null, spcl.c_dinode.di_size);
-finished:
- ;
- }
- if (xtrcnt == 0 && !mflag)
- return;
- for (xpp = xtrlist; xpp < &xtrlist[MAXINO]; xpp++) {
- for (xp = *xpp; xp; xp = xp->x_next) {
- if (mflag && (xp->x_flags & XISDIR)) {
- for (itp = inotab[INOHASH(xp->x_ino)];
- itp; itp = itp->t_next) {
- if (itp->t_ino != xp->x_ino)
- continue;
- utime(xp->x_name, itp->t_timep);
- break;
- }
- if (itp == 0)
- fprintf(stderr, "missing dir entry\n");
- }
- if (xp->x_flags & XTRACTD)
- continue;
- if ((xp->x_flags & XLINKED) == 0) {
- fprintf(stderr, "cannot find file %s\n",
- xp->x_name);
- continue;
- }
- if (!mflag)
- continue;
- vprintf(stdout, "link %s to %s\n",
- xp->x_linkedto->x_name, xp->x_name);
- if (link(xp->x_linkedto->x_name, xp->x_name) < 0)
- fprintf(stderr, "link %s to %s failed\n",
- xp->x_linkedto->x_name, xp->x_name);
- }
- }
-}
-
-/*
- * Read the tape, bulding up a directory structure for extraction
- * by name
- */
-pass1()
-{
- register int i;
- register struct dinode *ip;
- struct direct nulldir;
- char buf[TP_BSIZE];
- int putdir(), null(), dirwrite();
-
- nulldir.d_ino = 1;
- nulldir.d_namlen = 1;
- strncpy(nulldir.d_name, "/", nulldir.d_namlen);
- nulldir.d_reclen = DIRSIZ(&nulldir);
- 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:
- fclose(df);
- dirp = opendir(dirfile);
- if (dirp == NULL)
- perror("opendir");
- resetmt();
- return;
- }
- ip = &spcl.c_dinode;
- i = ip->di_mode & IFMT;
- if (i != IFDIR) {
- goto finish;
- }
- allocinotab(spcl.c_inumber, seekpt);
- getfile(putdir, null, spcl.c_dinode.di_size);
- putent(&nulldir, dirwrite);
- flushent(dirwrite);
- }
-}
-
-/*
- * Put the directory entries in the directory file
- */
-putdir(buf, size)
- char *buf;
- int size;
-{
- struct direct cvtbuf;
- register struct odirect *odp;
- struct odirect *eodp;
- register struct direct *dp;
- long loc, i;
-
- if (cvtflag) {
- eodp = (struct odirect *)&buf[size];
- for (odp = (struct odirect *)buf; odp < eodp; odp++)
- if (odp->d_ino != 0) {
- dcvt(odp, &cvtbuf);
- putent(&cvtbuf, dirwrite);
- }
- } else {
- for (loc = 0; loc < size; ) {
- dp = (struct direct *)(buf + loc);
- i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1));
- if (dp->d_reclen <= 0 || dp->d_reclen > i) {
- loc += i;
- continue;
- }
- loc += dp->d_reclen;
- if (dp->d_ino != 0) {
- putent(dp, dirwrite);
- }
- }
- }
-}
-
-/*
- * Recursively find names and inumbers of all files in subtree
- * pname and put them in xtrlist[]
- */
-getleaves(ino, pname)
- ino_t ino;
- char *pname;
-{
- register struct inotab *itp;
- int namelen;
- daddr_t bpt;
- register struct direct *dp;
- char locname[BUFSIZ + 1];
-
- if (BIT(ino, dumpmap) == 0) {
- vprintf(stdout, "%s: not on the tape\n", pname);
- return;
- }
- for (itp = inotab[INOHASH(ino)]; itp; itp = itp->t_next) {
- if (itp->t_ino != ino)
- continue;
- /*
- * pname is a directory name
- */
- (void)allocxtr(ino, pname, XISDIR);
- /*
- * begin search through the directory
- * skipping over "." and ".."
- */
- strncpy(locname, pname, BUFSIZ);
- strncat(locname, "/", BUFSIZ);
- namelen = strlen(locname);
- seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
- dp = readdir(dirp);
- dp = readdir(dirp);
- dp = readdir(dirp);
- bpt = telldir(dirp);
- /*
- * "/" signals end of directory
- */
- while (dp != NULL &&
- !(dp->d_namlen == 1 && dp->d_name[0] == '/')) {
- locname[namelen] = '\0';
- if (namelen + dp->d_namlen >= BUFSIZ) {
- fprintf(stderr, "%s%s: name exceeds %d char\n",
- locname, dp->d_name, BUFSIZ);
- } else {
- strncat(locname, dp->d_name, dp->d_namlen);
- getleaves(dp->d_ino, locname);
- seekdir(dirp, bpt, itp->t_seekpt);
- }
- dp = readdir(dirp);
- bpt = telldir(dirp);
- }
- return;
- }