386BSD 0.1 development
[unix-history] / usr / src / sbin / restore / tape.c
index 3af0c4d..f8694e5 100644 (file)
@@ -2,21 +2,37 @@
  * Copyright (c) 1983 The Regents of the University of California.
  * All rights reserved.
  *
  * Copyright (c) 1983 The Regents of the University of California.
  * All rights reserved.
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)tape.c     5.17 (Berkeley) %G%";
+static char sccsid[] = "@(#)tape.c     5.21 (Berkeley) 2/22/91";
 #endif /* not lint */
 
 #include "restore.h"
 #endif /* not lint */
 
 #include "restore.h"
@@ -33,6 +49,7 @@ static int    mt = -1;
 static int     pipein = 0;
 static char    magtape[BUFSIZ];
 static int     bct;
 static int     pipein = 0;
 static char    magtape[BUFSIZ];
 static int     bct;
+static int     numtrec;
 static char    *tbf;
 static union   u_spcl endoftapemark;
 static long    blksread;
 static char    *tbf;
 static union   u_spcl endoftapemark;
 static long    blksread;
@@ -47,6 +64,7 @@ static int    pathlen;
 
 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();
 /*
  * Set up an input source
  */
 /*
  * Set up an input source
  */
@@ -284,11 +302,22 @@ again:
        }
        closemt();
        fprintf(stderr, "Mount tape volume %d\n", newvol);
        }
        closemt();
        fprintf(stderr, "Mount tape volume %d\n", newvol);
-       fprintf(stderr, "then enter tape name (default: %s) ", magtape);
+       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);
        if (feof(terminal))
                done(1);
        (void) fflush(stderr);
        (void) fgets(tbf, BUFSIZ, terminal);
        if (feof(terminal))
                done(1);
+       if (!strcmp(tbf, "none\n")) {
+               curfile.name = "<name unknown>";
+               curfile.action = UNKNOWN;
+               curfile.dip = (struct dinode *)NIL;
+               curfile.ino = maxino;
+               if (gettingfile) {
+                       gettingfile = 0;
+                       longjmp(restart, 1);
+               }
+       }
        if (tbf[0] != '\n') {
                (void) strcpy(magtape, tbf);
                magtape[strlen(magtape) - 1] = '\0';
        if (tbf[0] != '\n') {
                (void) strcpy(magtape, tbf);
                magtape[strlen(magtape) - 1] = '\0';
@@ -654,14 +683,16 @@ readtape(b)
        long rd, newvol;
        int cnt;
 
        long rd, newvol;
        int cnt;
 
-       if (bct < ntrec) {
+top:
+       if (bct < numtrec) {
                bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
                blksread++;
                return;
        }
        for (i = 0; i < ntrec; i++)
                ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0;
                bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
                blksread++;
                return;
        }
        for (i = 0; i < ntrec; i++)
                ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0;
-       bct = 0;
+       if (numtrec == 0)
+               numtrec = ntrec;
        cnt = ntrec*TP_BSIZE;
        rd = 0;
 getmore:
        cnt = ntrec*TP_BSIZE;
        rd = 0;
 getmore:
@@ -670,6 +701,17 @@ getmore:
 #else
        i = read(mt, &tbf[rd], cnt);
 #endif
 #else
        i = read(mt, &tbf[rd], cnt);
 #endif
+       /*
+        * Check for mid-tape short read error.
+        * If found, return rest of buffer.
+        */
+       if (numtrec < ntrec && i != 0) {
+               numtrec = ntrec;
+               goto top;
+       }
+       /*
+        * Handle partial block read.
+        */
        if (i > 0 && i != ntrec*TP_BSIZE) {
                if (pipein) {
                        rd += i;
        if (i > 0 && i != ntrec*TP_BSIZE) {
                if (pipein) {
                        rd += i;
@@ -681,10 +723,12 @@ getmore:
                        if (i % TP_BSIZE != 0)
                                panic("partial block read: %d should be %d\n",
                                        i, ntrec * TP_BSIZE);
                        if (i % TP_BSIZE != 0)
                                panic("partial block read: %d should be %d\n",
                                        i, ntrec * TP_BSIZE);
-                       bcopy((char *)&endoftapemark, &tbf[i],
-                               (long)TP_BSIZE);
+                       numtrec = i / TP_BSIZE;
                }
        }
                }
        }
+       /*
+        * Handle read error.
+        */
        if (i < 0) {
                fprintf(stderr, "Tape read error while ");
                switch (curfile.action) {
        if (i < 0) {
                fprintf(stderr, "Tape read error while ");
                switch (curfile.action) {
@@ -716,10 +760,14 @@ getmore:
                        done(1);
                }
        }
                        done(1);
                }
        }
+       /*
+        * Handle end of tape.
+        */
        if (i == 0) {
                if (!pipein) {
                        newvol = volno + 1;
                        volno = 0;
        if (i == 0) {
                if (!pipein) {
                        newvol = volno + 1;
                        volno = 0;
+                       numtrec = 0;
                        getvol(newvol);
                        readtape(b);
                        return;
                        getvol(newvol);
                        readtape(b);
                        return;
@@ -729,6 +777,7 @@ getmore:
                                rd, ntrec * TP_BSIZE);
                bcopy((char *)&endoftapemark, &tbf[rd], (long)TP_BSIZE);
        }
                                rd, ntrec * TP_BSIZE);
                bcopy((char *)&endoftapemark, &tbf[rd], (long)TP_BSIZE);
        }
+       bct = 0;
        bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
        blksread++;
 }
        bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
        blksread++;
 }
@@ -755,6 +804,7 @@ findtapeblksize()
                done(1);
        }
        ntrec = i / TP_BSIZE;
                done(1);
        }
        ntrec = i / TP_BSIZE;
+       numtrec = ntrec;
        vprintf(stdout, "Tape block size is %d\n", ntrec);
 }
 
        vprintf(stdout, "Tape block size is %d\n", ntrec);
 }
 
@@ -803,7 +853,7 @@ readhdr(b)
 gethead(buf)
        struct s_spcl *buf;
 {
 gethead(buf)
        struct s_spcl *buf;
 {
-       long i, *j;
+       long i;
        union u_ospcl {
                char dummy[TP_BSIZE];
                struct  s_ospcl {
        union u_ospcl {
                char dummy[TP_BSIZE];
                struct  s_ospcl {
@@ -875,17 +925,18 @@ gethead(buf)
        buf->c_magic = NFS_MAGIC;
 
 good:
        buf->c_magic = NFS_MAGIC;
 
 good:
-       j = buf->c_dinode.di_qsize.val;
-       i = j[1];
        if (buf->c_dinode.di_size == 0 &&
        if (buf->c_dinode.di_size == 0 &&
-           (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt==0) {
-               if (*j || i) {
+           (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt == 0) {
+               if (buf->c_dinode.di_qsize.val[0] ||
+                   buf->c_dinode.di_qsize.val[1]) {
                        printf("Note: Doing Quad swapping\n");
                        Qcvt = 1;
                }
        }
        if (Qcvt) {
                        printf("Note: Doing Quad swapping\n");
                        Qcvt = 1;
                }
        }
        if (Qcvt) {
-               j[1] = *j; *j = i;
+               i = buf->c_dinode.di_qsize.val[1];
+               buf->c_dinode.di_qsize.val[1] = buf->c_dinode.di_qsize.val[0];
+               buf->c_dinode.di_qsize.val[0] = i;
        }
        switch (buf->c_type) {
 
        }
        switch (buf->c_type) {
 
@@ -1084,12 +1135,42 @@ msg(cp, a1, a2, a3)
 }
 #endif RRESTORE
 
 }
 #endif RRESTORE
 
+u_char *
+swabshort(sp, n)
+       register u_char *sp;
+       register int n;
+{
+       char c;
+
+       while (--n >= 0) {
+               c = sp[0]; sp[0] = sp[1]; sp[1] = c;
+               sp += 2;
+       }
+       return (sp);
+}
+
+u_char *
+swablong(sp, n)
+       register u_char *sp;
+       register int n;
+{
+       char c;
+
+       while (--n >= 0) {
+               c = sp[0]; sp[0] = sp[3]; sp[3] = c;
+               c = sp[2]; sp[2] = sp[1]; sp[1] = c;
+               sp += 4;
+       }
+       return (sp);
+}
+
 swabst(cp, sp)
 swabst(cp, sp)
-register char *cp, *sp;
+       register u_char *cp, *sp;
 {
        int n = 0;
 {
        int n = 0;
-       char c;
-       while(*cp) {
+       u_char c;
+
+       while (*cp) {
                switch (*cp) {
                case '0': case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
                switch (*cp) {
                case '0': case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
@@ -1097,20 +1178,32 @@ register char *cp, *sp;
                        continue;
                
                case 's': case 'w': case 'h':
                        continue;
                
                case 's': case 'w': case 'h':
-                       c = sp[0]; sp[0] = sp[1]; sp[1] = c;
-                       sp++;
+                       if (n == 0)
+                               n = 1;
+                       sp = swabshort(sp, n);
                        break;
 
                case 'l':
                        break;
 
                case 'l':
-                       c = sp[0]; sp[0] = sp[3]; sp[3] = c;
-                       c = sp[2]; sp[2] = sp[1]; sp[1] = c;
-                       sp += 3;
+                       if (n == 0)
+                               n = 1;
+                       sp = swablong(sp, n);
+                       break;
+
+               default: /* Any other character, like 'b' counts as byte. */
+                       if (n == 0)
+                               n = 1;
+                       sp += n;
+                       break;
                }
                }
-               sp++; /* Any other character, like 'b' counts as byte. */
-               if (n <= 1) {
-                       n = 0; cp++;
-               } else
-                       n--;
+               cp++;
+               n = 0;
        }
 }
        }
 }
-swabl(x) { unsigned long l = x; swabst("l", (char *)&l); return l; }
+
+u_long
+swabl(x)
+       u_long x;
+{
+       swabst("l", (char *)&x);
+       return (x);
+}