From ed22b5a77f39b7c1c901c357760d9596e2c9028b Mon Sep 17 00:00:00 2001 From: lucia-huang7 <226875132+lucia-huang7@users.noreply.github.com> Date: Sat, 15 Aug 2026 19:31:29 -0500 Subject: [PATCH] discover-image: rename image sidecar files from old paths image_rename() updated the Image object name and path before computing the source paths for auxiliary files. As a result, the auxiliary rename loop looked for files with the new image name, while existing sidecars such as .roothash, .verity, and .raw.tpmstate still used the old image name. Delay updating the Image object until after renaming its settings and auxiliary files. This lets image_auxiliary_path() resolve existing sidecars from the old image name while rename_auxiliary_file() assigns the new name. Extend the import test raw image rename coverage to check representative sidecars are renamed together with the image. --- src/shared/discover-image.c | 25 +++++++++++++++---------- test/units/TEST-25-IMPORT.sh | 27 +++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/shared/discover-image.c b/src/shared/discover-image.c index a8246e3b54..419246d733 100644 --- a/src/shared/discover-image.c +++ b/src/shared/discover-image.c @@ -26,6 +26,7 @@ #include "dissect-image.h" #include "env-file.h" #include "env-util.h" +#include "errno-util.h" #include "extension-util.h" #include "fd-util.h" #include "fs-util.h" @@ -1504,7 +1505,7 @@ int image_rename(Image *i, const char *new_name, RuntimeScope scope) { _cleanup_free_ char *new_path = NULL, *nn = NULL; _cleanup_strv_free_ char **settings = NULL; unsigned file_attr = 0; - int r; + int r, ret = 0; assert(i); @@ -1586,27 +1587,31 @@ int image_rename(Image *i, const char *new_name, RuntimeScope scope) { if (file_attr & FS_IMMUTABLE_FL) (void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL); - free_and_replace(i->path, new_path); - free_and_replace(i->name, nn); - STRV_FOREACH(j, settings) { r = rename_auxiliary_file(*j, new_name, ".nspawn"); if (r < 0 && r != -ENOENT) - log_debug_errno(r, "Failed to rename settings file %s, ignoring: %m", *j); + log_debug_errno(r, "Failed to rename settings file '%s', ignoring: %m", *j); } NULSTR_FOREACH(suffix, auxiliary_suffixes_nulstr) { _cleanup_free_ char *aux = NULL; + r = image_auxiliary_path(i, suffix, &aux); - if (r < 0) - return r; + if (r < 0) { + RET_GATHER(ret, log_debug_errno(r, "Failed to generate auxiliary path for image '%s' suffix '%s': %m", + i->name, suffix)); + continue; + } r = rename_auxiliary_file(aux, new_name, suffix); if (r < 0 && r != -ENOENT) - log_debug_errno(r, "Failed to rename roothash file %s, ignoring: %m", aux); + log_debug_errno(r, "Failed to rename auxiliary file '%s', ignoring: %m", aux); } - return 0; + free_and_replace(i->path, new_path); + free_and_replace(i->name, nn); + + return ret; } static int clone_auxiliary_file(const char *path, const char *new_name, const char *suffix) { @@ -1830,7 +1835,7 @@ int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope sco r = clone_auxiliary_file(aux, new_name, suffix); if (r < 0 && r != -ENOENT) - log_debug_errno(r, "Failed to clone root hash file %s, ignoring: %m", aux); + log_debug_errno(r, "Failed to clone auxiliary file '%s', ignoring: %m", aux); } return 0; diff --git a/test/units/TEST-25-IMPORT.sh b/test/units/TEST-25-IMPORT.sh index 51c163aa70..12a56a8643 100755 --- a/test/units/TEST-25-IMPORT.sh +++ b/test/units/TEST-25-IMPORT.sh @@ -25,17 +25,32 @@ cmp /var/tmp/testimage.raw /var/tmp/testimage2.raw rm /var/tmp/testimage2.raw # Test clone +printf 'hash\n' >/var/lib/machines/testimage.roothash +printf 'verity\n' >/var/lib/machines/testimage.verity +printf 'tpmstate\n' >/var/lib/machines/testimage.raw.tpmstate machinectl clone testimage testimage3 test -f /var/lib/machines/testimage3.raw +test -f /var/lib/machines/testimage3.roothash +test -f /var/lib/machines/testimage3.verity +test -f /var/lib/machines/testimage3.raw.tpmstate machinectl image-status testimage3 test -f /var/lib/machines/testimage.raw +test -f /var/lib/machines/testimage.roothash +test -f /var/lib/machines/testimage.verity +test -f /var/lib/machines/testimage.raw.tpmstate machinectl image-status testimage cmp /var/tmp/testimage.raw /var/lib/machines/testimage.raw cmp /var/tmp/testimage.raw /var/lib/machines/testimage3.raw +grep -Fx hash /var/lib/machines/testimage3.roothash +grep -Fx verity /var/lib/machines/testimage3.verity +grep -Fx tpmstate /var/lib/machines/testimage3.raw.tpmstate # Test removal machinectl remove testimage test ! -f /var/lib/machines/testimage.raw +test ! -f /var/lib/machines/testimage.roothash +test ! -f /var/lib/machines/testimage.verity +test ! -f /var/lib/machines/testimage.raw.tpmstate (! machinectl image-status testimage) # Test export of clone @@ -46,10 +61,19 @@ rm /var/tmp/testimage3.raw # Test rename machinectl rename testimage3 testimage4 test -f /var/lib/machines/testimage4.raw +test -f /var/lib/machines/testimage4.roothash +test -f /var/lib/machines/testimage4.verity +test -f /var/lib/machines/testimage4.raw.tpmstate machinectl image-status testimage4 test ! -f /var/lib/machines/testimage3.raw +test ! -f /var/lib/machines/testimage3.roothash +test ! -f /var/lib/machines/testimage3.verity +test ! -f /var/lib/machines/testimage3.raw.tpmstate (! machinectl image-status testimage3) cmp /var/tmp/testimage.raw /var/lib/machines/testimage4.raw +grep -Fx hash /var/lib/machines/testimage4.roothash +grep -Fx verity /var/lib/machines/testimage4.verity +grep -Fx tpmstate /var/lib/machines/testimage4.raw.tpmstate # Test export of rename machinectl export-raw testimage4 /var/tmp/testimage4.raw @@ -59,6 +83,9 @@ rm /var/tmp/testimage4.raw # Test removal machinectl remove testimage4 test ! -f /var/lib/machines/testimage4.raw +test ! -f /var/lib/machines/testimage4.roothash +test ! -f /var/lib/machines/testimage4.verity +test ! -f /var/lib/machines/testimage4.raw.tpmstate (! machinectl image-status testimage4) # → And now, let's test directory trees ← #