`
happmaoo
  • 浏览: 4349116 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

FAT16文件系统解析(C#版本)

阅读更多

今天FAT文件系统总算告一个段落了,已经可以非常完美的读取包含FAT16文件系统的磁盘了。由于是采用C#编写,直接借鉴的代码很少,并且考虑到MF不支持二进制序列化,所以对数据结构的解析,是一个一个字节进行的,所以很耗费时间。下面就是程序运行后的结果(可以识别物理磁盘及物理磁盘的分区)。
下图是用文件浏览器查看的结果。
磁盘系统的MDR和DBR信息如下。
为了便于后来者,把主要的结构声明代码罗列如下,希望有借鉴意义。
//基本类[叶帆工作室]http://blog.csdn.net/yefanqiu/
publicclassDiskBase
{
#region//MBRhttp://blog.csdn.net/yefanqiu/
publicstructPartitionTable
{
publicbyteBootFlag;//分区活动标志只能选00H和80H。80H为活动,00H为非活动
publicCHSStartCHS;//分区开始的柱面、磁头、扇区
publicbyteSystemID;//分区类型01FAT3204FAT16<32M06FAT1607HPFS/NTFS050F扩展分区
publicCHSEndCHS;//分区结束的柱面、磁头、扇区
publicUInt32RelativeSectors;//分区起始扇区数,指分区相对于记录该分区的分区表的扇区位置之差(该分区表:LBA=0x0)。
publicUInt32TotalSectors;//分区总扇区数
}
publicstructCHS
{
publicbyteHead;//磁头
publicbyteSector;//扇区六位
publicUInt16Cylinder;//柱面十位
}
publicstructMBR
{
publicbyte[]bytBootCode;//ofs:0.引导代码446字节"FA33C08ED0BC…"
publicPartitionTable[]PT;//ofs:446.64个字节分区表length=4*16
publicUInt16EndingFlag;//ofs:510.结束标识:0xAA55。

publicMBR(byte[]bytData)
{
inti;
bytBootCode
=newbyte[446];
for(i=0;i<446;i++)bytBootCode[i]=bytData[i];

PT
=newPartitionTable[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//DBRhttp://blog.csdn.net/yefanqiu/
//系统引导记录(兼容FAT16和FAT32)
publicstructDBR
{
publicbyte[]BS_JmpBoot;//ofs:0.典型的如:0xEB,0x3E,0x90。
publicbyte[]BS_OEMName;//ofs:3.典型的如:“MSWIN4.1”。
publicUInt16BPB_BytsPerSec;//ofs:11.每扇区字节数。
publicbyteBPB_SecPerClus;//ofs:13.每簇扇区数。
publicUInt16BPB_RsvdSecCnt;//ofs:14.保留扇区数,从DBR到FAT的扇区数。
publicbyteBPB_NumFATs;//ofs:16.FAT的个数。
publicUInt16BPB_RootEntCnt;//ofs:17.根目录项数。
publicUInt16BPB_TotSec16;//ofs:19.分区总扇区数(<32M时用)。
publicbyteBPB_Media;//ofs:21.分区介质标识,优盘一般用0xF8。
publicUInt16BPB_FATSz16;//ofs:22.每个FAT占的扇区数。
publicUInt16BPB_SecPerTrk;//ofs:24.每道扇区数。
publicUInt16BPB_NumHeads;//ofs:26.磁头数。
publicUInt32BPB_HiddSec;//ofs:28.隐藏扇区数,从MBR到DBR的扇区数。
publicUInt32BPB_TotSec32;//ofs:32.分区总扇区数(>=32M时用)。

//---------------------
//FAT32特有
publicUInt32BPB_FATSz32;//ofs:36.每个FAT占的扇区数。
publicUInt16BPB_ExtFlags;//ofs:40.FAT标志
publicUInt16BPB_FSVer;//ofs:42.版本号高字节主版本低字节次版本号
publicUInt32BPB_RootClus;//ofs:44.根目录所在第一个簇的簇号,通常该数值为2,但不是必须为2。
publicUInt16BPB_FSInfo;//ofs:48.保留区中FAT32卷FSINFO结构所占的扇区数,通常为1。
publicUInt16BPB_BkBootSec;//ofs:50.如果不为0,表示在保留区中引导记录的备份数据所占的扇区数,通常为6。同时不建议使用6以外的其他数值。
[MarshalAs(UnmanagedType.ByValArray,SizeConst=12)]
publicbyte[]BPB_Reserved;//ofs:52.备用

//---------------------
publicbyteBS_drvNum;//ofs:64/36.软盘使用0x00,硬盘使用0x80。
publicbyteBS_Reserved1;//ofs:65/37.保留。
publicbyteBS_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.引导代码。
publicUInt16EndingFlag;//ofs:510.结束标识:0xAA55。

//---------------------
//0-未知1-FAT122-FAT163-FAT32其它值为未知
publicbyteFATType;

//获取信息
publicDBR(byte[]bytData)
{
FATType
=IsType(bytData);
inti;
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

//文件系统判断(采用微软的判断方法)
publicstaticbyteIsType(byte[]bytData)
{
//不是合法BPB扇区数据
if(bytData[510]!=0x55||bytData[511]!=0xaa)return0;

//跳转指令不合法
if(bytData[0]!=0xeb&&bytData[0]!=0xe9)return0;

//每扇区包含的字节数(一般为512个字节)
UInt16BPB_BytsPerSec=(UInt16)(bytData[12]<<8|bytData[11]);

//仅处理512个字节的扇区
if(BPB_BytsPerSec!=512)return0;

//每簇扇区数
byteBPB_SecPerClus=bytData[13];
//保留扇区数
UInt16BPB_RsvdSecCnt=(UInt16)(bytData[15]<<8|bytData[14]);
//FAT表的个数
byteBPB_NumFATs=bytData[16];

//FAT表的个数必须为2
if(BPB_NumFATs!=2)return0;

//根目录项数(32字节为单位)
UInt16BPB_RootEntCnt=(UInt16)(bytData[18]<<<span style
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics