mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-18 06:03:42 +03:00
Merge pull request #1515 from poettering/install-symlink
install: follow unit file symlinks in /usr, but not /etc when looking for [Install] data and more
This commit is contained in:
commit
f1637bd3a8
@ -1493,7 +1493,8 @@ tests += \
|
|||||||
test-verbs \
|
test-verbs \
|
||||||
test-af-list \
|
test-af-list \
|
||||||
test-arphrd-list \
|
test-arphrd-list \
|
||||||
test-dns-domain
|
test-dns-domain \
|
||||||
|
test-install-root
|
||||||
|
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST += \
|
||||||
test/a.service \
|
test/a.service \
|
||||||
@ -1836,6 +1837,12 @@ test_verbs_SOURCES = \
|
|||||||
test_verbs_LDADD = \
|
test_verbs_LDADD = \
|
||||||
libshared.la
|
libshared.la
|
||||||
|
|
||||||
|
test_install_root_SOURCES = \
|
||||||
|
src/test/test-install-root.c
|
||||||
|
|
||||||
|
test_install_root_LDADD = \
|
||||||
|
libshared.la
|
||||||
|
|
||||||
test_namespace_LDADD = \
|
test_namespace_LDADD = \
|
||||||
libcore.la
|
libcore.la
|
||||||
|
|
||||||
|
@ -961,10 +961,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
|
|||||||
<term><command>list-unit-files <optional><replaceable>PATTERN...</replaceable></optional></command></term>
|
<term><command>list-unit-files <optional><replaceable>PATTERN...</replaceable></optional></command></term>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>List installed unit files. If one or more
|
<para>List installed unit files and their enablement state
|
||||||
<replaceable>PATTERN</replaceable>s are specified, only
|
(as reported by <command>is-enabled</command>). If one or
|
||||||
units whose filename (just the last component of the path)
|
more <replaceable>PATTERN</replaceable>s are specified,
|
||||||
matches one of them are shown.</para>
|
only units whose filename (just the last component of the
|
||||||
|
path) matches one of them are shown.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
@ -1134,7 +1135,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
|
|||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal>enabled</literal></entry>
|
<entry><literal>enabled</literal></entry>
|
||||||
<entry morerows='1'>Enabled through a symlink in <filename>.wants</filename> directory (permanently or just in <filename>/run</filename>).</entry>
|
<entry morerows='1'>Enabled through a symlink in a <filename>.wants/</filename> or <filename>.requires/</filename> subdirectory of <filename>/etc/systemd/system/</filename> (persistently) or <filename>/run/systemd/system/</filename> (transiently).</entry>
|
||||||
<entry morerows='1'>0</entry>
|
<entry morerows='1'>0</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
@ -1142,7 +1143,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
|
|||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal>linked</literal></entry>
|
<entry><literal>linked</literal></entry>
|
||||||
<entry morerows='1'>Made available through a symlink to the unit file (permanently or just in <filename>/run</filename>).</entry>
|
<entry morerows='1'>Made available through one or more symlinks to the unit file (permanently in <filename>/etc/systemd/system/</filename> or transiently in <filename>/run/systemd/system/</filename>), even though the unit file might reside outside of the unit file search path.</entry>
|
||||||
<entry morerows='1'>> 0</entry>
|
<entry morerows='1'>> 0</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
@ -1150,7 +1151,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
|
|||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal>masked</literal></entry>
|
<entry><literal>masked</literal></entry>
|
||||||
<entry morerows='1'>Disabled entirely (permanently or just in <filename>/run</filename>).</entry>
|
<entry morerows='1'>Completely disabled, so that any start operation on it fails (permanently in <filename>/etc/systemd/system/</filename> or transiently in <filename>/run/systemd/systemd/</filename>).</entry>
|
||||||
<entry morerows='1'>> 0</entry>
|
<entry morerows='1'>> 0</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
@ -1168,7 +1169,12 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
|
|||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal>disabled</literal></entry>
|
<entry><literal>disabled</literal></entry>
|
||||||
<entry>The unit file is not enabled.</entry>
|
<entry>Unit file is not enabled, but contains an <literal>[Install]</literal> section with installation instructions.</entry>
|
||||||
|
<entry>> 0</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><literal>bad</literal></entry>
|
||||||
|
<entry>Unit file is invalid or another error occured. Note that <command>is-enabled</command> will not actually return this state, but print an error message instead. However the unit file listing printed by <command>list-unit-files</command> might show it.</entry>
|
||||||
<entry>> 0</entry>
|
<entry>> 0</entry>
|
||||||
</row>
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -1227,22 +1227,22 @@
|
|||||||
<row>
|
<row>
|
||||||
<entry><literal>%u</literal></entry>
|
<entry><literal>%u</literal></entry>
|
||||||
<entry>User name</entry>
|
<entry>User name</entry>
|
||||||
<entry>This is the name of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry>
|
<entry>This is the name of the user running the service manager instance. In case of the system manager this resolves to <literal>root</literal>.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal>%U</literal></entry>
|
<entry><literal>%U</literal></entry>
|
||||||
<entry>User UID</entry>
|
<entry>User UID</entry>
|
||||||
<entry>This is the numeric UID of the configured user of the unit, or (if none is set) the user running the systemd user instance. Note that this specifier is not available for units run by the systemd system instance (as opposed to those run by a systemd user instance), unless the user has been configured as a numeric UID in the first place or the configured user is the root user.</entry>
|
<entry>This is the numeric UID of the user running the service manager instance. In case of the system manager this resolves to <literal>0</literal>.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal>%h</literal></entry>
|
<entry><literal>%h</literal></entry>
|
||||||
<entry>User home directory</entry>
|
<entry>User home directory</entry>
|
||||||
<entry>This is the home directory of the configured user of the unit, or (if none is set) the user running the systemd user instance. Similar to <literal>%U</literal>, this specifier is not available for units run by the systemd system instance, unless the configured user is the root user.</entry>
|
<entry>This is the home directory of the user running the service manager instance. In case of the system manager this resolves to <literal>/root</literal>.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal>%s</literal></entry>
|
<entry><literal>%s</literal></entry>
|
||||||
<entry>User shell</entry>
|
<entry>User shell</entry>
|
||||||
<entry>This is the shell of the configured user of the unit, or (if none is set) the user running the systemd user instance. Similar to <literal>%U</literal>, this specifier is not available for units run by the systemd system instance, unless the configured user is the root user.</entry>
|
<entry>This is the shell of the user running the service manager instance. In case of the system manager this resolves to <literal>/bin/sh</literal>.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal>%m</literal></entry>
|
<entry><literal>%m</literal></entry>
|
||||||
|
@ -233,6 +233,26 @@ int readlink_and_canonicalize(const char *p, char **r) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int readlink_and_make_absolute_root(const char *root, const char *path, char **ret) {
|
||||||
|
_cleanup_free_ char *target = NULL, *t = NULL;
|
||||||
|
const char *full;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
full = prefix_roota(root, path);
|
||||||
|
r = readlink_malloc(full, &target);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
t = file_in_same_dir(path, target);
|
||||||
|
if (!t)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
*ret = t;
|
||||||
|
t = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
|
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
|
||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ int readlink_malloc(const char *p, char **r);
|
|||||||
int readlink_value(const char *p, char **ret);
|
int readlink_value(const char *p, char **ret);
|
||||||
int readlink_and_make_absolute(const char *p, char **r);
|
int readlink_and_make_absolute(const char *p, char **r);
|
||||||
int readlink_and_canonicalize(const char *p, char **r);
|
int readlink_and_canonicalize(const char *p, char **r);
|
||||||
|
int readlink_and_make_absolute_root(const char *root, const char *path, char **ret);
|
||||||
|
|
||||||
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
|
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
|
||||||
int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
|
int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
|
||||||
|
@ -1521,9 +1521,9 @@ static int method_get_unit_file_state(sd_bus_message *message, void *userdata, s
|
|||||||
|
|
||||||
scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
|
scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
|
||||||
|
|
||||||
state = unit_file_get_state(scope, NULL, name);
|
r = unit_file_get_state(scope, NULL, name, &state);
|
||||||
if (state < 0)
|
if (r < 0)
|
||||||
return state;
|
return r;
|
||||||
|
|
||||||
return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
|
return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
|
||||||
}
|
}
|
||||||
@ -1651,6 +1651,8 @@ static int method_enable_unit_files_generic(
|
|||||||
scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
|
scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
|
||||||
|
|
||||||
r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
|
r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
|
||||||
|
if (r == -ESHUTDOWN)
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1885,6 +1887,8 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd
|
|||||||
scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
|
scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
|
||||||
|
|
||||||
r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, force, &changes, &n_changes);
|
r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, force, &changes, &n_changes);
|
||||||
|
if (r == -ESHUTDOWN)
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -159,162 +159,43 @@ static int specifier_runtime(char specifier, void *data, void *userdata, char **
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
|
static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
|
||||||
char *printed = NULL;
|
char *t;
|
||||||
Unit *u = userdata;
|
|
||||||
ExecContext *c;
|
|
||||||
int r = 0;
|
|
||||||
|
|
||||||
assert(u);
|
/* If we are UID 0 (root), this will not result in NSS,
|
||||||
|
* otherwise it might. This is good, as we want to be able to
|
||||||
|
* run this in PID 1, where our user ID is 0, but where NSS
|
||||||
|
* lookups are not allowed. */
|
||||||
|
|
||||||
c = unit_get_exec_context(u);
|
t = getusername_malloc();
|
||||||
if (!c)
|
if (!t)
|
||||||
return -EOPNOTSUPP;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (u->manager->running_as == MANAGER_SYSTEM) {
|
*ret = t;
|
||||||
|
return 0;
|
||||||
/* We cannot use NSS from PID 1, hence try to make the
|
}
|
||||||
* best of it in that case, and fail if we can't help
|
|
||||||
* it */
|
static int specifier_user_id(char specifier, void *data, void *userdata, char **ret) {
|
||||||
|
|
||||||
if (!c->user || streq(c->user, "root") || streq(c->user, "0"))
|
if (asprintf(ret, UID_FMT, getuid()) < 0)
|
||||||
printed = strdup(specifier == 'u' ? "root" : "0");
|
|
||||||
else {
|
|
||||||
if (specifier == 'u')
|
|
||||||
printed = strdup(c->user);
|
|
||||||
else {
|
|
||||||
uid_t uid;
|
|
||||||
|
|
||||||
r = parse_uid(c->user, &uid);
|
|
||||||
if (r < 0)
|
|
||||||
return -ENODATA;
|
|
||||||
|
|
||||||
r = asprintf(&printed, UID_FMT, uid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
_cleanup_free_ char *tmp = NULL;
|
|
||||||
const char *username = NULL;
|
|
||||||
uid_t uid;
|
|
||||||
|
|
||||||
if (c->user)
|
|
||||||
username = c->user;
|
|
||||||
else
|
|
||||||
/* get USER env from env or our own uid */
|
|
||||||
username = tmp = getusername_malloc();
|
|
||||||
|
|
||||||
/* fish username from passwd */
|
|
||||||
r = get_user_creds(&username, &uid, NULL, NULL, NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (specifier == 'u')
|
|
||||||
printed = strdup(username);
|
|
||||||
else
|
|
||||||
r = asprintf(&printed, UID_FMT, uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r < 0 || !printed)
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
*ret = printed;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_user_home(char specifier, void *data, void *userdata, char **ret) {
|
static int specifier_user_home(char specifier, void *data, void *userdata, char **ret) {
|
||||||
Unit *u = userdata;
|
|
||||||
ExecContext *c;
|
|
||||||
char *n;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(u);
|
/* On PID 1 (which runs as root) this will not result in NSS,
|
||||||
|
* which is good. See above */
|
||||||
|
|
||||||
c = unit_get_exec_context(u);
|
return get_home_dir(ret);
|
||||||
if (!c)
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
if (u->manager->running_as == MANAGER_SYSTEM) {
|
|
||||||
|
|
||||||
/* We cannot use NSS from PID 1, hence try to make the
|
|
||||||
* best of it if we can, but fail if we can't */
|
|
||||||
|
|
||||||
if (!c->user || streq(c->user, "root") || streq(c->user, "0"))
|
|
||||||
n = strdup("/root");
|
|
||||||
else
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* return HOME if set, otherwise from passwd */
|
|
||||||
if (!c || !c->user) {
|
|
||||||
r = get_home_dir(&n);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
} else {
|
|
||||||
const char *username, *home;
|
|
||||||
|
|
||||||
username = c->user;
|
|
||||||
r = get_user_creds(&username, NULL, NULL, &home, NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
n = strdup(home);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!n)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
*ret = n;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_user_shell(char specifier, void *data, void *userdata, char **ret) {
|
static int specifier_user_shell(char specifier, void *data, void *userdata, char **ret) {
|
||||||
Unit *u = userdata;
|
|
||||||
ExecContext *c;
|
|
||||||
char *n;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(u);
|
/* On PID 1 (which runs as root) this will not result in NSS,
|
||||||
|
* which is good. See above */
|
||||||
|
|
||||||
c = unit_get_exec_context(u);
|
return get_shell(ret);
|
||||||
if (!c)
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
if (u->manager->running_as == MANAGER_SYSTEM) {
|
|
||||||
|
|
||||||
/* We cannot use NSS from PID 1, hence try to make the
|
|
||||||
* best of it if we can, but fail if we can't */
|
|
||||||
|
|
||||||
if (!c->user || streq(c->user, "root") || streq(c->user, "0"))
|
|
||||||
n = strdup("/bin/sh");
|
|
||||||
else
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* return /bin/sh for root, otherwise the value from passwd */
|
|
||||||
if (!c->user) {
|
|
||||||
r = get_shell(&n);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
} else {
|
|
||||||
const char *username, *shell;
|
|
||||||
|
|
||||||
username = c->user;
|
|
||||||
r = get_user_creds(&username, NULL, NULL, NULL, &shell);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
n = strdup(shell);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!n)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
*ret = n;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int unit_name_printf(Unit *u, const char* format, char **ret) {
|
int unit_name_printf(Unit *u, const char* format, char **ret) {
|
||||||
@ -354,10 +235,10 @@ int unit_full_printf(Unit *u, const char *format, char **ret) {
|
|||||||
* %r where units in this slice are placed in the cgroup tree
|
* %r where units in this slice are placed in the cgroup tree
|
||||||
* %R the root of this systemd's instance tree
|
* %R the root of this systemd's instance tree
|
||||||
* %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
|
* %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
|
||||||
* %U the UID of the configured user or running user
|
* %U the UID of the running user
|
||||||
* %u the username of the configured user or running user
|
* %u the username of the running user
|
||||||
* %h the homedir of the configured user or running user
|
* %h the homedir of the running user
|
||||||
* %s the shell of the configured user or running user
|
* %s the shell of the running user
|
||||||
* %m the machine ID of the running system
|
* %m the machine ID of the running system
|
||||||
* %H the host name of the running system
|
* %H the host name of the running system
|
||||||
* %b the boot ID of the running system
|
* %b the boot ID of the running system
|
||||||
@ -377,7 +258,8 @@ int unit_full_printf(Unit *u, const char *format, char **ret) {
|
|||||||
{ 'r', specifier_cgroup_slice, NULL },
|
{ 'r', specifier_cgroup_slice, NULL },
|
||||||
{ 'R', specifier_cgroup_root, NULL },
|
{ 'R', specifier_cgroup_root, NULL },
|
||||||
{ 't', specifier_runtime, NULL },
|
{ 't', specifier_runtime, NULL },
|
||||||
{ 'U', specifier_user_name, NULL },
|
|
||||||
|
{ 'U', specifier_user_id, NULL },
|
||||||
{ 'u', specifier_user_name, NULL },
|
{ 'u', specifier_user_name, NULL },
|
||||||
{ 'h', specifier_user_home, NULL },
|
{ 'h', specifier_user_home, NULL },
|
||||||
{ 's', specifier_user_shell, NULL },
|
{ 's', specifier_user_shell, NULL },
|
||||||
|
@ -3148,12 +3148,19 @@ int unit_following_set(Unit *u, Set **s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UnitFileState unit_get_unit_file_state(Unit *u) {
|
UnitFileState unit_get_unit_file_state(Unit *u) {
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(u);
|
assert(u);
|
||||||
|
|
||||||
if (u->unit_file_state < 0 && u->fragment_path)
|
if (u->unit_file_state < 0 && u->fragment_path) {
|
||||||
u->unit_file_state = unit_file_get_state(
|
r = unit_file_get_state(
|
||||||
u->manager->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
|
u->manager->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
|
||||||
NULL, basename(u->fragment_path));
|
NULL,
|
||||||
|
basename(u->fragment_path),
|
||||||
|
&u->unit_file_state);
|
||||||
|
if (r < 0)
|
||||||
|
u->unit_file_state = UNIT_FILE_BAD;
|
||||||
|
}
|
||||||
|
|
||||||
return u->unit_file_state;
|
return u->unit_file_state;
|
||||||
}
|
}
|
||||||
@ -3164,7 +3171,8 @@ int unit_get_unit_file_preset(Unit *u) {
|
|||||||
if (u->unit_file_preset < 0 && u->fragment_path)
|
if (u->unit_file_preset < 0 && u->fragment_path)
|
||||||
u->unit_file_preset = unit_file_query_preset(
|
u->unit_file_preset = unit_file_query_preset(
|
||||||
u->manager->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
|
u->manager->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
|
||||||
NULL, basename(u->fragment_path));
|
NULL,
|
||||||
|
basename(u->fragment_path));
|
||||||
|
|
||||||
return u->unit_file_preset;
|
return u->unit_file_preset;
|
||||||
}
|
}
|
||||||
|
@ -67,42 +67,28 @@ static int specifier_instance(char specifier, void *data, void *userdata, char *
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
|
static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
|
||||||
UnitFileInstallInfo *i = userdata;
|
char *t;
|
||||||
const char *username;
|
|
||||||
_cleanup_free_ char *tmp = NULL;
|
|
||||||
char *printed = NULL;
|
|
||||||
|
|
||||||
assert(i);
|
/* If we are UID 0 (root), this will not result in NSS,
|
||||||
|
* otherwise it might. This is good, as we want to be able to
|
||||||
|
* run this in PID 1, where our user ID is 0, but where NSS
|
||||||
|
* lookups are not allowed. */
|
||||||
|
|
||||||
if (i->user)
|
t = getusername_malloc();
|
||||||
username = i->user;
|
if (!t)
|
||||||
else
|
return -ENOMEM;
|
||||||
/* get USER env from env or our own uid */
|
|
||||||
username = tmp = getusername_malloc();
|
|
||||||
|
|
||||||
switch (specifier) {
|
*ret = t;
|
||||||
case 'u':
|
|
||||||
printed = strdup(username);
|
|
||||||
break;
|
|
||||||
case 'U': {
|
|
||||||
/* fish username from passwd */
|
|
||||||
uid_t uid;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = get_user_creds(&username, &uid, NULL, NULL, NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (asprintf(&printed, UID_FMT, uid) < 0)
|
|
||||||
return -ENOMEM;
|
|
||||||
break;
|
|
||||||
}}
|
|
||||||
|
|
||||||
|
|
||||||
*ret = printed;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int specifier_user_id(char specifier, void *data, void *userdata, char **ret) {
|
||||||
|
|
||||||
|
if (asprintf(ret, UID_FMT, getuid()) < 0)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret) {
|
int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret) {
|
||||||
|
|
||||||
@ -114,8 +100,8 @@ int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret)
|
|||||||
* %p: the prefix (foo)
|
* %p: the prefix (foo)
|
||||||
* %i: the instance (bar)
|
* %i: the instance (bar)
|
||||||
|
|
||||||
* %U the UID of the configured user or running user
|
* %U the UID of the running user
|
||||||
* %u the username of the configured user or running user
|
* %u the username of running user
|
||||||
* %m the machine ID of the running system
|
* %m the machine ID of the running system
|
||||||
* %H the host name of the running system
|
* %H the host name of the running system
|
||||||
* %b the boot ID of the running system
|
* %b the boot ID of the running system
|
||||||
@ -128,7 +114,7 @@ int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret)
|
|||||||
{ 'p', specifier_prefix, NULL },
|
{ 'p', specifier_prefix, NULL },
|
||||||
{ 'i', specifier_instance, NULL },
|
{ 'i', specifier_instance, NULL },
|
||||||
|
|
||||||
{ 'U', specifier_user_name, NULL },
|
{ 'U', specifier_user_id, NULL },
|
||||||
{ 'u', specifier_user_name, NULL },
|
{ 'u', specifier_user_name, NULL },
|
||||||
|
|
||||||
{ 'm', specifier_machine_id, NULL },
|
{ 'm', specifier_machine_id, NULL },
|
||||||
|
2456
src/shared/install.c
2456
src/shared/install.c
File diff suppressed because it is too large
Load Diff
@ -25,13 +25,15 @@ typedef enum UnitFileScope UnitFileScope;
|
|||||||
typedef enum UnitFileState UnitFileState;
|
typedef enum UnitFileState UnitFileState;
|
||||||
typedef enum UnitFilePresetMode UnitFilePresetMode;
|
typedef enum UnitFilePresetMode UnitFilePresetMode;
|
||||||
typedef enum UnitFileChangeType UnitFileChangeType;
|
typedef enum UnitFileChangeType UnitFileChangeType;
|
||||||
|
typedef enum UnitFileType UnitFileType;
|
||||||
typedef struct UnitFileChange UnitFileChange;
|
typedef struct UnitFileChange UnitFileChange;
|
||||||
typedef struct UnitFileList UnitFileList;
|
typedef struct UnitFileList UnitFileList;
|
||||||
typedef struct UnitFileInstallInfo UnitFileInstallInfo;
|
typedef struct UnitFileInstallInfo UnitFileInstallInfo;
|
||||||
|
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "unit-name.h"
|
|
||||||
#include "path-lookup.h"
|
#include "path-lookup.h"
|
||||||
|
#include "strv.h"
|
||||||
|
#include "unit-name.h"
|
||||||
|
|
||||||
enum UnitFileScope {
|
enum UnitFileScope {
|
||||||
UNIT_FILE_SYSTEM,
|
UNIT_FILE_SYSTEM,
|
||||||
@ -51,7 +53,7 @@ enum UnitFileState {
|
|||||||
UNIT_FILE_STATIC,
|
UNIT_FILE_STATIC,
|
||||||
UNIT_FILE_DISABLED,
|
UNIT_FILE_DISABLED,
|
||||||
UNIT_FILE_INDIRECT,
|
UNIT_FILE_INDIRECT,
|
||||||
UNIT_FILE_INVALID,
|
UNIT_FILE_BAD,
|
||||||
_UNIT_FILE_STATE_MAX,
|
_UNIT_FILE_STATE_MAX,
|
||||||
_UNIT_FILE_STATE_INVALID = -1
|
_UNIT_FILE_STATE_INVALID = -1
|
||||||
};
|
};
|
||||||
@ -82,10 +84,17 @@ struct UnitFileList {
|
|||||||
UnitFileState state;
|
UnitFileState state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum UnitFileType {
|
||||||
|
UNIT_FILE_TYPE_REGULAR,
|
||||||
|
UNIT_FILE_TYPE_SYMLINK,
|
||||||
|
UNIT_FILE_TYPE_MASKED,
|
||||||
|
_UNIT_FILE_TYPE_MAX,
|
||||||
|
_UNIT_FILE_TYPE_INVALID = -1,
|
||||||
|
};
|
||||||
|
|
||||||
struct UnitFileInstallInfo {
|
struct UnitFileInstallInfo {
|
||||||
char *name;
|
char *name;
|
||||||
char *path;
|
char *path;
|
||||||
char *user;
|
|
||||||
|
|
||||||
char **aliases;
|
char **aliases;
|
||||||
char **wanted_by;
|
char **wanted_by;
|
||||||
@ -93,8 +102,26 @@ struct UnitFileInstallInfo {
|
|||||||
char **also;
|
char **also;
|
||||||
|
|
||||||
char *default_instance;
|
char *default_instance;
|
||||||
|
|
||||||
|
UnitFileType type;
|
||||||
|
|
||||||
|
char *symlink_target;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline bool UNIT_FILE_INSTALL_INFO_HAS_RULES(UnitFileInstallInfo *i) {
|
||||||
|
assert(i);
|
||||||
|
|
||||||
|
return !strv_isempty(i->aliases) ||
|
||||||
|
!strv_isempty(i->wanted_by) ||
|
||||||
|
!strv_isempty(i->required_by);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool UNIT_FILE_INSTALL_INFO_HAS_ALSO(UnitFileInstallInfo *i) {
|
||||||
|
assert(i);
|
||||||
|
|
||||||
|
return !strv_isempty(i->also);
|
||||||
|
}
|
||||||
|
|
||||||
int unit_file_enable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes);
|
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_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);
|
int unit_file_reenable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes);
|
||||||
@ -105,21 +132,14 @@ int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char
|
|||||||
int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes);
|
int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes);
|
||||||
int unit_file_set_default(UnitFileScope scope, const char *root_dir, const char *file, bool force, UnitFileChange **changes, unsigned *n_changes);
|
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);
|
int unit_file_get_default(UnitFileScope scope, const char *root_dir, char **name);
|
||||||
int unit_file_add_dependency(UnitFileScope scope, bool runtime, const char *root_dir, char **files, char *target, UnitDependency dep, bool force, UnitFileChange **changes, unsigned *n_changes);
|
int unit_file_add_dependency(UnitFileScope scope, bool runtime, const char *root_dir, char **files, const char *target, UnitDependency dep, bool force, UnitFileChange **changes, unsigned *n_changes);
|
||||||
|
|
||||||
UnitFileState unit_file_lookup_state(
|
int unit_file_lookup_state(UnitFileScope scope, const char *root_dir,const LookupPaths *paths, const char *name, UnitFileState *ret);
|
||||||
UnitFileScope scope,
|
int unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename, UnitFileState *ret);
|
||||||
const char *root_dir,
|
|
||||||
const LookupPaths *paths,
|
|
||||||
const char *name);
|
|
||||||
UnitFileState unit_file_get_state(
|
|
||||||
UnitFileScope scope,
|
|
||||||
const char *root_dir,
|
|
||||||
const char *filename);
|
|
||||||
|
|
||||||
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);
|
||||||
|
Hashmap* unit_file_list_free(Hashmap *h);
|
||||||
|
|
||||||
void unit_file_list_free(Hashmap *h);
|
|
||||||
int unit_file_changes_add(UnitFileChange **changes, unsigned *n_changes, UnitFileChangeType type, const char *path, const char *source);
|
int unit_file_changes_add(UnitFileChange **changes, unsigned *n_changes, UnitFileChangeType type, const char *path, const char *source);
|
||||||
void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes);
|
void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes);
|
||||||
|
|
||||||
|
@ -1335,7 +1335,7 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
|
|||||||
UNIT_FILE_MASKED,
|
UNIT_FILE_MASKED,
|
||||||
UNIT_FILE_MASKED_RUNTIME,
|
UNIT_FILE_MASKED_RUNTIME,
|
||||||
UNIT_FILE_DISABLED,
|
UNIT_FILE_DISABLED,
|
||||||
UNIT_FILE_INVALID)) {
|
UNIT_FILE_BAD)) {
|
||||||
on = ansi_highlight_red();
|
on = ansi_highlight_red();
|
||||||
off = ansi_normal();
|
off = ansi_normal();
|
||||||
} else if (u->state == UNIT_FILE_ENABLED) {
|
} else if (u->state == UNIT_FILE_ENABLED) {
|
||||||
@ -5437,10 +5437,10 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
|
|||||||
else
|
else
|
||||||
assert_not_reached("Unknown verb");
|
assert_not_reached("Unknown verb");
|
||||||
|
|
||||||
if (r < 0) {
|
if (r == -ESHUTDOWN)
|
||||||
log_error_errno(r, "Operation failed: %m");
|
return log_error_errno(r, "Unit file is masked.");
|
||||||
goto finish;
|
if (r < 0)
|
||||||
}
|
return log_error_errno(r, "Operation failed: %m");
|
||||||
|
|
||||||
if (!arg_quiet)
|
if (!arg_quiet)
|
||||||
dump_unit_file_changes(changes, n_changes);
|
dump_unit_file_changes(changes, n_changes);
|
||||||
@ -5557,7 +5557,7 @@ static int enable_unit(int argc, char *argv[], void *userdata) {
|
|||||||
|
|
||||||
r = acquire_bus(BUS_MANAGER, &bus);
|
r = acquire_bus(BUS_MANAGER, &bus);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
goto finish;
|
||||||
|
|
||||||
new_args[0] = (char*) (streq(argv[0], "enable") ? "start" : "stop");
|
new_args[0] = (char*) (streq(argv[0], "enable") ? "start" : "stop");
|
||||||
for (i = 0; i < n_changes; i++)
|
for (i = 0; i < n_changes; i++)
|
||||||
@ -5603,7 +5603,8 @@ static int add_dependency(int argc, char *argv[], void *userdata) {
|
|||||||
unsigned n_changes = 0;
|
unsigned n_changes = 0;
|
||||||
|
|
||||||
r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
|
r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
|
||||||
|
if (r == -ESHUTDOWN)
|
||||||
|
return log_error_errno(r, "Unit file is masked.");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Can't add dependency: %m");
|
return log_error_errno(r, "Can't add dependency: %m");
|
||||||
|
|
||||||
@ -5740,8 +5741,8 @@ static int unit_is_enabled(int argc, char *argv[], void *userdata) {
|
|||||||
STRV_FOREACH(name, names) {
|
STRV_FOREACH(name, names) {
|
||||||
UnitFileState state;
|
UnitFileState state;
|
||||||
|
|
||||||
state = unit_file_get_state(arg_scope, arg_root, *name);
|
r = unit_file_get_state(arg_scope, arg_root, *name, &state);
|
||||||
if (state < 0)
|
if (r < 0)
|
||||||
return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
|
return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
|
||||||
|
|
||||||
if (IN_SET(state,
|
if (IN_SET(state,
|
||||||
|
@ -742,6 +742,7 @@ static int fix_order(SysvStub *s, Hashmap *all_services) {
|
|||||||
|
|
||||||
static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
|
static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
|
||||||
char **path;
|
char **path;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(lp);
|
assert(lp);
|
||||||
assert(all_services);
|
assert(all_services);
|
||||||
@ -761,7 +762,6 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
|
|||||||
_cleanup_free_ char *fpath = NULL, *name = NULL;
|
_cleanup_free_ char *fpath = NULL, *name = NULL;
|
||||||
_cleanup_(free_sysvstubp) SysvStub *service = NULL;
|
_cleanup_(free_sysvstubp) SysvStub *service = NULL;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int r;
|
|
||||||
|
|
||||||
if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) {
|
if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) {
|
||||||
log_warning_errno(errno, "stat() failed on %s/%s, ignoring: %m", *path, de->d_name);
|
log_warning_errno(errno, "stat() failed on %s/%s, ignoring: %m", *path, de->d_name);
|
||||||
@ -781,8 +781,12 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
|
|||||||
if (hashmap_contains(all_services, name))
|
if (hashmap_contains(all_services, name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (unit_file_lookup_state(UNIT_FILE_SYSTEM, NULL, lp, name) >= 0) {
|
r = unit_file_lookup_state(UNIT_FILE_SYSTEM, NULL, lp, name, NULL);
|
||||||
log_debug("Native unit for %s already exists, skipping", name);
|
if (r < 0 && r != -ENOENT) {
|
||||||
|
log_debug_errno(r, "Failed to detect whether %s exists, skipping: %m", name);
|
||||||
|
continue;
|
||||||
|
} else if (r >= 0) {
|
||||||
|
log_debug("Native unit for %s already exists, skipping.", name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
665
src/test/test-install-root.c
Normal file
665
src/test/test-install-root.c
Normal file
@ -0,0 +1,665 @@
|
|||||||
|
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||||
|
|
||||||
|
/***
|
||||||
|
This file is part of systemd.
|
||||||
|
|
||||||
|
Copyright 2011 Lennart Poettering
|
||||||
|
|
||||||
|
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 "alloc-util.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "install.h"
|
||||||
|
#include "mkdir.h"
|
||||||
|
#include "rm-rf.h"
|
||||||
|
#include "string-util.h"
|
||||||
|
|
||||||
|
static void test_basic_mask_and_enable(const char *root) {
|
||||||
|
const char *p;
|
||||||
|
UnitFileState state;
|
||||||
|
UnitFileChange *changes = NULL;
|
||||||
|
unsigned n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) == -ENOENT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/a.service");
|
||||||
|
assert_se(write_string_file(p,
|
||||||
|
"[Install]\n"
|
||||||
|
"WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) >= 0);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/b.service");
|
||||||
|
assert_se(symlink("a.service", p) >= 0);
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) >= 0);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/c.service");
|
||||||
|
assert_se(symlink("/usr/lib/systemd/system/a.service", p) >= 0);
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) >= 0);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/d.service");
|
||||||
|
assert_se(symlink("c.service", p) >= 0);
|
||||||
|
|
||||||
|
/* This one is interesting, as d follows a relative, then an absolute symlink */
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) >= 0);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
assert_se(unit_file_mask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[0].source, "/dev/null"));
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_MASKED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_MASKED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_MASKED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_MASKED);
|
||||||
|
|
||||||
|
/* Enabling a masked unit should fail! */
|
||||||
|
assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == -ESHUTDOWN);
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_unmask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_UNLINK);
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == 1);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
|
||||||
|
/* Enabling it again should succeed but be a NOP */
|
||||||
|
assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == 1);
|
||||||
|
assert_se(n_changes == 0);
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_UNLINK);
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
/* Disabling a disabled unit must suceed but be a NOP */
|
||||||
|
assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 0);
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
/* Let's enable this indirectly via a symlink */
|
||||||
|
assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("d.service"), false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service"));
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
|
||||||
|
/* Let's try to reenable */
|
||||||
|
|
||||||
|
assert_se(unit_file_reenable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("b.service"), false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 2);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_UNLINK);
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
assert_se(changes[1].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[1].source, "/usr/lib/systemd/system/a.service"));
|
||||||
|
assert_se(streq(changes[1].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_linked_units(const char *root) {
|
||||||
|
const char *p, *q;
|
||||||
|
UnitFileState state;
|
||||||
|
UnitFileChange *changes = NULL;
|
||||||
|
unsigned n_changes = 0, i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We'll test three cases here:
|
||||||
|
*
|
||||||
|
* a) a unit file in /opt, that we use "systemctl link" and
|
||||||
|
* "systemctl enable" on to make it available to the system
|
||||||
|
*
|
||||||
|
* b) a unit file in /opt, that is statically linked into
|
||||||
|
* /usr/lib/systemd/system, that "enable" should work on
|
||||||
|
* correctly.
|
||||||
|
*
|
||||||
|
* c) a unit file in /opt, that is linked into
|
||||||
|
* /etc/systemd/system, and where "enable" should result in
|
||||||
|
* -ELOOP, since using information from /etc to generate
|
||||||
|
* information in /etc should not be allowed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
p = strjoina(root, "/opt/linked.service");
|
||||||
|
assert_se(write_string_file(p,
|
||||||
|
"[Install]\n"
|
||||||
|
"WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/opt/linked2.service");
|
||||||
|
assert_se(write_string_file(p,
|
||||||
|
"[Install]\n"
|
||||||
|
"WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/opt/linked3.service");
|
||||||
|
assert_se(write_string_file(p,
|
||||||
|
"[Install]\n"
|
||||||
|
"WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", NULL) == -ENOENT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", NULL) == -ENOENT);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/linked2.service");
|
||||||
|
assert_se(symlink("/opt/linked2.service", p) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked3.service");
|
||||||
|
assert_se(symlink("/opt/linked3.service", p) >= 0);
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) == -ENOENT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", &state) >= 0 && state == UNIT_FILE_LINKED);
|
||||||
|
|
||||||
|
/* First, let's link the unit into the search path */
|
||||||
|
assert_se(unit_file_link(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[0].source, "/opt/linked.service"));
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_LINKED);
|
||||||
|
|
||||||
|
/* Let's unlink it from the search path again */
|
||||||
|
assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_UNLINK);
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
|
||||||
|
|
||||||
|
/* Now, let's not just link it, but also enable it */
|
||||||
|
assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 2);
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
|
||||||
|
q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
|
||||||
|
for (i = 0 ; i < n_changes; i++) {
|
||||||
|
assert_se(changes[i].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[i].source, "/opt/linked.service"));
|
||||||
|
|
||||||
|
if (p && streq(changes[i].path, p))
|
||||||
|
p = NULL;
|
||||||
|
else if (q && streq(changes[i].path, q))
|
||||||
|
q = NULL;
|
||||||
|
else
|
||||||
|
assert_not_reached("wut?");
|
||||||
|
}
|
||||||
|
assert(!p && !q);
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
|
||||||
|
/* And let's unlink it again */
|
||||||
|
assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 2);
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service");
|
||||||
|
q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service");
|
||||||
|
for (i = 0; i < n_changes; i++) {
|
||||||
|
assert_se(changes[i].type == UNIT_FILE_UNLINK);
|
||||||
|
|
||||||
|
if (p && streq(changes[i].path, p))
|
||||||
|
p = NULL;
|
||||||
|
else if (q && streq(changes[i].path, q))
|
||||||
|
q = NULL;
|
||||||
|
else
|
||||||
|
assert_not_reached("wut?");
|
||||||
|
}
|
||||||
|
assert(!p && !q);
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT);
|
||||||
|
|
||||||
|
assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked2.service"), false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 2);
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked2.service");
|
||||||
|
q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked2.service");
|
||||||
|
for (i = 0 ; i < n_changes; i++) {
|
||||||
|
assert_se(changes[i].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[i].source, "/opt/linked2.service"));
|
||||||
|
|
||||||
|
if (p && streq(changes[i].path, p))
|
||||||
|
p = NULL;
|
||||||
|
else if (q && streq(changes[i].path, q))
|
||||||
|
q = NULL;
|
||||||
|
else
|
||||||
|
assert_not_reached("wut?");
|
||||||
|
}
|
||||||
|
assert(!p && !q);
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked3.service"), false, &changes, &n_changes) == -ELOOP);
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_default(const char *root) {
|
||||||
|
_cleanup_free_ char *def = NULL;
|
||||||
|
UnitFileChange *changes = NULL;
|
||||||
|
unsigned n_changes = 0;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/test-default-real.target");
|
||||||
|
assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/test-default.target");
|
||||||
|
assert_se(symlink("test-default-real.target", p) >= 0);
|
||||||
|
|
||||||
|
assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
|
||||||
|
|
||||||
|
assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "idontexist.target", false, &changes, &n_changes) == -ENOENT);
|
||||||
|
assert_se(n_changes == 0);
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT);
|
||||||
|
|
||||||
|
assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "test-default.target", false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[0].source, "/usr/lib/systemd/system/test-default-real.target"));
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/default.target");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) >= 0);
|
||||||
|
assert_se(streq_ptr(def, "test-default-real.target"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_add_dependency(const char *root) {
|
||||||
|
UnitFileChange *changes = NULL;
|
||||||
|
unsigned n_changes = 0;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-target.target");
|
||||||
|
assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-target.target");
|
||||||
|
assert_se(symlink("real-add-dependency-test-target.target", p) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-service.service");
|
||||||
|
assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-service.service");
|
||||||
|
assert_se(symlink("real-add-dependency-test-service.service", p) >= 0);
|
||||||
|
|
||||||
|
assert_se(unit_file_add_dependency(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("add-dependency-test-service.service"), "add-dependency-test-target.target", UNIT_WANTS, false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[0].source, "/usr/lib/systemd/system/real-add-dependency-test-service.service"));
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/real-add-dependency-test-target.target.wants/real-add-dependency-test-service.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_template_enable(const char *root) {
|
||||||
|
UnitFileChange *changes = NULL;
|
||||||
|
unsigned n_changes = 0;
|
||||||
|
UnitFileState state;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) == -ENOENT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) == -ENOENT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) == -ENOENT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) == -ENOENT);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/template@.service");
|
||||||
|
assert_se(write_string_file(p,
|
||||||
|
"[Install]\n"
|
||||||
|
"DefaultInstance=def\n"
|
||||||
|
"WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/template-symlink@.service");
|
||||||
|
assert_se(symlink("template@.service", p) >= 0);
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@def.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_UNLINK);
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@foo.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
|
||||||
|
assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_UNLINK);
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template-symlink@quux.service"), false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service"));
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@quux.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_indirect(const char *root) {
|
||||||
|
UnitFileChange *changes = NULL;
|
||||||
|
unsigned n_changes = 0;
|
||||||
|
UnitFileState state;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) == -ENOENT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) == -ENOENT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) == -ENOENT);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/indirecta.service");
|
||||||
|
assert_se(write_string_file(p,
|
||||||
|
"[Install]\n"
|
||||||
|
"Also=indirectb.service\n", WRITE_STRING_FILE_CREATE) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/indirectb.service");
|
||||||
|
assert_se(write_string_file(p,
|
||||||
|
"[Install]\n"
|
||||||
|
"WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/indirectc.service");
|
||||||
|
assert_se(symlink("indirecta.service", p) >= 0);
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
|
||||||
|
|
||||||
|
assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[0].source, "/usr/lib/systemd/system/indirectb.service"));
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT);
|
||||||
|
|
||||||
|
assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_UNLINK);
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_preset_and_list(const char *root) {
|
||||||
|
UnitFileChange *changes = NULL;
|
||||||
|
unsigned n_changes = 0, i;
|
||||||
|
const char *p, *q;
|
||||||
|
UnitFileState state;
|
||||||
|
bool got_yes = false, got_no = false;
|
||||||
|
Iterator j;
|
||||||
|
UnitFileList *fl;
|
||||||
|
Hashmap *h;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) == -ENOENT);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) == -ENOENT);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
|
||||||
|
assert_se(write_string_file(p,
|
||||||
|
"[Install]\n"
|
||||||
|
"WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
|
||||||
|
assert_se(write_string_file(p,
|
||||||
|
"[Install]\n"
|
||||||
|
"WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
|
||||||
|
assert_se(write_string_file(p,
|
||||||
|
"enable *-yes.*\n"
|
||||||
|
"disable *\n", WRITE_STRING_FILE_CREATE) >= 0);
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_SYMLINK);
|
||||||
|
assert_se(streq(changes[0].source, "/usr/lib/systemd/system/preset-yes.service"));
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 1);
|
||||||
|
assert_se(changes[0].type == UNIT_FILE_UNLINK);
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
|
||||||
|
assert_se(streq(changes[0].path, p));
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
|
||||||
|
assert_se(n_changes == 0);
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, false, root, UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0);
|
||||||
|
|
||||||
|
assert_se(n_changes > 0);
|
||||||
|
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service");
|
||||||
|
|
||||||
|
for (i = 0; i < n_changes; i++) {
|
||||||
|
|
||||||
|
if (changes[i].type == UNIT_FILE_SYMLINK) {
|
||||||
|
assert_se(streq(changes[i].source, "/usr/lib/systemd/system/preset-yes.service"));
|
||||||
|
assert_se(streq(changes[i].path, p));
|
||||||
|
} else
|
||||||
|
assert_se(changes[i].type == UNIT_FILE_UNLINK);
|
||||||
|
}
|
||||||
|
|
||||||
|
unit_file_changes_free(changes, n_changes);
|
||||||
|
changes = NULL; n_changes = 0;
|
||||||
|
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
|
assert_se(h = hashmap_new(&string_hash_ops));
|
||||||
|
assert_se(unit_file_get_list(UNIT_FILE_SYSTEM, root, h) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service");
|
||||||
|
q = strjoina(root, "/usr/lib/systemd/system/preset-no.service");
|
||||||
|
|
||||||
|
HASHMAP_FOREACH(fl, h, j) {
|
||||||
|
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, basename(fl->path), &state) >= 0);
|
||||||
|
assert_se(fl->state == state);
|
||||||
|
|
||||||
|
if (streq(fl->path, p)) {
|
||||||
|
got_yes = true;
|
||||||
|
assert_se(fl->state == UNIT_FILE_ENABLED);
|
||||||
|
} else if (streq(fl->path, q)) {
|
||||||
|
got_no = true;
|
||||||
|
assert_se(fl->state == UNIT_FILE_DISABLED);
|
||||||
|
} else
|
||||||
|
assert_se(IN_SET(fl->state, UNIT_FILE_DISABLED, UNIT_FILE_STATIC, UNIT_FILE_INDIRECT));
|
||||||
|
}
|
||||||
|
|
||||||
|
unit_file_list_free(h);
|
||||||
|
|
||||||
|
assert_se(got_yes && got_no);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
char root[] = "/tmp/rootXXXXXX";
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
assert_se(mkdtemp(root));
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system/");
|
||||||
|
assert_se(mkdir_p(p, 0755) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/");
|
||||||
|
assert_se(mkdir_p(p, 0755) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/run/systemd/system/");
|
||||||
|
assert_se(mkdir_p(p, 0755) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/opt/");
|
||||||
|
assert_se(mkdir_p(p, 0755) >= 0);
|
||||||
|
|
||||||
|
p = strjoina(root, "/usr/lib/systemd/system-preset/");
|
||||||
|
assert_se(mkdir_p(p, 0755) >= 0);
|
||||||
|
|
||||||
|
test_basic_mask_and_enable(root);
|
||||||
|
test_linked_units(root);
|
||||||
|
test_default(root);
|
||||||
|
test_add_dependency(root);
|
||||||
|
test_template_enable(root);
|
||||||
|
test_indirect(root);
|
||||||
|
test_preset_and_list(root);
|
||||||
|
|
||||||
|
assert_se(rm_rf(root, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -46,17 +46,19 @@ int main(int argc, char* argv[]) {
|
|||||||
const char *const files2[] = { "/home/lennart/test.service", NULL };
|
const char *const files2[] = { "/home/lennart/test.service", NULL };
|
||||||
UnitFileChange *changes = NULL;
|
UnitFileChange *changes = NULL;
|
||||||
unsigned n_changes = 0;
|
unsigned n_changes = 0;
|
||||||
|
UnitFileState state = 0;
|
||||||
|
|
||||||
h = hashmap_new(&string_hash_ops);
|
h = hashmap_new(&string_hash_ops);
|
||||||
r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
|
r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h);
|
||||||
assert_se(r == 0);
|
assert_se(r == 0);
|
||||||
|
|
||||||
HASHMAP_FOREACH(p, h, i) {
|
HASHMAP_FOREACH(p, h, i) {
|
||||||
UnitFileState s;
|
UnitFileState s = _UNIT_FILE_STATE_INVALID;
|
||||||
|
|
||||||
s = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(p->path));
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(p->path), &s);
|
||||||
|
|
||||||
assert_se(p->state == s);
|
assert_se((r < 0 && p->state == UNIT_FILE_BAD) ||
|
||||||
|
(p->state == s));
|
||||||
|
|
||||||
fprintf(stderr, "%s (%s)\n",
|
fprintf(stderr, "%s (%s)\n",
|
||||||
p->path,
|
p->path,
|
||||||
@ -78,7 +80,9 @@ int main(int argc, char* argv[]) {
|
|||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(state == UNIT_FILE_ENABLED);
|
||||||
|
|
||||||
log_error("disable");
|
log_error("disable");
|
||||||
|
|
||||||
@ -91,7 +95,9 @@ int main(int argc, char* argv[]) {
|
|||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
log_error("mask");
|
log_error("mask");
|
||||||
changes = NULL;
|
changes = NULL;
|
||||||
@ -106,7 +112,9 @@ int main(int argc, char* argv[]) {
|
|||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(state == UNIT_FILE_MASKED);
|
||||||
|
|
||||||
log_error("unmask");
|
log_error("unmask");
|
||||||
changes = NULL;
|
changes = NULL;
|
||||||
@ -121,7 +129,9 @@ int main(int argc, char* argv[]) {
|
|||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
log_error("mask");
|
log_error("mask");
|
||||||
changes = NULL;
|
changes = NULL;
|
||||||
@ -133,7 +143,9 @@ int main(int argc, char* argv[]) {
|
|||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(state == UNIT_FILE_MASKED);
|
||||||
|
|
||||||
log_error("disable");
|
log_error("disable");
|
||||||
changes = NULL;
|
changes = NULL;
|
||||||
@ -148,7 +160,9 @@ int main(int argc, char* argv[]) {
|
|||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(state == UNIT_FILE_MASKED);
|
||||||
|
|
||||||
log_error("umask");
|
log_error("umask");
|
||||||
changes = NULL;
|
changes = NULL;
|
||||||
@ -160,7 +174,9 @@ int main(int argc, char* argv[]) {
|
|||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state);
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(state == UNIT_FILE_DISABLED);
|
||||||
|
|
||||||
log_error("enable files2");
|
log_error("enable files2");
|
||||||
changes = NULL;
|
changes = NULL;
|
||||||
@ -172,19 +188,22 @@ int main(int argc, char* argv[]) {
|
|||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(state == UNIT_FILE_ENABLED);
|
||||||
|
|
||||||
log_error("disable files2");
|
log_error("disable files2");
|
||||||
changes = NULL;
|
changes = NULL;
|
||||||
n_changes = 0;
|
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, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
|
|
||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
|
||||||
|
assert_se(r < 0);
|
||||||
|
|
||||||
log_error("link files2");
|
log_error("link files2");
|
||||||
changes = NULL;
|
changes = NULL;
|
||||||
@ -196,19 +215,22 @@ int main(int argc, char* argv[]) {
|
|||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(state == UNIT_FILE_LINKED);
|
||||||
|
|
||||||
log_error("disable files2");
|
log_error("disable files2");
|
||||||
changes = NULL;
|
changes = NULL;
|
||||||
n_changes = 0;
|
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, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
|
|
||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
|
||||||
|
assert_se(r < 0);
|
||||||
|
|
||||||
log_error("link files2");
|
log_error("link files2");
|
||||||
changes = NULL;
|
changes = NULL;
|
||||||
@ -220,7 +242,9 @@ int main(int argc, char* argv[]) {
|
|||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(state == UNIT_FILE_LINKED);
|
||||||
|
|
||||||
log_error("reenable files2");
|
log_error("reenable files2");
|
||||||
changes = NULL;
|
changes = NULL;
|
||||||
@ -232,19 +256,22 @@ int main(int argc, char* argv[]) {
|
|||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(state == UNIT_FILE_ENABLED);
|
||||||
|
|
||||||
log_error("disable files2");
|
log_error("disable files2");
|
||||||
changes = NULL;
|
changes = NULL;
|
||||||
n_changes = 0;
|
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, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes);
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
|
|
||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state);
|
||||||
|
assert_se(r < 0);
|
||||||
log_error("preset files");
|
log_error("preset files");
|
||||||
changes = NULL;
|
changes = NULL;
|
||||||
n_changes = 0;
|
n_changes = 0;
|
||||||
@ -255,7 +282,9 @@ int main(int argc, char* argv[]) {
|
|||||||
dump_changes(changes, n_changes);
|
dump_changes(changes, n_changes);
|
||||||
unit_file_changes_free(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);
|
r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files[0]), &state);
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(state == UNIT_FILE_ENABLED);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "test-helper.h"
|
#include "test-helper.h"
|
||||||
|
#include "user-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
static int test_unit_file_get_set(void) {
|
static int test_unit_file_get_set(void) {
|
||||||
@ -558,76 +559,66 @@ static void test_load_env_file_5(void) {
|
|||||||
|
|
||||||
static void test_install_printf(void) {
|
static void test_install_printf(void) {
|
||||||
char name[] = "name.service",
|
char name[] = "name.service",
|
||||||
path[] = "/run/systemd/system/name.service",
|
path[] = "/run/systemd/system/name.service";
|
||||||
user[] = "xxxx-no-such-user";
|
UnitFileInstallInfo i = { .name = name, .path = path, };
|
||||||
UnitFileInstallInfo i = {name, path, user};
|
UnitFileInstallInfo i2 = { .name= name, .path = path, };
|
||||||
UnitFileInstallInfo i2 = {name, path, NULL};
|
|
||||||
char name3[] = "name@inst.service",
|
char name3[] = "name@inst.service",
|
||||||
path3[] = "/run/systemd/system/name.service";
|
path3[] = "/run/systemd/system/name.service";
|
||||||
UnitFileInstallInfo i3 = {name3, path3, user};
|
UnitFileInstallInfo i3 = { .name = name3, .path = path3, };
|
||||||
UnitFileInstallInfo i4 = {name3, path3, NULL};
|
UnitFileInstallInfo i4 = { .name = name3, .path = path3, };
|
||||||
|
|
||||||
_cleanup_free_ char *mid, *bid, *host;
|
_cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL;
|
||||||
|
|
||||||
assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
|
assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
|
||||||
assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
|
assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
|
||||||
assert_se((host = gethostname_malloc()));
|
assert_se((host = gethostname_malloc()));
|
||||||
|
assert_se((user = getusername_malloc()));
|
||||||
|
assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0);
|
||||||
|
|
||||||
#define expect(src, pattern, result) \
|
#define expect(src, pattern, result) \
|
||||||
do { \
|
do { \
|
||||||
_cleanup_free_ char *t = NULL; \
|
_cleanup_free_ char *t = NULL; \
|
||||||
_cleanup_free_ char \
|
_cleanup_free_ char \
|
||||||
*d1 = strdup(i.name), \
|
*d1 = strdup(i.name), \
|
||||||
*d2 = strdup(i.path), \
|
*d2 = strdup(i.path); \
|
||||||
*d3 = strdup(i.user); \
|
|
||||||
assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
|
assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
|
||||||
memzero(i.name, strlen(i.name)); \
|
memzero(i.name, strlen(i.name)); \
|
||||||
memzero(i.path, strlen(i.path)); \
|
memzero(i.path, strlen(i.path)); \
|
||||||
memzero(i.user, strlen(i.user)); \
|
assert_se(d1 && d2); \
|
||||||
assert_se(d1 && d2 && d3); \
|
|
||||||
if (result) { \
|
if (result) { \
|
||||||
printf("%s\n", t); \
|
printf("%s\n", t); \
|
||||||
assert_se(streq(t, result)); \
|
assert_se(streq(t, result)); \
|
||||||
} else assert_se(t == NULL); \
|
} else assert_se(t == NULL); \
|
||||||
strcpy(i.name, d1); \
|
strcpy(i.name, d1); \
|
||||||
strcpy(i.path, d2); \
|
strcpy(i.path, d2); \
|
||||||
strcpy(i.user, d3); \
|
|
||||||
} while(false)
|
} while(false)
|
||||||
|
|
||||||
assert_se(setenv("USER", "root", 1) == 0);
|
|
||||||
|
|
||||||
expect(i, "%n", "name.service");
|
expect(i, "%n", "name.service");
|
||||||
expect(i, "%N", "name");
|
expect(i, "%N", "name");
|
||||||
expect(i, "%p", "name");
|
expect(i, "%p", "name");
|
||||||
expect(i, "%i", "");
|
expect(i, "%i", "");
|
||||||
expect(i, "%u", "xxxx-no-such-user");
|
expect(i, "%u", user);
|
||||||
|
expect(i, "%U", uid);
|
||||||
DISABLE_WARNING_NONNULL;
|
|
||||||
expect(i, "%U", NULL);
|
|
||||||
REENABLE_WARNING;
|
|
||||||
|
|
||||||
expect(i, "%m", mid);
|
expect(i, "%m", mid);
|
||||||
expect(i, "%b", bid);
|
expect(i, "%b", bid);
|
||||||
expect(i, "%H", host);
|
expect(i, "%H", host);
|
||||||
|
|
||||||
expect(i2, "%u", "root");
|
expect(i2, "%u", user);
|
||||||
expect(i2, "%U", "0");
|
expect(i2, "%U", uid);
|
||||||
|
|
||||||
expect(i3, "%n", "name@inst.service");
|
expect(i3, "%n", "name@inst.service");
|
||||||
expect(i3, "%N", "name@inst");
|
expect(i3, "%N", "name@inst");
|
||||||
expect(i3, "%p", "name");
|
expect(i3, "%p", "name");
|
||||||
expect(i3, "%u", "xxxx-no-such-user");
|
expect(i3, "%u", user);
|
||||||
|
expect(i3, "%U", uid);
|
||||||
DISABLE_WARNING_NONNULL;
|
|
||||||
expect(i3, "%U", NULL);
|
|
||||||
REENABLE_WARNING;
|
|
||||||
|
|
||||||
expect(i3, "%m", mid);
|
expect(i3, "%m", mid);
|
||||||
expect(i3, "%b", bid);
|
expect(i3, "%b", bid);
|
||||||
expect(i3, "%H", host);
|
expect(i3, "%H", host);
|
||||||
|
|
||||||
expect(i4, "%u", "root");
|
expect(i4, "%u", user);
|
||||||
expect(i4, "%U", "0");
|
expect(i4, "%U", uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t make_cap(int cap) {
|
static uint64_t make_cap(int cap) {
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "unit-name.h"
|
#include "unit-name.h"
|
||||||
#include "unit-printf.h"
|
#include "unit-printf.h"
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
|
#include "user-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
static void test_unit_name_is_valid(void) {
|
static void test_unit_name_is_valid(void) {
|
||||||
@ -193,15 +194,15 @@ static int test_unit_printf(void) {
|
|||||||
Unit *u, *u2;
|
Unit *u, *u2;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
_cleanup_free_ char *mid, *bid, *host, *root_uid;
|
_cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *uid = NULL, *user = NULL, *shell = NULL, *home = NULL;
|
||||||
struct passwd *root;
|
|
||||||
|
|
||||||
assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
|
assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
|
||||||
assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
|
assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
|
||||||
assert_se((host = gethostname_malloc()));
|
assert_se(host = gethostname_malloc());
|
||||||
|
assert_se(user = getusername_malloc());
|
||||||
assert_se((root = getpwnam("root")));
|
assert_se(asprintf(&uid, UID_FMT, getuid()));
|
||||||
assert_se(asprintf(&root_uid, "%d", (int) root->pw_uid) > 0);
|
assert_se(get_home_dir(&home) >= 0);
|
||||||
|
assert_se(get_shell(&shell) >= 0);
|
||||||
|
|
||||||
r = manager_new(MANAGER_USER, true, &m);
|
r = manager_new(MANAGER_USER, true, &m);
|
||||||
if (r == -EPERM || r == -EACCES || r == -EADDRINUSE) {
|
if (r == -EPERM || r == -EACCES || r == -EADDRINUSE) {
|
||||||
@ -222,8 +223,6 @@ static int test_unit_printf(void) {
|
|||||||
assert_se(streq(t, expected)); \
|
assert_se(streq(t, expected)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_se(setenv("USER", "root", 1) == 0);
|
|
||||||
assert_se(setenv("HOME", "/root", 1) == 0);
|
|
||||||
assert_se(setenv("XDG_RUNTIME_DIR", "/run/user/1/", 1) == 0);
|
assert_se(setenv("XDG_RUNTIME_DIR", "/run/user/1/", 1) == 0);
|
||||||
|
|
||||||
assert_se(u = unit_new(m, sizeof(Service)));
|
assert_se(u = unit_new(m, sizeof(Service)));
|
||||||
@ -242,9 +241,9 @@ static int test_unit_printf(void) {
|
|||||||
expect(u, "%p", "blah");
|
expect(u, "%p", "blah");
|
||||||
expect(u, "%P", "blah");
|
expect(u, "%P", "blah");
|
||||||
expect(u, "%i", "");
|
expect(u, "%i", "");
|
||||||
expect(u, "%u", root->pw_name);
|
expect(u, "%u", user);
|
||||||
expect(u, "%U", root_uid);
|
expect(u, "%U", uid);
|
||||||
expect(u, "%h", root->pw_dir);
|
expect(u, "%h", home);
|
||||||
expect(u, "%m", mid);
|
expect(u, "%m", mid);
|
||||||
expect(u, "%b", bid);
|
expect(u, "%b", bid);
|
||||||
expect(u, "%H", host);
|
expect(u, "%H", host);
|
||||||
@ -262,9 +261,9 @@ static int test_unit_printf(void) {
|
|||||||
expect(u2, "%P", "blah");
|
expect(u2, "%P", "blah");
|
||||||
expect(u2, "%i", "foo-foo");
|
expect(u2, "%i", "foo-foo");
|
||||||
expect(u2, "%I", "foo/foo");
|
expect(u2, "%I", "foo/foo");
|
||||||
expect(u2, "%u", root->pw_name);
|
expect(u2, "%u", user);
|
||||||
expect(u2, "%U", root_uid);
|
expect(u2, "%U", uid);
|
||||||
expect(u2, "%h", root->pw_dir);
|
expect(u2, "%h", home);
|
||||||
expect(u2, "%m", mid);
|
expect(u2, "%m", mid);
|
||||||
expect(u2, "%b", bid);
|
expect(u2, "%b", bid);
|
||||||
expect(u2, "%H", host);
|
expect(u2, "%H", host);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user