Atrybut pliku zewnętrznego formatu zip

25

To nieco egzotyczne pytanie, ale wydaje się, że w sieci nie ma dużo informacji na ten temat. Właśnie dodałem odpowiedź na pytanie dotyczące zewnętrznego atrybutu pliku formatu zip . Jak widać z mojej odpowiedzi, dochodzę do wniosku, że tylko drugi bajt (z 4 bajtów) jest faktycznie używany dla Uniksa. Najwyraźniej zawiera to wystarczającą ilość informacji podczas rozpakowywania, aby wywnioskować, czy obiekt jest plikiem, czy katalogiem, a także ma miejsce na inne informacje o uprawnieniach i atrybutach. Moje pytanie brzmi: w jaki sposób mapuje się to na zwykłe uprawnienia Unix? Czy zwykłe uprawnienia uniksowe (np. Poniżej), które lspasują do dokładnie jednego bajtu, a jeśli tak, czy ktoś może opisać układ lub podać odniesienie, proszę?

$ 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

Pozwólcie, że uściślę to, zadając konkretne pytanie. Zgodnie z cytowaną w mojej odpowiedzi łatką Trac możesz utworzyć plik zip z fragmentem kodu Pythona poniżej.

040755 << 16LWartość odpowiada utworzenia pustego katalogu z uprawnieniami drwxr-xr-x. (Przetestowałem to). Wiem, że 0755odpowiada rwxr-xr-xwzorowi, ale co z tym 04i jak cała wartość odpowiada bajtowi? Zauważyłem również, że << 16Lodpowiada bitowe przesunięcie w lewo o 16 miejsc, co sprawiłoby, że skończyłoby to na drugim miejscu od górnego bajtu.

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()

EDYCJA: Po ponownym przeczytaniu tego, uważam, że mój wniosek, że uprawnienia Unix odpowiadają tylko jednemu bajtowi, może być niepoprawny, ale pozwolę powyższemu zastąpić teraźniejszość, ponieważ nie jestem pewien, jaka jest prawidłowa odpowiedź.

EDYCJA 2: Rzeczywiście, myliłem się co do wartości uniksowych odpowiadających tylko 1 bajtowi. Jak wyjaśniono w @ Random832, wykorzystuje on dwa górne dwa bajty. Na odpowiedź @ Random832 możemy skonstruować pożądaną 040755wartość z tabel, które podaje poniżej. Mianowicie:

__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 

Dodatek znajduje się tutaj w bazie 8 .

Faheem Mitha
źródło
Nic nie wiem o uprawnieniach zip, ale wiem, że tradycyjne uprawnienia unixowe używają 12 bitów, co stanowi więcej niż jeden bajt. Może zip nie przeszkadza w setxid i lepkim, ale to wciąż pozostawia 9 (rwx × ugo).
Gilles „SO- przestań być zły”

Odpowiedzi:

30

0040000to tradycyjna wartość S_IFDIRflagi typu pliku reprezentującej katalog. Typ wykorzystuje 4 górne bity 16-bitowej st_mode wartości, 0100000jest wartością dla zwykłych plików.

Wysokie 16 bitów atrybutów pliku zewnętrznego wydaje się być używanych do uprawnień specyficznych dla systemu operacyjnego. Wartości uniksowe są takie same jak w tradycyjnych implementacjach uniksowych. Inne systemy operacyjne używają innych wartości. Informacje na temat formatów używanych w różnych systemach operacyjnych można znaleźć w kodzie źródłowym Info-ZIP ( pobierz lub np. W debian apt-get source [zip or unzip]) - odpowiednie pliki są zipinfo.cw unzip, a pliki specyficzne dla platformy zip.

Są one konwencjonalnie zdefiniowane w liczbie ósemkowej (podstawa 8); jest to reprezentowane w C i python przez poprzedzenie liczby znakiem 0.

Wszystkie te wartości można znaleźć w <sys/stat.h>- link do wersji 4.4BSD . Nie ma ich w standardzie POSIX (który zamiast tego definiuje makra testowe); ale pochodzą z AT&T Unix i BSD. (w GNU libc / Linux same wartości są zdefiniowane jako __S_IFDIRetc in bits/stat.h, chociaż nagłówek jądra może być łatwiejszy do odczytania - wszystkie są wszędzie takie same).

#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 */

I oczywiście pozostałe 12 bitów dotyczy uprawnień i bitów setuid / setgid / sticky, tak samo jak dla 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 */

Z historycznych powodów powodem 0100000jest to, że zwykłe pliki zamiast 0 są takie, że w bardzo wczesnych wersjach Uniksa 0 było dla „małych” plików (nie korzystały one z bloków pośrednich w systemie plików), a wysoki bit flagi trybu był ustawione dla „dużych” plików, które używałyby bloków pośrednich. Pozostałe dwa typy używające tego bitu zostały dodane w późniejszych systemach uniksowych, po zmianie systemu plików.

Podsumowując, ogólny układ pola rozszerzonych atrybutów dla Uniksa jest następujący

TTTTsstrwxrwxrwx0000000000ADVSHR
^^^^____________________________ file type as explained above
    ^^^_________________________ setuid, setgid, sticky
       ^^^^^^^^^________________ permissions
                ^^^^^^^^________ This is the "lower-middle byte" your post mentions
                        ^^^^^^^^ DOS attribute bits
Losowo 832
źródło
@ Random832: Wow, to imponująco kompletne. Czy potrafisz także wyjaśnić, jak 040755 << 16Lskonstruowana jest wartość ? W szczególności, jakiej reprezentacji / bazy używa (myślę, że być może Octal ), a co najważniejsze, w jaki sposób język (w tym przypadku interpreter Pythona) wie, co to jest reprezentacja? Hmm, może ten typ jest zadeklarowany w kodzie C. Ponadto z jakiego pliku otrzymujesz wartości „typu pliku”? Pomocne byłoby dodanie niektórych linków / referencji.
Faheem Mitha
@ Random832: Widzę, że zipinfo.cjest to źródło do rozpakowania na Debianie . Alternatywnie można użyć wygodniejszego apt-get source unzip. Możesz dołączyć to do swojej odpowiedzi lub użyć niepublicznego źródła. Zazwyczaj cytuję Debiana, ponieważ wierzę, że będą na długo. :-)
Faheem Mitha,
@ Random832: Ok, myślę, że widzę, jak to działa. Po prostu dodajesz razem wszystkie wartości dla rzeczy, które są ustawione w podstawie 8 zgodnie z tabelą, i otrzymujesz liczbę 040755. Warto wspomnieć o imo dla ludzi, którzy nie wiedzą lub zapomnieli. Oczywiście, to wciąż pozostawia pytanie, skąd wie, że jest to podstawa 8, ale może ten typ jest zadeklarowany jako podstawa 8.
Faheem Mitha
Jest to podstawa 8, ponieważ zaczyna się od 0.
Wyjaśnię
@ Losowanie: Dzięki za wyjaśnienie. Nie byłem świadomy wiodącej konwencji 0. stat.hPlików w systemie Linux (jestem zakładając jest poprawny plik /usr/include/sys/stat.h) nie zawiera definicji tych stałych w tak jasny sposób, jak plik, który powiązany. Czy są ukryte gdzie indziej? Widzę, że użyłeś tego terminu test macros, ale nie jestem pewien, co to oznacza.
Faheem Mitha