Esta es una pregunta un poco exótica, pero no parece haber mucha información en la red sobre esto. Acabo de agregar una respuesta a una pregunta sobre el atributo de archivo externo del formato zip . Como puede ver en mi respuesta, concluyo que solo el segundo byte (de 4 bytes) se usa realmente para Unix. Aparentemente, esto contiene suficiente información al descomprimir para deducir si el objeto es un archivo o un directorio, y también tiene espacio para otros permisos e información de atributos. Mi pregunta es, ¿cómo se asigna esto a los permisos habituales de Unix? ¿Los permisos habituales de Unix (p. Ej., A continuación) se ls
ajustan exactamente a un byte y, de ser así, ¿alguien puede describir el diseño o dar una referencia, 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
Permítanme hacer esto más concreto haciendo una pregunta específica. Según el parche de Trac citado en mi respuesta anterior, puede crear un archivo zip con el fragmento de Python a continuación.
El 040755 << 16L
valor corresponde a la creación de un directorio vacío con los permisos drwxr-xr-x
. (Lo probé). Reconozco que 0755
corresponde al rwxr-xr-x
patrón, pero ¿qué pasa con el 04
, y cómo corresponde el valor completo a un byte? También reconozco que << 16L
corresponde a un desplazamiento a la izquierda bit a bit de 16 lugares, lo que lo haría terminar como el segundo desde el 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()
EDITAR: Al releer esto, creo que mi conclusión de que los permisos de Unix solo corresponden a un byte puede ser incorrecta, pero dejaré que lo anterior represente el presente, ya que no estoy seguro de cuál es la respuesta correcta.
EDIT2: De hecho, era incorrecto acerca de los valores de Unix que solo corresponden a 1 byte. Como explicó @ Random832, utiliza los dos primeros bytes. Según la respuesta de @ Random832, podemos construir el 040755
valor deseado a partir de las tablas que da a continuación. 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
La adición aquí está en la base 8 .
Respuestas:
0040000
es el valor tradicional deS_IFDIR
, el indicador de tipo de archivo que representa un directorio. El tipo utiliza los 4 bits superiores del valor de 16 bitsst_mode
,0100000
es el valor de los archivos normales.Los 16 bits altos de los atributos del archivo externo parecen usarse para permisos específicos del sistema operativo. Los valores de Unix son los mismos que en las implementaciones de Unix tradicionales. Otros sistemas operativos usan otros valores. Información sobre los formatos utilizados en una variedad de sistemas operativos diferentes se puede encontrar en el código postal Info-fuente ( descarga o, por ejemplo en debian
apt-get source [zip or unzip]
) - archivos relevantes sonzipinfo.c
enunzip
, y los archivos específicos de la plataforma enzip
.Estos se definen convencionalmente en octal (base 8); esto se representa en C y python prefijando el número con a
0
.Todos estos valores se pueden encontrar en
<sys/stat.h>
- enlace a la versión 4.4BSD . Estos no están en el estándar POSIX (que define macros de prueba en su lugar); pero se originan en AT&T Unix y BSD. (en GNU libc / Linux, los valores en sí mismos se definen como__S_IFDIR
etc.bits/stat.h
, aunque el encabezado del núcleo podría ser más fácil de leer: los valores son todos prácticamente iguales en todas partes).Y, por supuesto, los otros 12 bits son para los permisos y setuid / setgid / sticky bits, lo mismo que para chmod:
Como nota histórica, la razón
0100000
es para archivos regulares en lugar de 0 es que en versiones muy tempranas de Unix, 0 era para archivos 'pequeños' (estos no usaban bloques indirectos en el sistema de archivos) y el bit alto del indicador de modo era configurado para archivos 'grandes' que usarían bloques indirectos. Los otros dos tipos que usan este bit se agregaron en sistemas operativos derivados de Unix posteriores, después de que el sistema de archivos hubiera cambiado.Entonces, para concluir, el diseño general del campo de atributos extendidos para Unix es
fuente
040755 << 16L
se construye el valor ? Específicamente, ¿qué representación / base está usando (creo que posiblemente Octal ), y lo más importante, ¿cómo sabe el lenguaje (el intérprete de Python en este caso) cuál es la representación? Hmm, tal vez el tipo se declara en el código C. Además, ¿de qué archivo obtiene los valores de "tipo de archivo"? Agregar algunos enlaces / referencias sería útil.zipinfo.c
está en la fuente para descomprimir en Debian . Alternativamente, uno puede usar el más convenienteapt-get source unzip
. Puede agregar eso a su respuesta, o usar una fuente no corriente. Por lo general, cito a Debian porque tengo fe en que estarán a largo plazo. :-)040755
. Vale la pena mencionar a las personas que no saben o han olvidado. Por supuesto, eso todavía deja la pregunta de cómo sabe que es la base 8, pero tal vez el tipo se declare como base 8.stat.h
archivo en Linux (supongo que el archivo correcto es/usr/include/sys/stat.h
) no contiene la definición de estas constantes de una manera tan clara como el archivo al que se vinculó. ¿Están escondidos en otro lugar? Veo que usaste el términotest macros
, pero no estoy seguro de lo que eso significa.