Внешний атрибут файла формата zip

Вопрос или проблема

Это слегка экзотичный вопрос, но в сети, похоже, не так много информации на эту тему. Я только что добавил ответ на вопрос о внешнем атрибуте файла формата zip. Как видно из моего ответа, я пришел к выводу, что только второй байт (из 4 байтов) на самом деле используется для Unix. Похоже, что этого достаточно, когда распаковываешь файл, чтобы определить, является ли объект файлом или директорией, и также есть место для другой информации о разрешениях и атрибутах. Мой вопрос в том, как это соотносится с обычными Unix-разрешениями? Указывают ли обычные Unix-разрешения (например, ниже), которые выводит ls, ровно на один байт, и если да, может кто-нибудь описать структуру или дать ссылку, пожалуйста?

$ ls -la
total 36
drwxr-xr-x   3 faheem faheem  4096 Jun 10 01:11 .
drwxrwxrwt 136 root   root   28672 Jun 10 01:07 ..
-rw-r--r--   1 faheem faheem     0 Jun 10 01:07 a
drwxr-xr-x   2 faheem faheem  4096 Jun 10 01:07 b
lrwxrwxrwx   1 faheem faheem     1 Jun 10 01:11 c -> b

Позвольте мне сделать это более конкретным, задав конкретный вопрос. В соответствии с патчем Trac, который я привел в своем ответе выше, вы можете создать zip-файл с помощью следующего фрагмента Python.

Значение 040755 << 16L соответствует созданию пустой директории с разрешениями drwxr-xr-x. (Я это проверил). Я понимаю, что 0755 соответствует шаблону rwxr-xr-x, но что насчет 04, и как все значение соотносится с байтом? Я также понимаю, что << 16L соответствует побитовому сдвигу влево на 16 позиций, который делает его вторым байтом сверху.

def makezip1():
    import zipfile
    z = zipfile.ZipFile("foo.zip", mode="w")
    zfi = zipfile.ZipInfo("foo/empty/")
    zfi.external_attr = 040755 << 16L # разрешения drwxr-xr-x
    z.writestr(zfi, "")
    print z.namelist()
    z.close()

ИЗМЕНЕНИЕ: Перечитав это, я думаю, что мой вывод о том, что разрешения Unix соответствуют только одному байту, может быть неправильным, но я оставлю вышеуказанное на данный момент, так как не уверен, каков правильный ответ.

ИЗМЕНЕНИЕ2: Я действительно ошибался относительно значений Unix, которые соответствуют только 1 байту. Как объяснил @Random832, используются оба верхних байта. Согласно ответу @Random832, мы можем конструировать нужное значение 040755 из таблиц, которые он приводит ниже. А именно:

   0040000 # __S_IFDIR

+     0400 #   S_IRUSR
+     0200 #   S_IWUSR
+     0100 #   S_IXUSR

+     0040 #   S_IRGRP
           #   S_IWGRP пропущен
+     0010 #   S_IXGRP

+     0004 #   S_IROTH
           #   S_IWOTH пропущен
+     0001 #   S_IXOTH

==   40755

Сложение здесь в восьмеричной системе.

0040000 — это традиционное значение S_IFDIR, флага типа файла, представляющего директорию. Тип использует верхние 4 бита из 16-битного значения st_mode, 0100000 — это значение для обычных файлов.

Высокие 16 бит внешних атрибутов файлов, похоже, используются для специфичных для ОС разрешений. Значения Unix такие же, как и на традиционных реализациях Unix. Другие ОС используют другие значения. Информацию о форматах, используемых в различных ОС, можно найти в исходном коде Info-ZIP (скачать или, например, в Debian apt-get source [zip or unzip]) — соответствующие файлы это zipinfo.c в unzip, и платформозависимые файлы в zip.

Эти значения обычно определяются в восьмеричной (основание 8); это представлено в C и python путем добавления к числу префикса 0.

Эти значения можно найти в <sys/stat.h>ссылка на версию 4.4BSD. Эти значения не входят в стандарт POSIX (который вместо этого определяет тестовые макросы); но происходят из AT&T Unix и BSD. (в GNU libc / Linux сами значения определяются как __S_IFDIR и т.д. в bits/stat.h, хотя заголовок ядра может быть легче читать – значения везде абсолютно одинаковы.)

#define S_IFIFO  0010000  /* именованный канал (fifo) */
#define S_IFCHR  0020000  /* символьный специальный */
#define S_IFDIR  0040000  /* директория */
#define S_IFBLK  0060000  /* блочный специальный */
#define S_IFREG  0100000  /* обычный */
#define S_IFLNK  0120000  /* символическая ссылка */
#define S_IFSOCK 0140000  /* сокет */

И, конечно, остальные 12 бит для разрешений и битов setuid/setgid/стикер, такие же как для chmod:

#define S_ISUID 0004000 /* устанавливает идентификатор пользователя при выполнении */
#define S_ISGID 0002000 /* устанавливает идентификатор группы при выполнении */
#define S_ISTXT 0001000 /* бит стиля */
#define S_IRWXU 0000700 /* маска RWX для владельца */
#define S_IRUSR 0000400 /* R для владельца */
#define S_IWUSR 0000200 /* W для владельца */
#define S_IXUSR 0000100 /* X для владельца */
#define S_IRWXG 0000070 /* маска RWX для группы */
#define S_IRGRP 0000040 /* R для группы */
#define S_IWGRP 0000020 /* W для группы */
#define S_IXGRP 0000010 /* X для группы */
#define S_IRWXO 0000007 /* маска RWX для остальных */
#define S_IROTH 0000004 /* R для остальных */
#define S_IWOTH 0000002 /* W для остальных */
#define S_IXOTH 0000001 /* X для остальных */
#define S_ISVTX 0001000 /* сохранить измененный текст даже после использования */

Как историческая заметка, причина, по которой 0100000 соответствует обычным файлам, а не 0, заключается в том, что в очень ранних версиях Unix 0 использовалось для «маленьких» файлов (которые не использовали косвенные блоки в файловой системе), и верхний бит флага режима устанавливался для «больших» файлов, которые использовали бы косвенные блоки. Другие два типа, использующие этот бит, были добавлены в более поздние производные ОС Unix, после изменения файловой системы.

Таким образом, подводя итог, общая структура поля расширенных атрибутов для Unix выглядит так:

TTTTsstrwxrwxrwx0000000000ADVSHR
^^^^____________________________ тип файла, как объяснено выше
    ^^^_________________________ setuid, setgid, стирка
       ^^^^^^^^^________________ разрешения
                ^^^^^^^^________ Это "нижний средний байт", который упоминается в вашем сообщении
                        ^^^^^^^^ биты атрибута DOS

Ответ или решение

Внешный атрибут файла в формате ZIP: Подробный анализ

Формат ZIP стал стандартом в сфере архивирования данных благодаря своей способности эффективно сжимать и организовывать файлы. Одной из ключевых особенностей этого формата является наличие внешнего атрибута файла, который предоставляет информацию о свойствах файлов и каталогов. В этом ответе нас интересует, как внешний атрибут ZIP-файлов соотносится с привычными правами доступа Unix и как они представлены в двоичном формате.

Что такое внешний атрибут файла в формате ZIP?

Внешний атрибут файла в ZIP представляет собой 32-битное целое число, где старшие 16 бит используются для определения операционной системы и её специфических атрибутов, а младшие 16 бит — для определения Unix-пермишин. Эти значения позволяют извлекать категории (файлы, каталоги) и их разрешения при распаковке zip-архивов.

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

Соотношение внешнего атрибута и прав доступа Unix

В Unix права доступа задаются в виде трех групп разрешений: для владельца файла, для группы и для остальных пользователей. Каждая из этих групп имеет три разрешения: чтение (r), запись (w) и выполнение (x). В восьмеричной системе это представляется как три бита на каждое разрешение, что приводит к следующему формату:

  • 4 (r) — разрешение на чтение
  • 2 (w) — разрешение на запись
  • 1 (x) — разрешение на выполнение

Таким образом, для прав доступа rwxr-xr-x вы получаете следующее представление в восьмеричном формате:

  • Владельцы: rwx = 4 + 2 + 1 = 7
  • Группа: r-x = 4 + 0 + 1 = 5
  • Остальные: r-x = 4 + 0 + 1 = 5

Объединяя это, вы получаете 0755 в восьмеричном представлении.

Разделение битов в внешнем атрибуте

Внешний атрибут файла задаётся следующим образом:

TTTTsstrwxrwxrwx0000000000ADVSHR

Где:

  • TTTT — тип файла (например, 0x4000 для каталога).
  • s — установка битов setuid и setgid.
  • trwxrwxrwx — права доступа (чтение, запись, выполнение для владельца, группы и остальных).
  • Остальные биты могут использоваться для специфических атрибутов (например, sticky bit).

Общий вид представлен следующим образом:

  1. Данные о типе файла: 4 верхних бита
  2. Биты прав доступа: 12 следующих битов
  3. Специфические атрибуты: оставшиеся 16 бит.

Как Python помогает в создании ZIP-файлов

Для создания ZIP-файла с правильными правами можно воспользоваться библиотекой zipfile в Python. Как указано в вашем примере кода:

zfi.external_attr = 040755 << 16L

Это указывает, что мы хотим установить права доступа для каталога drwxr-xr-x, где 040755 соответствует правам, а << 16L означает, что эти права должны занимать 16 старших битов.

Программное представление статуса файла

Используя подход, изложенный выше, восстановление прав доступа для вывода ls в Unix происходит следующим образом:

Для drwxr-xr-x:

  • 0040000 (директория) + 00755 (права доступа) = 040755

Таким образом, создается впередсмотрящий и протестированный ZIP-файлы с точно заданными атрибутами и правами доступа.

Заключение

Внешний атрибут файла в формате ZIP играет важную роль в управлении правами доступа и отображении информации о файлах и каталогах. Применение стандартных Unix-пермишин в сочетании с форматом ZIP дает разработчикам мощный инструмент для работы с файлами. Понимание структуры и атрибутов, зафиксированных в ZIP, является основополагающим для работы с архивами на уровне системы и значительно расширяет возможности взаимодействия с файлами в разных операционных системах.

Оцените материал
Добавить комментарий

Капча загружается...