set file flags; add restoration of FIFO's
[unix-history] / usr / src / sbin / restore / tape.c
index dcbb69f..f539cff 100644 (file)
@@ -1,30 +1,46 @@
 /*
 /*
- * Copyright (c) 1983 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
  *
  * %sccs.include.redist.c%
  */
 
 #ifndef lint
  *
  * %sccs.include.redist.c%
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)tape.c     5.30 (Berkeley) %G%";
+static char sccsid[] = "@(#)tape.c     8.4 (Berkeley) %G%";
 #endif /* not lint */
 
 #endif /* not lint */
 
-#include "restore.h"
-#include <protocols/dumprestore.h>
+#include <sys/param.h>
+#include <sys/file.h>
 #include <sys/ioctl.h>
 #include <sys/mtio.h>
 #include <sys/ioctl.h>
 #include <sys/mtio.h>
-#include <sys/file.h>
-#include <setjmp.h>
 #include <sys/stat.h>
 #include <sys/stat.h>
+
+#include <ufs/ufs/dinode.h>
+#include <protocols/dumprestore.h>
+
+#include <errno.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "restore.h"
+#include "extern.h"
 #include "pathnames.h"
 
 static long    fssize = MAXBSIZE;
 static int     mt = -1;
 static int     pipein = 0;
 static char    magtape[BUFSIZ];
 #include "pathnames.h"
 
 static long    fssize = MAXBSIZE;
 static int     mt = -1;
 static int     pipein = 0;
 static char    magtape[BUFSIZ];
-static int     bct;
+static int     blkcnt;
 static int     numtrec;
 static int     numtrec;
-static char    *tbf;
+static char    *tapebuf;
 static union   u_spcl endoftapemark;
 static long    blksread;               /* blocks read since last header */
 static long    tpblksread = 0;         /* TP_BSIZE blocks read */
 static union   u_spcl endoftapemark;
 static long    blksread;               /* blocks read since last header */
 static long    tpblksread = 0;         /* TP_BSIZE blocks read */
@@ -38,20 +54,38 @@ static char *map;
 static char    lnkbuf[MAXPATHLEN + 1];
 static int     pathlen;
 
 static char    lnkbuf[MAXPATHLEN + 1];
 static int     pathlen;
 
+int            oldinofmt;      /* old inode format conversion required */
 int            Bcvt;           /* Swap Bytes (for CCI or sun) */
 static int     Qcvt;           /* Swap quads (for sun) */
 int            Bcvt;           /* Swap Bytes (for CCI or sun) */
 static int     Qcvt;           /* Swap quads (for sun) */
-u_long         swabl();
+
+#define        FLUSHTAPEBUF()  blkcnt = ntrec + 1
+
+static void     accthdr __P((struct s_spcl *));
+static int      checksum __P((int *));
+static void     findinode __P((struct s_spcl *));
+static void     findtapeblksize __P((void));
+static int      gethead __P((struct s_spcl *));
+static void     readtape __P((char *));
+static void     setdumpnum __P((void));
+static u_long   swabl __P((u_long));
+static u_char  *swablong __P((u_char *, int));
+static u_char  *swabshort __P((u_char *, int));
+static void     terminateinput __P((void));
+static void     xtrfile __P((char *, long));
+static void     xtrlnkfile __P((char *, long));
+static void     xtrlnkskip __P((char *, long));
+static void     xtrmap __P((char *, long));
+static void     xtrmapskip __P((char *, long));
+static void     xtrskip __P((char *, long));
 
 /*
  * Set up an input source
  */
 
 /*
  * Set up an input source
  */
+void
 setinput(source)
        char *source;
 {
 setinput(source)
        char *source;
 {
-       extern int errno;
-       char *strerror();
-
-       flsht();
+       FLUSHTAPEBUF();
        if (bflag)
                newtapebuf(ntrec);
        else
        if (bflag)
                newtapebuf(ntrec);
        else
@@ -74,12 +108,12 @@ setinput(source)
                 */
                terminal = fopen(_PATH_TTY, "r");
                if (terminal == NULL) {
                 */
                terminal = fopen(_PATH_TTY, "r");
                if (terminal == NULL) {
-                       (void)fprintf(stderr, "Cannot open %s: %s\n",
-                                     _PATH_TTY, strerror(errno));
+                       (void)fprintf(stderr, "cannot open %s: %s\n",
+                           _PATH_TTY, strerror(errno));
                        terminal = fopen(_PATH_DEVNULL, "r");
                        if (terminal == NULL) {
                        terminal = fopen(_PATH_DEVNULL, "r");
                        if (terminal == NULL) {
-                               (void)fprintf(stderr, "Cannot open %s: %s\n",
-                                             _PATH_DEVNULL, strerror(errno));
+                               (void)fprintf(stderr, "cannot open %s: %s\n",
+                                   _PATH_DEVNULL, strerror(errno));
                                done(1);
                        }
                }
                                done(1);
                        }
                }
@@ -89,33 +123,34 @@ setinput(source)
        (void) strcpy(magtape, source);
 }
 
        (void) strcpy(magtape, source);
 }
 
+void
 newtapebuf(size)
        long size;
 {
 newtapebuf(size)
        long size;
 {
-       static tbfsize = -1;
+       static tapebufsize = -1;
 
        ntrec = size;
 
        ntrec = size;
-       if (size <= tbfsize)
+       if (size <= tapebufsize)
                return;
                return;
-       if (tbf != NULL)
-               free(tbf);
-       tbf = (char *)malloc(size * TP_BSIZE);
-       if (tbf == NULL) {
+       if (tapebuf != NULL)
+               free(tapebuf);
+       tapebuf = malloc(size * TP_BSIZE);
+       if (tapebuf == NULL) {
                fprintf(stderr, "Cannot allocate space for tape buffer\n");
                done(1);
        }
                fprintf(stderr, "Cannot allocate space for tape buffer\n");
                done(1);
        }
-       tbfsize = size;
+       tapebufsize = size;
 }
 
 /*
  * Verify that the tape drive can be accessed and
  * that it actually is a dump tape.
  */
 }
 
 /*
  * Verify that the tape drive can be accessed and
  * that it actually is a dump tape.
  */
+void
 setup()
 {
        int i, j, *ip;
        struct stat stbuf;
 setup()
 {
        int i, j, *ip;
        struct stat stbuf;
-       extern int xtrmap(), xtrmapskip();
 
        vprintf(stdout, "Verify tape and initialize maps\n");
 #ifdef RRESTORE
 
        vprintf(stdout, "Verify tape and initialize maps\n");
 #ifdef RRESTORE
@@ -126,18 +161,18 @@ setup()
        if (pipein)
                mt = 0;
        else
        if (pipein)
                mt = 0;
        else
-               mt = open(magtape, 0);
+               mt = open(magtape, O_RDONLY, 0);
        if (mt < 0) {
        if (mt < 0) {
-               perror(magtape);
+               fprintf(stderr, "%s: %s\n", magtape, strerror(errno));
                done(1);
        }
        volno = 1;
        setdumpnum();
                done(1);
        }
        volno = 1;
        setdumpnum();
-       flsht();
+       FLUSHTAPEBUF();
        if (!pipein && !bflag)
                findtapeblksize();
        if (gethead(&spcl) == FAIL) {
        if (!pipein && !bflag)
                findtapeblksize();
        if (gethead(&spcl) == FAIL) {
-               bct--; /* push back this block */
+               blkcnt--; /* push back this block */
                blksread--;
                tpblksread--;
                cvtflag++;
                blksread--;
                tpblksread--;
                cvtflag++;
@@ -163,7 +198,7 @@ setup()
        dumptime = spcl.c_ddate;
        dumpdate = spcl.c_date;
        if (stat(".", &stbuf) < 0) {
        dumptime = spcl.c_ddate;
        dumpdate = spcl.c_date;
        if (stat(".", &stbuf) < 0) {
-               perror("cannot stat .");
+               fprintf(stderr, "cannot stat .: %s\n", strerror(errno));
                done(1);
        }
        if (stbuf.st_blksize > 0 && stbuf.st_blksize <= MAXBSIZE)
                done(1);
        }
        if (stbuf.st_blksize > 0 && stbuf.st_blksize <= MAXBSIZE)
@@ -172,26 +207,28 @@ setup()
                fprintf(stderr, "bad block size %d\n", fssize);
                done(1);
        }
                fprintf(stderr, "bad block size %d\n", fssize);
                done(1);
        }
-       if (checkvol(&spcl, (long)1) == FAIL) {
+       if (spcl.c_volume != 1) {
                fprintf(stderr, "Tape is not volume 1 of the dump\n");
                done(1);
        }
                fprintf(stderr, "Tape is not volume 1 of the dump\n");
                done(1);
        }
-       if (readhdr(&spcl) == FAIL)
+       if (gethead(&spcl) == FAIL) {
+               dprintf(stdout, "header read failed at %d blocks\n", blksread);
                panic("no header after volume mark!\n");
                panic("no header after volume mark!\n");
+       }
        findinode(&spcl);
        findinode(&spcl);
-       if (checktype(&spcl, TS_CLRI) == FAIL) {
+       if (spcl.c_type != TS_CLRI) {
                fprintf(stderr, "Cannot find file removal list\n");
                done(1);
        }
        maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
        dprintf(stdout, "maxino = %d\n", maxino);
        map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
                fprintf(stderr, "Cannot find file removal list\n");
                done(1);
        }
        maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
        dprintf(stdout, "maxino = %d\n", maxino);
        map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
-       if (map == (char *)NIL)
+       if (map == NULL)
                panic("no memory for file removal list\n");
        clrimap = map;
        curfile.action = USING;
        getfile(xtrmap, xtrmapskip);
                panic("no memory for file removal list\n");
        clrimap = map;
        curfile.action = USING;
        getfile(xtrmap, xtrmapskip);
-       if (checktype(&spcl, TS_BITS) == FAIL) {
+       if (spcl.c_type != TS_BITS) {
                fprintf(stderr, "Cannot find file dump list\n");
                done(1);
        }
                fprintf(stderr, "Cannot find file dump list\n");
                done(1);
        }
@@ -210,6 +247,7 @@ setup()
  * or incremental restores, but can be overrridden by
  * the user when only extracting a subset of the files.
  */
  * or incremental restores, but can be overrridden by
  * the user when only extracting a subset of the files.
  */
+void
 getvol(nextvol)
        long nextvol;
 {
 getvol(nextvol)
        long nextvol;
 {
@@ -217,7 +255,6 @@ getvol(nextvol)
        union u_spcl tmpspcl;
 #      define tmpbuf tmpspcl.s_spcl
        char buf[TP_BSIZE];
        union u_spcl tmpspcl;
 #      define tmpbuf tmpspcl.s_spcl
        char buf[TP_BSIZE];
-       extern char *ctime();
 
        if (nextvol == 1) {
                tapesread = 0;
 
        if (nextvol == 1) {
                tapesread = 0;
@@ -251,22 +288,22 @@ again:
                            " towards towards the first.\n");
                } else {
                        fprintf(stderr, "You have read volumes");
                            " towards towards the first.\n");
                } else {
                        fprintf(stderr, "You have read volumes");
-                       strcpy(tbf, ": ");
+                       strcpy(buf, ": ");
                        for (i = 1; i < 32; i++)
                                if (tapesread & (1 << i)) {
                        for (i = 1; i < 32; i++)
                                if (tapesread & (1 << i)) {
-                                       fprintf(stderr, "%s%d", tbf, i);
-                                       strcpy(tbf, ", ");
+                                       fprintf(stderr, "%s%d", buf, i);
+                                       strcpy(buf, ", ");
                                }
                        fprintf(stderr, "\n");
                }
                do      {
                        fprintf(stderr, "Specify next volume #: ");
                        (void) fflush(stderr);
                                }
                        fprintf(stderr, "\n");
                }
                do      {
                        fprintf(stderr, "Specify next volume #: ");
                        (void) fflush(stderr);
-                       (void) fgets(tbf, BUFSIZ, terminal);
-               } while (!feof(terminal) && tbf[0] == '\n');
+                       (void) fgets(buf, BUFSIZ, terminal);
+               } while (!feof(terminal) && buf[0] == '\n');
                if (feof(terminal))
                        done(1);
                if (feof(terminal))
                        done(1);
-               newvol = atoi(tbf);
+               newvol = atoi(buf);
                if (newvol <= 0) {
                        fprintf(stderr,
                            "Volume numbers are positive numerics\n");
                if (newvol <= 0) {
                        fprintf(stderr,
                            "Volume numbers are positive numerics\n");
@@ -281,15 +318,15 @@ again:
        fprintf(stderr, "Enter ``none'' if there are no more tapes\n");
        fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape);
        (void) fflush(stderr);
        fprintf(stderr, "Enter ``none'' if there are no more tapes\n");
        fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape);
        (void) fflush(stderr);
-       (void) fgets(tbf, BUFSIZ, terminal);
+       (void) fgets(buf, BUFSIZ, terminal);
        if (feof(terminal))
                done(1);
        if (feof(terminal))
                done(1);
-       if (!strcmp(tbf, "none\n")) {
+       if (!strcmp(buf, "none\n")) {
                terminateinput();
                return;
        }
                terminateinput();
                return;
        }
-       if (tbf[0] != '\n') {
-               (void) strcpy(magtape, tbf);
+       if (buf[0] != '\n') {
+               (void) strcpy(magtape, buf);
                magtape[strlen(magtape) - 1] = '\0';
        }
 #ifdef RRESTORE
                magtape[strlen(magtape) - 1] = '\0';
        }
 #ifdef RRESTORE
@@ -297,7 +334,7 @@ again:
                mt = rmtopen(magtape, 0);
        else
 #endif
                mt = rmtopen(magtape, 0);
        else
 #endif
-               mt = open(magtape, 0);
+               mt = open(magtape, O_RDONLY, 0);
 
        if (mt == -1) {
                fprintf(stderr, "Cannot open %s\n", magtape);
 
        if (mt == -1) {
                fprintf(stderr, "Cannot open %s\n", magtape);
@@ -307,13 +344,14 @@ again:
 gethdr:
        volno = newvol;
        setdumpnum();
 gethdr:
        volno = newvol;
        setdumpnum();
-       flsht();
-       if (readhdr(&tmpbuf) == FAIL) {
+       FLUSHTAPEBUF();
+       if (gethead(&tmpbuf) == FAIL) {
+               dprintf(stdout, "header read failed at %d blocks\n", blksread);
                fprintf(stderr, "tape is not dump tape\n");
                volno = 0;
                goto again;
        }
                fprintf(stderr, "tape is not dump tape\n");
                volno = 0;
                goto again;
        }
-       if (checkvol(&tmpbuf, volno) == FAIL) {
+       if (tmpbuf.c_volume != volno) {
                fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume);
                volno = 0;
                goto again;
                fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume);
                volno = 0;
                goto again;
@@ -375,6 +413,7 @@ gethdr:
 /*
  * Handle unexpected EOF.
  */
 /*
  * Handle unexpected EOF.
  */
+static void
 terminateinput()
 {
 
 terminateinput()
 {
 
@@ -384,7 +423,7 @@ terminateinput()
        }
        curfile.name = "<name unknown>";
        curfile.action = UNKNOWN;
        }
        curfile.name = "<name unknown>";
        curfile.action = UNKNOWN;
-       curfile.dip = (struct dinode *)NIL;
+       curfile.dip = NULL;
        curfile.ino = maxino;
        if (gettingfile) {
                gettingfile = 0;
        curfile.ino = maxino;
        if (gettingfile) {
                gettingfile = 0;
@@ -396,6 +435,7 @@ terminateinput()
  * handle multiple dumps per tape by skipping forward to the
  * appropriate one.
  */
  * handle multiple dumps per tape by skipping forward to the
  * appropriate one.
  */
+static void
 setdumpnum()
 {
        struct mtop tcom;
 setdumpnum()
 {
        struct mtop tcom;
@@ -414,13 +454,12 @@ setdumpnum()
        else 
 #endif
                if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0)
        else 
 #endif
                if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0)
-                       perror("ioctl MTFSF");
+                       fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno));
 }
 
 }
 
+void
 printdumpinfo()
 {
 printdumpinfo()
 {
-       extern char *ctime();
-
        fprintf(stdout, "Dump   date: %s", ctime(&spcl.c_date));
        fprintf(stdout, "Dumped from: %s",
            (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&spcl.c_ddate));
        fprintf(stdout, "Dump   date: %s", ctime(&spcl.c_date));
        fprintf(stdout, "Dumped from: %s",
            (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&spcl.c_ddate));
@@ -431,14 +470,14 @@ printdumpinfo()
        fprintf(stderr, "Label: %s\n", spcl.c_label);
 }
 
        fprintf(stderr, "Label: %s\n", spcl.c_label);
 }
 
+int
 extractfile(name)
        char *name;
 {
 extractfile(name)
        char *name;
 {
-       int mode;
+       int flags;
+       mode_t mode;
        struct timeval timep[2];
        struct entry *ep;
        struct timeval timep[2];
        struct entry *ep;
-       extern int xtrlnkfile(), xtrlnkskip();
-       extern int xtrfile(), xtrskip();
 
        curfile.name = name;
        curfile.action = USING;
 
        curfile.name = name;
        curfile.action = USING;
@@ -447,6 +486,7 @@ extractfile(name)
        timep[1].tv_sec = curfile.dip->di_mtime.ts_sec;
        timep[1].tv_usec = curfile.dip->di_mtime.ts_nsec / 1000;
        mode = curfile.dip->di_mode;
        timep[1].tv_sec = curfile.dip->di_mtime.ts_sec;
        timep[1].tv_usec = curfile.dip->di_mtime.ts_nsec / 1000;
        mode = curfile.dip->di_mode;
+       flags = curfile.dip->di_flags;
        switch (mode & IFMT) {
 
        default:
        switch (mode & IFMT) {
 
        default:
@@ -462,7 +502,7 @@ extractfile(name)
        case IFDIR:
                if (mflag) {
                        ep = lookupname(name);
        case IFDIR:
                if (mflag) {
                        ep = lookupname(name);
-                       if (ep == NIL || ep->e_flags & EXTRACT)
+                       if (ep == NULL || ep->e_flags & EXTRACT)
                                panic("unextracted directory %s\n", name);
                        skipfile();
                        return (GOOD);
                                panic("unextracted directory %s\n", name);
                        skipfile();
                        return (GOOD);
@@ -489,14 +529,33 @@ extractfile(name)
                        return (GOOD);
                }
                if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
                        return (GOOD);
                }
                if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
-                       fprintf(stderr, "%s: ", name);
-                       (void) fflush(stderr);
-                       perror("cannot create special file");
+                       fprintf(stderr, "%s: cannot create special file: %s\n",
+                           name, strerror(errno));
                        skipfile();
                        return (FAIL);
                }
                (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
                (void) chmod(name, mode);
                        skipfile();
                        return (FAIL);
                }
                (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
                (void) chmod(name, mode);
+               (void) chflags(name, flags);
+               skipfile();
+               utimes(name, timep);
+               return (GOOD);
+
+       case IFIFO:
+               vprintf(stdout, "extract fifo %s\n", name);
+               if (Nflag) {
+                       skipfile();
+                       return (GOOD);
+               }
+               if (mkfifo(name, mode) < 0) {
+                       fprintf(stderr, "%s: cannot create fifo: %s\n",
+                           name, strerror(errno));
+                       skipfile();
+                       return (FAIL);
+               }
+               (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
+               (void) chmod(name, mode);
+               (void) chflags(name, flags);
                skipfile();
                utimes(name, timep);
                return (GOOD);
                skipfile();
                utimes(name, timep);
                return (GOOD);
@@ -508,14 +567,14 @@ extractfile(name)
                        return (GOOD);
                }
                if ((ofile = creat(name, 0666)) < 0) {
                        return (GOOD);
                }
                if ((ofile = creat(name, 0666)) < 0) {
-                       fprintf(stderr, "%s: ", name);
-                       (void) fflush(stderr);
-                       perror("cannot create file");
+                       fprintf(stderr, "%s: cannot create file: %s\n",
+                           name, strerror(errno));
                        skipfile();
                        return (FAIL);
                }
                (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid);
                (void) fchmod(ofile, mode);
                        skipfile();
                        return (FAIL);
                }
                (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid);
                (void) fchmod(ofile, mode);
+               (void) fchflags(ofile, flags);
                getfile(xtrfile, xtrskip);
                (void) close(ofile);
                utimes(name, timep);
                getfile(xtrfile, xtrskip);
                (void) close(ofile);
                utimes(name, timep);
@@ -527,42 +586,46 @@ extractfile(name)
 /*
  * skip over bit maps on the tape
  */
 /*
  * skip over bit maps on the tape
  */
+void
 skipmaps()
 {
 
 skipmaps()
 {
 
-       while (checktype(&spcl, TS_CLRI) == GOOD ||
-              checktype(&spcl, TS_BITS) == GOOD)
+       while (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI)
                skipfile();
 }
 
 /*
  * skip over a file on the tape
  */
                skipfile();
 }
 
 /*
  * skip over a file on the tape
  */
+void
 skipfile()
 {
 skipfile()
 {
-       extern int null();
 
        curfile.action = SKIP;
 
        curfile.action = SKIP;
-       getfile(null, null);
+       getfile(xtrnull, xtrnull);
 }
 
 /*
 }
 
 /*
- * Do the file extraction, calling the supplied functions
- * with the blocks
+ * Extract a file from the tape.
+ * When an allocated block is found it is passed to the fill function;
+ * when an unallocated block (hole) is found, a zeroed buffer is passed
+ * to the skip function.
  */
  */
-getfile(f1, f2)
-       int     (*f2)(), (*f1)();
+void
+getfile(fill, skip)
+       void    (*fill) __P((char *, long));
+       void    (*skip) __P((char *, long));
 {
        register int i;
        int curblk = 0;
 {
        register int i;
        int curblk = 0;
-       off_t size = spcl.c_dinode.di_size;
+       long size = spcl.c_dinode.di_size;
        static char clearedbuf[MAXBSIZE];
        char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
        char junk[TP_BSIZE];
 
        static char clearedbuf[MAXBSIZE];
        char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
        char junk[TP_BSIZE];
 
-       if (checktype(&spcl, TS_END) == GOOD)
+       if (spcl.c_type == TS_END)
                panic("ran off end of tape\n");
                panic("ran off end of tape\n");
-       if (ishead(&spcl) == FAIL)
+       if (spcl.c_magic != NFS_MAGIC)
                panic("not at beginning of a file\n");
        if (!gettingfile && setjmp(restart) != 0)
                return;
                panic("not at beginning of a file\n");
        if (!gettingfile && setjmp(restart) != 0)
                return;
@@ -572,19 +635,19 @@ loop:
                if (spcl.c_addr[i]) {
                        readtape(&buf[curblk++][0]);
                        if (curblk == fssize / TP_BSIZE) {
                if (spcl.c_addr[i]) {
                        readtape(&buf[curblk++][0]);
                        if (curblk == fssize / TP_BSIZE) {
-                               (*f1)(buf, size > TP_BSIZE ?
+                               (*fill)((char *)buf, size > TP_BSIZE ?
                                     (long) (fssize) :
                                     (curblk - 1) * TP_BSIZE + size);
                                curblk = 0;
                        }
                } else {
                        if (curblk > 0) {
                                     (long) (fssize) :
                                     (curblk - 1) * TP_BSIZE + size);
                                curblk = 0;
                        }
                } else {
                        if (curblk > 0) {
-                               (*f1)(buf, size > TP_BSIZE ?
+                               (*fill)((char *)buf, size > TP_BSIZE ?
                                     (long) (curblk * TP_BSIZE) :
                                     (curblk - 1) * TP_BSIZE + size);
                                curblk = 0;
                        }
                                     (long) (curblk * TP_BSIZE) :
                                     (curblk - 1) * TP_BSIZE + size);
                                curblk = 0;
                        }
-                       (*f2)(clearedbuf, size > TP_BSIZE ?
+                       (*skip)(clearedbuf, size > TP_BSIZE ?
                                (long) TP_BSIZE : size);
                }
                if ((size -= TP_BSIZE) <= 0) {
                                (long) TP_BSIZE : size);
                }
                if ((size -= TP_BSIZE) <= 0) {
@@ -594,22 +657,23 @@ loop:
                        break;
                }
        }
                        break;
                }
        }
-       if (readhdr(&spcl) == GOOD && size > 0) {
-               if (checktype(&spcl, TS_ADDR) == GOOD)
+       if (gethead(&spcl) == GOOD && size > 0) {
+               if (spcl.c_type == TS_ADDR)
                        goto loop;
                        goto loop;
-               dprintf(stdout, "Missing address (header) block for %s\n",
-                       curfile.name);
+               dprintf(stdout,
+                       "Missing address (header) block for %s at %d blocks\n",
+                       curfile.name, blksread);
        }
        if (curblk > 0)
        }
        if (curblk > 0)
-               (*f1)(buf, (curblk * TP_BSIZE) + size);
+               (*fill)((char *)buf, (curblk * TP_BSIZE) + size);
        findinode(&spcl);
        gettingfile = 0;
 }
 
 /*
        findinode(&spcl);
        gettingfile = 0;
 }
 
 /*
- * The next routines are called during file extraction to
- * put the data into the right form and place.
+ * Write out the next block of a file.
  */
  */
+static void
 xtrfile(buf, size)
        char    *buf;
        long    size;
 xtrfile(buf, size)
        char    *buf;
        long    size;
@@ -618,29 +682,35 @@ xtrfile(buf, size)
        if (Nflag)
                return;
        if (write(ofile, buf, (int) size) == -1) {
        if (Nflag)
                return;
        if (write(ofile, buf, (int) size) == -1) {
-               fprintf(stderr, "write error extracting inode %d, name %s\n",
-                       curfile.ino, curfile.name);
-               perror("write");
+               fprintf(stderr,
+                   "write error extracting inode %d, name %s\nwrite: %s\n",
+                       curfile.ino, curfile.name, strerror(errno));
                done(1);
        }
 }
 
                done(1);
        }
 }
 
+/*
+ * Skip over a hole in a file.
+ */
+/* ARGSUSED */
+static void
 xtrskip(buf, size)
        char *buf;
        long size;
 {
 
 xtrskip(buf, size)
        char *buf;
        long size;
 {
 
-#ifdef lint
-       buf = buf;
-#endif
-       if (lseek(ofile, size, 1) == (long)-1) {
-               fprintf(stderr, "seek error extracting inode %d, name %s\n",
-                       curfile.ino, curfile.name);
-               perror("lseek");
+       if (lseek(ofile, size, SEEK_CUR) == -1) {
+               fprintf(stderr,
+                   "seek error extracting inode %d, name %s\nlseek: %s\n",
+                       curfile.ino, curfile.name, strerror(errno));
                done(1);
        }
 }
 
                done(1);
        }
 }
 
+/*
+ * Collect the next block of a symbolic link.
+ */
+static void
 xtrlnkfile(buf, size)
        char    *buf;
        long    size;
 xtrlnkfile(buf, size)
        char    *buf;
        long    size;
@@ -655,19 +725,25 @@ xtrlnkfile(buf, size)
        (void) strcat(lnkbuf, buf);
 }
 
        (void) strcat(lnkbuf, buf);
 }
 
+/*
+ * Skip over a hole in a symbolic link (should never happen).
+ */
+/* ARGSUSED */
+static void
 xtrlnkskip(buf, size)
        char *buf;
        long size;
 {
 
 xtrlnkskip(buf, size)
        char *buf;
        long size;
 {
 
-#ifdef lint
-       buf = buf, size = size;
-#endif
        fprintf(stderr, "unallocated block in symbolic link %s\n",
                curfile.name);
        done(1);
 }
 
        fprintf(stderr, "unallocated block in symbolic link %s\n",
                curfile.name);
        done(1);
 }
 
+/*
+ * Collect the next block of a bit map.
+ */
+static void
 xtrmap(buf, size)
        char    *buf;
        long    size;
 xtrmap(buf, size)
        char    *buf;
        long    size;
@@ -677,40 +753,52 @@ xtrmap(buf, size)
        map += size;
 }
 
        map += size;
 }
 
+/*
+ * Skip over a hole in a bit map (should never happen).
+ */
+/* ARGSUSED */
+static void
 xtrmapskip(buf, size)
        char *buf;
        long size;
 {
 
 xtrmapskip(buf, size)
        char *buf;
        long size;
 {
 
-#ifdef lint
-       buf = buf;
-#endif
        panic("hole in map\n");
        map += size;
 }
 
        panic("hole in map\n");
        map += size;
 }
 
-null() {;}
+/*
+ * Noop, when an extraction function is not needed.
+ */
+/* ARGSUSED */
+void
+xtrnull(buf, size)
+       char *buf;
+       long size;
+{
+
+       return;
+}
 
 /*
 
 /*
- * Do the tape i/o, dealing with volume changes
- * etc..
+ * Read TP_BSIZE blocks from the input.
+ * Handle read errors, and end of media.
  */
  */
-readtape(b)
-       char *b;
+static void
+readtape(buf)
+       char *buf;
 {
 {
-       register long i;
-       long rd, newvol;
-       int cnt;
-       int seek_failed;
+       long rd, newvol, i;
+       int cnt, seek_failed;
 
 
-       if (bct < numtrec) {
-               bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
+       if (blkcnt < numtrec) {
+               bcopy(&tapebuf[(blkcnt++ * TP_BSIZE)], buf, (long)TP_BSIZE);
                blksread++;
                tpblksread++;
                return;
        }
        for (i = 0; i < ntrec; i++)
                blksread++;
                tpblksread++;
                return;
        }
        for (i = 0; i < ntrec; i++)
-               ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0;
+               ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0;
        if (numtrec == 0)
                numtrec = ntrec;
        cnt = ntrec * TP_BSIZE;
        if (numtrec == 0)
                numtrec = ntrec;
        cnt = ntrec * TP_BSIZE;
@@ -718,10 +806,10 @@ readtape(b)
 getmore:
 #ifdef RRESTORE
        if (host)
 getmore:
 #ifdef RRESTORE
        if (host)
-               i = rmtread(&tbf[rd], cnt);
+               i = rmtread(&tapebuf[rd], cnt);
        else
 #endif
        else
 #endif
-               i = read(mt, &tbf[rd], cnt);
+               i = read(mt, &tapebuf[rd], cnt);
        /*
         * Check for mid-tape short read error.
         * If found, skip rest of buffer and start with the next.
        /*
         * Check for mid-tape short read error.
         * If found, skip rest of buffer and start with the next.
@@ -775,17 +863,18 @@ getmore:
                }
                if (!yflag && !reply("continue"))
                        done(1);
                }
                if (!yflag && !reply("continue"))
                        done(1);
-               i = ntrec*TP_BSIZE;
-               bzero(tbf, i);
+               i = ntrec * TP_BSIZE;
+               bzero(tapebuf, i);
 #ifdef RRESTORE
                if (host)
                        seek_failed = (rmtseek(i, 1) < 0);
                else
 #endif
 #ifdef RRESTORE
                if (host)
                        seek_failed = (rmtseek(i, 1) < 0);
                else
 #endif
-                       seek_failed = (lseek(mt, i, 1) == (long)-1);
+                       seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1);
 
                if (seek_failed) {
 
                if (seek_failed) {
-                       perror("continuation failed");
+                       fprintf(stderr,
+                           "continuation failed: %s\n", strerror(errno));
                        done(1);
                }
        }
                        done(1);
                }
        }
@@ -799,37 +888,38 @@ getmore:
                        volno = 0;
                        numtrec = 0;
                        getvol(newvol);
                        volno = 0;
                        numtrec = 0;
                        getvol(newvol);
-                       readtape(b);
+                       readtape(buf);
                        return;
                }
                if (rd % TP_BSIZE != 0)
                        panic("partial block read: %d should be %d\n",
                                rd, ntrec * TP_BSIZE);
                terminateinput();
                        return;
                }
                if (rd % TP_BSIZE != 0)
                        panic("partial block read: %d should be %d\n",
                                rd, ntrec * TP_BSIZE);
                terminateinput();
-               bcopy((char *)&endoftapemark, &tbf[rd], (long)TP_BSIZE);
+               bcopy((char *)&endoftapemark, &tapebuf[rd], (long)TP_BSIZE);
        }
        }
-       bct = 0;
-       bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
+       blkcnt = 0;
+       bcopy(&tapebuf[(blkcnt++ * TP_BSIZE)], buf, (long)TP_BSIZE);
        blksread++;
        tpblksread++;
 }
 
        blksread++;
        tpblksread++;
 }
 
+static void
 findtapeblksize()
 {
        register long i;
 
        for (i = 0; i < ntrec; i++)
 findtapeblksize()
 {
        register long i;
 
        for (i = 0; i < ntrec; i++)
-               ((struct s_spcl *)&tbf[i * TP_BSIZE])->c_magic = 0;
-       bct = 0;
+               ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0;
+       blkcnt = 0;
 #ifdef RRESTORE
        if (host)
 #ifdef RRESTORE
        if (host)
-               i = rmtread(tbf, ntrec * TP_BSIZE);
+               i = rmtread(tapebuf, ntrec * TP_BSIZE);
        else
 #endif
        else
 #endif
-               i = read(mt, tbf, ntrec * TP_BSIZE);
+               i = read(mt, tapebuf, ntrec * TP_BSIZE);
 
        if (i <= 0) {
 
        if (i <= 0) {
-               perror("Tape read error");
+               fprintf(stderr, "tape read error: %s\n", strerror(errno));
                done(1);
        }
        if (i % TP_BSIZE != 0) {
                done(1);
        }
        if (i % TP_BSIZE != 0) {
@@ -842,14 +932,10 @@ findtapeblksize()
        vprintf(stdout, "Tape block size is %d\n", ntrec);
 }
 
        vprintf(stdout, "Tape block size is %d\n", ntrec);
 }
 
-flsht()
-{
-
-       bct = ntrec+1;
-}
-
+void
 closemt()
 {
 closemt()
 {
+
        if (mt < 0)
                return;
 #ifdef RRESTORE
        if (mt < 0)
                return;
 #ifdef RRESTORE
@@ -860,31 +946,13 @@ closemt()
                (void) close(mt);
 }
 
                (void) close(mt);
 }
 
-checkvol(b, t)
-       struct s_spcl *b;
-       long t;
-{
-
-       if (b->c_volume != t)
-               return(FAIL);
-       return(GOOD);
-}
-
-readhdr(b)
-       struct s_spcl *b;
-{
-
-       if (gethead(b) == FAIL) {
-               dprintf(stdout, "readhdr fails at %d blocks\n", blksread);
-               return(FAIL);
-       }
-       return(GOOD);
-}
-
 /*
 /*
- * read the tape into buf, then return whether or
- * or not it is a header block.
+ * Read the next block from the tape.
+ * Check to see if it is one of several vintage headers.
+ * If it is an old style header, convert it to a new style header.
+ * If it is not any valid header, return an error.
  */
  */
+static int
 gethead(buf)
        struct s_spcl *buf;
 {
 gethead(buf)
        struct s_spcl *buf;
 {
@@ -934,7 +1002,7 @@ gethead(buf)
                if (checksum((int *)buf) == FAIL)
                        return (FAIL);
                if (Bcvt)
                if (checksum((int *)buf) == FAIL)
                        return (FAIL);
                if (Bcvt)
-                       swabst("8l4s31l", (char *)buf);
+                       swabst((u_char *)"8l4s31l", (u_char *)buf);
                goto good;
        }
        readtape((char *)(&u_ospcl.s_ospcl));
                goto good;
        }
        readtape((char *)(&u_ospcl.s_ospcl));
@@ -977,14 +1045,7 @@ good:
                i = qcvt.val[1];
                qcvt.val[1] = qcvt.val[0];
                qcvt.val[0] = i;
                i = qcvt.val[1];
                qcvt.val[1] = qcvt.val[0];
                qcvt.val[0] = i;
-       }
-       /*
-        * If we are restoring a filesystem with old format inodes, 
-        * copy the uid/gid to the new location.
-        */
-       if ((buf->c_flags & DR_NEWINODEFMT) == 0) {
-               buf->c_dinode.di_uid = buf->c_dinode.di_ouid;
-               buf->c_dinode.di_gid = buf->c_dinode.di_ogid;
+               buf->c_dinode.di_size = qcvt.qval;
        }
 
        switch (buf->c_type) {
        }
 
        switch (buf->c_type) {
@@ -1001,6 +1062,9 @@ good:
                break;
 
        case TS_TAPE:
                break;
 
        case TS_TAPE:
+               if ((buf->c_flags & DR_NEWINODEFMT) == 0)
+                       oldinofmt = 1;
+               /* fall through */
        case TS_END:
                buf->c_inumber = 0;
                break;
        case TS_END:
                buf->c_inumber = 0;
                break;
@@ -1013,6 +1077,14 @@ good:
                panic("gethead: unknown inode type %d\n", buf->c_type);
                break;
        }
                panic("gethead: unknown inode type %d\n", buf->c_type);
                break;
        }
+       /*
+        * If we are restoring a filesystem with old format inodes, 
+        * copy the uid/gid to the new location.
+        */
+       if (oldinofmt) {
+               buf->c_dinode.di_uid = buf->c_dinode.di_ouid;
+               buf->c_dinode.di_gid = buf->c_dinode.di_ogid;
+       }
        if (dflag)
                accthdr(buf);
        return(GOOD);
        if (dflag)
                accthdr(buf);
        return(GOOD);
@@ -1021,6 +1093,7 @@ good:
 /*
  * Check that a header is where it belongs and predict the next header
  */
 /*
  * Check that a header is where it belongs and predict the next header
  */
+static void
 accthdr(header)
        struct s_spcl *header;
 {
 accthdr(header)
        struct s_spcl *header;
 {
@@ -1030,9 +1103,10 @@ accthdr(header)
        long blks, i;
 
        if (header->c_type == TS_TAPE) {
        long blks, i;
 
        if (header->c_type == TS_TAPE) {
-               fprintf(stderr, "Volume header");
+               fprintf(stderr, "Volume header (%s inode format) ",
+                   oldinofmt ? "old" : "new");
                if (header->c_firstrec)
                if (header->c_firstrec)
-                       fprintf(stderr, " begins with record %d",
+                       fprintf(stderr, "begins with record %d",
                                header->c_firstrec);
                fprintf(stderr, "\n");
                previno = 0x7fffffff;
                                header->c_firstrec);
                fprintf(stderr, "\n");
                previno = 0x7fffffff;
@@ -1077,6 +1151,7 @@ newcalc:
  * Find an inode header.
  * Complain if had to skip, and complain is set.
  */
  * Find an inode header.
  * Complain if had to skip, and complain is set.
  */
+static void
 findinode(header)
        struct s_spcl *header;
 {
 findinode(header)
        struct s_spcl *header;
 {
@@ -1086,73 +1161,64 @@ findinode(header)
 
        curfile.name = "<name unknown>";
        curfile.action = UNKNOWN;
 
        curfile.name = "<name unknown>";
        curfile.action = UNKNOWN;
-       curfile.dip = (struct dinode *)NIL;
+       curfile.dip = NULL;
        curfile.ino = 0;
        curfile.ino = 0;
-       if (ishead(header) == FAIL) {
-               skipcnt++;
-               while (gethead(header) == FAIL || header->c_date != dumpdate)
+       do {
+               if (header->c_magic != NFS_MAGIC) {
                        skipcnt++;
                        skipcnt++;
-       }
-       for (;;) {
-               if (checktype(header, TS_ADDR) == GOOD) {
+                       while (gethead(header) == FAIL ||
+                           header->c_date != dumpdate)
+                               skipcnt++;
+               }
+               switch (header->c_type) {
+
+               case TS_ADDR:
                        /*
                         * Skip up to the beginning of the next record
                         */
                        for (i = 0; i < header->c_count; i++)
                                if (header->c_addr[i])
                                        readtape(buf);
                        /*
                         * Skip up to the beginning of the next record
                         */
                        for (i = 0; i < header->c_count; i++)
                                if (header->c_addr[i])
                                        readtape(buf);
-                       (void) gethead(header);
-                       continue;
-               }
-               if (checktype(header, TS_INODE) == GOOD) {
+                       while (gethead(header) == FAIL ||
+                           header->c_date != dumpdate)
+                               skipcnt++;
+                       break;
+
+               case TS_INODE:
                        curfile.dip = &header->c_dinode;
                        curfile.ino = header->c_inumber;
                        break;
                        curfile.dip = &header->c_dinode;
                        curfile.ino = header->c_inumber;
                        break;
-               }
-               if (checktype(header, TS_END) == GOOD) {
+
+               case TS_END:
                        curfile.ino = maxino;
                        break;
                        curfile.ino = maxino;
                        break;
-               }
-               if (checktype(header, TS_CLRI) == GOOD) {
+
+               case TS_CLRI:
                        curfile.name = "<file removal list>";
                        break;
                        curfile.name = "<file removal list>";
                        break;
-               }
-               if (checktype(header, TS_BITS) == GOOD) {
+
+               case TS_BITS:
                        curfile.name = "<file dump list>";
                        break;
                        curfile.name = "<file dump list>";
                        break;
+
+               case TS_TAPE:
+                       panic("unexpected tape header\n");
+                       /* NOTREACHED */
+
+               default:
+                       panic("unknown tape header type %d\n", spcl.c_type);
+                       /* NOTREACHED */
+
                }
                }
-               while (gethead(header) == FAIL)
-                       skipcnt++;
-       }
+       } while (header->c_type == TS_ADDR);
        if (skipcnt > 0)
                fprintf(stderr, "resync restore, skipped %d blocks\n", skipcnt);
        skipcnt = 0;
 }
 
        if (skipcnt > 0)
                fprintf(stderr, "resync restore, skipped %d blocks\n", skipcnt);
        skipcnt = 0;
 }
 
-/*
- * return whether or not the buffer contains a header block
- */
-ishead(buf)
-       struct s_spcl *buf;
-{
-
-       if (buf->c_magic != NFS_MAGIC)
-               return(FAIL);
-       return(GOOD);
-}
-
-checktype(b, t)
-       struct s_spcl *b;
-       int     t;
-{
-
-       if (b->c_type != t)
-               return(FAIL);
-       return(GOOD);
-}
-
-checksum(b)
-       register int *b;
+static int
+checksum(buf)
+       register int *buf;
 {
        register int i, j;
 
 {
        register int i, j;
 
@@ -1160,13 +1226,13 @@ checksum(b)
        i = 0;
        if(!Bcvt) {
                do
        i = 0;
        if(!Bcvt) {
                do
-                       i += *b++;
+                       i += *buf++;
                while (--j);
        } else {
                /* What happens if we want to read restore tapes
                        for a 16bit int machine??? */
                do 
                while (--j);
        } else {
                /* What happens if we want to read restore tapes
                        for a 16bit int machine??? */
                do 
-                       i += swabl(*b++);
+                       i += swabl(*buf++);
                while (--j);
        }
                        
                while (--j);
        }
                        
@@ -1179,16 +1245,33 @@ checksum(b)
 }
 
 #ifdef RRESTORE
 }
 
 #ifdef RRESTORE
-/* VARARGS1 */
-msg(cp, a1, a2, a3)
-       char *cp;
-{
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
 
 
-       fprintf(stderr, cp, a1, a2, a3);
+void
+#if __STDC__
+msg(const char *fmt, ...)
+#else
+msg(fmt, va_alist)
+       char *fmt;
+       va_dcl
+#endif
+{
+       va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
 }
 #endif /* RRESTORE */
 
 }
 #endif /* RRESTORE */
 
-u_char *
+static u_char *
 swabshort(sp, n)
        register u_char *sp;
        register int n;
 swabshort(sp, n)
        register u_char *sp;
        register int n;
@@ -1202,7 +1285,7 @@ swabshort(sp, n)
        return (sp);
 }
 
        return (sp);
 }
 
-u_char *
+static u_char *
 swablong(sp, n)
        register u_char *sp;
        register int n;
 swablong(sp, n)
        register u_char *sp;
        register int n;
@@ -1217,11 +1300,11 @@ swablong(sp, n)
        return (sp);
 }
 
        return (sp);
 }
 
+void
 swabst(cp, sp)
        register u_char *cp, *sp;
 {
        int n = 0;
 swabst(cp, sp)
        register u_char *cp, *sp;
 {
        int n = 0;
-       u_char c;
 
        while (*cp) {
                switch (*cp) {
 
        while (*cp) {
                switch (*cp) {
@@ -1253,26 +1336,10 @@ swabst(cp, sp)
        }
 }
 
        }
 }
 
-u_long
+static u_long
 swabl(x)
        u_long x;
 {
 swabl(x)
        u_long x;
 {
-       swabst("l", (char *)&x);
+       swabst((u_char *)"l", (u_char *)&x);
        return (x);
 }
        return (x);
 }
-
-#ifdef sunos
-char *
-strerror(errnum)
-       int errnum;
-{
-       extern int sys_nerr;
-       extern char *sys_errlist[];
-
-       if (errnum < sys_nerr) {
-               return(sys_errlist[errnum]);
-       } else {
-               return("bogus errno in strerror");
-       }
-}
-#endif