📄 restore.c
字号:
newnode(ip); } else { /* changing from node to leaf */ if ((ip->e_flags & TMPNAME) == 0) mktempname(ip); deleteino(ip->e_ino); ip->e_next = removelist; removelist = ip; ip = addentry(name, ino, type); } ip->e_flags |= NEW|KEEP; dprintf(stdout, "[%s] %s: %s\n", keyval(key), name, flagvalues(ip)); break; /* * A hard link to a diirectory that has been removed. * Ignore it. */ case NAMEFND: dprintf(stdout, "[%s] %s: Extraneous name\n", keyval(key), name); descend = FAIL; break; /* * If we find a directory entry for a file that is not on * the tape, then we must have found a file that was created * while the dump was in progress. Since we have no contents * for it, we discard the name knowing that it will be on the * next incremental tape. */ case NULL: fprintf(stderr, "%s: (inode %d) not found on tape\n", name, ino); break; /* * If any of these arise, something is grievously wrong with * the current state of the symbol table. */ case INOFND|NAMEFND|MODECHG: case NAMEFND|MODECHG: case INOFND|MODECHG: fprintf(stderr, "[%s] %s: inconsistent state\n", keyval(key), name); break; /* * These states "cannot" arise for any state of the symbol table. */ case ONTAPE|MODECHG: case MODECHG: default: panic("[%s] %s: impossible state\n", keyval(key), name); break; } return (descend);}/* * Calculate the active flags in a key. */static char *keyval(key) int key;{ static char keybuf[32]; (void) strcpy(keybuf, "|NIL"); keybuf[0] = '\0'; if (key & ONTAPE) (void) strcat(keybuf, "|ONTAPE"); if (key & INOFND) (void) strcat(keybuf, "|INOFND"); if (key & NAMEFND) (void) strcat(keybuf, "|NAMEFND"); if (key & MODECHG) (void) strcat(keybuf, "|MODECHG"); return (&keybuf[1]);}/* * Find unreferenced link names. */voidfindunreflinks(){ register struct entry *ep, *np; register ino_t i; 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); } } } /* * 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); } } }}/* * Remove old nodes (directories). * Note that this routine runs in O(N*D) where: * N is the number of directory entries to be removed. * D is the maximum depth of the tree. * If N == D this can be quite slow. If the list were * topologically sorted, the deletion could be done in * time O(N). */voidremoveoldnodes(){ register struct entry *ep, **prev; long change; vprintf(stdout, "Remove old nodes (directories).\n"); do { change = 0; prev = &removelist; for (ep = removelist; ep != NULL; ep = *prev) { if (ep->e_entries != NULL) { prev = &ep->e_next; continue; } *prev = ep->e_next; removenode(ep); freeentry(ep); change++; } } while (change); for (ep = removelist; ep != NULL; ep = ep->e_next) badentry(ep, "cannot remove, non-empty");}/* * This is the routine used to extract files for the 'r' command. * Extract new leaves. */voidcreateleaves(symtabfile) char *symtabfile;{ register struct entry *ep; ino_t first; long curvol; if (command == 'R') { vprintf(stdout, "Continue extraction of new leaves\n"); } else { vprintf(stdout, "Extract new leaves.\n"); dumpsymtable(symtabfile, volno); } first = lowerbnd(ROOTINO); curvol = volno; while (curfile.ino < maxino) { first = lowerbnd(first); /* * If the next available file is not the one which we * expect then we have missed one or more files. Since * we do not request files that were not on the tape, * the lost files must have been due to a tape read error, * or a file that was removed while the dump was in progress. */ while (first < curfile.ino) { ep = lookupino(first); if (ep == NULL) panic("%d: bad first\n", first); fprintf(stderr, "%s: not found on tape\n", myname(ep)); ep->e_flags &= ~(NEW|EXTRACT); first = lowerbnd(first); } /* * If we find files on the tape that have no corresponding * directory entries, then we must have found a file that * was created while the dump was in progress. Since we have * no name for it, we discard it knowing that it will be * on the next incremental tape. */ if (first != curfile.ino) { fprintf(stderr, "expected next file %d, got %d\n", first, curfile.ino); skipfile(); goto next; } ep = lookupino(curfile.ino); if (ep == NULL) panic("unknown file on tape\n"); if ((ep->e_flags & (NEW|EXTRACT)) == 0) badentry(ep, "unexpected file on tape"); /* * If the file is to be extracted, then the old file must * be removed since its type may change from one leaf type * to another (eg "file" to "character special"). */ if ((ep->e_flags & EXTRACT) != 0) { removeleaf(ep); ep->e_flags &= ~REMOVED; } (void) extractfile(myname(ep)); ep->e_flags &= ~(NEW|EXTRACT); /* * We checkpoint the restore after every tape reel, so * as to simplify the amount of work re quired by the * 'R' command. */ next: if (curvol != volno) { dumpsymtable(symtabfile, volno); skipmaps(); curvol = volno; } }}/* * This is the routine used to extract files for the 'x' and 'i' commands. * Efficiently extract a subset of the files on a tape. */voidcreatefiles(){ register ino_t first, next, last; register struct entry *ep; long curvol; vprintf(stdout, "Extract requested files\n"); curfile.action = SKIP; getvol((long)1); skipmaps(); skipdirs(); first = lowerbnd(ROOTINO); last = upperbnd(maxino - 1); for (;;) { first = lowerbnd(first); last = upperbnd(last); /* * Check to see if any files remain to be extracted */ if (first > last) return; /* * Reject any volumes with inodes greater * than the last one needed */ while (curfile.ino > last) { curfile.action = SKIP; getvol((long)0); skipmaps(); skipdirs(); } /* * Decide on the next inode needed. * Skip across the inodes until it is found * or an out of order volume change is encountered */ next = lowerbnd(curfile.ino); do { curvol = volno; while (next > curfile.ino && volno == curvol) skipfile(); skipmaps(); skipdirs(); } while (volno == curvol + 1); /* * If volume change out of order occurred the * current state must be recalculated */ if (volno != curvol) continue; /* * If the current inode is greater than the one we were * looking for then we missed the one we were looking for. * Since we only attempt to extract files listed in the * dump map, the lost files must have been due to a tape * read error, or a file that was removed while the dump * was in progress. Thus we report all requested files * between the one we were looking for, and the one we * found as missing, and delete their request flags. */ while (next < curfile.ino) { ep = lookupino(next); if (ep == NULL) panic("corrupted symbol table\n"); fprintf(stderr, "%s: not found on tape\n", myname(ep)); ep->e_flags &= ~NEW; next = lowerbnd(next); } /* * The current inode is the one that we are looking for, * so extract it per its requested name. */ if (next == curfile.ino && next <= last) { ep = lookupino(next); if (ep == NULL) panic("corrupted symbol table\n"); (void) extractfile(myname(ep)); ep->e_flags &= ~NEW; if (volno != curvol) skipmaps(); } }}/* * Add links. */voidcreatelinks(){ register struct entry *np, *ep; register ino_t i; char name[BUFSIZ]; vprintf(stdout, "Add links\n"); for (i = ROOTINO; i < maxino; i++) { ep = lookupino(i); if (ep == NULL) continue; for (np = ep->e_links; np != NULL; np = np->e_links) { if ((np->e_flags & NEW) == 0) continue; (void) strcpy(name, myname(ep)); if (ep->e_type == NODE) { (void) linkit(name, myname(np), SYMLINK); } else { (void) linkit(name, myname(np), HARDLINK); } np->e_flags &= ~NEW; } }}/* * Check the symbol table. * We do this to insure that all the requested work was done, and * that no temporary names remain. */voidcheckrestore(){ register struct entry *ep; register ino_t i; vprintf(stdout, "Check the symbol table.\n"); for (i = ROOTINO; i < maxino; i++) { for (ep = lookupino(i); ep != NULL; ep = ep->e_links) { ep->e_flags &= ~KEEP; if (ep->e_type == NODE) ep->e_flags &= ~(NEW|EXISTED); if (ep->e_flags != NULL) badentry(ep, "incomplete operations"); } }}/* * Compare with the directory structure on the tape * A paranoid check that things are as they should be. */longverifyfile(name, ino, type) char *name; ino_t ino; int type;{ struct entry *np, *ep; long descend = GOOD; ep = lookupname(name); if (ep == NULL) { fprintf(stderr, "Warning: missing name %s\n", name); return (FAIL); } np = lookupino(ino); if (np != ep) descend = FAIL; for ( ; np != NULL; np = np->e_links) if (np == ep) break; if (np == NULL) panic("missing inumber %d\n", ino); if (ep->e_type == LEAF && type != LEAF) badentry(ep, "type should be LEAF"); return (descend);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -