On Fri, Feb 28, 2025 at 09:57:08PM +0200, Nir Soffer wrote:
> This test depends on TarFile.addfile() to add tar member header without
> writing the member data, which we write ourself using qemu-nbd. Python
> 3.13 changed the function in a backward incompatible way[1] to require a
> file object for tarinfo with non-zero size, breaking the test:
> 
>      -[{"name": "vm.ovf", "offset": 512, "size": 6}, {"name": "disk", 
> "offset": 1536, "size": 393216}]
>      +Traceback (most recent call last):
>      +  File "/home/stefanha/qemu/tests/qemu-iotests/302", line 118, in 
> <module>
>      +    tar.addfile(disk)
>      +    ~~~~~~~~~~~^^^^^^
>      +  File "/usr/lib64/python3.13/tarfile.py", line 2262, in addfile
>      +    raise ValueError("fileobj not provided for non zero-size regular 
> file")
>      +ValueError: fileobj not provided for non zero-size regular file
> 
> The new behavior makes sense for most users, but breaks our unusual
> usage. Fix the test to add the member header directly using public but
> undocumented attributes. This is more fragile but the test works again.
> 
> This also fixes a bug in the previous code - when calling addfile()
> without a fileobject, tar.offset points to the start of the member data
> instead of the end.
> 
> [1] https://github.com/python/cpython/pull/117988
> 
> Signed-off-by: Nir Soffer <nir...@gmail.com>


Reviewed-by: Eric Blake <ebl...@redhat.com>

> ---
>  tests/qemu-iotests/302 | 19 ++++++++++++++-----
>  1 file changed, 14 insertions(+), 5 deletions(-)
> 
> diff --git a/tests/qemu-iotests/302 b/tests/qemu-iotests/302
> index a6d79e727b..e980ec513f 100755
> --- a/tests/qemu-iotests/302
> +++ b/tests/qemu-iotests/302
> @@ -115,13 +115,22 @@ with tarfile.open(tar_file, "w") as tar:
>  
>      disk = tarfile.TarInfo("disk")
>      disk.size = actual_size
> -    tar.addfile(disk)
>  
> -    # 6. Shrink the tar to the actual size, aligned to 512 bytes.
> +    # Since python 3.13 we cannot use addfile() to create the member header.
> +    # Add the tarinfo directly using public but undocumented attributes.
>  
> -    tar_size = offset + (disk.size + 511) & ~511
> -    tar.fileobj.seek(tar_size)
> -    tar.fileobj.truncate(tar_size)
> +    buf = disk.tobuf(tar.format, tar.encoding, tar.errors)
> +    tar.fileobj.write(buf)
> +    tar.members.append(disk)
> +
> +    # Update the offset and position to the location of the next member.
> +
> +    tar.offset = offset + (disk.size + 511) & ~511
> +    tar.fileobj.seek(tar.offset)
> +
> +    # 6. Shrink the tar to the actual size.
> +
> +    tar.fileobj.truncate(tar.offset)
>  
>  with tarfile.open(tar_file) as tar:
>      members = [{"name": m.name, "size": m.size, "offset": m.offset_data}
> -- 
> 2.39.5 (Apple Git-154)
> 
> 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization:  qemu.org | libguestfs.org


Reply via email to