Das externe Dateiattribut des Zip-Formats

25

Dies ist eine etwas exotische Frage, aber es scheint nicht viele Informationen im Internet zu geben. Ich habe gerade eine Antwort auf eine Frage zum externen Dateiattribut des Zip-Formats hinzugefügt . Wie Sie meiner Antwort entnehmen können, komme ich zu dem Schluss, dass nur das zweite Byte (von 4 Bytes) tatsächlich für Unix verwendet wird. Anscheinend enthält diese Datei beim Entpacken genügend Informationen, um zu ermitteln, ob es sich bei dem Objekt um eine Datei oder ein Verzeichnis handelt. Außerdem ist Platz für andere Berechtigungs- und Attributinformationen vorhanden. Meine Frage ist, wie ordnet sich diese den üblichen Unix-Berechtigungen zu? lsPassen die üblichen Unix-Berechtigungen (z. B. unten) in genau ein Byte, und wenn ja, kann jemand das Layout beschreiben oder eine Referenz angeben?

$ 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

Lassen Sie mich dies konkretisieren, indem ich eine bestimmte Frage stelle. Gemäß dem oben in meiner Antwort angegebenen Trac-Patch können Sie eine Zip-Datei mit dem folgenden Python-Snippet erstellen.

Der 040755 << 16LWert entspricht der Erstellung eines leeren Verzeichnisses mit den Berechtigungen drwxr-xr-x. (Ich habe es getestet). Ich erkenne, 0755entspricht dem rwxr-xr-xMuster, aber was ist mit dem 04, und wie entspricht der gesamte Wert einem Byte? Ich erkenne auch << 16L, dass dies einer bitweisen Linksverschiebung von 16 Stellen entspricht, was dazu führen würde, dass es das zweite Byte von oben ist.

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

BEARBEITEN: Beim erneuten Lesen denke ich, dass meine Schlussfolgerung, dass die Unix-Berechtigungen nur einem Byte entsprechen, falsch sein könnte, aber ich werde das Obige vorläufig stehen lassen, da ich nicht sicher bin, wie die richtige Antwort lautet.

EDIT2: Ich war in der Tat falsch über die Unix-Werte, die nur 1 Byte entsprechen. Wie @ Random832 erklärt hat, werden beide oberen zwei Bytes verwendet. Gemäß der Antwort von @ Random832 können wir den gewünschten 040755Wert aus den unten angegebenen Tabellen konstruieren . Nämlich:

__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 

Der Zusatz hier ist in der Basis 8 .

Faheem Mitha
quelle
Ich weiß nichts über Zip-Berechtigungen, aber ich weiß, dass herkömmliche Unix-Berechtigungen 12 Bit verwenden, was mehr als ein Byte entspricht. Vielleicht stört zip nicht mit setxid und sticky, aber das lässt immer noch 9 (rwx × ugo).
Gilles 'SO- hör auf böse zu sein'

Antworten:

30

0040000ist der traditionelle Wert von S_IFDIR, dem Dateityp-Flag, das ein Verzeichnis darstellt. Der Typ verwendet die oberen 4 Bits des 16-Bit- st_mode Werts und 0100000ist der Wert für reguläre Dateien.

Die hohen 16 Bit der externen Dateiattribute scheinen für betriebssystemspezifische Berechtigungen verwendet zu werden. Die Unix-Werte sind dieselben wie bei herkömmlichen Unix-Implementierungen. Andere Betriebssysteme verwenden andere Werte. Informationen zu den in verschiedenen Betriebssystemen verwendeten Formaten finden Sie im Info-ZIP-Quellcode ( Download oder zB in Debian apt-get source [zip or unzip]) - relevante Dateien sind zipinfo.cin unzipund die plattformspezifischen Dateien in zip.

Diese sind üblicherweise in Oktal (Basis 8) definiert; Dies wird in C und Python dargestellt, indem der Zahl ein vorangestellt wird 0.

Diese Werte sind alle in <sys/stat.h>- link zur Version 4.4BSD zu finden . Diese sind nicht im POSIX-Standard enthalten (der stattdessen Testmakros definiert). stammen aber von AT & T Unix und BSD. (In GNU libc / Linux sind die Werte selbst als __S_IFDIRetc in definiertbits/stat.h , obwohl der Kernel-Header möglicherweise einfacher zu lesen ist - die Werte sind fast überall gleich.)

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

Und natürlich sind die anderen 12 Bits für die Berechtigungen und setuid / setgid / sticky-Bits gleich wie für 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 */

Historisch gesehen liegt der Grund 0100000für reguläre Dateien anstelle von 0 darin, dass in sehr frühen Versionen von Unix 0 für 'kleine' Dateien (diese verwendeten keine indirekten Blöcke im Dateisystem) und das hohe Bit des Modus-Flags war Für 'große' Dateien festlegen, die indirekte Blöcke verwenden würden. Die beiden anderen Typen, die dieses Bit verwenden, wurden in späteren von Unix abgeleiteten Betriebssystemen hinzugefügt, nachdem sich das Dateisystem geändert hatte.

Zusammenfassend lässt sich sagen, dass das erweiterte Attributfeld für Unix insgesamt wie folgt aufgebaut ist

TTTTsstrwxrwxrwx0000000000ADVSHR
^^^^____________________________ file type as explained above
    ^^^_________________________ setuid, setgid, sticky
       ^^^^^^^^^________________ permissions
                ^^^^^^^^________ This is the "lower-middle byte" your post mentions
                        ^^^^^^^^ DOS attribute bits
Random832
quelle
@ Random832: Wow, das ist beeindruckend komplett und durch. Können Sie auch erklären, wie der Wert aufgebaut 040755 << 16List? Speziell, welche Repräsentation / Basis verwendet es (ich denke möglicherweise Octal ) und vor allem, wie weiß die Sprache (der Python-Interpreter in diesem Fall), was die Repräsentation ist? Hmm, vielleicht ist der Typ im C-Code deklariert. Aus welcher Datei erhalten Sie auch die "Dateityp" -Werte? Das Hinzufügen einiger Links / Verweise wäre hilfreich.
Faheem Mitha
@ Random832: Ich sehe, dass zipinfo.ces in der Quelle für das Entpacken unter Debian ist . Alternativ kann man die bequemere verwenden apt-get source unzip. Sie können dies an Ihre Antwort anhängen oder eine nicht übertragene Quelle verwenden. Normalerweise zitiere ich Debian, weil ich glaube, dass sie auf lange
Sicht verfügbar sein werden
@ Random832: Ok, ich denke ich sehe wie das funktioniert. Sie addieren einfach alle Werte für die Dinge, die in Basis 8 gemäß Ihrer Tabelle festgelegt sind, und Sie erhalten die Nummer 040755. Das wäre imo für Leute erwähnenswert, die es nicht wissen oder vergessen haben. Das lässt natürlich die Frage offen, woher es weiß, dass es sich um Basis 8 handelt, aber möglicherweise wird der Typ als Basis 8 deklariert.
Faheem Mitha
Es ist die Basis 8, weil sie mit einer 0 beginnt. Ich werde das in einer Bearbeitung verdeutlichen
Random832
@Random: Danke für die Klarstellung. Mir war die führende 0-Konvention nicht bekannt. Die stat.hDatei unter Linux (ich nehme an, die richtige Datei ist /usr/include/sys/stat.h) enthält die Definition dieser Konstanten nicht so klar wie die Datei, mit der Sie verlinkt haben. Sind sie woanders versteckt? Ich sehe, Sie haben den Begriff verwendet test macros, aber ich bin mir nicht sicher, was das bedeutet.
Faheem Mitha