X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Frestore.c;h=c773d9066f63a2de811133253ef0558537446ba7;hp=5ac6c870d56949ffe319a22414672f92c05869ce;hb=2359fe7e917ea8a52c5d523c77d29bddf6f82fce;hpb=e1abc9ce25132eef1239047a071c2c1d4822dd9f diff --git a/restore/restore.c b/restore/restore.c index 5ac6c87..c773d90 100644 --- a/restore/restore.c +++ b/restore/restore.c @@ -37,7 +37,7 @@ #ifndef lint static const char rcsid[] = - "$Id: restore.c,v 1.31 2003/03/30 15:40:39 stelian Exp $"; + "$Id: restore.c,v 1.40 2010/12/06 14:26:50 stelian Exp $"; #endif /* not lint */ #include @@ -54,8 +54,14 @@ static const char rcsid[] = #endif #include #else /* __linux__ */ +#ifdef sunos +#include +#include +#else #include +#endif #endif /* __linux__ */ + #include #include @@ -213,8 +219,11 @@ removeoldleaves(void) continue; #ifdef __linux__ (void)fprintf(stderr, "BUG! Should call delwhiteout\n"); +#else +#ifdef sunos #else delwhiteout(ep); +#endif #endif freeentry(ep); } @@ -557,25 +566,40 @@ 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) { struct entry *ep, *np; dump_ino_t i; + int j; Vprintf(stdout, "Find unreferenced names.\n"); for (i = ROOTINO; i < maxino; i++) { ep = lookupino(i); if (ep == NULL || ep->e_type == LEAF || TSTINO(i, dumpmap) == 0) continue; - for (np = ep->e_entries; np != NULL; np = np->e_sibling) { - if (np->e_flags == 0) { - Dprintf(stdout, - "%s: remove unreferenced name\n", - myname(np)); - removeleaf(np); - freeentry(np); + if (ep->e_entries == NULL) + continue; + for (j = 0; j < dirhash_size; j++) { + for (np = ep->e_entries[j]; np != NULL; np = np->e_sibling) { + if ((np->e_flags & ~TMPNAME) == 0) { + Dprintf(stdout, + "%s: remove unreferenced name\n", + myname(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; + } + } } } } @@ -583,15 +607,30 @@ findunreflinks(void) * Any leaves remaining in removed directories is unreferenced. */ for (ep = removelist; ep != NULL; ep = ep->e_next) { - for (np = ep->e_entries; np != NULL; np = np->e_sibling) { - if (np->e_type == LEAF) { - if (np->e_flags != 0) - badentry(np, "unreferenced with flags"); - Dprintf(stdout, - "%s: remove unreferenced name\n", - myname(np)); - removeleaf(np); - freeentry(np); + if (ep->e_entries == NULL) + continue; + 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) + badentry(np, "unreferenced with flags"); + Dprintf(stdout, + "%s: remove unreferenced name\n", + 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; + } + } } } } @@ -617,10 +656,19 @@ removeoldnodes(void) change = 0; prev = &removelist; for (ep = removelist; ep != NULL; ep = *prev) { + int docont = 0; if (ep->e_entries != NULL) { - prev = &ep->e_next; - continue; + int i; + for (i = 0; i < dirhash_size; i++) { + if (ep->e_entries[i] != NULL) { + prev = &ep->e_next; + docont = 1; + break; + } + } } + if (docont) + continue; *prev = ep->e_next; removenode(ep); freeentry(ep); @@ -642,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); } @@ -686,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; } @@ -798,13 +848,15 @@ createleaves(char *symtabfile) else doremove = 0; (void) extractfile(ep, doremove); + skipxattr(); ep->e_flags &= ~(NEW|EXTRACT); + /* * We checkpoint the restore after every tape reel, so * as to simplify the amount of work required by the * 'R' command. */ - next: +next: if (curvol != volno) { dumpsymtable(symtabfile, volno); skipmaps(); @@ -844,21 +896,23 @@ createfiles(void) long curvol; #ifdef USE_QFA long tnum, tmpcnt; - long long tpos, curtpos; + long long tpos, curtpos = 0; time_t tistart, tiend, titaken; + int volChg; #endif 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); @@ -907,38 +961,41 @@ createfiles(void) #ifdef USE_QFA tistart = time(NULL); if (tapeposflag) { - /* get tape position for inode (position directly) */ - (void)Inode2Tapepos(next, &tnum, &tpos, 1); - if (tpos == 0) - /* get tape position for last available inode - * (position before) */ - (void)Inode2Tapepos(next, &tnum, &tpos, 0); + /* get tape position for inode */ + (void)Inode2Tapepos(next, &tnum, &tpos, 0); if (tpos != 0) { - if (tnum != volno) + if (tnum != volno) { (void)RequestVol(tnum); + volChg = 1; + } else { + volChg = 0; + } if (GetTapePos(&curtpos) == 0) { /* curtpos +1000 ???, some drives * might be too slow */ - if (tpos != curtpos) { + if (((tpos > (curtpos + 1000)) && (volChg == 0)) || ((tpos != curtpos) && (volChg == 1))) { + volChg = 0; #ifdef DEBUG_QFA - msg("positioning tape %ld from %lld to %lld for inode %10lu ...\n", volno, curtpos, tpos, (unsigned long)next); + msg("positioning tape %ld from %lld to %lld for inode %lu ...\n", volno, curtpos, tpos, (unsigned long)next); #endif if (GotoTapePos(tpos) == 0) { #ifdef DEBUG_QFA - if (GetTapePos(&curtpos) == 0) - msg("before resync at tape position %lld (%ld, %ld, %s)\n", curtpos, next, curfile.ino, curfile.name); + if (GetTapePos(&curtpos) == 0) { + msg("before resnyc at tape position %lld (%ld, %ld, %s)\n", curtpos, next, curfile.ino, curfile.name); + } #endif ReReadInodeFromTape(next); #ifdef DEBUG_QFA - if (GetTapePos(&curtpos) == 0) - msg("after resync at tape position %lld (%ld, %ld, %s)\n", curtpos, next, curfile.ino, curfile.name); + if (GetTapePos(&curtpos) == 0) { + msg("after resnyc at tape position %lld (%ld, %ld, %s)\n", curtpos, next, curfile.ino, curfile.name); + } #endif } - } + } else { #ifdef DEBUG_QFA - else - msg("already at tape %ld position %ld for inode %10lu ...\n", volno, tpos, (unsigned long)next); + msg("already at tape %ld position %ld for inode %lu ...\n", volno, tpos, (unsigned long)next); #endif + } } } } @@ -999,9 +1056,9 @@ createfiles(void) panic("corrupted symbol table\n"); #ifdef USE_QFA if (!createtapeposflag) +#endif fprintf(stderr, "%s: (inode %lu) not found on tape\n", myname(ep), (unsigned long)next); -#endif ep->e_flags &= ~NEW; next = lowerbnd(next); } @@ -1020,13 +1077,13 @@ createfiles(void) #endif sprintf(gTps, "%ld\t%ld\t%lld\n", (unsigned long)curfile.ino, volno, curtapepos); if (write(gTapeposfd, gTps, strlen(gTps)) != (ssize_t)strlen(gTps)) - warn("error writing tapepos file.\n"); + warn("error writing tapepos file.\n"); skipfile(); - } - else { - msg("restoring %s\n", myname(ep)); + } else { #endif /* USE_QFA */ (void) extractfile(ep, 0); + skipxattr(); + #ifdef USE_QFA } #endif /* USE_QFA */ @@ -1054,8 +1111,11 @@ createlinks(void) continue; #ifdef __linux__ (void)fprintf(stderr, "BUG! Should call addwhiteout\n"); +#else +#ifdef sunos #else (void) addwhiteout(myname(ep)); +#endif #endif ep->e_flags &= ~NEW; }