FAT16檔案系統解析(C 版本)
阿新 • • 發佈:2018-12-20
//基本類 [葉帆工作室] http://blog.csdn.net/yefanqiu/publicclass DiskBase{ #region//MBR http://blog.csdn.net/yefanqiu/publicstruct PartitionTable { publicbyte BootFlag; //分割槽活動標誌 只能選00H和80H。80H為活動,00H為非活動public CHS StartCHS; //分割槽開始的柱面、磁頭、扇區 publicbyte SystemID; //分割槽型別 01 FAT32 04 FAT16<32M 06 FAT16 07 HPFS/NTFS 05 0F 擴充套件分割槽 public CHS EndCHS; //分割槽結束的柱面、磁頭、扇區 public UInt32 RelativeSectors; //分割槽起始扇區數,指分割槽相對於記錄該分割槽的分割槽表的扇區位置之差 (該分割槽表:LBA=0x0)。 public UInt32 TotalSectors; //分割槽總扇區數 } publicstruct CHS { publicbyte Head; //磁頭publicbyte Sector; //扇區 六位public UInt16 Cylinder; //柱面 十位 } publicstruct MBR { publicbyte[] bytBootCode; //ofs:0.引導程式碼446位元組 "FA 33 C0 8E D0 BC…"public PartitionTable[] PT; //ofs:446.64個位元組 分割槽表 length=4*16public UInt16 EndingFlag; //ofs:510.結束標識:0xAA55。public MBR(byte[] bytData) { int i; bytBootCode =newbyte[446]; for (i =0; i <446; i++) bytBootCode[i] = bytData[i]; PT =new PartitionTable[4]; for (i =0; i <4; i++) { PT[i].BootFlag = bytData[446+ i *16+0]; PT[i].StartCHS.Head = bytData[446+ i *16+1]; PT[i].StartCHS.Sector = (byte)(bytData[446+ i *16+2] &0x3f); PT[i].StartCHS.Cylinder = (UInt16)(((bytData[446+ i *16+2] &0xc0) <<2) | bytData[446+ i *16+3]); PT[i].SystemID = bytData[446+ i *16+4]; PT[i].EndCHS.Head = bytData[446+ i *16+5]; PT[i].EndCHS.Sector = (byte)(bytData[446+ i *16+6] &0x3f); PT[i].EndCHS.Cylinder = (UInt16)(((bytData[446+ i *16+6] &0xc0) <<2) | bytData[446+ i *16+7]); PT[i].RelativeSectors = (UInt32)(bytData[446+ i *16+11] <<24| bytData[446+ i *16+10] <<16| bytData[446+ i *16+9] <<8| bytData[446+ i *16+8]); PT[i].TotalSectors = (UInt32)(bytData[446+ i *16+15] <<24| bytData[446+ i *16+14] <<16| bytData[446+ i *16+13] <<8| bytData[446+ i *16+12]); } EndingFlag = (UInt16)(bytData[510] <<8| bytData[511]); } #endregion#region//DBR http://blog.csdn.net/yefanqiu///系統引導記錄(相容FAT16和FAT32)publicstruct DBR { publicbyte[] BS_JmpBoot; //ofs:0.典型的如:0xEB,0x3E,0x90。publicbyte[] BS_OEMName; //ofs:3.典型的如:“MSWIN4.1”。 public UInt16 BPB_BytsPerSec; //ofs:11.每扇區位元組數。 publicbyte BPB_SecPerClus; //ofs:13.每簇扇區數。 public UInt16 BPB_RsvdSecCnt; //ofs:14.保留扇區數,從 DBR到 FAT的扇區數。publicbyte BPB_NumFATs; //ofs:16.FAT的個數。 public UInt16 BPB_RootEntCnt; //ofs:17.根目錄項數。 public UInt16 BPB_TotSec16; //ofs:19.分割槽總扇區數(<32M時用)。 publicbyte BPB_Media; //ofs:21.分割槽介質標識,優盤一般用 0xF8。 public UInt16 BPB_FATSz16; //ofs:22.每個 FAT佔的扇區數。 public UInt16 BPB_SecPerTrk; //ofs:24.每道扇區數。 public UInt16 BPB_NumHeads; //ofs:26.磁頭數。 public UInt32 BPB_HiddSec; //ofs:28.隱藏扇區數,從 MBR到 DBR的扇區數。 public UInt32 BPB_TotSec32; //ofs:32.分割槽總扇區數(>=32M時用)。 //--------------------- //FAT32特有public UInt32 BPB_FATSz32; //ofs:36.每個 FAT佔的扇區數。public UInt16 BPB_ExtFlags; //ofs:40.FAT標誌public UInt16 BPB_FSVer; //ofs:42.版本號 高位元組主版本 低位元組次版本號public UInt32 BPB_RootClus; //ofs:44.根目錄所在第一個簇的簇號,通常該數值為2,但不是必須為2。public UInt16 BPB_FSInfo; //ofs:48.保留區中FAT32 卷FSINFO 結構所佔的扇區數,通常為1。public UInt16 BPB_BkBootSec; //ofs:50.如果不為0,表示在保留區中引導記錄的備份資料所佔的扇區數,通常為6。同時不建議使用6 以外的其他數值。 [MarshalAs(UnmanagedType.ByValArray, SizeConst =12)] publicbyte[] BPB_Reserved; //ofs:52.備用 //---------------------publicbyte BS_drvNum; //ofs:64/36.軟盤使用 0x00,硬碟使用 0x80。 publicbyte BS_Reserved1; //ofs:65/37.保留。 publicbyte BS_BootSig; //ofs:66/38.擴充套件引導標記:0x29。 publicbyte[] BS_VolID; //ofs:67/39.盤序列號。publicbyte[] BS_VolLab; //ofs:71/43.“Msdos ”。 publicbyte[] BS_FilSysType; //ofs:82/54.“FAT32 ”。 publicbyte[] ExecutableCode; //ofs:90/62.引導程式碼。 public UInt16 EndingFlag; //ofs:510.結束標識:0xAA55。 //--------------------- //0-未知 1-FAT12 2-FAT16 3-FAT32 其它值為未知publicbyte FATType; //獲取資訊public DBR(byte[] bytData) { FATType = IsType(bytData); int i; BS_JmpBoot =newbyte[3]; for (i =0; i <2; i++) BS_JmpBoot[i] = bytData[i]; BS_OEMName =newbyte[8]; for (i =0; i <8; i++) BS_OEMName[i] = bytData[i +3]; BPB_BytsPerSec = (UInt16)(bytData[12] <<8| bytData[11]); BPB_SecPerClus = bytData[13]; BPB_RsvdSecCnt = (UInt16)(bytData[15] <<8| bytData[14]); BPB_NumFATs = bytData[16]; BPB_RootEntCnt = (UInt16)(bytData[18] <<8| bytData[17]); BPB_TotSec16 = (UInt16)(bytData[20] <<8| bytData[19]); BPB_Media = bytData[21]; BPB_FATSz16 = (UInt16)(bytData[23] <<8| bytData[22]); BPB_SecPerTrk = (UInt16)(bytData[25] <<8| bytData[24]); BPB_NumHeads = (UInt16)(bytData[27] <<8| bytData[26]); BPB_HiddSec = (UInt32)(bytData[31] <<24| bytData[30] <<16| bytData[29] <<8| bytData[28]); BPB_TotSec32 = (UInt32)(bytData[35] <<24| bytData[34] <<16| bytData[33] <<8| bytData[32]); //----------if (FATType ==3) { //FAT32 BPB_FATSz32 = (UInt32)(bytData[39] <<24| bytData[38] <<16| bytData[37] <<8| bytData[36]); BPB_ExtFlags = (UInt16)(bytData[41] <<8| bytData[40]); BPB_FSVer = (UInt16)(bytData[43] <<8| bytData[42]); BPB_RootClus = (UInt32)(bytData[47] <<24| bytData[46] <<16| bytData[45] <<8| bytData[44]); BPB_FSInfo = (UInt16)(bytData[49] <<8| bytData[48]); BPB_BkBootSec = (UInt16)(bytData[51] <<8| bytData[50]); BPB_Reserved =newbyte[12]; for (i =0; i <12; i++) BPB_Reserved[i] = bytData[i +52]; //---------- BS_drvNum = bytData[64]; BS_Reserved1 = bytData[65]; BS_BootSig = bytData[66]; BS_VolID =newbyte[4]; for (i =0; i <4; i++) BS_VolID[i] = bytData[67+ i]; BS_VolLab =newbyte[11]; for (i =0; i <11; i++) BS_VolLab[i] = bytData[71+ i]; BS_FilSysType =newbyte[8]; for (i =0; i <8; i++) BS_FilSysType[i] = bytData[82+ i]; ExecutableCode =newbyte[420]; for (i =0; i <420; i++) ExecutableCode[i] = bytData[90+ i]; } else { //FAT16 BS_drvNum = bytData[36]; BS_Reserved1 = bytData[37]; BS_BootSig = bytData[38]; BS_VolID =newbyte[4]; for (i =0; i <4; i++) BS_VolID[i] = bytData[39+ i]; BS_VolLab =newbyte[11]; for (i =0; i <11; i++) BS_VolLab[i] = bytData[43+ i]; BS_FilSysType =newbyte[8]; for (i =0; i <8; i++) BS_FilSysType[i] = bytData[54+ i]; ExecutableCode =newbyte[448]; for (i =0; i <448; i++) ExecutableCode[i] = bytData[62+ i]; //FAT32 BPB_FATSz32 =0; BPB_ExtFlags =0; BPB_FSVer =0; BPB_RootClus =0; BPB_FSInfo =0; BPB_BkBootSec =0; BPB_Reserved =newbyte[12]; } //---------- EndingFlag = (UInt16)(bytData[510] <<8| bytData[511]); } #endregion//檔案系統判斷(採用微軟的判斷方法) publicstaticbyte IsType(byte[] bytData) { //不是合法BPB扇區資料if (bytData[510] !=0x55|| bytData[511] !=0xaa) return0; //跳轉指令不合法if (bytData[0] !=0xeb&& bytData[0] !=0xe9) return0; //每扇區包含的位元組數(一般為512個位元組) UInt16 BPB_BytsPerSec = (UInt16)(bytData[12] <<8| bytData[11]); //僅處理512個位元組的扇區if (BPB_BytsPerSec !=512) return0; //每簇扇區數byte BPB_SecPerClus = bytData[13]; //保留扇區數 UInt16 BPB_RsvdSecCnt = (UInt16)(bytData[15] <<8| bytData[14]); //FAT表的個數byte BPB_NumFATs = bytData[16]; //FAT表的個數必須為2if (BPB_NumFATs !=2) return0; //根目錄項數(32位元組為單位) UInt16 BPB_RootEntCnt = (UInt16)(bytData[18] <<8| bytData[17]); //分割槽總扇區數(<32M時用) UInt16 BPB_TotSec16 = (UInt16)(bytData[20] <<8| bytData[19]); //每個FAT佔的扇區數 UInt16 BPB_FATSz16 = (UInt16)(bytData[23] <<8| bytData[22]); //分割槽總扇區數(>=32M時用) UInt32 BPB_TotSec32 = (UInt32)(bytData[35] <<24| bytData[34] <<16| bytData[33] <<8| bytData[32]); //每個FAT佔的扇區數(FAT32) UInt32 BPB_FATSz32 = (UInt32)(bytData[39] <<24| bytData[38] <<16| bytData[37] <<8| bytData[36]); UInt64 FATSz =0, TotSec =0, DataSec =0; UInt64 RootDirSectors = (UInt64)(((BPB_RootEntCnt *32) + (BPB_BytsPerSec -1)) / BPB_BytsPerSec); if (BPB_FATSz16 !=0) FATSz = BPB_FATSz16; else FATSz = BPB_FATSz32; if (BPB_TotSec16 !=0) TotSec = BPB_TotSec16; else TotSec = BPB_TotSec32; DataSec = TotSec - (BPB_RsvdSecCnt + (BPB_NumFATs