1
0
mirror of https://github.com/systemd/systemd synced 2024-07-08 20:15:55 +00:00

shared/install: modernize unit_file_get_list, use key destructor

The rest of the basename()s are easy to drop.
This commit is contained in:
Mike Yuan 2024-05-01 16:26:05 +08:00 committed by Luca Boccassi
parent 0bb4614adc
commit ca3c95c1c5
7 changed files with 55 additions and 69 deletions

View File

@ -2187,9 +2187,8 @@ static int method_enqueue_marked_jobs(sd_bus_message *message, void *userdata, s
}
static int list_unit_files_by_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states, char **patterns) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = ASSERT_PTR(userdata);
UnitFileList *item;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_hashmap_free_ Hashmap *h = NULL;
int r;
@ -2205,11 +2204,7 @@ static int list_unit_files_by_patterns(sd_bus_message *message, void *userdata,
if (r < 0)
return r;
h = hashmap_new(&unit_file_list_hash_ops_free);
if (!h)
return -ENOMEM;
r = unit_file_get_list(m->runtime_scope, NULL, h, states, patterns);
r = unit_file_get_list(m->runtime_scope, /* root_dir = */ NULL, states, patterns, &h);
if (r < 0)
return r;
@ -2217,8 +2212,8 @@ static int list_unit_files_by_patterns(sd_bus_message *message, void *userdata,
if (r < 0)
return r;
UnitFileList *item;
HASHMAP_FOREACH(item, h) {
r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
if (r < 0)
return r;

View File

@ -3714,27 +3714,24 @@ static UnitFileList* unit_file_list_free(UnitFileList *f) {
DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free);
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
unit_file_list_hash_ops_free,
char,
string_hash_func,
string_compare_func,
UnitFileList,
unit_file_list_free);
DEFINE_PRIVATE_HASH_OPS_FULL(unit_file_list_hash_ops_free_free,
char, string_hash_func, string_compare_func, free,
UnitFileList, unit_file_list_free);
int unit_file_get_list(
RuntimeScope scope,
const char *root_dir,
Hashmap *h,
char **states,
char **patterns) {
char * const *states,
char * const *patterns,
Hashmap **ret) {
_cleanup_(lookup_paths_done) LookupPaths lp = {};
_cleanup_hashmap_free_ Hashmap *h = NULL;
int r;
assert(scope >= 0);
assert(scope < _RUNTIME_SCOPE_MAX);
assert(h);
assert(ret);
r = lookup_paths_init(&lp, scope, 0, root_dir);
if (r < 0)
@ -3756,7 +3753,11 @@ int unit_file_get_list(
}
FOREACH_DIRENT(de, d, return -errno) {
_cleanup_(unit_file_list_freep) UnitFileList *f = NULL;
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
continue;
if (hashmap_contains(h, de->d_name))
continue;
if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
continue;
@ -3764,36 +3765,42 @@ int unit_file_get_list(
if (!strv_fnmatch_or_empty(patterns, de->d_name, FNM_NOESCAPE))
continue;
if (hashmap_get(h, de->d_name))
UnitFileState state;
r = unit_file_lookup_state(scope, &lp, de->d_name, &state);
if (r < 0)
state = UNIT_FILE_BAD;
if (!strv_isempty(states) &&
!strv_contains(states, unit_file_state_to_string(state)))
continue;
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
continue;
f = new0(UnitFileList, 1);
_cleanup_(unit_file_list_freep) UnitFileList *f = new(UnitFileList, 1);
if (!f)
return -ENOMEM;
f->path = path_make_absolute(de->d_name, *dirname);
*f = (UnitFileList) {
.path = path_make_absolute(de->d_name, *dirname),
.state = state,
};
if (!f->path)
return -ENOMEM;
r = unit_file_lookup_state(scope, &lp, de->d_name, &f->state);
if (r < 0)
f->state = UNIT_FILE_BAD;
_cleanup_free_ char *unit_name = strdup(de->d_name);
if (!unit_name)
return -ENOMEM;
if (!strv_isempty(states) &&
!strv_contains(states, unit_file_state_to_string(f->state)))
continue;
r = hashmap_put(h, basename(f->path), f);
r = hashmap_ensure_put(&h, &unit_file_list_hash_ops_free_free, unit_name, f);
if (r < 0)
return r;
assert(r > 0);
f = NULL; /* prevent cleanup */
TAKE_PTR(unit_name);
TAKE_PTR(f);
}
}
*ret = TAKE_PTR(h);
return 0;
}

View File

@ -199,9 +199,7 @@ static inline int unit_file_exists(RuntimeScope scope, const LookupPaths *paths,
return unit_file_exists_full(scope, paths, name, NULL);
}
int unit_file_get_list(RuntimeScope scope, const char *root_dir, Hashmap *h, char **states, char **patterns);
extern const struct hash_ops unit_file_list_hash_ops_free;
int unit_file_get_list(RuntimeScope scope, const char *root_dir, char * const *states, char * const *patterns, Hashmap **ret);
InstallChangeType install_changes_add(InstallChange **changes, size_t *n_changes, InstallChangeType type, const char *path, const char *source);
void install_changes_free(InstallChange *changes, size_t n_changes);

View File

@ -142,23 +142,15 @@ static int output_unit_file_list(const UnitFileList *units, unsigned c) {
int verb_list_unit_files(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_free_ UnitFileList *units = NULL;
_cleanup_hashmap_free_ Hashmap *h = NULL;
_cleanup_free_ UnitFileList *units = NULL;
unsigned c = 0;
const char *state;
char *path;
int r;
bool fallback = false;
if (install_client_side()) {
UnitFileList *u;
unsigned n_units;
h = hashmap_new(&unit_file_list_hash_ops_free);
if (!h)
return log_oom();
r = unit_file_get_list(arg_runtime_scope, arg_root, h, arg_states, strv_skip(argv, 1));
r = unit_file_get_list(arg_runtime_scope, arg_root, arg_states, strv_skip(argv, 1), &h);
if (r < 0)
return log_error_errno(r, "Failed to get unit file list: %m");
@ -168,6 +160,7 @@ int verb_list_unit_files(int argc, char *argv[], void *userdata) {
if (!units)
return log_oom();
UnitFileList *u;
HASHMAP_FOREACH(u, h) {
if (!output_show_unit_file(u, NULL, NULL))
continue;
@ -179,6 +172,8 @@ int verb_list_unit_files(int argc, char *argv[], void *userdata) {
} else {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *path, *state;
bool fallback = false;
sd_bus *bus;
r = acquire_bus(BUS_MANAGER, &bus);
@ -201,19 +196,17 @@ int verb_list_unit_files(int argc, char *argv[], void *userdata) {
return log_error_errno(r, "Failed to append unit dependencies: %m");
r = sd_bus_message_append_strv(m, names_with_deps);
if (r < 0)
return bus_log_create_error(r);
} else {
} else
r = sd_bus_message_append_strv(m, strv_skip(argv, 1));
if (r < 0)
return bus_log_create_error(r);
}
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0 && sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) {
/* Fallback to legacy ListUnitFiles method */
log_debug_errno(r, "Unable to list unit files through ListUnitFilesByPatterns, falling back to ListUnitsFiles method.");
fallback = true;
log_debug_errno(r, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error, r));
m = sd_bus_message_unref(m);
sd_bus_error_free(&error);
@ -235,16 +228,15 @@ int verb_list_unit_files(int argc, char *argv[], void *userdata) {
if (!GREEDY_REALLOC(units, c + 1))
return log_oom();
units[c] = (struct UnitFileList) {
path,
unit_file_state_from_string(state)
units[c] = (UnitFileList) {
.path = (char*) path,
.state = unit_file_state_from_string(state),
};
if (output_show_unit_file(&units[c],
fallback ? arg_states : NULL,
fallback ? strv_skip(argv, 1) : NULL))
c++;
}
if (r < 0)
return bus_log_parse_error(r);

View File

@ -680,8 +680,7 @@ TEST(preset_and_list) {
assert_se(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
assert_se(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "preset-ignore.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
assert_se(h = hashmap_new(&unit_file_list_hash_ops_free));
assert_se(unit_file_get_list(RUNTIME_SCOPE_SYSTEM, root, h, NULL, NULL) >= 0);
ASSERT_OK(unit_file_get_list(RUNTIME_SCOPE_SYSTEM, root, NULL, NULL, &h));
p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
q = strjoina(root, "/usr/lib/systemd/system/preset-no.service");

View File

@ -31,9 +31,7 @@ int main(int argc, char* argv[]) {
test_setup_logging(LOG_DEBUG);
h = hashmap_new(&unit_file_list_hash_ops_free);
r = unit_file_get_list(RUNTIME_SCOPE_SYSTEM, NULL, h, NULL, NULL);
assert_se(r == 0);
ASSERT_OK(unit_file_get_list(RUNTIME_SCOPE_SYSTEM, NULL, NULL, NULL, &h));
HASHMAP_FOREACH(p, h) {
UnitFileState s = _UNIT_FILE_STATE_INVALID;

View File

@ -42,15 +42,12 @@ STATIC_DESTRUCTOR_REGISTER(runtime_dir, rm_rf_physical_and_freep);
/* For testing type compatibility. */
_unused_ ConfigPerfItemLookup unused_lookup = load_fragment_gperf_lookup;
TEST_RET(unit_file_get_set) {
TEST_RET(unit_file_get_list) {
int r;
_cleanup_hashmap_free_ Hashmap *h = NULL;
UnitFileList *p;
h = hashmap_new(&unit_file_list_hash_ops_free);
assert_se(h);
r = unit_file_get_list(RUNTIME_SCOPE_SYSTEM, NULL, h, NULL, NULL);
r = unit_file_get_list(RUNTIME_SCOPE_SYSTEM, NULL, NULL, NULL, &h);
if (IN_SET(r, -EPERM, -EACCES))
return log_tests_skipped_errno(r, "unit_file_get_list");