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

📄 fsdvol.c

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

#include "shared\vxddebug.h"
#include "error.h"
#include "fsdfile.h"
#include "fsdvol.h"

#include "ext2fs.h"
#include "super.h"
#include "inode.h"
#include "unixstat.h"
#include "util.h"
#include "dir.h"
#include "file.h"
#include "crs.h"


//extern PVRP gVrp;


#define SUPER(ioreq) ( ((TSuperBlock *) (ioreq)->ir_rh) )

//static int __cdecl FsdShortFindNext(pioreq Ioreq) {return 0;}
//static TFindContext* FsdPrepareFindNext(pioreq Ioreq) {return 0;}
//static ext2_dir_entry* FsdDoFindNext(TFindContext	*findcontext, ext2_inode *Inode, char *ShortName) { return 0;}
//static int __cdecl FsdLfnFindNext(pioreq Ioreq) {return 0;}

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


static hndlmisc sFsdFileFunctions = 
	{
		IFS_VERSION,
		IFS_REVISION,
		NUM_HNDLMISC,

		FsdFileSeek,
		FsdFileClose,
		FsdFileCommit,	 
		FsdFileFilelocks,
		FsdFileFiletimes,
		FsdFilePiperequest,
		FsdFileHandleInfo,
		FsdFileEnumHandle
	};

static hndlmisc gFsdFindFunctions = 
	{
		IFS_VERSION,
		IFS_REVISION,
		NUM_HNDLMISC,
		{
			FsdFileEmptyFunc,
			FsdFileFindClose,
			FsdFileEmptyFunc,
			FsdFileEmptyFunc,
			FsdFileEmptyFunc,
			FsdFileEmptyFunc,
			FsdFileEmptyFunc,
			FsdFileEnumHandle
		}
	};

static char gFileSystem[] = "ext2 fs";
static char gResourceName[] = "linux";

#ifdef DEBUG
static char*	sDirActions[] =
	{
		"create",
		"delete",
		"check",
		"query8.3",
		"querylfn"
	};

static char*	sAttribActions[] =
	{
		"GET_ATTRIBUTES",
		"SET_ATTRIBUTES",
		"GET_ATTRIB_COMP_FILESIZE",
		"SET_ATTRIB_MODIFY_DATETIME",
		"GET_ATTRIB_MODIFY_DATETIME",
		"SET_ATTRIB_LAST_ACCESS_DATETIME",
		"GET_ATTRIB_LAST_ACCESS_DATETIME",
		"SET_ATTRIB_CREATION_DATETIME",
		"GET_ATTRIB_CREATION_DATETIME",
		"GET_ATTRIB_FIRST_CLUST"
	};
#endif




/**********************************
 *
 * STATIC HELPERS
 *
 **********************************/

#ifdef NYI
static PIOR CreateIOR(PVRP Vrp, DWORD opcode, DWORD flags, int Drive)
{							
	DWORD size = Vrp->VRP_max_req_size + Vrp->VRP_max_sgd * sizeof(SGD);
	DWORD offset = Vrp->VRP_delta_to_ior;
	PIOR ior = IspCreateIor((USHORT) size, (USHORT) offset, ISP_M_FL_MUST_SUCCEED);
	if (!ior)
		return NULL;

	ior->IOR_next = 0;					// used for request queueing by lots of downstream people
	ior->IOR_start_addr[1] = 0;			// assume only 32-bits worth of sector number
	ior->IOR_flags = IORF_VERSION_002 | flags;	// this is how IOS knows we're giving it a new-style IOR
	ior->IOR_private_client = offset;	// a common use for this field
	ior->IOR_req_vol_handle = (ULONG) Vrp;
	ior->IOR_sgd_lin_phys = (ULONG) (ior + 1); // where scatter/gather descriptors can be built
	ior->IOR_num_sgds = 0;				// incremented by criteria routine, so must start at zero
	ior->IOR_vol_designtr = Drive;	// drive number
	ior->IOR_func = (USHORT) opcode;

	return ior;
}

static void DestroyIOR(PIOR ior)
{
	IspDeallocMem((PVOID) ((DWORD) ior - ior->IOR_private_client));
}
#endif		/* NYI */

static void FillLfnFindData(TFindContext *FindContext, _WIN32_FIND_DATA *FindData)
{
	_QWORD			Result;
	ext2_inode		*ext2inode;

		/*
		 * We've set the attributes when we tested them for a match
		 */
	ext2inode = InodeLock(FindContext->FoundInode);

	FindData->dwFileAttributes = FindContext->FoundInode->DosAttrib;

	IFSMgr_DosToWin32Time(dateUnix2Dos(ext2inode->i_ctime), &FindData->ftCreationTime);
	IFSMgr_DosToWin32Time(dateUnix2Dos(ext2inode->i_atime), &FindData->ftLastAccessTime);
	IFSMgr_DosToWin32Time(dateUnix2Dos(ext2inode->i_mtime), &FindData->ftLastWriteTime);
	FindData->nFileSizeHigh = 0;
	FindData->nFileSizeLow = ext2inode->i_size;
		
		/*
		 * Convert to Unicode LFN FileName
		 */
	BCSToUni(FindData->cFileName, FindContext->FoundDirEntry->name, FindContext->FoundDirEntry->name_len, BCS_OEM, &Result);
	FindData->cFileName[Result.ddLower >> 1] = 0;

		/*
		 * Convert to Unicode Short FileName, make sure we do not
		 * convert . or ..
		 */
	if (isDotOrDotDot(FindContext->FoundDirEntry->name, FindContext->FoundDirEntry->name_len))
	{
		BCSToUni(FindData->cAlternateFileName, FindContext->FoundDirEntry->name, FindContext->FoundDirEntry->name_len, BCS_OEM, &Result);
		FindData->cAlternateFileName[Result.ddLower >> 1] = 0;
	}
	else
	{
		LongToShort(FindContext->FoundDirEntry->name, FindContext->FoundDirEntry->name_len, FindContext->ShortName, FindContext->FoundDirEntry->inode);
		BCSToUni(FindData->cAlternateFileName, FindContext->ShortName, strlen(FindContext->ShortName), BCS_OEM, &Result);
		FindData->cAlternateFileName[Result.ddLower >> 1] = 0;
	}

	InodeUnlock(FindContext->FoundInode);
}



static void FillShortFindData(TFindContext *FindContext, srch_entry *SearchEntry)
{
	dos_time		d;
	ext2_inode		*ext2inode;

	ext2inode = InodeLock(FindContext->FoundInode);

	SearchEntry->se_attrib = (UCHAR) FindContext->FoundInode->DosAttrib;
	d = dateUnix2Dos(ext2inode->i_mtime);
	SearchEntry->se_time = d.dt_time;
	SearchEntry->se_date = d.dt_date;
	SearchEntry->se_size = ext2inode->i_size;

	strcpy(SearchEntry->se_name, FindContext->ShortName);

	InodeUnlock(FindContext->FoundInode);
}




/*
 * Called by both FsdFindFirst and FsdSearch
 * to setup search info
 *
 */
static TFindContext* FsdPrepareFindNext(pioreq Ioreq)
{
	TFindContext	*findcontext;
	TInode			*inode;
	char			bcspathname[MAX_PATH];
	char			*filename;
	char			*path;


	VxdDebugPrint(D_VOLUME, "FsdPrepareFindNext");

	findcontext = 0;
	Ioreq->ir_error = 0;

		/*
		 * First get the bcs_pathname of the directory in which
		 * the lookup is to be performed
		 */
	if (GetBcsPath(SUPER(Ioreq)->DosDrive, Ioreq->ir_upath, bcspathname))
	{
			/*
			 * Cut off the file name part by looking for the
			 * last dirname separator
			 */
		if ((filename = strrchr(bcspathname, '/')))
		{
			path = bcspathname;
			*filename++ = 0;
		}
		else
		{
			path = "";
			filename = bcspathname;		// we only have a filename
		}

			/*
			 * Get the inode belonging to the directoryname
			 */
		if ( (inode = DirName2Inode(SUPER(Ioreq), path)))
		{

				/*
				 */
			if ((findcontext = DirCreateFindContext(inode, filename, Ioreq->ir_attr)))
			{
					/*
					 * As we peform the matching ourselves, translate 
					 * "*.*" in "*"
					 */

				if (findcontext->SearchFlags & FILE_FLAG_HAS_DOT)
				{
					findcontext->SearchFlags &= ~FILE_FLAG_HAS_DOT;
					SmartConvertDots2QuestionMark(findcontext->SearchName);
				}
			}
			else
			{
				Ioreq->ir_error = ERROR_PATH_NOT_FOUND;
				InodeRelease(inode);
			}
		}
		else
		{
			VxdDebugPrint(D_VOLUME, "FsdPrepareFindNext: path not found");	
			Ioreq->ir_error = ERROR_PATH_NOT_FOUND;
		}
	}
	else
	{
		VxdDebugPrint(D_ERROR, "FsdPrepareFindNext: could not getbcspath on:%U", Ioreq->ir_upath);
		Ioreq->ir_error = ERROR_PATH_NOT_FOUND;
	}

	VxdDebugPrint(D_VOLUME, "FsdPrepareFindNext: done");
	return findcontext;
}


static int __cdecl FsdLfnFindNext(pioreq Ioreq)
{
	TFindContext		*findcontext;

		/*
		 * Search for entry, using lfn matching scheme
		 */
	Ioreq->ir_error = 0;
	findcontext = (TFindContext	*) Ioreq->ir_fh;

	if (findcontext)
	{

		VxdDebugPrint(D_VOLUME, "FNEXT(lfn): inode=(dev=%s, ino=%lu), search=%s",
				findcontext->Inode->Super->DeviceName,
				findcontext->Inode->InodeNo,
				findcontext->SearchName);

			/*
			 * Perform a lookup on long names
			 */
		if ((DirFindEntry(findcontext, FALSE)))
		{
				/*
				/*
				 * Great! found a match...
				 * Fill in the Win32 FindData structure
				 */
			FillLfnFindData(findcontext, Ioreq->ir_data);
			BlockUnlock(findcontext->Block);
			InodeRelease(findcontext->FoundInode);
			VxdDebugPrint(D_VOLUME, "FNEXT(lfn): done, found:%U", 
				((_WIN32_FIND_DATA *) Ioreq->ir_data)->cFileName);
		}
		else
		{
			VxdDebugPrint(D_VOLUME, "FNEXT(lfn): done, no more files");
			Ioreq->ir_error = ERROR_NO_MORE_FILES;
		}
		VxdDebugFlush();
	}
	else
	{
		VxdDebugPrint(D_VOLUME, "FNEXT(lfn): done (no findcontext), no more files");
		Ioreq->ir_error = ERROR_NO_MORE_FILES;
	}

	return Ioreq->ir_error;
}



static int __cdecl FsdShortFindNext(pioreq Ioreq)
{
	TFindContext		*findcontext;
	srch_entry			*search_entry;

		/*
		 * Search for entry, using lfn matching scheme
		 */
	Ioreq->ir_error = 0;
	search_entry = (srch_entry *) Ioreq->ir_data;
	memcpy(&findcontext, search_entry->se_key.sk_localFSD, 4);

	VxdDebugPrint(D_VOLUME, "FNEXT(short): inode=(dev=%s, ino=%lu), search=%s",
			findcontext->Inode->Super->DeviceName,
			findcontext->Inode->InodeNo,
			findcontext->SearchName);

	if ((DirFindEntry(findcontext, TRUE)))
	{
			/*
			/*
			 * Great! found a match...
			 * Fill in the search entry structure
			 */
		FillShortFindData(findcontext, search_entry);
		BlockUnlock(findcontext->Block);
		InodeRelease(findcontext->FoundInode);
		VxdDebugPrint(D_VOLUME, "FNEXT(short): done, found:%s", 
			findcontext->ShortName);
	}
	else
	{
		VxdDebugPrint(D_VOLUME, "FNEXT(short): done, no more files");
		Ioreq->ir_error = ERROR_NO_MORE_FILES;
		DirDestroyFindContext(findcontext);
	}
	VxdDebugFlush();
	return Ioreq->ir_error;


#ifdef NYI
	TFindContext	*findcontext;
	ext2_inode			inode;
	ext2_dir_entry		*dir_entry;
	srch_entry			*search_entry;

		/*
		 * Search for entry, using short filename matching scheme
		 */
	Ioreq->ir_error = 0;
	search_entry = (srch_entry *) Ioreq->ir_data;
	memcpy(&findcontext, search_entry->se_key.sk_localFSD, 4);
	if ((dir_entry=FsdDoFindNext(findcontext, &inode, search_entry->se_name)))
	{
			/*
			/*
			 * Great! found a match...
			 * Fill in the search entry structure
			 */
		FillShortFindData(dir_entry, &inode, search_entry);
	}
	else
		Ioreq->ir_error = ERROR_NO_MORE_FILES;

	return Ioreq->ir_error;
#endif			/* NYI */
}




/**********************************
 *
 * INTERFACE ROUTINES
 *
 **********************************/


int __cdecl FsdVolOpen(pioreq Ioreq)
{
	char			bcsfilename[MAX_PATH];
	TFileContext	*filecontext;
	TInode			*inode;
	ext2_inode		*ext2inode;
	unsigned char	flags;

		
	VxdDebugPrint(D_VOLUME,  "FileOpen, file=%U, sfn=%lu, flags=%lu, options=%lu", 
			Ioreq->ir_upath, (ULONG) Ioreq->ir_sfn, (ULONG) Ioreq->ir_flags, (ULONG) Ioreq->ir_options);

	if (GetBcsPath(SUPER(Ioreq)->DosDrive, Ioreq->ir_upath, bcsfilename))
	{
		if ((inode = DirName2Inode(SUPER(Ioreq), bcsfilename)))
		{
			//if (!S_ISDIR(inode->Mode))
			if (S_ISREG(inode->Mode))
			{

					/*
					 * We are a read-only file system
					 */

				flags = Ioreq->ir_flags & ACCESS_MODE_MASK;
				if (	((flags == ACCESS_READONLY) || (flags != ACCESS_EXECUTE))
						&&
						((Ioreq->ir_options == ACTION_OPENEXISTING) || (Ioreq->ir_options == ACTION_OPENALWAYS)))
				{
					if ((filecontext = FileCreateFileContext(inode)))
					{
						ext2inode = InodeLock(inode);

						Ioreq->ir_hfunc->hf_read = FsdFileRead;	
						Ioreq->ir_hfunc->hf_write = FsdFileWrite;	
						Ioreq->ir_hfunc->hf_misc = &sFsdFileFunctions;
						Ioreq->ir_fh = filecontext;
						Ioreq->ir_options = ACTION_OPENED;
						Ioreq->ir_size = filecontext->FileSize;
						Ioreq->ir_attr = inode->DosAttrib;
						Ioreq->ir_dostime = dateUnix2Dos(ext2inode->i_mtime);
						Ioreq->ir_error = 0;

						InodeUnlock(inode);	
					}
					else
					{
						Ioreq->ir_error = ERROR_NOT_ENOUGH_MEMORY;
						InodeRelease(inode);
					}
				}
				else
				{
					Ioreq->ir_error = ERROR_ACCESS_DENIED;
					InodeRelease(inode);
				}
			}
			else
			{
				Ioreq->ir_error = ERROR_FILE_NOT_FOUND;
				InodeRelease(inode);
			}
		}
		else
			Ioreq->ir_error = ERROR_FILE_NOT_FOUND;
	}
	else
		Ioreq->ir_error = ERROR_FILE_NOT_FOUND;

	VxdDebugPrint(D_VOLUME,  "FileOpen, done, error=%lu", Ioreq->ir_error);
	VxdDebugFlush();

	return Ioreq->ir_error;
}



int __cdecl FsdVolIoctl16(pioreq Ioreq)
{
	CLIENT_STRUCT		*pRegs;
	PIOR				ior;
	USHORT				status;

	pRegs = (CLIENT_STRUCT*) Ioreq->ir_cregptr;	

	VxdDebugPrint(D_VOLUME, "IOCTL16, al=%x, bl=%x, cl=%x", (unsigned) _clientAL, (unsigned) _clientBL, (unsigned) _clientCL);

	Ioreq->ir_error = 5;
	VxdDebugFlush();
	return Ioreq->ir_error;

#ifdef NYI
	ior = CreateIOR((PVRP) SUPER(Ioreq)->Vrp, IOR_GEN_IOCTL, IORF_SYNC_COMMAND, SUPER(Ioreq)->DosDrive);

⌨️ 快捷键说明

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