FAT32 实际上不符合 Microsoft 的文档
FAT32 in practice does not conform Microsoft's documentation
我正在做一个项目,我需要读取 FAT32 分区的 BPB,然后在此基础上验证该分区确实是有效的 FAT32,然后再对其进行任何其他操作。
根据Microsoft's documentation(在第9页开始的table),字段BPB_RootEntCnt
(位于0x17,大小2)和BPB_TotSec16
(位于在 0x19,大小 2) 在任何 FAT32 分区的情况下都必须设置为 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/...
,例如 OS X 上的 /dev/disk1s1
,或 Linux 上的 /dev/sda1
。
这怎么可能?如果你给它一个 FAT32 分区的路径,这个程序总是打印出两个非零值,而(根据文档)这些值应该是零。
这是你的程序:)
BPB_RootEntCnt
和 BPB_TotSec16
的偏移量
不是 0x17
(=23) 和 0x19
(=25),而是 17
和 19
。
为了将来比较此类问题的数据,获取第一个 KB 很有帮助
在文件中添加 dd
并使用十六进制编辑器查看它。 (并仔细阅读...)
我正在做一个项目,我需要读取 FAT32 分区的 BPB,然后在此基础上验证该分区确实是有效的 FAT32,然后再对其进行任何其他操作。
根据Microsoft's documentation(在第9页开始的table),字段BPB_RootEntCnt
(位于0x17,大小2)和BPB_TotSec16
(位于在 0x19,大小 2) 在任何 FAT32 分区的情况下都必须设置为 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/...
,例如 OS X 上的 /dev/disk1s1
,或 Linux 上的 /dev/sda1
。
这怎么可能?如果你给它一个 FAT32 分区的路径,这个程序总是打印出两个非零值,而(根据文档)这些值应该是零。
这是你的程序:)
BPB_RootEntCnt
和 BPB_TotSec16
的偏移量
不是 0x17
(=23) 和 0x19
(=25),而是 17
和 19
。
为了将来比较此类问题的数据,获取第一个 KB 很有帮助
在文件中添加 dd
并使用十六进制编辑器查看它。 (并仔细阅读...)