1. 程式人生 > >FAT16檔案系統解析(C 版本)

FAT16檔案系統解析(C 版本)

//基本類 [葉帆工作室] 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!=0xaareturn0;        //跳轉指令不合法if (bytData[0!=0xeb&& bytData[0!=0xe9return0;        //每扇區包含的位元組數(一般為512個位元組)        UInt16 BPB_BytsPerSec = (UInt16)(bytData[12<<8| bytData[11]);        //僅處理512個位元組的扇區if (BPB_BytsPerSec !=512return0;        //每簇扇區數byte BPB_SecPerClus = bytData[13];        //保留扇區數        UInt16 BPB_RsvdSecCnt = (UInt16)(bytData[15<<8| bytData[14]);        //FAT表的個數byte BPB_NumFATs = bytData[16];        //FAT表的個數必須為2if (BPB_NumFATs !=2return0;        //根目錄項數(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