allow only /bin/csh, not /bin/oldcsh
[unix-history] / usr / src / sbin / restore / main.c
index 91e6126..4b524dc 100644 (file)
@@ -1,39 +1,50 @@
-/* Copyright (c) 1981 Regents of the University of California */
+/* Copyright (c) 1982 Regents of the University of California */
 
 
-char version[] = "@(#)main.c 1.10 %G%";
+#ifndef lint
+char version[] = "@(#)main.c 2.6 %G%";
+#endif
 
 /*     Modified to include h option (recursively extract all files within
  *     a subtree) and m option (recreate the heirarchical structure of
  *     that subtree and move extracted files to their proper homes).
  *     8/29/80         by Mike Litzkow
  *
 
 /*     Modified to include h option (recursively extract all files within
  *     a subtree) and m option (recreate the heirarchical structure of
  *     that subtree and move extracted files to their proper homes).
  *     8/29/80         by Mike Litzkow
  *
+ *     Modified to work on the new file system
+ *     1/19/82         by Kirk McKusick
+ *
  *     Includes the s (skip files) option for use with multiple dumps on
  *     a single tape.
  */
 
  *     Includes the s (skip files) option for use with multiple dumps on
  *     a single tape.
  */
 
-/* static char *sccsid = "@(#)restor.c 4.3 (Berkeley) 6/3/81"; */
-
 #define MAXINO 3000
 #define BITS   8
 #define NCACHE 3
 #define SIZEINC 10
 
 #define MAXINO 3000
 #define BITS   8
 #define NCACHE 3
 #define SIZEINC 10
 
-#ifndef STANDALONE
 #include <stdio.h>
 #include <signal.h>
 #include <stdio.h>
 #include <signal.h>
-#endif
+#include <fstab.h>
+#ifndef SIMFS
+#include <sys/param.h>
+#include <sys/inode.h>
+#include <sys/fs.h>
+#include <dir.h>
+#include <stat.h>
+#include <dumprestor.h>
+#else
 #include "../h/param.h"
 #include "../h/param.h"
+#include "../h/dir.h"
+#include "../h/stat.h"
 #include "../h/inode.h"
 #include "../h/fs.h"
 #include "../h/inode.h"
 #include "../h/fs.h"
-#include "../h/buf.h"
-#include "../h/dir.h"
-#include "../h/user.h"
 #include "../h/dumprestor.h"
 #include "../h/dumprestor.h"
+#endif
 #include <sys/mtio.h>
 
 #include <sys/mtio.h>
 
+#define ODIRSIZ 14
 struct odirect {
        u_short d_ino;
 struct odirect {
        u_short d_ino;
-       char    d_name[DIRSIZ];
+       char    d_name[ODIRSIZ];
 };
 
 #define        MWORD(m,i) (m[(unsigned)(i-1)/NBBY])
 };
 
 #define        MWORD(m,i) (m[(unsigned)(i-1)/NBBY])
@@ -42,13 +53,11 @@ struct odirect {
 #define        BIC(i,w)        (MWORD(w,i) &= ~MBIT(i))
 #define        BIT(i,w)        (MWORD(w,i) & MBIT(i))
 
 #define        BIC(i,w)        (MWORD(w,i) &= ~MBIT(i))
 #define        BIT(i,w)        (MWORD(w,i) & MBIT(i))
 
-ino_t  ino, maxi;
-struct inode *cur_ip;
+ino_t  ino;
 
 int    eflag = 0, hflag = 0, mflag = 0, cvtdir = 0;
 
 
 int    eflag = 0, hflag = 0, mflag = 0, cvtdir = 0;
 
-char   mounted = 0;
-dev_t  dev = 0;
+long   fssize;
 char   tapename[] = "/dev/rmt8";
 char   *magtape = tapename;
 int    mt;
 char   tapename[] = "/dev/rmt8";
 char   *magtape = tapename;
 int    mt;
@@ -58,14 +67,13 @@ int curblk = 0;
 int    bct = NTREC+1;
 char   tbf[NTREC*TP_BSIZE];
 
 int    bct = NTREC+1;
 char   tbf[NTREC*TP_BSIZE];
 
-#ifdef STANDALONE
-char   mbuf[50];
-#endif
-
 daddr_t        seekpt;
 FILE   *df;
 daddr_t        seekpt;
 FILE   *df;
+DIR    *dirp;
 int    ofile;
 int    ofile;
-char   dirfile[] = "rstXXXXXX";
+char   dirfile[] = "/tmp/rstXXXXXX";
+char   lnkbuf[MAXPATHLEN + 1];
+int    pathlen;
 
 #define INOHASH(val) (val % MAXINO)
 struct inotab {
 
 #define INOHASH(val) (val % MAXINO)
 struct inotab {
@@ -89,26 +97,22 @@ struct xtrlist {
 } *xtrlist[MAXINO];
 int xtrcnt = 0;
 
 } *xtrlist[MAXINO];
 int xtrcnt = 0;
 
-#ifdef STANDALONE
-#define msiz 8192
-char   dumpmap[msiz];
-char   clrimap[msiz];
-#else
-int    msiz;
 char   *dumpmap;
 char   *clrimap;
 char   *dumpmap;
 char   *clrimap;
-#endif
 
 char   clearedbuf[MAXBSIZE];
 
 extern char *ctime();
 
 char   clearedbuf[MAXBSIZE];
 
 extern char *ctime();
+extern int seek();
 ino_t search();
 ino_t search();
-char **envp;
+int dirwrite();
+#ifdef RRESTOR
+char *host;
+#endif
 
 
-main(argc, argv, arge)
+main(argc, argv)
        int argc;
        char *argv[];
        int argc;
        char *argv[];
-       char **arge;
 {
        register char *cp;
        char command;
 {
        register char *cp;
        char command;
@@ -119,9 +123,7 @@ main(argc, argv, arge)
                signal(SIGINT, SIG_IGN);
        if (signal(SIGTERM, done) == SIG_IGN)
                signal(SIGTERM, SIG_IGN);
                signal(SIGINT, SIG_IGN);
        if (signal(SIGTERM, done) == SIG_IGN)
                signal(SIGTERM, SIG_IGN);
-#ifndef STANDALONE
-       envp = arge;
-       mktmp(dirfile);
+       mktemp(dirfile);
        if (argc < 2) {
 usage:
                fprintf(stderr, "Usage: restor x[s|m|h|v] file file..., restor r|R filesys, or restor t\n");
        if (argc < 2) {
 usage:
                fprintf(stderr, "Usage: restor x[s|m|h|v] file file..., restor r|R filesys, or restor t\n");
@@ -135,12 +137,26 @@ usage:
                        break;
                case 'f':
                        magtape = *argv++;
                        break;
                case 'f':
                        magtape = *argv++;
+#ifdef RRESTOR
+               { char *index();
+                 host = magtape;
+                 magtape = index(host, ':');
+                 if (magtape == 0) {
+nohost:
+                       msg("need keyletter ``f'' and device ``host:tape''");
+                       done(1);
+                 }
+                 *magtape++ = 0;
+                 if (rmthost(host) == 0)
+                       done(1);
+               }
+#endif
                        argc--;
                        break;
                /* s dumpnum (skip to) for multifile dump tapes */
                case 's':
                        dumpnum = atoi(*argv++);
                        argc--;
                        break;
                /* s dumpnum (skip to) for multifile dump tapes */
                case 's':
                        dumpnum = atoi(*argv++);
-                       if(dumpnum <= 0) {
+                       if (dumpnum <= 0) {
                                fprintf(stderr, "Dump number must be a positive integer\n");
                                done(1);
                        }
                                fprintf(stderr, "Dump number must be a positive integer\n");
                                done(1);
                        }
@@ -154,6 +170,8 @@ usage:
                        break;
                case 'r':
                case 'R':
                        break;
                case 'r':
                case 'R':
+                       hflag++;
+                       mflag++;
                case 't':
                case 'x':
                        command = *cp;
                case 't':
                case 'x':
                        command = *cp;
@@ -163,21 +181,12 @@ usage:
                        goto usage;
                }
        }
                        goto usage;
                }
        }
-       if (command == 'x') {
-               df = fopen(dirfile, "w");
-               if (df == 0) {
-                       fprintf(stderr, "restor: %s - cannot create directory temporary\n", dirfile);
-                       done(1);
-               }
-               xmount(envp);
-               mounted++;
-       }
+#ifdef RRESTOR
+       if (host == 0)
+               goto nohost;
+#endif
        doit(command, argc, argv);
        done(0);
        doit(command, argc, argv);
        done(0);
-#else
-       magtape = "tape";
-       doit('r', 1, 0);
-#endif
 }
 
 doit(command, argc, argv)
 }
 
 doit(command, argc, argv)
@@ -187,28 +196,26 @@ doit(command, argc, argv)
 {
        struct mtop tcom;
 
 {
        struct mtop tcom;
 
-#ifndef STANDALONE
+#ifdef RRESTOR
+       if ((mt = rmtopen(magtape, 0)) < 0) {
+#else
        if ((mt = open(magtape, 0)) < 0) {
        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;
                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");
                if (ioctl(mt,MTIOCTOP,&tcom) < 0)
                        perror("ioctl MTFSF");
-       }
-#else
-       do {
-               fprintf(stderr, "Tape? ");
-               gets(mbuf);
-               mt = open(mbuf, 0);
-       } while (mt == -1);
-       magtape = mbuf;
 #endif
 #endif
-       blkclr(clearedbuf, MAXBSIZE);
+       }
+       blkclr(clearedbuf, (long)MAXBSIZE);
        switch(command) {
        switch(command) {
-#ifndef STANDALONE
        case 't':
                if (readhdr(&spcl) == 0) {
                        fprintf(stderr, "Tape is not a dump tape\n");
        case 't':
                if (readhdr(&spcl) == 0) {
                        fprintf(stderr, "Tape is not a dump tape\n");
@@ -217,18 +224,23 @@ doit(command, argc, argv)
                fprintf(stdout, "Dump   date: %s", ctime(&spcl.c_date));
                fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate));
                return;
                fprintf(stdout, "Dump   date: %s", ctime(&spcl.c_date));
                fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate));
                return;
+       case 'R':
+       case 'r':
+               setdir(*argv);
+               argc = 1;
+               *argv = ".";
+               /* and then extract it all */
        case 'x':
        case 'x':
+               df = fopen(dirfile, "w");
+               if (df == 0) {
+                       fprintf(stderr, "restor: %s - cannot create directory temporary\n", dirfile);
+                       done(1);
+               }
                extractfiles(argc, argv);
                return;
                extractfiles(argc, argv);
                return;
-#endif
-       case 'r':
-       case 'R':
-               restorfiles(command, argv);
-               return;
        }
 }
 
        }
 }
 
-#ifndef STANDALONE
 extractfiles(argc, argv)
        int argc;
        char **argv;
 extractfiles(argc, argv)
        int argc;
        char **argv;
@@ -236,12 +248,23 @@ extractfiles(argc, argv)
        char    *ststore();
        register struct xtrlist *xp;
        struct xtrlist **xpp;
        char    *ststore();
        register struct xtrlist *xp;
        struct xtrlist **xpp;
-       struct fs *fs;
        ino_t   d;
        ino_t   d;
-       int     xtrfile(), xtrskip(), xtrcvtdir(), xtrcvtskip(), null();
-       int     mode;
+       int     xtrfile(), xtrskip(), xtrcvtdir(), xtrcvtskip(),
+               xtrlnkfile(), xtrlnkskip(), null();
+       int     mode, uid, gid, i;
        char    name[BUFSIZ + 1];
        char    name[BUFSIZ + 1];
+       struct  stat stbuf;
 
 
+       if (stat(".", &stbuf) < 0) {
+               fprintf(stderr, "cannot stat .\n");
+               done(1);
+       }
+       /*
+        * should be!!!
+        *
+       fssize = stbuf.st_blksize;
+        */
+       fssize = MAXBSIZE;
        if (readhdr(&spcl) == 0) {
                fprintf(stderr, "Tape is not a dump tape\n");
                done(1);
        if (readhdr(&spcl) == 0) {
                fprintf(stderr, "Tape is not a dump tape\n");
                done(1);
@@ -249,19 +272,18 @@ extractfiles(argc, argv)
        if (checkvol(&spcl, 1) == 0) {
                fprintf(stderr, "Tape is not volume 1 of the dump\n");
        }
        if (checkvol(&spcl, 1) == 0) {
                fprintf(stderr, "Tape is not volume 1 of the dump\n");
        }
-       fs = getfs(dev);
-       msiz = roundup(howmany(fs->fs_ipg * fs->fs_ncg, NBBY), TP_BSIZE);
-       clrimap = (char *)calloc(msiz, sizeof(char));
-       dumpmap = (char *)calloc(msiz, sizeof(char));
+       clrimap = 0;
+       dumpmap = 0;
        pass1(1);  /* This sets the various maps on the way by */
        while (argc--) {
                if ((d = psearch(*argv)) == 0 || BIT(d,dumpmap) == 0) {
        pass1(1);  /* This sets the various maps on the way by */
        while (argc--) {
                if ((d = psearch(*argv)) == 0 || BIT(d,dumpmap) == 0) {
+                       printf("d = %d\n", d);
                        fprintf(stdout, "%s: not on tape\n", *argv++);
                        continue;
                }
                if (mflag)
                        checkdir(*argv);
                        fprintf(stdout, "%s: not on tape\n", *argv++);
                        continue;
                }
                if (mflag)
                        checkdir(*argv);
-               if(hflag)
+               if (hflag)
                        getleaves(d, *argv++);
                else
                        allocxtr(d, *argv++, XINUSE);
                        getleaves(d, *argv++);
                else
                        allocxtr(d, *argv++, XINUSE);
@@ -279,7 +301,11 @@ extractfiles(argc, argv)
                goto rbits;
        }
 newvol:
                goto rbits;
        }
 newvol:
-       resetmt();
+#ifdef RRESTOR
+       rmtclose();
+#else
+       close(mt);
+#endif
 getvol:
        fprintf(stderr, "Mount desired tape volume; Specify volume #: ");
        if (gets(tbf) == NULL)
 getvol:
        fprintf(stderr, "Mount desired tape volume; Specify volume #: ");
        if (gets(tbf) == NULL)
@@ -289,6 +315,16 @@ getvol:
                fprintf(stderr, "Volume numbers are positive numerics\n");
                goto getvol;
        }
                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 (readhdr(&spcl) == 0) {
                fprintf(stderr, "tape is not dump tape\n");
                goto newvol;
@@ -306,12 +342,16 @@ rbits:
        }
        if (checktype(&spcl, TS_BITS) == 0)
                goto rbits;
        }
        if (checktype(&spcl, TS_BITS) == 0)
                goto rbits;
-       readbits(dumpmap);
+       readbits(&dumpmap);
        while (xtrcnt > 0) {
 again:
        while (xtrcnt > 0) {
 again:
-               if (ishead(&spcl) == 0)
-                       while(gethead(&spcl) == 0)
-                               ;
+               if (ishead(&spcl) == 0) {
+                       i = 0;
+                       while (gethead(&spcl) == 0)
+                               i++;
+                       fprintf(stderr, "resync restor, skipped %i blocks\n",
+                           i);
+               }
                if (checktype(&spcl, TS_END) == 1) {
                        fprintf(stderr, "end of tape\n");
                        break;
                if (checktype(&spcl, TS_END) == 1) {
                        fprintf(stderr, "end of tape\n");
                        break;
@@ -335,14 +375,15 @@ again:
                                sprintf(name, "%u", xp->x_ino);
                        switch (mode & IFMT) {
                        default:
                                sprintf(name, "%u", xp->x_ino);
                        switch (mode & IFMT) {
                        default:
-                               fprintf(stderr, "%s: unknown file type\n", name);
+                               fprintf(stderr, "%s: unknown file mode 0%o\n",
+                                   name, mode);
                                xp->x_flags |= XTRACTD;
                                xtrcnt--;
                                goto skipfile;
                        case IFCHR:
                        case IFBLK:
                                fprintf(stdout, "extract special file %s\n", name);
                                xp->x_flags |= XTRACTD;
                                xtrcnt--;
                                goto skipfile;
                        case IFCHR:
                        case IFBLK:
                                fprintf(stdout, "extract special file %s\n", name);
-                               if (xmknod(name, mode, spcl.c_dinode.di_rdev)) {
+                               if (mknod(name, mode, spcl.c_dinode.di_rdev)) {
                                        fprintf(stderr, "%s: cannot create special file\n", name);
                                        xp->x_flags |= XTRACTD;
                                        xtrcnt--;
                                        fprintf(stderr, "%s: cannot create special file\n", name);
                                        xp->x_flags |= XTRACTD;
                                        xtrcnt--;
@@ -355,41 +396,57 @@ again:
                                        fprintf(stdout, "extract directory %s\n", name);
                                        strncat(name, "/.", BUFSIZ);
                                        checkdir(name);
                                        fprintf(stdout, "extract directory %s\n", name);
                                        strncat(name, "/.", BUFSIZ);
                                        checkdir(name);
-                                       xchown(xp->x_name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
+                                       chown(xp->x_name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
                                        getfile(null, null, spcl.c_dinode.di_size);
                                        break;
                                }
                                fprintf(stdout, "extract file %s\n", name);
                                        getfile(null, null, spcl.c_dinode.di_size);
                                        break;
                                }
                                fprintf(stdout, "extract file %s\n", name);
-                               if ((ofile = xcreat(name, 0666)) < 0) {
+                               if ((ofile = creat(name, 0666)) < 0) {
                                        fprintf(stderr, "%s: cannot create file\n", name);
                                        xp->x_flags |= XTRACTD;
                                        xtrcnt--;
                                        goto skipfile;
                                }
                                        fprintf(stderr, "%s: cannot create file\n", name);
                                        xp->x_flags |= XTRACTD;
                                        xtrcnt--;
                                        goto skipfile;
                                }
-                               xchown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
-                               if (cvtdir)
+                               chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
+                               if (cvtdir) {
                                        getfile(xtrcvtdir, xtrcvtskip,
                                            spcl.c_dinode.di_size);
                                        getfile(xtrcvtdir, xtrcvtskip,
                                            spcl.c_dinode.di_size);
-                               else
+                                       flushent(xtrfile);
+                               } else
                                        getfile(xtrfile, xtrskip,
                                            spcl.c_dinode.di_size);
                                        getfile(xtrfile, xtrskip,
                                            spcl.c_dinode.di_size);
-                               xclose(ofile);
+                               close(ofile);
+                               break;
+                       case IFLNK:
+                               fprintf(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:
                                fprintf(stdout, "extract file %s\n", name);
                                break;
                        case IFREG:
                                fprintf(stdout, "extract file %s\n", name);
-                               if ((ofile = xcreat(name, 0666)) < 0) {
+                               if ((ofile = creat(name, 0666)) < 0) {
                                        fprintf(stderr, "%s: cannot create file\n", name);
                                        xp->x_flags |= XTRACTD;
                                        xtrcnt--;
                                        goto skipfile;
                                }
                                        fprintf(stderr, "%s: cannot create file\n", name);
                                        xp->x_flags |= XTRACTD;
                                        xtrcnt--;
                                        goto skipfile;
                                }
-                               xchown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
+                               chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
                                getfile(xtrfile, xtrskip, spcl.c_dinode.di_size);
                                getfile(xtrfile, xtrskip, spcl.c_dinode.di_size);
-                               xclose(ofile);
+                               close(ofile);
                                break;
                        }
                                break;
                        }
-                       xchmod(name, mode);
-                       xutime(name, xp->x_timep);
+                       chmod(name, mode);
+                       utime(name, xp->x_timep);
                        xp->x_flags |= XTRACTD;
                        xtrcnt--;
                        goto finished;
                        xp->x_flags |= XTRACTD;
                        xtrcnt--;
                        goto finished;
@@ -404,7 +461,7 @@ finished:
        for (xpp = xtrlist; xpp < &xtrlist[MAXINO]; xpp++) {
                for (xp = *xpp; xp; xp = xp->x_next) {
                        if (mflag && (xp->x_flags & XISDIR))
        for (xpp = xtrlist; xpp < &xtrlist[MAXINO]; xpp++) {
                for (xp = *xpp; xp; xp = xp->x_next) {
                        if (mflag && (xp->x_flags & XISDIR))
-                               xutime(xp->x_name, xp->x_timep);
+                               utime(xp->x_name, xp->x_timep);
                        if (xp->x_flags & XTRACTD)
                                continue;
                        if ((xp->x_flags & XLINKED) == 0) {
                        if (xp->x_flags & XTRACTD)
                                continue;
                        if ((xp->x_flags & XLINKED) == 0) {
@@ -416,178 +473,17 @@ finished:
                                continue;
                        fprintf(stdout, "link %s to %s\n",
                                xp->x_linkedto->x_name, xp->x_name);
                                continue;
                        fprintf(stdout, "link %s to %s\n",
                                xp->x_linkedto->x_name, xp->x_name);
-                       if (xlink(xp->x_linkedto->x_name, xp->x_name) < 0)
+                       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);
                }
        }
 }
                                fprintf(stderr, "link %s to %s failed\n",
                                        xp->x_linkedto->x_name, xp->x_name);
                }
        }
 }
-#endif
-
-restorfiles(command, argv)
-       char command;
-       char **argv;
-{
-       int     rstrfile(), rstrskip(), rstrcvtdir(), rstrcvtskip();
-       register struct dinode *dp;
-       register struct inode *ip;
-       struct fs *fs;
-       int mode, type;
-       char mount[BUFSIZ + 1];
-       char *ptr[2];
-
-       mount[0] = '\0';
-       strcpy(mount, "MOUNT=");
-#ifndef STANDALONE
-       strncat(mount, *argv, BUFSIZ);
-#else
-       fprintf(stderr, "Disk? ");
-       gets(&mount[6]);
-#endif
-       ptr[0] = mount;
-       ptr[1] = 0;
-       xmount(ptr);
-       mounted++;
-       iput(u.u_cdir); /* release root inode */
-       iput(u.u_rdir); /* release root inode */
-       fs = getfs(dev);
-       maxi = fs->fs_ipg * fs->fs_ncg;
-#ifndef STANDALONE
-       msiz = roundup(howmany(maxi, NBBY), TP_BSIZE);
-       clrimap = (char *)calloc(msiz, sizeof(char));
-       dumpmap = (char *)calloc(msiz, sizeof(char));
-       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');
-       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);
-       }
-       pass1(0);
-       gethead(&spcl); /* volume header already checked above */
-       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);
-                       /*
-                        * if throwing away the root inode, must also
-                        * discard the predefined lost+found directory.
-                        */
-                       if (BIT(ROOTINO, clrimap))
-                               BIS(LOSTFOUNDINO + 1, clrimap);
-                       for (ino = ROOTINO; 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;
-               type = ip->i_mode & IFMT;
-               if (type == IFCHR || type == IFBLK)
-                       ip->i_rdev = dp->di_rdev;
-               ip->i_size = 0;
-               cur_ip = ip;
-               u.u_offset = 0;
-               u.u_segflg = 1;
-               if (cvtdir && type == IFDIR)
-                       getfile(rstrcvtdir, rstrcvtskip, dp->di_size);
-               else
-                       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
  */
 
 /*
  * Read the tape, bulding up a directory structure for extraction
  * by name
  */
-#ifndef STANDALONE
 pass1(savedir)
        int savedir;
 {
 pass1(savedir)
        int savedir;
 {
@@ -595,26 +491,32 @@ pass1(savedir)
        register struct dinode *ip;
        struct direct nulldir;
        char buf[TP_BSIZE];
        register struct dinode *ip;
        struct direct nulldir;
        char buf[TP_BSIZE];
-       int putdir(), null();
+       int putdir(), null(), dirwrite();
 
 
-       nulldir.d_ino = 0;
-       strncpy(nulldir.d_name, "/", DIRSIZ);
+       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) {
        while (gethead(&spcl) == 0) {
                fprintf(stderr, "Can't find directory header!\n");
        }
        for (;;) {
                if (checktype(&spcl, TS_BITS) == 1) {
-                       readbits(dumpmap);
+                       readbits(&dumpmap);
                        continue;
                }
                if (checktype(&spcl, TS_CLRI) == 1) {
                        continue;
                }
                if (checktype(&spcl, TS_CLRI) == 1) {
-                       readbits(clrimap);
+                       readbits(&clrimap);
                        continue;
                }
                if (checktype(&spcl, TS_INODE) == 0) {
 finish:
                        continue;
                }
                if (checktype(&spcl, TS_INODE) == 0) {
 finish:
-                       if (savedir)
-                               freopen(dirfile, "r", df);
+                       if (savedir) {
+                               fclose(df);
+                               dirp = opendir(dirfile);
+                               if (dirp == NULL)
+                                       perror("opendir");
+                       }
                        resetmt();
                        return;
                }
                        resetmt();
                        return;
                }
@@ -642,18 +544,17 @@ finish:
                allocinotab(spcl.c_inumber, seekpt);
                if (savedir) {
                        getfile(putdir, null, spcl.c_dinode.di_size);
                allocinotab(spcl.c_inumber, seekpt);
                if (savedir) {
                        getfile(putdir, null, spcl.c_dinode.di_size);
-                       putent(&nulldir);
+                       putent(&nulldir, dirwrite);
+                       flushent(dirwrite);
                } else {
                        getfile(null, null, spcl.c_dinode.di_size);
                }
        }
 }
                } else {
                        getfile(null, null, spcl.c_dinode.di_size);
                }
        }
 }
-#endif
 
 /*
  * Put the directory entries in the directory file
  */
 
 /*
  * Put the directory entries in the directory file
  */
-#ifndef STANDALONE
 putdir(buf, size)
        char *buf;
        int size;
 putdir(buf, size)
        char *buf;
        int size;
@@ -662,44 +563,28 @@ putdir(buf, size)
        register struct odirect *odp;
        struct odirect *eodp;
        register struct direct *dp;
        register struct odirect *odp;
        struct odirect *eodp;
        register struct direct *dp;
-       struct direct *edp;
+       long loc, i;
 
        if (cvtdir) {
                eodp = (struct odirect *)&buf[size];
                for (odp = (struct odirect *)buf; odp < eodp; odp++)
                        if (odp->d_ino != 0) {
                                dcvt(odp, &cvtbuf);
 
        if (cvtdir) {
                eodp = (struct odirect *)&buf[size];
                for (odp = (struct odirect *)buf; odp < eodp; odp++)
                        if (odp->d_ino != 0) {
                                dcvt(odp, &cvtbuf);
-                               putent(&cvtbuf);
+                               putent(&cvtbuf, dirwrite);
                        }
        } else {
                        }
        } else {
-               edp = (struct direct *)&buf[size];
-               for (dp = (struct direct *)buf; dp < edp; dp++)
-                       if (dp->d_ino != 0)
-                               putent(dp);
-       }
-}
-
-putent(dp)
-       struct direct *dp;
-{
-       fwrite(dp, 1, sizeof(struct direct), df);
-       seekpt = ftell(df);
-}
-
-dcvt(odp, ndp)
-       register struct odirect *odp;
-       register struct direct *ndp;
-{
-       register struct inotab *itp;
-
-       blkclr(ndp, sizeof *ndp);
-       ndp->d_ino =  odp->d_ino;
-       strncpy(ndp->d_name, odp->d_name, DIRSIZ);
-       for (itp = inotab[INOHASH(odp->d_ino)]; itp; itp = itp->t_next) {
-               if (itp->t_ino != odp->d_ino)
-                       continue;
-               ndp->d_fmt = IFDIR;
-               break;
+               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);
+                       }
+               }
        }
 }
 
        }
 }
 
@@ -713,9 +598,9 @@ getleaves(ino, pname)
 {
        register struct inotab *itp;
        int namelen;
 {
        register struct inotab *itp;
        int namelen;
-       daddr_t bpt;
-       struct direct dir;
-       char    locname[BUFSIZ + 1];
+       daddr_t bpt;
+       register struct direct *dp;
+       char locname[BUFSIZ + 1];
 
        if (BIT(ino, dumpmap) == 0) {
                fprintf(stdout, "%s: not on the tape\n", pname);
 
        if (BIT(ino, dumpmap) == 0) {
                fprintf(stdout, "%s: not on the tape\n", pname);
@@ -735,26 +620,26 @@ getleaves(ino, pname)
                strncpy(locname, pname, BUFSIZ);
                strncat(locname, "/", BUFSIZ);
                namelen = strlen(locname);
                strncpy(locname, pname, BUFSIZ);
                strncat(locname, "/", BUFSIZ);
                namelen = strlen(locname);
-               fseek(df, itp->t_seekpt, 0);
-               fread(&dir, 1, sizeof(struct direct), df);
-               fread(&dir, 1, sizeof(struct direct), df);
-               fread(&dir, 1, sizeof(struct direct), df);
-               bpt = ftell(df);
+               seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
+               dp = readdir(dirp);
+               dp = readdir(dirp);
+               dp = readdir(dirp);
+               bpt = telldir(dirp);
                /*
                 * "/" signals end of directory
                 */
                /*
                 * "/" signals end of directory
                 */
-               while (strncmp(dir.d_name, "/", DIRSIZ)) {
+               while (dp->d_namlen != 1 || dp->d_name[0] != '/') {
                        locname[namelen] = '\0';
                        locname[namelen] = '\0';
-                       strncat(locname, dir.d_name, DIRSIZ);
-                       if (strlen(locname) >= BUFSIZ) {
-                               fprintf(stderr, "%s: name exceedes %d char\n",
-                                       locname, BUFSIZ);
+                       if (namelen + dp->d_namlen >= BUFSIZ) {
+                               fprintf(stderr, "%s%s: name exceedes %d char\n",
+                                       locname, dp->d_name, BUFSIZ);
                                continue;
                        }
                                continue;
                        }
-                       getleaves(dir.d_ino, locname);
-                       fseek(df, bpt, 0);
-                       fread(&dir, 1, sizeof(struct direct), df);
-                       bpt = ftell(df);
+                       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;
        }
                }
                return;
        }
@@ -805,23 +690,24 @@ search(inum, cp)
        ino_t   inum;
        char    *cp;
 {
        ino_t   inum;
        char    *cp;
 {
-       struct direct dir;
+       register struct direct *dp;
        register struct inotab *itp;
        register struct inotab *itp;
+       int len;
 
        for (itp = inotab[INOHASH(inum)]; itp; itp = itp->t_next)
                if (itp->t_ino == inum)
                        goto found;
        return(0);
 found:
 
        for (itp = inotab[INOHASH(inum)]; itp; itp = itp->t_next)
                if (itp->t_ino == inum)
                        goto found;
        return(0);
 found:
-       fseek(df, itp->t_seekpt, 0);
+       seekdir(dirp, itp->t_seekpt, itp->t_seekpt);
+       len = strlen(cp);
        do {
        do {
-               fread(&dir, 1, sizeof(struct direct), df);
-               if (!strncmp(dir.d_name, "/", DIRSIZ))
+               dp = readdir(dirp);
+               if (dp->d_namlen == 1 && dp->d_name[0] == '/')
                        return(0);
                        return(0);
-       } while (strncmp(dir.d_name, cp, DIRSIZ));
-       return(dir.d_ino);
+       } while (dp->d_namlen != len || strncmp(dp->d_name, cp, len));
+       return(dp->d_ino);
 }
 }
-#endif
 
 /*
  * Do the file extraction, calling the supplied functions
 
 /*
  * Do the file extraction, calling the supplied functions
@@ -829,23 +715,21 @@ found:
  */
 getfile(f1, f2, size)
        int     (*f2)(), (*f1)();
  */
 getfile(f1, f2, size)
        int     (*f2)(), (*f1)();
-       long    size;
+       off_t   size;
 {
        register int i;
        char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
        union u_spcl addrblk;
 {
        register int i;
        char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
        union u_spcl addrblk;
-       register struct fs *fs;
 #      define addrblock addrblk.s_spcl
 
        addrblock = spcl;
 #      define addrblock addrblk.s_spcl
 
        addrblock = spcl;
-       fs = getfs(dev);
        for (;;) {
                for (i = 0; i < addrblock.c_count; i++) {
                        if (addrblock.c_addr[i]) {
                                readtape(&buf[curblk++][0]);
        for (;;) {
                for (i = 0; i < addrblock.c_count; i++) {
                        if (addrblock.c_addr[i]) {
                                readtape(&buf[curblk++][0]);
-                               if (curblk == BLKING(fs) * fs->fs_frag) {
+                               if (curblk == fssize / TP_BSIZE) {
                                        (*f1)(buf, size > TP_BSIZE ?
                                        (*f1)(buf, size > TP_BSIZE ?
-                                            (long) (BLKING(fs) * fs->fs_frag * TP_BSIZE) :
+                                            (long) (fssize) :
                                             (curblk - 1) * TP_BSIZE + size);
                                        curblk = 0;
                                }
                                             (curblk - 1) * TP_BSIZE + size);
                                        curblk = 0;
                                }
@@ -888,12 +772,12 @@ out:
  * The next routines are called during file extraction to
  * put the data into the right form and place.
  */
  * 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;
 {
 xtrfile(buf, size)
        char    *buf;
        long    size;
 {
-       if (xwrite(ofile, buf, (int) size) == -1) {
+
+       if (write(ofile, buf, (int) size) == -1) {
                perror("extract write");
                done(1);
        }
                perror("extract write");
                done(1);
        }
@@ -903,7 +787,11 @@ xtrskip(buf, size)
        char *buf;
        long size;
 {
        char *buf;
        long size;
 {
-       if (xseek(ofile, size, 1) == -1) {
+
+#ifdef lint
+       buf = buf;
+#endif
+       if (lseek(ofile, size, 1) == -1) {
                perror("extract seek");
                done(1);
        }
                perror("extract seek");
                done(1);
        }
@@ -913,18 +801,13 @@ xtrcvtdir(buf, size)
        struct odirect *buf;
        long size;
 {
        struct odirect *buf;
        long size;
 {
-       struct direct
-               cvtbuf[MAXBSIZE / sizeof(struct odirect)];
        struct odirect *odp, *edp;
        struct odirect *odp, *edp;
-       struct direct *dp;
+       struct direct cvtbuf;
 
        edp = &buf[size / sizeof(struct odirect)];
 
        edp = &buf[size / sizeof(struct odirect)];
-       for (odp = buf, dp = cvtbuf; odp < edp; odp++, dp++) 
-               dcvt(odp, dp);
-       size = size * sizeof(struct direct) / sizeof(struct odirect);
-       if (xwrite(ofile, cvtbuf, (int) size) == -1) {
-               perror("extract write");
-               done(1);
+       for (odp = buf; odp < edp; odp++) {
+               dcvt(odp, &cvtbuf);
+               putent(&cvtbuf, xtrfile);
        }
 }
 
        }
 }
 
@@ -932,61 +815,35 @@ xtrcvtskip(buf, size)
        char *buf;
        long size;
 {
        char *buf;
        long size;
 {
-       fprintf(stderr, "unallocated block in directory\n");
-       if (xseek(ofile, size, 1) == -1) {
-               perror("extract seek");
-               done(1);
-       }
-}
-#endif
-
-rstrfile(buf, size)
-       char *buf;
-       long size;
-{
-       u.u_base = buf;
-       u.u_count = size;
-       writei(cur_ip);
-       if (u.u_error) {
-               perror("restor write");
-               done(1);
-       }
-}
 
 
-rstrskip(buf, size)
-       char *buf;
-       long size;
-{
-       u.u_offset += size;
+       fprintf(stderr, "unallocated block in directory\n");
+       xtrskip(buf, size);
 }
 
 }
 
-rstrcvtdir(buf, size)
-       struct odirect *buf;
-       long size;
+xtrlnkfile(buf, size)
+       char    *buf;
+       long    size;
 {
 {
-       struct direct
-               cvtbuf[MAXBSIZE / sizeof(struct odirect)];
-       struct odirect *odp, *edp;
-       struct direct *dp;
 
 
-       edp = &buf[size / sizeof(struct odirect)];
-       for (odp = buf, dp = cvtbuf; odp < edp; odp++, dp++) 
-               dcvt(odp, dp);
-       u.u_base = (char *)cvtbuf;
-       u.u_count = size * sizeof(struct direct) / sizeof(struct odirect);
-       writei(cur_ip);
-       if (u.u_error) {
-               perror("restor write");
+       pathlen += size;
+       if (pathlen > MAXPATHLEN) {
+               fprintf(stderr, "symbolic link name: %s; too long %d\n",
+                   buf, size);
                done(1);
        }
                done(1);
        }
+       strcat(lnkbuf, buf);
 }
 
 }
 
-rstrcvtskip(buf, size)
+xtrlnkskip(buf, size)
        char *buf;
        long size;
 {
        char *buf;
        long size;
 {
-       fprintf(stderr, "unallocated block in directory\n");
-       u.u_offset += size;
+
+#ifdef lint
+       buf = buf, size = size;
+#endif
+       fprintf(stderr, "unallocated block in symbolic link\n");
+       done(1);
 }
 
 null() {;}
 }
 
 null() {;}
@@ -998,28 +855,58 @@ null() {;}
 readtape(b)
        char *b;
 {
 readtape(b)
        char *b;
 {
-       register int i;
-       struct s_spcl tmpbuf;
+       register long i;
+       struct u_spcl tmpbuf;
+       char c;
 
        if (bct >= NTREC) {
                for (i = 0; i < NTREC; i++)
                        ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0;
                bct = 0;
 
        if (bct >= NTREC) {
                for (i = 0; i < NTREC; i++)
                        ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0;
                bct = 0;
+#ifdef RRESTOR
+               if ((i = rmtread(tbf, NTREC*TP_BSIZE)) < 0) {
+#else
                if ((i = read(mt, tbf, NTREC*TP_BSIZE)) < 0) {
                if ((i = read(mt, tbf, NTREC*TP_BSIZE)) < 0) {
-                       perror("Tape read error");
+#endif
+                       fprintf(stderr, "Tape read error, continue?");
+                       do      {
+                               fprintf(stderr, "[yn]\n");
+                               c = getchar();
+                               while (getchar() != '\n')
+                                       /* void */;
+                       } while (c != 'y' && c != 'n');
                        eflag++;
                        eflag++;
-                       done(1);
+                       if (c == 'n')
+                               done(1);
+                       i = NTREC*TP_BSIZE;
+                       blkclr(tbf, i);
+#ifdef RRESTOR
+                       if (rmtseek(i, 1) < 0) {
+#else
+                       if (lseek(mt, i, 1) < 0) {
+#endif
+                               fprintf(stderr, "continuation failed\n");
+                               done(1);
+                       }
                }
                if (i == 0) {
                        bct = NTREC + 1;
                        volno++;
 loop:
                        flsht();
                }
                if (i == 0) {
                        bct = NTREC + 1;
                        volno++;
 loop:
                        flsht();
+#ifdef RRESTOR
+                       rmtclose();
+#else
                        close(mt);
                        close(mt);
+#endif
                        fprintf(stderr, "Mount volume %d\n", volno);
                        while (getchar() != '\n')
                                ;
                        fprintf(stderr, "Mount volume %d\n", volno);
                        while (getchar() != '\n')
                                ;
+#ifdef RRESTOR
+                       if ((mt = rmtopen(magtape, 0)) == -1) {
+#else
                        if ((mt = open(magtape, 0)) == -1) {
                        if ((mt = open(magtape, 0)) == -1) {
+#endif
                                fprintf(stderr, "Cannot open tape!\n");
                                goto loop;
                        }
                                fprintf(stderr, "Cannot open tape!\n");
                                goto loop;
                        }
@@ -1035,29 +922,34 @@ loop:
                        return;
                }
        }
                        return;
                }
        }
-       copy(&tbf[(bct++*TP_BSIZE)], b, TP_BSIZE);
+       blkcpy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
 }
 
 flsht()
 {
 }
 
 flsht()
 {
+
        bct = NTREC+1;
 }
 
        bct = NTREC+1;
 }
 
-copy(f, t, s)
-       register char *f, *t;
+blkcpy(from, to, size)
+       char *from, *to;
+       long size;
 {
 {
-       register int i;
 
 
-       i = s;
-       do
-               *t++ = *f++;
-       while (--i);
+#ifdef lint
+       from = from, to = to, size = size;
+#endif
+       asm("   movc3   12(ap),*4(ap),*8(ap)");
 }
 
 blkclr(buf, size)
        char *buf;
 }
 
 blkclr(buf, size)
        char *buf;
-       int size;
+       long size;
 {
 {
+
+#ifdef lint
+       buf = buf, size = size;
+#endif
        asm("movc5      $0,(r0),$0,8(ap),*4(ap)");
 }
 
        asm("movc5      $0,(r0),$0,8(ap),*4(ap)");
 }
 
@@ -1065,20 +957,31 @@ resetmt()
 {
        struct mtop tcom;
 
 {
        struct mtop tcom;
 
-       if(dumpnum > 1)
+       if (dumpnum > 1)
                tcom.mt_op = MTBSF;
        else
                tcom.mt_op = MTREW;
        tcom.mt_count = 1;
        flsht();
                tcom.mt_op = MTBSF;
        else
                tcom.mt_op = MTREW;
        tcom.mt_count = 1;
        flsht();
+#ifdef RRESTOR
+       if (rmtioctl(tcom.mt_op, 1) == -1) {
+               /* kludge for disk dumps */
+               rmtseek((long)0, 0);
+       }
+#else
        if (ioctl(mt,MTIOCTOP,&tcom) == -1) {
                /* kludge for disk dumps */
                lseek(mt, (long)0, 0);
        }
        if (ioctl(mt,MTIOCTOP,&tcom) == -1) {
                /* kludge for disk dumps */
                lseek(mt, (long)0, 0);
        }
+#endif
        if (dumpnum > 1) {
        if (dumpnum > 1) {
+#ifdef RRESTOR
+               rmtioctl(MTFSF, 1);
+#else
                tcom.mt_op = MTFSF;
                tcom.mt_count = 1;
                ioctl(mt,MTIOCTOP,&tcom);
                tcom.mt_op = MTFSF;
                tcom.mt_count = 1;
                ioctl(mt,MTIOCTOP,&tcom);
+#endif
        }
 }
 
        }
 }
 
@@ -1086,6 +989,7 @@ checkvol(b, t)
        struct s_spcl *b;
        int t;
 {
        struct s_spcl *b;
        int t;
 {
+
        if (b->c_volume == t)
                return(1);
        return(0);
        if (b->c_volume == t)
                return(1);
        return(0);
@@ -1094,6 +998,7 @@ checkvol(b, t)
 readhdr(b)
        struct s_spcl *b;
 {
 readhdr(b)
        struct s_spcl *b;
 {
+
        if (gethead(b) == 0)
                return(0);
        if (checktype(b, TS_TAPE) == 0)
        if (gethead(b) == 0)
                return(0);
        if (checktype(b, TS_TAPE) == 0)
@@ -1108,6 +1013,7 @@ readhdr(b)
 gethead(buf)
        struct s_spcl *buf;
 {
 gethead(buf)
        struct s_spcl *buf;
 {
+
        readtape((char *)buf);
        if (buf->c_magic != MAGIC || checksum((int *)buf) == 0)
                return(0);
        readtape((char *)buf);
        if (buf->c_magic != MAGIC || checksum((int *)buf) == 0)
                return(0);
@@ -1120,6 +1026,7 @@ gethead(buf)
 ishead(buf)
        struct s_spcl *buf;
 {
 ishead(buf)
        struct s_spcl *buf;
 {
+
        if (buf->c_magic != MAGIC || checksum((int *)buf) == 0)
                return(0);
        return(1);
        if (buf->c_magic != MAGIC || checksum((int *)buf) == 0)
                return(0);
        return(1);
@@ -1129,19 +1036,24 @@ checktype(b, t)
        struct s_spcl *b;
        int     t;
 {
        struct s_spcl *b;
        int     t;
 {
+
        return(b->c_type == t);
 }
 
 /*
  * read a bit mask from the tape into m.
  */
        return(b->c_type == t);
 }
 
 /*
  * read a bit mask from the tape into m.
  */
-readbits(m)
-       char    *m;
+readbits(mapp)
+       char **mapp;
 {
        register int i;
 {
        register int i;
+       char    *m;
 
        i = spcl.c_count;
 
 
        i = spcl.c_count;
 
+       if (*mapp == 0)
+               *mapp = (char *)calloc(i, (TP_BSIZE/(NBBY/BITS)));
+       m = *mapp;
        while (i--) {
                readtape((char *) m);
                m += (TP_BSIZE/(NBBY/BITS));
        while (i--) {
                readtape((char *) m);
                m += (TP_BSIZE/(NBBY/BITS));
@@ -1181,54 +1093,189 @@ checkdir(name)
        for (cp = name; *cp; cp++) {
                if (*cp == '/') {
                        *cp = '\0';
        for (cp = name; *cp; cp++) {
                if (*cp == '/') {
                        *cp = '\0';
-                       if (xaccess(name, 01) < 0) {
+                       if (access(name, 01) < 0) {
                                register int pid, rp;
 
                                register int pid, rp;
 
-                               xumount();
                                if ((pid = fork()) == 0) {
                                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");
+                                       execl("/bin/mkdir", "mkdir", name, 0);
+                                       execl("/usr/bin/mkdir", "mkdir", name, 0);
+                                       fprintf(stderr, "restor: cannot find mkdir!\n");
                                        done(0);
                                }
                                while ((rp = wait(&i)) >= 0 && rp != pid)
                                        ;
                                        done(0);
                                }
                                while ((rp = wait(&i)) >= 0 && rp != pid)
                                        ;
-                               xmount(envp);
                        }
                        *cp = '/';
                }
        }
 }
 
                        }
                        *cp = '/';
                }
        }
 }
 
+setdir(dev)
+       char *dev;
+{
+       struct fstab *fsp;
+
+       if (setfsent() == 0) {
+               fprintf(stderr, "Can't open checklist file: %s\n", FSTAB);
+               done(1);
+       }
+       while ((fsp = getfsent()) != 0) {
+               if (strcmp(fsp->fs_spec, dev) == 0) {
+                       printf("%s mounted on %s\n", dev, fsp->fs_file);
+                       if (chdir(fsp->fs_file) >= 0)
+                               return;
+                       fprintf(stderr, "%s cannot chdir to %s\n",
+                           fsp->fs_file);
+                       done(1);
+               }
+       }
+       fprintf(stderr, "%s not mounted\n", dev);
+       done(1);
+}
+
 /*
 /*
- * tell whether an inode is allocated
- * this is drawn from ialloccg in sys/alloc.c
+ * These variables are "local" to the following two functions.
  */
  */
-iexist(dev, ino)
-       dev_t dev;
-       ino_t ino;
+char dirbuf[DIRBLKSIZ];
+long dirloc = 0;
+long prev = 0;
+
+/*
+ * add a new directory entry to a file.
+ */
+putent(dp, wrtfunc)
+       struct direct *dp;
+       int (*wrtfunc)();
 {
 {
-       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, fsbtodb(fs, cgtod(cg, fs)), fs->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);
+
+       if (dp->d_ino == 0)
+               return;
+       if (dirloc + dp->d_reclen > DIRBLKSIZ) {
+               ((struct direct *)(dirbuf + prev))->d_reclen =
+                   DIRBLKSIZ - prev;
+               (*wrtfunc)(dirbuf, DIRBLKSIZ);
+               dirloc = 0;
+       }
+       blkcpy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen);
+       prev = dirloc;
+       dirloc += dp->d_reclen;
+}
+
+/*
+ * flush out a directory that is finished.
+ */
+flushent(wrtfunc)
+       int (*wrtfunc)();
+{
+
+       ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev;
+       (*wrtfunc)(dirbuf, dirloc);
+       dirloc = 0;
+}
+
+dirwrite(buf, size)
+       char *buf;
+       int size;
+{
+
+       fwrite(buf, 1, size, df);
+       seekpt = ftell(df);
+}
+
+dcvt(odp, ndp)
+       register struct odirect *odp;
+       register struct direct *ndp;
+{
+
+       blkclr((char *)ndp, (long)(sizeof *ndp));
+       ndp->d_ino =  odp->d_ino;
+       strncpy(ndp->d_name, odp->d_name, ODIRSIZ);
+       ndp->d_namlen = strlen(ndp->d_name);
+       ndp->d_reclen = DIRSIZ(ndp);
+       /*
+        * this quickly calculates if this inode is a directory.
+        * Currently not maintained.
+        *
+       for (itp = inotab[INOHASH(odp->d_ino)]; itp; itp = itp->t_next) {
+               if (itp->t_ino != odp->d_ino)
+                       continue;
+               ndp->d_fmt = IFDIR;
+               break;
+       }
+        */
+}
+
+/*
+ * Open a directory.
+ * Modified to allow any random file to be a legal directory.
+ */
+DIR *
+opendir(name)
+       char *name;
+{
+       register DIR *dirp;
+
+       dirp = (DIR *)malloc(sizeof(DIR));
+       dirp->dd_fd = open(name, 0);
+       if (dirp->dd_fd == -1) {
+               free((char *)dirp);
+               return NULL;
+       }
+       dirp->dd_loc = 0;
+       return dirp;
+}
+
+/*
+ * Seek to an entry in a directory.
+ * Only values returned by ``telldir'' should be passed to seekdir.
+ * Modified to have many directories based in one file.
+ */
+void
+seekdir(dirp, loc, base)
+       register DIR *dirp;
+       daddr_t loc, base;
+{
+
+       if (loc == telldir(dirp))
+               return;
+       loc -= base;
+       if (loc < 0)
+               fprintf(stderr, "bad seek pointer to seekdir %d\n", loc);
+       (void)lseek(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), 0);
+       dirp->dd_loc = loc & (DIRBLKSIZ - 1);
+       if (dirp->dd_loc != 0)
+               dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ);
+}
+
+/*
+ * get next entry in a directory.
+ */
+struct direct *
+readdir(dirp)
+       register DIR *dirp;
+{
+       register struct direct *dp;
+
+       for (;;) {
+               if (dirp->dd_loc == 0) {
+                       dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 
+                           DIRBLKSIZ);
+                       if (dirp->dd_size <= 0)
+                               return NULL;
+               }
+               if (dirp->dd_loc >= dirp->dd_size) {
+                       dirp->dd_loc = 0;
+                       continue;
+               }
+               dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc);
+               if (dp->d_reclen <= 0 ||
+                   dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc)
+                       return NULL;
+               dirp->dd_loc += dp->d_reclen;
+               if (dp->d_ino == 0)
+                       continue;
+               return (dp);
        }
        }
-       brelse(bp);
-       return (1);
 }
 
 allocinotab(ino, seekpt)
 }
 
 allocinotab(ino, seekpt)
@@ -1276,10 +1323,7 @@ allocxtr(ino, name, flags)
 done(exitcode)
        int exitcode;
 {
 done(exitcode)
        int exitcode;
 {
-#ifndef STANDALONE
+
        unlink(dirfile);
        unlink(dirfile);
-#endif
-       if (mounted)
-               xumount();
        exit(exitcode);
 }
        exit(exitcode);
 }