XPost. CPIO под микроскопом.

Это кросспост моей статьи CPIO под микроскопом. Описание этого формата будет нам необходимо при рассмотрении вопроса создания RamFS. В статье приводятся примеры из HEX-редактора, так что удобнее, на мой взгляд, читать ее через браузер.

CPIO - это достаточно старый (1992 год), но в то же время очень удобный вариант архива. Он достаточно прост, и, возможно поэтому, получил широкое распространение. Например данный формат используют RPM, initramfs ядра Linux, а также установщик архивов "pax" от Apple.

Данный архив позволяет собирать любое число файлов, директори и других объектов файловой системы (символических ссылок и т.д.) в единый поток байт.


Давайте на примерах рассмотрим формат этого архива.

Каждый объект файловой системы в таком архиве состоит из заголовка с базовыми метаданными, за которым следует полный путь к объекту и содержимое этого объекта. Заголовок содержит набор целочисленных значений, которые во много повторяют поля структуры stat(2) файлов в *nix системах. Конец архива помечается специальной записью (аналогичной остальным) названием 'TRAILER!!!'.

Формат Файла

На данный момент самым распространенным является старый формат записей файла CPIO. Именно его описание и будет приведено.

Заголовок формата записи имеет следующую структуру:
struct header_old_cpio {
    unsigned short c_magic;
    unsigned short c_dev;
    unsigned short c_ino;
    unsigned short c_mode;
    unsigned short c_uid;
    unsigned short c_gid;
    unsigned short c_nlink;
    unsigned short c_rdev;
    unsigned short c_mtime[2];
    unsigned short c_namesize;
    unsigned short c_filesize[2];
};

Здесь предполагается, что тип unsigned short имеет размер 16 бит.

c_magic
    Целочисленное значение, равное 070707 (в восьмеричной СС), или 0x71c7 (в шестнадцатеричной СС). Используется для определения порядка байт (little-endian vs big-endian).

c_dev,c_ino
    Номера устройства и инода (inode) с диска. Соответствуют значениям, выдаваемым утилитой stat. Если значение inode больше 65535, то старшие разряды будут утеряны.

c_mode
    Поле одновременно определяет права доступа и тип объекта:
    0170000        Маскирует биты типа файла
    0140000        Сокет
    0120000        Символическая ссылка. Для символических ссылок, тело ссылки будет содержать путь к файлу, на который та ссылается.
    0100000        Обычный файл
    0060000        Специальное блочное устройство
    0040000        Каталог
    0020000        Специальное символьное устройство
    0010000        Именованный канал(named pipe) или очередь(FIFO).
    0004000        SUID
    0002000        SGID
    0001000        Sticky bit.
    0000777        Младшие 9 бит определяют права доступа к объекту. Соответствует значению, выдаваемому утилитой stat.

c_uid,c_gid
    Идентификаторы пользователя и группы владельца файла.

c_nlink
    Количество ссылок на этот файл. Для каталогов значение этого поля всегда не меньше 2.

c_rdev
    Только для специальных символьных и блочных устройств. Поле содержит ассоциированный номер устройства. Для всех остальных типов файлов значение данного поля должно быть нулевым.

c_mtime
    Время последнего изменения файла. Формат соответствует количеству секунд, прошедшего с начала эпохи UNIX. 32-битное целое записывается как массив двух 16-битных целых: сначала старшие разряды, потом младшие.

c_namesize
    Длина строки полного пути к файлу включая терминальный NULL.

c_filesize
    Размер файла.

Сразу за заголовком помещается полный путь к объекту. Если длина строки пути не выравнена по границе слова (2 байта), то в конец добавляется еще один NULL. Затем помещается содержимое файла. Если размер содержимого файла также оказывается на выравнен по границе слова, то добавляется NULL.

Примеры различных архивов.

Теперь давайте возьмем микроскоп. Я в качестве микроскопа возьму Bless. Не скажу, что мне этот hex-редактор очень нравится, но название того, который мне нравится я забыл.

Создадим простой каталог:
cpio_test
 |
 + test.txt
 |
 + testl.txt

Здесь testl.txt - это символическая ссылка на файл test.txt.
Содержимое файла test.txt:
Simple example of cpio usage.

Затем создадим архив:
$ find cpio_test | cpio -ov > example.cpio

и откроем получившийся архив в любимом hex-редакторе.

У меня этот архив выглядит так:
0000 | C7 71 09 08 9A 34 FD 41 F4 01 F4 01 02 00 00 00 | .q...4.A........
0010 | 8C 4E 09 31 0A 00 00 00 00 00 63 70 69 6F 5F 74 | .N.1......cpio_t
0020 | 65 73 74 00 C7 71 09 08 A2 34 B4 81 F4 01 F4 01 | est..q...4......
0030 | 01 00 00 00 8C 4E 09 31 13 00 00 00 1E 00 63 70 | .....N.1......cp
0040 | 69 6F 5F 74 65 73 74 2F 74 65 73 74 2E 74 78 74 | io_test/test.txt
0050 | 00 00 53 69 6D 70 6C 65 20 65 78 61 6D 70 6C 65 | ..Simple example
0060 | 20 6F 66 20 63 70 69 6F 20 75 73 61 67 65 2E 0A |  of cpio usage..
0070 | C7 71 09 08 9C 34 FF A1 F4 01 F4 01 01 00 00 00 | .q...4..........
0080 | 8C 4E 1A 2F 14 00 00 00 08 00 63 70 69 6F 5F 74 | .N./......cpio_t
0090 | 65 73 74 2F 74 65 73 74 6C 2E 74 78 74 00 74 65 | est/testl.txt.te
00A0 | 73 74 2E 74 78 74 C7 71 00 00 00 00 00 00 00 00 | st.txt.q........
00B0 | 00 00 01 00 00 00 00 00 00 00 0B 00 00 00 00 00 | ................
00C0 | 54 52 41 49 4C 45 52 21 21 21 00 00 00 00 00 00 | TRAILER!!!......

Ну что ж, давайте разбираться.

0x71c7 = 070707 - начало заголовка. И мы уже можем сказать, что порядок байт при создании архива - little-endian.
0x0809 - это c_dev - номер устройства на котором находится файл.
0x349a - это c_ino - inode. В данном случае как раз старшие разряды были утеряны.
0x41fd = 0040775 - c_mode. То есть заголовок описывает каталог с правами доступа 0775.
0x01f4 = 500 - c_uid.
0x01f4 = 500 - c_gid.
0x0002 - c_nlink. На каждый каталог существует как минимум две ссылки (. и ..)
0x0000 - c_rdev.
0x4e8c и 0x3109 - это старший и младший разряды 32-битного значения времени модификации файла. 0x31094e8c = 1317810441.
0x000a - длина имени каталога.
0x00000000 - у каталога нет тела.
Далее идет название каталога.

Затем сразу следует заголовок следующей записи. Не будем подробно на ней останавливаться - только заметим некоторые отличия:
c_mode: 0x34a2 = 0100664 - показывает. что это обычный файл с правами доступа 664.
0x0000001e - размер содержимого файла.
В остальном запись похожа не описание каталога.

Далее идет запись символической ссылки. Содержимое символической ссылки - название файла, на который она указывает.

Ссылки по теме:
Описание утилиты CPIO
Описание формата CPIO

Комментариев нет:

Отправить комментарий