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

📄 fatparser.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//////////////////////////////////////////////////////////////////////////////
// FatParser.cpp
//
// Implementation of class FatParser.
//////////////////////////////////////////////////////////////////////////////

// $Id: FatParser.cpp,v 1.7 1999/02/13 04:24:35 nryan Exp $

// Copyright (C) 1998 by Network Associates, Inc.
// All rights reserved.

#include <vtoolscp.h>

#include "Required.h"
#include "UtilityFunctions.h"

#include "FatParser.h"
#include "Globals.h"


////////////
// Constants
////////////

PGPUInt32	kFPFragArrayChunkSize	= 20;		// frags to allocate at once
PGPUInt32	kFPDataBufSize			= 2;		// # FAT secs at once
PGPUInt32	kFPMaxLoops				= 0x500000;	// max clusters to loop


//////////////////////////////////////////
// Class FatParser public member functions
//////////////////////////////////////////

// The FatParser path and Volume object overloaded constructor prepares for
// I/O to the specified file on the specified host.

FatParser::FatParser(LPCSTR path, PGPUInt8 hostDrive, PGPUInt32 bytesFile)
	 : FileSystemParser(path, hostDrive, bytesFile)
{
	pgpAssert(mHost.Mounted());
	pgpAssert(IsFatVolume(mFsId));

	mDataBuf		= NULL;
	mNumFragsInUse	= 0;
	mSizeFragArray	= 0;
	mFragArray		= NULL;

	mFatParserReq.isInUse = FALSE;

	mInitErr = FileSystemParser::mInitErr;

	// Note how we allocate space for one extra sector in the main sector
	// buffer. This is because FAT12 sectors can overflow sector boundaries.

	if (mInitErr.IsntError())
	{
		mInitErr = GetByteBuffer((kFPDataBufSize + 1) * mHost.GetBlockSize(), 
			&mDataBuf);
	}

	if (mInitErr.IsntError())
	{
		mInitErr = GetByteBuffer(kFPFragArrayChunkSize*sizeof(FileFrag), 
			(PGPUInt8 **) &mFragArray);

		mSizeFragArray = kFPFragArrayChunkSize;
	}

	if (mInitErr.IsntError())
	{
		mInitErr = GetFatData();
	}

	if (mInitErr.IsntError())
	{
		mInitErr = MakeFatFrags();
	}

#if PGP_DEBUG
	if (mInitErr.IsntError())
		DumpFrags();
#endif	// PGP_DEBUG
}

// The FatParser destructor is responsible for deallocating the list of frags
// and deleting the sector buffer.

FatParser::~FatParser()
{
	if (mFragArray)
		FreeByteBuffer((PGPUInt8 *) mFragArray);

	if (mDataBuf)
		FreeByteBuffer((PGPUInt8 *) mDataBuf);
}

// ReadAsync reads nBytes from the file at position pos (in bytes) 
// asynchronously.

void 
FatParser::ReadAsync(
	PGPUInt8			*buf, 
	PGPUInt64			pos, 
	PGPUInt32			nBytes, 
	GenericCallbackInfo	*upInfo)
{
	DualErr		derr;
	PGPUInt16	blockSize;

	pgpAssertAddrValid(buf, PGPUInt8);
	pgpAssertAddrValid(upInfo, GenericCallbackInfo);
	pgpAssertAddrValid(upInfo->callback, PGPUInt8);

	pgpAssertAddrValid(mFragArray, FileFrag);
	pgpAssert(mHost.Mounted());
	pgpAssert(mNumFragsInUse > 0);

	pgpAssert(!mFatParserReq.isInUse);
	mFatParserReq.isInUse = TRUE;

	blockSize = mHost.GetBlockSize();

	if (pos + nBytes > mBytesFile)
		derr = DualErr(kPGDMinorError_OOBFileRequest);

	// Prepare the request for execution.
	if (derr.IsntError())
	{
		PGPBoolean doneWithRequest;

		mFatParserReq.op = kFPOP_Read;
		mFatParserReq.upInfo = upInfo;

		mFatParserReq.downInfo.callback = FatParserCallback;
		mFatParserReq.downInfo.refData[0] = (PGPUInt32) this;

		// We start out by initializing the request so that all possible
		// pieces of the request are marked as completed.
		
		mFatParserReq.read.readHeader	= TRUE;
		mFatParserReq.read.readMiddle	= TRUE;
		mFatParserReq.read.readTail		= TRUE;

		// Now we analyze the request and determine what pieces must be
		// read so that the entire request can be marked as done.
		
		if (pos%blockSize > 0)
		{
			PGPUInt32 bytesInHeader;

			// The request has a header - that is, it doesn't begin on a
			// block boundary.
			
			bytesInHeader = min(nBytes, blockSize - (PGPUInt32) 
				(pos%blockSize));

			mFatParserReq.read.readHeader	= FALSE;
			mFatParserReq.read.bufHeader	= buf;
			mFatParserReq.read.posHeader	= pos;
			mFatParserReq.read.nBytesHeader	= bytesInHeader;

			buf		+= bytesInHeader;
			pos		+= bytesInHeader;
			nBytes	-= bytesInHeader;
		}

		if (nBytes >= blockSize)
		{
			PGPUInt32 bytesInMiddle;

			// The request has a middle - that is, a section that begins and
			// ends on a block boundary and is more than one block in length.
			
			bytesInMiddle = nBytes - nBytes%blockSize;

			mFatParserReq.read.readMiddle	= FALSE;
			mFatParserReq.read.bufMiddle	= buf;
			mFatParserReq.read.posMiddle	= pos;
			mFatParserReq.read.nBytesMiddle	= bytesInMiddle;

			buf		+= bytesInMiddle;
			pos		+= bytesInMiddle;
			nBytes	-= bytesInMiddle;
		}

		if (nBytes > 0)
		{
			// The request has a tail - that is, it doesn't end on a
			// block boundary.
			
			mFatParserReq.read.readTail		= FALSE;
			mFatParserReq.read.bufTail		= buf;
			mFatParserReq.read.posTail		= pos;
			mFatParserReq.read.nBytesTail	= nBytes;
		}

		// Execute the request.
		ExecuteRequest(&doneWithRequest);

		// Should always have stuff to do at this point. But if we don't, then
		// don't hang the computer by not calling back.

		if (doneWithRequest)
		{
			pgpAssert(FALSE);
			ScheduleAsyncCallback();
		}
	}

	// Callback on error.
	if (derr.IsError())
	{
		ScheduleAsyncCallback(derr);
	}
}

// WriteAsync writes nBytes to the file at position pos (in bytes)
// asynchronously.

void 
FatParser::WriteAsync(
	PGPUInt8			*buf, 
	PGPUInt64			pos, 
	PGPUInt32			nBytes, 
	GenericCallbackInfo	*upInfo)
{
	DualErr		derr;
	PGPUInt16	blockSize;

	pgpAssertAddrValid(buf, PGPUInt8);
	pgpAssertAddrValid(upInfo, GenericCallbackInfo);
	pgpAssertAddrValid(upInfo->callback, PGPUInt8);

	pgpAssertAddrValid(mFragArray, FileFrag);
	pgpAssert(mHost.Mounted());
	pgpAssert(mNumFragsInUse > 0);

	pgpAssert(!mFatParserReq.isInUse);
	mFatParserReq.isInUse = TRUE;

	blockSize = mHost.GetBlockSize();

	if (pos + nBytes > mBytesFile)
		derr = DualErr(kPGDMinorError_OOBFileRequest);

	// Prepare the request for execution.
	if (derr.IsntError())
	{
		PGPBoolean doneWithRequest;

		mFatParserReq.op = kFPOP_Write;
		mFatParserReq.upInfo = upInfo;

		mFatParserReq.downInfo.callback = FatParserCallback;
		mFatParserReq.downInfo.refData[0] = (PGPUInt32) this;

		// We start out by initializing the request so that all possible
		// pieces of the request are marked as completed.
		
		mFatParserReq.write.readHeader	= TRUE;
		mFatParserReq.write.wroteHeader	= TRUE;
		mFatParserReq.write.wroteMiddle	= TRUE;
		mFatParserReq.write.readTail	= TRUE;
		mFatParserReq.write.wroteTail	= TRUE;

		// Now we analyze the request and determine what pieces must be
		// written so that the entire request can be marked as done.
		
		if (pos%blockSize > 0)
		{
			PGPUInt32 bytesInHeader;

			// The request has a header - that is, it doesn't begin on a
			// block boundary.
			
			bytesInHeader = min(nBytes, blockSize - (PGPUInt32) 
				(pos%blockSize));

			mFatParserReq.write.readHeader		= FALSE;
			mFatParserReq.write.wroteHeader		= FALSE;
			mFatParserReq.write.bufHeader		= buf;
			mFatParserReq.write.posHeader		= pos;
			mFatParserReq.write.nBytesHeader	= bytesInHeader;

			buf		+= bytesInHeader;
			pos		+= bytesInHeader;
			nBytes	-= bytesInHeader;
		}

		if (nBytes >= blockSize)
		{
			PGPUInt32 bytesInMiddle;

			// The request has a middle - that is, a section that begins and
			// ends on a block boundary and is more than one block in length.
			
			bytesInMiddle = nBytes - nBytes%blockSize;

			mFatParserReq.write.wroteMiddle		= FALSE;
			mFatParserReq.write.bufMiddle		= buf;
			mFatParserReq.write.posMiddle		= pos;
			mFatParserReq.write.nBytesMiddle	= bytesInMiddle;

			buf		+= bytesInMiddle;
			pos		+= bytesInMiddle;
			nBytes	-= bytesInMiddle;
		}

		if (nBytes > 0)
		{
			// The request has a tail - that is, it doesn't end on a
			// block boundary.
			
			mFatParserReq.write.readTail	= FALSE;
			mFatParserReq.write.wroteTail	= FALSE;
			mFatParserReq.write.bufTail		= buf;
			mFatParserReq.write.posTail		= pos;
			mFatParserReq.write.nBytesTail	= nBytes;
		}

		// Execute the request.
		ExecuteRequest(&doneWithRequest);

		// Should always have stuff to do at this point. But if we don't, then
		// don't hang the computer by not calling back.

		if (doneWithRequest)
		{
			pgpAssert(FALSE);
			ScheduleAsyncCallback();
		}
	}

	// Callback on error;
	if (derr.IsError())
	{
		ScheduleAsyncCallback(derr);
	}
}

// ReadSync reads nBytes from the file at position pos (in bytes)
// synchronously.

DualErr 
FatParser::ReadSync(PGPUInt8 *buf, PGPUInt64 pos, PGPUInt32 nBytes)
{
	DualErr		derr;
	PGPUInt16	blockSize;
	PGPUInt32	bufPos, i, blocksToRead, sizeChunk;
	PGPUInt64	blockVolume;

	pgpAssertAddrValid(buf, PGPUInt8);
	pgpAssertAddrValid(mFragArray, FileFrag);
	pgpAssert(mHost.Mounted());
	pgpAssert(mNumFragsInUse > 0);
	pgpAssert(nBytes > 0);

	blockSize = mHost.GetBlockSize();

	if (pos + nBytes > mBytesFile)
		derr = DualErr(kPGDMinorError_OOBFileRequest);

	// The position (pos) and size (nBytes) variables are in bytes, but we can
	// only read from a volume in sectors. What we have to do is handle the
	// request in at most three separate pieces - a head, middle, and end.

	if (derr.IsntError())
	{
		bufPos = 0;

		if (pos%blockSize > 0)				// is there a head?
		{
			PGPUInt32 headOffset, headSize;

			i = FindFragmentIndex(pos);

			// Now read in the head.
			//
			// blockVolume = sector on disk containing the head.
			// headOffset = byte offset into blockVolume where the head starts
			// headSize = size of the head, in bytes

			blockVolume	= CalcDiskSector(pos, &mFragArray[i], blockSize);
			headOffset	= (PGPUInt32) pos%blockSize;
			headSize	= min(nBytes, blockSize - headOffset);

			derr = mHost.Read(mDataBuf, blockVolume, 1);

			if (derr.IsntError())
			{
				pgpCopyMemory(mDataBuf + headOffset, buf, headSize);

				bufPos	= headSize;
				pos		+= headSize;
				nBytes	-= headSize;
			}
		}
	}

	// Read in the middle. Since the middle may be in any number of fragments
	// on the disk, we have to use a while loop.

	if (derr.IsntError())
	{
		blocksToRead = nBytes/blockSize;

		while (derr.IsntError() && (blocksToRead > 0))	// is there a middle?
		{
			i = FindFragmentIndex(pos);

			// Determine exactly how many sectors we can read before we must
			// move onto the next file fragment.
			//
			// blockVolume = sector on disk where the current read begins
			// sizeChunk = the most sectors we can read in this iteration

			blockVolume = CalcDiskSector(pos, &mFragArray[i], blockSize);
			sizeChunk = min(blocksToRead, (PGPUInt32) 
				((mFragArray[i].fileEnd - pos) / blockSize) + 1);

			derr = mHost.Read(buf + bufPos, blockVolume, sizeChunk);

			if (derr.IsntError())
			{
				bufPos			+= sizeChunk * blockSize;
				nBytes			-= sizeChunk * blockSize;
				pos				+= sizeChunk * blockSize;
				blocksToRead	-= sizeChunk;
			}
		}
	}
	
	// Process the tail.
	if (derr.IsntError())
	{
		if (nBytes)							// is there a tail?	
		{
			i = FindFragmentIndex(pos);

			// This read is very simple because we know the tail begins on a
			// sector boundary.
			//
			// secsDisk = the sectors in disk containing the tail.

			blockVolume = CalcDiskSector(pos, &mFragArray[i], blockSize);
			derr = mHost.Read(mDataBuf, blockVolume, 1);

			if (derr.IsntError())
				pgpCopyMemory(mDataBuf, buf + bufPos, nBytes);
		}
	}

	return derr;
}

// WriteSync reads nBytes from the file at position pos (in bytes)
// synchronously.

DualErr 
FatParser::WriteSync(PGPUInt8 *buf, PGPUInt64 pos, PGPUInt32 nBytes)
{
	DualErr		derr;
	PGPUInt16	blockSize;
	PGPUInt32	bufPos, i, blocksToWrite, sizeChunk;
	PGPUInt64	blockVolume;

	pgpAssertAddrValid(buf, PGPUInt8);
	pgpAssertAddrValid(mFragArray, FileFrag);
	pgpAssert(mHost.Mounted());
	pgpAssert(mNumFragsInUse > 0);
	pgpAssert(nBytes > 0);

	blockSize = mHost.GetBlockSize();

	if (pos + nBytes > mBytesFile)
		derr = DualErr(kPGDMinorError_OOBFileRequest);

	// Process the head.
	if (derr.IsntError())
	{
		bufPos = 0;

		if (pos%blockSize > 0)				// is there a head?
		{
			PGPUInt32 headOffset, headSize;

			i = FindFragmentIndex(pos);

			// Write out the head.
			//
			// blockVolume = sector on disk containing the head
			// headOffset = byte offset into secsDisk where the head starts
			// headSize = size of the head, in bytes

			blockVolume	= CalcDiskSector(pos, &mFragArray[i], blockSize);
			headOffset	= (PGPUInt32) pos%blockSize;
			headSize	= min(nBytes, blockSize - headOffset);

			derr = mHost.Read(mDataBuf, blockVolume, 1);

			if (derr.IsntError())
			{
				pgpCopyMemory(buf, mDataBuf + headOffset, headSize);
				derr = mHost.Write(mDataBuf, blockVolume, 1);
			}

⌨️ 快捷键说明

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