Атрибут внешнего файла формата zip

25

Это немного экзотический вопрос, но в сети не так много информации об этом. Я только добавил ответ на вопрос об атрибуте внешнего файла в формате 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 # permissions drwxr-xr-x
    z.writestr(zfi, "")
    print z.namelist()
    z.close()

РЕДАКТИРОВАТЬ: Перечитывая это, я думаю, что мой вывод о том, что разрешения Unix соответствуют только одному байту, может быть неправильным, но я позволю вышеизложенному обозначать настоящее, поскольку я не уверен, каков правильный ответ.

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

__S_IFDIR + S_IRUSR + S_IWUSR + S_IXUSR + S_IRGRP + S_IXGRP + S_IROTH + S_IXOTH
0040000   + 0400    + 0200    + 0100    + 0040    + 0010    + 0004    + 0001
= 40755 

Дополнение здесь находится в базе 8 .

Фахим Митха
источник
Я ничего не знаю о разрешениях zip, но я знаю, что традиционные разрешения unix используют 12 битов, что составляет более одного байта. Возможно, zip не беспокоится о setxid и sticky, но это все равно оставляет 9 (rwx × ugo).
Жиль "ТАК - перестань быть злым"

Ответы:

30

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  /* named pipe (fifo) */
#define S_IFCHR  0020000  /* character special */
#define S_IFDIR  0040000  /* directory */
#define S_IFBLK  0060000  /* block special */
#define S_IFREG  0100000  /* regular */
#define S_IFLNK  0120000  /* symbolic link */
#define S_IFSOCK 0140000  /* socket */

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

#define S_ISUID 0004000 /* set user id on execution */
#define S_ISGID 0002000 /* set group id on execution */
#define S_ISTXT 0001000 /* sticky bit */
#define S_IRWXU 0000700 /* RWX mask for owner */
#define S_IRUSR 0000400 /* R for owner */
#define S_IWUSR 0000200 /* W for owner */
#define S_IXUSR 0000100 /* X for owner */
#define S_IRWXG 0000070 /* RWX mask for group */
#define S_IRGRP 0000040 /* R for group */
#define S_IWGRP 0000020 /* W for group */
#define S_IXGRP 0000010 /* X for group */
#define S_IRWXO 0000007 /* RWX mask for other */
#define S_IROTH 0000004 /* R for other */
#define S_IWOTH 0000002 /* W for other */
#define S_IXOTH 0000001 /* X for other */
#define S_ISVTX 0001000 /* save swapped text even after use */

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

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

TTTTsstrwxrwxrwx0000000000ADVSHR
^^^^____________________________ file type as explained above
    ^^^_________________________ setuid, setgid, sticky
       ^^^^^^^^^________________ permissions
                ^^^^^^^^________ This is the "lower-middle byte" your post mentions
                        ^^^^^^^^ DOS attribute bits
Random832
источник
@ Random832: Вау, это впечатляюще завершено. Можете ли вы также объяснить, как 040755 << 16Lстроится значение ? В частности, какое представление / основание оно использует (я думаю, что возможно Octal ), и, самое главное, как язык (в данном случае интерпретатор Python) знает, что такое представление? Хм, может быть, тип объявлен в коде C. Кроме того, из какого файла вы получаете значения типа файла? Добавление некоторых ссылок / ссылок было бы полезно.
Фахим Митха
@ Random832: Я вижу, что zipinfo.cэто источник Unzip в Debian . В качестве альтернативы можно использовать более удобный apt-get source unzip. Вы можете добавить это к своему ответу или использовать сторонний источник. Я обычно цитирую Debian, потому что я верю, что они будут здесь надолго. :-)
Фахим Митха
@ Random832: Хорошо, я думаю, что вижу, как это работает. Вы просто складываете все значения для вещей, которые установлены в базе 8 согласно вашей таблице, и вы получаете число 040755. Это стоило бы упомянуть imo для людей, которые не знают или забыли. Конечно, это все еще оставляет вопрос о том, как он знает, что это база 8, но, возможно, тип объявлен как база 8.
Фахим Митха
Это база 8, потому что она начинается с 0. Я
поясню,
@ Случайно: Спасибо за разъяснения. Я не знал о ведущей 0 конвенции. stat.hФайл на Linux (я предполагаю , что правильный файл является /usr/include/sys/stat.h) не содержит определения этих констант в такой ясной, как файл вы связаны. Они спрятаны где-то еще? Я вижу, вы использовали этот термин test macros, но я не уверен, что это значит.
Фахим Митха