Python文件权限中的Zipfile [英] Zipfile in Python file permission

查看:26
本文介绍了Python文件权限中的Zipfile的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 zipfile lib 从 zip 中提取文件,现在解压缩目录后我发现我的文件的权限已损坏,

导入压缩文件fh = open('sample.zip', 'rb')z = zipfile.ZipFile(fh)打印 z.namelist()对于 z.namelist() 中的名称:z.extract(name, '/tmp/')fh.close()

但是当我使用 linux 解压工具时,这个问题不会发生我尝试使用

os.system('unzip sample.zip')

但我仍然想用 zipfile

解决方案

相关的 Python 问题提供了有关该问题最初存在的原因的一些见解:https://bugs.python.org/issue18262https:///bugs.python.org/issue15795

此外,可以在此处找到原始 Zip 规范:https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT

重要的部分是:

<前>4.4.2 版本制作者(2 字节)4.4.2.1 高位字节表示文件的兼容性属性信息.如果外部文件属性与 MS-DOS 兼容,可以通过 PKZIP 读取DOS 版本 2.04g 那么这个值将为零.如果这些属性不兼容,则此值将识别属性所在的主机系统兼容的.软件可以使用这些信息来确定文本文件的行记录格式等.4.4.2.2 目前的映射是:0 - MS-DOS 和 OS/2(FAT/VFAT/FAT32 文件系统)1 - Amiga 2 - OpenVMS3 - UNIX 4 - 虚拟机/内容管理系统5 - 雅达利 ST 6 - OS/2 H.P.F.S.7 - Macintosh 8 - Z 系统9 - CP/M 10 - Windows NTFS11 - MVS (OS/390 - Z/OS) 12 - VSE13 - Acorn Risc 14 - VFAT15 - 备用 MVS 16 - BeOS17 - 串联 18 - OS/40019 - OS X (Darwin) 20 到 255 - 未使用...4.4.15 外部文件属性:(4 字节)外部属性的映射是取决于主机系统(请参阅版本制作者").为了MS-DOS,低位字节是 MS-DOS 目录属性字节.如果输入来自标准输入,这字段设置为零.

这意味着外部文件属性是系统特定的.解释不同系统的外部文件属性可能会使情况变得更糟.如果我们只关心 UNIX,我们可以检查 ZipInfo.created_system 并将其与 3(对于 UNIX)进行比较.不幸的是,规范并没有帮助我们进一步解释如何解释外部属性.

此 Wiki 中有一些内容 http://forensicswiki.org/wiki/Zip#External_file_attributes

<前>外部属性 UNIX (3) 的大小为 4 个字节,包括:╔========╦=========╦=======╦=====================================================╗║ 偏移量 ║ 尺寸 ║ 数值 ║ 说明 ║╠========╬=========╬=======╬=====================================================╣║ 0 ║ 1 ║ ║ FAT (MS-DOS) 文件属性.║║ 1 ║ 1 ║ ║ 未知 ║║ 2 ║ 16 位 ║ ║ UNIX 模式(或许可).║║ ║ ║ ║ 这个值好像和stat.st_mode的值差不多.║╚========╩=========╩=======╩======================================================╝

虽然这是观察性的,但似乎是共识.

综合起来:

from zipfile import ZipFileZIP_UNIX_SYSTEM = 3def extract_all_with_permission(zf, target_dir):有关 zf.infolist() 中的信息:提取路径 = zf.extract(信息,目标目录)如果 info.create_system == ZIP_UNIX_SYSTEM:unix_attributes = info.external_attr >>16如果 unix_attributes:os.chmod(extracted_pa​​th, unix_attributes)使用 ZipFile('sample.zip', 'r') 作为 zf:extract_all_with_permission(zf, '/tmp')

可能会出现一个问题,为什么我们首先要保留权限.有些人可能敢说我们只想保留可执行标志.在这种情况下,一个稍微安全的选择可能是仅恢复可执行标志,仅用于文件.

from zipfile import ZipFile从统计导入 S_IXUSRZIP_UNIX_SYSTEM = 3def extract_all_with_executable_permission(zf, target_dir):有关 zf.infolist() 中的信息:提取路径 = zf.extract(信息,目标目录)如果 info.create_system == ZIP_UNIX_SYSTEM 和 os.path.isfile(extracted_pa​​th):unix_attributes = info.external_attr >>16如果 unix_attributes &S_IXUSR:os.chmod(extracted_pa​​th, os.stat(extracted_pa​​th).st_mode | S_IXUSR)使用 ZipFile('sample.zip', 'r') 作为 zf:extract_all_with_executable_permission(zf, '/tmp')

i used zipfile lib to extract file from zip and now after unzip the directory i found the permission of my file has been corrupted ,

import zipfile
fh = open('sample.zip', 'rb')
z = zipfile.ZipFile(fh)
print z.namelist()
for name in z.namelist():
    z.extract(name, '/tmp/')
fh.close()

but when i use linux unzip tools this issue don't happen i try to use

os.system('unzip sample.zip')

but i still want to do this with zipfile

解决方案

The related Python issues provide some insight as to why the issue existed in the first place: https://bugs.python.org/issue18262 and https://bugs.python.org/issue15795

Additionally the original Zip spec can be found here: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT

The important sections are:

4.4.2 version made by (2 bytes)

        4.4.2.1 The upper byte indicates the compatibility of the file
        attribute information.  If the external file attributes 
        are compatible with MS-DOS and can be read by PKZIP for 
        DOS version 2.04g then this value will be zero.  If these 
        attributes are not compatible, then this value will 
        identify the host system on which the attributes are 
        compatible.  Software can use this information to determine
        the line record format for text files etc.  

        4.4.2.2 The current mappings are:

         0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)
         1 - Amiga                     2 - OpenVMS
         3 - UNIX                      4 - VM/CMS
         5 - Atari ST                  6 - OS/2 H.P.F.S.
         7 - Macintosh                 8 - Z-System
         9 - CP/M                     10 - Windows NTFS
        11 - MVS (OS/390 - Z/OS)      12 - VSE
        13 - Acorn Risc               14 - VFAT
        15 - alternate MVS            16 - BeOS
        17 - Tandem                   18 - OS/400
        19 - OS X (Darwin)            20 thru 255 - unused
...
4.4.15 external file attributes: (4 bytes)

       The mapping of the external attributes is
       host-system dependent (see 'version made by').  For
       MS-DOS, the low order byte is the MS-DOS directory
       attribute byte.  If input came from standard input, this
       field is set to zero.

That means that the external file attributes are system specific. Interpreting the external file attributes for a different system could potentially make it worse. If we only care about UNIX, we could check the ZipInfo.created_system and compare it with 3 (for UNIX). Unfortunately the spec doesn't help us much further in how to interpret the external attributes.

There is something in this Wiki http://forensicswiki.org/wiki/Zip#External_file_attributes

The external attributes UNIX (3) is 4 bytes of size and consists of:

╔═════════╦══════════╦════════╦═══════════════════════════════════════════════════════╗
║ Offset  ║  Size    ║ Value  ║                      Description                      ║
╠═════════╬══════════╬════════╬═══════════════════════════════════════════════════════╣
║      0  ║ 1        ║        ║ FAT (MS-DOS) file attributes.                         ║
║      1  ║ 1        ║        ║ Unknown                                               ║
║      2  ║ 16 bits  ║        ║ The UNIX mode (or permission).                        ║
║         ║          ║        ║ The value seems to be similar to stat.st_mode value.  ║
╚═════════╩══════════╩════════╩═══════════════════════════════════════════════════════╝

While that is rather observational, it seems to be the consensus.

Putting this together:

from zipfile import ZipFile

ZIP_UNIX_SYSTEM = 3

def extract_all_with_permission(zf, target_dir):
  for info in zf.infolist():
    extracted_path = zf.extract(info, target_dir)

    if info.create_system == ZIP_UNIX_SYSTEM:
      unix_attributes = info.external_attr >> 16
      if unix_attributes:
        os.chmod(extracted_path, unix_attributes)

with ZipFile('sample.zip', 'r') as zf:
  extract_all_with_permission(zf, '/tmp')

There may be a question coming up why we want to preserve the permissions in the first place. Some may dare to say that we only want to keep the executable flag. A slightly safer option in that case could be to only restore the executable flag, for files only.

from zipfile import ZipFile
from stat import S_IXUSR

ZIP_UNIX_SYSTEM = 3

def extract_all_with_executable_permission(zf, target_dir):
  for info in zf.infolist():
    extracted_path = zf.extract(info, target_dir)

    if info.create_system == ZIP_UNIX_SYSTEM and os.path.isfile(extracted_path):
      unix_attributes = info.external_attr >> 16
      if unix_attributes & S_IXUSR:
        os.chmod(extracted_path, os.stat(extracted_path).st_mode | S_IXUSR)

with ZipFile('sample.zip', 'r') as zf:
  extract_all_with_executable_permission(zf, '/tmp')

这篇关于Python文件权限中的Zipfile的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆