portable: Don't refuse copying out instance of template that exists

There's no reason to refuse copying out capsule@abc.service even if
capsule@.service already exists on the host, so let's optionally not
search for templates if we can't find an instance when looking up
units and use it in portabled.
This commit is contained in:
Daan De Meyer
2026-01-16 21:25:10 +01:00
committed by Daan De Meyer
parent 4d388536ee
commit ae6dcaff0d
4 changed files with 14 additions and 13 deletions

View File

@@ -2047,7 +2047,7 @@ int portable_attach(
if (!FLAGS_SET(flags, PORTABLE_REATTACH) && !FLAGS_SET(flags, PORTABLE_FORCE_ATTACH))
HASHMAP_FOREACH(item, unit_files) {
r = unit_file_exists(scope, &paths, item->name);
r = unit_file_exists_full(scope, &paths, SEARCH_IGNORE_TEMPLATE, item->name, /* ret_path= */ NULL);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to determine whether unit '%s' exists on the host: %m", item->name);
if (r > 0)

View File

@@ -37,12 +37,6 @@
#define UNIT_FILE_FOLLOW_SYMLINK_MAX 64
typedef enum SearchFlags {
SEARCH_LOAD = 1 << 0,
SEARCH_FOLLOW_CONFIG_SYMLINKS = 1 << 1,
SEARCH_DROPIN = 1 << 2,
} SearchFlags;
typedef struct {
RuntimeScope scope;
OrderedHashmap *will_process;
@@ -1563,7 +1557,7 @@ static int unit_file_search(
assert(info->name);
if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
if (!FLAGS_SET(flags, SEARCH_IGNORE_TEMPLATE) && unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
r = unit_name_template(info->name, &template);
if (r < 0)
return r;
@@ -3242,7 +3236,7 @@ int unit_file_get_state(
int unit_file_exists_full(
RuntimeScope scope,
const LookupPaths *lp,
bool follow,
SearchFlags flags,
const char *name,
char **ret_path) {
@@ -3262,7 +3256,7 @@ int unit_file_exists_full(
&c,
lp,
name,
follow ? SEARCH_FOLLOW_CONFIG_SYMLINKS : 0,
flags,
ret_path ? &info : NULL,
/* changes= */ NULL,
/* n_changes= */ NULL);

View File

@@ -39,6 +39,13 @@ typedef enum UnitFileFlags {
_UNIT_FILE_FLAGS_MASK_PUBLIC = UNIT_FILE_RUNTIME|UNIT_FILE_PORTABLE|UNIT_FILE_FORCE,
} UnitFileFlags;
typedef enum SearchFlags {
SEARCH_LOAD = 1 << 0,
SEARCH_FOLLOW_CONFIG_SYMLINKS = 1 << 1,
SEARCH_DROPIN = 1 << 2,
SEARCH_IGNORE_TEMPLATE = 1 << 3, /* Don't look up the template if the instance does not exist. */
} SearchFlags;
/* type can be either one of the INSTALL_CHANGE_SYMLINK, INSTALL_CHANGE_UNLINK, … listed above, or a negative
* errno value.
*
@@ -184,12 +191,12 @@ int unit_file_get_state(RuntimeScope scope, const char *root_dir, const char *fi
int unit_file_exists_full(
RuntimeScope scope,
const LookupPaths *lp,
bool follow,
SearchFlags flags,
const char *name,
char **ret_path);
static inline int unit_file_exists(RuntimeScope scope, const LookupPaths *lp, const char *name) {
return unit_file_exists_full(scope, lp, false, name, NULL);
return unit_file_exists_full(scope, lp, 0, name, NULL);
}
int unit_file_get_list(RuntimeScope scope, const char *root_dir, char * const *states, char * const *patterns, Hashmap **ret);

View File

@@ -474,7 +474,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
_cleanup_free_ char *found_sshd_template_unit = NULL;
r = unit_file_exists_full(RUNTIME_SCOPE_SYSTEM, &lp,
/* follow = */ true,
SEARCH_FOLLOW_CONFIG_SYMLINKS,
"sshd@.service",
&found_sshd_template_unit);
if (r < 0)