def write_block(file, type, flags, data): block = bytearray() for part in data: block.extend(part) header = S_BLK_HDR_DATA.pack(type, flags, S_BLK_HDR.size + len(block)) crc = crc32(header) crc = crc32(block, crc) file.write(S_SHORT.pack(crc & bitmask(16))) file.write(header) file.write(block)
def write_block(file, btype, flags, data): block = bytearray() for part in data: block.extend(part) header = S_BLK_HDR_DATA.pack(btype, flags, S_BLK_HDR.size + len(block)) crc = crc32(header) crc = crc32(block, crc) file.write(S_SHORT.pack(crc & bitmask(16))) file.write(header) file.write(block)
def write_file(volume, file, split_before, split_after, name, is_unicode, dictsize, host_os, attr, accum_crc, dostime, xtime=None, size=None, pack_size=None): size_64 = size_64_encode(pack_size, size) header_size = file_hdr_size(name, xtime, size_64) volume.seek(+header_size, io.SEEK_CUR) left = pack_size crc = 0 if split_after else accum_crc while left > 0: chunk = file.read(min(FILE_COPY_CRC_BUF, left)) left -= len(chunk) volume.write(chunk) crc = crc32(chunk, crc) if split_after: accum_crc = crc32(chunk, accum_crc) parts = list() flags = (RAR_LONG_BLOCK ^ split_before * RAR_FILE_SPLIT_BEFORE ^ split_after * RAR_FILE_SPLIT_AFTER ^ dictsize ^ is_unicode * RAR_FILE_UNICODE) parts.append( S_FILE_HDR.pack(pack_size & bitmask(32), size & bitmask(32), host_os, crc, dostime, 20, ord("0"), len(name), attr)) if size_64 is not None: flags ^= RAR_FILE_LARGE parts.append(size_64) parts.append(name) if xtime is not None: flags ^= RAR_FILE_EXTTIME parts.append(xtime) volume.seek(-pack_size - header_size, io.SEEK_CUR) write_block(volume, RAR_BLOCK_FILE, flags, parts) volume.seek(+pack_size, io.SEEK_CUR) if split_after: return accum_crc
def file_crc32(file, size): crc = 0 while size > 0: chunk = file.read(min(FILE_CRC_BUF, size)) size -= len(chunk) crc = crc32(chunk, crc) return crc
def write_file(volume, file, split_before, split_after, name, is_unicode, dict, host_os, attr, accum_crc, dostime, xtime=None, size=None, pack_size=None): size_64 = size_64_encode(pack_size, size) header_size = file_hdr_size(name, xtime, size_64) volume.seek(+header_size, io.SEEK_CUR) left = pack_size crc = 0 if split_after else accum_crc while left > 0: chunk = file.read(min(FILE_COPY_CRC_BUF, left)) left -= len(chunk) volume.write(chunk) crc = crc32(chunk, crc) if split_after: accum_crc = crc32(chunk, accum_crc) parts = list() flags = (RAR_LONG_BLOCK ^ split_before * RAR_FILE_SPLIT_BEFORE ^ split_after * RAR_FILE_SPLIT_AFTER ^ dict ^ is_unicode * RAR_FILE_UNICODE) parts.append(S_FILE_HDR.pack( pack_size & bitmask(32), size & bitmask(32), host_os, crc, dostime, 20, ord("0"), len(name), attr )) if size_64 is not None: flags ^= RAR_FILE_LARGE parts.append(size_64) parts.append(name) if xtime is not None: flags ^= RAR_FILE_EXTTIME parts.append(xtime) volume.seek(-pack_size - header_size, io.SEEK_CUR) write_block(volume, RAR_BLOCK_FILE, flags, parts) volume.seek(+pack_size, io.SEEK_CUR) if split_after: return accum_crc
def write_rr(version, host_os, volume, rr_count): prot_size = volume.tell() (rr_crcs, rr_sects) = rr_calc(volume, rr_count, prot_size) crc = crc32(rr_crcs, RR_CRC_INIT) for s in rr_sects: crc = crc32(s.buffer(), crc) prot_sect_count = len(rr_crcs) // S_SHORT.size size = prot_sect_count * RR_CRC_SIZE + rr_count * RR_SECT_SIZE if version < 3: write_block(volume, type=RAR_BLOCK_OLD_RECOVERY, flags=RAR_LONG_BLOCK ^ RAR_SKIP_IF_UNKNOWN, data=( S_LONG.pack(size), (20,), S_SHORT.pack(rr_count), S_LONG.pack(prot_sect_count), RR_PROTECT_2, )) else: write_block(volume, type=RAR_BLOCK_SUB, flags=RAR_LONG_BLOCK ^ RAR_SKIP_IF_UNKNOWN, data=( S_FILE_HDR.pack(size, size, host_os, crc, 0, 29, ord("0"), len(RR_SUB_NAME), 0), RR_SUB_NAME, RR_PROTECT_3, S_LONG.pack(rr_count), struct.pack("<Q", prot_sect_count), )) volume.write(rr_crcs) for s in rr_sects: volume.write(s.buffer())
def write_rr(version, host_os, volume, rr_count): prot_size = volume.tell() (rr_crcs, rr_sects) = rr_calc(volume, rr_count, prot_size) crc = crc32(rr_crcs, RR_CRC_INIT) for s in rr_sects: crc = crc32(s.buffer(), crc) prot_sect_count = len(rr_crcs) // S_SHORT.size size = prot_sect_count * RR_CRC_SIZE + rr_count * RR_SECT_SIZE if version < 3: write_block(volume, type=RAR_BLOCK_OLD_RECOVERY, flags=RAR_LONG_BLOCK ^ RAR_SKIP_IF_UNKNOWN, data=( S_LONG.pack(size), (20, ), S_SHORT.pack(rr_count), S_LONG.pack(prot_sect_count), RR_PROTECT_2, )) else: write_block(volume, type=RAR_BLOCK_SUB, flags=RAR_LONG_BLOCK ^ RAR_SKIP_IF_UNKNOWN, data=( S_FILE_HDR.pack(size, size, host_os, crc, 0, 29, ord("0"), len(RR_SUB_NAME), 0), RR_SUB_NAME, RR_PROTECT_3, S_LONG.pack(rr_count), struct.pack("<Q", prot_sect_count), )) volume.write(rr_crcs) for s in rr_sects: volume.write(s.buffer())
def rr_calc(volume, rr_count, size): volume.seek(0) rr_crcs = bytearray() rr_sects = tuple(BitVector(RR_SECT_SIZE) for i in range(rr_count)) slice = 0 while size > 0: if size < RR_SECT_SIZE: chunk = volume.read(size).ljust(RR_SECT_SIZE, bytes((0,))) size = 0 else: chunk = volume.read(RR_SECT_SIZE) size -= RR_SECT_SIZE rr_crcs.extend(S_SHORT.pack(~crc32(chunk) & bitmask(16))) rr_sects[slice].xor(chunk) slice = (slice + 1) % rr_count return (rr_crcs, rr_sects)
def rr_calc(volume, rr_count, size): volume.seek(0) rr_crcs = bytearray() rr_sects = tuple(BitVector(RR_SECT_SIZE) for _ in range(rr_count)) aslice = 0 while size > 0: if size < RR_SECT_SIZE: chunk = volume.read(size).ljust(RR_SECT_SIZE, bytes((0, ))) size = 0 else: chunk = volume.read(RR_SECT_SIZE) size -= RR_SECT_SIZE rr_crcs.extend(S_SHORT.pack(~crc32(chunk) & bitmask(16))) rr_sects[aslice].xor(chunk) aslice = (aslice + 1) % rr_count return (rr_crcs, rr_sects)