📄 fat.c
字号:
NameCopy((EntryStuff->Dir_item_ptr->dir).Name,String,ShortEntryLength*sizeof(uint16)); (EntryStuff->Dir_item_ptr->dir).NameLength = ShortEntryLength; } } else { //no long name for directory NameCopy((EntryStuff->Dir_item_ptr->dir).Name,String,ShortEntryLength*sizeof(uint16)); (EntryStuff->Dir_item_ptr->dir).NameLength = ShortEntryLength; } return S_SEARCHED_DIR_FILE_ENTRY_FOUND; } else { //it is . or .. entry if((ShortEntryLength==2)&&(String[0]==0x2E)&&(String[1]==0x2E)) { // it is .. entry, there is info about parent directory cluster /* GET_WORD(EntryStuff->EntryBuf,ParentRecordAddress,20); ParentRecordAddress=ParentRecordAddress<<16; GET_WORD(EntryStuff->EntryBuf,ParentRecordAddressLo,26); ParentRecordAddress=ParentRecordAddress|ParentRecordAddressLo; (EntryStuff->FAT_private_struct_ptr)->ParentDirFirstClusNum = ParentRecordAddress; */ } return E_SEARCHED_DIR_FILE_ENTRY_NOT_FOUND; } } else { //found a file or invalid directory entry if((LDIR_attr&(ATTR_DIRECTORY|ATTR_VOLUME_ID)) == 0x00) { //found a file //look for extension in extension table if(FindExtInTbl(EntryStuff->ExtTbl,Ext,EntryStuff->ExtTblLen)||(EntryStuff->ExtTblLen==0)) { //ext is in ext table, so fill FILE_STRUCT (EntryStuff->Dir_item_ptr->file).ExtentLba = RecordAddress; GET_WORD(EntryStuff->EntryBuf,(EntryStuff->Dir_item_ptr->file).WrtDate,24); GET_WORD(EntryStuff->EntryBuf,(EntryStuff->Dir_item_ptr->file).WrtTime,22); GET_DWORD(EntryStuff->EntryBuf,(EntryStuff->Dir_item_ptr->file).FileSize,28); EntryStuff->TypeOfEntry = FAT_FILE_FOUND; if(EntryStuff->LongNameFound) { //file has long name EntryStuff->LongNameFound = false; if((EntryStuff->CheckSum==ChkSum(EntryStuff->EntryBuf))&&(EntryStuff->StatusLongName)) { //long name is OK //NameCopy((EntryStuff->Dir_item_ptr->file).Name,EntryStuff->LongName,(EntryStuff->WholeLongEntryLength)*sizeof(uint16)); p.be = 0; p.trunc = 0; p.limit = 0; (EntryStuff->Dir_item_ptr->file).NameLength = \ WideFileNameToUTF8((uint8*)(EntryStuff->LongName),(EntryStuff->Dir_item_ptr->file).Name,EntryStuff->WholeLongEntryLength,&p); if(0>(EntryStuff->Dir_item_ptr->file).NameLength) return E_SEARCHED_DIR_FILE_ENTRY_NOT_FOUND; } else { //long name is corrupted NameCopy((EntryStuff->Dir_item_ptr->file).Name,String,ShortEntryLength*sizeof(uint16)); (EntryStuff->Dir_item_ptr->file).NameLength = ShortEntryLength; } } else { //no long name for file NameCopy((EntryStuff->Dir_item_ptr->file).Name,String,ShortEntryLength*sizeof(uint16)); (EntryStuff->Dir_item_ptr->file).NameLength = ShortEntryLength; } return S_SEARCHED_DIR_FILE_ENTRY_FOUND; } else { //ext not in table LongChainCancel(EntryStuff); return E_SEARCHED_DIR_FILE_ENTRY_NOT_FOUND; } } else { //found invalid directory entry LongChainCancel(EntryStuff); return E_SEARCHED_DIR_FILE_ENTRY_NOT_FOUND; } } } else { //no short, no long entry, invalid entry LongChainCancel(EntryStuff); return E_SEARCHED_DIR_FILE_ENTRY_NOT_FOUND; } }}GRESULT LookForDirFileEntrySectorBasedNext(PRIVATE_DATA_FAT *FAT_private, ENTRY_STUFF_STRUCT *EntryStuff){ ENTRY_ADDRESS PreviousEntryAddress; uint32 PreviousDirRecordOffset; uint32 CountOfCycles = 0; GRESULT ReturnCode; Get_BytesParamsStruct Get_BytesParams; //save current position of pointer, restored if there is no next file or dir PreviousEntryAddress.Cluster = (EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster; PreviousEntryAddress.Byte = (EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte; PreviousDirRecordOffset = EntryStuff->Scan_struct_ptr->DirRecordOffset; for( ; ; ) { //parse long or short entry, if any //via 32 bytes blocks //Are we still in root dir region? if((EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster >= FAT_private->RootRecordLba + FAT_private->RootDirSec) { LongChainCancel(EntryStuff); //restore original position (EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster = PreviousEntryAddress.Cluster; (EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte = PreviousEntryAddress.Byte; EntryStuff->Scan_struct_ptr->DirRecordOffset = PreviousDirRecordOffset; return E_SEARCHED_DIR_FILE_ENTRY_NOT_FOUND; } //there could still be some dirs //read one entry Get_BytesParams.FirstSectorOfCluster = ((EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster); Get_BytesParams.ClusterOffset = ((EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte); Get_BytesParams.num = 32; if((ReturnCode=Get_Bytes(EntryStuff->EntryBuf,EntryStuff->SectorBuffer,&Get_BytesParams,EntryStuff->Scan_struct_ptr->fs_descriptor)) != S_OK) { LongChainCancel(EntryStuff); if(ReturnCode == E_FORCED_UNPLUG) return ReturnCode; } if((ReturnCode == S_OK) && ((EntryStuff->EntryBuf)[0]==0x0)) //all next entries are free { LongChainCancel(EntryStuff); //restore original position (EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster = PreviousEntryAddress.Cluster; (EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte = PreviousEntryAddress.Byte; EntryStuff->Scan_struct_ptr->DirRecordOffset = PreviousDirRecordOffset; return E_SEARCHED_DIR_FILE_ENTRY_NOT_FOUND; } //there is at least one entry //update current position in root directory (EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte += 32; EntryStuff->Scan_struct_ptr->DirRecordOffset += 32; if(ReturnCode != S_OK) CountOfCycles = 0; else CountOfCycles++; if((EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte >= (FAT_private->BPB_boot_common).BytesPerSec) { //we moved to next sector (EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster += 1; (EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte = 0; } if((ReturnCode == S_OK) && (ParseEntry(EntryStuff) == S_SEARCHED_DIR_FILE_ENTRY_FOUND)) { //short entry found (dir or file) //save dir/file entry position (offset from beg. of record) for next possible whole name parsing if(EntryStuff->TypeOfEntry == FAT_DIR_FOUND) //found dir EntryStuff->Dir_item_ptr->dir.ParentOffset = EntryStuff->Scan_struct_ptr->DirRecordOffset-CountOfCycles*32; else //found file EntryStuff->Dir_item_ptr->file.DirRecordOffset = EntryStuff->Scan_struct_ptr->DirRecordOffset-CountOfCycles*32; return S_SEARCHED_DIR_FILE_ENTRY_FOUND; } } //end for}GRESULT LookForDirFileEntryClusterBasedNext(PRIVATE_DATA_FAT *FAT_private, ENTRY_STUFF_STRUCT *EntryStuff){ ENTRY_ADDRESS PreviousEntryAddress; GRESULT ReturnCode; uint32 PreviousDirRecordOffset; uint32 CountOfCycles = 0; static uint32 Cluster; Get_BytesParamsStruct Get_BytesParams; //FatEntryCheck = 0xFFFFFFFF; //save current position of pointer, restored if there is no next file or dir PreviousEntryAddress.Cluster = (EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster; PreviousEntryAddress.Byte = (EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte; PreviousDirRecordOffset = EntryStuff->Scan_struct_ptr->DirRecordOffset; for( ; ; ) { //parse long or short entry, if any //via 32 bytes blocks //check if cluster valid if(EntryStuff->Scan_struct_ptr->FatEntryCheck != (EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster) { Cluster = (EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster; if(!CheckIfEOF(&FAT_private->BPB_boot_common,Cluster)) { //actual cluster not EOF if((ReturnCode=Get_FATEntry(EntryStuff->Scan_struct_ptr->fs_descriptor,&Cluster,EntryStuff->SectorBuffer)) != S_OK) //continue in next cluster { //error reading FAT table LongChainCancel(EntryStuff); (EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster = PreviousEntryAddress.Cluster; (EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte = PreviousEntryAddress.Byte; EntryStuff->Scan_struct_ptr->DirRecordOffset = PreviousDirRecordOffset; EntryStuff->Scan_struct_ptr->FatEntryCheck = 0xFFFFFFFF; return ReturnCode; } } if(CheckIfEOF(&FAT_private->BPB_boot_common,(EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster) || CheckIfBadCluster(&FAT_private->BPB_boot_common,Cluster)) { //whole directory record is parsed, nothing to do anymore LongChainCancel(EntryStuff); //restore original position (EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster = PreviousEntryAddress.Cluster; (EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte = PreviousEntryAddress.Byte; EntryStuff->Scan_struct_ptr->DirRecordOffset = PreviousDirRecordOffset; EntryStuff->Scan_struct_ptr->FatEntryCheck = 0xFFFFFFFF; return E_SEARCHED_DIR_FILE_ENTRY_NOT_FOUND; } EntryStuff->Scan_struct_ptr->FatEntryCheck = (EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster; } //read one entry Get_BytesParams.FirstSectorOfCluster = Get_FirstSectorofCluster(&FAT_private->BPB_boot_common,FAT_private->FirstDataSector,(EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster); Get_BytesParams.ClusterOffset = ((EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte); Get_BytesParams.num = 32; if((ReturnCode=Get_Bytes(EntryStuff->EntryBuf,EntryStuff->SectorBuffer,&Get_BytesParams,EntryStuff->Scan_struct_ptr->fs_descriptor)) != S_OK) { LongChainCancel(EntryStuff); if(ReturnCode == E_FORCED_UNPLUG) return ReturnCode; } if((ReturnCode == S_OK) && ((EntryStuff->EntryBuf)[0]==0x0)) //all next entries are free { LongChainCancel(EntryStuff); //restore original position (EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster = PreviousEntryAddress.Cluster; (EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte = PreviousEntryAddress.Byte; EntryStuff->Scan_struct_ptr->DirRecordOffset = PreviousDirRecordOffset; return E_SEARCHED_DIR_FILE_ENTRY_NOT_FOUND; } //there is at least one entry //update current position in directory (EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte += 32; EntryStuff->Scan_struct_ptr->DirRecordOffset += 32; if(ReturnCode != S_OK) CountOfCycles = 0; else CountOfCycles++; if((EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte >= (uint32)(FAT_private->BPB_boot_common.BytesPerSec)*(FAT_private->BPB_boot_common.SecPerClust)) { //we moved to next cluster (EntryStuff->Scan_struct_ptr->DirEntryAddress).Byte = 0; (EntryStuff->Scan_struct_ptr->DirEntryAddress).Cluster = Cluster; } if((ReturnCode == S_OK) && (ParseEntry(EntryStuff) == S_SEARCHED_DIR_FILE_ENTRY_FOUND)) { //directory short entry found //save dir/file entry position (offset from beg. of record) for next possible whole name parsing if(EntryStuff->TypeOfEntry == FAT_DIR_FOUND) //found dir EntryStuff->Dir_item_ptr->dir.ParentOffset = EntryStuff->Scan_struct_ptr->DirRecordOffset-CountOfCycles*32; else //found file EntryStuff->Dir_item_ptr->file.DirRecordOffset = EntryStuff->Scan_struct_ptr->DirRecordOffset-CountOfCycles*32; return S_SEARCHED_DIR_FILE_ENTRY_FOUND; } } //end for}GRESULT FAT_Detect(DUID cdid, int partition, FS_DESCRIPTOR *fsd){ GRESULT ReturnCode; uint8 buf[512]; //inherited fsd->LargeBlockSize=SYS_DeviceInfoStruct(cdid)->LargeBlockSize; fsd->Partition=partition; fsd->PartitionLBA= (SYS_DeviceInfoStruct(cdid)->PartitionLBA)[partition]; fsd->FSType = FS_FAT_TYPE; fsd->did = cdid; fsd->PD.FAT_pd.FirstPassGetSector_FAT = true; if((ReturnCode = Get_BPB_BS(fsd,buf)) != S_OK) return ReturnCode; fsd->PD.FAT_pd.ExtTblLen = 0; if(fsd->PD.FAT_pd.BPB_boot_common.FATType) { //FAT12 or 16 fsd->PD.FAT_pd.RootRecordLba = Get_FAT12_16_FirstRootDirSecNum(&(fsd->PD.FAT_pd.BPB_boot_common)); fsd->PD.FAT_pd.RootDirSec = Get_RootDirSectors(&(fsd->PD.FAT_pd.BPB_boot_common)); } else { //FAT32 fsd->PD.FAT_pd.RootRecordLba = fsd->PD.FAT_pd.BPB_boot_rest.BPB_boot_rest_FAT_32.RootClus; } fsd->PD.FAT_pd.FirstDataSector = Get_FirstDataSector(&(fsd->PD.FAT_pd.BPB_boot_common)); return S_TRUE;}GRESULT FAT_GetExtent(SCAN_STRUCT *scans, uint32 *LengthOfExtent, uint8 *SectorBuffer){ uint32 PreviousCluster; GRESULT ReturnCode; uint32 BytesPerCluster = (uint32)(scans->fs_descriptor->PD.FAT_pd.BPB_boot_common.BytesPerSec)*scans->fs_descriptor->PD.FAT_pd.BPB_boot_common.SecPerClust; //certainly one cluster is available *LengthOfExtent = BytesPerCluster; for( ; ; ) { //via clusters PreviousCluster = scans->Cluster; if((ReturnCode=Get_FATEntry(scans->fs_descriptor,&(scans->Cluster),SectorBuffer)) != S_OK) //continue in next cluster return ReturnCode; if(CheckIfBadCluster(&(scans->fs_descriptor->PD.FAT_pd.BPB_boot_common),scans->Cluster)) { //cluster is bad *LengthOfExtent -= BytesPerCluster; return E_FAIL; } if(CheckIfEOF(&(scans->fs_descriptor->PD.FAT_pd.BPB_boot_common),scans->Cluster)) { //EOC return S_OK; } if(scans->Cluster != PreviousCluster+1) { //discontinuity of cluster chain return S_OK; } else { //continuity of cluster chain *LengthOfExtent += BytesPerCluster; } } //via clusters}void SetEOF(BPB_boot_common_t *BPB_boot_common, uint32 *FATContent){ switch(BPB_boot_common->FATType) { case 1: *FATContent = 0x0FF8; break; case 2: *FATContent = 0xFFF8; break; case 0: *FATContent = 0x0FFFFFF8; break; }}GRESULT FAT_GetDirItem(SCAN_STRUCT *scans, DIR_ITEM *item, uint8 *buf){ ENTRY_STUFF_STRUCT EntryStuff; uint8 EntryBuf[32]; //alloc memory for 32 bytes == 1 entry GRESULT ReturnCode; uint32 LengthOfExtent,PrevDirRecordOffset; if(scans->byte0 == S_FALSE) { //parse dir record EntryStuff.EntryBuf = EntryBuf; EntryStuff.SectorBuffer = buf; EntryStuff.Scan_struct_ptr = scans; EntryStuff.Dir_item_ptr = item; EntryStuff.FAT_private_struct_ptr = &(scans->fs_descriptor->PD.FAT_pd); EntryStuff.LongNameFound = false;// EntryStuff.ExtTbl = scans->fs_descriptor->PD.FAT_pd.ExtTbl; EntryStuff.ExtTblLen = scans->fs_descriptor->PD.FAT_pd.ExtTblLen; if(scans->DirRecordOffset == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -