1850a1951SThomas Huth# Utilities for python-based QEMU tests 2850a1951SThomas Huth# 3850a1951SThomas Huth# Copyright 2024 Red Hat, Inc. 4850a1951SThomas Huth# 5850a1951SThomas Huth# Authors: 6850a1951SThomas Huth# Thomas Huth <thuth@redhat.com> 7850a1951SThomas Huth# 8850a1951SThomas Huth# This work is licensed under the terms of the GNU GPL, version 2 or 9850a1951SThomas Huth# later. See the COPYING file in the top-level directory. 10850a1951SThomas Huth 11d5674412SThomas Huthimport gzip 12e2e9fd25SThomas Huthimport lzma 13e2e9fd25SThomas Huthimport os 14e2e9fd25SThomas Huthimport shutil 1534917eadSPhilippe Mathieu-Daudéimport subprocess 16850a1951SThomas Huthimport tarfile 17850a1951SThomas Huth 18*f7d6b772SThomas Huth""" 19*f7d6b772SThomas HuthRound up to next power of 2 20*f7d6b772SThomas Huth""" 21*f7d6b772SThomas Huthdef pow2ceil(x): 22*f7d6b772SThomas Huth return 1 if x == 0 else 2**(x - 1).bit_length() 23*f7d6b772SThomas Huth 24*f7d6b772SThomas Huthdef file_truncate(path, size): 25*f7d6b772SThomas Huth if size != os.path.getsize(path): 26*f7d6b772SThomas Huth with open(path, 'ab+') as fd: 27*f7d6b772SThomas Huth fd.truncate(size) 28*f7d6b772SThomas Huth 29*f7d6b772SThomas Huth""" 30*f7d6b772SThomas HuthExpand file size to next power of 2 31*f7d6b772SThomas Huth""" 32*f7d6b772SThomas Huthdef image_pow2ceil_expand(path): 33*f7d6b772SThomas Huth size = os.path.getsize(path) 34*f7d6b772SThomas Huth size_aligned = pow2ceil(size) 35*f7d6b772SThomas Huth if size != size_aligned: 36*f7d6b772SThomas Huth with open(path, 'ab+') as fd: 37*f7d6b772SThomas Huth fd.truncate(size_aligned) 38*f7d6b772SThomas Huth 39850a1951SThomas Huthdef archive_extract(archive, dest_dir, member=None): 40850a1951SThomas Huth with tarfile.open(archive) as tf: 41850a1951SThomas Huth if hasattr(tarfile, 'data_filter'): 42850a1951SThomas Huth tf.extraction_filter = getattr(tarfile, 'data_filter', 43850a1951SThomas Huth (lambda member, path: member)) 44850a1951SThomas Huth if member: 45850a1951SThomas Huth tf.extract(member=member, path=dest_dir) 46850a1951SThomas Huth else: 47850a1951SThomas Huth tf.extractall(path=dest_dir) 48e2e9fd25SThomas Huth 49d5674412SThomas Huthdef gzip_uncompress(gz_path, output_path): 50d5674412SThomas Huth if os.path.exists(output_path): 51d5674412SThomas Huth return 52d5674412SThomas Huth with gzip.open(gz_path, 'rb') as gz_in: 53d5674412SThomas Huth try: 54d5674412SThomas Huth with open(output_path, 'wb') as raw_out: 55d5674412SThomas Huth shutil.copyfileobj(gz_in, raw_out) 56d5674412SThomas Huth except: 57d5674412SThomas Huth os.remove(output_path) 58d5674412SThomas Huth raise 59d5674412SThomas Huth 60e2e9fd25SThomas Huthdef lzma_uncompress(xz_path, output_path): 61e2e9fd25SThomas Huth if os.path.exists(output_path): 62e2e9fd25SThomas Huth return 63e2e9fd25SThomas Huth with lzma.open(xz_path, 'rb') as lzma_in: 64e2e9fd25SThomas Huth try: 65e2e9fd25SThomas Huth with open(output_path, 'wb') as raw_out: 66e2e9fd25SThomas Huth shutil.copyfileobj(lzma_in, raw_out) 67e2e9fd25SThomas Huth except: 68e2e9fd25SThomas Huth os.remove(output_path) 69e2e9fd25SThomas Huth raise 7034917eadSPhilippe Mathieu-Daudé 7134917eadSPhilippe Mathieu-Daudédef cpio_extract(cpio_handle, output_path): 7234917eadSPhilippe Mathieu-Daudé cwd = os.getcwd() 7334917eadSPhilippe Mathieu-Daudé os.chdir(output_path) 7434917eadSPhilippe Mathieu-Daudé subprocess.run(['cpio', '-i'], 7534917eadSPhilippe Mathieu-Daudé input=cpio_handle.read(), 7634917eadSPhilippe Mathieu-Daudé stderr=subprocess.DEVNULL) 7734917eadSPhilippe Mathieu-Daudé os.chdir(cwd) 78