Восстановление данных. Практическое руководство
/* 0x70 */ ufs2_daddr_t di_db[NDADDR]; /* 112: Непоср. дисковые блоки */
/* 0xD0 */ ufs2_daddr_t di_ib[NIADDR]; /* 208: Косв. дисковые блоки */
/* 0xE8 */ int64_t di_spare[3]; /* 232: Зарезервировано */
};
Имена файлов хранятся в каталогах (рис. 8.12). В индексных дескрипторах их нет. С точки зрения UFS, каталоги являются файлами особого типа и могут храниться по любому адресу, принадлежащему группе цилиндров. Файловая система UFS поддерживает несколько типов хеширования каталогов, однако на структуре хранения имен это никак не отражается. Имена хранятся в блоках, называемых
, в структурах типаDIRBLKSIZ
, выровненных по 4-х байтной границе.direct
Рис. 8.12. Хранение имен файлов и каталогов
Структура
определена в файле /src/ufs/ufs/dir.h (листинг 8.11) и содержит: номер inode, описывающий данный файл, тип файла, его имя, а также длину самой структурыdirect
, используемую для нахождения следующей структуры этого типа в блоке.direct
Листинг 8.11. Структура
, отвечающая за хранение имен файлов и каталогов<b>direct</b>
struct direct {
/* 0x00 */ u_int32_t d_ino; /* Номер inode данной записи */
/* 0x04 */ u_int16_t d_reclen; /* Длина данной записи */
/* 0x06 */ u_int8_t d_type; /* Тип файла, см. ниже */
/* 0x07 */ u_int8_t d_namlen; /* Длина строки в d_name */
/* 0x08 */ char d_name[MAXNAMLEN + 1]; /* Имя с длиной <= MAXNAMLEN */
};
На этом описание файловой системы UFS можно считать законченным. Для ручного восстановления данных приведенной информации вполне достаточно.
На развалинах империи
При удалении файла на разделе UFS происходят следующие события (они перечислены в порядке расположения соответствующих структур в разделе и могут не совпадать с порядком их возникновения).
□ В суперблоке обновляется поле
(время последнего доступа к разделу).fs_time
□ В суперблоке обновляется структура
(количество свободных inode и блоков данных в разделе).fs_cstotal
□ В группе цилиндров обновляются карты занятых inode и блоков данных. Inode и все блоки данных удаляемого файла помечаются как освобожденные.
□ В inode родительского каталога обновляются поля времени последнего доступа и времени последней модификации.
□ В inode родительского каталога обновляется поле времени последнего изменения inode.
□ В inode удаляемого файла обнуляются поля
(IFMT, права доступа),di_mode
(количество ссылок на файл) иdi_nlink
(размер файла).di_size
□ В inode удаляемого файла затираются нулями поля
(массив указателей на 12 первых блоков файла) иdi_db
(указатель на блок косвенной адресации).di_ib
□ В inode удаляемого файла обновляются поля времени последней модификации и последнего изменения inode, время последнего доступа при этом остается неизменным.
□ В inode удаляемого файла обновляется поле
. В исходных текстах оно помечено как зарезервированное, но просмотр дампа показывает, что это не так. Судя по всему, здесь хранится нечто вроде последовательности обновления (update sequence), используемой для контроля целостности inode. Однако это только мое предположение.di_spare
□ В каталоге удаленного файла размер предшествующей структуры
увеличивается на значениеdirect
, в результате чего она как бы "поглощает" имя удаляемого файла. Однако физического затирания имени не происходит. Во всяком случае оно затирается не сразу, а лишь в тот момент, когда в этом возникнет реальная необходимость.d_reclen
Средства восстановления файлов
Обнаружив, что один или несколько файлов были непреднамеренного удалены, немедленно демонтируйте раздел и запустите дисковый редактор, работающий на секторном уровне. Например, можно воспользоваться вариантом уже описанного редактора lde, переписанным для BSD. К сожалению, в моей системе (4.5 BSD) он работает крайне нестабильно. Так, например, он не отображает основные структуры данных в удобочитаемом виде, хотя поддержка UFS в нем заявлена. При наличии достаточного количества свободного дискового пространства можно скопировать раздел в файл и натравить на него любой hex-редактор (например, BIEW). Как вариант, можно открыть непосредственно само устройство раздела (например,
). Наконец, можно загрузить компьютер с загрузочного CD с Windows РЕ и воспользоваться любым Windows-редактором — от Microsoft Disk Probe до Runtime DiskExplorer. Можно загрузиться даже с загрузочной дискеты MS-DOS и запустить Norton Disk Editor (правда, Norton Disk Editor не поддерживает ни диски большого объема, ни устройства SCSI). Наконец, можно запустить KNOPPIX или любой дистрибутив Live Linux, ориентированный на восстановление данных. Правда, в большинстве "реанимационных" дистрибутивов, в частности, Frenzy 0.3, никакого дискового редактора вообще нет./dev/ad0s1a
В общем, выбор средств восстановления достаточно широк.
Техника восстановления удаленных файлов
Начнем наше обсуждение на грустной ноте. Поскольку при удалении файла ссылки на 12 первых блоков и 3 блока косвенной адресации необратимо затираются, автоматическое восстановление данных принципиально невозможно. Найти удаленный файл можно только по его содержимому. Искать, естественно, необходимо в свободном пространстве. Вот тут-то нам и пригодятся карты, расположенные за концом описателя группы цилиндров.
Если нам повезет, и файл окажется нефрагментированным (а на разделах UFS, как уже отмечалось, фрагментация обычно отсутствует или крайне невелика), остальное будет делом техники. Достаточно выделить группу секторов и записать ее на диск. Здесь, как и во всех ранее описанных случаях, следует помнить, что запись ни в коем случае не должна вестись на сам восстанавливаемый раздел! Например, файл можно передать на соседний компьютер по сети. К сожалению, поле длины файла безжалостно затирается при его удалении, и реальный размер приходится определять "на глазок". В реальности эта задача намного проще, чем кажется на первый взгляд. Неиспользуемый хвост последнего фрагмента всегда забивается нулями, что дает хороший ориентир. Проблема заключается в том, что некоторые типы файлов содержат в своем конце некоторое количество нулей, при отсечении которых их работоспособность нарушается, поэтому тут приходится экспериментировать.
А что делать, если файл фрагментирован? Первые 13 блоков (именно блоков, а не фрагментов!) придется собирать руками. В идеальном случае это будет один непрерывный регион. Хуже, если первый фрагмент расположен в "чужом" блоке (т.е. блоке, частично занятом другим файлом), а оставшиеся 12 блоков находятся в одном или нескольких регионах. На практике, однако, достаточно трудно представить себе ситуацию, в которой первые 13 блоков были бы сильно фрагментированы, ведь UFS поддерживает фоновую дефрагментацию. Такое может произойти только при масштабной перегруппировке большого количества файлов, что в реальной жизни практически никогда не встречается. Поэтому будем считать, что 13-й блок файла найден. В массив непосредственной адресации он уже не помещается (там содержатся только 12 блоков), и ссылка на него, как и на все последующие блоки файла, должна содержаться в блоках косвенной адресации. Как вы помните, блоки косвенной адресации при удалении файла помечаются как свободные, но не затираются сразу же. Затирание происходит только по мере реальной необходимости, и это существенно упрощает нашу задачу.