mirror of
https://github.com/systemd/systemd
synced 2024-10-06 16:21:34 +00:00
Merge pull request #32603 from YHNdnzj/install-basename
shared/install: modernize and eliminate the use of basename()
This commit is contained in:
commit
29d5da5fef
|
@ -699,7 +699,7 @@ static int add_names(
|
|||
|
||||
if (inst_fragment &&
|
||||
fragment_basename &&
|
||||
!streq(basename(inst_fragment), fragment_basename)) {
|
||||
!path_equal_filename(inst_fragment, fragment_basename)) {
|
||||
log_debug("Instance %s has fragment %s and is not an alias of %s.",
|
||||
inst, inst_fragment, unit_name);
|
||||
continue;
|
||||
|
|
|
@ -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;
|
||||
|
@ -2425,7 +2420,7 @@ static int reply_install_changes_and_free(
|
|||
static int method_enable_unit_files_generic(
|
||||
sd_bus_message *message,
|
||||
Manager *m,
|
||||
int (*call)(RuntimeScope scope, UnitFileFlags flags, const char *root_dir, char *files[], InstallChange **changes, size_t *n_changes),
|
||||
int (*call)(RuntimeScope scope, UnitFileFlags flags, const char *root_dir, char * const *files, InstallChange **changes, size_t *n_changes),
|
||||
bool carries_install_info,
|
||||
sd_bus_error *error) {
|
||||
|
||||
|
@ -2490,7 +2485,7 @@ static int method_link_unit_files(sd_bus_message *message, void *userdata, sd_bu
|
|||
return method_enable_unit_files_generic(message, userdata, unit_file_link, /* carries_install_info = */ false, error);
|
||||
}
|
||||
|
||||
static int unit_file_preset_without_mode(RuntimeScope scope, UnitFileFlags flags, const char *root_dir, char **files, InstallChange **changes, size_t *n_changes) {
|
||||
static int unit_file_preset_without_mode(RuntimeScope scope, UnitFileFlags flags, const char *root_dir, char * const *files, InstallChange **changes, size_t *n_changes) {
|
||||
return unit_file_preset(scope, flags, root_dir, files, UNIT_FILE_PRESET_FULL, changes, n_changes);
|
||||
}
|
||||
|
||||
|
@ -2550,7 +2545,7 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use
|
|||
static int method_disable_unit_files_generic(
|
||||
sd_bus_message *message,
|
||||
Manager *m,
|
||||
int (*call)(RuntimeScope scope, UnitFileFlags flags, const char *root_dir, char *files[], InstallChange **changes, size_t *n_changes),
|
||||
int (*call)(RuntimeScope scope, UnitFileFlags flags, const char *root_dir, char * const *files, InstallChange **changes, size_t *n_changes),
|
||||
bool carries_install_info,
|
||||
sd_bus_error *error) {
|
||||
|
||||
|
|
|
@ -596,7 +596,7 @@ static int normalize_portable_changes(
|
|||
bool found = false;
|
||||
|
||||
for (size_t j = 0; j < n_changes_attached; ++j)
|
||||
if (streq(basename(changes_detached[i].path), basename(changes_attached[j].path))) {
|
||||
if (path_equal_filename(changes_detached[i].path, changes_attached[j].path)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -23,39 +23,48 @@
|
|||
#include "strv.h"
|
||||
#include "unit-name.h"
|
||||
|
||||
int drop_in_file(const char *dir, const char *unit, unsigned level,
|
||||
const char *name, char **ret_p, char **ret_q) {
|
||||
int drop_in_file(
|
||||
const char *dir,
|
||||
const char *unit,
|
||||
unsigned level,
|
||||
const char *name,
|
||||
char **ret_unit_dir,
|
||||
char **ret_path) {
|
||||
|
||||
char prefix[DECIMAL_STR_MAX(unsigned) + 1] = {};
|
||||
_cleanup_free_ char *b = NULL, *p = NULL, *q = NULL;
|
||||
_cleanup_free_ char *n = NULL, *unit_dir = NULL, *path = NULL;
|
||||
|
||||
assert(dir);
|
||||
assert(unit);
|
||||
assert(name);
|
||||
assert(ret_p);
|
||||
assert(ret_q);
|
||||
assert(ret_unit_dir);
|
||||
assert(ret_path);
|
||||
|
||||
n = xescape(name, "/.");
|
||||
if (!n)
|
||||
return -ENOMEM;
|
||||
if (!filename_is_valid(n))
|
||||
return -EINVAL;
|
||||
|
||||
if (level != UINT_MAX)
|
||||
xsprintf(prefix, "%u-", level);
|
||||
|
||||
b = xescape(name, "/.");
|
||||
if (!b)
|
||||
unit_dir = path_join(dir, strjoina(unit, ".d"));
|
||||
path = strjoin(unit_dir, "/", prefix, n, ".conf");
|
||||
if (!unit_dir || !path)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!filename_is_valid(b))
|
||||
return -EINVAL;
|
||||
|
||||
p = strjoin(dir, "/", unit, ".d");
|
||||
q = strjoin(p, "/", prefix, b, ".conf");
|
||||
if (!p || !q)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret_p = TAKE_PTR(p);
|
||||
*ret_q = TAKE_PTR(q);
|
||||
*ret_unit_dir = TAKE_PTR(unit_dir);
|
||||
*ret_path = TAKE_PTR(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_drop_in(const char *dir, const char *unit, unsigned level,
|
||||
const char *name, const char *data) {
|
||||
int write_drop_in(
|
||||
const char *dir,
|
||||
const char *unit,
|
||||
unsigned level,
|
||||
const char *name,
|
||||
const char *data) {
|
||||
|
||||
_cleanup_free_ char *p = NULL, *q = NULL;
|
||||
int r;
|
||||
|
@ -73,9 +82,14 @@ int write_drop_in(const char *dir, const char *unit, unsigned level,
|
|||
return write_string_file_atomic_label(q, data);
|
||||
}
|
||||
|
||||
int write_drop_in_format(const char *dir, const char *unit, unsigned level,
|
||||
const char *name, const char *format, ...) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int write_drop_in_format(
|
||||
const char *dir,
|
||||
const char *unit,
|
||||
unsigned level,
|
||||
const char *name,
|
||||
const char *format, ...) {
|
||||
|
||||
_cleanup_free_ char *content = NULL;
|
||||
va_list ap;
|
||||
int r;
|
||||
|
||||
|
@ -85,13 +99,13 @@ int write_drop_in_format(const char *dir, const char *unit, unsigned level,
|
|||
assert(format);
|
||||
|
||||
va_start(ap, format);
|
||||
r = vasprintf(&p, format, ap);
|
||||
r = vasprintf(&content, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
return write_drop_in(dir, unit, level, name, p);
|
||||
return write_drop_in(dir, unit, level, name, content);
|
||||
}
|
||||
|
||||
static int unit_file_add_dir(
|
||||
|
|
|
@ -6,14 +6,26 @@
|
|||
#include "set.h"
|
||||
#include "unit-name.h"
|
||||
|
||||
int drop_in_file(const char *dir, const char *unit, unsigned level,
|
||||
const char *name, char **_p, char **_q);
|
||||
int drop_in_file(
|
||||
const char *dir,
|
||||
const char *unit,
|
||||
unsigned level,
|
||||
const char *name,
|
||||
char **ret_unit_dir,
|
||||
char **ret_path);
|
||||
|
||||
int write_drop_in(const char *dir, const char *unit, unsigned level,
|
||||
const char *name, const char *data);
|
||||
|
||||
int write_drop_in_format(const char *dir, const char *unit, unsigned level,
|
||||
const char *name, const char *format, ...) _printf_(5, 6);
|
||||
int write_drop_in(
|
||||
const char *dir,
|
||||
const char *unit,
|
||||
unsigned level,
|
||||
const char *name,
|
||||
const char *data);
|
||||
int write_drop_in_format(
|
||||
const char *dir,
|
||||
const char *unit,
|
||||
unsigned level,
|
||||
const char *name,
|
||||
const char *format, ...) _printf_(5, 6);
|
||||
|
||||
int unit_file_find_dropin_paths(
|
||||
const char *original_root,
|
||||
|
|
|
@ -117,17 +117,23 @@ static int in_search_path(const LookupPaths *lp, const char *path) {
|
|||
|
||||
/* Check if 'path' is in lp->search_path. */
|
||||
|
||||
r = path_extract_directory(ASSERT_PTR(path), &parent);
|
||||
assert(lp);
|
||||
assert(path);
|
||||
|
||||
r = path_extract_directory(path, &parent);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return path_strv_contains(ASSERT_PTR(lp)->search_path, parent);
|
||||
return path_strv_contains(lp->search_path, parent);
|
||||
}
|
||||
|
||||
static int underneath_search_path(const LookupPaths *lp, const char *path) {
|
||||
static bool underneath_search_path(const LookupPaths *lp, const char *path) {
|
||||
/* Check if 'path' is underneath lp->search_path. */
|
||||
|
||||
return !!path_startswith_strv(ASSERT_PTR(path), ASSERT_PTR(lp)->search_path);
|
||||
assert(lp);
|
||||
assert(path);
|
||||
|
||||
return path_startswith_strv(path, lp->search_path);
|
||||
}
|
||||
|
||||
static const char* skip_root(const char *root_dir, const char *path) {
|
||||
|
@ -660,7 +666,7 @@ static int remove_marked_symlinks_fd(
|
|||
size_t *n_changes) {
|
||||
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
int r = 0;
|
||||
int r, ret = 0;
|
||||
|
||||
assert(remove_symlinks_to);
|
||||
assert(fd >= 0);
|
||||
|
@ -678,36 +684,32 @@ static int remove_marked_symlinks_fd(
|
|||
rewinddir(d);
|
||||
|
||||
FOREACH_DIRENT(de, d, return -errno)
|
||||
|
||||
if (de->d_type == DT_DIR) {
|
||||
_cleanup_close_ int nfd = -EBADF;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int nfd, q;
|
||||
|
||||
nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
|
||||
nfd = RET_NERRNO(openat(fd, de->d_name, O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW));
|
||||
if (nfd < 0) {
|
||||
if (errno == ENOENT)
|
||||
continue;
|
||||
|
||||
if (r == 0)
|
||||
r = -errno;
|
||||
if (nfd != -ENOENT)
|
||||
RET_GATHER(ret, nfd);
|
||||
continue;
|
||||
}
|
||||
|
||||
p = path_make_absolute(de->d_name, path);
|
||||
if (!p) {
|
||||
safe_close(nfd);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* This will close nfd, regardless whether it succeeds or not */
|
||||
q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, lp, dry_run, restart, changes, n_changes);
|
||||
if (q < 0 && r == 0)
|
||||
r = q;
|
||||
RET_GATHER(ret, remove_marked_symlinks_fd(remove_symlinks_to,
|
||||
TAKE_FD(nfd), p,
|
||||
config_path, lp,
|
||||
dry_run,
|
||||
restart,
|
||||
changes, n_changes));
|
||||
|
||||
} else if (de->d_type == DT_LNK) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
bool found;
|
||||
int q;
|
||||
|
||||
if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
|
||||
continue;
|
||||
|
@ -726,64 +728,61 @@ static int remove_marked_symlinks_fd(
|
|||
if (!found) {
|
||||
_cleanup_free_ char *template = NULL;
|
||||
|
||||
q = unit_name_template(de->d_name, &template);
|
||||
if (q < 0 && q != -EINVAL)
|
||||
return q;
|
||||
if (q >= 0)
|
||||
r = unit_name_template(de->d_name, &template);
|
||||
if (r < 0 && r != -EINVAL)
|
||||
return r;
|
||||
if (r >= 0)
|
||||
found = set_contains(remove_symlinks_to, template);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
_cleanup_free_ char *dest = NULL;
|
||||
_cleanup_free_ char *dest = NULL, *dest_name = NULL;
|
||||
|
||||
q = chase(p, lp->root_dir, CHASE_NONEXISTENT, &dest, NULL);
|
||||
if (q == -ENOENT)
|
||||
r = chase(p, lp->root_dir, CHASE_NONEXISTENT, &dest, NULL);
|
||||
if (r == -ENOENT)
|
||||
continue;
|
||||
if (q < 0) {
|
||||
log_debug_errno(q, "Failed to resolve symlink \"%s\": %m", p);
|
||||
install_changes_add(changes, n_changes, q, p, NULL);
|
||||
|
||||
if (r == 0)
|
||||
r = q;
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to resolve symlink \"%s\": %m", p);
|
||||
RET_GATHER(ret, install_changes_add(changes, n_changes, r, p, NULL));
|
||||
continue;
|
||||
}
|
||||
|
||||
r = path_extract_filename(dest, &dest_name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
found = set_contains(remove_symlinks_to, dest) ||
|
||||
set_contains(remove_symlinks_to, basename(dest));
|
||||
|
||||
set_contains(remove_symlinks_to, dest_name);
|
||||
}
|
||||
|
||||
|
||||
if (!found)
|
||||
continue;
|
||||
|
||||
if (!dry_run) {
|
||||
if (unlinkat(fd, de->d_name, 0) < 0 && errno != ENOENT) {
|
||||
if (r == 0)
|
||||
r = -errno;
|
||||
install_changes_add(changes, n_changes, -errno, p, NULL);
|
||||
RET_GATHER(ret, install_changes_add(changes, n_changes, -errno, p, NULL));
|
||||
continue;
|
||||
}
|
||||
|
||||
(void) rmdir_parents(p, config_path);
|
||||
}
|
||||
|
||||
q = install_changes_add(changes, n_changes, INSTALL_CHANGE_UNLINK, p, NULL);
|
||||
if (q < 0)
|
||||
return q;
|
||||
r = install_changes_add(changes, n_changes, INSTALL_CHANGE_UNLINK, p, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Now, remember the full path (but with the root prefix removed) of
|
||||
* the symlink we just removed, and remove any symlinks to it, too. */
|
||||
|
||||
const char *rp = skip_root(lp->root_dir, p);
|
||||
q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: p);
|
||||
if (q < 0)
|
||||
return q;
|
||||
if (q > 0 && !dry_run)
|
||||
r = mark_symlink_for_removal(&remove_symlinks_to, rp ?: p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0 && !dry_run)
|
||||
*restart = true;
|
||||
}
|
||||
|
||||
return r;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int remove_marked_symlinks(
|
||||
|
@ -809,7 +808,7 @@ static int remove_marked_symlinks(
|
|||
return errno == ENOENT ? 0 : -errno;
|
||||
|
||||
do {
|
||||
int q, cfd;
|
||||
int cfd;
|
||||
restart = false;
|
||||
|
||||
cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
|
||||
|
@ -817,9 +816,12 @@ static int remove_marked_symlinks(
|
|||
return -errno;
|
||||
|
||||
/* This takes possession of cfd and closes it */
|
||||
q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, lp, dry_run, &restart, changes, n_changes);
|
||||
if (r == 0)
|
||||
r = q;
|
||||
RET_GATHER(r, remove_marked_symlinks_fd(remove_symlinks_to,
|
||||
cfd, config_path,
|
||||
config_path, lp,
|
||||
dry_run,
|
||||
&restart,
|
||||
changes, n_changes));
|
||||
} while (restart);
|
||||
|
||||
return r;
|
||||
|
@ -828,6 +830,9 @@ static int remove_marked_symlinks(
|
|||
static int is_symlink_with_known_name(const InstallInfo *i, const char *name) {
|
||||
int r;
|
||||
|
||||
assert(i);
|
||||
assert(name);
|
||||
|
||||
if (streq(name, i->name))
|
||||
return true;
|
||||
|
||||
|
@ -861,11 +866,17 @@ static int find_symlinks_in_directory(
|
|||
const char *config_path,
|
||||
bool *same_name_link) {
|
||||
|
||||
int r = 0;
|
||||
int r, ret = 0;
|
||||
|
||||
assert(dir);
|
||||
assert(dir_path);
|
||||
assert(info);
|
||||
assert(unit_name_is_valid(info->name, UNIT_NAME_ANY));
|
||||
assert(config_path);
|
||||
assert(same_name_link);
|
||||
|
||||
FOREACH_DIRENT(de, dir, return -errno) {
|
||||
bool found_path = false, found_dest = false, b = false;
|
||||
int q;
|
||||
|
||||
if (de->d_type != DT_LNK)
|
||||
continue;
|
||||
|
@ -874,32 +885,17 @@ static int find_symlinks_in_directory(
|
|||
_cleanup_free_ char *dest = NULL;
|
||||
|
||||
/* Acquire symlink destination */
|
||||
q = readlinkat_malloc(dirfd(dir), de->d_name, &dest);
|
||||
if (q == -ENOENT)
|
||||
r = readlinkat_malloc(dirfd(dir), de->d_name, &dest);
|
||||
if (r < 0) {
|
||||
if (r != -ENOENT)
|
||||
RET_GATHER(ret, r);
|
||||
continue;
|
||||
if (q < 0) {
|
||||
if (r == 0)
|
||||
r = q;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Make absolute */
|
||||
if (!path_is_absolute(dest)) {
|
||||
char *x;
|
||||
|
||||
x = path_join(dir_path, dest);
|
||||
if (!x)
|
||||
return -ENOMEM;
|
||||
|
||||
free_and_replace(dest, x);
|
||||
}
|
||||
|
||||
/* Check if what the symlink points to matches what we are looking for */
|
||||
found_dest = streq(basename(dest), info->name);
|
||||
found_dest = path_equal_filename(dest, info->name);
|
||||
}
|
||||
|
||||
assert(unit_name_is_valid(info->name, UNIT_NAME_ANY));
|
||||
|
||||
/* Check if the symlink itself matches what we are looking for.
|
||||
*
|
||||
* If ignore_destination is specified, we only look at the source name.
|
||||
|
@ -914,10 +910,10 @@ static int find_symlinks_in_directory(
|
|||
if (!found_path && ignore_destination) {
|
||||
_cleanup_free_ char *template = NULL;
|
||||
|
||||
q = unit_name_template(de->d_name, &template);
|
||||
if (q < 0 && q != -EINVAL)
|
||||
return q;
|
||||
if (q >= 0)
|
||||
r = unit_name_template(de->d_name, &template);
|
||||
if (r < 0 && r != -EINVAL)
|
||||
return r;
|
||||
if (r >= 0)
|
||||
found_dest = streq(template, info->name);
|
||||
}
|
||||
|
||||
|
@ -927,7 +923,6 @@ static int find_symlinks_in_directory(
|
|||
/* Filter out same name links in the main config path */
|
||||
p = path_make_absolute(de->d_name, dir_path);
|
||||
t = path_make_absolute(info->name, config_path);
|
||||
|
||||
if (!p || !t)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -941,15 +936,13 @@ static int find_symlinks_in_directory(
|
|||
return 1;
|
||||
|
||||
/* Check if symlink name is in the set of names used by [Install] */
|
||||
q = is_symlink_with_known_name(info, de->d_name);
|
||||
if (q < 0)
|
||||
return q;
|
||||
if (q > 0)
|
||||
return 1;
|
||||
r = is_symlink_with_known_name(info, de->d_name);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int find_symlinks(
|
||||
|
@ -961,7 +954,7 @@ static int find_symlinks(
|
|||
bool *same_name_link) {
|
||||
|
||||
_cleanup_closedir_ DIR *config_dir = NULL;
|
||||
int r = 0;
|
||||
int r;
|
||||
|
||||
assert(i);
|
||||
assert(config_path);
|
||||
|
@ -1004,7 +997,7 @@ static int find_symlinks(
|
|||
same_name_link);
|
||||
if (r > 0)
|
||||
return 1;
|
||||
else if (r < 0)
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to look up symlinks in \"%s\": %m", path);
|
||||
}
|
||||
|
||||
|
@ -1187,16 +1180,19 @@ static int install_info_add(
|
|||
bool auxiliary,
|
||||
InstallInfo **ret) {
|
||||
|
||||
_cleanup_free_ char *name_alloc = NULL;
|
||||
int r;
|
||||
|
||||
assert(ctx);
|
||||
|
||||
if (!name) {
|
||||
/* 'name' and 'path' must not both be null. Check here 'path' using assert_se() to
|
||||
* workaround a bug in gcc that generates a -Wnonnull warning when calling basename(),
|
||||
* but this cannot be possible in any code path (See #6119). */
|
||||
assert_se(path);
|
||||
name = basename(path);
|
||||
assert(path);
|
||||
|
||||
r = path_extract_filename(path, &name_alloc);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
name = name_alloc;
|
||||
}
|
||||
|
||||
if (!unit_name_is_valid(name, UNIT_NAME_ANY))
|
||||
|
@ -1211,35 +1207,35 @@ static int install_info_add(
|
|||
return 0;
|
||||
}
|
||||
|
||||
_cleanup_(install_info_freep) InstallInfo *alloc = new(InstallInfo, 1);
|
||||
if (!alloc)
|
||||
_cleanup_(install_info_freep) InstallInfo *new_info = new(InstallInfo, 1);
|
||||
if (!new_info)
|
||||
return -ENOMEM;
|
||||
|
||||
*alloc = (InstallInfo) {
|
||||
*new_info = (InstallInfo) {
|
||||
.install_mode = _INSTALL_MODE_INVALID,
|
||||
.auxiliary = auxiliary,
|
||||
};
|
||||
|
||||
alloc->name = strdup(name);
|
||||
if (!alloc->name)
|
||||
return -ENOMEM;
|
||||
|
||||
if (root) {
|
||||
alloc->root = strdup(root);
|
||||
if (!alloc->root)
|
||||
if (name_alloc)
|
||||
new_info->name = TAKE_PTR(name_alloc);
|
||||
else {
|
||||
new_info->name = strdup(name);
|
||||
if (!new_info->name)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (path) {
|
||||
alloc->path = strdup(path);
|
||||
if (!alloc->path)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = ordered_hashmap_ensure_put(&ctx->will_process, &string_hash_ops, alloc->name, alloc);
|
||||
r = strdup_to(&new_info->root, root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
i = TAKE_PTR(alloc);
|
||||
|
||||
r = strdup_to(&new_info->path, path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ordered_hashmap_ensure_put(&ctx->will_process, &string_hash_ops, new_info->name, new_info);
|
||||
if (r < 0)
|
||||
return r;
|
||||
i = TAKE_PTR(new_info);
|
||||
|
||||
if (ret)
|
||||
*ret = i;
|
||||
|
@ -1662,7 +1658,7 @@ static int install_info_follow(
|
|||
|
||||
/* If the basename doesn't match, the caller should add a complete new entry for this. */
|
||||
|
||||
if (!ignore_different_name && !streq(basename(info->symlink_target), info->name))
|
||||
if (!ignore_different_name && !path_equal_filename(info->symlink_target, info->name))
|
||||
return -EXDEV;
|
||||
|
||||
free_and_replace(info->path, info->symlink_target);
|
||||
|
@ -1686,9 +1682,9 @@ static int install_info_traverse(
|
|||
unsigned k = 0;
|
||||
int r;
|
||||
|
||||
assert(ctx);
|
||||
assert(lp);
|
||||
assert(start);
|
||||
assert(ctx);
|
||||
|
||||
r = unit_file_search(ctx, start, lp, flags);
|
||||
if (r < 0)
|
||||
|
@ -1701,7 +1697,7 @@ static int install_info_traverse(
|
|||
if (++k > UNIT_FILE_FOLLOW_SYMLINK_MAX)
|
||||
return -ELOOP;
|
||||
|
||||
if (!(flags & SEARCH_FOLLOW_CONFIG_SYMLINKS)) {
|
||||
if (!FLAGS_SET(flags, SEARCH_FOLLOW_CONFIG_SYMLINKS)) {
|
||||
r = path_is_config(lp, i->path, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1713,15 +1709,17 @@ static int install_info_traverse(
|
|||
/* If linked, don't look at the target name */
|
||||
/* ignore_different_name= */ i->install_mode == INSTALL_MODE_LINKED);
|
||||
if (r == -EXDEV && i->symlink_target) {
|
||||
_cleanup_free_ char *buffer = NULL;
|
||||
_cleanup_free_ char *target_name = NULL, *unit_instance = NULL;
|
||||
const char *bn;
|
||||
|
||||
/* Target is an alias, create a new install info object and continue with that. */
|
||||
|
||||
bn = basename(i->symlink_target);
|
||||
r = path_extract_filename(i->symlink_target, &target_name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE) &&
|
||||
unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) {
|
||||
unit_name_is_valid(target_name, UNIT_NAME_TEMPLATE)) {
|
||||
|
||||
_cleanup_free_ char *instance = NULL;
|
||||
|
||||
|
@ -1729,12 +1727,11 @@ static int install_info_traverse(
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_name_replace_instance(bn, instance, &buffer);
|
||||
r = unit_name_replace_instance(target_name, instance, &unit_instance);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (streq(buffer, i->name)) {
|
||||
|
||||
if (streq(unit_instance, i->name)) {
|
||||
/* We filled in the instance, and the target stayed the same? If so,
|
||||
* then let's honour the link as it is. */
|
||||
|
||||
|
@ -1745,8 +1742,9 @@ static int install_info_traverse(
|
|||
continue;
|
||||
}
|
||||
|
||||
bn = buffer;
|
||||
}
|
||||
bn = unit_instance;
|
||||
} else
|
||||
bn = target_name;
|
||||
|
||||
r = install_info_add(ctx, bn, NULL, lp->root_dir, /* auxiliary= */ false, &i);
|
||||
if (r < 0)
|
||||
|
@ -1758,7 +1756,6 @@ static int install_info_traverse(
|
|||
/* Translate error code to highlight this specific case */
|
||||
return -ENOLINK;
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
@ -2310,7 +2307,7 @@ int unit_file_mask(
|
|||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **names,
|
||||
char * const *names,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes) {
|
||||
|
||||
|
@ -2353,7 +2350,7 @@ int unit_file_unmask(
|
|||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **names,
|
||||
char * const *names,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes) {
|
||||
|
||||
|
@ -2465,36 +2462,41 @@ int unit_file_link(
|
|||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **files,
|
||||
char * const *files,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes) {
|
||||
|
||||
_cleanup_(lookup_paths_done) LookupPaths lp = {};
|
||||
_cleanup_strv_free_ char **todo = NULL;
|
||||
_cleanup_ordered_hashmap_free_ OrderedHashmap *todo = NULL;
|
||||
const char *config_path;
|
||||
size_t n_todo = 0;
|
||||
int r;
|
||||
|
||||
assert(scope >= 0);
|
||||
assert(scope < _RUNTIME_SCOPE_MAX);
|
||||
assert(changes);
|
||||
assert(n_changes);
|
||||
|
||||
r = lookup_paths_init(&lp, scope, 0, root_dir);
|
||||
if (r < 0)
|
||||
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)
|
||||
return -ENXIO;
|
||||
|
||||
STRV_FOREACH(file, files) {
|
||||
_cleanup_free_ char *full = NULL;
|
||||
struct stat st;
|
||||
char *fn;
|
||||
_cleanup_free_ char *fn = NULL, *path = NULL, *full = NULL;
|
||||
|
||||
if (ordered_hashmap_contains(todo, *file))
|
||||
continue;
|
||||
|
||||
if (!path_is_absolute(*file))
|
||||
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))
|
||||
return install_changes_add(changes, n_changes, -EUCLEAN, *file, NULL);
|
||||
|
||||
|
@ -2502,10 +2504,7 @@ int unit_file_link(
|
|||
if (!full)
|
||||
return -ENOMEM;
|
||||
|
||||
if (lstat(full, &st) < 0)
|
||||
return install_changes_add(changes, n_changes, -errno, *file, NULL);
|
||||
|
||||
r = stat_verify_regular(&st);
|
||||
r = verify_regular_at(AT_FDCWD, full, /* follow = */ false);
|
||||
if (r < 0)
|
||||
return install_changes_add(changes, n_changes, r, *file, NULL);
|
||||
|
||||
|
@ -2516,33 +2515,33 @@ int unit_file_link(
|
|||
/* A silent noop if the file is already in the search path. */
|
||||
continue;
|
||||
|
||||
r = underneath_search_path(&lp, *file);
|
||||
if (r > 0)
|
||||
r = -ETXTBSY;
|
||||
if (underneath_search_path(&lp, *file))
|
||||
return install_changes_add(changes, n_changes, -ETXTBSY, *file, NULL);
|
||||
|
||||
path = strdup(*file);
|
||||
if (!path)
|
||||
return -ENOMEM;
|
||||
|
||||
r = ordered_hashmap_ensure_put(&todo, &path_hash_ops_free_free, path, fn);
|
||||
if (r < 0)
|
||||
return install_changes_add(changes, n_changes, r, *file, NULL);
|
||||
return r;
|
||||
assert(r > 0);
|
||||
|
||||
if (!GREEDY_REALLOC0(todo, n_todo + 2))
|
||||
return -ENOMEM;
|
||||
|
||||
todo[n_todo] = strdup(*file);
|
||||
if (!todo[n_todo])
|
||||
return -ENOMEM;
|
||||
|
||||
n_todo++;
|
||||
TAKE_PTR(path);
|
||||
TAKE_PTR(fn);
|
||||
}
|
||||
|
||||
strv_uniq(todo);
|
||||
|
||||
r = 0;
|
||||
STRV_FOREACH(i, todo) {
|
||||
|
||||
const char *fn, *path;
|
||||
ORDERED_HASHMAP_FOREACH_KEY(fn, path, todo) {
|
||||
_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)
|
||||
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;
|
||||
|
@ -2570,7 +2569,7 @@ static int path_shall_revert(const LookupPaths *lp, const char *path) {
|
|||
int unit_file_revert(
|
||||
RuntimeScope scope,
|
||||
const char *root_dir,
|
||||
char **names,
|
||||
char * const *names,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes) {
|
||||
|
||||
|
@ -2727,7 +2726,7 @@ int unit_file_add_dependency(
|
|||
RuntimeScope scope,
|
||||
UnitFileFlags file_flags,
|
||||
const char *root_dir,
|
||||
char **names,
|
||||
char * const *names,
|
||||
const char *target,
|
||||
UnitDependency dep,
|
||||
InstallChange **changes,
|
||||
|
@ -2799,7 +2798,7 @@ static int do_unit_file_enable(
|
|||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *config_path,
|
||||
char **names_or_paths,
|
||||
char * const *names_or_paths,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes) {
|
||||
|
||||
|
@ -2830,7 +2829,7 @@ int unit_file_enable(
|
|||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **names_or_paths,
|
||||
char * const *names_or_paths,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes) {
|
||||
|
||||
|
@ -2856,7 +2855,7 @@ static int do_unit_file_disable(
|
|||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *config_path,
|
||||
char **names,
|
||||
char * const *names,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes) {
|
||||
|
||||
|
@ -2898,7 +2897,7 @@ int unit_file_disable(
|
|||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **files,
|
||||
char * const *files,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes) {
|
||||
|
||||
|
@ -2922,7 +2921,7 @@ int unit_file_disable(
|
|||
static int normalize_linked_files(
|
||||
RuntimeScope scope,
|
||||
const LookupPaths *lp,
|
||||
char **names_or_paths,
|
||||
char * const *names_or_paths,
|
||||
char ***ret_names,
|
||||
char ***ret_files) {
|
||||
|
||||
|
@ -2981,7 +2980,7 @@ int unit_file_reenable(
|
|||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **names_or_paths,
|
||||
char * const *names_or_paths,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes) {
|
||||
|
||||
|
@ -3116,7 +3115,7 @@ int unit_file_lookup_state(
|
|||
|
||||
case INSTALL_MODE_REGULAR:
|
||||
/* Check if the name we were querying is actually an alias */
|
||||
if (!streq(name, basename(info->path)) && !unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
|
||||
if (!path_equal_filename(name, info->path) && !unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) {
|
||||
state = UNIT_FILE_ALIAS;
|
||||
break;
|
||||
}
|
||||
|
@ -3399,6 +3398,8 @@ static int pattern_match_multiple_instances(
|
|||
_cleanup_free_ char *templated_name = NULL;
|
||||
int r;
|
||||
|
||||
assert(unit_name);
|
||||
|
||||
/* If no ret is needed or the rule itself does not have instances
|
||||
* initialized, we return not matching */
|
||||
if (!ret || !rule.instances)
|
||||
|
@ -3445,20 +3446,25 @@ static int pattern_match_multiple_instances(
|
|||
static int query_presets(const char *name, const UnitFilePresets *presets, char ***instance_name_list) {
|
||||
PresetAction action = PRESET_UNKNOWN;
|
||||
|
||||
assert(name);
|
||||
assert(presets);
|
||||
|
||||
if (!unit_name_is_valid(name, UNIT_NAME_ANY))
|
||||
return -EINVAL;
|
||||
|
||||
for (size_t i = 0; i < presets->n_rules; i++)
|
||||
if (pattern_match_multiple_instances(presets->rules[i], name, instance_name_list) > 0 ||
|
||||
fnmatch(presets->rules[i].pattern, name, FNM_NOESCAPE) == 0) {
|
||||
action = presets->rules[i].action;
|
||||
FOREACH_ARRAY(i, presets->rules, presets->n_rules)
|
||||
if (pattern_match_multiple_instances(*i, name, instance_name_list) > 0 ||
|
||||
fnmatch(i->pattern, name, FNM_NOESCAPE) == 0) {
|
||||
action = i->action;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
|
||||
case PRESET_UNKNOWN:
|
||||
log_debug("Preset files don't specify rule for %s. Enabling.", name);
|
||||
return PRESET_ENABLE;
|
||||
|
||||
case PRESET_ENABLE:
|
||||
if (instance_name_list && *instance_name_list)
|
||||
STRV_FOREACH(s, *instance_name_list)
|
||||
|
@ -3466,12 +3472,15 @@ static int query_presets(const char *name, const UnitFilePresets *presets, char
|
|||
else
|
||||
log_debug("Preset files say enable %s.", name);
|
||||
return PRESET_ENABLE;
|
||||
|
||||
case PRESET_DISABLE:
|
||||
log_debug("Preset files say disable %s.", name);
|
||||
return PRESET_DISABLE;
|
||||
|
||||
case PRESET_IGNORE:
|
||||
log_debug("Preset files say ignore %s.", name);
|
||||
return PRESET_IGNORE;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
@ -3498,7 +3507,7 @@ static int execute_preset(
|
|||
InstallContext *minus,
|
||||
const LookupPaths *lp,
|
||||
const char *config_path,
|
||||
char **files,
|
||||
char * const *files,
|
||||
UnitFilePresetMode mode,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes) {
|
||||
|
@ -3597,7 +3606,7 @@ int unit_file_preset(
|
|||
RuntimeScope scope,
|
||||
UnitFileFlags file_flags,
|
||||
const char *root_dir,
|
||||
char **names,
|
||||
char * const *names,
|
||||
UnitFilePresetMode mode,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes) {
|
||||
|
@ -3716,27 +3725,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)
|
||||
|
@ -3758,7 +3764,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;
|
||||
|
@ -3766,36 +3776,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -106,28 +106,28 @@ int unit_file_enable(
|
|||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **names_or_paths,
|
||||
char * const *names_or_paths,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_disable(
|
||||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **names,
|
||||
char * const *names,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_reenable(
|
||||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **names_or_paths,
|
||||
char * const *names_or_paths,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_preset(
|
||||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **names,
|
||||
char * const *names,
|
||||
UnitFilePresetMode mode,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes);
|
||||
|
@ -142,27 +142,27 @@ int unit_file_mask(
|
|||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **names,
|
||||
char * const *names,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_unmask(
|
||||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **names,
|
||||
char * const *names,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_link(
|
||||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **files,
|
||||
char * const *files,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_revert(
|
||||
RuntimeScope scope,
|
||||
const char *root_dir,
|
||||
char **names,
|
||||
char * const *names,
|
||||
InstallChange **changes,
|
||||
size_t *n_changes);
|
||||
int unit_file_set_default(
|
||||
|
@ -180,7 +180,7 @@ int unit_file_add_dependency(
|
|||
RuntimeScope scope,
|
||||
UnitFileFlags flags,
|
||||
const char *root_dir,
|
||||
char **names,
|
||||
char * const *names,
|
||||
const char *target,
|
||||
UnitDependency dep,
|
||||
InstallChange **changes,
|
||||
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
Loading…
Reference in a new issue