📄 fat.c
字号:
/* * NOTE: This code derived from information obtained from the Microsoft * FAT specification v1.03. The code also uses Microsoft names wherever * possible. * * * 0 Boot Sector * 1 FAT0 * x ... * FATn * ... * y Root Dir Entries * ... * z Clusters for Data/Dir Entries * ... * * */ #include "fat.h" #include "example.h" #include "partition.h" #include "util.h"typedef struct FATBootSector{ int8 BS_jmpBoot[3]; int8 BS_OEMName[8]; uint8 BPB_BytsPerSec[2]; uint8 BPB_SecPerClus; uint8 BPB_RsvdSecCnt[2]; uint8 BPB_NumFATs; uint8 BPB_RootEntCnt[2]; uint8 BPB_TotSec16[2]; uint8 BPB_Media; uint8 BPB_FATSz16[2]; uint16 BPB_SecPerTrk; uint16 BPB_NumHeads; uint8 BPB_HiddSec[4]; uint8 BPB_TotSec32[4]; union { struct { uint8 BS_DrvNum; uint8 BS_Reserved1; uint8 BS_BootSig; uint8 BS_VolID[4]; uint8 BS_VolLab[11]; uint8 BS_FilSysType[8]; } fat16; struct { uint8 BPB_FATSz32[4]; uint8 BPB_ExtFlags[2]; uint8 BPB_FSVer[2]; uint8 BPB_RootClus[4]; uint8 BPB_FSInfo[2]; uint8 BPB_BkBootSec[2]; uint8 BPB_Reserved[12]; uint8 BS_DrvNum; uint8 BS_Reserved1; uint8 BS_BootSig; uint8 BS_VolID[4]; uint8 BS_VolLab[11]; uint8 BS_FilSysType[8]; } fat32; uint8 padding[474]; /* to make final size exactly 512 */ } u; uint8 offset510; uint8 offset511;} FATBootSector;typedef struct FATDirEntry { uint8 name[8],ext[3]; /* name and extension */ uint8 attr; /* attribute bits */ uint8 lcase; /* Case for base and extension */ uint8 ctime_ms; /* Creation time, milliseconds */ uint16 ctime; /* Creation time */ uint16 cdate; /* Creation date */ uint16 adate; /* Last access date */ uint16 starthi; /* High 16 bits of cluster in FAT32 */ uint16 time,date,start;/* time, date and first cluster */ uint32 size; /* file size (in bytes) */} FATDirEntry;enum FATType{ UNKNOWN, FAT12, FAT16, FAT32};char fatTableCache[512];int fatCachedSector;DiskFunctions fatDiskFunctions;/********************************************************************//* * Structure for managing FAT filesystem */struct FATInfo{ FATBootSector fbs; int bytesPerSector; int reservedSectorCount; unsigned int sectorCount; int sectorsPerCluster; int clusterSize; int clusterCount; int firstDataSector; int sectorsPerFAT; int rootEntryCount; int directoriesPerSectorCount; int rootDirSectorCount; int rootDirSector; int FATSize; enum FATType type; int dataSectorCount; int rootSector;} fat;#define MAX_CLUSTER_SIZE (512 * 128)typedef struct FatFileHandle{ int currentCluster; int byteOffset; int bufferOffset; char buffer[MAX_CLUSTER_SIZE]; FATDirEntry info;} FatFileHandle;FatFileHandle fatHandle;void displayFATInfo(){ int i; printf("\n-------------------------------\n"); printf("FAT Info:\n"); printf(" OEMName: '"); for (i = 0; i < 8; ++i) printf("%c", fat.fbs.BS_OEMName[i]); printf("'\n"); printf(" filesystem: "); switch(fat.type) { case FAT12: printf("FAT12"); break; case FAT16: printf("FAT16"); break; case FAT32: printf("FAT32"); break; } printf("\n"); printf(" sectorSize: %d\n", fat.bytesPerSector); printf(" sectorCount: %d\n", fat.sectorCount); printf(" clusterSize: %d\n", fat.clusterSize); printf(" clusterCnt: %d\n", fat.clusterCount); printf(" BPB_NumFATs: %d\n", fat.fbs.BPB_NumFATs); printf(" fatSize: %d\n", fat.FATSize); printf(" numRootDirE: %d\n", fat.rootEntryCount); printf(" dirEPerSect: %d\n", fat.directoriesPerSectorCount); printf(" sectorsRoot: %d\n", fat.rootDirSectorCount); printf(" ReservedCnt: %d\n", fat.reservedSectorCount); printf(" fstDataSec: %d\n", fat.firstDataSector); printf(" sectPerClus: %d\n", fat.sectorsPerCluster); printf(" diskSize: %dK\n", (fat.sectorCount * fat.bytesPerSector) >> 10); printf("-------------------------------\n");}void displayDirectoryEntry(FATDirEntry* handle){ int FATOffset, ThisFATSecNum, ThisFATEntOffset; int i; short buffer[2048]; printf("\n-------------------------------\n"); printf("File Info:"); printf("\nFilename: "); for(i = 0; i < 8; ++i) { printf("%c", handle->name[i]); } printf("."); for(i = 0; i < 3; ++i) { printf("%c", handle->ext[i]); } printf("\nAttributes: %X", handle->attr); printf("\nSize: %d Bytes", handle->size); printf("\nStart Cluster: %d\n", handle->start); FATOffset = handle->start * 2; ThisFATSecNum = fat.reservedSectorCount + (FATOffset / fat.bytesPerSector); ThisFATEntOffset = FATOffset % fat.bytesPerSector; printf("FATOffset: %d\n", FATOffset); printf("ThisFATSecNum: %d\n", ThisFATSecNum); printf("ThisFATEntOffset: %d\n", ThisFATEntOffset); printf("-------------------------------\n");}int getSectorNumber(int clusterOffset){ return fat.rootSector + (clusterOffset - 2) * fat.fbs.BPB_SecPerClus + fat.firstDataSector;}int getNextCluster(int currentCluster){ int FATOffset, ThisFATSecNum, ThisFATEntOffset, next; next = 0; switch(fat.type) { case FAT12: break; //not supported case FAT16: FATOffset = currentCluster * 2; break; case FAT32: FATOffset = currentCluster * 4; break; } ThisFATSecNum = fat.reservedSectorCount + (FATOffset / fat.bytesPerSector); ThisFATEntOffset = FATOffset % fat.bytesPerSector; if(fatCachedSector != ThisFATSecNum) //is FAT sector cached? { fatDiskFunctions.read(fat.rootSector + ThisFATSecNum, 1, (void*)fatTableCache); //read FAT table sector fatCachedSector = ThisFATSecNum; } //load lower 16-bits of cluster offset (FAT16 offsets are only 16-bits) next = ((fatTableCache[ThisFATEntOffset+1] & 0x0ff) << 8) | (fatTableCache[ThisFATEntOffset] & 0x0ff); if(fat.type == FAT32) //load upper 16-bits of cluster offset next |= ((fatTableCache[ThisFATEntOffset+2] & 0x0ff) << 16) | ((fatTableCache[ThisFATEntOffset+3] & 0x0ff) << 24); return next;}char toUpper(char c){ return (c <= 'z' && c >= 'a') ? c - 0x20 : c;}int compareFileName(char fatName[8], char fatExt[3], const char* searchName){ int i, j; int period = 0; DPRINTF("\n"); #if defined(_DEBUG) printf("Search Name: %s\n", searchName); printf("Fat Name: "); for(i = 0; i < 8; ++i) printf("%c", fatName[i]); printf("."); for(i = 0; i < 3; ++i) printf("%c", fatExt[i]); printf("\n"); #endif for(i = 0; i < 13 && searchName[i] != 0; ++i) if(searchName[i] == '.') period = i; if(period > 0 && period < 9 && searchName[i] == 0) { //compare names for(i = 0; i < period; ++i) if(fatName[i] != toUpper(searchName[i])) return fatName[i] < toUpper(searchName[i]) ? -1 : 1; for(; i < 8; ++i) if(fatName[i] != ' ') return -1; //compare extentions for(i = 0, j = period+1; searchName[j] != 0; ++i, ++j) if(fatExt[i] != toUpper(searchName[j])) return fatExt[i] < toUpper(searchName[j]) ? -1 : 1; for(; i < 3; ++i) if(fatExt[i] != ' ') return -1; return 0; } return -1; }int findFile(const char* fileName, FATDirEntry* handle){ int i; char buffer[MAX_CLUSTER_SIZE]; FATDirEntry* tempHandle; int sector = fat.rootSector + fat.rootDirSector; int cluster = 2; for(i = 0; i < fat.rootEntryCount || fat.rootEntryCount == 0; ++i, ++tempHandle) { if((i*sizeof(FATDirEntry)) % (fat.bytesPerSector*fat.sectorsPerCluster) == 0) //if at cluster boundary { fatDiskFunctions.read(sector, fat.sectorsPerCluster, buffer); tempHandle = (FATDirEntry*)buffer; if(fat.type == FAT32) { cluster = getNextCluster(cluster); //The root directory on a FAT32 FS is treated like a regular file sector = getSectorNumber(cluster); //Therefore the next cluster of the directory list is located in the FAT table } else sector += fat.sectorsPerCluster; //On FAT16 all items in the root directory are sequentially allocated } if( tempHandle->name[0] == 0x00 ) return 0; else if( tempHandle->name[0] != 0xE5 && compareFileName(tempHandle->name, tempHandle->ext, fileName) == 0 ) { //displayDirectoryEntry(tempHandle); memCopy(tempHandle, handle, sizeof(FATDirEntry)); return 1; } } return 0;}int fatLoad(DiskFunctions diskFunctions){ fatDiskFunctions = diskFunctions; char* buffer[2048]; /* * Check for MSDOS/FAT filesystem, if yes, then allocate * a control structure for managing this filesystem */ int i, rootBytes; /* * Read boot sector/partition table sector, sector 0 */ fat.rootSector = partitionGetRootSector(FAT, 0, fatDiskFunctions.read); DPRINTF("root sector: %d\n", fat.rootSector); if(fat.rootSector == -1) return 0; if(fatDiskFunctions.read(fat.rootSector, 1, (short*) &fat.fbs)) { if ((fat.fbs.offset510 == 0x55) && (fat.fbs.offset511 == 0xAA)) { fat.bytesPerSector = (fat.fbs.BPB_BytsPerSec[1] << 8) | fat.fbs.BPB_BytsPerSec[0]; /* Check for valid FAT sector size */ switch (fat.bytesPerSector) { case 512: case 1024: case 2048: case 4096: break; default: return 0; break; } fat.sectorsPerCluster = fat.fbs.BPB_SecPerClus; /* Check for valid Cluster size */ switch (fat.sectorsPerCluster) { case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: break; default: return 0; break; } /* Check that cluster size does not exceed 32KB */ fat.clusterSize = fat.bytesPerSector * fat.sectorsPerCluster; if (fat.clusterSize > (32 * 1024)) return 0; /* Reserved area must be at least 1 sector */ fat.reservedSectorCount = (fat.fbs.BPB_RsvdSecCnt[0] << 0) | (fat.fbs.BPB_RsvdSecCnt[1] << 8) ; if (fat.reservedSectorCount == 0) return 0; /* Must have at least 1 FAT */ if (fat.fbs.BPB_NumFATs == 0) return 0; fat.sectorCount = (fat.fbs.BPB_TotSec16[1] << 8) | fat.fbs.BPB_TotSec16[0]; if (fat.sectorCount == 0) { fat.sectorCount = (fat.fbs.BPB_TotSec32[0] << 0) | (fat.fbs.BPB_TotSec32[1] << 8) | (fat.fbs.BPB_TotSec32[2] << 16) | (fat.fbs.BPB_TotSec32[3] << 24) ; } fat.sectorsPerCluster = fat.fbs.BPB_SecPerClus; fat.rootEntryCount = (fat.fbs.BPB_RootEntCnt[1] << 8) | fat.fbs.BPB_RootEntCnt[0]; fat.directoriesPerSectorCount = fat.bytesPerSector / sizeof(FATDirEntry); rootBytes = ((fat.rootEntryCount * sizeof(FATDirEntry)) + (fat.bytesPerSector - 1)); fat.rootDirSectorCount = ((fat.rootEntryCount * sizeof(FATDirEntry)) + (fat.bytesPerSector - 1)) / fat.bytesPerSector; /* * Check if this is FAT12, FAT16, FAT32 * take the number of clusters and check that against number of * entries in FAT if it were 12-, 16- or 32-bits per entry. */ if (fat.fbs.BPB_FATSz16[0] || fat.fbs.BPB_FATSz16[1]) { fat.FATSize = (fat.fbs.BPB_FATSz16[0] << 0) | (fat.fbs.BPB_FATSz16[1] << 8) ; } else { fat.FATSize = (fat.fbs.u.fat32.BPB_FATSz32[0] << 0) | (fat.fbs.u.fat32.BPB_FATSz32[1] << 8) | (fat.fbs.u.fat32.BPB_FATSz32[2] << 16) | (fat.fbs.u.fat32.BPB_FATSz32[3] << 24) ; } fat.rootDirSector = fat.reservedSectorCount + (fat.fbs.BPB_NumFATs * fat.FATSize); fat.firstDataSector = fat.rootDirSector + fat.rootDirSectorCount; fat.dataSectorCount = fat.sectorCount - (fat.reservedSectorCount + (fat.fbs.BPB_NumFATs * fat.FATSize) + fat.rootDirSectorCount); fat.clusterCount = fat.dataSectorCount / fat.fbs.BPB_SecPerClus; /* FAT12 volumes have no more than 4084 clusters */ if (fat.clusterCount < 4085) { fat.type = FAT12; DPRINTF("FAT12 Partition\n"); } /* FAT16 volumes have at least 4085 clusters and no more than 655524 */ else if (fat.clusterCount < 65525) { fat.type = FAT16; DPRINTF("FAT16 Partition\n"); } /* FAT32 volumes have at least 65525 clusters */ else { fat.type = FAT32; DPRINTF("FAT32 Partition\n"); } //if (fat.type == FAT32) return 0; // doesn't quite work yet //displayFATInfo(); return 1; } } return 0; /* unable to read disk */}int fatClose(){ return 1;}int fatOpen(const char* fileName){ fatCachedSector = -1; if(findFile(fileName, &fatHandle.info)) { DPRINTF("Found File: %s, %d\n", fileName, fatHandle.info.start); fatHandle.byteOffset = 0; fatHandle.currentCluster = (fatHandle.info.starthi << 16) | fatHandle.info.start; fatHandle.bufferOffset = fat.clusterSize; return fatHandle.info.size; } return 0;}int fatRead(void* buffer, int size){ int i; char* cBuffer = (char*)buffer; for(i = 0; i < size; ++i, ++fatHandle.byteOffset, ++fatHandle.bufferOffset) { if(fatHandle.byteOffset == fatHandle.info.size) return i; if(fatHandle.bufferOffset == fat.clusterSize) { if(fatHandle.byteOffset != 0) { fatHandle.currentCluster = getNextCluster(fatHandle.currentCluster); } fatDiskFunctions.read( getSectorNumber(fatHandle.currentCluster), fat.sectorsPerCluster, (void*)&fatHandle.buffer); //buffer cluster fatHandle.bufferOffset = 0; } cBuffer[i] = fatHandle.buffer[fatHandle.bufferOffset]; } return i;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -