我正在做一个项目,在这个项目中,我需要读取FAT32分区的BPB,然后在此基础上,在对该分区执行任何其他操作之前,验证该分区确实是有效的FAT32。
根据Microsoft's documentation(在第9页开始的表中),如果存在任何FAT32分区,则字段BPB_RootEntCnt
(位于0x17,大小2)和BPB_TotSec16
(位于0x19,大小2)都必须设置为0。由于官方文档对此非常清楚,我认为检查这些值是否为零是验证分区是否为有效的FAT32的一个好主意(这两个值不是我用于验证的唯一值,而是有问题的值)。
我尝试了许多不同的存储设备,每一个都在不同的操作系统下格式化为FAT32,并且在每一种情况下,这两个字段都有非零值!
这是为什么?FAT32的官方文件明确指出,这些字段必须设置为零。那么,所有不同的格式化工具(包括Windows的内置格式化选项)如何忽略这一规则呢?
首先我认为我的程序没有按预期工作,但我认为没有问题。下面是一个简短的自包含示例,它只打印出FAT32分区的这两个字段的值:
#include <iostream>
#include <string>
#include <cstdio>
#include <unistd.h>
using namespace std;
void printFAT32Fields(const string& vol) {
// Unmount the volume
system(("sudo umount -f "s + vol + " 1> /dev/null 2>&1"s).c_str());
// Open
auto fp = fopen(vol.c_str(), "r");
if (!fp) {
perror("Error");
throw runtime_error("The volume '"s + vol + "' cannot be accessed!"s);
}
setbuf(fp, NULL);
uint16_t BPB_RootEntCnt = 0x0;
uint16_t BPB_TotSec16 = 0x0;
fseek(fp, 0x17, SEEK_SET);
fread(&BPB_RootEntCnt, 1, 2, fp);
fseek(fp, 0x19, SEEK_SET);
fread(&BPB_TotSec16, 1, 2, fp);
fclose(fp);
cout << BPB_RootEntCnt << " " << BPB_TotSec16 << endl;
}
int main() {
if (getuid()) {
cout << "This program needs root privileges to run!" << endl;
return 0;
}
try {
printFAT32Fields("PATH TO VOLUME GOES HERE");
} catch(runtime_error err) {
cout << err.what();
}
return 0;
}
这段代码也适用于OS X、Linux和其他类似UNIX的系统,但不适用于Windows。”“path to volume”当然必须是
/dev/...
,例如在OSX上是/dev/disk1s1
,在Linux上是/dev/sda1
。那这怎么可能呢?如果给这个程序一个FAT32分区的路径,它总是输出两个非零值,而(根据文档)这些值应该是零。
最佳答案
这是你的程序:)BPB_RootEntCnt
和BPB_TotSec16
的偏移量
不是0x17
(=23)和0x19
(=25),而是17
和19
。
为了比较将来此类问题的数据,可以得到第一个知识库
在文件中使用dd
并使用十六进制编辑器查看它。(更仔细地阅读…)
关于c++ - FAT32实际上不符合Microsoft的文档,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31450920/