]> git.wh0rd.org - dump.git/blobdiff - restore/tape.c
Changed some "panic" into "errx" for some errors when restore
[dump.git] / restore / tape.c
index 55519818bc61fc636029ee1c84a97c617aef7ac4..2f57d5fe59192541ddb9e028da896b60e67f3bf3 100644 (file)
@@ -2,7 +2,7 @@
  *     Ported to Linux's Second Extended File System as part of the
  *     dump and restore backup suit
  *     Remy Card <card@Linux.EU.Org>, 1994-1997
- *     Stelian Pop <pop@cybercable.fr>, 1999 
+ *     Stelian Pop <pop@cybercable.fr>, 1999-2000
  */
 
 /*
@@ -45,7 +45,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: tape.c,v 1.6 1999/10/13 09:57:21 stelian Exp $";
+       "$Id: tape.c,v 1.18 2000/06/25 18:42:39 stelian Exp $";
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -81,7 +81,8 @@ static const char rcsid[] =
 static long    fssize = MAXBSIZE;
 static int     mt = -1;
 static int     pipein = 0;
-static char    *magtape;
+static char    magtape[MAXPATHLEN];
+static char    magtapeprefix[MAXPATHLEN];
 static int     blkcnt;
 static int     numtrec;
 static char    *tapebuf;
@@ -124,6 +125,15 @@ static void         xtrmap __P((char *, size_t));
 static void     xtrmapskip __P((char *, size_t));
 static void     xtrskip __P((char *, size_t));
 
+#define COMPARE_ONTHEFLY 1
+
+#if COMPARE_ONTHEFLY
+static int     ifile;          /* input file for compare */
+static int     cmperror;       /* compare error */
+static void    xtrcmpfile __P((char *, size_t));
+static void    xtrcmpskip __P((char *, size_t));
+#endif
+
 static int readmapflag;
 
 /*
@@ -163,9 +173,14 @@ setinput(char *source)
                pipein++;
        }
        setuid(getuid());       /* no longer need or want root privileges */
-       magtape = strdup(source);
-       if (magtape == NULL)
-               errx(1, "Cannot allocate space for magtape buffer");
+       if (Mflag) {
+               strncpy(magtapeprefix, source, MAXPATHLEN);
+               magtapeprefix[MAXPATHLEN-1] = '\0';
+               snprintf(magtape, MAXPATHLEN, "%s%03d", source, 1);
+       }
+       else
+               strncpy(magtape, source, MAXPATHLEN);
+       magtape[MAXPATHLEN - 1] = '\0';
 }
 
 void
@@ -233,8 +248,13 @@ setup(void)
        }
        if (vflag || command == 't' || command == 'C')
                printdumpinfo();
-       if (filesys == NULL) {
-               filesys = spcl.c_filesys;
+       if (filesys[0] == '\0') {
+               char *dirptr;
+               strncpy(filesys, spcl.c_filesys, NAMELEN);
+               filesys[NAMELEN - 1] = '\0';
+               dirptr = strstr(filesys, " (dir");
+               if (dirptr != NULL)
+                       *dirptr = '\0';
        }
        dumptime = spcl.c_ddate;
        dumpdate = spcl.c_date;
@@ -256,10 +276,10 @@ setup(void)
        if (spcl.c_type != TS_CLRI)
                errx(1, "Cannot find file removal list");
        maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
-       Dprintf(stdout, "maxino = %ld\n", maxino);
+       Dprintf(stdout, "maxino = %ld\n", (long)maxino);
        map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
        if (map == NULL)
-               panic("no memory for active inode map\n");
+               errx(1, "no memory for active inode map");
        usedinomap = map;
        curfile.action = USING;
        getfile(xtrmap, xtrmapskip);
@@ -267,7 +287,7 @@ setup(void)
                errx(1, "Cannot find file dump list");
        map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
        if (map == (char *)NULL)
-               panic("no memory for file dump list\n");
+               errx(1, "no memory for file dump list");
        dumpmap = map;
        curfile.action = USING;
        getfile(xtrmap, xtrmapskip);
@@ -294,6 +314,7 @@ getvol(long nextvol)
        union u_spcl tmpspcl;
 #      define tmpbuf tmpspcl.s_spcl
        char buf[TP_BSIZE];
+       int haderror = 0;
 
        if (nextvol == 1) {
                tapesread = 0;
@@ -338,7 +359,7 @@ again:
                do      {
                        fprintf(stderr, "Specify next volume #: ");
                        (void) fflush(stderr);
-                       (void) fgets(buf, BUFSIZ, terminal);
+                       (void) fgets(buf, TP_BSIZE, terminal);
                } while (!feof(terminal) && buf[0] == '\n');
                if (feof(terminal))
                        exit(1);
@@ -353,20 +374,27 @@ again:
                return;
        }
        closemt();
-       fprintf(stderr, "Mount tape volume %ld\n", (long)newvol);
-       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(buf, BUFSIZ, terminal);
-       if (feof(terminal))
-               exit(1);
-       if (!strcmp(buf, "none\n")) {
-               terminateinput();
-               return;
+       if (Mflag) {
+               snprintf(magtape, MAXPATHLEN, "%s%03ld", magtapeprefix, newvol);
+               magtape[MAXPATHLEN - 1] = '\0';
        }
-       if (buf[0] != '\n') {
-               (void) strcpy(magtape, buf);
-               magtape[strlen(magtape) - 1] = '\0';
+       if (!Mflag || haderror) {
+               haderror = 0;
+               fprintf(stderr, "Mount tape volume %ld\n", (long)newvol);
+               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(buf, TP_BSIZE, terminal);
+               if (feof(terminal))
+                       exit(1);
+               if (!strcmp(buf, "none\n")) {
+                       terminateinput();
+                       return;
+               }
+               if (buf[0] != '\n') {
+                       (void) strcpy(magtape, buf);
+                       magtape[strlen(magtape) - 1] = '\0';
+               }
        }
 #ifdef RRESTORE
        if (host)
@@ -378,6 +406,7 @@ again:
        if (mt == -1) {
                fprintf(stderr, "Cannot open %s\n", magtape);
                volno = -1;
+               haderror = 1;
                goto again;
        }
 gethdr:
@@ -388,11 +417,13 @@ gethdr:
                Dprintf(stdout, "header read failed at %ld blocks\n", (long)blksread);
                fprintf(stderr, "tape is not dump tape\n");
                volno = 0;
+               haderror = 1;
                goto again;
        }
        if (tmpbuf.c_volume != volno) {
                fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume);
                volno = 0;
+               haderror = 1;
                goto again;
        }
        if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) {
@@ -406,6 +437,7 @@ gethdr:
                fprintf(stderr, "\twanted: %s", ctime(&dumpdate));
 #endif
                volno = 0;
+               haderror = 1;
                goto again;
        }
        tapesread |= 1 << volno;
@@ -566,9 +598,11 @@ extractfile(char *name)
                return (genliteraldir(name, curfile.ino));
 
        case IFLNK:
-       {       uid_t luid = curfile.dip->di_uid;
+       {
+#ifdef HAVE_LCHOWN
+               uid_t luid = curfile.dip->di_uid;
                gid_t lgid = curfile.dip->di_gid;
-
+#endif
                lnkbuf[0] = '\0';
                pathlen = 0;
                getfile(xtrlnkfile, xtrlnkskip);
@@ -579,7 +613,9 @@ extractfile(char *name)
                }
                if (linkit(lnkbuf, name, SYMLINK) == FAIL)
                        return (FAIL);
-               (void) chown(name, luid, lgid);
+#ifdef HAVE_LCHOWN
+               (void) lchown(name, luid, lgid);
+#endif
                return (GOOD);
        }
 
@@ -846,6 +882,63 @@ xtrnull(char *buf, size_t size)
        return;
 }
 
+#if COMPARE_ONTHEFLY
+/*
+ * Compare the next block of a file.
+ */
+static void
+xtrcmpfile(char *buf, size_t size)
+{
+       static char cmpbuf[MAXBSIZE];
+
+       if (cmperror)
+               return;
+       
+       if (read(ifile, cmpbuf, size) != size) {
+               fprintf(stderr, "%s: size has changed.\n", 
+                       curfile.name);
+               cmperror = 1;
+               return;
+       }
+       
+       if (memcmp(buf, cmpbuf, size) != 0) {
+               fprintf(stderr, "%s: tape and disk copies are different\n",
+                       curfile.name);
+               cmperror = 1;
+               return;
+       }
+}
+
+/*
+ * Skip over a hole in a file.
+ */
+static void
+xtrcmpskip(char *buf, size_t size)
+{
+       static char cmpbuf[MAXBSIZE];
+       int i;
+
+       if (cmperror)
+               return;
+       
+       if (read(ifile, cmpbuf, size) != size) {
+               fprintf(stderr, "%s: size has changed.\n", 
+                       curfile.name);
+               cmperror = 1;
+               return;
+       }
+
+       for (i = 0; i < size; ++i)
+               if (cmpbuf[i] != '\0') {
+                       fprintf(stderr, "%s: tape and disk copies are different\n",
+                               curfile.name);
+                       cmperror = 1;
+                       return;
+               }
+}
+#endif /* COMPARE_ONTHEFLY */
+
+#if !COMPARE_ONTHEFLY
 static int
 do_cmpfiles(int fd_tape, int fd_disk, long size)
 {
@@ -891,12 +984,14 @@ cmpfiles(char *tapefile, char *diskfile, struct stat *sbuf_disk)
        if (stat(tapefile, &sbuf_tape) != 0) {
                panic("Can't lstat tmp file %s: %s\n", tapefile,
                      strerror(errno));
+               compare_errors = 1;
        }
 
        if (sbuf_disk->st_size != sbuf_tape.st_size) {
                fprintf(stderr,
                        "%s: size changed from %ld to %ld.\n",
                        diskfile, (long)sbuf_tape.st_size, (long)sbuf_disk->st_size);
+               compare_errors = 1;
 #ifdef COMPARE_FAIL_KEEP_FILE
                return (0);
 #else
@@ -906,10 +1001,12 @@ cmpfiles(char *tapefile, char *diskfile, struct stat *sbuf_disk)
 
        if ((fd_tape = open(tapefile, O_RDONLY)) < 0) {
                panic("Can't open %s: %s\n", tapefile, strerror(errno));
+               compare_errors = 1;
        }
        if ((fd_disk = open(diskfile, O_RDONLY)) < 0) {
                close(fd_tape);
                panic("Can't open %s: %s\n", diskfile, strerror(errno));
+               compare_errors = 1;
        }
 
        if (do_cmpfiles(fd_tape, fd_disk, sbuf_tape.st_size)) {
@@ -917,6 +1014,7 @@ cmpfiles(char *tapefile, char *diskfile, struct stat *sbuf_disk)
                        diskfile);
                close(fd_tape);
                close(fd_disk);
+               compare_errors = 1;
 #ifdef COMPARE_FAIL_KEEP_FILE
                /* rename the file to live in /tmp */
                /* rename `tapefile' to /tmp/<basename of diskfile> */
@@ -950,19 +1048,26 @@ cmpfiles(char *tapefile, char *diskfile, struct stat *sbuf_disk)
        return (1);
 #endif
 }
+#endif /* !COMPARE_ONTHEFLY */
 
+#if !COMPARE_ONTHEFLY
 static char tmpfilename[MAXPATHLEN];
+#endif
 
 void
 comparefile(char *name)
 {
-       static char *tmpfile = NULL;
        int mode;
-       struct stat sb, stemp;
+       struct stat sb;
        int r;
+#if !COMPARE_ONTHEFLY
+       static char *tmpfile = NULL;
+       struct stat stemp;
+#endif
 
        if ((r = lstat(name, &sb)) != 0) {
                warn("%s: does not exist (%d)", name, r);
+               compare_errors = 1;
                skipfile();
                return;
        }
@@ -977,6 +1082,7 @@ comparefile(char *name)
        if (sb.st_mode != mode) {
                fprintf(stderr, "%s: mode changed from 0%o to 0%o.\n",
                        name, mode & 07777, sb.st_mode & 07777);
+               compare_errors = 1;
        }
        switch (mode & IFMT) {
        default:
@@ -998,6 +1104,7 @@ comparefile(char *name)
                if (!(sb.st_mode & S_IFLNK)) {
                        fprintf(stderr, "%s: is no longer a symbolic link\n",
                                name);
+                       compare_errors = 1;
                        return;
                }
                lnkbuf[0] = '\0';
@@ -1007,17 +1114,20 @@ comparefile(char *name)
                        fprintf(stderr,
                                "%s: zero length symbolic link (ignored)\n",
                                name);
+                       compare_errors = 1;
                        return;
                }
                if ((lsize = readlink(name, lbuf, MAXPATHLEN)) < 0) {
                        panic("readlink of %s failed: %s", name,
                              strerror(errno));
+                       compare_errors = 1;
                }
                lbuf[lsize] = 0;
                if (strcmp(lbuf, lnkbuf) != 0) {
                        fprintf(stderr,
                                "%s: symbolic link changed from %s to %s.\n",
                                name, lnkbuf, lbuf);
+                       compare_errors = 1;
                        return;
                }
                return;
@@ -1028,6 +1138,7 @@ comparefile(char *name)
                if (!(sb.st_mode & (S_IFCHR|S_IFBLK))) {
                        fprintf(stderr, "%s: no longer a special file\n",
                                name);
+                       compare_errors = 1;
                        skipfile();
                        return;
                }
@@ -1040,11 +1151,34 @@ comparefile(char *name)
                                (int)curfile.dip->di_rdev & 0xff,
                                ((int)sb.st_rdev >> 8) & 0xff,
                                (int)sb.st_rdev & 0xff);
+                       compare_errors = 1;
                }
                skipfile();
                return;
 
        case IFREG:
+#if COMPARE_ONTHEFLY
+               if ((ifile = open(name, O_RDONLY)) < 0) {
+                       panic("Can't open %s: %s\n", name, strerror(errno));
+                       skipfile();
+                       compare_errors = 1;
+               }
+               else {
+                       cmperror = 0;
+                       getfile(xtrcmpfile, xtrcmpskip);
+                       if (!cmperror) {
+                               char c;
+                               if (read(ifile, &c, 1) != 0) {
+                                       fprintf(stderr, "%s: size has changed.\n", 
+                                               name);
+                                       cmperror = 1;
+                               }
+                       }
+                       if (cmperror)
+                               compare_errors = 1;
+                       close(ifile);
+               }
+#else
                if (tmpfile == NULL) {
                        /* argument to mktemp() must not be in RO space: */
                        snprintf(tmpfilename, sizeof(tmpfilename), "%s/restoreCXXXXXX", tmpdir);
@@ -1067,6 +1201,7 @@ comparefile(char *name)
                cmpfiles(tmpfile, name, &sb);
                unlink(tmpfile);
 #endif
+#endif /* COMPARE_ONTHEFLY */
                return;
        }
        /* NOTREACHED */
@@ -1417,7 +1552,7 @@ accthdr(struct s_spcl *header)
                fprintf(stderr, "File header, ino %lu", (unsigned long)previno);
                break;
        case TS_ADDR:
-               fprintf(stderr, "File continuation header, ino %ld", previno);
+               fprintf(stderr, "File continuation header, ino %ld", (long)previno);
                break;
        case TS_END:
                fprintf(stderr, "End of tape header");