Восстановление данных. Практическое руководство, стр. 65
/* 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 поддерживает несколько типов хеширования каталогов, однако на структуре хранения имен это никак не отражается. Имена хранятся в блоках, называемых
DIRBLKSIZdirectРис. 8.12. Хранение имен файлов и каталогов
Структура
directdirectЛистинг 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□ В суперблоке обновляется структура
fs_cstotal□ В группе цилиндров обновляются карты занятых inode и блоков данных. Inode и все блоки данных удаляемого файла помечаются как освобожденные.
□ В inode родительского каталога обновляются поля времени последнего доступа и времени последней модификации.
□ В inode родительского каталога обновляется поле времени последнего изменения inode.
□ В inode удаляемого файла обнуляются поля
di_modedi_nlinkdi_size□ В inode удаляемого файла затираются нулями поля
di_dbdi_ib□ В inode удаляемого файла обновляются поля времени последней модификации и последнего изменения inode, время последнего доступа при этом остается неизменным.
□ В inode удаляемого файла обновляется поле
di_spare□ В каталоге удаленного файла размер предшествующей структуры
directd_reclenСредства восстановления файлов
Обнаружив, что один или несколько файлов были непреднамеренного удалены, немедленно демонтируйте раздел и запустите дисковый редактор, работающий на секторном уровне. Например, можно воспользоваться вариантом уже описанного редактора lde, переписанным для BSD. К сожалению, в моей системе (4.5 BSD) он работает крайне нестабильно. Так, например, он не отображает основные структуры данных в удобочитаемом виде, хотя поддержка UFS в нем заявлена. При наличии достаточного количества свободного дискового пространства можно скопировать раздел в файл и натравить на него любой hex-редактор (например, BIEW). Как вариант, можно открыть непосредственно само устройство раздела (например,
/dev/ad0s1aВ общем, выбор средств восстановления достаточно широк.
Техника восстановления удаленных файлов
Начнем наше обсуждение на грустной ноте. Поскольку при удалении файла ссылки на 12 первых блоков и 3 блока косвенной адресации необратимо затираются, автоматическое восстановление данных принципиально невозможно. Найти удаленный файл можно только по его содержимому. Искать, естественно, необходимо в свободном пространстве. Вот тут-то нам и пригодятся карты, расположенные за концом описателя группы цилиндров.
Если нам повезет, и файл окажется нефрагментированным (а на разделах UFS, как уже отмечалось, фрагментация обычно отсутствует или крайне невелика), остальное будет делом техники. Достаточно выделить группу секторов и записать ее на диск. Здесь, как и во всех ранее описанных случаях, следует помнить, что запись ни в коем случае не должна вестись на сам восстанавливаемый раздел! Например, файл можно передать на соседний компьютер по сети. К сожалению, поле длины файла безжалостно затирается при его удалении, и реальный размер приходится определять "на глазок". В реальности эта задача намного проще, чем кажется на первый взгляд. Неиспользуемый хвост последнего фрагмента всегда забивается нулями, что дает хороший ориентир. Проблема заключается в том, что некоторые типы файлов содержат в своем конце некоторое количество нулей, при отсечении которых их работоспособность нарушается, поэтому тут приходится экспериментировать.
А что делать, если файл фрагментирован? Первые 13 блоков (именно блоков, а не фрагментов!) придется собирать руками. В идеальном случае это будет один непрерывный регион. Хуже, если первый фрагмент расположен в "чужом" блоке (т.е. блоке, частично занятом другим файлом), а оставшиеся 12 блоков находятся в одном или нескольких регионах. На практике, однако, достаточно трудно представить себе ситуацию, в которой первые 13 блоков были бы сильно фрагментированы, ведь UFS поддерживает фоновую дефрагментацию. Такое может произойти только при масштабной перегруппировке большого количества файлов, что в реальной жизни практически никогда не встречается. Поэтому будем считать, что 13-й блок файла найден. В массив непосредственной адресации он уже не помещается (там содержатся только 12 блоков), и ссылка на него, как и на все последующие блоки файла, должна содержаться в блоках косвенной адресации. Как вы помните, блоки косвенной адресации при удалении файла помечаются как свободные, но не затираются сразу же. Затирание происходит только по мере реальной необходимости, и это существенно упрощает нашу задачу.