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

📄 inode.c

📁 Win9x下文件系统驱动的例子(EXT2)源代码。
💻 C
字号:
#include "vxd.h"

#include "shared\vxddebug.h"
#include "inode.h"
#include "super.h"
#include "ext2fs.h"
#include "unixstat.h"


#define HASH_QUEUE_SIZE 4

/**********************************
 *
 * GLOBAL DATA
 *
 **********************************/

// none


/**********************************
 *
 * STATIC DATA
 *
 **********************************/

		/*
		 */
static MUTEXHANDLE		sMutex = 0;
static TInode			**sInodeTable = 0;
static UINT				sNrsInodeTable;


/**********************************************
 *
 * STATIC HELPERS
 *
 * For all static function the following PRE CONDITION
 * holds: sMutex is entered, that is, it is safe to
 * alter the static variables (in particular sInodeTable)
 *
 *********************************************/

static ULONG UnixToWinAttrib(ext2_inode *Ext2Inode, char *FileName, int NameLen)
{
	ULONG attrib;

	attrib = 0;
	if (S_ISDIR(Ext2Inode->i_mode))
		attrib |= FILE_ATTRIBUTE_DIRECTORY;
//	if (Ext2Inode->i_mode & S_IRUSR)
//		attrib |= FILE_ATTRIBUTE_READONLY;

		/*
		 * We have a "hidden" entry, if the name starts with
		 * a dot and it's not . or ..
		 */
	if (FileName)
	{
		if (FileName[0] == '.')
		{
			if ((NameLen > 1) && (FileName[1] != '.'))
				attrib |= FILE_ATTRIBUTE_HIDDEN;
		}
	}
	return attrib;
}

static __inline UINT HashFunction(ULONG DeviceId, ULONG InodeNo)
{
	return (UINT) ((DeviceId ^ InodeNo) % sNrsInodeTable);
}




/*
 * If present, get an Inode from the InodeTable.
 * 
 * PRE:
 * <none>
 *
 * POST:
 * <none>
 *  
 * IN:
 *	Super		: Superblock of the file system the inode resides in
 *	InodeNo		: Inode nr of the Inode
 *
 * OUT
 *	<none>
 *
 * RETURNS
 *	pointer to TInode if found, otherwise 0.
 */
static TInode* InodeGetFromTable(TSuperBlock *Super, ULONG InodeNo)
{
	UINT		hash;
	TInode		*inode, *hashfirst;
	
	hash = HashFunction((ULONG) Super->Device, InodeNo);

	VxdDebugPrint(D_INODE, "InodeGetFromTable: dev=%s inono=%lu, hash=%u", 
		Super->DeviceName,
		InodeNo,
		hash);

	inode = hashfirst = sInodeTable[hash];
	if(!inode)
		return 0;

		/*
		 * loop over the (circular) list to see if it's
		 * there
		 */
	do
	{
		if (inode->Super->Device == Super->Device && inode->InodeNo == InodeNo)
			goto getfromtable_done;
	} while ( (inode = inode->InodeNext) != hashfirst);
	inode = 0;

getfromtable_done:
	VxdDebugPrint(D_INODE, "InodeGetFromTable: inode %s", inode ? "found":"not found");
	
	return inode;
}


/*
 * Create an TInode structure
 * 
 * PRE:
 * The inode is not yet present in the InodeTable, that is,
 * InodeGetFromTable returned 0.
 *
 * POST:
 * New TInode structure is created and (if succesfull) is chained 
 * in InodeTable. TInode fields initialised:
 *	inode->nrClients = 0
 *	inode->InodePrev and InodeNext --> used to chain the inode in Table
 *	inode->Super = Super
 *	inode=>ParentInode = ParentInode
 *  
 * IN:
 *	Super		: Superblock of the file system the inode resides in
 *	ParentInode	: pointer to TInode of parent inode (may be zero)
 *	InodeNo		: Inode nr of the Inode
 *
 * OUT
 *	<none>
 *
 * RETURNS
 *	pointer to TInode if created, otherwise 0.
 */
static TInode* InodeCreate(TSuperBlock *Super, TInode *ParentInode, ULONG InodeNo)
{
	UINT		hash;
	TInode		*inode, *hashfirst;

	hash = HashFunction((ULONG) Super->Device, InodeNo);

	VxdDebugPrint(D_INODE, "InodeCreate: dev=%s, inono=%lu, hash=%u", 
		Super->DeviceName,
		InodeNo,
		hash);

	inode = (TInode *) calloc(1, sizeof(TInode));
	if (!inode)
	{
		VxdDebugPrint(D_ERROR, "InodeCreate: could not alloc TInode");
		goto inocreate_err_1;
	}

		/*
		 * Set fields
		 */
	inode->ParentInode = ParentInode;
	inode->InodeNo = InodeNo;
	inode->Super = Super;
	inode->nrClients = 0;

		/*
		 * Link inode in InodeTable, put it first in list.
		 * Special treatment for empty linked list
		 */
	if ((hashfirst = sInodeTable[hash]))
	{
		hashfirst->InodePrev->InodeNext = inode;
		inode->InodePrev = hashfirst->InodePrev;
		inode->InodeNext = hashfirst;
		hashfirst->InodePrev = inode;
		sInodeTable[hash] = inode;
	}
	else
	{
		inode->InodePrev = inode->InodeNext = inode;
		sInodeTable[hash] = inode;
	}
	
inocreate_err_1:
	VxdDebugPrint(D_INODE, "InodeCreate: done");
	
	return inode;
}



/*
 * Remove a TInode object.
 *
 * PRE_CONDITION
 *	Inode is fully initialised
 *	Inode->nrClient == 0, that is, there are no more
 *	clients holding the inode
 */
static void InodeDestroy(TInode *Inode)
{
	UINT		hash;

	hash = HashFunction((ULONG) Inode->Super->Device, Inode->InodeNo);

	VxdDebugPrint(D_INODE, "InodeDestroy: dev=%s, inono=%lu, hash=%u", 
		Inode->Super->DeviceName,
		Inode->InodeNo,
		hash);

		/*
		 * Remove inode from HashTable.
		 * Special treatment if we're last item in list
		 */
	if (Inode == Inode->InodeNext)
	{
		sInodeTable[hash] = 0;
	}
	else
	{
			/*
			 * If we're head of the chain, let our
			 * neighbour be the head of the chain
			 */
		if (sInodeTable[hash] == Inode)
			sInodeTable[hash] = Inode->InodeNext;

			/*
			 * Remove us from the list
			 */
		Inode->InodePrev->InodeNext = Inode->InodeNext;
		Inode->InodeNext->InodePrev = Inode->InodePrev;
	}
		
		/*
		 * Get rid of the TInode itself
		 */
	free(Inode);

	VxdDebugPrint(D_INODE, "InodeDestroy: done");
}

/*
 * Generic function to deal with the creating/lookup of inodes.
 * 
 */
static TInode* doInodeGetInode(TSuperBlock *Super, TInode *ParentInode, ULONG InodeNo, char *FileName, int NameLen)
{
	TInode		*inode;
	ext2_inode	*ext2inode;

	inode = 0;		// assume error

	VxdDebugPrint(D_INODE, "doInodeGetInode: dev=%s, inono=%lu", 
		Super->DeviceName,
		InodeNo);

		/*
		 * Sometimes directories contain entries with InodeNo=0
		 * Don't consider this an error, just return silently
		 */
	if (!InodeNo)
		return 0;

		/*
		 * First, see if it's in the the Table, if not
		 * create a TInode and get it from disk (actually the block
		 * my be in the cache)
		 */
	if (!(inode = InodeGetFromTable(Super, InodeNo)))
	{
			/*
			 * Not present, so first create a TInode object
			 */
		if (!(inode = InodeCreate(Super, ParentInode, InodeNo)))
		{
			VxdDebugPrint(D_ERROR, "doInodeGetInode: could not create a TInode");
			goto doget_inode_done;
		}

			/*
			 * Get it from the file system
			 */
		if (!Ext2ReadInode(inode))
		{
			VxdDebugPrint(D_ERROR, "doInodeGetInode: could not readinode from disk");

			InodeDestroy(inode);
			inode = (TInode *) 0;
			goto doget_inode_done;
		}

		ext2inode = InodeLock(inode);
		inode->DosAttrib = UnixToWinAttrib(ext2inode, FileName, NameLen);
		inode->Mode = ext2inode->i_mode;
		InodeUnlock(inode);
	}

	inode->nrClients++;		// increase reference count for this inode

doget_inode_done:
	VxdDebugPrint(D_INODE, "doInodeGetInode: done (attrib=%i)", inode ? inode->DosAttrib : -1);

	return inode;
}





/**************************************
 *
 * INTERFACE ROUNTINES
 *
 **************************************/

/*
 * Get an inode (but not the root inode) relative to a directory
 * inode.
 *
 * PRE:
 * Since this function is used to get all _but_ the rootinode, the
 * root inode of a device must succesfully have been read using 
 * InodeGetRootInode.
 *
 * POST:
 * If the inode is in the InodeTable, a reference is returned, that is,
 * the nrClients is increased by one. If it's not present, a new
 * inode structure is created, chanined in the table and nrClients is
 * set to 1, next the inode is read from disk.
 *
 *
 * IN:
 *	ParentInode	: pointer to inode structure of the parent inode
 *					(this may _not_ be zero)
 *	InodeNo		: Inode nr of the Inode
 *
 * OUT:
 *	<none>
 *
 * RETURNS:
 *	pointer to TInode if succesfull, otherwise 0
 *
 */
TInode* InodeGetInode(TInode *ParentInode, ULONG InodeNo, char *FileName, int NameLen)
{
	TInode		*Inode;

		/*
		 * Basically, we are a wrapper for doInodeGetInode
		 * Our Inode resides on the same filesystem (identified by
		 * ParentInode->Super) as our parent inode
		 */
	if (!ParentInode)
	{
		VxdDebugPrint(D_ERROR, "InodeGetInode: ParentInode==0");
		return 0;
	}

	EnterMutex(sMutex, BLOCK_THREAD_IDLE);

		/*
		 * First get the inode
		 */
	Inode = doInodeGetInode(ParentInode->Super, ParentInode, InodeNo, FileName, NameLen);


	VxdDebugPrint(D_INODE, "InodeGetInode: done, Inode=%X", Inode);

	LeaveMutex(sMutex);

	return Inode;
}

TBlock* InodeGetBlock(TInode *Inode, ULONG LogicalBlockNo)
{
	TBlock		*block;
	ULONG		blockno;

	VxdDebugPrint(D_INODE, "InodeGetBlock: inode=(dev=%s, inono=%lu), lblock=%lu",
			Inode->Super->DeviceName,
			Inode->InodeNo,
			LogicalBlockNo);

	if (!(blockno = Ext2BlockMap(Inode, LogicalBlockNo)))
	{
		VxdDebugPrint(D_ERROR, "InodeGetBlock: done, could not Ext2BlockMap");
		return 0;
	}

	if (!(block = BlockGetBlock(Inode->Super->Device, blockno)))
	{
		VxdDebugPrint(D_ERROR, "InodeGetBlock: done, could not get block(dev=%s, blockno=%lu)",
				Inode->Super->DeviceName,
				blockno);
		return 0;
	}

	VxdDebugPrint(D_INODE, "InodeGetBlock: done, blockno=%lu", blockno);
	
	return block;
}



/*
 * Get the root inode
 *
 * PRE:
 * <none>
 *
 * POST:
 *
 *
 * IN:
 *	ParentInode	: pointer to inode structure of the parent inode
 *					(this may _not_ be zero)
 *	InodeNo		: Inode nr of the Inode
 *
 * OUT:
 *	<none>
 *
 * RETURNS:
 *	pointer to TInode if succesfull, otherwise 0
 *
 */
TInode* InodeGetRootInode(TSuperBlock *Super)
{
	TInode	*inode;

		/*
		 * Basically, we are a wrapper for doInodeGetInode
		 * We need the root inode of the file system identified
		 * by Super. Since we are the root inode, we have no parent
		 * inode
		 */
	EnterMutex(sMutex, BLOCK_THREAD_IDLE);

	inode = doInodeGetInode(Super, 0, EXT2_ROOT_INO, "", 0);

	LeaveMutex(sMutex);

	return inode;
}


void InodeRelease(TInode *Inode)
{
	EnterMutex(sMutex, BLOCK_THREAD_IDLE);

	VxdDebugPrint(D_INODE, "InodeReleaseInode: dev=%s, inono=%lu, inode=%X", 
		Inode->Super->DeviceName,
		Inode->InodeNo,
		Inode);

		/*
		 * Inodes are reference counted, only destroy when
		 * we have no more clients referencing it.
		 */
	if (--(Inode->nrClients) == 0)
	{
			/*
			 * Remove the TInode object from the InodeTable
			 */
		BlockRelease(Inode->Block);
		InodeDestroy(Inode);
	}
	
	VxdDebugPrint(D_INODE, "InoReleaseInode: done");
	
	LeaveMutex(sMutex);
}



void* InodeLock(TInode *Inode)
{
	return Inode->Ext2Inode;
}


void InodeUnlock(TInode *Inode)
{
}


BOOL InodeInitialise(UINT EstimatedInodesResident)
{
	sNrsInodeTable = EstimatedInodesResident / HASH_QUEUE_SIZE;

	VxdDebugPrint(D_SYSTEM, "InoInitialise: resident=%u", EstimatedInodesResident);

		/*
		 * Create sInodeTable
		 */
	if (!(sInodeTable = (TInode **) calloc(sNrsInodeTable, sizeof(TInode *))))
	{
		VxdDebugPrint(D_ERROR, "InoInitialise: could not alloc sInodeTable");
		goto ino_init_1;
	}

	sMutex = CreateMutex(0, MUTEX_MUST_COMPLETE);

	VxdDebugPrint(D_SYSTEM, "InoInitialise: done");

	return TRUE;

ino_init_1:

	VxdDebugPrint(D_SYSTEM, "InoInitialise: done");

	return FALSE;
}


void InodeCleanup()
{
	VxdDebugPrint(D_SYSTEM, "InoCleanUp");
	
	EnterMutex(sMutex, BLOCK_THREAD_IDLE);

	free(sInodeTable);

	LeaveMutex(sMutex);

	DestroyMutex(sMutex);

	VxdDebugPrint(D_SYSTEM, "InoCleanUp: done");
}


TInode* InodeCloneInode(TInode *Inode)
{
	Inode->nrClients++;
	return Inode;
}














⌨️ 快捷键说明

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