Адресация данных
Еще раз обратим внимание на временные отметки файла в листинге 12. Время удаления файла, датируемое 1970 годом, - не временной парадокс, а единая точка отсчета всех 4 временных отметок. Если она не указывает реальное время, значит факт удаления файла еще не состоялся.
Система адресации данных - это одна из самых существенных составных частей файловой системы. Всего в inode для целей адресации зарезервировано 15 полей по 4 байта. Номера первых 12 блоков хранятся непосредственно в inode; их еще иногда называют блоками с прямой адресацией (direct blocks). При размере логического блока 4 Кб таким образом можно создавать файлы размером до 4x12 = 48 Кб.
При большем объеме файла используется нелинейная система адресации данных. Очередное поле содержит адрес (номер) блока, в котором хранятся номера еще 256 блоков данных. Его называют блоком косвенной адресации (indirect block).
Если файл все же не помещается в пространство 256*4 + 48 = 1072 Кб, очередное поле inode указывает номер блока, в котором хранятся 256 номеров блоков косвенной адресации. Этот блок называют блоком двойной косвенной адресации (double indirect block). Наконец, если и этого пространства для размещения файла недостаточно, последнее поле адресует номер блока, в котором хранятся 256 номеров блоков двойной косвенной адресации. Его называют блоком тройной косвенной адресации (triply indirect block).
При логическом удалении файла и последующем использовании освободившихся блоков проще всего найти блоки прямой адресации (разумеется, если индексный дескриптор к этому времени не пострадал). Но если будет повторно использован один из блоков косвенной адресации, то все номера блоков, на которые он указывал, будут потеряны. Варианты восстановления данных в логически удаленных или поврежденных файлах будут рассмотрены ниже.
В листинге 13 приведены inode и фрагмент блока данных файла - сценария. Для этого файла был установлен дополнительный бит SUID, а также дополнительные атрибуты, предписывающие блокирование любых изменений файла, его автоматическое сжатие и декомпрессию при записи/чтении, а также гарантированное стирание блоков данных при удалении файла. Установка дополнительных атрибутов производилась командой:
chattr +ics file_name
Однако в распечатке inode дополнительные атрибуты не отображаются. Их можно увидеть лишь в соответствующих полях в таблице индексных дескрипторов. В этом нет ничего странного: операционные системы непрерывно развиваются и дополнительные атрибуты файлов появились несколько позже утилит, отображающих информацию о файлах.
INODE: 527744 (0x00080D80)
-rwsr-xr-x 0 |
0 |
69 |
Sat |
: Apr |
TYPE: |
regular |
file |
LINKS: |
1 |
|||||
MODEFLAGS.MODE: |
010.4755 |
|||||
SIZE: |
69 |
|||||
BLOCK COUNT: |
8 |
|||||
UID: |
00000 |
|||||
GID: |
00000 |
|||||
ACCESS TIME: |
Sat Apr |
3 |
13 |
:19 |
:39 |
2004 |
CREATION TIME: |
Sat Apr |
3 |
13 |
:23 |
:24 |
2004 |
MODIFICATION TIME: |
Sat Apr |
3 |
13 |
:19 |
:39 |
2004 |
DELETION TIME: |
Thu Jan |
1 |
05 |
:00 |
:00 |
1970 |
DIRECT BLOCKS: |
0x001024F9 |
3 13:19:39 2004
INDIRECT BLOCK: DOUBLE INDIRECT BLOCK: TRIPLE INDIRECT BLOCK:
Листинг 13. Информация о файле-сценарии
Блок данных файла-сценария
0x024F9000 |
64 |
64 |
20 |
69 |
66 |
3D |
2F |
64 |
0x024F9010 |
66 |
3D |
2F |
68 |
6F |
6D |
65 |
2F |
0x024F9020 |
20 |
73 |
6B |
69 |
70 |
3D |
32 |
30 |
0x024F9030 |
30 |
30 |
20 |
63 |
6F |
6E |
76 |
3D |
0x024F9040 |
73 |
79 |
6E |
63 |
0A |
00 |
00 |
00 |
0x024F9050 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
0x024F9060 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
0x024F9070 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
0x024F9080 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
Листинг 14. |
Бл< |
-
76 2F 66 64 30 20 6F dd if=/dev/fd0 о
-
6C 6F 70 70 79 5F 61 f=/home/floppy_a 20 63 6F 75 6E 74 3D 31 skip=20 count=l 6E 6F 65 72 72 6F 72 2C 00 conv=noerror,
00 00 00 00 00 00 00 00 sync
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
Осталось рассмотреть, где и как размещается третий компонент файла -его символьное имя. У каждого inode может быть 65536 «жестких» ссылок, т.е. символьных имен. Ассоциативные связи между именами файлов и их индексными дескрипторами устанавливаются с помощью записей в каталогах, которые представляют собой разновидность текстовых файлов. Рассмотрим, как выглядит листинг одного из каталогов. В листинге 15 представлен фрагмент распечатки расширенных сведений о файлах, находящихся в каталоге /bin.
131329 |
drwxr-xr-x |
2 |
root |
root |
4096 Map |
18 |
17:42 |
. |
2 |
drwxr-xr-x |
19 |
root |
root |
4096 Anp |
6 |
12:53 |
. . |
131559 |
-rwxr-xr-x |
1 |
root |
root |
4594 Anp |
25 |
2003 |
arch |
131542 |
lrwxrwxrwx |
1 |
root |
root |
4 Map |
18 |
17:29 |
awk -> gawk |
131509 |
-rwxr-xr-x |
1 |
root |
root |
15643 Май |
4 |
2003 |
basename |
131333 |
-rwxr-xr-x |
1 |
root |
root |
626028 Anp |
26 |
2003 |
bash |
131510 |
-rwxr-xr-x |
1 |
root |
root |
19812 Май |
4 |
2003 |
cat |
131334 |
lrwxrwxrwx |
1 |
root |
root |
131512 |
-rwxr-xr-x |
1 |
root |
root |
131513 |
-rwxr-xr-x |
1 |
root |
root |
131514 |
-rwxr-xr-x |
1 |
root |
root |
131957 |
-rwxr-xr-x |
1 |
root |
root |
131515 |
-rwxr-xr-x |
1 |
root |
root |
131516 |
-rwxr-xr-x |
1 |
root |
root |
131517 |
-rwxr-xr-x |
1 |
root |
root |
131518 |
-rwxr-xr-x |
1 |
root |
root |
131560 |
-rwxr-xr-x |
1 |
root |
root |
131552 |
lrwxrwxrwx |
1 |
root |
root |
4 Map 18 17:29 sh -> bash
23999 |
Май |
4 |
2003 |
chmod |
26124 |
Май |
4 |
2003 |
chown |
57792 |
Май |
4 |
2003 |
ср |
63871 |
Апр |
29 |
2003 |
cpio |
26305 |
Май |
4 |
2003 |
cut |
45838 |
Май |
4 |
2003 |
date |
35496 |
Май |
4 |
2003 |
dd |
38648 |
Май |
4 |
2003 |
df |
6537 |
Апр |
25 |
2003 |
dmesg |
8 Map 18 17:30 dnsdomainname ->
Листинг 15. Фрагмент каталога /bin, отображенный командой Is -ali /bin
В первой строке приведена запись о самом каталоге /bin (он обозначен точкой). Двумя точками обозначается родительский, в данном случае корневой каталог. Расширенная информация содержит индексные дескрипторы, тип файлов и права доступа к ним, количество жестких ссылок (имен) файлов, владельца и его группу, размер файла, дату и время его создания и, наконец, само имя файла. Каталог по сути представляет собой таблицу, каждая строка которой имеет переменную длину и состоит из 5 полей. >- Индексный дескриптор файла длиной 4 байта.
> Длина записи 2 байта.
>- Длина имени файла 1 байт.
>- Тип файла 1 байт. В отличие от соответствующего байта в индексном дескрипторе обычный файл здесь обозначается цифрой 1, каталог -2, символическая ссылка-7.
> Имя файла в ASCII-кодировке. Имя файла имеет переменную длину, допол
ненную нулями до 4 - байтной границы.
0x40203000 |
01 |
01 |
02 |
00 |
ОС |
00 |
01 |
02 : |
: 2Е |
00 |
00 |
00 |
02 |
00 |
0x40203010 |
ОС |
00 |
02 |
02 |
2Е |
2Е |
00 |
00 : |
: 06 |
01 |
02 |
00 |
ОС |
00 |
0x40203020 |
73 |
68 |
00 |
00 |
05 |
01 |
02 |
00 : |
: ОС |
00 |
04 |
01 |
62 |
61 |
0x40203030 |
В5 |
01 |
02 |
00 |
18 |
00 |
08 |
01 : |
: 62 |
61 |
73 |
65 |
6Е |
61 |
0x40203040 |
39 |
39 |
35 |
66 |
34 |
34 |
34 |
00 : |
: 04 |
01 |
02 |
00 |
10 |
00 |
0x40203050 |
6D |
6В |
74 |
65 |
6D |
70 |
00 |
00 : |
: 03 |
01 |
02 |
00 |
10 |
00 |
0x40203060 |
62 |
61 |
73 |
68 |
32 |
00 |
00 |
00 : |
: В2 |
01 |
02 |
00 |
10 |
00 |
0x40203070 |
65 |
67 |
72 |
65 |
70 |
00 |
00 |
00 : |
: ВЗ |
01 |
02 |
00 |
10 |
00 |
0x40203080 |
66 |
67 |
72 |
65 |
70 |
00 |
00 |
00 : |
: В4 |
01 |
02 |
00 |
ОС |
00 |
0x40203090 |
67 |
72 |
65 |
70 |
В7 |
01 |
02 |
00 : |
: 14 |
00 |
05 |
01 |
63 |
68 |
0х402030А0 |
70 |
30 |
35 |
39 |
39 |
35 |
66 |
34 : |
: В6 |
01 |
02 |
00 |
ОС |
00 |
0х402030В0 |
63 |
61 |
74 |
00 |
Е0 |
01 |
02 |
00 : |
: 18 |
00 |
0D |
07 |
64 |
6Е |
0х402030С0 |
6F |
6D |
61 |
69 |
6Е |
6Е |
61 |
6D : |
: 65 |
66 |
34 |
00 |
В8 |
01 |
0x402030D0 |
10 |
00 |
05 |
01 |
63 |
68 |
6D |
6F : |
: 64 |
00 |
00 |
00 |
В9 |
01 |
0х402030Е0 |
10 |
00 |
05 |
01 |
63 |
68 |
6F |
77 : |
: 6Е |
00 |
00 |
00 |
ВА |
01 |
0x402030F0 |
ОС |
00 |
02 |
01 |
63 |
70 |
00 |
00 : |
: ВВ |
01 |
02 |
00 |
ОС |
00 |
00 00
02 07
73 68 sh bash
6D 65 basename
06 01 995f444
05 07 mktemp
05 01 bash2
05 01 egrep
04 01 fgrep
67 72 grep chgr
03 01 p05995f4
73 64 cat dnsd
02 00 omainnamef4
02 00 ....chmod
-
00 ....chown
-
01 cp
Листинг 16. Дамп блока данных, содержащего каталог /bin
В листинге 16 представлен фрагмент блока данных каталога /bin. Проанализируем информацию, содержащуюся в нескольких начальных записях.
Первые 4 байта записи 1 дают число 00 02 01 Olh = 131329, что совпадает с номером inode каталога /bin. Следующие два байта 00 OCh =12 определяют длину записи в байтах. Третье поле содержит байт Olh = 1, указывая на то, что имя каталога состоит из одного символа. Действительно, имя каталога обозначено одним символом - точкой. Четвертое поле - 02h = 2, указывает на то, что это - каталог. Точке, которой обозначено имя файла, соответствует байт 2Е. Оставшиеся три байта являются нулями и представляют собой дополнение до 4-байтной границы.
Запись 2 начинается 4-байтным числом 00 00 00 02h = 2, что является номером индексного дескриптора родительского (корневого) каталога. Длина этой записи также равна 00 OCh =12 байт. Третье поле - байт 02h - дает нам длину имени каталога (имя родительского каталога - две точки). Четвертое поле 02h -тип файла (каталог). Имя файла - две точки - соответствует двум байтам 2Е 2Eh. Еще два байта заполнения 00 00h завершают эту запись.
Индексный дескриптор файла в третьей записи 00 02 01 06h = 131334, что соответствует inode символической ссылки sh на командный интерпретатор bash (11 строка сверху в листинге 15). Имя этого файла тоже короткое, и длина записи по-прежнему составляет 12 байт. Третье поле - байт 02h определяет длину имени файла. Тип файла (четвертое поле) равен 07h, что соответствует символической ссылке. Наконец, байты 68 73h последнего поля соответствуют символам имени файла - sh. Приведенных примеров вполне достаточно, чтобы произвести разбор любой записи - хоть с ее начала, хоть с конца.
Как уже указывалось, большинство каталогов помещаются в один логический блок. Однако, если этого не хватает, система выделяет каталогу столько блоков, сколько необходимо. Отдельная запись в каталоге не может пересекать границу блока (то есть должна быть расположена целиком внутри одного блока). Поэтому, если очередная запись не помещается целиком в данном блоке, она переносится в следующий блок, а предыдущая запись продолжается нулями, чтобы они заполнили блок до конца.