]> git.wh0rd.org - dump.git/blobdiff - restore/restore.c
Fix restoring of files splitted on several volumes and starting on 2nd or later tapes.
[dump.git] / restore / restore.c
index e8b9027bee6a4df93c1ddb1642d9030eb9422122..c773d9066f63a2de811133253ef0558537446ba7 100644 (file)
@@ -37,7 +37,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: restore.c,v 1.34 2004/12/14 14:07:57 stelian Exp $";
+       "$Id: restore.c,v 1.40 2010/12/06 14:26:50 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -566,6 +566,9 @@ keyval(int key)
 
 /*
  * Find unreferenced link names.
+ *
+ * This also takes care of directories which were missed by removeoldleaves(),
+ * because their inode has been reused, but excluded from the dump.
  */
 void
 findunreflinks(void)
@@ -581,14 +584,21 @@ findunreflinks(void)
                        continue;
                if (ep->e_entries == NULL)
                        continue;
-               for (j = 0; j < DIRHASH_SIZE; j++) {
+               for (j = 0; j < dirhash_size; j++) {
                        for (np = ep->e_entries[j]; np != NULL; np = np->e_sibling) {
-                               if (np->e_flags == 0) {
+                               if ((np->e_flags & ~TMPNAME) == 0) {
                                        Dprintf(stdout,
                                            "%s: remove unreferenced name\n",
                                            myname(np));
-                                       removeleaf(np);
-                                       freeentry(np);
+                                       if (np->e_type == LEAF) {
+                                               removeleaf(np);
+                                               freeentry(np);
+                                       } else {
+                                               np->e_flags |= TMPNAME;
+                                               deleteino(np->e_ino);
+                                               np->e_next = removelist;
+                                               removelist = np;
+                                       }
                                }
                        }
                }
@@ -599,7 +609,7 @@ findunreflinks(void)
        for (ep = removelist; ep != NULL; ep = ep->e_next) {
                if (ep->e_entries == NULL)
                        continue;
-               for (j = 0; j < DIRHASH_SIZE; j++) {
+               for (j = 0; j < dirhash_size; j++) {
                        for (np = ep->e_entries[j]; np != NULL; np = np->e_sibling) {
                                if (np->e_type == LEAF) {
                                        if (np->e_flags != 0)
@@ -609,6 +619,17 @@ findunreflinks(void)
                                            myname(np));
                                        removeleaf(np);
                                        freeentry(np);
+                               } else {
+                                       if ((np->e_flags & ~TMPNAME) != 0)
+                                               badentry(np, "unreferenced with flags");
+
+                                       if (np->e_flags == 0) {
+                                               Dprintf(stdout,
+                                                   "%s: remove unreferenced name\n",
+                                                   myname(np));
+                                               np->e_next = ep->e_next;
+                                               ep->e_next = np;
+                                       }
                                }
                        }
                }
@@ -635,15 +656,19 @@ removeoldnodes(void)
                change = 0;
                prev = &removelist;
                for (ep = removelist; ep != NULL; ep = *prev) {
+                       int docont = 0;
                        if (ep->e_entries != NULL) {
                                int i;
-                               for (i = 0; i < DIRHASH_SIZE; i++) {
+                               for (i = 0; i < dirhash_size; i++) {
                                        if (ep->e_entries[i] != NULL) {
                                                prev = &ep->e_next;
-                                               continue;
+                                               docont = 1;
+                                               break;
                                        }
                                }
                        }
+                       if (docont)
+                               continue;
                        *prev = ep->e_next;
                        removenode(ep);
                        freeentry(ep);
@@ -665,7 +690,10 @@ compare_entry(struct entry *ep, int do_compare)
                badentry(ep, "unexpected file on tape");
                do_compare_error;
        }
-       if (do_compare) (void) comparefile(myname(ep));
+       if (do_compare) {
+               (void) comparefile(myname(ep));
+               skipxattr();
+       }
        ep->e_flags &= ~(NEW|EXTRACT);
 }
 
@@ -709,7 +737,6 @@ compareleaves(void)
                if (first != curfile.ino) {
                        fprintf(stderr, "expected next file %ld, got %lu\n",
                                (long)first, (unsigned long)curfile.ino);
-                       do_compare_error;
                        skipfile();
                        goto next;
                }
@@ -821,39 +848,9 @@ createleaves(char *symtabfile)
                else
                        doremove = 0;
                (void) extractfile(ep, doremove);
+               skipxattr();
                ep->e_flags &= ~(NEW|EXTRACT);
 
-finderres:
-               if ((first == curfile.ino) && (spcl.c_flags & DR_EXTATTRIBUTES)) {
-                       switch (spcl.c_extattributes) {
-                       case EXT_MACOSFNDRINFO:
-#ifdef DUMP_MACOSX
-                               (void)extractfinderinfoufs(myname(ep));
-#else
-                               msg("MacOSX not supported in this version, skipping\n");
-                               skipfile();
-#endif
-                               break;
-                       case EXT_MACOSRESFORK:
-#ifdef DUMP_MACOSX
-                               (void)extractresourceufs(myname(ep));
-#else
-                               msg("MacOSX not supported in this version, skipping\n");
-                               skipfile();
-#endif
-                               break;
-                       case EXT_ACL:
-                               msg("ACLs not supported in this version, skipping\n");
-                               skipfile();
-                               break;
-                       default:
-                               msg("unexpected inode extension %ld, skipping\n", spcl.c_extattributes);
-                               skipfile();
-                               break;
-                       }
-                       goto finderres;
-               }
-
                /*
                 * We checkpoint the restore after every tape reel, so
                 * as to simplify the amount of work required by the
@@ -907,14 +904,15 @@ createfiles(void)
        Vprintf(stdout, "Extract requested files\n");
        curfile.action = SKIP;
 #ifdef USE_QFA
-       if (tapeposflag)
-               curfile.ino = 0;
-       else
+       if (!tapeposflag) {
 #endif
                if (volinfo[1] == ROOTINO)
                        curfile.ino = 0;
                else
                        getvol((long)1);
+#ifdef USE_QFA
+       }
+#endif
        skipmaps();
        skipdirs();
        first = lowerbnd(ROOTINO);
@@ -1084,37 +1082,7 @@ createfiles(void)
                        } else {
 #endif /* USE_QFA */
                                (void) extractfile(ep, 0);
-
-finderres:
-                               if ((next == curfile.ino) && (spcl.c_flags & DR_EXTATTRIBUTES)) {
-                                       switch (spcl.c_extattributes) {
-                                       case EXT_MACOSFNDRINFO:
-#ifdef DUMP_MACOSX
-                                               (void)extractfinderinfoufs(myname(ep));
-#else
-                                               msg("MacOSX not supported in this version, skipping\n");
-                                               skipfile();
-#endif
-                                               break;
-                                       case EXT_MACOSRESFORK:
-#ifdef DUMP_MACOSX
-                                               (void)extractresourceufs(myname(ep));
-#else
-                                               msg("MacOSX not supported in this version, skipping\n");
-                                               skipfile();
-#endif
-                                               break;
-                                       case EXT_ACL:
-                                               msg("ACLs not supported in this version, skipping\n");
-                                               skipfile();
-                                               break;
-                                       default:
-                                               msg("unexpected inode extension %ld, skipping\n", spcl.c_extattributes);
-                                               skipfile();
-                                               break;
-                                       }
-                                       goto finderres;
-                               }
+                               skipxattr();
 
 #ifdef USE_QFA
                        }