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

📄 yaffs_guts.c

📁 linux 镜像文件制作 用于压制yaffs2类型的文件镜像啊啊啊啊啊啊
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	return NULL;}yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev, int number,				    yaffs_ObjectType type){	yaffs_Object *theObject;	yaffs_Tnode *tn = NULL;	if (number < 0)		number = yaffs_CreateNewObjectNumber(dev);	theObject = yaffs_AllocateEmptyObject(dev);	if (!theObject)		return NULL;	if (type == YAFFS_OBJECT_TYPE_FILE) {		tn = yaffs_GetTnode(dev);		if (!tn) {			yaffs_FreeObject(theObject);			return NULL;		}	}	if (theObject) {		theObject->fake = 0;		theObject->renameAllowed = 1;		theObject->unlinkAllowed = 1;		theObject->objectId = number;		yaffs_HashObject(theObject);		theObject->variantType = type;#ifdef CONFIG_YAFFS_WINCE		yfsd_WinFileTimeNow(theObject->win_atime);		theObject->win_ctime[0] = theObject->win_mtime[0] =		    theObject->win_atime[0];		theObject->win_ctime[1] = theObject->win_mtime[1] =		    theObject->win_atime[1];#else		theObject->yst_atime = theObject->yst_mtime =		    theObject->yst_ctime = Y_CURRENT_TIME;#endif		switch (type) {		case YAFFS_OBJECT_TYPE_FILE:			theObject->variant.fileVariant.fileSize = 0;			theObject->variant.fileVariant.scannedFileSize = 0;			theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF;	/* max __u32 */			theObject->variant.fileVariant.topLevel = 0;			theObject->variant.fileVariant.top = tn;			break;		case YAFFS_OBJECT_TYPE_DIRECTORY:			YINIT_LIST_HEAD(&theObject->variant.directoryVariant.					children);			break;		case YAFFS_OBJECT_TYPE_SYMLINK:		case YAFFS_OBJECT_TYPE_HARDLINK:		case YAFFS_OBJECT_TYPE_SPECIAL:			/* No action required */			break;		case YAFFS_OBJECT_TYPE_UNKNOWN:			/* todo this should not happen */			break;		}	}	return theObject;}static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device *dev,						      int number,						      yaffs_ObjectType type){	yaffs_Object *theObject = NULL;	if (number > 0)		theObject = yaffs_FindObjectByNumber(dev, number);	if (!theObject)		theObject = yaffs_CreateNewObject(dev, number, type);	return theObject;}static YCHAR *yaffs_CloneString(const YCHAR *str){	YCHAR *newStr = NULL;	if (str && *str) {		newStr = YMALLOC((yaffs_strlen(str) + 1) * sizeof(YCHAR));		if (newStr)			yaffs_strcpy(newStr, str);	}	return newStr;}/* * Mknod (create) a new object. * equivalentObject only has meaning for a hard link; * aliasString only has meaning for a sumlink. * rdev only has meaning for devices (a subset of special objects) */static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,				       yaffs_Object *parent,				       const YCHAR *name,				       __u32 mode,				       __u32 uid,				       __u32 gid,				       yaffs_Object *equivalentObject,				       const YCHAR *aliasString, __u32 rdev){	yaffs_Object *in;	YCHAR *str = NULL;	yaffs_Device *dev = parent->myDev;	/* Check if the entry exists. If it does then fail the call since we don't want a dup.*/	if (yaffs_FindObjectByName(parent, name))		return NULL;	in = yaffs_CreateNewObject(dev, -1, type);	if (!in)		return YAFFS_FAIL;	if (type == YAFFS_OBJECT_TYPE_SYMLINK) {		str = yaffs_CloneString(aliasString);		if (!str) {			yaffs_FreeObject(in);			return NULL;		}	}	if (in) {		in->hdrChunk = 0;		in->valid = 1;		in->variantType = type;		in->yst_mode = mode;#ifdef CONFIG_YAFFS_WINCE		yfsd_WinFileTimeNow(in->win_atime);		in->win_ctime[0] = in->win_mtime[0] = in->win_atime[0];		in->win_ctime[1] = in->win_mtime[1] = in->win_atime[1];#else		in->yst_atime = in->yst_mtime = in->yst_ctime = Y_CURRENT_TIME;		in->yst_rdev = rdev;		in->yst_uid = uid;		in->yst_gid = gid;#endif		in->nDataChunks = 0;		yaffs_SetObjectName(in, name);		in->dirty = 1;		yaffs_AddObjectToDirectory(parent, in);		in->myDev = parent->myDev;		switch (type) {		case YAFFS_OBJECT_TYPE_SYMLINK:			in->variant.symLinkVariant.alias = str;			break;		case YAFFS_OBJECT_TYPE_HARDLINK:			in->variant.hardLinkVariant.equivalentObject =				equivalentObject;			in->variant.hardLinkVariant.equivalentObjectId =				equivalentObject->objectId;			ylist_add(&in->hardLinks, &equivalentObject->hardLinks);			break;		case YAFFS_OBJECT_TYPE_FILE:		case YAFFS_OBJECT_TYPE_DIRECTORY:		case YAFFS_OBJECT_TYPE_SPECIAL:		case YAFFS_OBJECT_TYPE_UNKNOWN:			/* do nothing */			break;		}		if (yaffs_UpdateObjectHeader(in, name, 0, 0, 0) < 0) {			/* Could not create the object header, fail the creation */			yaffs_DeleteObject(in);			in = NULL;		}	}	return in;}yaffs_Object *yaffs_MknodFile(yaffs_Object *parent, const YCHAR *name,			__u32 mode, __u32 uid, __u32 gid){	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_FILE, parent, name, mode,				uid, gid, NULL, NULL, 0);}yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent, const YCHAR *name,				__u32 mode, __u32 uid, __u32 gid){	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY, parent, name,				 mode, uid, gid, NULL, NULL, 0);}yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent, const YCHAR *name,				__u32 mode, __u32 uid, __u32 gid, __u32 rdev){	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode,				 uid, gid, NULL, NULL, rdev);}yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const YCHAR *name,				__u32 mode, __u32 uid, __u32 gid,				const YCHAR *alias){	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode,				uid, gid, NULL, alias, 0);}/* yaffs_Link returns the object id of the equivalent object.*/yaffs_Object *yaffs_Link(yaffs_Object *parent, const YCHAR *name,			yaffs_Object *equivalentObject){	/* Get the real object in case we were fed a hard link as an equivalent object */	equivalentObject = yaffs_GetEquivalentObject(equivalentObject);	if (yaffs_MknodObject	    (YAFFS_OBJECT_TYPE_HARDLINK, parent, name, 0, 0, 0,	     equivalentObject, NULL, 0)) {		return equivalentObject;	} else {		return NULL;	}}static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir,				const YCHAR *newName, int force, int shadows){	int unlinkOp;	int deleteOp;	yaffs_Object *existingTarget;	if (newDir == NULL)		newDir = obj->parent;	/* use the old directory */	if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {		T(YAFFS_TRACE_ALWAYS,		  (TSTR		   ("tragedy: yaffs_ChangeObjectName: newDir is not a directory"		    TENDSTR)));		YBUG();	}	/* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */	if (obj->myDev->isYaffs2)		unlinkOp = (newDir == obj->myDev->unlinkedDir);	else		unlinkOp = (newDir == obj->myDev->unlinkedDir			    && obj->variantType == YAFFS_OBJECT_TYPE_FILE);	deleteOp = (newDir == obj->myDev->deletedDir);	existingTarget = yaffs_FindObjectByName(newDir, newName);	/* If the object is a file going into the unlinked directory,	 *   then it is OK to just stuff it in since duplicate names are allowed.	 *   else only proceed if the new name does not exist and if we're putting	 *   it into a directory.	 */	if ((unlinkOp ||	     deleteOp ||	     force ||	     (shadows > 0) ||	     !existingTarget) &&	    newDir->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) {		yaffs_SetObjectName(obj, newName);		obj->dirty = 1;		yaffs_AddObjectToDirectory(newDir, obj);		if (unlinkOp)			obj->unlinked = 1;		/* If it is a deletion then we mark it as a shrink for gc purposes. */		if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows) >= 0)			return YAFFS_OK;	}	return YAFFS_FAIL;}int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName,		yaffs_Object *newDir, const YCHAR *newName){	yaffs_Object *obj = NULL;	yaffs_Object *existingTarget = NULL;	int force = 0;	if (!oldDir || oldDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)		YBUG();	if (!newDir || newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)		YBUG();#ifdef CONFIG_YAFFS_CASE_INSENSITIVE	/* Special case for case insemsitive systems (eg. WinCE).	 * While look-up is case insensitive, the name isn't.	 * Therefore we might want to change x.txt to X.txt	*/	if (oldDir == newDir && yaffs_strcmp(oldName, newName) == 0)		force = 1;#endif	else if (yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)		/* ENAMETOOLONG */		return YAFFS_FAIL;	obj = yaffs_FindObjectByName(oldDir, oldName);	if (obj && obj->renameAllowed) {		/* Now do the handling for an existing target, if there is one */		existingTarget = yaffs_FindObjectByName(newDir, newName);		if (existingTarget &&			existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&			!ylist_empty(&existingTarget->variant.directoryVariant.children)) {			/* There is a target that is a non-empty directory, so we fail */			return YAFFS_FAIL;	/* EEXIST or ENOTEMPTY */		} else if (existingTarget && existingTarget != obj) {			/* Nuke the target first, using shadowing,			 * but only if it isn't the same object			 */			yaffs_ChangeObjectName(obj, newDir, newName, force,						existingTarget->objectId);			yaffs_UnlinkObject(existingTarget);		}		return yaffs_ChangeObjectName(obj, newDir, newName, 1, 0);	}	return YAFFS_FAIL;}/*------------------------- Block Management and Page Allocation ----------------*/static int yaffs_InitialiseBlocks(yaffs_Device *dev){	int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;	dev->blockInfo = NULL;	dev->chunkBits = NULL;	dev->allocationBlock = -1;	/* force it to get a new one */	/* If the first allocation strategy fails, thry the alternate one */	dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo));	if (!dev->blockInfo) {		dev->blockInfo = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockInfo));		dev->blockInfoAlt = 1;	} else		dev->blockInfoAlt = 0;	if (dev->blockInfo) {		/* Set up dynamic blockinfo stuff. */		dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */		dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks);		if (!dev->chunkBits) {			dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks);			dev->chunkBitsAlt = 1;		} else			dev->chunkBitsAlt = 0;	}	if (dev->blockInfo && dev->chunkBits) {		memset(dev->blockInfo, 0, nBlocks * sizeof(yaffs_BlockInfo));		memset(dev->chunkBits, 0, dev->chunkBitmapStride * nBlocks);		return YAFFS_OK;	}	return YAFFS_FAIL;}static void yaffs_DeinitialiseBlocks(yaffs_Device *dev){	if (dev->blockInfoAlt && dev->blockInfo)		YFREE_ALT(dev->blockInfo);	else if (dev->blockInfo)		YFREE(dev->blockInfo);	dev->blockInfoAlt = 0;	dev->blockInfo = NULL;	if (dev->chunkBitsAlt && dev->chunkBits)		YFREE_ALT(dev->chunkBits);	else if (dev->chunkBits)		YFREE(dev->chunkBits);	dev->chunkBitsAlt = 0;	dev->chunkBits = NULL;}static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev,					yaffs_BlockInfo *bi){	int i;	__u32 seq;	yaffs_BlockInfo *b;	if (!dev->isYaffs2)		return 1;	/* disqualification only applies to yaffs2. */	if (!bi->hasShrinkHeader)		return 1;	/* can gc */	/* Find the oldest dirty sequence number if we don't know it and save it	 * so we don't have to keep recomputing it.	 */	if (!dev->oldestDirtySequence) {		seq = dev->sequenceNumber;		for (i = dev->internalStartBlock; i <= dev->internalEndBlock;				i++) {			b = yaffs_GetBlockInfo(dev, i);			if (b->blockState == YAFFS_BLOCK_STATE_FULL &&			    (b->pagesInUse - b->softDeletions) <			    dev->nChunksPerBlock && b->sequenceNumber < seq) {				seq = b->sequenceNumber;			}		}		dev->oldestDirtySequence = seq;	}	/* Can't do gc of this block if there are any blocks older than this one that have	 * discarded pages.	 */	return (bi->sequenceNumber <= dev->oldestDirtySequence);}/* FindDiretiestBlock is used to select the dirtiest block (or close enough) * for garbage collection. */static int yaffs_FindBlockForGarbageCollection(yaffs_Device *dev,					int aggressive){	int b = dev->currentDirtyChecker;	int i;	int iterations;	int dirtiest = -1;	int pagesInUse = 0;	int prioritised = 0;	yaffs_BlockInfo *bi;	int pendingPrioritisedExist = 0;	/* First let's see if we need to grab a prioritised block */	if (dev->hasPendingPrioritisedGCs) {		for (i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++) {			bi = yaffs_GetBlockInfo(dev, i);			/* yaffs_VerifyBlock(dev,bi,i); */			if (bi->gcPrioritise) {				pendingPrioritisedExist = 1;				if (bi->blockState == YAFFS_BLOCK_STATE_FULL &&				   yaffs_BlockNotDisqualifiedFromGC(dev, bi)) {					pagesInUse = (bi->pagesInUse - bi->softDeletions);					dirtiest = i;					prioritised = 1;					aggressive = 1; /* Fool the non-aggressive skip logiv below */				}			}		}		if (!pendingPrioritisedExist) /* None found, so we can clear this */			dev->hasPendingPrioritisedGCs = 0;	}	/* If we're doing aggressive GC then we are happy to take a less-dirty block, and	 * search harder.	 * else (we're doing a leasurely gc), then we only bother to do this if the	 * block has only a few pages in use.	 */	dev->nonAggressiveSkip--;	if (!aggressive && (dev->nonAggressiveSkip > 0))		return -1;	if (!prioritised)		pagesInUse =			(aggressive) ? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1;	if (aggressive)		iterations =		    dev->internalEndBlock - dev->internalStartBlock + 1;	else {		iterations =		    dev->internalEndBlock - dev->internalStartBlock + 1;		iterations = iterations / 16;		if (iterations > 200)			iterations = 200;	}	for (i = 0; i <= iterations && pagesInUse > 0 && !prioritised; i++) {		b++;		if (b < dev->internalStartBlock || b > dev->internalEndBlock)			b = dev->internalStartBlock;		if (b < dev->internalStartBlock || b > dev->internalEndBlock) {			T(YAFFS_TRACE_ERROR,			  (TSTR("**>> Block %d is not valid" TENDSTR), b));			YBUG();		}		bi = yaffs_GetBlockInfo(dev, b);		if (bi->blockState == YAFFS_BLOCK_STATE_FULL &&			(bi->pagesInUse - bi->softDeletions) < pagesInUse &&				yaffs_BlockNotDisqualifiedFromGC(dev, bi)) {			dirtiest = b;			pagesInUse = (bi->

⌨️ 快捷键说明

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