zip 格式的外部文件属性

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

让我通过提出一个具体问题来使这一点更加具体。根据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_modevalue,0100000是常规文件的值。

外部文件属性的高 16 位似乎用于特定于操作系统的权限。 Unix 值与传统 Unix 实现上的相同。其他操作系统使用其他值。有关各种不同操作系统中使用的格式的信息可以在 Info-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_IFDIRetcbits/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

相关内容