Zip

zip 格式的外部文件屬性

  • June 10, 2011

這是一個有點異國情調的問題,但網上似乎沒有太多關於此的資訊。我剛剛添加了一個關於 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 為基數的。

0040000是 的傳統值S_IFDIR,代表目錄的文件類型標誌。該類型使用16 位 st_mode值的前 4 位,0100000是正常文件的值。

外部文件屬性的高 16 位似乎用於特定於作業系統的權限。Unix 值與傳統的 Unix 實現相同。其他作業系統使用其他值。有關各種不同作業系統中使用的格式的資訊可以在 Info-ZIP 原始碼(下載或例如在 debian 中apt-get source [zip or unzip])中找到 - 相關文件位於zipinfo.cunzip,平台特定文件位於zip.

這些通常以八進制(以 8 為基數)定義;這在 C 和python中通過在數字前面加上 . 來表示0

這些值都可以在4.4BSD 版本的連結中<sys/stat.h>找到。這些不在 POSIX 標準中(而是定義了測試宏);但起源於 AT&T Unix 和 BSD。(在 GNU libc / Linux 中,值本身被定義為etc in ,儘管核心標頭檔可能更容易閱讀 - 這些值幾乎在任何地方都相同。)__S_IFDIRbits/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

引用自:https://unix.stackexchange.com/questions/14705