Восстановление информации своими руками

  35790931     

Последовательности обновления (update sequence)


Будучи очень важными компонентами файловой системы, $MFT, INDEX и $LogFile нуждаются в механизме контроля целостности своего содержимого. Традиционно для этого используется ECC/EDC-коды, однако, во времена проектирования NTFS процессоры были не настолько быстрыми как теперь и расчет корректирующих кодов занимал значительное время, существенно снижающее производительность файловой системы. Поэтому, от них пришлось отказаться. Вместо этого, разработчики NTFS применили так называемые последовательности обновления (update sequence), так же называемые fix-up'ами.

В конец каждого из секторов, слагающих файловую запись (INDEX Record, RCRD Record или RSTR Record) записывается специальный 16-байтовый номер последовательности обновления (update sequence number), дублируемый в заголовке файловой записи. При каждой операции чтения два последних байта сектора сверяется с соответствующим полем заголовка и, если NTFS-драйвер обнаруживает расхождение, данная файловая запись считается недействительной.

Основное назначение последовательностей обновления– защита от "обрыва записи". Если в процессе записи сектора на диск, исчезнет питающее напряжение, может случиться так, что половина файловой записи будет успешно записана, а половина – сохранит прежнее содержимое (файловая запись, как мы помним, обычно состоит из двух секторов). После восстановления питания, драйвер файловой системы не может уверенно сказать – была ли файловая запись записана целиком или нет. Вот тут-то последовательности обновления и выручают! При каждой перезаписи сектора update sequence увеличивается на единицу и потому если произошел обрыв записи, значение последовательности обновления, находящейся в заголовке файловой записи не будет совпадать с последовательностью обновления, расположенной в конце сектора.

Оригинальное содержимое, расположенное "под" последовательностью обновления, хранится в специальном массиве обновления (update sequence array), расположенном в заголовке файловой записи непосредственно за концом update sequence number. Для восстановления файловой записи в исходный вид, мы должны извлечь из заголовка указатель на update sequence number (он хранится по смещению 04h байт от начала заголовка), и сверить лежащее по этому адресу 16-байтное значение с последним словом каждого из секторов, слагающих файловую запись (INDEX Record, RCRD Record или RSTR Record). Если они не совпадут, значит соответствующая структура данных повреждена и использовать ее следует с очень большой осторожностью (а на первых порах лучше не использовать вообще).


По смещению 006h от начала сектора находится 16-разрядное поле, хранящее совокупный размер номера последовательности обновления вместе с массивном последовательности обновления (sizeof(update sequence number) + sizeif(update sequence array)), выраженный в словах (не в байтах!). Поскольку, размер номера последовательности обновления всегда равен одному слову, то размер массива последовательности обновления, выпаженный в байтах, равен: (update sequence number & update sequence array ? 1)*2. Соответственно, смещение массива оригинального содержимого равно: (offset to update sequence number) + 2. В NT и W2K update sequence number всегда располагается по смещению 2Ah от начала FILE Record Header/INDEX Header, а update sequence array – по смещению 2Сh. В XP же и более старших системах – по смещениям 2Dh и 2Fh соответственно.

Первое слово массива последовательности обновления соответствует последнему слову первого сектора FILE Record/INDEX. Второе – последнему слову второго сектора, и т. д. Для восстановления сектора в исходный вид, мы должны вернуть все элементы массива последовательности обновления на их законные места (естественно, модифицируется не сам сектор, а его копия в памяти).

Продемонстрируем это на следующем примере:

--> начало первого сектора FILE Record

00000000:  46 49 4C 45-2A 00 03 00-7C 77 1A 04-02 00 00 00  FILE* ¦ |w>¦O  

00000010:  01 00 02 00-30 00 01 00-28 02 00 00-00 04 00 00  O O 0 O (O   ¦ 

00000020:  00 00 00 00-00 00 00 00-06 00 06 00-00 00 47 11          ¦ ¦   G<



000001F0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 06 00                ¦

<-- конец первого сектора FILE Record



000003F0:  07 CC E1 0D-00 09 00 00-FF FF FF FF-82 79 06 00  •Iad 0  yyyyВy¦

<-- конец второго сектора FILE Record


Содержание раздела