这是一个有点奇怪的问题,但网上似乎没有太多关于这方面的信息。我刚刚添加了关于 zip 格式的外部文件属性问题的答案。正如您从我的回答中看到的,我得出的结论是,只有第二个字节(4 个字节)实际上用于 Unix。显然,这在解压缩时包含了足够的信息来推断该对象是文件还是目录,并且还有空间用于其他权限和属性信息。我的问题是,这如何映射到通常的 Unix 权限?通常的 Unix 权限(例如下面)是否ls
恰好适合一个字节,如果是,有人可以描述布局或提供参考吗?
$ 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
让我通过提出一个具体问题来使这一点更加具体。根据Trac补丁在我上面的回答中引用,您可以使用下面的 Python 代码片段创建一个 zip 文件。
该040755 << 16L
值对应于创建具有权限的空目录drwxr-xr-x
。 (我测试过)。我认识到0755
对应于该rwxr-xr-x
模式,但是04
, 整个值如何对应于一个字节?我还认识到<< 16L
对应于按位左移 16 位,这将使其最终成为从顶部开始的第二个字节。
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()
编辑:在重读这篇文章时,我认为我的 Unix 权限仅对应于一个字节的结论可能是不正确的,但我将让上面的内容代表现在,因为我不确定正确的答案是什么。
EDIT2:对于仅对应于 1 个字节的 Unix 值,我确实是错误的。正如 @Random832 所解释的,它使用前两个字节。根据 @Random832 的回答,我们可以040755
从他给出的下表中构建所需的值。即:
__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
这里的补充是在基数 8。
答案1
0040000
是 的传统值S_IFDIR
,表示目录的文件类型标志。该类型使用前 4 位16位 st_mode
value,0100000
是常规文件的值。
外部文件属性的高 16 位似乎用于特定于操作系统的权限。 Unix 值与传统 Unix 实现上的相同。其他操作系统使用其他值。有关各种不同操作系统中使用的格式的信息可以在 Info-ZIP 源代码中找到(下载或例如在 debian 中apt-get source [zip or unzip]
) - 相关文件位于zipinfo.c
中unzip
,特定于平台的文件位于zip
.
它们通常以八进制(基数 8)定义;这在 C 中表示并且Python通过在数字前加上前缀0
.
这些值都可以在<sys/stat.h>
-4.4BSD版本链接。这些不在 POSIX 标准中(而是定义测试宏);但源自 AT&T Unix 和 BSD。 (在 GNU libc / Linux 中,值本身定义为__S_IFDIR
etcbits/stat.h
,虽然内核头文件可能更容易阅读 - 值几乎在任何地方都是相同的。)
#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 */
当然,其他 12 位用于权限和 setuid/setgid/sticky 位,与 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 */
作为历史记录,原因0100000
是常规文件而不是 0 是因为在 unix 的早期版本中,0 表示“小”文件(这些文件不使用文件系统中的间接块),并且模式标志的高位是设置为将使用间接块的“大”文件。在文件系统发生更改后,使用该位的其他两种类型被添加到后来的 UNIX 派生操作系统中。
因此,总而言之,Unix 扩展属性字段的总体布局是
TTTTsstrwxrwxrwx0000000000ADVSHR
^^^^____________________________ file type as explained above
^^^_________________________ setuid, setgid, sticky
^^^^^^^^^________________ permissions
^^^^^^^^________ This is the "lower-middle byte" your post mentions
^^^^^^^^ DOS attribute bits