#!/usr/bin/python -t import gzip import types import struct import sys from dumpMetadata import byteranges BUF_SIZE = 32768 def get_signature_from_file(sigfile): f = open(sigfile, "r") sig = f.read() f.close() return sig def make_delta_from_sig(src_delta, sigfile, dst_delta): # Open source deltarpm and read/write header (range_start, range_end) = byteranges(src_delta) sfd = open(src_delta, "r") dfd = open(dst_delta, "w") dfd.write(sfd.read(range_end)) # Switch to compressed mode try: scfd = gzip.GzipFile("", "rb", 9, sfd) except: raise zlibError("Data not stored in gzip format") if scfd.read(4) != "DLT3": raise Exception("Not a deltarpm") dcfd = gzip.GzipFile("", "wb", 9, dfd) dcfd.write("DLT3") # Get nevr and write it len_str = scfd.read(4) (length, ) = struct.unpack('>I', len_str) nevr_length = len_str nevr = scfd.read(length) dcfd.write("%s%s" % (nevr_length, nevr)) # Read sequence and write it len_str = scfd.read(4) (length, ) = struct.unpack('>I', len_str) dcfd.write(len_str + scfd.read(length)) # Read md5 and discard, replacing with \x00's. New versions of deltarpm # will see this and use the rpm's md5 checksum rather than this one. scfd.read(16) dcfd.write("\x00" * 16) # Read and write target size dcfd.write(scfd.read(4)) # Read and write other data dcfd.write(scfd.read(12)) len_str = scfd.read(4) (length, ) = struct.unpack('>I', len_str) dcfd.write(len_str + scfd.read(length*2*4)) dcfd.write(scfd.read(4)) # Read and write lead dcfd.write(scfd.read(96)) # Write signature from signature file and skip signature in src deltarpm signature = get_signature_from_file(sigfile) dcfd.write(signature) scfd.read(8) binindex = scfd.read(4) (sigindex, ) = struct.unpack('>I', binindex) bindata = scfd.read(4) (sigdata, ) = struct.unpack('>I', bindata) # each index is 4 32bit segments - so each is 16 bytes sigindexsize = sigindex * 16 sigsize = sigdata + sigindexsize # we have to round off to the next 8 byte boundary disttoboundary = (sigsize % 8) if disttoboundary != 0: disttoboundary = 8 - disttoboundary scfd.read(sigsize + disttoboundary) data = scfd.read(BUF_SIZE) while data != "": dcfd.write(data) data = scfd.read(BUF_SIZE) def main(): if len(sys.argv) != 4: print "Usage: %s " % sys.argv[0] sys.exit(1) make_delta_from_sig(sys.argv[1], sys.argv[2], sys.argv[3]) if __name__ == '__main__': main()