📄 sdfat.c
字号:
}
BOOL FATIsArchive(PFILEINFO pFileInfo){
return (pFileInfo->FileAttribute&DIRENTRY_ARCHIVE) != 0;
}
BOOL FATEndOfFile(PFILEINFO pFileInfo){
return pFileInfo->CurrentPostion >= pFileInfo->FileLength;
}
DWORD FATGetFileSize(PFILEINFO pFileInfo){
return pFileInfo->FileLength;
}
DWORD FATGetFilePos(PFILEINFO pFileInfo){
return pFileInfo->CurrentPostion;
}
BOOL FATSetFilePos(PFILEINFO pFileInfo, DWORD dwPos){
PPARTITION pPartition;
// parameter check
if(pFileInfo->PartitionNumber >= PartitionNumber){
return FAT_ERROR;
}
// adjust dwPos, if need
if(dwPos > pFileInfo->FileLength){
dwPos = pFileInfo->FileLength;
}
// start seeking...
pPartition = &Partition[pFileInfo->PartitionNumber];
if(pFileInfo->StartingCluster == FAT_ROOTCLUSTER){ // handle root specially
// root area is continuous, simply assign new position
pFileInfo->CurrentPostion = dwPos;
}
else{ // not root...
DWORD dwStartCluster, dwClusterNumber;
if(dwPos < pFileInfo->CurrentPostion){ // prev
dwStartCluster = pFileInfo->StartingCluster;
dwClusterNumber = dwPos/pPartition->LengthPerCluster;
}
else{ // next
dwStartCluster = pFileInfo->CurrentCluster;
dwClusterNumber = dwPos/pPartition->LengthPerCluster-
pFileInfo->CurrentPostion/pPartition->LengthPerCluster;
}
// one time pass one cluster
while(dwClusterNumber--){
// go to next cluster
dwStartCluster = GetFATEntry(pFileInfo->PartitionNumber, dwStartCluster);
// verify it
if(!IsAllocFATEntry(pFileInfo->PartitionNumber, dwStartCluster) && dwPos<pFileInfo->FileLength){
return FAT_ERROR; // invalid cluster
}
}
// update state
pFileInfo->CurrentPostion = dwPos;
pFileInfo->CurrentCluster = dwStartCluster;
}
return TRUE;
}
DWORD FATReadFile(PFILEINFO pFileInfo, PVOID pBuffer, DWORD dwLength){
DWORD dwSavedLength;
PPARTITION pPartition;
// parameter check
if(pFileInfo->PartitionNumber >= PartitionNumber){
return FAT_ERROR;
}
if(pFileInfo->CurrentPostion >= pFileInfo->FileLength){ // end of file
return 0; // no more data to read
}
// adjust dwLength, if need
if(pFileInfo->CurrentPostion+dwLength > pFileInfo->FileLength){
dwLength = pFileInfo->FileLength-pFileInfo->CurrentPostion;
}
// save length for later use
dwSavedLength = dwLength;
// start reading...
pPartition = &Partition[pFileInfo->PartitionNumber];
if(pFileInfo->StartingCluster == FAT_ROOTCLUSTER){ // handle root specially
// root area is continuous, just need read one time
DWORD dwReadBytes = FATReadPartition(pFileInfo->PartitionNumber,
pBuffer, dwLength, pPartition->StartingRootEntry+pFileInfo->CurrentPostion);
// error check
if(dwReadBytes == FAT_ERROR){
return FAT_ERROR;
}
// update state info
(PBYTE)pBuffer += dwReadBytes;
dwLength -= dwReadBytes;
pFileInfo->CurrentPostion += dwReadBytes;
}
else{ // not root...
FILEINFO fnFileInfo = *pFileInfo; // make copy for error tolerance
while(dwLength){ // not end
// offset from current cluster
DWORD dwOffset = fnFileInfo.CurrentPostion%pPartition->LengthPerCluster;
// maximum bytes we can read at one time
DWORD dwReadBytes = pPartition->LengthPerCluster-dwOffset;
// adjust dwReadBytes, if need
if(dwReadBytes > dwLength){
dwReadBytes = dwLength;
}
// read one cluster
dwReadBytes = FATReadPartition(fnFileInfo.PartitionNumber, pBuffer, dwReadBytes, pPartition->StartingCluster+
pPartition->LengthPerCluster*(fnFileInfo.CurrentCluster-FAT_STARTCLUSTER)+dwOffset);
// error check
if(dwReadBytes == FAT_ERROR){
return FAT_ERROR;
}
// update state info
(PBYTE)pBuffer += dwReadBytes;
dwLength -= dwReadBytes;
fnFileInfo.CurrentPostion += dwReadBytes;
if(fnFileInfo.CurrentPostion%pPartition->LengthPerCluster == 0){ // end of cluster
// go to next cluster
fnFileInfo.CurrentCluster = GetFATEntry(fnFileInfo.PartitionNumber, fnFileInfo.CurrentCluster);
// verify it
if(!IsAllocFATEntry(fnFileInfo.PartitionNumber, fnFileInfo.CurrentCluster) &&
fnFileInfo.CurrentPostion<fnFileInfo.FileLength){ // not end of file){
return FAT_ERROR; // invalid cluster
}
}
}
*pFileInfo = fnFileInfo; // everything is ok, copy back
}
return dwSavedLength-dwLength;
}
DWORD FATReadFileEx(PFILEINFO pFileInfo, PVOID pBuffer, DWORD dwLength, DWORD dwPos){
return FATSetFilePos(pFileInfo, dwPos)?FATReadFile(pFileInfo, pBuffer, dwLength):FAT_ERROR;
}
// dump function for testing only
VOID DumpMasterBootRecord(){
DWORD dwMBRNo, dwPartNo;
// dumping...
for(dwMBRNo = 0; dwMBRNo < MasterBootRecordNumber; ++dwMBRNo){
OALLog(L"Signature:%04X\r\n", MasterBootRecord[dwMBRNo].Signature);
// 123 1234 1234 12345 123456 1234 12345 123456 123456 123456789012 1234567890123
OALLog(L"|No.|Boot|Head/Track/Sector--Head/Track/Sector|System|Start Sector|Sector Number|\r\n");
for(dwPartNo = 0; dwPartNo < PARTITION_NUMBER; ++dwPartNo){
OALLog(L"|%3d| %02X|%4u/%5u/%6u %4u/%5u/%6u| %02X|%12u|%13u|\r\n",
dwPartNo,
MasterBootRecord[dwMBRNo].Partition[dwPartNo].BootIndicator,
MasterBootRecord[dwMBRNo].Partition[dwPartNo].StartingHead,
MasterBootRecord[dwMBRNo].Partition[dwPartNo].StartingCylinder,
MasterBootRecord[dwMBRNo].Partition[dwPartNo].StartingSector,
MasterBootRecord[dwMBRNo].Partition[dwPartNo].EndingHead,
MasterBootRecord[dwMBRNo].Partition[dwPartNo].EndingCylinder,
MasterBootRecord[dwMBRNo].Partition[dwPartNo].EndingSector,
MasterBootRecord[dwMBRNo].Partition[dwPartNo].SystemId,
MasterBootRecord[dwMBRNo].Partition[dwPartNo].RelativeSector,
MasterBootRecord[dwMBRNo].Partition[dwPartNo].TotalSector
);
}
}
}
VOID DumpPartitionBootSector(DWORD dwPartNo){
// parameter check
if(dwPartNo >= PartitionNumber){
KITLOutputDebugString("Partition Number beyond scope\r\n");
return;
}
// dumping...
OALLog(L"JumpCode : %06X\r\n" , *((UINT32*)(RawPartition[dwPartNo].JumpCode))&0x00FFFFFF);
OALLog(L"CreatorID : %.8S\r\n" , RawPartition[dwPartNo].CreatorID);
OALLog(L"SectorSize : %u\r\n" , RawPartition[dwPartNo].SectorSize);
OALLog(L"SectorPerCluster : %u\r\n" , RawPartition[dwPartNo].SectorPerCluster);
OALLog(L"ReservedSector : %u\r\n" , RawPartition[dwPartNo].ReservedSector);
OALLog(L"NumberOfFAT : %u\r\n" , RawPartition[dwPartNo].NumberOfFAT);
OALLog(L"NumberOfRootEntry : %u\r\n" , RawPartition[dwPartNo].NumberOfRootEntry);
OALLog(L"TotalSector : %u\r\n" , RawPartition[dwPartNo].TotalSector);
OALLog(L"MediumId : %02X\r\n" , RawPartition[dwPartNo].MediumId);
OALLog(L"SectorPerFAT : %u\r\n" , RawPartition[dwPartNo].SectorPerFAT);
OALLog(L"SectorPerTrack : %u\r\n" , RawPartition[dwPartNo].SectorPerTrack);
OALLog(L"NumberOfSide : %u\r\n" , RawPartition[dwPartNo].NumberOfSide);
OALLog(L"NumberOfHiddenSector: %u\r\n" , RawPartition[dwPartNo].NumberOfHiddenSector);
OALLog(L"TotalSector2 : %u\r\n" , RawPartition[dwPartNo].TotalSector2);
if(Partition[dwPartNo].FileSystem == PART_FAT32){
OALLog(L"SectorPerFAT2 : %u\r\n" , RawPartition[dwPartNo].FAT32.SectorPerFAT);
OALLog(L"ExtentFlag : %04X\r\n" , RawPartition[dwPartNo].FAT32.ExtentFlag);
OALLog(L"FileSystemVersion : %04X\r\n" , RawPartition[dwPartNo].FAT32.FileSystemVersion);
OALLog(L"RootEntryCluster : %u\r\n" , RawPartition[dwPartNo].FAT32.RootEntryCluster);
OALLog(L"FileSystemInfomation: %u\r\n" , RawPartition[dwPartNo].FAT32.FileSystemInfomation);
OALLog(L"BackupBootSector : %u\r\n" , RawPartition[dwPartNo].FAT32.BackupBootSector);
OALLog(L"PhysicalDiskNumber : %02X\r\n" , RawPartition[dwPartNo].FAT32.PhysicalDiskNumber);
OALLog(L"EFDCSignature : %02X\r\n" , RawPartition[dwPartNo].FAT32.EFDCSignature);
OALLog(L"VolumeSerialNumber : %08X\r\n" , RawPartition[dwPartNo].FAT32.VolumeSerialNumber);
OALLog(L"VolumeLabel : %.11S\r\n", RawPartition[dwPartNo].FAT32.VolumeLabel);
OALLog(L"FileSystemType : %.8S\r\n" , RawPartition[dwPartNo].FAT32.FileSystemType);
}
else{ // FAT12/FAT16
OALLog(L"PhysicalDiskNumber : %02X\r\n" , RawPartition[dwPartNo].PhysicalDiskNumber);
OALLog(L"EFDCSignature : %02X\r\n" , RawPartition[dwPartNo].EFDCSignature);
OALLog(L"VolumeSerialNumber : %08X\r\n" , RawPartition[dwPartNo].VolumeSerialNumber);
OALLog(L"VolumeLabel : %.11S\r\n", RawPartition[dwPartNo].VolumeLabel);
OALLog(L"FileSystemType : %.8S\r\n" , RawPartition[dwPartNo].FileSystemType);
}
OALLog(L"Signature : %04X\r\n" , RawPartition[dwPartNo].Signature);
}
VOID DumpFATTable(DWORD dwPartNo, DWORD dwStart, DWORD dwCount){
DWORD dwBits, dwLine, dwLoop;
// parameter check
if(dwPartNo >= PartitionNumber){
KITLOutputDebugString("Partition Number beyond scope\r\n");
return;
}
if(dwStart >= Partition[dwPartNo].FATEntryNumber){
KITLOutputDebugString("Start position beyond FAT entry number\r\n");
return;
}
// adjust dwCount if need
if(dwStart+dwCount > Partition[dwPartNo].FATEntryNumber){
dwCount = Partition[dwPartNo].FATEntryNumber-dwStart;
}
// get FAT entry bit size
dwBits = GetFATEntryBits(dwPartNo);
dwLine = 32/GetFATEntryBytes(dwPartNo); // one line display 32 bytes
// begin dump
for(dwLoop = 0; dwLoop < dwCount; ++dwLoop){
if(dwLoop%dwLine == 0){
OALLog(L"%04X ", dwStart+dwLoop);
}
OALLog(L"%0*X ", dwBits/4, GetFATEntry(dwPartNo, dwStart+dwLoop));
if(dwLoop%dwLine==dwLine-1 || dwLoop+1==dwCount){
OALLog(L"\r\n");
}
}
}
VOID DumpDirectory(PCSTR pDirName, DWORD dwStart, DWORD dwCount){
FILEINFO fnFileInfo;
DIRENTRY drEntry;
DWORD dwEntries;
// open dir&verify it
if(!FATOpenFile(&fnFileInfo, pDirName)){
KITLOutputDebugString("Can't open %S\r\n", pDirName);
return;
}
// get dir entries
dwEntries = GetDirEntryNumber(&fnFileInfo);
// check&adjust parameter
if(dwStart >= dwEntries){
KITLOutputDebugString("Start position beyond directory entry number\r\n");
return;
}
if(dwStart+dwCount > dwEntries){
dwCount = dwEntries-dwStart;
}
// 123456789012345678901**12345678901234567**12345678**
OALLog(L"Created Modified Accessed "
// 123*123*123*12345678**12345678*1234567890123
L"Att Sum Ord Cluster Length FileName\r\n"
);
// process each directory entry
while(dwCount--){
// read item
if(!GetDirEntry(&fnFileInfo, &drEntry, dwStart++)){
KITLOutputDebugString("Fail to read %S\r\n", pDirName);
break;
}
// output
OALLog(L"%02u/%02u/%02u-%02u:%02u:%02u:%03u %02u/%02u/%02u-%02u:%02u:%02u "
L"%02u/%02u/%02u %02X %02X %02X %08X %-8u %-13S\r\n",
drEntry.Created.wYear%100, drEntry.Created.wMonth, drEntry.Created.wDay,
drEntry.Created.wHour, drEntry.Created.wMinute, drEntry.Created.wSecond,
drEntry.Created.wMilliseconds,
drEntry.Modified.wYear%100, drEntry.Modified.wMonth, drEntry.Modified.wDay,
drEntry.Modified.wHour, drEntry.Modified.wMinute, drEntry.Modified.wSecond,
drEntry.Accessed.wYear%100, drEntry.Accessed.wMonth, drEntry.Accessed.wDay,
drEntry.Attribute, drEntry.CheckSum, drEntry.Ordinal,
drEntry.StartingCluster, drEntry.FileLength, drEntry.FileName
);
}
}
VOID DumpDirectoryEx(PCSTR pDirName){
FILEINFO fnFileInfo;
DIRENTRY drEntry;
// open dir&verify it
if(!FATOpenFile(&fnFileInfo, pDirName)){
KITLOutputDebugString("Can't open %S\r\n", pDirName);
return;
}
if(!FATIsDirectory(&fnFileInfo)){
KITLOutputDebugString("%S isn't directory\r\n", pDirName);
return;
}
// 12345678901234567**123*12345678**12345678*1...
OALLog(L"Modified Att Cluster Length FileName\r\n");
// process each directory entry
while(1){
// read item
if(!GetDirEntryEx(&fnFileInfo, &drEntry)){
break;
}
if(drEntry.FileName[0] == DIRENTRY_NEVERUSED){
break; // finish?
}
// output
OALLog(L"%02u/%02u/%02u-%02u:%02u:%02u %02X %08X %-8u %S\r\n",
drEntry.Modified.wYear%100, drEntry.Modified.wMonth, drEntry.Modified.wDay,
drEntry.Modified.wHour, drEntry.Modified.wMinute, drEntry.Modified.wSecond,
drEntry.Attribute, drEntry.StartingCluster, drEntry.FileLength, drEntry.FileName
);
}
}
VOID DumpRootDirectoryEx(){
FILEINFO fnFileInfo;
DIRENTRY drEntry;
DWORD dwPartNo = 0;
// open dir&verify it
if(Partition[dwPartNo].FileSystem == PART_FAT32){
InitFileInfo(&fnFileInfo, dwPartNo, Partition[dwPartNo].StartingRootEntry, 0, DIRENTRY_SUBDIR);
}
else{
InitFileInfo(&fnFileInfo, dwPartNo, FAT_ROOTCLUSTER, Partition[dwPartNo].RootEntryLength, DIRENTRY_SUBDIR);
}
if(!FATIsDirectory(&fnFileInfo)){
KITLOutputDebugString("root isn't directory\r\n");
return;
}
// 12345678901234567**123*12345678**12345678*1...
OALLog(L"Modified Att Cluster Length FileName\r\n");
// process each directory entry
while(1){
// read item
if(!GetDirEntryEx(&fnFileInfo, &drEntry)){
break;
}
if(drEntry.FileName[0] == DIRENTRY_NEVERUSED){
break; // finish?
}
// output
OALLog(L"%02u/%02u/%02u-%02u:%02u:%02u %02X %08X %-8u %S\r\n",
drEntry.Modified.wYear%100, drEntry.Modified.wMonth, drEntry.Modified.wDay,
drEntry.Modified.wHour, drEntry.Modified.wMinute, drEntry.Modified.wSecond,
drEntry.Attribute, drEntry.StartingCluster, drEntry.FileLength, drEntry.FileName
);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -