zip 格式的外部文件属性

Fah*_*tha 29 zip

这是一个有点奇特的问题,但网上似乎没有太多关于此的信息。我刚刚添加了一个关于 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
Run Code Online (Sandbox Code Playgroud)

让我通过提出一个具体问题来更具体地说明这一点。根据我上面的回答中引用的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()
Run Code Online (Sandbox Code Playgroud)

编辑:在重读这篇文章时,我认为我的结论 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 
Run Code Online (Sandbox Code Playgroud)

这里的加法是以8底的

Ran*_*832 38

0040000是 的传统值S_IFDIR,代表目录的文件类型标志。该类型使用16 位 st_mode值的前 4 位,0100000是常规文件的值。

外部文件属性的高 16 位似乎用于操作系统特定的权限。Unix 值与传统的 Unix 实现相同。其他操作系统使用其他值。关于在各种不同的操作系统所使用的格式的信息可以在信息-ZIP的源代码(可以找到下载或如Debian中apt-get source [zip or unzip]) -有关文件zipinfo.cunzip,并且在平台特定的文件zip

这些通常以八进制(基数为 8)定义;这在 C 和python 中通过在数字前面加上前缀来表示0

这些数值都可以在发现<sys/stat.h>-链路4.4BSD版本。这些不在 POSIX 标准中(它定义了测试宏);但起源于 AT&T Unix 和 BSD。(在 GNU libc / Linux 中,值本身被定义为__S_IFDIRetc in bits/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 */
Run Code Online (Sandbox Code Playgroud)

当然,其他 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 */
Run Code Online (Sandbox Code Playgroud)

作为一个历史记录,原因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
Run Code Online (Sandbox Code Playgroud)

  • 我在这里创建一个帐户只是为了支持这个问题和答案。非常感谢您的详细解释。这对我帮助很大。 (3认同)