Victoria: случайно импортозаместился (21.08.2025). Печать
2025 - Август
21.08.2025 00:00
Save & Share
Victoria - программа для проверки и восстановления накопителей. Белорусская - а так как в некоторых местах идёт жёсткое импортозамещение на отечественный отстой (когда на американское ядро Debian разработчики криво натягивают свою сову), нужно было искать альтернативу - да ещё и не под Windows. Её не оказалось - пришлось писать самому.


На самом деле, всё было немного не так - и именно мелкие детали переворачивают понимание ситуации вверх тормашками. Изначально программа писалась для тестирования магнитного уничтожителя накопителей: действительно ли он убивает данные конкретно на блинах (а не тупо выжигает контроллер). А то, что программой можно проверять поверхность носителей, - побочный эффект; и раз запрещено пользоваться нормальным софтом - придётся допиливать этот огрызок до нормального состояния.

В процессе написания ПО, было доказано в очередной раз: на Astra + Qt - времени на разработку затрачивается гораздо больше (баги не уходят, а лишь заменяются на другие, - мешая и в смежных областях работы), чем на Windows с нормальным языком типа Borland (который на фоне Qt считается лапочкой). Другим результатом был успешный опыт записи-чтения уникальных данных с диска - отвязавшись не просто от файловой системы, но и от размера кластера-сектора, и от самих кластеров-секторов. А вот основной результат с блинами пока достигнут не был: там проблемы нетехнического характера, которые пока написать нельзя - и, может быть, нельзя будет писать вообще.

Алгоритмы записи и чтения уникальных данных:
- на носителе создаётся один раздел NTFS (в случае проверки всего носителя - во весь носитель). Свойства NTFS и прочие баги Qt описываются здесь, и они своей точностью дополняют данный материал;
- весь раздел забивается 8-байтными данными quint64 потоком QDataStream: даже имея баг записи quint64 (не равно int64: проверено HEX-редакторами несколько раз в разное время) - он обратимый в рамках операции чтения после записи (а также работает быстро - что позволяет использовать 1 разогнанное ядро процессора без многопоточности);
- в 64 бита данных входят сами изменяющиеся данные (правая часть: последовательное увеличение нуля до количества записываемых данных) и фиксированный паттерн (левая часть: идентификатор, что это именно порождённые записью данные, а не какой-то мусор). Паттерн и максимальное число данных разделяются нулём. Паттерн должен быть вычурным: выбранный паттерн 1111...10 - привёл к тому, что при неполном заполнении раздела в зоне MFT/MBR нашлось одно "искомое" число, - предпочтительнее 1010...101010 (где последний 0 - между паттерном и данными);
- проверка большого количества данных, минуя файловую систему, - требует огромного количества RAM (128ГБ для 1ТБ данных: убедиться, что все 125млрд уникальных данных на диске 1ТБ - записались корректно). Поэтому в ход идут ухищрения: создать массив bool размерностью 16млрд - и делать 8 проходов по жёсткому диску (проверив во время первого прохода, что все 125млрд данных нашлись - просто разместить их негде). Но так как это только моя цель (чтение информации, минуя ФС и сектора) - проще файл считывать обратным алгоритмом: тогда ни фрагментация файла не важна, ни прочие данные вне раздела, ни огромный массив bool не требуется.

Сущности:
- класс cVolume (sys/statvfs.h для statvfs). Получение информации о разделе (statvfs: размер кластера f_frsize, полное количество кластеров f_blocks, их произведение как количество байтов в разделе, количество свободных кластеров f_bfree, их произведение как количество свободного места в разделе. Информация получилась избыточная - по сути, нужно полное количество байтов в разделе: при записи зона MFT превратится в 0 байтов - количество ценной информации станет равным размеру раздела;
- класс cDrive (sys/ioctl.h для ioctl, fcntl.h для open и O_RDONLY, linux/fs.h для BLKSSZGET и аналогичных, unistd.h для pread (необязательно), sys/types.h для off_t, qthread.h для sleep (неозябательно), qdebug.h для дебага, qdatastream.h" для QDataStream (fstream - говно), qfile.h для QFile). Получение информации о носителе (ioctl: размер сектора BLKSSZGET, количество секторов BLKGETSIZE, количество байтов BLKGETSIZE64). По сути, здесь вся информация лишняя - но помогает в понимании поведения носителя и разделов. Чтение данных с помощью QFile (да, весь носитель открывается как "файл") и QDataStream. Во время чтения первых ~37МБ - читается служебная информация по NTFS, а также MBR (с огромной вероятностью: многовато служебной информации);
- класс cData (qdatastream.h, qfile.h, math.h для pow, QtGlobal для quint64). Получение максимального количества данных для забиваемого раздела, вычисление паттерна (в числовом и текстовом виде, для удобства отладки), запись данных именно в один огромный файл с помощью QFile и QDataStream (максимально возможная скорость записи и избавление части от багов драйвера NTFS (ntfs, ntfs3) в Astra).

Нюансы, не содержащиеся в статье о багах Qt или имеющие особую важность:
- текстовое отслеживание паттерна в считанных данных - замедляет скорость чтения в 60 раз. После того, как убедились в правильности нахождения паттерна и данных, - нужно выставить всего 2 условия: значение quint64 больше или равно числу-паттерну (похоже на искомые данные) и меньше числа максимального значения данных (точно искомые данные);
- форматирование носителя в программе сделать не удалось даже под root: команда выполняется только в консоли (mkfs -t ntfs -c 512 -Q /dev/sdb1);
- quint64, как и int64, - позволяет хранить уникальные данные с паттерном - вплоть до дисков 30ТБ;
- драйвер ntfs3 глючит и не даёт заполнить оставшиеся 6400 блоков раздела по 1КиБ. Драйвер ntfs данной проблемы не имеет, но имеет ограничение по скорости ~30МБ/с.
Обновлено ( 21.08.2025 11:59 )