BSD 4_3 release
[unix-history] / usr / src / etc / restore / tape.c
index 6bf4ea7..ee01884 100644 (file)
@@ -1,23 +1,27 @@
-#ifndef lint
-static char sccsid[] = "@(#)tape.c     3.21    (Berkeley)      83/08/11";
-#endif
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
 
 
-/* Copyright (c) 1983 Regents of the University of California */
+#ifndef lint
+static char sccsid[] = "@(#)tape.c     5.6 (Berkeley) 5/2/86";
+#endif not lint
 
 #include "restore.h"
 
 #include "restore.h"
-#include <dumprestor.h>
+#include <protocols/dumprestore.h>
 #include <sys/ioctl.h>
 #include <sys/mtio.h>
 #include <sys/file.h>
 #include <setjmp.h>
 #include <sys/stat.h>
 
 #include <sys/ioctl.h>
 #include <sys/mtio.h>
 #include <sys/file.h>
 #include <setjmp.h>
 #include <sys/stat.h>
 
-static long    fssize;
+static long    fssize = MAXBSIZE;
 static int     mt = -1;
 static int     pipein = 0;
 static int     mt = -1;
 static int     pipein = 0;
-static char    *magtape;
-static int     bct = NTREC+1;
-static char    tbf[NTREC*TP_BSIZE];
+static char    magtape[BUFSIZ];
+static int     bct;
+static char    *tbf;
 static union   u_spcl endoftapemark;
 static long    blksread;
 static long    tapesread;
 static union   u_spcl endoftapemark;
 static long    blksread;
 static long    tapesread;
@@ -29,6 +33,8 @@ static char   *map;
 static char    lnkbuf[MAXPATHLEN + 1];
 static int     pathlen;
 
 static char    lnkbuf[MAXPATHLEN + 1];
 static int     pathlen;
 
+int            Bcvt;           /* Swap Bytes (for CCI or sun) */
+static int     Qcvt;           /* Swap quads (for sun) */
 /*
  * Set up an input source
  */
 /*
  * Set up an input source
  */
@@ -36,19 +42,25 @@ setinput(source)
        char *source;
 {
 #ifdef RRESTORE
        char *source;
 {
 #ifdef RRESTORE
-       char *host;
+       char *host, *tape;
 #endif RRESTORE
 
 #endif RRESTORE
 
+       flsht();
+       if (bflag)
+               newtapebuf(ntrec);
+       else
+               newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC);
        terminal = stdin;
 #ifdef RRESTORE
        host = source;
        terminal = stdin;
 #ifdef RRESTORE
        host = source;
-       magtape = index(host, ':');
-       if (magtape == 0) {
+       tape = index(host, ':');
+       if (tape == 0) {
 nohost:
                msg("need keyletter ``f'' and device ``host:tape''\n");
                done(1);
        }
 nohost:
                msg("need keyletter ``f'' and device ``host:tape''\n");
                done(1);
        }
-       *magtape++ = '\0';
+       *tape++ = '\0';
+       (void) strcpy(magtape, tape);
        if (rmthost(host) == 0)
                done(1);
        setuid(getuid());       /* no longer need or want root privileges */
        if (rmthost(host) == 0)
                done(1);
        setuid(getuid());       /* no longer need or want root privileges */
@@ -60,15 +72,37 @@ nohost:
                 */
                terminal = fopen("/dev/tty", "r");
                if (terminal == NULL) {
                 */
                terminal = fopen("/dev/tty", "r");
                if (terminal == NULL) {
-                       perror("open(\"/dev/tty\")");
-                       done(1);
+                       perror("Cannot open(\"/dev/tty\")");
+                       terminal = fopen("/dev/null", "r");
+                       if (terminal == NULL) {
+                               perror("Cannot open(\"/dev/null\")");
+                               done(1);
+                       }
                }
                pipein++;
        }
                }
                pipein++;
        }
-       magtape = source;
+       (void) strcpy(magtape, source);
 #endif RRESTORE
 }
 
 #endif RRESTORE
 }
 
+newtapebuf(size)
+       long size;
+{
+       static tbfsize = -1;
+
+       ntrec = size;
+       if (size <= tbfsize)
+               return;
+       if (tbf != NULL)
+               free(tbf);
+       tbf = (char *)malloc(size * TP_BSIZE);
+       if (tbf == NULL) {
+               fprintf(stderr, "Cannot allocate space for tape buffer\n");
+               done(1);
+       }
+       tbfsize = 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.
@@ -95,6 +129,8 @@ setup()
        volno = 1;
        setdumpnum();
        flsht();
        volno = 1;
        setdumpnum();
        flsht();
+       if (!pipein && !bflag)
+               findtapeblksize();
        if (gethead(&spcl) == FAIL) {
                bct--; /* push back this block */
                cvtflag++;
        if (gethead(&spcl) == FAIL) {
                bct--; /* push back this block */
                cvtflag++;
@@ -125,8 +161,9 @@ setup()
                perror("cannot stat .");
                done(1);
        }
                perror("cannot stat .");
                done(1);
        }
-       fssize = stbuf.st_blksize;
-       if (fssize <= 0 || ((fssize - 1) & fssize) != 0) {
+       if (stbuf.st_blksize > 0 && stbuf.st_blksize <= MAXBSIZE)
+               fssize = stbuf.st_blksize;
+       if (((fssize - 1) & fssize) != 0) {
                fprintf(stderr, "bad block size %d\n", fssize);
                done(1);
        }
                fprintf(stderr, "bad block size %d\n", fssize);
                done(1);
        }
@@ -176,8 +213,10 @@ getvol(nextvol)
        union u_spcl tmpspcl;
 #      define tmpbuf tmpspcl.s_spcl
 
        union u_spcl tmpspcl;
 #      define tmpbuf tmpspcl.s_spcl
 
-       if (nextvol == 1)
+       if (nextvol == 1) {
                tapesread = 0;
                tapesread = 0;
+               gettingfile = 0;
+       }
        if (pipein) {
                if (nextvol != 1)
                        panic("Changing volumes on pipe input?\n");
        if (pipein) {
                if (nextvol != 1)
                        panic("Changing volumes on pipe input?\n");
@@ -229,17 +268,24 @@ again:
                return;
        }
        closemt();
                return;
        }
        closemt();
-       fprintf(stderr, "Mount tape volume %d then type return ", newvol);
+       fprintf(stderr, "Mount tape volume %d\n", newvol);
+       fprintf(stderr, "then enter tape name (default: %s) ", magtape);
        (void) fflush(stderr);
        (void) fflush(stderr);
-       while (getc(terminal) != '\n')
-               ;
+       (void) fgets(tbf, BUFSIZ, terminal);
+       if (feof(terminal))
+               done(1);
+       if (tbf[0] != '\n') {
+               (void) strcpy(magtape, tbf);
+               magtape[strlen(magtape) - 1] = '\0';
+       }
 #ifdef RRESTORE
        if ((mt = rmtopen(magtape, 0)) == -1)
 #else
        if ((mt = open(magtape, 0)) == -1)
 #endif
        {
 #ifdef RRESTORE
        if ((mt = rmtopen(magtape, 0)) == -1)
 #else
        if ((mt = open(magtape, 0)) == -1)
 #endif
        {
-               fprintf(stderr, "Cannot open tape!\n");
+               fprintf(stderr, "Cannot open %s\n", magtape);
+               volno = -1;
                goto again;
        }
 gethdr:
                goto again;
        }
 gethdr:
@@ -323,6 +369,11 @@ extractfile(name)
                skipfile();
                return (FAIL);
 
                skipfile();
                return (FAIL);
 
+       case IFSOCK:
+               vprintf(stdout, "skipped socket %s\n", name);
+               skipfile();
+               return (GOOD);
+
        case IFDIR:
                if (mflag) {
                        ep = lookupname(name);
        case IFDIR:
                if (mflag) {
                        ep = lookupname(name);
@@ -341,14 +392,9 @@ extractfile(name)
                if (pathlen == 0) {
                        vprintf(stdout,
                            "%s: zero length symbolic link (ignored)\n", name);
                if (pathlen == 0) {
                        vprintf(stdout,
                            "%s: zero length symbolic link (ignored)\n", name);
-               } else if (symlink(lnkbuf, name) < 0) {
-                       fprintf(stderr, "%s: ", name);
-                       (void) fflush(stderr);
-                       perror("cannot create symbolic link");
-                       return (FAIL);
-               } else
-                       vprintf(stdout, "extract symbolic link %s\n", name);
-               return (GOOD);
+                       return (GOOD);
+               }
+               return (linkit(lnkbuf, name, SYMLINK));
 
        case IFCHR:
        case IFBLK:
 
        case IFCHR:
        case IFBLK:
@@ -419,6 +465,7 @@ getfile(f1, f2)
        off_t size = spcl.c_dinode.di_size;
        static char clearedbuf[MAXBSIZE];
        char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
        off_t size = spcl.c_dinode.di_size;
        static char clearedbuf[MAXBSIZE];
        char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
+       char junk[TP_BSIZE];
 
        if (checktype(&spcl, TS_END) == GOOD)
                panic("ran off end of tape\n");
 
        if (checktype(&spcl, TS_END) == GOOD)
                panic("ran off end of tape\n");
@@ -447,8 +494,12 @@ loop:
                        (*f2)(clearedbuf, size > TP_BSIZE ?
                                (long) TP_BSIZE : size);
                }
                        (*f2)(clearedbuf, size > TP_BSIZE ?
                                (long) TP_BSIZE : size);
                }
-               if ((size -= TP_BSIZE) <= 0)
+               if ((size -= TP_BSIZE) <= 0) {
+                       for (i++; i < spcl.c_count; i++)
+                               if (spcl.c_addr[i])
+                                       readtape(junk);
                        break;
                        break;
+               }
        }
        if (readhdr(&spcl) == GOOD && size > 0) {
                if (checktype(&spcl, TS_ADDR) == GOOD)
        }
        if (readhdr(&spcl) == GOOD && size > 0) {
                if (checktype(&spcl, TS_ADDR) == GOOD)
@@ -556,81 +607,114 @@ readtape(b)
        long rd, newvol;
        int cnt;
 
        long rd, newvol;
        int cnt;
 
-       if (bct >= NTREC) {
-               for (i = 0; i < NTREC; i++)
-                       ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0;
-               bct = 0;
-               cnt = NTREC*TP_BSIZE;
-               rd = 0;
-       getmore:
+       if (bct < ntrec) {
+               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;
+       cnt = ntrec*TP_BSIZE;
+       rd = 0;
+getmore:
 #ifdef RRESTORE
 #ifdef RRESTORE
-               i = rmtread(&tbf[rd], cnt);
+       i = rmtread(&tbf[rd], cnt);
 #else
 #else
-               i = read(mt, &tbf[rd], cnt);
+       i = read(mt, &tbf[rd], cnt);
 #endif
 #endif
-               if (i > 0 && i != NTREC*TP_BSIZE) {
-                       if (!pipein)
-                               panic("partial block read: %d should be %d\n",
-                                       i, NTREC*TP_BSIZE);
+       if (i > 0 && i != ntrec*TP_BSIZE) {
+               if (pipein) {
                        rd += i;
                        cnt -= i;
                        if (cnt > 0)
                                goto getmore;
                        i = rd;
                        rd += i;
                        cnt -= i;
                        if (cnt > 0)
                                goto getmore;
                        i = rd;
+               } else {
+                       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);
                }
                }
-               if (i < 0) {
-                       fprintf(stderr, "Tape read error while ");
-                       switch (curfile.action) {
-                       default:
-                               fprintf(stderr, "trying to set up tape\n");
-                               break;
-                       case UNKNOWN:
-                               fprintf(stderr, "trying to resyncronize\n");
-                               break;
-                       case USING:
-                               fprintf(stderr, "restoring %s\n", curfile.name);
-                               break;
-                       case SKIP:
-                               fprintf(stderr, "skipping over inode %d\n",
-                                       curfile.ino);
-                               break;
-                       }
-                       if (!yflag && !reply("continue"))
-                               done(1);
-                       i = NTREC*TP_BSIZE;
-                       bzero(tbf, i);
+       }
+       if (i < 0) {
+               fprintf(stderr, "Tape read error while ");
+               switch (curfile.action) {
+               default:
+                       fprintf(stderr, "trying to set up tape\n");
+                       break;
+               case UNKNOWN:
+                       fprintf(stderr, "trying to resyncronize\n");
+                       break;
+               case USING:
+                       fprintf(stderr, "restoring %s\n", curfile.name);
+                       break;
+               case SKIP:
+                       fprintf(stderr, "skipping over inode %d\n",
+                               curfile.ino);
+                       break;
+               }
+               if (!yflag && !reply("continue"))
+                       done(1);
+               i = ntrec*TP_BSIZE;
+               bzero(tbf, i);
 #ifdef RRESTORE
 #ifdef RRESTORE
-                       if (rmtseek(i, 1) < 0)
+               if (rmtseek(i, 1) < 0)
 #else
 #else
-                       if (lseek(mt, i, 1) == (long)-1)
+               if (lseek(mt, i, 1) == (long)-1)
 #endif
 #endif
-                       {
-                               perror("continuation failed");
-                               done(1);
-                       }
+               {
+                       perror("continuation failed");
+                       done(1);
                }
                }
-               if (i == 0) {
-                       if (pipein) {
-                               bcopy((char *)&endoftapemark, b,
-                                       (long)TP_BSIZE);
-                               flsht();
-                               return;
-                       }
+       }
+       if (i == 0) {
+               if (!pipein) {
                        newvol = volno + 1;
                        volno = 0;
                        getvol(newvol);
                        readtape(b);
                        return;
                }
                        newvol = volno + 1;
                        volno = 0;
                        getvol(newvol);
                        readtape(b);
                        return;
                }
+               if (rd % TP_BSIZE != 0)
+                       panic("partial block read: %d should be %d\n",
+                               rd, ntrec * TP_BSIZE);
+               bcopy((char *)&endoftapemark, &tbf[rd], (long)TP_BSIZE);
        }
        bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
        blksread++;
 }
 
        }
        bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
        blksread++;
 }
 
+findtapeblksize()
+{
+       register long i;
+
+       for (i = 0; i < ntrec; i++)
+               ((struct s_spcl *)&tbf[i * TP_BSIZE])->c_magic = 0;
+       bct = 0;
+#ifdef RRESTORE
+       i = rmtread(tbf, ntrec * TP_BSIZE);
+#else
+       i = read(mt, tbf, ntrec * TP_BSIZE);
+#endif
+       if (i <= 0) {
+               perror("Tape read error");
+               done(1);
+       }
+       if (i % TP_BSIZE != 0) {
+               fprintf(stderr, "Tape block size (%d) %s (%d)\n",
+                       i, "is not a multiple of dump block size", TP_BSIZE);
+               done(1);
+       }
+       ntrec = i / TP_BSIZE;
+       vprintf(stdout, "Tape block size is %d\n", ntrec);
+}
+
 flsht()
 {
 
 flsht()
 {
 
-       bct = NTREC+1;
+       bct = ntrec+1;
 }
 
 closemt()
 }
 
 closemt()
@@ -672,7 +756,7 @@ readhdr(b)
 gethead(buf)
        struct s_spcl *buf;
 {
 gethead(buf)
        struct s_spcl *buf;
 {
-       long i;
+       long i, *j;
        union u_ospcl {
                char dummy[TP_BSIZE];
                struct  s_ospcl {
        union u_ospcl {
                char dummy[TP_BSIZE];
                struct  s_ospcl {
@@ -703,8 +787,18 @@ gethead(buf)
 
        if (!cvtflag) {
                readtape((char *)buf);
 
        if (!cvtflag) {
                readtape((char *)buf);
-               if (buf->c_magic != NFS_MAGIC || checksum((int *)buf) == FAIL)
-                       return(FAIL);
+               if (buf->c_magic != NFS_MAGIC) {
+                       if (swabl(buf->c_magic) != NFS_MAGIC)
+                               return (FAIL);
+                       if (!Bcvt) {
+                               vprintf(stdout, "Note: Doing Byte swapping\n");
+                               Bcvt = 1;
+                       }
+               }
+               if (checksum((int *)buf) == FAIL)
+                       return (FAIL);
+               if (Bcvt)
+                       swabst("8l4s31l", (char *)buf);
                goto good;
        }
        readtape((char *)(&u_ospcl.s_ospcl));
                goto good;
        }
        readtape((char *)(&u_ospcl.s_ospcl));
@@ -734,6 +828,18 @@ gethead(buf)
        buf->c_magic = NFS_MAGIC;
 
 good:
        buf->c_magic = NFS_MAGIC;
 
 good:
+       j = buf->c_dinode.di_ic.ic_size.val;
+       i = j[1];
+       if (buf->c_dinode.di_size == 0 &&
+           (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt==0) {
+               if (*j || i) {
+                       printf("Note: Doing Quad swapping\n");
+                       Qcvt = 1;
+               }
+       }
+       if (Qcvt) {
+               j[1] = *j; *j = i;
+       }
        switch (buf->c_type) {
 
        case TS_CLRI:
        switch (buf->c_type) {
 
        case TS_CLRI:
@@ -889,9 +995,18 @@ checksum(b)
 
        j = sizeof(union u_spcl) / sizeof(int);
        i = 0;
 
        j = sizeof(union u_spcl) / sizeof(int);
        i = 0;
-       do
-               i += *b++;
-       while (--j);
+       if(!Bcvt) {
+               do
+                       i += *b++;
+               while (--j);
+       } else {
+               /* What happens if we want to read restore tapes
+                       for a 16bit int machine??? */
+               do 
+                       i += swabl(*b++);
+               while (--j);
+       }
+                       
        if (i != CHECKSUM) {
                fprintf(stderr, "Checksum error %o, inode %d file %s\n", i,
                        curfile.ino, curfile.name);
        if (i != CHECKSUM) {
                fprintf(stderr, "Checksum error %o, inode %d file %s\n", i,
                        curfile.ino, curfile.name);
@@ -909,3 +1024,34 @@ msg(cp, a1, a2, a3)
        fprintf(stderr, cp, a1, a2, a3);
 }
 #endif RRESTORE
        fprintf(stderr, cp, a1, a2, a3);
 }
 #endif RRESTORE
+
+swabst(cp, sp)
+register char *cp, *sp;
+{
+       int n = 0;
+       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':
+                       n = (n * 10) + (*cp++ - '0');
+                       continue;
+               
+               case 's': case 'w': case 'h':
+                       c = sp[0]; sp[0] = sp[1]; sp[1] = c;
+                       sp++;
+                       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;
+               }
+               sp++; /* Any other character, like 'b' counts as byte. */
+               if (n <= 1) {
+                       n = 0; cp++;
+               } else
+                       n--;
+       }
+}
+swabl(x) { unsigned long l = x; swabst("l", (char *)&l); return l; }