Я работаю над проектом, в котором мне нужно прочитать ВРВ раздела FAT32, затем на основе этого убедитесь, что раздел действительно является допустимым FAT32, прежде чем делать с ним что-либо еще.
В соответствии с Документация Microsoft (в таблице, начиная со страницы 9), поля BPB_RootEntCnt
(расположен в 0x17, размер 2), и BPB_TotSec16
(расположен в 0x19, размер 2) должен быть установлен в 0 в случае любого раздела FAT32. Поскольку в официальной документации об этом совершенно ясно, я предположил, что проверка, равны ли они нулю, является хорошей идеей, чтобы убедиться, что раздел является допустимым 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. «путь к объему» должен быть, конечно, /dev/...
, например /dev/disk1s1
на OS X или /dev/sda1
в линуксе
Так как это может быть? Эта программа всегда выводит два ненулевых значения, если вы указываете путь к разделу FAT32, в то время как (согласно документации) эти значения должны быть равны нулю.
Это твоя программа 🙂
Смещения для BPB_RootEntCnt
а также BPB_TotSec16
не 0x17
(= 23) и 0x19
(= 25), но 17
а также 19
,
Чтобы сравнить данные по таким проблемам в будущем, полезно получить первые КБ
с dd
в файл и просматривать его с помощью шестнадцатеричного редактора. (и читать внимательнее …)