簡體   English   中英

python中的Zipfile文件權限

[英]Zipfile in Python file permission

我使用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.

這意味着外部文件屬性是系統特定的。 解釋其他系統的外部文件屬性可能會使情況更糟。 如果僅關心UNIX,則可以檢查ZipInfo.created_system並將其與3 (對於UNIX)進行比較。 不幸的是,該規范在解釋外部屬性方面並沒有進一步幫助我們。

該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.  ║
╚═════════╩══════════╩════════╩═══════════════════════════════════════════════════════╝

雖然這是觀察性的,但似乎是共識。

放在一起:

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')
import zipfile
import os

unZipFile = zipfile.ZipFile("sample.zip", "r")

tmp_dir = "/tmp"
try:
    for info in unZipFile.infolist():
        real_path = unZipFile.extract(info, tmp_dir)

        # permission
        unix_attributes = info.external_attr >> 16
        target = os.path.join(tmp_dir, info.filename)
        if unix_attributes:
            os.chmod(target, unix_attributes)

        if not real_path:
            print "Extract failed: " + info.filename
finally:
    unZipFile.close()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM