The rest of the basename()s are easy to drop.
}
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;
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;
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;
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)
}
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;
if (!strv_fnmatch_or_empty(patterns, de->d_name, FNM_NOESCAPE))
continue;
- if (hashmap_get(h, de->d_name))
- continue;
+ UnitFileState state;
- if (!IN_SET(de->d_type, DT_LNK, DT_REG))
+ 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;
- 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;
-
- if (!strv_isempty(states) &&
- !strv_contains(states, unit_file_state_to_string(f->state)))
- continue;
+ _cleanup_free_ char *unit_name = strdup(de->d_name);
+ if (!unit_name)
+ return -ENOMEM;
- 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;
}
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);
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");
if (!units)
return log_oom();
+ UnitFileList *u;
HASHMAP_FOREACH(u, h) {
if (!output_show_unit_file(u, NULL, NULL))
continue;
} 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);
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);
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);
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");
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;
/* 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");