Skip to content

Instantly share code, notes, and snippets.

@folkertdev
Created March 9, 2024 17:06
Show Gist options
  • Save folkertdev/79b31ab271602bf095957868aed449d4 to your computer and use it in GitHub Desktop.
Save folkertdev/79b31ab271602bf095957868aed449d4 to your computer and use it in GitHub Desktop.
Creating a zip file with a unix extra field

run and validate with

rm -f extrafield.zip && python add_unix_extra_field.py && zipinfo -v extrafield.zip

this should show

Archive:  extrafield.zip
There is no zipfile comment.

End-of-central-directory record:
-------------------------------

  Zip archive file size:                       181 (00000000000000B5h)
  Actual end-cent-dir record offset:           159 (000000000000009Fh)
  Expected end-cent-dir record offset:         159 (000000000000009Fh)
  (based on the length of the central directory and its expected offset)

  This zipfile constitutes the sole disk of a single-part archive; its
  central directory contains 1 entry.
  The central directory is 76 (000000000000004Ch) bytes long,
  and its (expected) offset in bytes from the beginning of the zipfile
  is 83 (0000000000000053h).


Central directory entry #1:
---------------------------

  sample.txt

  offset of local header from start of archive:   0
                                                  (0000000000000000h) bytes
  file system or operating system of origin:      Unix
  version of encoding software:                   2.0
  minimum file system compatibility required:     MS-DOS, OS/2 or NT FAT
  minimum software version required to extract:   2.0
  compression method:                             none (stored)
  file security status:                           not encrypted
  extended local header:                          no
  file last modified on (DOS date/time):          1980 Jan 1 00:00:00
  file last modified on (UT extra field modtime): 1970 Jan 1 01:00:00 local
  file last modified on (UT extra field modtime): 1970 Jan 1 00:00:00 UTC
  32-bit CRC value (hex):                         b1d0042c
  compressed size:                                23 bytes
  uncompressed size:                              23 bytes
  length of filename:                             10 characters
  length of extra field:                          20 bytes
  length of file comment:                         0 characters
  disk number on which file begins:               disk 1
  apparent file type:                             binary
  Unix file attributes (100664 octal):            -rw-rw-r--
  MS-DOS file attributes (00 hex):                none

  The central-directory extra field contains:
  - A subfield with ID 0x000d (PKWARE Unix) and 16 data bytes:
    00 00 00 00 00 00 00 00 00 00 00 00 01 02 03 04.

  There is no file comment.
import zipfile
import os
import time
def add_unix_extra_field(zip_filename, file_path):
with zipfile.ZipFile(zip_filename, 'a', zipfile.ZIP_DEFLATED) as zip_file:
# Get current time
now = int(time.time())
# Prepare Unix extra field data
extra_field = b'\x0D\x00' # magic number for a unix extra field
extra_field += b'\x10\x00' # TSize
extra_field += b'\x00\x00\x00\x00' # Access time
extra_field += b'\x00\x00\x00\x00' # Modification time
extra_field += b'\x00\x00\x00\x00' # user ID
extra_field += b'\x01\x02\x03\x04' # data
# Create a ZipInfo object with the extra field data
zip_info = zipfile.ZipInfo(os.path.basename(file_path))
zip_info.external_attr = (os.stat(file_path).st_mode & 0xFFFF) << 16 # Preserve file permissions
zip_info.extra = extra_field
# Copy the file to the zip file with the ZipInfo object
with open(file_path, 'rb') as file:
zip_file.writestr(zip_info, file.read())
if __name__ == "__main__":
zip_filename = "extrafield.zip"
file_path = "sample.txt"
add_unix_extra_field(zip_filename, file_path)
This is a sample file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment