Зовнішній атрибут файлу формату zip


25

Це злегка екзотичне питання, але в мережі, як здається, не так багато інформації. Я щойно додав відповідь на запитання про зовнішній атрибут файлу формату zip . Як видно з моєї відповіді, я роблю висновок, що для Unix насправді використовується лише другий байт (4 байти). Мабуть, це містить достатньо інформації при розпакуванні, щоб визначити, чи є об'єктом файл чи каталог, а також є місце для іншої інформації про дозвіл та атрибути. Моє запитання полягає в тому, як це відображається до звичайних дозволів Unix? Чи lsпідходять звичайні дозволи Unix (наприклад, нижче), що відповідає точно одному байту, і якщо так, чи може хтось описати макет чи дати посилання?

$ 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, процитованим у моїй відповіді вище, ви можете створити поштовий файл із фрагментом 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()

EDIT: Перечитуючи це, я вважаю, що мій висновок про те, що дозволи Unix відповідають лише одному байту, може бути невірним, але я дозволю вищевикладеному сказати, оскільки я не впевнений, що правильна відповідь.

EDIT2: Я дійсно помилявся щодо значень 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 біт, що більше одного байта. Можливо, поштовий індекс не турбує сетксиду та липкого, але це все одно залишає 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 шляхом префіксації числа a 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: Нічого, це вражаюче завершене. Чи можете ви також пояснити, як 040755 << 16Lбудується значення ? Зокрема, яке представництво / базу воно використовує (я думаю, можливо, Octal ), і головне, як мова (інтерпретатор Python в даному випадку) знає, що таке представництво? Хм, можливо, тип оголошено в коді С. Крім того, з якого файлу ви отримуєте значення "тип файлу"? Додавання деяких посилань / посилань було б корисно.
Faheem Mitha

@ Random832: Я бачу, що zipinfo.cце джерело для розпакування на Debian . Як варіант, можна скористатися і зручнішим apt-get source unzip. Ви можете додати це до своєї відповіді або використати джерело без потоку. Я зазвичай цитую Debian, тому що я вірю, що вони будуть довгий час. :-)
Faheem Mitha

@ Random832: Гаразд, я думаю, я бачу, як це працює. Ви просто додаєте всі значення для речей, які встановлені в базі 8 відповідно до вашої таблиці, і ви отримаєте число 040755. Це варто згадати іммо для людей, які не знають або забули. Звичайно, це все ще залишає питання про те, як він знає, що це база 8, але, можливо, тип оголошений як база 8.
Faheem Mitha

Це база 8, оскільки вона починається з 0. Я
уточню,

@ Випадково: Дякую за уточнення. Мені не було відомо про провідну конвенцію 0. stat.hФайл на Linux (я припускаю , що правильний файл є /usr/include/sys/stat.h) не містить визначення цих констант в такий ясною, як файл ви пов'язані. Вони сховані десь десь? Я бачу, що ви використовували цей термін test macros, але я не впевнений, що це означає.
Faheem Mitha
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.