⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 restore.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
			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 + -