Essa é uma pergunta um pouco exótica, mas não parece haver muita informação na rede sobre isso. Acabei de adicionar uma resposta a uma pergunta sobre o atributo de arquivo externo do formato zip . Como você pode ver na minha resposta, concluo que apenas o segundo byte (de 4 bytes) é realmente usado para Unix. Aparentemente, isso contém informações suficientes ao descompactar para deduzir se o objeto é um arquivo ou um diretório e também possui espaço para outras informações de permissão e atributo. Minha pergunta é: como isso é mapeado para as permissões usuais do Unix? Faça as permissões usuais do Unix (por exemplo, abaixo) que se ls
encaixam em exatamente um byte e, nesse caso, alguém pode descrever o layout ou fornecer 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. De acordo com o patch Trac citado na minha resposta acima, você pode criar um arquivo zip com o snippet de Python abaixo.
O 040755 << 16L
valor corresponde à criação de um diretório vazio com as permissões drwxr-xr-x
. (Eu testei). Reconheço que 0755
corresponde ao rwxr-xr-x
padrão, mas e quanto a 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 lugares, o que faria com que fosse o segundo do byte superior.
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 exposto acima no momento, pois não tenho certeza de qual é a resposta correta.
EDIT2: Eu estava realmente incorreto sobre os valores Unix correspondentes apenas a 1 byte. Como o @ Random832 explicou, ele usa os dois primeiros bytes. Pela resposta de @ Random832, podemos construir o 040755
valor desejado a partir das tabelas que ele fornece abaixo. Nomeadamente:
__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 .
Respostas:
0040000
é o valor tradicional deS_IFDIR
, o sinalizador de tipo de arquivo que representa um diretório. O tipo usa os 4 bits superiores do valor de 16 bitsst_mode
,0100000
é o valor para arquivos regulares.Os 16 bits altos dos atributos de arquivo externo parecem ser usados para permissões específicas do SO. 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 Info-ZIP ( download ou, por exemplo, no debian
apt-get source [zip or unzip]
) - arquivos relevantes estãozipinfo.c
dentrounzip
e arquivos específicos da plataformazip
.Estes são convencionalmente definidos em octal (base 8); isso é representado em C e python , prefixando o número com a
0
.Esses valores podem ser encontrados no
<sys/stat.h>
- link para a versão 4.4BSD . Eles não estão no padrão POSIX (que define macros de teste); mas são originários da AT&T Unix e BSD. (no GNU libc / Linux, os próprios valores são definidos como__S_IFDIR
etcbits/stat.h
, embora o cabeçalho do kernel possa ser mais fácil de ler - os valores são todos os mesmos em praticamente todos os lugares.)E, é claro, os outros 12 bits são para as permissões e os bits setuid / setgid / sticky, o mesmo que para o chmod:
Como uma nota histórica, o motivo
0100000
é que os arquivos regulares são substituídos por 0, pois nas versões mais antigas do unix, 0 era para arquivos 'pequenos' (eles não usavam blocos indiretos no sistema de arquivos) e o alto nível do sinalizador de modo era definido para arquivos 'grandes' que usariam blocos indiretos. Os outros dois tipos que usam esse bit foram adicionados em sistemas operacionais derivados do unix posteriores, após a alteração do sistema de arquivos.Portanto, para finalizar, o layout geral do campo de atributos estendidos do Unix é
fonte
040755 << 16L
é construído? Especificamente, que representação / base está usando (acho que possivelmente Octal ) e, o mais importante, como a linguagem (o intérprete Python nesse caso) sabe qual é a representação? Hmm, talvez o tipo seja declarado no código C. Além disso, de qual arquivo você está obtendo os valores "tipo de arquivo"? Adicionar alguns links / referências seria útil.zipinfo.c
está na fonte para descompactar no Debian . Alternativamente, pode-se usar o mais convenienteapt-get source unzip
. Você pode anexá-lo à sua resposta ou usar uma fonte unstream. Eu costumo citar Debian, porque eu tenho fé que será em torno de um longo tempo :-).040755
. Vale a pena mencionar o imo para pessoas que não sabem ou se esqueceram. Claro, isso ainda deixa a questão de como ele sabe que é base 8, mas talvez o tipo é declarado como base de 8.stat.h
arquivo no Linux (suponho que seja o arquivo correto/usr/include/sys/stat.h
) não contém a definição dessas constantes de maneira tão clara quanto o arquivo ao qual você vinculou. Eles estão escondidos em outro lugar? Vejo que você usou o termotest macros
, mas não tenho certeza do que isso significa.