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

📄 fatparser.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:

			if (derr.IsntError())
			{
				bufPos	= headSize;
				pos		+= headSize;
				nBytes	-= headSize;
			}
		}
	}

	// Write out 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())
	{
		blocksToWrite = nBytes / blockSize;

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

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

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

			// Now we perform the write from the output buffer to disk.

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

			if (derr.IsntError())
			{
				bufPos			+= sizeChunk * blockSize;
				nBytes			-= sizeChunk * blockSize;
				pos				+= sizeChunk * blockSize;
				blocksToWrite	-= sizeChunk;
			}
		}
	}

	// Process the tail.
	if (derr.IsntError())
	{
		if (nBytes)							// is there a tail?	
		{
			i = FindFragmentIndex(pos);

			// Write out the tail.
			//
			// blockVolume = sector on disk containing the tail
			// headSize = size of the tail, in bytes

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

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

	return derr;
}

// Read reads nBytes from the file at position pos (in bytes). It uses the
// previously initialized member variable mFragArray to map locations in the
// file to locations on disk, since a file on a FAT volume may be spread out
// in many fragments.

DualErr 
FatParser::Read(
	PGPUInt8			*buf, 
	PGPUInt64			pos, 
	PGPUInt32			nBytes, 
	GenericCallbackInfo	*upInfo)
{
	DualErr derr;

	pgpAssertAddrValid(buf, PGPUInt8);

	if (upInfo)
		ReadAsync(buf, pos, nBytes, upInfo);
	else
		derr = ReadSync(buf, pos, nBytes);

	return derr;
}

// Write writes nBytes to the file at position pos (in bytes). It uses the
// previously initialized member variable mPFF to map locations in the file
// to locations on disk, since a file on a FAT volume may be spread out in
// many fragments.

DualErr 
FatParser::Write(
	PGPUInt8			*buf, 
	PGPUInt64			pos, 
	PGPUInt32			nBytes, 
	GenericCallbackInfo	*upInfo)
{
	DualErr derr;

	pgpAssertAddrValid(buf, PGPUInt8);

	if (upInfo)
		WriteAsync(buf, pos, nBytes, upInfo);
	else
		derr = WriteSync(buf, pos, nBytes);

	return derr;
}


///////////////////////////////////////////
// Class FatParser private member functions
///////////////////////////////////////////

// CalcDiskSector calculates the sector on disk containing a certain location
// in a file, given that location and a pointer to a single FileFrag.

PGPUInt64 
FatParser::CalcDiskSector(
	PGPUInt64	filePos, 
	PFileFrag	pFF, 
	PGPUInt16	blockSize)
{
	PGPUInt64	diskPos;

	pgpAssertAddrValid(pFF, FileFrag);
	pgpAssert(filePos >= pFF->fileBegin);
	pgpAssert(filePos <= pFF->fileEnd);

	diskPos = pFF->diskBegin + (filePos - pFF->fileBegin);

	return (diskPos / blockSize);
}

// ExpandFragArray allocated memory for more file fragments.

DualErr 
FatParser::ExpandFragArray()
{
	DualErr		derr;
	PFileFrag	temp;

	// Get memory for more fragments.
	derr = GetByteBuffer(
		(mSizeFragArray + kFPFragArrayChunkSize) * sizeof(FileFrag), 
		(PGPUInt8 **) &temp);

	if (derr.IsntError())
	{
		// Copy the old fragments to the new memory.
		pgpCopyMemory(mFragArray, temp, mSizeFragArray*sizeof(FileFrag));

		// Delete the old memory.
		FreeByteBuffer((PGPUInt8 *) mFragArray);

		mFragArray = temp;
		mSizeFragArray += kFPFragArrayChunkSize;
	}

	return derr;
}

// FindFragmentIndex will find and return the index of the file fragment that
// contains the file position specified.

PGPUInt32 
FatParser::FindFragmentIndex(PGPUInt64 pos)
{
	PGPBoolean	foundFrag	= FALSE;
	PGPUInt32	i, j, x;

	pgpAssertAddrValid(mFragArray, FileFrag);
	pgpAssert(mSizeFragArray > 0);

	i = 0;
	j = mNumFragsInUse - 1;

	// Binary search.
	do
	{
		x = (i + j)/2;

		if ((pos >= mFragArray[x].fileBegin) && 
			(pos <= mFragArray[x].fileEnd))
		{
			foundFrag = TRUE;
			break;
		}
		else
		{
			(pos > mFragArray[x].fileEnd ? i = x + 1: j = x - 1);
		}
	}
	while (j >= i);

	if (!foundFrag)
	{
		pgpDebugMsg("PGPdisk: FindFragment recieved an OOB position");
		return 0xFFFFFFFF;
	}
	else
	{
		return x;
	}
}

// InitFileFrag initializes a file fragment. It sets the beginning (and ending,
// since it is zero length) file and disk parameters according to the passed
// values.

void 
FatParser::InitFileFrag(
	PFileFrag	pFF, 
	PGPUInt64	fileByte, 
	PGPUInt64	diskByte)
{
	pgpAssertAddrValid(pFF, FileFrag);

	pFF->fileBegin	= pFF->fileEnd	= fileByte;
	pFF->diskBegin	= pFF->diskEnd	= diskByte;
	pFF->next		= pFF->prev		= NULL;
}

#if PGP_DEBUG

// DumpFrags is a debugging procedure that will print out a list of the
// fragments in a file to the debugger.

void 
FatParser::DumpFrags()
{
	PGPUInt16	blockSize;
	PGPUInt64	secBegin, secEnd;

	blockSize = mHost.GetBlockSize();
	DebugOut("\nPGPdisk: Frags Dump for %s:\n", GetPath());

	if (mNumFragsInUse == 0)
	{
		DebugOut("\nPGPdisk: No frags to dump\n");
	}
	else
	{
		for (PGPUInt32 i=0; i < mNumFragsInUse; i++)
		{
			DebugOut("PGPdisk: Frag #%u", i);

			secBegin	= mFragArray[i].fileBegin/blockSize;
			secEnd		= mFragArray[i].fileEnd/blockSize;

			DebugOut("PGPdisk: File begin: %u to file end: %u", secBegin, 
				secEnd);

			secBegin	= (PGPUInt32) (mFragArray[i].diskBegin/blockSize);
			secEnd		= (PGPUInt32) (mFragArray[i].diskEnd/blockSize);

			DebugOut("PGPdisk: Disk begin: %u to disk end: %u", secBegin, 
				secEnd);
		}
	
		DebugOut("\nPGPdisk: Frag Dump completed\n");
	}
}

#endif	// PGP_DEBUG

// GetFatData acquires data specific to the FAT filesystem of the host drive
// and fills in the data member 'mFat'.

DualErr 
FatParser::GetFatData()
{
	DualErr	derr;

	pgpAssert(mHost.Mounted());

	mFat.fdBlockSize = mHost.GetBlockSize();
	mFat.fdFsId = mFsId;

	switch (mFsId)
	{

	case kFS_FAT12:
	case kFS_FAT16:
	{
		DevParams16	dp16;

		derr = mHost.GetDevParams16(&dp16);

		if (derr.IsntError())
		{
			mFat.fdActiveFat	= 0;					// always 0
			mFat.fdFatCount		= dp16.dpFats;			// number of FATs
			mFat.fdReservedSecs	= dp16.dpResSectors;	// reserved sectors
			mFat.fdRootDirEnts	= dp16.dpRootDirEnts;	// root dir entries
			mFat.fdSpc			= dp16.dpSecPerClust;	// sectors per cluster
			mFat.fdFatSize		= dp16.dpFatSecs;		// sectors per FAT
			mFat.fdFirstSecFat	= dp16.dpResSectors;	// FATs begin > rsrvd

			CalcFatDataSec(&mFat);
		}
		break;
	}

	case kFS_FAT32:
	{
		DevParams32 dp32;
		PGPUInt8	activeFat;
		PGPUInt32	flags;

		derr = mHost.GetDevParams32(&dp32);

		if (derr.IsntError())
		{
			// Check for mirrored FAT tables in FAT32.
			flags = dp32.dpExtFlags;
			if (flags & BGBPB_F_NoFATMirror)
				activeFat = 0;
			else
				activeFat = (PGPUInt8) (flags & BGBPB_F_ActiveFATMsk);
		
			mFat.fdActiveFat	= activeFat;				// # of active FAT
			mFat.fdFatCount		= dp32.dpNumberOfFats;		// number of FATs
			mFat.fdReservedSecs	= dp32.dpReservedSectors;	// reserved seecs
			mFat.fdSpc			= dp32.dpSectorsPerClust;	// sects per clust
			mFat.fdFatSize		= dp32.dpBigSectorsPerFat;	// secs per FAT
			mFat.fdFirstSecFat	= dp32.dpReservedSectors;	// FATs > reserved

			CalcFatDataSec(&mFat);
		}
		break;
	}

	default:
		pgpAssert(FALSE);
		break;
	}

	// Finally we make a system call to determine the index of the first
	// cluster in the FAT table for our file.

	if (derr.IsntError())
	{
	    derr = Driver->GetFirstClustFile(mPath, &mFat.fdFirstClustFile);
	}

	return derr;
}

// ParseNextCluster is a helper function for MakeFatFrags. Given a set of
// information about a file and its associated FAT table, and the index of
// a cluster in that FAT table, it reads in the next clusters and expands
// the file's fragment list as appropriate.

DualErr 
FatParser::ParseNextCluster(ParseNextClusterInfo *pPNCI)
{
	DualErr		derr;
	PGPUInt64	blockVolume;

	pgpAssertAddrValid(pPNCI, ParseNextClusterInfo);

	// Sanity checks.

	if ((pPNCI->curClust > pPNCI->totalClusts) || 
		((++pPNCI->overFlow) > kFPMaxLoops))
	{
		derr = DualErr(kPGDMinorError_CorruptFat);
	}

	// Check if we are still within the current fragment - that is, if the
	// next cluster is 1 greater than the current cluster. If not, create a
	// new file fragment.

	if (derr.IsntError())
	{
		if (pPNCI->nextClust == (pPNCI->curClust + 1))	// within fragment?
		{
			// We are not at the end of a fragment. First increment curClust
			// by 1, and expand our fragment by the size (in bytes) of 1
			// cluster.

			pPNCI->curClust++;
			mFragArray[pPNCI->i].fileEnd += pPNCI->spc * pPNCI->blockSize;
			mFragArray[pPNCI->i].diskEnd += pPNCI->spc * pPNCI->blockSize;

			// Next update the offset to point to the new current cluster's
			// data (which will hold the next cluster's index). If the offset
			// runs over our buffer size, we have to read in the next buffer.

			pPNCI->bitOffset += pPNCI->bitsClust;

			if (pPNCI->bitOffset >= 
				(PGPUInt32) kFPDataBufSize * pPNCI->blockSize * kBitsPerByte)
			{
				GetClusterInfo(pPNCI->firstSecFat, pPNCI->curClust, 
					pPNCI->bitsClust, pPNCI->blockSize, &pPNCI->clustSec, 
					&pPNCI->bitOffset);

				derr = mHost.Read(mDataBuf, pPNCI->clustSec, 
					kFPDataBufSize + 1);
			}
		}
		else
		{
			PGPUInt64 oldSector;

			// OK, we are at the end of a fragment. Set curClust to the index
			// of the new cluster (which can be any valid cluster index), and
			// expand the current fragment.

			pPNCI->curClust = pPNCI->nextClust;

			mFragArray[pPNCI->i].fileEnd += 
				(pPNCI->spc * pPNCI->blockSize) - 1;

			mFragArray[pPNCI->i].diskEnd += 
				(pPNCI->spc * pPNCI->blockSize) - 1;

			oldSector = pPNCI->clustSec;

			// Find the new FAT sector.
			GetClusterInfo(pPNCI->firstSecFat, pPNCI->curClust, 
				pPNCI->bitsClust, pPNCI->blockSize, &pPNCI->clustSec, 
				&pPNCI->bitOffset);

			// If this lies in a different sector, read it in.
			if (pPNCI->clustSec != oldSector)
			{
				derr = mHost.Read(mDataBuf, pPNCI->clustSec, 
					kFPDataBufSize + 1);
			}

			// Finally we calculate which sector on disk the new curClust
			// refers to, and then we init a new fragment

			if (derr.IsntError())
			{
				blockVolume = ClusterToSector(pPNCI->curClust, 
					pPNCI->firstSecData, pPNCI->spc, pPNCI->clustBias);

				// See if we have to allocate a new frag.
				if (pPNCI->i + 1 == mSizeFragArray)
					derr = ExpandFragArray();
			}

			// Init a new file fragment.
			if (derr.IsntError())
			{
				pPNCI->i++;
				mNumFragsInUse++;

				InitFileFrag(&mFragArray[pPNCI->i], 
					mFragArray[pPNCI->i - 1].fileEnd + 1, 
					blockVolume * pPNCI->blockSize);
			}
		}
	}

	// Extract the next cluster.
	pPNCI->nextClust = ExtractCluster(mDataBuf, pPNCI->bitOffset, 
		pPNCI->curClust, mFsId);

	return derr;
}

// MakeFATFrags constructs the file fragment array for the File being opened
// on its FAT host drive with direct disk access mode. This procedure reads
// directly from the FAT table of the host drive.

DualErr 
FatParser::MakeFatFrags()
{
	DualErr		derr;
	PGPUInt8	bitsClust, clustBias;
	PGPUInt16	blockSize, spc;
	PGPUInt32	bitOffset, clustSec, curClust, fatSize, firstSecFat;
	PGPUInt32	firstClustFile, firstSecFile, firstSecData, i, maxClust;
	PGPUInt32	minClust, totalClusts;

	pgpAssertAddrValid(mDataBuf, PGPUInt8);
	pgpAssert(mNumFragsInUse == 0);

	// First fill in some filesystem specific data.
	switch (mFsId)
	{
	case kFS_FAT12:
		bitsClust	= kBitsFat12Clust;
		clustBias	= kFat12ClustBias;
		maxClust	= kMaxFat12Clust;
		minClust	= kMinFat12Clust;
		break;

	case kFS_FAT16:
		bitsClust	= kBitsFat16Clust;

⌨️ 快捷键说明

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