
Данный архив позволяет собирать любое число файлов, директори и других объектов файловой системы (символических ссылок и т.д.) в единый поток байт.
Давайте на примерах рассмотрим формат этого архива.
Каждый объект файловой системы в таком архиве состоит из заголовка с базовыми метаданными, за которым следует полный путь к объекту и содержимое этого объекта. Заголовок содержит набор целочисленных значений, которые во многом повторяют поля структуры 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 бит определяют права доступа к объекту. |
c_uid,c_gid
Идентификаторы пользователя и группы владельца файла.
c_nlink
Количество ссылок на этот файл. Для каталогов значение этого поля всегда не меньше двух.
c_rdev
Только для специальных символьных и блочных устройств. Поле содержит
ассоциированный номер устройства. Для всех остальных типов файлов значение
данного поля должно быть нулевым.
c_mtime
Время последнего изменения файла. Формат соответствует количеству секунд,
прошедшего с начала эпохи UNIX. 32-битное целое записывается как массив двух
16-битных целых: сначала старшие разряды, потом младшие.
c_namesize
Длина строки полного пути к файлу включая терминальный NULL.
c_filesize
Размер файла.
Сразу за заголовком помещается полный путь к объекту. Если длина строки пути не кратна степени двойки, то в конец добавляется еще один 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. В будущем хотелось бы в аналогичной манере рассмотреть формат файла, создаваемого Gzip. В частности при помощи связки cpio+gzip создается ramfs, используемая ядром GNU/Linux.
Надеюсь статья будет полезна.
Ссылки по теме:
Описание утилиты CPIO
Описание формата CPIO