Attribut de fichier externe du format zip

25

C'est une question un peu exotique, mais il ne semble pas y avoir beaucoup d'informations sur le net à ce sujet. Je viens d'ajouter une réponse à une question sur l'attribut de fichier externe du format zip . Comme vous pouvez le voir dans ma réponse, je conclus que seul le deuxième octet (de 4 octets) est réellement utilisé pour Unix. Apparemment, cela contient suffisamment d'informations lors de la décompression pour déduire si l'objet est un fichier ou un répertoire, et dispose également d'un espace pour d'autres informations d'autorisation et d'attribut. Ma question est, comment cette carte correspond-elle aux autorisations Unix habituelles? Faites les autorisations Unix habituelles (par exemple ci-dessous) qui lscorrespondent à exactement un octet, et si oui, quelqu'un peut-il décrire la mise en page ou donner une référence, s'il vous plaît?

$ 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

Permettez-moi de rendre cela plus concret en posant une question spécifique. Selon le patch Trac cité dans ma réponse ci-dessus, vous pouvez créer un fichier zip avec l'extrait de Python ci-dessous.

La 040755 << 16Lvaleur correspond à la création d'un répertoire vide avec les autorisations drwxr-xr-x. (Je l'ai testé). Je reconnais que cela 0755correspond au rwxr-xr-xmotif, mais qu'en est-il du 04, et comment la valeur entière correspond-elle à un octet? Je reconnais également que cela << 16Lcorrespond à un décalage gauche au niveau du bit de 16 positions, ce qui le ferait finir comme le deuxième à partir de l'octet supérieur.

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: En relisant cela, je pense que ma conclusion que les autorisations Unix ne correspondent qu'à un octet peut être incorrecte, mais je laisserai ce qui précède représenter le présent, car je ne suis pas sûr de la bonne réponse.

EDIT2: J'avais en effet tort sur les valeurs Unix ne correspondant qu'à 1 octet. Comme l'a expliqué @ Random832, il utilise les deux premiers octets. Selon la réponse de @ Random832, nous pouvons construire la 040755valeur souhaitée à partir des tableaux qu'il donne ci-dessous. À savoir:

__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 

L'addition ici est en base 8 .

Faheem Mitha
la source
Je ne sais rien des autorisations zip, mais je sais que les autorisations unix traditionnelles utilisent 12 bits, ce qui représente plus d'un octet. Peut-être que zip ne dérange pas avec setxid et collant, mais cela laisse toujours 9 (rwx × ugo).
Gilles 'SO- arrête d'être méchant'

Réponses:

30

0040000est la valeur traditionnelle de S_IFDIR, l'indicateur de type de fichier représentant un répertoire. Le type utilise les 4 premiers bits de la valeur 16 bits st_mode , 0100000c'est la valeur des fichiers normaux.

Les 16 bits élevés des attributs de fichiers externes semblent être utilisés pour les autorisations spécifiques au système d'exploitation. Les valeurs Unix sont les mêmes que sur les implémentations Unix traditionnelles. D'autres systèmes d'exploitation utilisent d'autres valeurs. Des informations sur les formats utilisés dans une variété d'OS différents peuvent être trouvées dans le code source Info-ZIP ( téléchargement ou par exemple dans debian apt-get source [zip or unzip]) - les fichiers pertinents sont zipinfo.cdans unzipet les fichiers spécifiques à la plate-forme dans zip.

Celles-ci sont classiquement définies en octal (base 8); ceci est représenté en C et python en préfixant le nombre avec a 0.

Ces valeurs peuvent toutes être trouvées dans <sys/stat.h>- lien vers la version 4.4BSD . Ce ne sont pas dans la norme POSIX (qui définit à la place les macros de test); mais proviennent d'AT & T Unix et BSD. (dans GNU libc / Linux, les valeurs elles-mêmes sont définies comme __S_IFDIRetc dans bits/stat.h, bien que l'en- tête du noyau puisse être plus facile à lire - les valeurs sont toutes les mêmes à peu près partout.)

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

Et bien sûr, les 12 autres bits sont pour les permissions et les bits setuid / setgid / sticky, les mêmes que pour 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 */

Comme note historique, la raison 0100000pour les fichiers normaux au lieu de 0 est que dans les toutes premières versions d'Unix, 0 était pour les 'petits' fichiers (ceux-ci n'utilisaient pas de blocs indirects dans le système de fichiers) et le bit élevé de l'indicateur de mode était défini pour les «gros» fichiers qui utiliseraient des blocs indirects. Les deux autres types utilisant ce bit ont été ajoutés dans les systèmes d'exploitation ultérieurs dérivés d'Unix, après la modification du système de fichiers.

Donc, pour conclure, la disposition générale du champ d'attributs étendus pour Unix est

TTTTsstrwxrwxrwx0000000000ADVSHR
^^^^____________________________ file type as explained above
    ^^^_________________________ setuid, setgid, sticky
       ^^^^^^^^^________________ permissions
                ^^^^^^^^________ This is the "lower-middle byte" your post mentions
                        ^^^^^^^^ DOS attribute bits
Aléatoire832
la source
@ Random832: Wow, c'est incroyablement complet et complet. Pouvez-vous également expliquer comment la valeur 040755 << 16Lest construite? Plus précisément, quelle représentation / base utilise-t-il (je pense peut-être Octal ), et surtout, comment le langage (l'interpréteur Python dans ce cas) sait-il ce qu'est la représentation? Hmm, peut-être que le type est déclaré dans le code C. De plus, de quel fichier obtenez-vous les valeurs de "type de fichier"? L'ajout de liens / références serait utile.
Faheem Mitha
@ Random832: Je vois que zipinfo.cc'est dans la source pour décompresser sur Debian . Alternativement, on peut utiliser le plus pratique apt-get source unzip. Vous pouvez ajouter cela à votre réponse ou utiliser une source non diffusée. Je cite habituellement Debian parce que j'ai confiance qu'ils seront là pour longtemps. :-)
Faheem Mitha
@ Random832: Ok, je pense que je vois comment cela fonctionne. Vous additionnez simplement toutes les valeurs pour les choses qui sont définies dans la base 8 selon votre table, et vous obtenez le nombre 040755. Cela vaut la peine de mentionner imo pour les personnes qui ne savent pas ou qui ont oublié. Bien sûr, cela laisse encore la question de savoir comment il sait qu'il est en base 8, mais peut-être que le type est déclaré en base 8.
Faheem Mitha
C'est la base 8 car il commence par un 0. Je clarifierai cela dans une édition
Random832
@Random: Merci pour la clarification. Je n'étais pas au courant de la principale convention 0. Le stat.hfichier sous Linux (je suppose que le bon fichier l'est /usr/include/sys/stat.h) ne contient pas la définition de ces constantes d'une manière aussi claire que le fichier auquel vous avez lié. Sont-ils cachés ailleurs? Je vois que vous avez utilisé le terme test macros, mais je ne sais pas ce que cela signifie.
Faheem Mitha