在上一章节《FAT12文件系统剖析1》中,我们把a.img启动软盘使用FreeDos系统格式化为FAT12文件系统的组织方式,并且向a.img软盘写入两个文件,同时通过FreeDos操作系统也查看了a.img软盘中的文件。之所以这么做,是因为主引导程序不可以超过512字节,所以主引导程序需要在基本的初始化工作完成后加载启动介质(这里是软盘a.img)中的启动程序到内存,然后跳转到对应内存处执行。
上一节我们是通过FreeDos操作系统来查看a.img软盘中FAT12根目录的目标文件,那么在程序中我们怎去判断目标文件是否存在FAT12根目录中?要解决这个问题,我们首先来了解FAT12的根目录在文件系统中的位置
上图中直接给了计算根目录大小的公式:根目录个数 * 每个根目录项大小 / 每个扇区大小 = 根目录占用的扇区数量,
其中根目录个数在上一章节我们已经求出,为0xe0,十进制为224,不熟悉的可以参考上一章节。每个根目录项大小为32字节,每个扇区大小为512字节,那么有 224 * 32 / 512 = 14,即根目录文件项在FAT12文件系统中总共占用14个扇区,也就是7168字节。
除了上边说的根目录区,我们还需要了解下根目录项,根目录由根目录项组成,上文中的224,就是FAT12文件系统有224个根目录项,一个根目录项代表根目录中的一个文件索引,每个根目录项中,包含了这个文件的基本信息,如下:
下边需要做的实验,便是读取FAT12中每个根目录项的内容并打印(代码在上章代码基础上增加更目录项的打印)
#include <QtCore/QCoreApplication>
#include <QFile>
#include <QDataStream>
#include <QDebug>
#pragma pack(push)
#pragma pack(1)
struct Fat12Header
{
char BS_OEMName[8];
ushort BPB_BytsPerSec; //每扇区字节数,默认512字节
uchar BPB_SecPerClus; //每簇扇区数
ushort BPB_RsvdSecCnt;
uchar BPB_NumFATs;
ushort BPB_RootEntCnt; //最大跟目录文件数
ushort BPB_TotSec16;
uchar BPB_Media;
ushort BPB_FATSz16;
ushort BPB_SecPerTrk;
ushort BPB_NumHeads;
uint BPB_HiddSec;
uint BPB_TotSec32;
uchar BS_DrvNum;
uchar BS_Reserved1;
uchar BS_BootSig;
uint BS_VolID;
char BS_VolLab[11];
char BS_FileSysType[8];
};
//根目录项结构体
struct RootEntry
{
char DIR_Name[11];
uchar DIR_Attr;
uchar reserve[10];
ushort DIR_WrtTime;
ushort DIR_WrtDate;
ushort DIR_FstClus;
uint DIR_FileSize;
};
#pragma pack(pop)
void PrintHeader(Fat12Header& rf, QString p)
{
QFile file(p);
if( file.open(QIODevice::ReadOnly) )
{
QDataStream in(&file);
file.seek(3); //偏移开头3字节
in.readRawData(reinterpret_cast<char*>(&rf), sizeof(rf));
rf.BS_OEMName[7] = 0;
rf.BS_VolLab[10] = 0;
rf.BS_FileSysType[7] = 0;
qDebug() << "BS_OEMName: " << rf.BS_OEMName;
qDebug() << "BPB_BytsPerSec: " << hex << rf.BPB_BytsPerSec;
qDebug() << "BPB_SecPerClus: " << hex << rf.BPB_SecPerClus;
qDebug() << "BPB_RsvdSecCnt: " << hex << rf.BPB_RsvdSecCnt;
qDebug() << "BPB_NumFATs: " << hex << rf.BPB_NumFATs;
qDebug() << "BPB_RootEntCnt: " << hex << rf.BPB_RootEntCnt;
qDebug() << "BPB_TotSec16: " << hex << rf.BPB_TotSec16;
qDebug() << "BPB_Media: " << hex << rf.BPB_Media;
qDebug() << "BPB_FATSz16: " << hex << rf.BPB_FATSz16;
qDebug() << "BPB_SecPerTrk: " << hex << rf.BPB_SecPerTrk;
qDebug() << "BPB_NumHeads: " << hex << rf.BPB_NumHeads;
qDebug() << "BPB_HiddSec: " << hex << rf.BPB_HiddSec;
qDebug() << "BPB_TotSec32: " << hex << rf.BPB_TotSec32;
qDebug() << "BS_DrvNum: " << hex << rf.BS_DrvNum;
qDebug() << "BS_Reserved1: " << hex << rf.BS_Reserved1;
qDebug() <&