[systemd-devel] [PATCH, REVIEW] Added unit enabled-context cache to improve performance w/ many units.
Ken Sedgwick
ksedgwic at bonsai.com
Tue Oct 7 23:08:13 PDT 2014
Resubmitting using git format-patch, git imap-send ... no code changes.
---
.gitignore | 1 +
Makefile.am | 44 +++-
src/core/dbus-manager.c | 4 +-
src/core/manager.c | 6 +
src/core/manager.h | 2 +
src/core/unit.c | 2 +-
src/shared/install.c | 268 +++++++++++++++++----
src/shared/install.h | 16 +-
src/systemctl/systemctl.c | 4 +-
src/test/test-enabled.c | 151 ++++++++++++
src/test/test-install.c | 87 ++++---
src/test/test-unit-file.c | 2 +-
.../etc/systemd/system/masked.service | 1 +
.../etc/systemd/system/maskedstatic.service | 1 +
.../etc/systemd/system/some.target | 11 +
.../system/some.target.wants/aliased.service | 1 +
.../system/some.target.wants/also_masked.service | 1 +
.../system/some.target.wants/another.service | 1 +
.../system/some.target.wants/different.service | 1 +
.../system/some.target.wants/masked.service | 1 +
.../some.target.wants/templating at four.service | 1 +
.../some.target.wants/templating at one.service | 1 +
.../some.target.wants/templating at three.service | 1 +
.../some.target.wants/templating at two.service | 1 +
.../run/systemd/system/maskedruntime.service | 1 +
.../run/systemd/system/maskedruntimestatic.service | 1 +
.../run/systemd/system/other.target | 14 ++
.../system/other.target.wants/runtime.service | 1 +
.../usr/lib/systemd/system/another.service | 9 +
.../usr/lib/systemd/system/disabled.service | 9 +
.../usr/lib/systemd/system/invalid.service | 1 +
.../usr/lib/systemd/system/masked.service | 9 +
.../usr/lib/systemd/system/maskedruntime.service | 9 +
.../lib/systemd/system/maskedruntimestatic.service | 6 +
.../usr/lib/systemd/system/maskedstatic.service | 6 +
.../usr/lib/systemd/system/runtime.service | 9 +
.../usr/lib/systemd/system/static.service | 6 +
.../usr/lib/systemd/system/templating at .service | 9 +
.../lib/systemd/system/templating at three.service | 9 +
.../usr/lib/systemd/system/templating at two.service | 9 +
.../usr/lib/systemd/system/unique.service | 9 +
41 files changed, 626 insertions(+), 100 deletions(-)
create mode 100644 src/test/test-enabled.c
create mode 120000 test/test-enabled-root/etc/systemd/system/masked.service
create mode 120000
test/test-enabled-root/etc/systemd/system/maskedstatic.service
create mode 100644 test/test-enabled-root/etc/systemd/system/some.target
create mode 120000
test/test-enabled-root/etc/systemd/system/some.target.wants/aliased.service
create mode 120000
test/test-enabled-root/etc/systemd/system/some.target.wants/also_masked.service
create mode 120000
test/test-enabled-root/etc/systemd/system/some.target.wants/another.service
create mode 120000
test/test-enabled-root/etc/systemd/system/some.target.wants/different.service
create mode 120000
test/test-enabled-root/etc/systemd/system/some.target.wants/masked.service
create mode 120000
test/test-enabled-root/etc/systemd/system/some.target.wants/templating at four.service
create mode 120000
test/test-enabled-root/etc/systemd/system/some.target.wants/templating at one.service
create mode 120000
test/test-enabled-root/etc/systemd/system/some.target.wants/templating at three.service
create mode 120000
test/test-enabled-root/etc/systemd/system/some.target.wants/templating at two.service
create mode 120000
test/test-enabled-root/run/systemd/system/maskedruntime.service
create mode 120000
test/test-enabled-root/run/systemd/system/maskedruntimestatic.service
create mode 100644 test/test-enabled-root/run/systemd/system/other.target
create mode 120000
test/test-enabled-root/run/systemd/system/other.target.wants/runtime.service
create mode 100644
test/test-enabled-root/usr/lib/systemd/system/another.service
create mode 100644
test/test-enabled-root/usr/lib/systemd/system/disabled.service
create mode 100644
test/test-enabled-root/usr/lib/systemd/system/invalid.service
create mode 100644 test/test-enabled-root/usr/lib/systemd/system/masked.service
create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedruntimestatic.service
create mode 100644
test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service
create mode 100644
test/test-enabled-root/usr/lib/systemd/system/runtime.service
create mode 100644 test/test-enabled-root/usr/lib/systemd/system/static.service
create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating at .service
create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating at three.service
create mode 100644
test/test-enabled-root/usr/lib/systemd/system/templating at two.service
create mode 100644 test/test-enabled-root/usr/lib/systemd/system/unique.service
diff --git a/.gitignore b/.gitignore
index f119b57..97b2b2b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -173,6 +173,7 @@
/test-icmp6-rs
/test-ellipsize
/test-engine
+/test-enabled
/test-env-replace
/test-event
/test-fdset
diff --git a/Makefile.am b/Makefile.am
index e52db17..7d4f2f5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1358,7 +1358,8 @@ tests += \
test-ratelimit \
test-condition-util \
test-uid-range \
- test-bus-policy
+ test-bus-policy \
+ test-enabled
EXTRA_DIST += \
test/a.service \
@@ -1394,8 +1395,36 @@ EXTRA_DIST += \
test/bus-policy/hello.conf \
test/bus-policy/methods.conf \
test/bus-policy/ownerships.conf \
- test/bus-policy/signals.conf
-
+ test/bus-policy/signals.conf \
+ test/test-enabled-root/usr/lib/systemd/system/masked.service \
+ test/test-enabled-root/usr/lib/systemd/system/runtime.service \
+ test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service \
+ test/test-enabled-root/usr/lib/systemd/system/another.service \
+ test/test-enabled-root/usr/lib/systemd/system/templating at three.service \
+ test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service \
+ test/test-enabled-root/usr/lib/systemd/system/invalid.service \
+ test/test-enabled-root/usr/lib/systemd/system/disabled.service \
+ test/test-enabled-root/usr/lib/systemd/system/templating at two.service \
+ test/test-enabled-root/usr/lib/systemd/system/unique.service \
+ test/test-enabled-root/usr/lib/systemd/system/templating at .service \
+ test/test-enabled-root/usr/lib/systemd/system/static.service \
+ test/test-enabled-root/usr/lib/systemd/system/maskedruntimestatic.service \
+ test/test-enabled-root/run/systemd/system/other.target.wants/runtime.service \
+ test/test-enabled-root/run/systemd/system/maskedruntime.service \
+ test/test-enabled-root/run/systemd/system/other.target \
+ test/test-enabled-root/run/systemd/system/maskedruntimestatic.service \
+ test/test-enabled-root/etc/systemd/system/masked.service \
+ test/test-enabled-root/etc/systemd/system/some.target.wants/masked.service \
+ test/test-enabled-root/etc/systemd/system/some.target.wants/another.service \
+ test/test-enabled-root/etc/systemd/system/some.target.wants/templating at three.service
\
+ test/test-enabled-root/etc/systemd/system/some.target.wants/templating at one.service
\
+ test/test-enabled-root/etc/systemd/system/some.target.wants/templating at two.service
\
+ test/test-enabled-root/etc/systemd/system/some.target.wants/templating at four.service
\
+ test/test-enabled-root/etc/systemd/system/some.target.wants/also_masked.service
\
+ test/test-enabled-root/etc/systemd/system/some.target.wants/different.service
\
+ test/test-enabled-root/etc/systemd/system/some.target.wants/aliased.service \
+ test/test-enabled-root/etc/systemd/system/maskedstatic.service \
+ test/test-enabled-root/etc/systemd/system/some.target
EXTRA_DIST += \
src/test/test-helper.h
@@ -1782,6 +1811,15 @@ test_install_LDADD = \
libsystemd-shared.la \
libsystemd-internal.la
+test_enabled_SOURCES = \
+ src/test/test-enabled.c
+
+test_enabled_LDADD = \
+ libsystemd-units.la \
+ libsystemd-label.la \
+ libsystemd-shared.la \
+ libsystemd-internal.la
+
test_watchdog_SOURCES = \
src/test/test-watchdog.c
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 533ce43..8dcd552 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -1403,7 +1403,7 @@ static int method_list_unit_files(sd_bus *bus,
sd_bus_message *message, void *us
if (!h)
return -ENOMEM;
- r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ?
UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
+ r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ?
UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h, m->enabled);
if (r < 0)
goto fail;
@@ -1454,7 +1454,7 @@ static int method_get_unit_file_state(sd_bus
*bus, sd_bus_message *message, void
scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM :
UNIT_FILE_USER;
- state = unit_file_get_state(scope, NULL, name);
+ state = unit_file_get_state(scope, NULL, name, m->enabled);
if (state < 0)
return state;
diff --git a/src/core/manager.c b/src/core/manager.c
index e0c1cd1..c9aef42 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -465,6 +465,10 @@ int manager_new(SystemdRunningAs running_as, bool
test_run, Manager **_m) {
if (r < 0)
goto fail;
+ m->enabled = enabled_context_new();
+ if (!m->enabled)
+ goto fail;
+
r = set_ensure_allocated(&m->startup_units, NULL);
if (r < 0)
goto fail;
@@ -808,6 +812,8 @@ void manager_free(Manager *m) {
hashmap_free(m->watch_pids2);
hashmap_free(m->watch_bus);
+ enabled_context_free(m->enabled);
+
set_free(m->startup_units);
set_free(m->failed_units);
diff --git a/src/core/manager.h b/src/core/manager.h
index 8e3c146..3f54fe0 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -72,6 +72,7 @@ typedef enum ManagerExitCode {
#include "unit-name.h"
#include "exit-status.h"
#include "show-status.h"
+#include "install.h"
#include "failure-action.h"
struct Manager {
@@ -82,6 +83,7 @@ struct Manager {
/* Active jobs and units */
Hashmap *units; /* name string => Unit object n:1 */
Hashmap *jobs; /* job id => Job object 1:1 */
+ EnabledContext *enabled; /* name string => is enabled */
/* To make it easy to iterate through the units of a specific
* type we maintain a per type linked list */
diff --git a/src/core/unit.c b/src/core/unit.c
index 399d202..c97b061 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2941,7 +2941,7 @@ UnitFileState unit_get_unit_file_state(Unit *u) {
if (u->unit_file_state < 0 && u->fragment_path)
u->unit_file_state = unit_file_get_state(
u->manager->running_as ==
SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
- NULL, basename(u->fragment_path));
+ NULL, basename(u->fragment_path),
u->manager->enabled);
return u->unit_file_state;
}
diff --git a/src/shared/install.c b/src/shared/install.c
index fa064c2..b4e4bc1 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -25,6 +25,7 @@
#include <string.h>
#include <fnmatch.h>
+#include "macro.h"
#include "util.h"
#include "mkdir.h"
#include "hashmap.h"
@@ -382,21 +383,106 @@ static int remove_marked_symlinks(
return r;
}
-static int find_symlinks_fd(
- const char *name,
+EnabledContext *enabled_context_new(void) {
+ EnabledContext *ec;
+ int r;
+
+ ec = new0(EnabledContext, 1);
+ if (!ec)
+ return NULL;
+
+ r = hashmap_ensure_allocated(&ec->config_paths_forward,
&string_hash_ops);
+ if (r < 0) {
+ free(ec);
+ return NULL;
+ }
+
+ r = hashmap_ensure_allocated(&ec->config_paths_reverse,
&string_hash_ops);
+ if (r < 0) {
+ free(ec);
+ return NULL;
+ }
+
+ return ec;
+}
+
+void enabled_context_free(EnabledContext *ec) {
+ char *key;
+ Hashmap *h;
+
+ while ((key = hashmap_first_key(ec->config_paths_forward))) {
+ h = hashmap_steal_first(ec->config_paths_forward);
+ hashmap_free_free_free(h);
+ free(key);
+ }
+ hashmap_free_free_free(ec->config_paths_forward);
+ ec->config_paths_forward = NULL;
+
+ while ((key = hashmap_first_key(ec->config_paths_reverse))) {
+ h = hashmap_steal_first(ec->config_paths_reverse);
+ hashmap_free_free_free(h);
+ free(key);
+ }
+ hashmap_free_free_free(ec->config_paths_reverse);
+ ec->config_paths_reverse = NULL;
+
+ free(ec);
+}
+
+static int insert_link_mapping(Hashmap *h, const char * key, const char *val) {
+ int r = 0;
+ char *keycpy, *valcpy;
+
+ /* Make copies of the key and value */
+ keycpy = strdup(key);
+ valcpy = strdup(val);
+
+ r = hashmap_put(h, keycpy, valcpy);
+ if (r == 1) {
+ /* Our copies were inserted, we're done */
+ return 0;
+ } else {
+ /* Either an error or the mapping already existed, either way
+ * we don't want the key and value copies any more ...
+ */
+ free(keycpy);
+ free(valcpy);
+ return r;
+ }
+}
+
+static int fill_enabled_context(
int fd,
const char *path,
const char *config_path,
- bool *same_name_link) {
-
+ EnabledContext *ec) {
int r = 0;
_cleanup_closedir_ DIR *d = NULL;
-
- assert(name);
- assert(fd >= 0);
- assert(path);
- assert(config_path);
- assert(same_name_link);
+ Hashmap *config_path_forward;
+ Hashmap *config_path_reverse;
+
+ config_path_forward = hashmap_get(ec->config_paths_forward,
config_path);
+ config_path_reverse = hashmap_get(ec->config_paths_reverse,
config_path);
+
+ /* If config_path_forward isn't cached, generate both directions */
+ if (config_path_forward == NULL) {
+ /* Initialize empty forward and reverse lookups for the
+ * enabled context cache */
+ r = hashmap_ensure_allocated(&config_path_forward,
&string_hash_ops);
+ if (r < 0) {
+ return r;
+ }
+ r = hashmap_put(ec->config_paths_forward,
strdup(config_path), config_path_forward);
+ if (r < 0)
+ return r;
+ r = hashmap_ensure_allocated(&config_path_reverse,
&string_hash_ops);
+ if (r < 0) {
+ return r;
+ }
+ r = hashmap_put(ec->config_paths_reverse,
strdup(config_path), config_path_reverse);
+ if (r < 0)
+ return r;
+ }
d = fdopendir(fd);
if (!d) {
@@ -413,7 +499,7 @@ static int find_symlinks_fd(
return -errno;
if (!de)
- return r;
+ break;
if (ignore_file(de->d_name))
continue;
@@ -441,15 +527,12 @@ static int find_symlinks_fd(
}
/* This will close nfd, regardless whether it
succeeds or not */
- q = find_symlinks_fd(name, nfd, p,
config_path, same_name_link);
- if (q > 0)
- return 1;
+ q = fill_enabled_context(nfd, p, config_path, ec);
if (r == 0)
r = q;
} else if (de->d_type == DT_LNK) {
_cleanup_free_ char *p = NULL, *dest = NULL;
- bool found_path, found_dest, b = false;
int q;
/* Acquire symlink name */
@@ -468,44 +551,121 @@ static int find_symlinks_fd(
continue;
}
- /* Check if the symlink itself matches what we
- * are looking for */
- if (path_is_absolute(name))
- found_path = path_equal(p, name);
- else
- found_path = streq(de->d_name, name);
+ /* Insert symlink's own full path and
+ * name as keys pointing to the unit's
+ * full path */
+ q = insert_link_mapping(config_path_forward, p, dest);
+ if (r == 0)
+ r = q;
+ q = insert_link_mapping(config_path_forward,
de->d_name, dest);
+ if (r == 0)
+ r = q;
- /* Check if what the symlink points to
- * matches what we are looking for */
- if (path_is_absolute(name))
- found_dest = path_equal(dest, name);
- else
- found_dest = streq(basename(dest), name);
+ /* Insert full path and base of the
+ * symlink target as keys pointing to
+ * the symlink's own full path */
+ q = insert_link_mapping(config_path_reverse, dest, p);
+ if (r == 0)
+ r = q;
+ q = insert_link_mapping(config_path_reverse,
basename(dest), p);
+ if (r == 0)
+ r = q;
+ }
+ }
- if (found_path && found_dest) {
- _cleanup_free_ char *t = NULL;
+ return r;
+}
- /* Filter out same name links in the main
- * config path */
- t = path_make_absolute(name, config_path);
- if (!t)
- return -ENOMEM;
+static int find_symlinks_fd(
+ const char *name,
+ int fd,
+ const char *path,
+ const char *config_path,
+ bool *same_name_link,
+ EnabledContext *ec) {
- b = path_equal(t, p);
- }
+ int r = 0;
+ _cleanup_closedir_ DIR *d = NULL;
+ _cleanup_enabled_context_ EnabledContext *temp_ec = NULL;
+ char *symlink_path;
+ char *symlink_target_path;
+ Hashmap *config_path_forward;
+ Hashmap *config_path_reverse;
+ bool found_path, found_dest, b = false;
- if (b)
- *same_name_link = true;
- else if (found_path || found_dest)
- return 1;
- }
+ assert(name);
+ assert(fd >= 0);
+ assert(path);
+ assert(config_path);
+ assert(same_name_link);
+
+ /* If no ec is passed in, use a temporary one that auto-frees */
+ if (ec == NULL) {
+ ec = enabled_context_new();
+ if (ec == NULL)
+ return -ENOMEM;
+ temp_ec = ec;
+ }
+
+ config_path_forward = hashmap_get(ec->config_paths_forward,
config_path);
+
+ /* If config_path_forward isn't cached, generate both directions */
+ if (config_path_forward == NULL) {
+ r = fill_enabled_context(fd, path, config_path, ec);
+ if (r < 0)
+ return r;
+ } else {
+ safe_close(fd);
+ }
+
+ /* Refetch, may have been filled. */
+ config_path_forward = hashmap_get(ec->config_paths_forward,
config_path);
+ config_path_reverse = hashmap_get(ec->config_paths_reverse,
config_path);
+
+ /* Use the cache to perform a reverse lookup of symlink
+ * destinations to see if any one matches what we are looking
+ * for. Because both full and base names are keys, there is no
+ * need to check if "name" is a full path or base name. */
+ symlink_path = hashmap_get(config_path_reverse, name);
+ found_dest = (symlink_path != NULL);
+
+ /* Choose a strategy to determine if the unit's name matches the
+ * symlink's name. If the reverse lookup succeeded, we can skip
+ * the forward lookup. */
+ if (found_dest) {
+ if (path_is_absolute(name))
+ found_path = path_equal(symlink_path, name);
+ else
+ found_path = streq(basename(symlink_path), name);
+ } else {
+ symlink_target_path = hashmap_get(config_path_forward, name);
+ found_path = (symlink_target_path != NULL);
}
+
+ if (found_path && found_dest) {
+ _cleanup_free_ char *t = NULL;
+
+ /* Filter out same name links in the main config path */
+ t = path_make_absolute(name, config_path);
+ if (!t)
+ return -ENOMEM;
+
+ b = path_equal(t, symlink_path);
+ }
+
+ if (b)
+ *same_name_link = true;
+ else if (found_path || found_dest)
+ return 1;
+
+ return 0;
}
static int find_symlinks(
const char *name,
const char *config_path,
- bool *same_name_link) {
+ bool *same_name_link,
+ EnabledContext *ec) {
int fd;
@@ -521,14 +681,15 @@ static int find_symlinks(
}
/* This takes possession of fd and closes it */
- return find_symlinks_fd(name, fd, config_path, config_path,
same_name_link);
+ return find_symlinks_fd(name, fd, config_path, config_path,
same_name_link, ec);
}
static int find_symlinks_in_scope(
UnitFileScope scope,
const char *root_dir,
const char *name,
- UnitFileState *state) {
+ UnitFileState *state,
+ EnabledContext *ec) {
int r;
_cleanup_free_ char *path = NULL;
@@ -544,7 +705,7 @@ static int find_symlinks_in_scope(
if (r < 0)
return r;
- r = find_symlinks(name, path, &same_name_link_runtime);
+ r = find_symlinks(name, path, &same_name_link_runtime, ec);
if (r < 0)
return r;
else if (r > 0) {
@@ -557,7 +718,7 @@ static int find_symlinks_in_scope(
if (r < 0)
return r;
- r = find_symlinks(name, path, &same_name_link);
+ r = find_symlinks(name, path, &same_name_link, ec);
if (r < 0)
return r;
else if (r > 0) {
@@ -1687,7 +1848,8 @@ int unit_file_get_default(
UnitFileState unit_file_get_state(
UnitFileScope scope,
const char *root_dir,
- const char *name) {
+ const char *name,
+ EnabledContext *ec) {
_cleanup_lookup_paths_free_ LookupPaths paths = {};
UnitFileState state = _UNIT_FILE_STATE_INVALID;
@@ -1750,7 +1912,7 @@ UnitFileState unit_file_get_state(
}
}
- r = find_symlinks_in_scope(scope, root_dir, name, &state);
+ r = find_symlinks_in_scope(scope, root_dir, name, &state, ec);
if (r < 0)
return r;
else if (r > 0)
@@ -2033,7 +2195,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*,
unit_file_list_free_one);
int unit_file_get_list(
UnitFileScope scope,
const char *root_dir,
- Hashmap *h) {
+ Hashmap *h,
+ EnabledContext *ec) {
_cleanup_lookup_paths_free_ LookupPaths paths = {};
char **i;
@@ -2117,7 +2280,7 @@ int unit_file_get_list(
goto found;
}
- r = find_symlinks_in_scope(scope, root_dir,
de->d_name, &f->state);
+ r = find_symlinks_in_scope(scope, root_dir,
de->d_name, &f->state, ec);
if (r < 0)
return r;
else if (r > 0) {
@@ -2149,7 +2312,10 @@ int unit_file_get_list(
}
}
- return r;
+ /* The 1 that hashmap_put in the "found" section returns on
+ * successful put can get here. No valid error r value can
+ * get here. */
+ return 0;
}
static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
diff --git a/src/shared/install.h b/src/shared/install.h
index ff16d9f..fd3d1e3 100644
--- a/src/shared/install.h
+++ b/src/shared/install.h
@@ -83,6 +83,11 @@ typedef struct {
char *default_instance;
} InstallInfo;
+typedef struct {
+ Hashmap* config_paths_forward; /* config_path string =>
symlink name/path => unit_name path */
+ Hashmap* config_paths_reverse; /* config_path string =>
unit_name/path string => symlink path */
+} EnabledContext;
+
int unit_file_enable(UnitFileScope scope, bool runtime, const char
*root_dir, char **files, bool force, UnitFileChange **changes,
unsigned *n_changes);
int unit_file_disable(UnitFileScope scope, bool runtime, const char
*root_dir, char **files, UnitFileChange **changes, unsigned
*n_changes);
int unit_file_reenable(UnitFileScope scope, bool runtime, const char
*root_dir, char **files, bool force, UnitFileChange **changes,
unsigned *n_changes);
@@ -94,9 +99,9 @@ int unit_file_unmask(UnitFileScope scope, bool
runtime, const char *root_dir, ch
int unit_file_set_default(UnitFileScope scope, const char *root_dir,
const char *file, bool force, UnitFileChange **changes, unsigned
*n_changes);
int unit_file_get_default(UnitFileScope scope, const char *root_dir,
char **name);
-UnitFileState unit_file_get_state(UnitFileScope scope, const char
*root_dir, const char *filename);
+UnitFileState unit_file_get_state(UnitFileScope scope, const char
*root_dir, const char *filename, EnabledContext *ec);
-int unit_file_get_list(UnitFileScope scope, const char *root_dir, Hashmap *h);
+int unit_file_get_list(UnitFileScope scope, const char *root_dir,
Hashmap *h, EnabledContext *ec);
void unit_file_list_free(Hashmap *h);
void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes);
@@ -109,5 +114,12 @@ UnitFileState unit_file_state_from_string(const
char *s) _pure_;
const char *unit_file_change_type_to_string(UnitFileChangeType s) _const_;
UnitFileChangeType unit_file_change_type_from_string(const char *s) _pure_;
+EnabledContext *enabled_context_new(void);
+void enabled_context_free(EnabledContext *ec);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(EnabledContext*, enabled_context_free);
+
+#define _cleanup_enabled_context_ _cleanup_(enabled_context_freep)
+
const char *unit_file_preset_mode_to_string(UnitFilePresetMode m) _const_;
UnitFilePresetMode unit_file_preset_mode_from_string(const char *s) _pure_;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 1c6fef4..b3f491a 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -1342,7 +1342,7 @@ static int list_unit_files(sd_bus *bus, char **args) {
if (!h)
return log_oom();
- r = unit_file_get_list(arg_scope, arg_root, h);
+ r = unit_file_get_list(arg_scope, arg_root, h, NULL);
if (r < 0) {
unit_file_list_free(h);
log_error("Failed to get unit file list: %s",
strerror(-r));
@@ -5366,7 +5366,7 @@ static int unit_is_enabled(sd_bus *bus, char **args) {
STRV_FOREACH(name, names) {
UnitFileState state;
- state = unit_file_get_state(arg_scope,
arg_root, *name);
+ state = unit_file_get_state(arg_scope,
arg_root, *name, NULL);
if (state < 0) {
log_error("Failed to get unit file
state for %s: %s", *name, strerror(-state));
return state;
diff --git a/src/test/test-enabled.c b/src/test/test-enabled.c
new file mode 100644
index 0000000..fa5d596
--- /dev/null
+++ b/src/test/test-enabled.c
@@ -0,0 +1,151 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Pantheon, Inc.
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#include "util.h"
+#include "path-util.h"
+#include "unit-name.h"
+#include "install.h"
+
+/*
+.
+├── etc
+│ └── systemd
+│ └── system
+│ ├── masked.service -> /dev/null
+│ ├── maskedstatic.service -> /dev/null
+│ ├── some.target
+│ └── some.target.wants
+│ ├── another.service ->
../../../../usr/lib/systemd/system/another.service
+│ ├── aliased.service ->
../../../../usr/lib/systemd/system/another.service
+│ ├── different.service ->
../../../../usr/lib/systemd/system/unique.service
+│ ├── masked.service ->
../../../../usr/lib/systemd/system/masked.service
+│ ├── also_masked.service ->
../../../../usr/lib/systemd/system/masked.service
+│ ├── templating at one.service ->
../../../../usr/lib/systemd/system/templating at .service
+│ ├── templating at two.service ->
../../../../usr/lib/systemd/system/templating at two.service
+│ ├── templating at three.service ->
../../../../usr/lib/systemd/system/templating at .service
+│ └── templating at four.service ->
../../../../usr/lib/systemd/system/templating at four.service
+├── run
+│ └── systemd
+│ └── system
+│ ├── maskedruntime.service -> /dev/null
+│ ├── maskedruntimestatic.service -> /dev/null
+│ ├── other.target
+│ └── other.target.wants
+│ └── runtime.service ->
../../../../usr/lib/systemd/system/runtime.service
+└── usr
+ └── lib
+ └── systemd
+ └── system
+ ├── invalid.service
+ ├── disabled.service
+ ├── another.service
+ ├── runtime.service
+ ├── masked.service
+ ├── maskedruntime.service
+ ├── static.service
+ ├── maskedstatic.service
+ ├── maskedruntimestatic.service
+ ├── templating at .service
+ ├── templating at two.service
+ ├── templating at three.service
+ └── unique.service
+*/
+
+
+#define confirm_unit_state(unit, expected) \
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
unit, ec) == expected)
+
+static void test_enabled(int argc, char* argv[], EnabledContext *ec) {
+ Hashmap *h;
+ UnitFileList *p;
+ Iterator i;
+ int r;
+ const char *root_dir;
+
+ root_dir = strappenda(TEST_DIR, "/test-enabled-root");
+
+ /* Explicitly check each of the units. */
+ confirm_unit_state("nonexistent.service", -ENOENT);
+ confirm_unit_state("invalid.service", -EBADMSG);
+ confirm_unit_state("disabled.service", UNIT_FILE_DISABLED);
+ confirm_unit_state("another.service", UNIT_FILE_ENABLED);
+ confirm_unit_state("runtime.service", UNIT_FILE_ENABLED_RUNTIME);
+ confirm_unit_state("masked.service", UNIT_FILE_MASKED);
+ confirm_unit_state("maskedruntime.service", UNIT_FILE_MASKED_RUNTIME);
+ confirm_unit_state("static.service", UNIT_FILE_STATIC);
+ confirm_unit_state("maskedstatic.service", UNIT_FILE_MASKED);
+ confirm_unit_state("maskedruntimestatic.service",
UNIT_FILE_MASKED_RUNTIME);
+ confirm_unit_state("templating at .service", UNIT_FILE_ENABLED);
+ confirm_unit_state("templating at two.service", UNIT_FILE_ENABLED);
+ confirm_unit_state("templating at three.service", UNIT_FILE_ENABLED);
+ confirm_unit_state("unique.service", UNIT_FILE_ENABLED);
+
+ /* Reconcile unit_file_get_list with the return for each unit. */
+ h = hashmap_new(&string_hash_ops);
+ r = unit_file_get_list(UNIT_FILE_SYSTEM, root_dir, h, ec);
+ assert_se(r == 0);
+ HASHMAP_FOREACH(p, h, i) {
+ UnitFileState s;
+
+ s = unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
+ basename(p->path), ec);
+
+ /* unit_file_get_list and unit_file_get_state are
+ * a little different in some cases. Handle these
+ * cases here ...
+ */
+ switch ((int)s) {
+ case UNIT_FILE_ENABLED_RUNTIME:
+ assert_se(p->state == UNIT_FILE_ENABLED);
+ break;
+ case -EBADMSG:
+ assert_se(p->state == UNIT_FILE_INVALID);
+ break;
+ default:
+ assert_se(p->state == s);
+ break;
+ }
+
+ fprintf(stderr, "%s (%s)\n",
+ p->path,
+ unit_file_state_to_string(p->state));
+ }
+ unit_file_list_free(h);
+}
+
+int main(int argc, char* argv[]) {
+ _cleanup_enabled_context_ EnabledContext *ec = NULL;
+
+ /* built-in EnabledContext */
+ test_enabled(argc, argv, NULL);
+
+ /* explicit EnabledContext */
+ ec = enabled_context_new();
+ assert(ec);
+ test_enabled(argc, argv, ec);
+
+ return 0;
+}
diff --git a/src/test/test-install.c b/src/test/test-install.c
index 467970b..0c8c05b 100644
--- a/src/test/test-install.c
+++ b/src/test/test-install.c
@@ -41,24 +41,25 @@ static void dump_changes(UnitFileChange *c, unsigned n) {
}
}
-int main(int argc, char* argv[]) {
+static void test_install(int argc, char* argv[], EnabledContext *ec) {
Hashmap *h;
UnitFileList *p;
Iterator i;
int r;
- const char *const files[] = { "avahi-daemon.service", NULL };
+ const char *root_dir = argv[1] ?: NULL;
+ const char *const files[] = { "systemd-timesyncd.service", NULL };
const char *const files2[] = { "/home/lennart/test.service", NULL };
UnitFileChange *changes = NULL;
unsigned n_changes = 0;
h = hashmap_new(&string_hash_ops);
- r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
+ r = unit_file_get_list(UNIT_FILE_SYSTEM, root_dir, h, ec);
assert_se(r == 0);
HASHMAP_FOREACH(p, h, i) {
UnitFileState s;
- s = unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
basename(p->path));
+ s = unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
basename(p->path), ec);
assert_se(p->state == s);
@@ -71,195 +72,205 @@ int main(int argc, char* argv[]) {
log_error("enable");
- r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**)
files, false, &changes, &n_changes);
+ r = unit_file_enable(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files, false, &changes, &n_changes);
assert_se(r >= 0);
log_error("enable2");
- r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**)
files, false, &changes, &n_changes);
+ r = unit_file_enable(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files, false, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
files[0]) == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
files[0], ec) == UNIT_FILE_ENABLED);
log_error("disable");
changes = NULL;
n_changes = 0;
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**)
files, &changes, &n_changes);
+ r = unit_file_disable(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
files[0]) == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
files[0], ec) == UNIT_FILE_DISABLED);
log_error("mask");
changes = NULL;
n_changes = 0;
- r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**)
files, false, &changes, &n_changes);
+ r = unit_file_mask(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files, false, &changes, &n_changes);
assert_se(r >= 0);
log_error("mask2");
- r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**)
files, false, &changes, &n_changes);
+ r = unit_file_mask(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files, false, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
files[0]) == UNIT_FILE_MASKED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
files[0], ec) == UNIT_FILE_MASKED);
log_error("unmask");
changes = NULL;
n_changes = 0;
- r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**)
files, &changes, &n_changes);
+ r = unit_file_unmask(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files, &changes, &n_changes);
assert_se(r >= 0);
log_error("unmask2");
- r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**)
files, &changes, &n_changes);
+ r = unit_file_unmask(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
files[0]) == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
files[0], ec) == UNIT_FILE_DISABLED);
log_error("mask");
changes = NULL;
n_changes = 0;
- r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**)
files, false, &changes, &n_changes);
+ r = unit_file_mask(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files, false, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
files[0]) == UNIT_FILE_MASKED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
files[0], ec) == UNIT_FILE_MASKED);
log_error("disable");
changes = NULL;
n_changes = 0;
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**)
files, &changes, &n_changes);
+ r = unit_file_disable(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files, &changes, &n_changes);
assert_se(r >= 0);
log_error("disable2");
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**)
files, &changes, &n_changes);
+ r = unit_file_disable(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
files[0]) == UNIT_FILE_MASKED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
files[0], ec) == UNIT_FILE_MASKED);
log_error("umask");
changes = NULL;
n_changes = 0;
- r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**)
files, &changes, &n_changes);
+ r = unit_file_unmask(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
files[0]) == UNIT_FILE_DISABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
files[0], ec) == UNIT_FILE_DISABLED);
log_error("enable files2");
changes = NULL;
n_changes = 0;
- r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**)
files2, false, &changes, &n_changes);
+ r = unit_file_enable(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files2, false, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
basename(files2[0])) == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
basename(files2[0]), ec) == UNIT_FILE_ENABLED);
log_error("disable files2");
changes = NULL;
n_changes = 0;
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**)
files2, &changes, &n_changes);
+ r = unit_file_disable(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files2, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
basename(files2[0])) == _UNIT_FILE_STATE_INVALID);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
basename(files2[0]), ec) == _UNIT_FILE_STATE_INVALID);
log_error("link files2");
changes = NULL;
n_changes = 0;
- r = unit_file_link(UNIT_FILE_SYSTEM, false, NULL, (char**)
files2, false, &changes, &n_changes);
+ r = unit_file_link(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files2, false, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
basename(files2[0])) == UNIT_FILE_LINKED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
basename(files2[0]), ec) == UNIT_FILE_LINKED);
log_error("disable files2");
changes = NULL;
n_changes = 0;
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**)
files2, &changes, &n_changes);
+ r = unit_file_disable(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files2, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
basename(files2[0])) == _UNIT_FILE_STATE_INVALID);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
basename(files2[0]), ec) == _UNIT_FILE_STATE_INVALID);
log_error("link files2");
changes = NULL;
n_changes = 0;
- r = unit_file_link(UNIT_FILE_SYSTEM, false, NULL, (char**)
files2, false, &changes, &n_changes);
+ r = unit_file_link(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files2, false, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
basename(files2[0])) == UNIT_FILE_LINKED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
basename(files2[0]), ec) == UNIT_FILE_LINKED);
log_error("reenable files2");
changes = NULL;
n_changes = 0;
- r = unit_file_reenable(UNIT_FILE_SYSTEM, false, NULL,
(char**) files2, false, &changes, &n_changes);
+ r = unit_file_reenable(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files2, false, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
basename(files2[0])) == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
basename(files2[0]), ec) == UNIT_FILE_ENABLED);
log_error("disable files2");
changes = NULL;
n_changes = 0;
- r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**)
files2, &changes, &n_changes);
+ r = unit_file_disable(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files2, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
basename(files2[0])) == _UNIT_FILE_STATE_INVALID);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
basename(files2[0]), ec) == _UNIT_FILE_STATE_INVALID);
log_error("preset files");
changes = NULL;
n_changes = 0;
- r = unit_file_preset(UNIT_FILE_SYSTEM, false, NULL, (char**)
files, UNIT_FILE_PRESET_FULL, false, &changes, &n_changes);
+ r = unit_file_preset(UNIT_FILE_SYSTEM, false, root_dir,
(char**) files, UNIT_FILE_PRESET_FULL, false, &changes, &n_changes);
assert_se(r >= 0);
dump_changes(changes, n_changes);
unit_file_changes_free(changes, n_changes);
- assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, NULL,
basename(files[0])) == UNIT_FILE_ENABLED);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root_dir,
basename(files[0]), ec) == UNIT_FILE_ENABLED);
+}
+
+int main(int argc, char* argv[]) {
+ EnabledContext *ec;
+
+ test_install(argc, argv, NULL);
+
+ ec = enabled_context_new();
+ assert(ec);
+ test_install(argc, argv, ec);
return 0;
}
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index 03b3e25..227ec10 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -47,7 +47,7 @@ static int test_unit_file_get_set(void) {
h = hashmap_new(&string_hash_ops);
assert_se(h);
- r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
+ r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL);
if (r == -EPERM || r == -EACCES) {
printf("Skipping test: unit_file_get_list: %s", strerror(-r));
diff --git a/test/test-enabled-root/etc/systemd/system/masked.service
b/test/test-enabled-root/etc/systemd/system/masked.service
new file mode 120000
index 0000000..dc1dc0c
--- /dev/null
+++ b/test/test-enabled-root/etc/systemd/system/masked.service
@@ -0,0 +1 @@
+/dev/null
\ No newline at end of file
diff --git a/test/test-enabled-root/etc/systemd/system/maskedstatic.service
b/test/test-enabled-root/etc/systemd/system/maskedstatic.service
new file mode 120000
index 0000000..dc1dc0c
--- /dev/null
+++ b/test/test-enabled-root/etc/systemd/system/maskedstatic.service
@@ -0,0 +1 @@
+/dev/null
\ No newline at end of file
diff --git a/test/test-enabled-root/etc/systemd/system/some.target
b/test/test-enabled-root/etc/systemd/system/some.target
new file mode 100644
index 0000000..06eb04e
--- /dev/null
+++ b/test/test-enabled-root/etc/systemd/system/some.target
@@ -0,0 +1,11 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Some sort of target.
+Requires=multi-user.target
+After=multi-user.target
diff --git a/test/test-enabled-root/etc/systemd/system/some.target.wants/aliased.service
b/test/test-enabled-root/etc/systemd/system/some.target.wants/aliased.service
new file mode 120000
index 0000000..fec3d43
--- /dev/null
+++ b/test/test-enabled-root/etc/systemd/system/some.target.wants/aliased.service
@@ -0,0 +1 @@
+../../../../usr/lib/systemd/system/another.service
\ No newline at end of file
diff --git a/test/test-enabled-root/etc/systemd/system/some.target.wants/also_masked.service
b/test/test-enabled-root/etc/systemd/system/some.target.wants/also_masked.service
new file mode 120000
index 0000000..322a87b
--- /dev/null
+++ b/test/test-enabled-root/etc/systemd/system/some.target.wants/also_masked.service
@@ -0,0 +1 @@
+../../../../usr/lib/systemd/system/masked.service
\ No newline at end of file
diff --git a/test/test-enabled-root/etc/systemd/system/some.target.wants/another.service
b/test/test-enabled-root/etc/systemd/system/some.target.wants/another.service
new file mode 120000
index 0000000..fec3d43
--- /dev/null
+++ b/test/test-enabled-root/etc/systemd/system/some.target.wants/another.service
@@ -0,0 +1 @@
+../../../../usr/lib/systemd/system/another.service
\ No newline at end of file
diff --git a/test/test-enabled-root/etc/systemd/system/some.target.wants/different.service
b/test/test-enabled-root/etc/systemd/system/some.target.wants/different.service
new file mode 120000
index 0000000..40b36c8
--- /dev/null
+++ b/test/test-enabled-root/etc/systemd/system/some.target.wants/different.service
@@ -0,0 +1 @@
+../../../../usr/lib/systemd/system/unique.service
\ No newline at end of file
diff --git a/test/test-enabled-root/etc/systemd/system/some.target.wants/masked.service
b/test/test-enabled-root/etc/systemd/system/some.target.wants/masked.service
new file mode 120000
index 0000000..322a87b
--- /dev/null
+++ b/test/test-enabled-root/etc/systemd/system/some.target.wants/masked.service
@@ -0,0 +1 @@
+../../../../usr/lib/systemd/system/masked.service
\ No newline at end of file
diff --git a/test/test-enabled-root/etc/systemd/system/some.target.wants/templating at four.service
b/test/test-enabled-root/etc/systemd/system/some.target.wants/templating at four.service
new file mode 120000
index 0000000..7ccde6b
--- /dev/null
+++ b/test/test-enabled-root/etc/systemd/system/some.target.wants/templating at four.service
@@ -0,0 +1 @@
+../../../../usr/lib/systemd/system/templating at four.service
\ No newline at end of file
diff --git a/test/test-enabled-root/etc/systemd/system/some.target.wants/templating at one.service
b/test/test-enabled-root/etc/systemd/system/some.target.wants/templating at one.service
new file mode 120000
index 0000000..16f781d
--- /dev/null
+++ b/test/test-enabled-root/etc/systemd/system/some.target.wants/templating at one.service
@@ -0,0 +1 @@
+../../../../usr/lib/systemd/system/templating at .service
\ No newline at end of file
diff --git a/test/test-enabled-root/etc/systemd/system/some.target.wants/templating at three.service
b/test/test-enabled-root/etc/systemd/system/some.target.wants/templating at three.service
new file mode 120000
index 0000000..16f781d
--- /dev/null
+++ b/test/test-enabled-root/etc/systemd/system/some.target.wants/templating at three.service
@@ -0,0 +1 @@
+../../../../usr/lib/systemd/system/templating at .service
\ No newline at end of file
diff --git a/test/test-enabled-root/etc/systemd/system/some.target.wants/templating at two.service
b/test/test-enabled-root/etc/systemd/system/some.target.wants/templating at two.service
new file mode 120000
index 0000000..ee2c510
--- /dev/null
+++ b/test/test-enabled-root/etc/systemd/system/some.target.wants/templating at two.service
@@ -0,0 +1 @@
+../../../../usr/lib/systemd/system/templating at two.service
\ No newline at end of file
diff --git a/test/test-enabled-root/run/systemd/system/maskedruntime.service
b/test/test-enabled-root/run/systemd/system/maskedruntime.service
new file mode 120000
index 0000000..dc1dc0c
--- /dev/null
+++ b/test/test-enabled-root/run/systemd/system/maskedruntime.service
@@ -0,0 +1 @@
+/dev/null
\ No newline at end of file
diff --git a/test/test-enabled-root/run/systemd/system/maskedruntimestatic.service
b/test/test-enabled-root/run/systemd/system/maskedruntimestatic.service
new file mode 120000
index 0000000..dc1dc0c
--- /dev/null
+++ b/test/test-enabled-root/run/systemd/system/maskedruntimestatic.service
@@ -0,0 +1 @@
+/dev/null
\ No newline at end of file
diff --git a/test/test-enabled-root/run/systemd/system/other.target
b/test/test-enabled-root/run/systemd/system/other.target
new file mode 100644
index 0000000..0f54eb3
--- /dev/null
+++ b/test/test-enabled-root/run/systemd/system/other.target
@@ -0,0 +1,14 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Other Target
+Requires=multi-user.target
+After=multi-user.target
+Conflicts=rescue.target
+Wants=display-manager.service
+AllowIsolate=yes
diff --git a/test/test-enabled-root/run/systemd/system/other.target.wants/runtime.service
b/test/test-enabled-root/run/systemd/system/other.target.wants/runtime.service
new file mode 120000
index 0000000..a28ebda
--- /dev/null
+++ b/test/test-enabled-root/run/systemd/system/other.target.wants/runtime.service
@@ -0,0 +1 @@
+../../../../usr/lib/systemd/system/runtime.service
\ No newline at end of file
diff --git a/test/test-enabled-root/usr/lib/systemd/system/another.service
b/test/test-enabled-root/usr/lib/systemd/system/another.service
new file mode 100644
index 0000000..e4ea7f3
--- /dev/null
+++ b/test/test-enabled-root/usr/lib/systemd/system/another.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Another Service
+
+[Service]
+Type=oneshot
+ExecStart=/bin/echo "Another Service Start"
+
+[Install]
+WantedBy=some.target
diff --git a/test/test-enabled-root/usr/lib/systemd/system/disabled.service
b/test/test-enabled-root/usr/lib/systemd/system/disabled.service
new file mode 100644
index 0000000..f1d1fc6
--- /dev/null
+++ b/test/test-enabled-root/usr/lib/systemd/system/disabled.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Disabled Service
+
+[Service]
+Type=oneshot
+ExecStart=/bin/echo "Disabled Service Start"
+
+[Install]
+WantedBy=some.target
diff --git a/test/test-enabled-root/usr/lib/systemd/system/invalid.service
b/test/test-enabled-root/usr/lib/systemd/system/invalid.service
new file mode 100644
index 0000000..e420fe4
--- /dev/null
+++ b/test/test-enabled-root/usr/lib/systemd/system/invalid.service
@@ -0,0 +1 @@
+INVALID
diff --git a/test/test-enabled-root/usr/lib/systemd/system/masked.service
b/test/test-enabled-root/usr/lib/systemd/system/masked.service
new file mode 100644
index 0000000..7a64302
--- /dev/null
+++ b/test/test-enabled-root/usr/lib/systemd/system/masked.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Masked Service
+
+[Service]
+Type=oneshot
+ExecStart=/bin/echo "Masked Service Start"
+
+[Install]
+WantedBy=some.target
diff --git a/test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
b/test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
new file mode 100644
index 0000000..db50f6e
--- /dev/null
+++ b/test/test-enabled-root/usr/lib/systemd/system/maskedruntime.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Masked Runtime Service
+
+[Service]
+Type=oneshot
+ExecStart=/bin/echo "Masked Runtime Service Start"
+
+[Install]
+WantedBy=some.target
diff --git a/test/test-enabled-root/usr/lib/systemd/system/maskedruntimestatic.service
b/test/test-enabled-root/usr/lib/systemd/system/maskedruntimestatic.service
new file mode 100644
index 0000000..d2a95d2
--- /dev/null
+++ b/test/test-enabled-root/usr/lib/systemd/system/maskedruntimestatic.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=Masked Runtime Static Service
+
+[Service]
+Type=oneshot
+ExecStart=/bin/echo "Masked Runtime Static Service Start"
diff --git a/test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service
b/test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service
new file mode 100644
index 0000000..dd2ff1e
--- /dev/null
+++ b/test/test-enabled-root/usr/lib/systemd/system/maskedstatic.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=Masked Static Service
+
+[Service]
+Type=oneshot
+ExecStart=/bin/echo "Masked Static Service Start"
diff --git a/test/test-enabled-root/usr/lib/systemd/system/runtime.service
b/test/test-enabled-root/usr/lib/systemd/system/runtime.service
new file mode 100644
index 0000000..0b24bd0
--- /dev/null
+++ b/test/test-enabled-root/usr/lib/systemd/system/runtime.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Runtime Service
+
+[Service]
+Type=oneshot
+ExecStart=/bin/echo "Runtime Service Start"
+
+[Install]
+WantedBy=other.target
diff --git a/test/test-enabled-root/usr/lib/systemd/system/static.service
b/test/test-enabled-root/usr/lib/systemd/system/static.service
new file mode 100644
index 0000000..a5f6c11
--- /dev/null
+++ b/test/test-enabled-root/usr/lib/systemd/system/static.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=Static Service
+
+[Service]
+Type=oneshot
+ExecStart=/bin/echo "Static Service Start"
diff --git a/test/test-enabled-root/usr/lib/systemd/system/templating at .service
b/test/test-enabled-root/usr/lib/systemd/system/templating at .service
new file mode 100644
index 0000000..57a8c9d
--- /dev/null
+++ b/test/test-enabled-root/usr/lib/systemd/system/templating at .service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Templating Service
+
+[Service]
+Type=oneshot
+ExecStart=/bin/echo "Templating Service Start"
+
+[Install]
+WantedBy=some.target
diff --git a/test/test-enabled-root/usr/lib/systemd/system/templating at three.service
b/test/test-enabled-root/usr/lib/systemd/system/templating at three.service
new file mode 100644
index 0000000..d2b2d6c
--- /dev/null
+++ b/test/test-enabled-root/usr/lib/systemd/system/templating at three.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Templating Three Service
+
+[Service]
+Type=oneshot
+ExecStart=/bin/echo "Templating Three Start"
+
+[Install]
+WantedBy=some.target
diff --git a/test/test-enabled-root/usr/lib/systemd/system/templating at two.service
b/test/test-enabled-root/usr/lib/systemd/system/templating at two.service
new file mode 100644
index 0000000..3517229
--- /dev/null
+++ b/test/test-enabled-root/usr/lib/systemd/system/templating at two.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Templating Two
+
+[Service]
+Type=oneshot
+ExecStart=/bin/echo "Templating Two Start"
+
+[Install]
+WantedBy=some.target
diff --git a/test/test-enabled-root/usr/lib/systemd/system/unique.service
b/test/test-enabled-root/usr/lib/systemd/system/unique.service
new file mode 100644
index 0000000..efd176f
--- /dev/null
+++ b/test/test-enabled-root/usr/lib/systemd/system/unique.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Unique Service
+
+[Service]
+Type=oneshot
+ExecStart=/bin/echo "Unique Service Start"
+
+[Install]
+WantedBy=some.target
--
1.9.3
More information about the systemd-devel
mailing list