Skip to content

Commit 9ff6156

Browse files
committed
portabled: refactor extraction/validation into a common helper
1 parent 239ac0c commit 9ff6156

File tree

1 file changed

+92
-77
lines changed

1 file changed

+92
-77
lines changed

src/portable/portable.c

Lines changed: 92 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -527,14 +527,18 @@ static int portable_extract_by_path(
527527
return 0;
528528
}
529529

530-
int portable_extract(
530+
static int extract_image_and_extensions(
531531
const char *name_or_path,
532532
char **matches,
533533
char **extension_image_paths,
534+
bool validate_sysext,
535+
Image **ret_image,
536+
OrderedHashmap **ret_extension_images,
534537
PortableMetadata **ret_os_release,
535538
Hashmap **ret_unit_files,
536539
sd_bus_error *error) {
537540

541+
_cleanup_free_ char *id = NULL, *version_id = NULL, *sysext_level = NULL;
538542
_cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
539543
_cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL;
540544
_cleanup_hashmap_free_ Hashmap *unit_files = NULL;
@@ -543,6 +547,9 @@ int portable_extract(
543547
int r;
544548

545549
assert(name_or_path);
550+
assert(matches);
551+
assert(ret_image);
552+
assert(ret_extension_images);
546553

547554
r = image_find_harder(IMAGE_PORTABLE, name_or_path, NULL, &image);
548555
if (r < 0)
@@ -573,17 +580,91 @@ int portable_extract(
573580
if (r < 0)
574581
return r;
575582

583+
/* If we are layering extension images on top of a runtime image, check that the os-release and extension-release metadata
584+
* match, otherwise reject it immediately as invalid, or it will fail when the units are started. */
585+
if (validate_sysext) {
586+
_cleanup_fclose_ FILE *f = NULL;
587+
588+
r = take_fdopen_unlocked(&os_release->fd, "r", &f);
589+
if (r < 0)
590+
return r;
591+
592+
r = parse_env_file(f, os_release->name,
593+
"ID", &id,
594+
"VERSION_ID", &version_id,
595+
"SYSEXT_LEVEL", &sysext_level);
596+
if (r < 0)
597+
return r;
598+
}
599+
576600
ORDERED_HASHMAP_FOREACH(ext, extension_images) {
601+
_cleanup_(portable_metadata_unrefp) PortableMetadata *extension_release_meta = NULL;
577602
_cleanup_hashmap_free_ Hashmap *extra_unit_files = NULL;
603+
_cleanup_strv_free_ char **extension_release = NULL;
604+
_cleanup_fclose_ FILE *f = NULL;
578605

579-
r = portable_extract_by_path(ext->path, /* path_is_extension= */ true, matches, NULL, &extra_unit_files, error);
606+
r = portable_extract_by_path(ext->path, /* path_is_extension= */ true, matches, &extension_release_meta, &extra_unit_files, error);
580607
if (r < 0)
581608
return r;
609+
582610
r = hashmap_move(unit_files, extra_unit_files);
583611
if (r < 0)
584612
return r;
613+
614+
if (!validate_sysext)
615+
continue;
616+
617+
r = take_fdopen_unlocked(&extension_release_meta->fd, "r", &f);
618+
if (r < 0)
619+
return r;
620+
621+
r = load_env_file_pairs(f, extension_release_meta->name, &extension_release);
622+
if (r < 0)
623+
return r;
624+
625+
r = extension_release_validate(ext->path, id, version_id, sysext_level, extension_release);
626+
if (r == 0)
627+
return sd_bus_error_set_errnof(error, SYNTHETIC_ERRNO(ESTALE), "Image %s extension-release metadata does not match the root's", ext->path);
628+
if (r < 0)
629+
return sd_bus_error_set_errnof(error, r, "Failed to compare image %s extension-release metadata with the root's os-release: %m", ext->path);
585630
}
586631

632+
*ret_image = TAKE_PTR(image);
633+
*ret_extension_images = TAKE_PTR(extension_images);
634+
if (ret_os_release)
635+
*ret_os_release = TAKE_PTR(os_release);
636+
if (ret_unit_files)
637+
*ret_unit_files = TAKE_PTR(unit_files);
638+
639+
return 0;
640+
}
641+
642+
int portable_extract(
643+
const char *name_or_path,
644+
char **matches,
645+
char **extension_image_paths,
646+
PortableMetadata **ret_os_release,
647+
Hashmap **ret_unit_files,
648+
sd_bus_error *error) {
649+
650+
_cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
651+
_cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL;
652+
_cleanup_hashmap_free_ Hashmap *unit_files = NULL;
653+
_cleanup_(image_unrefp) Image *image = NULL;
654+
int r;
655+
656+
r = extract_image_and_extensions(name_or_path,
657+
matches,
658+
extension_image_paths,
659+
/* validate_sysext= */ false,
660+
&image,
661+
&extension_images,
662+
&os_release,
663+
&unit_files,
664+
error);
665+
if (r < 0)
666+
return r;
667+
587668
if (hashmap_isempty(unit_files)) {
588669
_cleanup_free_ char *extensions = strv_join(extension_image_paths, ", ");
589670
if (!extensions)
@@ -1165,91 +1246,25 @@ int portable_attach(
11651246
size_t *n_changes,
11661247
sd_bus_error *error) {
11671248

1168-
_cleanup_free_ char *id = NULL, *version_id = NULL, *sysext_level = NULL;
1169-
_cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
11701249
_cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL;
11711250
_cleanup_hashmap_free_ Hashmap *unit_files = NULL;
11721251
_cleanup_(lookup_paths_free) LookupPaths paths = {};
11731252
_cleanup_(image_unrefp) Image *image = NULL;
11741253
PortableMetadata *item;
1175-
Image *ext;
1176-
char **p;
11771254
int r;
11781255

1179-
assert(name_or_path);
1180-
1181-
r = image_find_harder(IMAGE_PORTABLE, name_or_path, NULL, &image);
1182-
if (r < 0)
1183-
return r;
1184-
if (!strv_isempty(extension_image_paths)) {
1185-
extension_images = ordered_hashmap_new(&image_hash_ops);
1186-
if (!extension_images)
1187-
return -ENOMEM;
1188-
1189-
STRV_FOREACH(p, extension_image_paths) {
1190-
_cleanup_(image_unrefp) Image *new = NULL;
1191-
1192-
r = image_find_harder(IMAGE_PORTABLE, *p, NULL, &new);
1193-
if (r < 0)
1194-
return r;
1195-
1196-
r = ordered_hashmap_put(extension_images, new->name, new);
1197-
if (r < 0)
1198-
return r;
1199-
TAKE_PTR(new);
1200-
}
1201-
}
1202-
1203-
r = portable_extract_by_path(image->path, /* path_is_extension= */ false, matches, &os_release, &unit_files, error);
1256+
r = extract_image_and_extensions(name_or_path,
1257+
matches,
1258+
extension_image_paths,
1259+
/* validate_sysext= */ true,
1260+
&image,
1261+
&extension_images,
1262+
/* os_release= */ NULL,
1263+
&unit_files,
1264+
error);
12041265
if (r < 0)
12051266
return r;
12061267

1207-
/* If we are layering extension images on top of a runtime image, check that the os-release and extension-release metadata
1208-
* match, otherwise reject it immediately as invalid, or it will fail when the units are started. */
1209-
if (os_release) {
1210-
_cleanup_fclose_ FILE *f = NULL;
1211-
1212-
r = take_fdopen_unlocked(&os_release->fd, "r", &f);
1213-
if (r < 0)
1214-
return r;
1215-
1216-
r = parse_env_file(f, os_release->name,
1217-
"ID", &id,
1218-
"VERSION_ID", &version_id,
1219-
"SYSEXT_LEVEL", &sysext_level);
1220-
if (r < 0)
1221-
return r;
1222-
}
1223-
1224-
ORDERED_HASHMAP_FOREACH(ext, extension_images) {
1225-
_cleanup_(portable_metadata_unrefp) PortableMetadata *extension_release_meta = NULL;
1226-
_cleanup_hashmap_free_ Hashmap *extra_unit_files = NULL;
1227-
_cleanup_strv_free_ char **extension_release = NULL;
1228-
_cleanup_fclose_ FILE *f = NULL;
1229-
1230-
r = portable_extract_by_path(ext->path, /* path_is_extension= */ true, matches, &extension_release_meta, &extra_unit_files, error);
1231-
if (r < 0)
1232-
return r;
1233-
1234-
r = take_fdopen_unlocked(&extension_release_meta->fd, "r", &f);
1235-
if (r < 0)
1236-
return r;
1237-
1238-
r = load_env_file_pairs(f, extension_release_meta->name, &extension_release);
1239-
if (r < 0)
1240-
return r;
1241-
1242-
r = extension_release_validate(ext->path, id, version_id, sysext_level, extension_release);
1243-
if (r == 0)
1244-
return sd_bus_error_set_errnof(error, SYNTHETIC_ERRNO(ESTALE), "Image %s extension-release metadata does not match the root's", ext->path);
1245-
if (r < 0)
1246-
return sd_bus_error_set_errnof(error, r, "Failed to compare image %s extension-release metadata with the root's os-release: %m", ext->path);
1247-
1248-
r = hashmap_move(unit_files, extra_unit_files);
1249-
if (r < 0)
1250-
return r;
1251-
}
1252-
12531268
if (hashmap_isempty(unit_files)) {
12541269
_cleanup_free_ char *extensions = strv_join(extension_image_paths, ", ");
12551270
if (!extensions)

0 commit comments

Comments
 (0)