static bool unit_match(const char *unit, char **matches) {
const char *dot;
- char **i;
dot = strrchr(unit, '.');
if (!dot)
_cleanup_close_ int os_release_fd = -1;
_cleanup_free_ char *os_release_path = NULL;
const char *os_release_id;
- char **i;
int r;
/* Extracts the metadata from a directory tree 'where'. Extracts two kinds of information: the /etc/os-release
bool validate_sysext,
Image **ret_image,
OrderedHashmap **ret_extension_images,
+ OrderedHashmap **ret_extension_releases,
PortableMetadata **ret_os_release,
Hashmap **ret_unit_files,
char ***ret_valid_prefixes,
_cleanup_free_ char *id = NULL, *version_id = NULL, *sysext_level = NULL;
_cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
- _cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL;
+ _cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL, *extension_releases = NULL;
_cleanup_hashmap_free_ Hashmap *unit_files = NULL;
_cleanup_strv_free_ char **valid_prefixes = NULL;
_cleanup_(image_unrefp) Image *image = NULL;
return r;
if (!strv_isempty(extension_image_paths)) {
- char **p;
-
extension_images = ordered_hashmap_new(&image_hash_ops);
if (!extension_images)
return -ENOMEM;
+ if (ret_extension_releases) {
+ extension_releases = ordered_hashmap_new(&portable_metadata_hash_ops);
+ if (!extension_releases)
+ return -ENOMEM;
+ }
+
STRV_FOREACH(p, extension_image_paths) {
_cleanup_(image_unrefp) Image *new = NULL;
_cleanup_(portable_metadata_unrefp) PortableMetadata *extension_release_meta = NULL;
_cleanup_hashmap_free_ Hashmap *extra_unit_files = NULL;
_cleanup_strv_free_ char **extension_release = NULL;
+ _cleanup_close_ int extension_release_fd = -1;
_cleanup_fclose_ FILE *f = NULL;
const char *e;
if (r < 0)
return r;
- if (!validate_sysext && !ret_valid_prefixes)
+ if (!validate_sysext && !ret_valid_prefixes && !ret_extension_releases)
continue;
- r = take_fdopen_unlocked(&extension_release_meta->fd, "r", &f);
+ /* We need to keep the fd valid, to return the PortableMetadata to the caller. */
+ extension_release_fd = fd_reopen(extension_release_meta->fd, O_CLOEXEC|O_RDONLY);
+ if (extension_release_fd < 0)
+ return extension_release_fd;
+
+ r = take_fdopen_unlocked(&extension_release_fd, "r", &f);
if (r < 0)
return r;
if (r < 0)
return r;
}
+
+ if (ret_extension_releases) {
+ r = ordered_hashmap_put(extension_releases, ext->name, extension_release_meta);
+ if (r < 0)
+ return r;
+ TAKE_PTR(extension_release_meta);
+ }
}
strv_sort(valid_prefixes);
*ret_image = TAKE_PTR(image);
if (ret_extension_images)
*ret_extension_images = TAKE_PTR(extension_images);
+ if (ret_extension_releases)
+ *ret_extension_releases = TAKE_PTR(extension_releases);
if (ret_os_release)
*ret_os_release = TAKE_PTR(os_release);
if (ret_unit_files)
char **matches,
char **extension_image_paths,
PortableMetadata **ret_os_release,
+ OrderedHashmap **ret_extension_releases,
Hashmap **ret_unit_files,
char ***ret_valid_prefixes,
sd_bus_error *error) {
_cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
- _cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL;
+ _cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL, *extension_releases = NULL;
_cleanup_hashmap_free_ Hashmap *unit_files = NULL;
_cleanup_(strv_freep) char **valid_prefixes = NULL;
_cleanup_(image_unrefp) Image *image = NULL;
/* validate_sysext= */ false,
&image,
&extension_images,
+ &extension_releases,
&os_release,
&unit_files,
ret_valid_prefixes ? &valid_prefixes : NULL,
if (ret_os_release)
*ret_os_release = TAKE_PTR(os_release);
+ if (ret_extension_releases)
+ *ret_extension_releases = TAKE_PTR(extension_releases);
if (ret_unit_files)
*ret_unit_files = TAKE_PTR(unit_files);
if (ret_valid_prefixes)
r = copy_file_atomic(from, dropin, 0644, 0, 0, COPY_REFLINK);
if (r < 0)
- return log_debug_errno(r, "Failed to copy %s %s %s: %m", from, special_glyph(SPECIAL_GLYPH_ARROW), dropin);
+ return log_debug_errno(r, "Failed to copy %s %s %s: %m", from, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), dropin);
(void) portable_changes_add(changes, n_changes, PORTABLE_COPY, dropin, from);
} else {
if (symlink(from, dropin) < 0)
- return log_debug_errno(errno, "Failed to link %s %s %s: %m", from, special_glyph(SPECIAL_GLYPH_ARROW), dropin);
+ return log_debug_errno(errno, "Failed to link %s %s %s: %m", from, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), dropin);
(void) portable_changes_add(changes, n_changes, PORTABLE_SYMLINK, dropin, from);
}
(void) mkdir_parents(sl, 0755);
if (symlink(image_path, sl) < 0)
- return log_debug_errno(errno, "Failed to link %s %s %s: %m", image_path, special_glyph(SPECIAL_GLYPH_ARROW), sl);
+ return log_debug_errno(errno, "Failed to link %s %s %s: %m", image_path, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), sl);
(void) portable_changes_add(changes, n_changes, PORTABLE_SYMLINK, sl, image_path);
return 0;
}
static bool prefix_matches_compatible(char **matches, char **valid_prefixes) {
- char **m;
-
/* Checks if all 'matches' are included in the list of 'valid_prefixes' */
STRV_FOREACH(m, matches)
/* validate_sysext= */ true,
&image,
&extension_images,
+ /* extension_releases= */ NULL,
/* os_release= */ NULL,
&unit_files,
&valid_prefixes,
static bool marker_matches_images(const char *marker, const char *name_or_path, char **extension_image_paths) {
_cleanup_strv_free_ char **root_and_extensions = NULL;
- char **image_name_or_path;
const char *a;
int r;
static int portable_get_state_internal(
sd_bus *bus,
const char *name_or_path,
+ char **extension_image_paths,
PortableFlags flags,
PortableState *ret,
sd_bus_error *error) {
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
continue;
- r = test_chroot_dropin(d, where, de->d_name, name_or_path, NULL, NULL);
+ r = test_chroot_dropin(d, where, de->d_name, name_or_path, extension_image_paths, NULL);
if (r < 0)
return r;
if (r == 0)
int portable_get_state(
sd_bus *bus,
const char *name_or_path,
+ char **extension_image_paths,
PortableFlags flags,
PortableState *ret,
sd_bus_error *error) {
/* We look for matching units twice: once in the regular directories, and once in the runtime directories — but
* the latter only if we didn't find anything in the former. */
- r = portable_get_state_internal(bus, name_or_path, flags & ~PORTABLE_RUNTIME, &state, error);
+ r = portable_get_state_internal(bus, name_or_path, extension_image_paths, flags & ~PORTABLE_RUNTIME, &state, error);
if (r < 0)
return r;
if (state == PORTABLE_DETACHED) {
- r = portable_get_state_internal(bus, name_or_path, flags | PORTABLE_RUNTIME, &state, error);
+ r = portable_get_state_internal(bus, name_or_path, extension_image_paths, flags | PORTABLE_RUNTIME, &state, error);
if (r < 0)
return r;
}