[英]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/issue18262和https://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.