Прямое чтение файлов с диска не средствами файловой системы

Тема в разделе "WASM.WIN32", создана пользователем Dmitry_Milk, 3 июн 2024.

  1. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Где-нибудь есть собранная в одном документе и достаточно структурированная инфа о том, как взаимосвязаны устройства/тома/кластеры/LBA в винде, и как с ними работать?

    Хочу прочитать содержимое файла через прямое чтение LBA-блоков, но пока только смог заполучить списки логических номеров кластеров, в которых располагается файл, через DeviceIoControl / FSCTL_GET_RETRIEVAL_POINTERS.

    Теперь, скорее всего, надо как-то преобразовать логические номера кластеров в номера LBA и найти функции, позволяющие работать с конкретными LBA (хотя может быть я даже неправильно знаю, и LBA относится не к устройствам, а к томам?).

    На learn.microsoft.com наверное это где-то есть, но, скажем, https://learn.microsoft.com/en-us/windows/win32/api/_fs/ - просто огромный плоский список всяких штук, о назначении которых без предварительного знания догадаться очень сложно.
     
  2. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    189
    Да.. тема мутная, а потому приходится искать истину только опытным путём.
    Когда-то я тоже читал файл таким образом, причём вполне успешно. Конкретных деталей сейчас не припомню, но общая картина вроде такая.

    Кластер обозвали логическим только потому, что во-первых адресация к тому Volume, а не к физ.диску как к более крупной единице. Поскольку через CreateFile() мы можем открывать тома, то логический превращается в физический. Во-вторых, при вызове FSCTL_GET_RETRIEVAL_POINTERS можно указывать стартовый кластер (аля точку отсчёта) в структуре STARTING_VCN_INPUT_BUFFER - нужно всегда сбрасывать его в нуль, иначе к результату нужно будет применять поправки, т.е. фактически кластер так-же становится логическим. Таким образом если открываем том и указываем стартовый кластер(0), то на выходе получаем физ.кластер. Остальное проблемы драйвера и он сам разберётся что там к чему.

    В общем случае двигаться нужно так..

    1. GetDiskFreeSpace() чтобы узнать кол-во секторов в одном кластере.
    2. FSCTL_GET_RETRIEVAL_POINTERS с vcn=0, чтобы запросить инфу о кластерах файла.
    3. Результат пункта(2) умножить на кол-во секторов пункта(1).
    4. Открыть том через CreateFile() с обязательной шарой R/W.
    5. Установить позицию для чтения SetFilePointer(), передав ей результат пункта(3).
    6. ReadFile() для чтения секторов.
    7. Если пункт(2) вернул фрагменты, то возврат к пункту(5).
     
    Dmitry_Milk нравится это.
  3. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    Dmitry_Milk,
    о прямом чтении файлов с диска с учетом его геометрии я видел в какой-то из статей Marylin, ссылки на них собраны здесь
     
    Dmitry_Milk нравится это.
  4. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Marylin, Все это похоже на то, как было устроено еще в MS-DOS-овском FAT, когда были функции BIOS, позволяющие читать/писать сектор по логическому номеру.

    Но меня смущает тот факт, что много где пишется про то, что работа с носителями сейчас осуществляется через LBA (Logical Block Addressing). Вроде по сути похоже на логическую нумерацию секторов в томе, но я не уверен, что это одно и то же. В частности, везде, где говорится про особенности работы SSD-накопителей, везде фигурирует чтение/запись (и переотображение на разные физические участки контроллером SSD) именно этих блоков LBA, а не логическая нумерация секторов.
     
  5. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    189
    LBA этот тот-же сектор, просто не с 3-хмерной адресацией CHS, а линейной 0..N.
    Транслятор адресов в контроллёре диска сам преобразует линейную адресацию как нужно в зависимости от того, какого типа накопитель HDD или SSD.
     
    miilalex и Dmitry_Milk нравится это.
  6. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    А, ну то есть все-таки логическая (не цилиндр/сектор, а подряд целочисленная) нумерация секторов и LBA это разные названия одного и того же. Тогда действительно все понятно. Спасибо.
     
  7. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    189
    Dmitry_Milk, для тестов возьми редактор HxD, открой в нём том где лежит файл, и перейди к сектору, который вычислишь по результату FSCTL_GET_RETRIEVAL_POINTERS. Если файла там нет, значит где-то в расчётах ошибка.
    --- Сообщение объединено, 3 июн 2024 ---
    обычно в кластере 8-секторов = 4КБ.
    если от FSCTL_GET_RETRIEVAL_POINTERS ты получил кластер(200),
    то умножаешь его 8 и получаешь таким образом LBA(1600), который будет совпадать с номером сектора в HxD.
     
  8. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Спасибо, все получилось, через GetDiskFreeSpace() действительно получил всю нужную инфу, и по вычисленному смещению из "файла" информация соответствует содержимому файла.

    Правда для установки позиции надо использовать уже SetFilePointerEx() c 64-битной позицией (т.к. размер тома сейчас редко у кого бывает меньше 4 гигабайт :) ).

    Ну и возможно в скором времени размеры дисков могут перестать "влезать" в функцию GetDiskFreeSpace(). И если я не ошибаюсь, на замену ей придется использовать GetDiskSpaceInformation(), принимающую структуру с 64-битными полями (правда не проверял, т.к пока хватает размеров GetDiskFreeSpace).
     
    Marylin нравится это.