O atributo de arquivo externo do formato zip

21

Essa é uma pergunta um pouco exótica, mas não parece haver muita informação na internet sobre isso. Acabei de adicionar uma resposta a uma pergunta sobre o atributo de arquivo externo do formato zip . Como você pode ver pela minha resposta, concluo que apenas o segundo byte (de 4 bytes) é realmente usado para o Unix. Aparentemente, isso contém informações suficientes ao descompactar para deduzir se o objeto é um arquivo ou um diretório e também tem espaço para outras informações de permissão e atributo. Minha pergunta é, como isso mapeia para as habituais permissões do Unix? Faça as habituais permissões Unix (por exemplo, abaixo) de que ls encaixa exatamente em um byte e, em caso afirmativo, alguém pode descrever o layout ou dar uma referência, por favor?

$ 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

Deixe-me tornar isso mais concreto fazendo uma pergunta específica. Pelo patch do Trac citado na minha resposta acima, você pode criar um arquivo zip com o snippet de Python abaixo.

O valor 040755 << 16L corresponde à criação de um diretório vazio com as permissões drwxr-xr-x . (Eu testei). Eu reconheço que 0755 corresponde ao padrão rwxr-xr-x , mas e quanto ao 04 e como o valor inteiro corresponde a um byte? Eu também reconheço que << 16L corresponde a um deslocamento à esquerda bit a bit de 16 locais, o que faria com que ele terminasse como o segundo do topo do byte.

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: Ao reler isso, acho que minha conclusão de que as permissões do Unix correspondem apenas a um byte pode estar incorreta, mas deixarei o acima exposto para o presente, já que não sei qual é a resposta correta .

EDIT2: Eu estava de fato incorreto sobre os valores Unix que correspondem apenas a 1 byte. Como @ Random832 explicou, ele usa os dois principais bytes. Resposta de Per @ Random832, podemos construir o valor 040755 desejado das tabelas que ele dá abaixo. A saber:

__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 

A adição aqui está na base 8 .

    
por Faheem Mitha 09.06.2011 / 21:52

1 resposta

25

0040000 é o valor tradicional de S_IFDIR , o sinalizador de tipo de arquivo que representa um diretório. O tipo usa os 4 bits principais do valor 16-bit st_mode , 0100000 é o valor dos arquivos regulares.

Os altos 16 bits dos atributos de arquivos externos parecem ser usados para permissões específicas do sistema operacional. Os valores do Unix são os mesmos das implementações tradicionais do Unix. Outros sistemas operacionais usam outros valores. Informações sobre os formatos usados em vários sistemas operacionais diferentes podem ser encontradas no código-fonte do Info-ZIP ( download ou por exemplo em debian apt-get source [zip or unzip] ) - arquivos relevantes são zipinfo.c em unzip e os arquivos específicos da plataforma em zip .

Estes são convencionalmente definidos em octal (base 8); isso é representado em C e python prefixando o número com um 0 .

Esses valores podem ser encontrados em <sys/stat.h> - link para a versão 4.4BSD . Estes não estão no padrão POSIX (que define macros de teste); mas são originários do AT & T Unix e do BSD. (no GNU libc / Linux, os próprios valores são definidos como __S_IFDIR etc em bits/stat.h , embora o cabeçalho do kernel pode ser mais fácil de ler - os valores são praticamente iguais em todos os lugares.)

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

E, claro, os outros 12 bits são para as permissões e setuid / setgid / sticky bits, o mesmo que para 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 */

Como uma observação histórica, a razão 0100000 é para arquivos regulares em vez de 0 é que em versões muito antigas do unix, 0 era para arquivos 'pequenos' (estes não usavam blocos indiretos no sistema de arquivos) e o alto bit do sinalizador de modo foi definido para arquivos 'grandes' que usariam blocos indiretos. Os outros dois tipos que usam esse bit foram adicionados em sistemas operacionais posteriores derivados de unix, depois que o sistema de arquivos mudou.

Então, para finalizar, o layout geral do campo de atributos estendidos para o Unix é

TTTTsstrwxrwxrwx0000000000ADVSHR
^^^^____________________________ file type as explained above
    ^^^_________________________ setuid, setgid, sticky
       ^^^^^^^^^________________ permissions
                ^^^^^^^^________ This is the "lower-middle byte" your post mentions
                        ^^^^^^^^ DOS attribute bits
    
por 10.06.2011 / 04:24

Tags