clalancette / pycdlib

Python library to read and write ISOs
GNU Lesser General Public License v2.1
147 stars 38 forks source link

create reproducible UDF image #113

Open milahu opened 1 year ago

milahu commented 1 year ago

afaik, there is no way to create reproducible UDF images with mkudffs or the linux udf driver, because i cannot set file times to zero

i can create a reproducible ISO image with SOURCE_DATE_EPOCH=0 xorrisofs --modification-date=1970010100000000 --set_all_file_dates set_to_mtime -uid 0 -gid 0 -volid SOME_THING --gpt_disk_guid 00000000000000000000000000000000 -preparer "" -path-list files.txt where files.txt is sorted with LC_ALL=C sort

expected

actual

find pycdlib/ -name "*.py" | xargs grep -HnF -e 'time.time()' -e uuid -e random ``` pycdlib/udf.py:22:import random pycdlib/udf.py:566: self.desc_creation_time.new(time.time()) pycdlib/udf.py:1528: # random value, all ASCII encoded. pycdlib/udf.py:1529: unique = format(int(time.time()), '08x') + format(random.getrandbits(26), '08x') pycdlib/udf.py:1542: self.recording_date.new(time.time()) pycdlib/udf.py:3477: self.recording_date.new(time.time()) pycdlib/udf.py:3649: self.recording_date.new(time.time()) pycdlib/udf.py:4045: self.access_time.new(time.time()) pycdlib/udf.py:4048: self.mod_time.new(time.time()) pycdlib/udf.py:4051: self.attr_time.new(time.time()) pycdlib/udf.py:5323: self.timestamp.new(time.time()) pycdlib/udf.py:5505: self.access_time.new(time.time()) pycdlib/udf.py:5508: self.mod_time.new(time.time()) pycdlib/udf.py:5511: self.attr_time.new(time.time()) pycdlib/headervd.py:308: self.root_dir_record.new_root(self, seqnum, self.log_block_size, time.time()) pycdlib/headervd.py:327: now = time.time() pycdlib/headervd.py:424: vol_mod_date.new(time.time()) pycdlib/pycdlib.py:1081: # Some ISOs use random extent locations for zero-length files. pycdlib/pycdlib.py:1083: # other files, as the linkage will be essentially random. pycdlib/pycdlib.py:1818: False, False, self.xa, 0o040555, time.time()) pycdlib/pycdlib.py:2262: b'', False, 0, time.time()) pycdlib/pycdlib.py:3137: time.time()) pycdlib/pycdlib.py:3449: False, -1, time.time()) pycdlib/pycdlib.py:3718: vd.logical_block_size(), xa, file_mode, time.time()) pycdlib/pycdlib.py:3739: time.time()) pycdlib/pycdlib.py:4767: self.xa, file_mode, time.time()) pycdlib/pycdlib.py:4798: self.xa, file_mode, time.time()) pycdlib/pycdlib.py:5347: rr_symlink_name_bytes, self.xa, time.time()) pycdlib/pycdlib.py:5413: self.xa, -1, time.time()) pycdlib/pycdlib.py:5579: mbr_id - The mbr_id to use. If set to None (the default), a random one pycdlib/isohybrid.py:21:import random pycdlib/isohybrid.py:24:import uuid pycdlib/isohybrid.py:263: self.part_guid = uuid.UUID(bytes=part_guid) pycdlib/isohybrid.py:289: self.part_guid = uuid.uuid4() pycdlib/isohybrid.py:359: self.disk_guid = uuid.UUID(bytes=disk_guid) pycdlib/isohybrid.py:385: self.disk_guid = uuid.uuid4() pycdlib/isohybrid.py:815: self.mbr_id = random.getrandbits(32) ```

workaround

# create reproducible UDF image
# set all times to zero
import time
def zero_time():
    return 0.0
time.time = zero_time
# set all uuid's to zero
import uuid
real_uuid = uuid.UUID
def zero_uuid():
    return real_uuid(hex="00000000000000000000000000000000")
uuid.UUID = zero_uuid
real_uuid4 = uuid.uuid4
def zero_uuid4():
    return real_uuid4(hex="00000000000000000000000000000000")
uuid.uuid4 = zero_uuid4
# set random bits to zero
import random
def zero_getrandbits(k):
    return 0
random.getrandbits = zero_getrandbits
import pycdlib

this will create reproducible image files

but this will set wrong times per TZ=UTC 7z l test.iso and TZ=UTC stat mnt/test.txt, times are off by 56 minutes = 3360 seconds

+ 1970-01-01 00:00:00
- 1970-01-01 00:56:00

see also