gpt4 book ai didi

python - Python 文件权限中的 Zipfile

转载 作者:行者123 更新时间:2023-11-28 21:06:47 30 4
gpt4 key购买 nike

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

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()

但是当我使用 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 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')

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

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 - Python 文件权限中的 Zipfile,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42326428/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com