]> git.wh0rd.org - dump.git/blobdiff - restore/tape.c
Fix restoring of files splitted on several volumes and starting on 2nd or later tapes.
[dump.git] / restore / tape.c
index e60921bf3b86b1afff5ce0a8666978da04fe89d7..4710f889d1cdae269f1c3c586eb594cdc401c650 100644 (file)
@@ -42,7 +42,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: tape.c,v 1.89 2005/05/02 15:10:46 stelian Exp $";
+       "$Id: tape.c,v 1.100 2010/12/06 14:26:51 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -61,6 +61,8 @@ static const char rcsid[] =
 #include <sys/file.h>
 #include <sys/mtio.h>
 #include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 
 #ifdef __linux__
 #include <sys/time.h>
@@ -346,6 +348,7 @@ setup(void)
 #endif
        FLUSHTAPEBUF();
        findtapeblksize();
+       cvtflag = 0;
        if (gethead(&spcl) == FAIL) {
                blkcnt--; /* push back this block */
                blksread--;
@@ -473,7 +476,6 @@ getvol(long nextvol)
        if (nextvol == 1) {
                tapesread = 0;
                gettingfile = 0;
-               tpblksread = 0;
                blksread = 0;
        }
        if (pipein) {
@@ -520,7 +522,8 @@ again:
                do      {
                        fprintf(stderr, "Specify next volume # (none if no more volumes): ");
                        (void) fflush(stderr);
-                       (void) fgets(buf, TP_BSIZE, terminal);
+                       if (!fgets(buf, TP_BSIZE, terminal))
+                               break;
                } while (!feof(terminal) && buf[0] == '\n');
                if (feof(terminal))
                        exit(1);
@@ -569,6 +572,8 @@ again:
        }
        if (haderror || (bot_code && !Mflag)) {
                haderror = 0;
+               if (compare_errors)
+                       fprintf(stderr, "%d compare errors so far\n", compare_errors);
 #ifdef sunos
                fprintf(stderr, "Mount volume %ld\n", (long)newvol);
 #else
@@ -581,7 +586,8 @@ again:
                fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape);
 #endif
                (void) fflush(stderr);
-               (void) fgets(buf, TP_BSIZE, terminal);
+               if (fgets(buf, TP_BSIZE, terminal))
+                       exit(1);
                if (feof(terminal))
                        exit(1);
                if (!strcmp(buf, "none\n")) {
@@ -841,9 +847,54 @@ extractfile(struct entry *ep, int doremove)
                return (FAIL);
 
        case IFSOCK:
-               Vprintf(stdout, "skipped socket %s\n", name);
+       {
+               uid_t luid = curfile.dip->di_uid;
+               gid_t lgid = curfile.dip->di_gid;
+
+               Vprintf(stdout, "extract socket %s\n", name);
                skipfile();
+               if (Nflag)
+                       return (GOOD);
+               if (! (spcl.c_flags & DR_METAONLY)) {
+                       int sk;
+                       struct sockaddr_un addr;
+
+                       if (uflag)
+                               (void)unlink(name);
+
+                       if ((sk = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
+                               warn("%s: cannot create socket", name);
+                               return (FAIL);
+                       }
+                       addr.sun_family = AF_UNIX;
+                       strcpy(addr.sun_path, name);
+                       if (bind(sk, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
+                               warn("%s: cannot create socket", name);
+                               return (FAIL);
+                       }
+                       close(sk);
+               }
+               if (chown(name, luid, lgid) < 0)
+                       warn("%s: chown", name);
+               if (chmod(name, mode) < 0)
+                       warn("%s: chmod", name);
+               extractattr(name);
+               utimes(name, timep);
+               if (flags)
+#ifdef __linux__
+                       (void) lsetflags(name, flags);
+#else
+#ifdef sunos
+                       {
+                       warn("%s: cannot call chflags", name);
+                       /* (void) chflags(name, flags); */
+                       }
+#else
+                       (void) chflags(name, flags);
+#endif
+#endif
                return (GOOD);
+       }
 
        case IFDIR:
        {
@@ -882,29 +933,36 @@ extractfile(struct entry *ep, int doremove)
                        skipfile();
 
 #ifdef HAVE_LCHOWN
-               (void) lchown(name, luid, lgid);
+               if (lchown(name, luid, lgid) < 0)
+                       warn("%s: lchown", name);
 #endif
                extractattr(name);
                return (GOOD);
        }
 
        case IFIFO:
+       {
+               uid_t luid = curfile.dip->di_uid;
+               gid_t lgid = curfile.dip->di_gid;
+
                Vprintf(stdout, "extract fifo %s\n", name);
-               if (Nflag) {
-                       skipfile();
+               skipfile();
+               if (Nflag)
                        return (GOOD);
-               }
                if (! (spcl.c_flags & DR_METAONLY)) {
                        if (uflag && !Nflag)
                                (void)unlink(name);
                        if (mkfifo(name, mode) < 0) {
                                warn("%s: cannot create fifo", name);
-                               skipfile();
                                return (FAIL);
                        }
                }
-               (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
-               (void) chmod(name, mode);
+               if (chown(name, luid, lgid) < 0)
+                       warn("%s: chown", name);
+               if (chmod(name, mode) < 0)
+                       warn("%s: chmod", name);
+               extractattr(name);
+               utimes(name, timep);
                if (flags)
 #ifdef  __linux__
                        (void) lsetflags(name, flags);
@@ -918,29 +976,33 @@ extractfile(struct entry *ep, int doremove)
                        (void) chflags(name, flags);
 #endif
 #endif
-               skipfile();
-               extractattr(name);
-               utimes(name, timep);
                return (GOOD);
-
+       }
        case IFCHR:
        case IFBLK:
+       {
+               uid_t luid = curfile.dip->di_uid;
+               gid_t lgid = curfile.dip->di_gid;
+               int lrdev = (int)curfile.dip->di_rdev;
+
                Vprintf(stdout, "extract special file %s\n", name);
-               if (Nflag) {
-                       skipfile();
+               skipfile();
+               if (Nflag)
                        return (GOOD);
-               }
                if (! (spcl.c_flags & DR_METAONLY)) {
                        if (uflag)
                                (void)unlink(name);
-                       if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
+                       if (mknod(name, mode, lrdev) < 0) {
                                warn("%s: cannot create special file", name);
-                               skipfile();
                                return (FAIL);
                        }
                }
-               (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
-               (void) chmod(name, mode);
+               if (chown(name, luid, lgid) < 0)
+                       warn("%s: chown", name);
+               if (chmod(name, mode) < 0)
+                       warn("%s: chmod", name);
+               extractattr(name);
+               utimes(name, timep);
                if (flags)
 #ifdef __linux__
                        {
@@ -960,11 +1022,8 @@ extractfile(struct entry *ep, int doremove)
                        }
 #endif
 #endif
-               skipfile();
-               extractattr(name);
-               utimes(name, timep);
                return (GOOD);
-
+       }
        case IFREG:
        {
                uid_t luid = curfile.dip->di_uid;
@@ -989,8 +1048,12 @@ extractfile(struct entry *ep, int doremove)
                }
                else
                        skipfile();
-               (void) chown(name, luid, lgid);
-               (void) chmod(name, mode);
+               if (chown(name, luid, lgid) < 0)
+                       warn("%s: chown", name);
+               if (chmod(name, mode) < 0)
+                       warn("%s: chmod", name);
+               extractattr(name);
+               utimes(name, timep);
                if (flags)
 #ifdef __linux__
                        (void) lsetflags(name, flags);
@@ -1004,8 +1067,6 @@ extractfile(struct entry *ep, int doremove)
                        (void) chflags(name, flags);
 #endif
 #endif
-               extractattr(name);
-               utimes(name, timep);
                return (GOOD);
        }
        }
@@ -1210,11 +1271,13 @@ extractresourceufs(char *name)
                /* and add the resource data from tape */
                getfile(xtrfile, xtrskip);
 
-               (void) fchown(ofile, uid, gid);
-               (void) fchmod(ofile, mode);
+               if (fchown(ofile, uid, gid) < 0)
+                       warn("%s: fchown", name);
+               if (fchmod(ofile, mode) < 0)
+                       warn("%s: fchmod", name);
                (void) close(ofile);
-               (void) lsetflags(oFileRsrc, flags);
                utimes(oFileRsrc, timep);
+               (void) lsetflags(oFileRsrc, flags);
                return (GOOD);
        }
        /* NOTREACHED */
@@ -1233,12 +1296,20 @@ readxattr(char *buffer)
                skipfile();
                return (FAIL);
        }
-       
+
        memset(xattrbuf, 0, XATTR_MAXSIZE);
        xattrlen = 0;
 
+       /*
+        * ugly hack: cope with invalid spcl.c_addr[] records written by
+        * old versions of dump.
+        */
+       readmapflag = 1;
+
        getfile(xtrxattr, xtrnull);
 
+       readmapflag = 0;
+
        memcpy(buffer, xattrbuf, XATTR_MAXSIZE);
 
        return (GOOD);
@@ -1330,7 +1401,11 @@ loop:
                        break;
                }
        }
-       if (gethead(&spcl) == GOOD && size > 0) {
+       while (gethead(&spcl) != GOOD) {
+               fprintf(stderr, "Incorrect block for %s at %ld blocks\n",
+                       curfile.name, (long)blksread);
+       }
+       if (size > 0) {
                if (spcl.c_type == TS_ADDR)
                        goto loop;
                Dprintf(stdout,
@@ -1351,7 +1426,8 @@ loop:
                last_write_was_hole = 1;
        }
        if (last_write_was_hole) {
-               FTRUNCATE(ofile, origsize);
+               if (FTRUNCATE(ofile, origsize) < 0)
+                       warn("%s: ftruncate", curfile.name);
        }
        if (!readingmaps) 
                findinode(&spcl);
@@ -2345,8 +2421,8 @@ decompress_tapebuf(struct tapebuf *tpbin, int readsize)
        }
        if (reason) {
                if (lengtherr)
-                       fprintf(stderr, "%s compressed block: %d expected: %u\n",
-                               lengtherr, readsize, tpbin->length + PREFIXSIZE);
+                       fprintf(stderr, "%s compressed block: %d expected: %lu\n",
+                               lengtherr, readsize, (unsigned long)tpbin->length + PREFIXSIZE);
                fprintf(stderr, "decompression error, block %ld: %s\n",
                        tpblksread+1, reason);
                if (!cresult)
@@ -2412,6 +2488,7 @@ findtapeblksize(void)
                errx(1, "Tape read error on first record");
 
        memcpy(&spclpt, tapebuf, TP_BSIZE);
+       cvtflag = 0;
        if (converthead(&spclpt) == FAIL) {
                cvtflag++;
                if (converthead(&spclpt) == FAIL) {
@@ -2622,7 +2699,7 @@ converthead(struct s_spcl *buf)
                if (checksum((int *)buf) == FAIL)
                        return (FAIL);
                if (Bcvt)
-                       swabst((u_char *)"8i4s31i528bi192b3i", (u_char *)buf);
+                       swabst((u_char *)"8i4s1l29i528bi192b4i", (u_char *)buf);
                goto good;
        }
        memcpy(&u_ospcl.s_ospcl, buf, TP_BSIZE);
@@ -3259,11 +3336,14 @@ ReReadInodeFromTape(dump_ino_t theino)
                cntloop++;
                gethead(&spcl);
        } while (!(spcl.c_inumber == theino && spcl.c_type == TS_INODE && spcl.c_date == dumpdate));
+
+       tpblksread = spcl.c_tapea + spcl.c_volume;
 #ifdef DEBUG_QFA
        fprintf(stderr, "DEBUG: %ld reads\n", cntloop);
        fprintf(stderr, "DEBUG: bufsize %ld\n", bufsize);
        fprintf(stderr, "DEBUG: ntrec %ld\n", ntrec);
-       fprintf(stderr, "DEBUG: %ld reads\n", cntloop);
+       fprintf(stderr, "DEBUG: tapea %d\n", spcl.c_tapea);
+       fprintf(stderr, "DEBUG: tpblksread %ld\n", tpblksread);
 #endif
        findinode(&spcl);
        noresyncmesg = 0;