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

📄 pass2.c

📁 早期freebsd实现
💻 C
字号:
/* * Copyright (c) 1980, 1986, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)pass2.c	8.2 (Berkeley) 2/27/94";#endif /* not lint */#include <sys/param.h>#include <sys/time.h>#include <ufs/ufs/dinode.h>#include <ufs/ufs/dir.h>#include <ufs/ffs/fs.h>#include <stdlib.h>#include <string.h>#include "fsck.h"#define MINDIRSIZE	(sizeof (struct dirtemplate))int	pass2check(), blksort();pass2(){	register struct dinode *dp;	register struct inoinfo **inpp, *inp;	struct inoinfo **inpend;	struct inodesc curino;	struct dinode dino;	char pathbuf[MAXPATHLEN + 1];	switch (statemap[ROOTINO]) {	case USTATE:		pfatal("ROOT INODE UNALLOCATED");		if (reply("ALLOCATE") == 0)			errexit("");		if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)			errexit("CANNOT ALLOCATE ROOT INODE\n");		break;	case DCLEAR:		pfatal("DUPS/BAD IN ROOT INODE");		if (reply("REALLOCATE")) {			freeino(ROOTINO);			if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)				errexit("CANNOT ALLOCATE ROOT INODE\n");			break;		}		if (reply("CONTINUE") == 0)			errexit("");		break;	case FSTATE:	case FCLEAR:		pfatal("ROOT INODE NOT DIRECTORY");		if (reply("REALLOCATE")) {			freeino(ROOTINO);			if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)				errexit("CANNOT ALLOCATE ROOT INODE\n");			break;		}		if (reply("FIX") == 0)			errexit("");		dp = ginode(ROOTINO);		dp->di_mode &= ~IFMT;		dp->di_mode |= IFDIR;		inodirty();		break;	case DSTATE:		break;	default:		errexit("BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]);	}	statemap[ROOTINO] = DFOUND;	/*	 * Sort the directory list into disk block order.	 */	qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort);	/*	 * Check the integrity of each directory.	 */	bzero((char *)&curino, sizeof(struct inodesc));	curino.id_type = DATA;	curino.id_func = pass2check;	dp = &dino;	inpend = &inpsort[inplast];	for (inpp = inpsort; inpp < inpend; inpp++) {		inp = *inpp;		if (inp->i_isize == 0)			continue;		if (inp->i_isize < MINDIRSIZE) {			direrror(inp->i_number, "DIRECTORY TOO SHORT");			inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ);			if (reply("FIX") == 1) {				dp = ginode(inp->i_number);				dp->di_size = inp->i_isize;				inodirty();				dp = &dino;			}		} else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) {			getpathname(pathbuf, inp->i_number, inp->i_number);			pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d",				pathbuf, inp->i_isize, DIRBLKSIZ);			if (preen)				printf(" (ADJUSTED)\n");			inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ);			if (preen || reply("ADJUST") == 1) {				dp = ginode(inp->i_number);				dp->di_size = roundup(inp->i_isize, DIRBLKSIZ);				inodirty();				dp = &dino;			}		}		bzero((char *)&dino, sizeof(struct dinode));		dino.di_mode = IFDIR;		dp->di_size = inp->i_isize;		bcopy((char *)&inp->i_blks[0], (char *)&dp->di_db[0],			(size_t)inp->i_numblks);		curino.id_number = inp->i_number;		curino.id_parent = inp->i_parent;		(void)ckinode(dp, &curino);	}	/*	 * Now that the parents of all directories have been found,	 * make another pass to verify the value of `..'	 */	for (inpp = inpsort; inpp < inpend; inpp++) {		inp = *inpp;		if (inp->i_parent == 0 || inp->i_isize == 0)			continue;		if (statemap[inp->i_parent] == DFOUND &&		    statemap[inp->i_number] == DSTATE)			statemap[inp->i_number] = DFOUND;		if (inp->i_dotdot == inp->i_parent ||		    inp->i_dotdot == (ino_t)-1)			continue;		if (inp->i_dotdot == 0) {			inp->i_dotdot = inp->i_parent;			fileerror(inp->i_parent, inp->i_number, "MISSING '..'");			if (reply("FIX") == 0)				continue;			(void)makeentry(inp->i_number, inp->i_parent, "..");			lncntp[inp->i_parent]--;			continue;		}		fileerror(inp->i_parent, inp->i_number,		    "BAD INODE NUMBER FOR '..'");		if (reply("FIX") == 0)			continue;		lncntp[inp->i_dotdot]++;		lncntp[inp->i_parent]--;		inp->i_dotdot = inp->i_parent;		(void)changeino(inp->i_number, "..", inp->i_parent);	}	/*	 * Mark all the directories that can be found from the root.	 */	propagate();}pass2check(idesc)	struct inodesc *idesc;{	register struct direct *dirp = idesc->id_dirp;	register struct inoinfo *inp;	int n, entrysize, ret = 0;	struct dinode *dp;	char *errmsg;	struct direct proto;	char namebuf[MAXPATHLEN + 1];	char pathbuf[MAXPATHLEN + 1];	/*	 * If converting, set directory entry type.	 */	if (doinglevel2 && dirp->d_ino > 0 && dirp->d_ino < maxino) {		dirp->d_type = typemap[dirp->d_ino];		ret |= ALTERED;	}	/* 	 * check for "."	 */	if (idesc->id_entryno != 0)		goto chk1;	if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) {		if (dirp->d_ino != idesc->id_number) {			direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'");			dirp->d_ino = idesc->id_number;			if (reply("FIX") == 1)				ret |= ALTERED;		}		if (newinofmt && dirp->d_type != DT_DIR) {			direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'");			dirp->d_type = DT_DIR;			if (reply("FIX") == 1)				ret |= ALTERED;		}		goto chk1;	}	direrror(idesc->id_number, "MISSING '.'");	proto.d_ino = idesc->id_number;	if (newinofmt)		proto.d_type = DT_DIR;	else		proto.d_type = 0;	proto.d_namlen = 1;	(void)strcpy(proto.d_name, ".");	entrysize = DIRSIZ(0, &proto);	if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {		pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",			dirp->d_name);	} else if (dirp->d_reclen < entrysize) {		pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");	} else if (dirp->d_reclen < 2 * entrysize) {		proto.d_reclen = dirp->d_reclen;		bcopy((char *)&proto, (char *)dirp, (size_t)entrysize);		if (reply("FIX") == 1)			ret |= ALTERED;	} else {		n = dirp->d_reclen - entrysize;		proto.d_reclen = entrysize;		bcopy((char *)&proto, (char *)dirp, (size_t)entrysize);		idesc->id_entryno++;		lncntp[dirp->d_ino]--;		dirp = (struct direct *)((char *)(dirp) + entrysize);		bzero((char *)dirp, (size_t)n);		dirp->d_reclen = n;		if (reply("FIX") == 1)			ret |= ALTERED;	}chk1:	if (idesc->id_entryno > 1)		goto chk2;	inp = getinoinfo(idesc->id_number);	proto.d_ino = inp->i_parent;	if (newinofmt)		proto.d_type = DT_DIR;	else		proto.d_type = 0;	proto.d_namlen = 2;	(void)strcpy(proto.d_name, "..");	entrysize = DIRSIZ(0, &proto);	if (idesc->id_entryno == 0) {		n = DIRSIZ(0, dirp);		if (dirp->d_reclen < n + entrysize)			goto chk2;		proto.d_reclen = dirp->d_reclen - n;		dirp->d_reclen = n;		idesc->id_entryno++;		lncntp[dirp->d_ino]--;		dirp = (struct direct *)((char *)(dirp) + n);		bzero((char *)dirp, (size_t)proto.d_reclen);		dirp->d_reclen = proto.d_reclen;	}	if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) {		inp->i_dotdot = dirp->d_ino;		if (newinofmt && dirp->d_type != DT_DIR) {			direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'");			dirp->d_type = DT_DIR;			if (reply("FIX") == 1)				ret |= ALTERED;		}		goto chk2;	}	if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) {		fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");		pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n",			dirp->d_name);		inp->i_dotdot = (ino_t)-1;	} else if (dirp->d_reclen < entrysize) {		fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");		pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");		inp->i_dotdot = (ino_t)-1;	} else if (inp->i_parent != 0) {		/*		 * We know the parent, so fix now.		 */		inp->i_dotdot = inp->i_parent;		fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");		proto.d_reclen = dirp->d_reclen;		bcopy((char *)&proto, (char *)dirp, (size_t)entrysize);		if (reply("FIX") == 1)			ret |= ALTERED;	}	idesc->id_entryno++;	if (dirp->d_ino != 0)		lncntp[dirp->d_ino]--;	return (ret|KEEPON);chk2:	if (dirp->d_ino == 0)		return (ret|KEEPON);	if (dirp->d_namlen <= 2 &&	    dirp->d_name[0] == '.' &&	    idesc->id_entryno >= 2) {		if (dirp->d_namlen == 1) {			direrror(idesc->id_number, "EXTRA '.' ENTRY");			dirp->d_ino = 0;			if (reply("FIX") == 1)				ret |= ALTERED;			return (KEEPON | ret);		}		if (dirp->d_name[1] == '.') {			direrror(idesc->id_number, "EXTRA '..' ENTRY");			dirp->d_ino = 0;			if (reply("FIX") == 1)				ret |= ALTERED;			return (KEEPON | ret);		}	}	idesc->id_entryno++;	n = 0;	if (dirp->d_ino > maxino) {		fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE");		n = reply("REMOVE");	} else {again:		switch (statemap[dirp->d_ino]) {		case USTATE:			if (idesc->id_entryno <= 2)				break;			fileerror(idesc->id_number, dirp->d_ino, "UNALLOCATED");			n = reply("REMOVE");			break;		case DCLEAR:		case FCLEAR:			if (idesc->id_entryno <= 2)				break;			if (statemap[dirp->d_ino] == FCLEAR)				errmsg = "DUP/BAD";			else if (!preen)				errmsg = "ZERO LENGTH DIRECTORY";			else {				n = 1;				break;			}			fileerror(idesc->id_number, dirp->d_ino, errmsg);			if ((n = reply("REMOVE")) == 1)				break;			dp = ginode(dirp->d_ino);			statemap[dirp->d_ino] =			    (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE;			lncntp[dirp->d_ino] = dp->di_nlink;			goto again;		case DSTATE:			if (statemap[idesc->id_number] == DFOUND)				statemap[dirp->d_ino] = DFOUND;			/* fall through */		case DFOUND:			inp = getinoinfo(dirp->d_ino);			if (inp->i_parent != 0 && idesc->id_entryno > 2) {				getpathname(pathbuf, idesc->id_number,				    idesc->id_number);				getpathname(namebuf, dirp->d_ino, dirp->d_ino);				pwarn("%s %s %s\n", pathbuf,				    "IS AN EXTRANEOUS HARD LINK TO DIRECTORY",				    namebuf);				if (preen)					printf(" (IGNORED)\n");				else if ((n = reply("REMOVE")) == 1)					break;			}			if (idesc->id_entryno > 2)				inp->i_parent = idesc->id_number;			/* fall through */		case FSTATE:			if (newinofmt && dirp->d_type != typemap[dirp->d_ino]) {				fileerror(idesc->id_number, dirp->d_ino,				    "BAD TYPE VALUE");				dirp->d_type = typemap[dirp->d_ino];				if (reply("FIX") == 1)					ret |= ALTERED;			}			lncntp[dirp->d_ino]--;			break;		default:			errexit("BAD STATE %d FOR INODE I=%d",			    statemap[dirp->d_ino], dirp->d_ino);		}	}	if (n == 0)		return (ret|KEEPON);	dirp->d_ino = 0;	return (ret|KEEPON|ALTERED);}/* * Routine to sort disk blocks. */blksort(inpp1, inpp2)	struct inoinfo **inpp1, **inpp2;{	return ((*inpp1)->i_blks[0] - (*inpp2)->i_blks[0]);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -