shared/install: modernize unit_file_link

Also eliminate one more use of basename(), yay!
This commit is contained in:
Mike Yuan 2024-05-01 15:44:37 +08:00 committed by Luca Boccassi
parent e9e77e443d
commit 0bb4614adc

View file

@ -2466,31 +2466,36 @@ int unit_file_link(
size_t *n_changes) { size_t *n_changes) {
_cleanup_(lookup_paths_done) LookupPaths lp = {}; _cleanup_(lookup_paths_done) LookupPaths lp = {};
_cleanup_strv_free_ char **todo = NULL; _cleanup_ordered_hashmap_free_ OrderedHashmap *todo = NULL;
const char *config_path; const char *config_path;
size_t n_todo = 0;
int r; int r;
assert(scope >= 0); assert(scope >= 0);
assert(scope < _RUNTIME_SCOPE_MAX); assert(scope < _RUNTIME_SCOPE_MAX);
assert(changes);
assert(n_changes);
r = lookup_paths_init(&lp, scope, 0, root_dir); r = lookup_paths_init(&lp, scope, 0, root_dir);
if (r < 0) if (r < 0)
return r; return r;
config_path = (flags & UNIT_FILE_RUNTIME) ? lp.runtime_config : lp.persistent_config; config_path = FLAGS_SET(flags, UNIT_FILE_RUNTIME) ? lp.runtime_config : lp.persistent_config;
if (!config_path) if (!config_path)
return -ENXIO; return -ENXIO;
STRV_FOREACH(file, files) { STRV_FOREACH(file, files) {
_cleanup_free_ char *full = NULL; _cleanup_free_ char *fn = NULL, *path = NULL, *full = NULL;
struct stat st;
char *fn; if (ordered_hashmap_contains(todo, *file))
continue;
if (!path_is_absolute(*file)) if (!path_is_absolute(*file))
return install_changes_add(changes, n_changes, -EINVAL, *file, NULL); return install_changes_add(changes, n_changes, -EINVAL, *file, NULL);
fn = basename(*file); r = path_extract_filename(*file, &fn);
if (r < 0)
return install_changes_add(changes, n_changes, r, *file, NULL);
if (!unit_name_is_valid(fn, UNIT_NAME_ANY)) if (!unit_name_is_valid(fn, UNIT_NAME_ANY))
return install_changes_add(changes, n_changes, -EUCLEAN, *file, NULL); return install_changes_add(changes, n_changes, -EUCLEAN, *file, NULL);
@ -2498,10 +2503,7 @@ int unit_file_link(
if (!full) if (!full)
return -ENOMEM; return -ENOMEM;
if (lstat(full, &st) < 0) r = verify_regular_at(AT_FDCWD, full, /* follow = */ false);
return install_changes_add(changes, n_changes, -errno, *file, NULL);
r = stat_verify_regular(&st);
if (r < 0) if (r < 0)
return install_changes_add(changes, n_changes, r, *file, NULL); return install_changes_add(changes, n_changes, r, *file, NULL);
@ -2515,27 +2517,30 @@ int unit_file_link(
if (underneath_search_path(&lp, *file)) if (underneath_search_path(&lp, *file))
return install_changes_add(changes, n_changes, -ETXTBSY, *file, NULL); return install_changes_add(changes, n_changes, -ETXTBSY, *file, NULL);
if (!GREEDY_REALLOC0(todo, n_todo + 2)) path = strdup(*file);
if (!path)
return -ENOMEM; return -ENOMEM;
todo[n_todo] = strdup(*file); r = ordered_hashmap_ensure_put(&todo, &path_hash_ops_free_free, path, fn);
if (!todo[n_todo]) if (r < 0)
return -ENOMEM; return r;
assert(r > 0);
n_todo++; TAKE_PTR(path);
TAKE_PTR(fn);
} }
strv_uniq(todo);
r = 0; r = 0;
STRV_FOREACH(i, todo) {
const char *fn, *path;
ORDERED_HASHMAP_FOREACH_KEY(fn, path, todo) {
_cleanup_free_ char *new_path = NULL; _cleanup_free_ char *new_path = NULL;
new_path = path_make_absolute(basename(*i), config_path); new_path = path_make_absolute(fn, config_path);
if (!new_path) if (!new_path)
return -ENOMEM; return -ENOMEM;
RET_GATHER(r, create_symlink(&lp, *i, new_path, flags & UNIT_FILE_FORCE, changes, n_changes)); RET_GATHER(r, create_symlink(&lp, path, new_path, FLAGS_SET(flags, UNIT_FILE_FORCE), changes, n_changes));
} }
return r; return r;