Thuộc tính tệp bên ngoài của định dạng zip


25

Đây là một câu hỏi hơi kỳ lạ, nhưng dường như không có nhiều thông tin trên mạng về điều này. Tôi vừa thêm một câu trả lời cho một câu hỏi về thuộc tính tệp bên ngoài của định dạng zip . Như bạn có thể thấy từ câu trả lời của tôi, tôi kết luận rằng chỉ có byte thứ hai (gồm 4 byte) thực sự được sử dụng cho Unix. Rõ ràng điều này chứa đủ thông tin khi giải nén để suy ra liệu đối tượng là tệp hay thư mục và cũng có không gian cho thông tin thuộc tính và quyền khác. Câu hỏi của tôi là, làm thế nào để bản đồ này với các quyền Unix thông thường? Các quyền Unix thông thường (ví dụ bên dưới) có lsphù hợp với chính xác một byte không, và nếu vậy, ai đó có thể mô tả bố cục hoặc đưa ra một tham chiếu không, làm ơn?

$ 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

Hãy để tôi làm điều này cụ thể hơn bằng cách đặt một câu hỏi cụ thể. Theo bản vá Trac được trích dẫn trong câu trả lời của tôi ở trên, bạn có thể tạo một tệp zip với đoạn mã Python bên dưới.

Các 040755 << 16Lgiá trị tương ứng với việc tạo ra một thư mục rỗng với các điều khoản drwxr-xr-x. (Tôi đã thử nó). Tôi nhận ra 0755tương ứng với rwxr-xr-xmẫu, nhưng còn về 04giá trị và toàn bộ giá trị tương ứng với một byte thì sao? Tôi cũng nhận ra << 16Ltương ứng với sự dịch chuyển trái của bit theo 16 bit, điều này sẽ làm cho nó kết thúc dưới dạng thứ hai từ byte trên cùng.

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

EDIT: Khi đọc lại điều này, tôi nghĩ rằng kết luận của tôi rằng các quyền Unix chỉ tương ứng với một byte có thể không chính xác, nhưng tôi sẽ để ý ở trên cho hiện tại, vì tôi không chắc câu trả lời đúng là gì.

EDIT2: Tôi thực sự không chính xác về các giá trị Unix chỉ tương ứng với 1 byte. Như @ Random832 đã giải thích, nó sử dụng cả hai byte trên cùng. Mỗi câu trả lời của @ Random832, chúng ta có thể xây dựng 040755giá trị mong muốn từ các bảng anh ta đưa ra dưới đây. Cụ thể là:

__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 

Việc bổ sung ở đây là trong cơ sở 8 .


Tôi không biết gì về quyền zip, nhưng tôi biết rằng quyền unix truyền thống sử dụng 12 bit, nhiều hơn một byte. Có thể zip không bận tâm với setxid và dính, nhưng vẫn để lại 9 (rwx × ugo).
Gilles 'SO- ngừng trở nên xấu xa'

Câu trả lời:


30

0040000là giá trị truyền thống của S_IFDIR, cờ loại tệp đại diện cho một thư mục. Loại sử dụng 4 bit trên cùng của giá trị 16 bit st_mode , 0100000là giá trị cho các tệp thông thường.

16 bit cao của các thuộc tính tệp bên ngoài dường như được sử dụng cho các quyền cụ thể của hệ điều hành. Các giá trị Unix giống như trên các triển khai unix truyền thống. Các hệ điều hành khác sử dụng các giá trị khác. Thông tin về các định dạng được sử dụng trong nhiều hệ điều hành khác nhau có thể được tìm thấy trong mã nguồn Info-ZIP ( tải xuống hoặc ví dụ trong debian apt-get source [zip or unzip]) - các tệp có liên quan nằm zipinfo.ctrong unzipvà các tệp dành riêng cho nền tảng zip.

Đây là quy ước được xác định trong bát phân (cơ sở 8); điều này được thể hiện bằng C và python bằng cách thêm tiền tố vào số a 0.

Tất cả các giá trị này có thể được tìm thấy trong <sys/stat.h>- liên kết đến phiên bản 4.4BSD . Đây không phải là trong tiêu chuẩn POSIX (thay vào đó xác định các macro thử nghiệm); nhưng bắt nguồn từ AT & T Unix và BSD. (trong GNU libc / Linux, các giá trị được định nghĩa là __S_IFDIRvv bits/stat.h, mặc dù tiêu đề kernel có thể dễ đọc hơn - các giá trị đều giống nhau ở mọi nơi.)

#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 */

Và tất nhiên, 12 bit còn lại dành cho các quyền và bit setuid / setgid / dính, giống như đối với 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 */

Như một ghi chú lịch sử, lý do 0100000là cho các tệp thông thường thay vì 0 là trong các phiên bản đầu tiên của unix, 0 là cho các tệp 'nhỏ' (những tệp này không sử dụng các khối gián tiếp trong hệ thống tệp) và bit cao của cờ chế độ là đặt cho các tệp 'lớn' sẽ sử dụng các khối gián tiếp. Hai loại khác sử dụng bit này đã được thêm vào trong các hệ điều hành có nguồn gốc unix sau này, sau khi hệ thống tập tin đã thay đổi.

Vì vậy, để kết thúc, bố cục tổng thể của trường thuộc tính mở rộng cho Unix là

TTTTsstrwxrwxrwx0000000000ADVSHR
^^^^____________________________ file type as explained above
    ^^^_________________________ setuid, setgid, sticky
       ^^^^^^^^^________________ permissions
                ^^^^^^^^________ This is the "lower-middle byte" your post mentions
                        ^^^^^^^^ DOS attribute bits

@ Random832: Wow, đó là hoàn thành ấn tượng và thông qua. Bạn cũng có thể giải thích làm thế nào giá trị 040755 << 16Lđược xây dựng? Cụ thể, nó sử dụng đại diện / cơ sở nào (tôi nghĩ có thể là Octal ) và quan trọng nhất là làm thế nào để ngôn ngữ (trình thông dịch Python trong trường hợp này) biết đại diện là gì? Hmm, có thể loại được khai báo trong mã C. Ngoài ra, tập tin nào bạn nhận được các giá trị "loại tệp" từ? Thêm một số liên kết / tài liệu tham khảo sẽ hữu ích.
Faheem Mitha

@ Random832: Tôi thấy đó zipinfo.clà trong nguồn giải nén trên Debian . Hoặc người ta có thể sử dụng thuận tiện hơn apt-get source unzip. Bạn có thể nối nó vào câu trả lời của bạn hoặc sử dụng một nguồn không chính thống. Tôi thường trích dẫn Debian vì tôi tin rằng họ sẽ có mặt trong một thời gian dài. :-)
Faheem Mitha

@ Random832: Ok, tôi nghĩ rằng tôi thấy cách này hoạt động. Bạn chỉ cần cộng tất cả các giá trị cho những thứ được đặt trong cơ sở 8 theo bảng của bạn và bạn nhận được số 040755. Đó sẽ là giá trị đề cập đến imo cho những người không biết hoặc đã quên. Tất nhiên, điều đó vẫn để lại câu hỏi làm thế nào nó biết nó là cơ sở 8, nhưng có lẽ loại được khai báo là cơ sở 8.
Faheem Mitha

Đó là cơ sở 8 vì nó bắt đầu bằng 0. Tôi sẽ làm rõ điều đó trong một chỉnh sửa
Random832

@Random: Cảm ơn đã làm rõ. Tôi đã không nhận thức được các quy ước 0 hàng đầu. Các stat.htập tin trên Linux (tôi giả sử các tập tin chính xác là /usr/include/sys/stat.h) không chứa định nghĩa của những hằng số trong một cách rõ ràng như các tập tin bạn liên kết đến. Có phải họ đang trốn đi nơi khác? Tôi thấy bạn đã sử dụng thuật ngữ này test macros, nhưng tôi không chắc điều đó có nghĩa là gì.
Faheem Mitha
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.