📄 fatutils.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
// FatUtils.cpp
//
// Utility functions for processing FAT filesystem data.
//////////////////////////////////////////////////////////////////////////////
// $Id: FatUtils.cpp,v 1.7 1999/02/13 04:24:36 nryan Exp $
// Copyright (C) 1998 by Network Associates, Inc.
// All rights reserved.
#if defined(PGPDISK_MFC)
#include "StdAfx.h"
#elif defined(PGPDISK_95DRIVER)
#include <vtoolscp.h>
#elif defined(PGPDISK_NTDRIVER)
#include <vdw.h>
#else
#error Define PGPDISK_MFC, PGPDISK_95DRIVER, or PGPDISK_NTDRIVER.
#endif // PGPDISK_MFC
#include "Required.h"
#include "FatUtils.h"
#include "UtilityFunctions.h"
//////////////////////////////////
// Disk Geometry Utility Functions
//////////////////////////////////
// CalcGeometry return fake geometry information for a drive.
void
CalcGeometry(PGPUInt64 blocksDisk, PGPUInt16 blockSize, Geometry *geom)
{
pgpAssertAddrValid(geom, Geometry);
pgpAssert(blocksDisk > 0);
pgpAssert(blockSize > 0);
geom->geHeads = kMaxHeads - 1;
geom->geCyls = kMaxCyls - 1;
geom->geSpt = kMaxSpt - 1;
geom->geBlockSize = blockSize;
geom->geSecsDisk = blocksDisk;
}
////////////////////////////////
// General FAT Utility Functions
////////////////////////////////
// CalcFat16Spc calculates the sectors per cluster required for a FAT16
// volume of the given size in blocks.
PGPUInt16
CalcFat16Spc(PGPUInt64 blocksData, PGPUInt16 blockSize)
{
PGPUInt64 megsData = blocksData * blockSize/kBytesPerMeg;
if (megsData < 16)
return 8;
else if (megsData < 128)
return 4;
else if (megsData < 256)
return 8;
else if (megsData < 512)
return 16;
else if (megsData < 1024)
return 32;
else
return 64;
}
// CalcFat32Spc calculates the sectors per cluster required for a FAT32
// volume of the given size in blocks.
PGPUInt16
CalcFat32Spc(PGPUInt64 blocksData, PGPUInt16 blockSize)
{
PGPUInt64 megsData = blocksData * blockSize/kBytesPerMeg;
// This function is not reliable for sizes above 8 gigabytes as Microsoft
// hasn't appeared to have told us yet what clusters sizes should be in
// volumes above 8 gigs.
if (megsData < 8192)
return 8;
else
return 32;
}
// CalcFatSize will calculate the size of the FAT tables for a volume.
//
// On entry the fdBlockSize, fdFatCount, fdReservedSecs, and fdSPC members
// must be specified.
//
// On exit fdFatSize will have been filled in.
void
CalcFatSize(FatData *fat, PGPUInt64 blocksDisk)
{
PGPUInt32 bitsPerClust, bitsPerBlock, bitsPerSpc, numClusts;
PGPUInt64 bitsAvail;
pgpAssertAddrValid(fat, FatData);
pgpAssert(IsFatVolume(fat->fdFsId));
pgpAssert(fat->fdBlockSize > 0);
pgpAssert(fat->fdFatCount > 0);
pgpAssert(fat->fdSpc > 0);
switch (fat->fdFsId)
{
case kFS_FAT12:
bitsPerClust = kBitsFat12Clust;
break;
case kFS_FAT16:
bitsPerClust = kBitsFat16Clust;
break;
case kFS_FAT32:
bitsPerClust = kBitsFat32Clust;
break;
default:
pgpAssert(FALSE);
break;
}
// Bits per block = bytes per block * bits per byte.
bitsPerBlock = fat->fdBlockSize * kBitsPerByte;
// Bits available for FAT tables = (# of blocks on disk - # of reserved
// sectors) * bits per block.
bitsAvail = (blocksDisk - fat->fdReservedSecs) * bitsPerBlock;
// Bits per SPC = # of spc * bits per block.
bitsPerSpc = fat->fdSpc * bitsPerBlock;
// # of clusters = available bits / (bits per SPC + (# fats * bits per
// fat table cluster)).
numClusts = (PGPUInt32)
(bitsAvail / (bitsPerSpc + (fat->fdFatCount * bitsPerClust)));
// Blocks per FAT = ceiling of (# of clusters * bits per cluster) divided
// by (bits per block);
fat->fdFatSize = (PGPUInt32) CeilDiv((numClusts * bitsPerClust),
bitsPerBlock);
}
// CalcFatDataSec will calculate and return the index of the first sector on
// disk of the data area of a FAT drive.
//
// On entry the fdBlockSize, fdFatCount, fdReservedSecs, fdSPC,
// fdRootDirEnts (if non-FAT32), and fdFatSize members must be specified.
//
// On exit fdFirstSecData will have been filled in.
void
CalcFatDataSec(FatData *fat)
{
PGPUInt32 bytesDirEnt, secsRootDir;
pgpAssertAddrValid(fat, FatData);
pgpAssert(IsFatVolume(fat->fdFsId));
pgpAssert(fat->fdBlockSize > 0);
pgpAssert(fat->fdFatCount > 0);
pgpAssert(fat->fdSpc > 0);
pgpAssert(fat->fdFatSize > 0);
switch (fat->fdFsId)
{
case kFS_FAT12:
case kFS_FAT16:
// Size of the root directory = ceiling of (# of root directory
// entries * the size of each entry) divided by (# bytes per sector).
bytesDirEnt = (fat->fdFsId == kFS_FAT12 ? kBytesFat12DirEnt :
kBytesFat16DirEnt);
// First sector of data area = (# of reserved sectors) plus (# of FAT
// tables times size of each table in sectors) plus (sectors in the
// root directory).
secsRootDir = (PGPUInt32)
CeilDiv((fat->fdRootDirEnts * bytesDirEnt),
fat->fdBlockSize);
fat->fdFirstSecData = fat->fdReservedSecs +
(fat->fdFatCount * fat->fdFatSize) + secsRootDir;
break;
case kFS_FAT32:
// First sector of data area = (# of reserved sectors) plus (# of FAT
// tables times size of each table in sectors).
fat->fdFirstSecData = fat->fdReservedSecs +
(fat->fdFatCount*fat->fdFatSize);
break;
default:
pgpAssert(FALSE);
break;
}
}
// InitFatData will initialize a FatData structure with default values. On
// entrance, the fdFsId member must be filled in.
void
InitFatData(FatData *fat, PGPUInt64 blocksDisk)
{
pgpAssertAddrValid(fat, FatData);
pgpAssert(IsFatVolume(fat->fdFsId));
switch (fat->fdFsId)
{
case kFS_FAT12:
fat->fdBlockSize = kDefaultBlockSize;
fat->fdActiveFat = 0;
fat->fdFatCount = kDefaultFatCount;
fat->fdReservedSecs = kDefaultFat12Reserved;
fat->fdRootDirEnts = kDefaultRootDirEnts;
fat->fdSpc = 1;
break;
case kFS_FAT16:
fat->fdBlockSize = kDefaultBlockSize;
fat->fdActiveFat = 0;
fat->fdFatCount = kDefaultFatCount;
fat->fdReservedSecs = kDefaultFat16Reserved;
fat->fdRootDirEnts = kDefaultRootDirEnts;
fat->fdSpc = CalcFat16Spc(blocksDisk, fat->fdBlockSize);
break;
case kFS_FAT32:
fat->fdBlockSize = kDefaultBlockSize;
fat->fdActiveFat = kDefaultActiveFat;
fat->fdFatCount = kDefaultFatCount;
fat->fdReservedSecs = kDefaultFat32Reserved;
fat->fdSpc = CalcFat32Spc(blocksDisk, fat->fdBlockSize);
break;
default:
pgpAssert(FALSE);
break;
}
CalcFatSize(fat, blocksDisk);
CalcFatDataSec(fat);
}
/////////////////////////////////////
// Cluster Specific Utility Functions
/////////////////////////////////////
// ClusterToSector returns the sector number corresponding to the first sector
// that the given cluster points to. The bias is a small constant subtracted
// from the cluster index to account for some reserved non-data clusters at
// the beginning of every FAT table.
//
// First sector referenced by cluster = the first sector of the data area +
// the adjusted index of the cluster * the number of sectors per cluster.
PGPUInt32
ClusterToSector(
PGPUInt32 clustNum,
PGPUInt32 firstSecData,
PGPUInt16 spc,
PGPUInt16 bias)
{
pgpAssert(firstSecData > 0);
pgpAssert(spc > 0);
return firstSecData + ((clustNum - bias) * spc);
}
// ExtractCluster returns the value stored at the cluster that is bitOffset
// bits into the buffer mSecBuf (which contains sectors from a FAT table),
// representing the cluster index curClust.
PGPUInt32
ExtractCluster(
PGPUInt8 *buf,
PGPUInt32 bitOffset,
PGPUInt32 curClust,
FileSysId fsId)
{
PGPUInt8 a, b;
pgpAssertAddrValid(buf, PGPUInt8);
pgpAssert(IsFatVolume(fsId));
switch (fsId)
{
case kFS_FAT12:
a = buf[bitOffset/kBitsPerByte]; // get byte 1
b = buf[bitOffset/kBitsPerByte + 1]; // get byte 2
if (curClust % 2)
return (MakeWord(a, b) >> 4);
else
return (MakeWord(a, b) & 0x0FFF);
case kFS_FAT16:
return ((PGPUInt16*) buf)[bitOffset/kBitsPerWord];
case kFS_FAT32:
return ((PGPUInt32*) buf)[bitOffset/kBitsPerDWord] & kFat32ClustMask;
default:
pgpAssert(FALSE);
return 0;
}
return 0;
}
// GetClusterSector takes as input:
//
// fFatSec = the number of the first sector of a FAT table,
// clustNum = the index of a cluster in that table,
// bitsClust = the size of each cluster in bits.
//
// As output, it sets the value of these variables (passed by reference):
//
// clustSec = the number of the sector (within the FAT table) containing
// bitOffset = the offset of the cluster in that particular sector (in bits).
void
GetClusterInfo(
PGPUInt32 firstFatSec,
PGPUInt32 clustNum,
PGPUInt32 bitsClust,
PGPUInt16 blockSize,
PGPUInt32 *clustSec,
PGPUInt32 *bitOffset)
{
pgpAssertAddrValid(clustSec, PGPUInt32);
pgpAssertAddrValid(bitOffset, PGPUInt32);
pgpAssert(firstFatSec > 0);
pgpAssert(bitsClust > 0);
(* clustSec) = firstFatSec +
((clustNum*bitsClust)/kBitsPerByte/blockSize);
(* bitOffset) = (PGPUInt16)
((clustNum*bitsClust)%(blockSize*kBitsPerByte));
}
// TotalClusters returns the total number of clusters in a FAT table of size
// 'fatSize' (in sectors) with clusters of size 'bitsClust' (in bits) and
// blocks of size 'blockSize' (in bytes).
PGPUInt32
TotalClusters(
PGPUInt32 fatSize,
PGPUInt32 bitsClust,
PGPUInt16 blockSize)
{
pgpAssert(fatSize > 0);
pgpAssert(bitsClust > 0);
pgpAssert(blockSize > 0);
return (fatSize * blockSize * kBitsPerByte) / bitsClust;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -