def validate_update( filepath: str, progress_callback: Callable[[float], None]) -> Tuple[str, str]: """ Like otupdate.buildroot.file_actions.validate_update but moreso Checks for the rootfs, rootfs hash, bootfs, and bootfs hash. Returns the path to the rootfs and the path to the bootfs """ filenames = [ROOTFS_NAME, ROOTFS_HASH_NAME, BOOT_NAME, BOOT_HASH_NAME] def zip_callback(progress): progress_callback(progress / 3.0) files, sizes = unzip_update(filepath, zip_callback, filenames, filenames) def rootfs_hash_callback(progress): progress_callback(progress / 3.0 + 0.33) rootfs = files.get(ROOTFS_NAME) assert rootfs rootfs_calc_hash = hash_file(rootfs, rootfs_hash_callback, file_size=sizes[ROOTFS_NAME]) rootfs_hashfile = files.get(ROOTFS_HASH_NAME) assert rootfs_hashfile rootfs_packaged_hash = open(rootfs_hashfile, 'rb').read().strip() if rootfs_calc_hash != rootfs_packaged_hash: msg = f"Hash mismatch (rootfs): calculated {rootfs_calc_hash!r} != "\ f"packaged {rootfs_packaged_hash!r}" LOG.error(msg) raise HashMismatch(msg) def bootfs_hash_callback(progress): progress_callback(progress / 3.0 + 0.66) bootfs = files.get(BOOT_NAME) assert bootfs bootfs_calc_hash = hash_file(bootfs, bootfs_hash_callback, file_size=sizes[BOOT_NAME]) bootfs_hashfile = files.get(BOOT_HASH_NAME) assert bootfs_hashfile bootfs_packaged_hash = open(bootfs_hashfile, 'rb').read().strip() if bootfs_calc_hash != bootfs_packaged_hash: msg = f"Hash mismatch (bootfs): calculated {bootfs_calc_hash!r} != "\ f"packged {bootfs_packaged_hash!r}" LOG.error(msg) raise HashMismatch(msg) return rootfs, bootfs
def test_unzip(downloaded_update_file): cb = mock.Mock() paths, sizes = file_actions.unzip_update(downloaded_update_file, cb, file_actions.UPDATE_FILES, file_actions.UPDATE_FILES) assert sorted(list(paths.keys())) == sorted(file_actions.UPDATE_FILES) for filename, path in paths.items(): assert os.path.dirname(path) == os.path.dirname(downloaded_update_file) with zipfile.ZipFile(downloaded_update_file) as zf: for filename, size in sizes.items(): assert zf.getinfo(filename).file_size == size for filename, path in paths.items(): assert zf.read(filename) == open(path, 'rb').read() # We should have callback calls for # - every chunk (including the fractional one at the end) of rootfs calls = sizes[file_actions.ROOTFS_NAME] // 1024 if calls * 1024 != sizes[file_actions.ROOTFS_NAME]: calls += 1 # - the two files that are less than a chunk calls += 2 assert cb.call_count == calls
def test_unzip_requires_sig(downloaded_update_file): cb = mock.Mock() with pytest.raises(file_actions.FileMissing): file_actions.unzip_update(downloaded_update_file, cb, file_actions.UPDATE_FILES, file_actions.UPDATE_FILES)
def test_unzip_does_not_require_sig(downloaded_update_file): cb = mock.Mock() file_actions.unzip_update(downloaded_update_file, cb, file_actions.UPDATE_FILES, [file_actions.ROOTFS_NAME, file_actions.ROOTFS_HASH_NAME])