diff --git a/man/systemd-mount.xml b/man/systemd-mount.xml
index 87bc2b36eb..76ea0550d7 100644
--- a/man/systemd-mount.xml
+++ b/man/systemd-mount.xml
@@ -159,6 +159,14 @@
Additional mount options for the mount point.
+
+
+
+ Let the specified user USER own the mounted file system.
+ This is done by appending and options to the list
+ of mount options. Only certain file systems support this option.
+
+
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c
index 403f288b57..0fa0472ee1 100644
--- a/src/basic/unit-name.c
+++ b/src/basic/unit-name.c
@@ -28,6 +28,7 @@
#include "glob-util.h"
#include "hexdecoct.h"
#include "path-util.h"
+#include "special.h"
#include "string-util.h"
#include "strv.h"
#include "unit-name.h"
@@ -673,7 +674,7 @@ int slice_build_parent_slice(const char *slice, char **ret) {
if (!slice_name_is_valid(slice))
return -EINVAL;
- if (streq(slice, "-.slice")) {
+ if (streq(slice, SPECIAL_ROOT_SLICE)) {
*ret = NULL;
return 0;
}
@@ -686,7 +687,7 @@ int slice_build_parent_slice(const char *slice, char **ret) {
if (dash)
strcpy(dash, ".slice");
else {
- r = free_and_strdup(&s, "-.slice");
+ r = free_and_strdup(&s, SPECIAL_ROOT_SLICE);
if (r < 0) {
free(s);
return r;
@@ -710,7 +711,7 @@ int slice_build_subslice(const char *slice, const char*name, char **ret) {
if (!unit_prefix_is_valid(name))
return -EINVAL;
- if (streq(slice, "-.slice"))
+ if (streq(slice, SPECIAL_ROOT_SLICE))
subslice = strappend(name, ".slice");
else {
char *e;
@@ -735,7 +736,7 @@ bool slice_name_is_valid(const char *name) {
if (!unit_name_is_valid(name, UNIT_NAME_PLAIN))
return false;
- if (streq(name, "-.slice"))
+ if (streq(name, SPECIAL_ROOT_SLICE))
return true;
e = endswith(name, ".slice");
diff --git a/src/core/slice.c b/src/core/slice.c
index 5ab1e6f898..fef47b04fe 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -59,30 +59,24 @@ static void slice_set_state(Slice *t, SliceState state) {
}
static int slice_add_parent_slice(Slice *s) {
- char *a, *dash;
- Unit *parent;
+ Unit *u = UNIT(s), *parent;
+ _cleanup_free_ char *a = NULL;
int r;
assert(s);
- if (UNIT_ISSET(UNIT(s)->slice))
+ if (UNIT_ISSET(u->slice))
return 0;
- if (unit_has_name(UNIT(s), SPECIAL_ROOT_SLICE))
- return 0;
+ r = slice_build_parent_slice(u->id, &a);
+ if (r <= 0) /* 0 means root slice */
+ return r;
- a = strdupa(UNIT(s)->id);
- dash = strrchr(a, '-');
- if (dash)
- strcpy(dash, ".slice");
- else
- a = (char*) SPECIAL_ROOT_SLICE;
-
- r = manager_load_unit(UNIT(s)->manager, a, NULL, NULL, &parent);
+ r = manager_load_unit(u->manager, a, NULL, NULL, &parent);
if (r < 0)
return r;
- unit_ref_set(&UNIT(s)->slice, parent);
+ unit_ref_set(&u->slice, parent);
return 0;
}
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index 7e61332e52..531edc6847 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -61,7 +61,7 @@ static int create_disk(
const char *password,
const char *options) {
- _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *e = NULL,
+ _cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL,
*filtered = NULL, *u_escaped = NULL, *password_escaped = NULL, *filtered_escaped = NULL, *name_escaped = NULL;
_cleanup_fclose_ FILE *f = NULL;
const char *dmname;
@@ -90,18 +90,14 @@ static int create_disk(
if (!e)
return log_oom();
- r = unit_name_build("systemd-cryptsetup", e, ".service", &n);
- if (r < 0)
- return log_error_errno(r, "Failed to generate unit name: %m");
-
- p = strjoin(arg_dest, "/", n);
- if (!p)
- return log_oom();
-
u = fstab_node_to_udev_node(device);
if (!u)
return log_oom();
+ r = unit_name_build("systemd-cryptsetup", e, ".service", &n);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate unit name: %m");
+
u_escaped = specifier_escape(u);
if (!u_escaped)
return log_oom();
@@ -114,14 +110,11 @@ static int create_disk(
if (!password_escaped)
return log_oom();
- f = fopen(p, "wxe");
- if (!f)
- return log_error_errno(errno, "Failed to create unit file %s: %m", p);
-
- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+ r = generator_open_unit_file(arg_dest, NULL, n, &f);
+ if (r < 0)
+ return r;
fprintf(f,
- "# Automatically generated by systemd-cryptsetup-generator\n\n"
"[Unit]\n"
"Description=Cryptography Setup for %%I\n"
"Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n"
@@ -210,7 +203,7 @@ static int create_disk(
r = fflush_and_check(f);
if (r < 0)
- return log_error_errno(r, "Failed to write file %s: %m", p);
+ return log_error_errno(r, "Failed to write unit file %s: %m", n);
if (!noauto) {
r = generator_add_symlink(arg_dest, d, "wants", n);
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 22c4ae9861..95bc5e38d5 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -102,7 +102,7 @@ static int add_swap(
struct mntent *me,
MountpointFlags flags) {
- _cleanup_free_ char *name = NULL, *unit = NULL;
+ _cleanup_free_ char *name = NULL;
_cleanup_fclose_ FILE *f = NULL;
int r;
@@ -123,19 +123,9 @@ static int add_swap(
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
- unit = strjoin(arg_dest, "/", name);
- if (!unit)
- return log_oom();
-
- f = fopen(unit, "wxe");
- if (!f)
- return log_error_errno(errno,
- errno == EEXIST ?
- "Failed to create swap unit file %s, as it already exists. Duplicate entry in /etc/fstab?" :
- "Failed to create unit file %s: %m",
- unit);
-
- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+ r = generator_open_unit_file(arg_dest, "/etc/fstab", name, &f);
+ if (r < 0)
+ return r;
fputs("# Automatically generated by systemd-fstab-generator\n\n"
"[Unit]\n"
@@ -153,7 +143,7 @@ static int add_swap(
r = fflush_and_check(f);
if (r < 0)
- return log_error_errno(r, "Failed to write unit file %s: %m", unit);
+ return log_error_errno(r, "Failed to write unit file %s: %m", name);
/* use what as where, to have a nicer error message */
r = generator_write_timeouts(arg_dest, what, what, me->mnt_opts, NULL);
@@ -323,10 +313,9 @@ static int add_mount(
_cleanup_free_ char
*name = NULL,
- *automount_name = NULL, *automount_unit = NULL,
+ *automount_name = NULL,
*filtered = NULL,
*where_escaped = NULL;
- const char *unit;
_cleanup_fclose_ FILE *f = NULL;
int r;
@@ -363,20 +352,11 @@ static int add_mount(
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
- unit = strjoina(dest, "/", name);
-
- f = fopen(unit, "wxe");
- if (!f)
- return log_error_errno(errno,
- errno == EEXIST ?
- "Failed to create mount unit file %s, as it already exists. Duplicate entry in /etc/fstab?" :
- "Failed to create unit file %s: %m",
- unit);
-
- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+ r = generator_open_unit_file(dest, "/etc/fstab", name, &f);
+ if (r < 0)
+ return r;
fprintf(f,
- "# Automatically generated by systemd-fstab-generator\n\n"
"[Unit]\n"
"SourcePath=%s\n"
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
@@ -461,7 +441,7 @@ static int add_mount(
r = fflush_and_check(f);
if (r < 0)
- return log_error_errno(r, "Failed to write unit file %s: %m", unit);
+ return log_error_errno(r, "Failed to write unit file %s: %m", name);
if (flags & MAKEFS) {
r = generator_hook_up_mkfs(dest, what, where, fstype);
@@ -487,19 +467,13 @@ static int add_mount(
if (r < 0)
return log_error_errno(r, "Failed to generate unit name: %m");
- automount_unit = strjoin(dest, "/", automount_name);
- if (!automount_unit)
- return log_oom();
-
fclose(f);
- f = fopen(automount_unit, "wxe");
- if (!f)
- return log_error_errno(errno, "Failed to create unit file %s: %m", automount_unit);
- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+ r = generator_open_unit_file(dest, "/etc/fstab", automount_name, &f);
+ if (r < 0)
+ return r;
fprintf(f,
- "# Automatically generated by systemd-fstab-generator\n\n"
"[Unit]\n"
"SourcePath=%s\n"
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
@@ -534,7 +508,7 @@ static int add_mount(
r = fflush_and_check(f);
if (r < 0)
- return log_error_errno(r, "Failed to write unit file %s: %m", automount_unit);
+ return log_error_errno(r, "Failed to write unit file %s: %m", automount_name);
r = generator_add_symlink(dest, post,
(flags & NOFAIL) ? "wants" : "requires", automount_name);
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 94e250b94a..32b2045696 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -344,16 +344,13 @@ static int user_mkdir_runtime_path(User *u) {
if (path_is_mount_point(u->runtime_path, NULL, 0) <= 0) {
_cleanup_free_ char *t = NULL;
- (void) mkdir_label(u->runtime_path, 0700);
+ r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu%s",
+ u->uid, u->gid, u->manager->runtime_dir_size,
+ mac_smack_use() ? ",smackfsroot=*" : "");
+ if (r < 0)
+ return log_oom();
- if (mac_smack_use())
- r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
- else
- r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
- if (r < 0) {
- r = log_oom();
- goto fail;
- }
+ (void) mkdir_label(u->runtime_path, 0700);
r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, t);
if (r < 0) {
@@ -461,7 +458,7 @@ int user_start(User *u) {
u->stopping = false;
if (!u->started) {
- log_debug("New user %s logged in.", u->name);
+ log_debug("Starting services for new user %s.", u->name);
/* Make XDG_RUNTIME_DIR */
r = user_mkdir_runtime_path(u);
@@ -530,9 +527,7 @@ static int user_stop_service(User *u) {
return r;
}
- free(u->service_job);
- u->service_job = job;
-
+ free_and_replace(u->service_job, job);
return r;
}
diff --git a/src/machine/machined.c b/src/machine/machined.c
index d481020893..b5cb863e5d 100644
--- a/src/machine/machined.c
+++ b/src/machine/machined.c
@@ -37,6 +37,7 @@
#include "machined.h"
#include "process-util.h"
#include "signal-util.h"
+#include "special.h"
Manager *manager_new(void) {
Manager *m;
@@ -112,7 +113,7 @@ static int manager_add_host_machine(Manager *m) {
if (!rd)
return log_oom();
- unit = strdup("-.slice");
+ unit = strdup(SPECIAL_ROOT_SLICE);
if (!unit)
return log_oom();
diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c
index da3647e7e2..f82e9dac44 100644
--- a/src/mount/mount-tool.c
+++ b/src/mount/mount-tool.c
@@ -41,6 +41,7 @@
#include "strv.h"
#include "udev-util.h"
#include "unit-name.h"
+#include "user-util.h"
#include "terminal-util.h"
enum {
@@ -69,6 +70,8 @@ static usec_t arg_timeout_idle = USEC_INFINITY;
static bool arg_timeout_idle_set = false;
static char **arg_automount_property = NULL;
static int arg_bind_device = -1;
+static uid_t arg_uid = UID_INVALID;
+static gid_t arg_gid = GID_INVALID;
static bool arg_fsck = true;
static bool arg_aggressive_gc = false;
@@ -89,6 +92,7 @@ static void help(void) {
" --discover Discover mount device metadata\n"
" -t --type=TYPE File system type\n"
" -o --options=OPTIONS Mount options\n"
+ " --owner=USER Add uid= and gid= options for USER\n"
" --fsck=no Don't run file system check before mount\n"
" --description=TEXT Description for unit\n"
" -p --property=NAME=VALUE Set mount unit property\n"
@@ -116,6 +120,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_DISCOVER,
ARG_MOUNT_TYPE,
ARG_MOUNT_OPTIONS,
+ ARG_OWNER,
ARG_FSCK,
ARG_DESCRIPTION,
ARG_TIMEOUT_IDLE,
@@ -139,6 +144,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "discover", no_argument, NULL, ARG_DISCOVER },
{ "type", required_argument, NULL, 't' },
{ "options", required_argument, NULL, 'o' },
+ { "owner", required_argument, NULL, ARG_OWNER },
{ "fsck", required_argument, NULL, ARG_FSCK },
{ "description", required_argument, NULL, ARG_DESCRIPTION },
{ "property", required_argument, NULL, 'p' },
@@ -220,6 +226,18 @@ static int parse_argv(int argc, char *argv[]) {
return log_oom();
break;
+ case ARG_OWNER: {
+ const char *user = optarg;
+
+ r = get_user_creds(&user, &arg_uid, &arg_gid, NULL, NULL);
+ if (r < 0)
+ return log_error_errno(r,
+ r == -EBADMSG ? "UID or GID of user %s are invalid."
+ : "Cannot use \"%s\" as owner: %m",
+ optarg);
+ break;
+ }
+
case ARG_FSCK:
r = parse_boolean(optarg);
if (r < 0)
@@ -422,6 +440,7 @@ static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
}
static int transient_mount_set_properties(sd_bus_message *m) {
+ _cleanup_free_ char *options = NULL;
int r;
assert(m);
@@ -442,11 +461,24 @@ static int transient_mount_set_properties(sd_bus_message *m) {
return r;
}
- if (arg_mount_options) {
- r = sd_bus_message_append(m, "(sv)", "Options", "s", arg_mount_options);
+ /* Prepend uid=…,gid=… if arg_uid is set */
+ if (arg_uid != UID_INVALID) {
+ r = asprintf(&options,
+ "uid=" UID_FMT ",gid=" GID_FMT "%s%s",
+ arg_uid, arg_gid,
+ arg_mount_options ? "," : "", arg_mount_options);
+ if (r < 0)
+ return -ENOMEM;
+ }
+
+ if (options || arg_mount_options) {
+ log_debug("Using mount options: %s", options ?: arg_mount_options);
+
+ r = sd_bus_message_append(m, "(sv)", "Options", "s", options ?: arg_mount_options);
if (r < 0)
return r;
- }
+ } else
+ log_debug("Not using any mount options");
if (arg_fsck) {
_cleanup_free_ char *fsck = NULL;
@@ -1604,6 +1636,23 @@ int main(int argc, char* argv[]) {
}
}
+ /* The kernel (properly) refuses mounting file systems with unknown uid=,gid= options,
+ * but not for all filesystem types. Let's try to catch the cases where the option
+ * would be used if the file system does not support it. It is also possible to
+ * autodetect the file system, but that's only possible with disk-based file systems
+ * which incidentally seem to be implemented more carefully and reject unknown options,
+ * so it's probably OK that we do the check only when the type is specified.
+ */
+ if (arg_mount_type &&
+ !streq(arg_mount_type, "auto") &&
+ arg_uid != UID_INVALID &&
+ !fstype_can_uid_gid(arg_mount_type)) {
+ log_error("File system type %s is not known to support uid=/gid=, refusing.",
+ arg_mount_type);
+ r = -EOPNOTSUPP;
+ goto finish;
+ }
+
switch (arg_action) {
case ACTION_MOUNT:
diff --git a/src/shared/generator.c b/src/shared/generator.c
index 3495a7ef7d..2b0a4ecdc8 100644
--- a/src/shared/generator.c
+++ b/src/shared/generator.c
@@ -19,6 +19,7 @@
***/
#include
+#include
#include
#include "alloc-util.h"
@@ -39,6 +40,39 @@
#include "unit-name.h"
#include "util.h"
+int generator_open_unit_file(
+ const char *dest,
+ const char *source,
+ const char *name,
+ FILE **file) {
+
+ const char *unit;
+ FILE *f;
+
+ unit = strjoina(dest, "/", name);
+
+ f = fopen(unit, "wxe");
+ if (!f) {
+ if (source && errno == EEXIST)
+ return log_error_errno(errno,
+ "Failed to create unit file %s, as it already exists. Duplicate entry in %s?",
+ unit, source);
+ else
+ return log_error_errno(errno,
+ "Failed to create unit file %s: %m",
+ unit);
+ }
+
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+
+ fprintf(f,
+ "# Automatically generated by %s\n\n",
+ program_invocation_short_name);
+
+ *file = f;
+ return 0;
+}
+
int generator_add_symlink(const char *root, const char *dst, const char *dep_type, const char *src) {
/* Adds a symlink from ..d/ to ../ */
diff --git a/src/shared/generator.h b/src/shared/generator.h
index 32d1ad021c..e1c636a218 100644
--- a/src/shared/generator.h
+++ b/src/shared/generator.h
@@ -22,6 +22,12 @@
#include
+int generator_open_unit_file(
+ const char *dest,
+ const char *source,
+ const char *name,
+ FILE **file);
+
int generator_add_symlink(const char *root, const char *dst, const char *dep_type, const char *src);
int generator_write_fsck_deps(
diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c
index 45eb3ef8b1..2248a30635 100644
--- a/src/test/test-cgroup-util.c
+++ b/src/test/test-cgroup-util.c
@@ -27,6 +27,7 @@
#include "parse-util.h"
#include "proc-cmdline.h"
#include "process-util.h"
+#include "special.h"
#include "stat-util.h"
#include "string-util.h"
#include "test-helper.h"
@@ -141,10 +142,10 @@ static void check_p_g_slice(const char *path, int code, const char *result) {
static void test_path_get_slice(void) {
check_p_g_slice("/user.slice", 0, "user.slice");
- check_p_g_slice("/foobar", 0, "-.slice");
+ check_p_g_slice("/foobar", 0, SPECIAL_ROOT_SLICE);
check_p_g_slice("/user.slice/user-waldo.slice", 0, "user-waldo.slice");
- check_p_g_slice("", 0, "-.slice");
- check_p_g_slice("foobar", 0, "-.slice");
+ check_p_g_slice("", 0, SPECIAL_ROOT_SLICE);
+ check_p_g_slice("foobar", 0, SPECIAL_ROOT_SLICE);
check_p_g_slice("foobar.slice", 0, "foobar.slice");
check_p_g_slice("foo.slice/foo-bar.slice/waldo.service", 0, "foo-bar.slice");
}
@@ -165,10 +166,10 @@ static void test_path_get_user_slice(void) {
check_p_g_u_slice("foobar.slice", -ENXIO, NULL);
check_p_g_u_slice("foo.slice/foo-bar.slice/waldo.service", -ENXIO, NULL);
- check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service", 0, "-.slice");
- check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/", 0, "-.slice");
- check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service///", 0, "-.slice");
- check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/waldo.service", 0, "-.slice");
+ check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service", 0, SPECIAL_ROOT_SLICE);
+ check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/", 0, SPECIAL_ROOT_SLICE);
+ check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service///", 0, SPECIAL_ROOT_SLICE);
+ check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/waldo.service", 0, SPECIAL_ROOT_SLICE);
check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/piep.slice/foo.service", 0, "piep.slice");
check_p_g_u_slice("/foo.slice//foo-bar.slice/user@1000.service/piep.slice//piep-pap.slice//foo.service", 0, "piep-pap.slice");
}
@@ -274,7 +275,7 @@ static void test_slice_to_path(void) {
test_slice_to_path_one("foobar.slice", "foobar.slice", 0);
test_slice_to_path_one("foobar-waldo.slice", "foobar.slice/foobar-waldo.slice", 0);
test_slice_to_path_one("foobar-waldo.service", NULL, -EINVAL);
- test_slice_to_path_one("-.slice", "", 0);
+ test_slice_to_path_one(SPECIAL_ROOT_SLICE, "", 0);
test_slice_to_path_one("--.slice", NULL, -EINVAL);
test_slice_to_path_one("-", NULL, -EINVAL);
test_slice_to_path_one("-foo-.slice", NULL, -EINVAL);
diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c
index e24892b590..416542c83f 100644
--- a/src/test/test-unit-name.c
+++ b/src/test/test-unit-name.c
@@ -32,6 +32,7 @@
#include "manager.h"
#include "path-util.h"
#include "rm-rf.h"
+#include "special.h"
#include "specifier.h"
#include "string-util.h"
#include "test-helper.h"
@@ -338,7 +339,7 @@ static void test_unit_name_build(void) {
}
static void test_slice_name_is_valid(void) {
- assert_se(slice_name_is_valid("-.slice"));
+ assert_se(slice_name_is_valid(SPECIAL_ROOT_SLICE));
assert_se(slice_name_is_valid("foo.slice"));
assert_se(slice_name_is_valid("foo-bar.slice"));
assert_se(slice_name_is_valid("foo-bar-baz.slice"));
@@ -356,7 +357,7 @@ static void test_build_subslice(void) {
char *a;
char *b;
- assert_se(slice_build_subslice("-.slice", "foo", &a) >= 0);
+ assert_se(slice_build_subslice(SPECIAL_ROOT_SLICE, "foo", &a) >= 0);
assert_se(slice_build_subslice(a, "bar", &b) >= 0);
free(a);
assert_se(slice_build_subslice(b, "barfoo", &a) >= 0);
@@ -378,8 +379,8 @@ static void test_build_parent_slice_one(const char *name, const char *expect, in
}
static void test_build_parent_slice(void) {
- test_build_parent_slice_one("-.slice", NULL, 0);
- test_build_parent_slice_one("foo.slice", "-.slice", 1);
+ test_build_parent_slice_one(SPECIAL_ROOT_SLICE, NULL, 0);
+ test_build_parent_slice_one("foo.slice", SPECIAL_ROOT_SLICE, 1);
test_build_parent_slice_one("foo-bar.slice", "foo.slice", 1);
test_build_parent_slice_one("foo-bar-baz.slice", "foo-bar.slice", 1);
test_build_parent_slice_one("foo-bar--baz.slice", NULL, -EINVAL);
diff --git a/src/veritysetup/veritysetup-generator.c b/src/veritysetup/veritysetup-generator.c
index 5919b1380e..c29c6f0bb3 100644
--- a/src/veritysetup/veritysetup-generator.c
+++ b/src/veritysetup/veritysetup-generator.c
@@ -27,6 +27,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fstab-util.h"
+#include "generator.h"
#include "hexdecoct.h"
#include "id128-util.h"
#include "mkdir.h"
@@ -36,6 +37,8 @@
#include "string-util.h"
#include "unit-name.h"
+#define SYSTEMD_VERITYSETUP_SERVICE "systemd-veritysetup@root.service"
+
static char *arg_dest = NULL;
static bool arg_enabled = true;
static char *arg_root_hash = NULL;
@@ -45,7 +48,7 @@ static char *arg_hash_what = NULL;
static int create_device(void) {
_cleanup_free_ char *u = NULL, *v = NULL, *d = NULL, *e = NULL, *u_escaped = NULL, *v_escaped = NULL, *root_hash_escaped = NULL;
_cleanup_fclose_ FILE *f = NULL;
- const char *p, *to;
+ const char *to;
int r;
/* If all three pieces of information are missing, then verity is turned off */
@@ -67,8 +70,6 @@ static int create_device(void) {
" hash device %s,\n"
" and root hash %s.", arg_data_what, arg_hash_what, arg_root_hash);
- p = strjoina(arg_dest, "/systemd-veritysetup@root.service");
-
u = fstab_node_to_udev_node(arg_data_what);
if (!u)
return log_oom();
@@ -94,12 +95,11 @@ static int create_device(void) {
if (!root_hash_escaped)
return log_oom();
- f = fopen(p, "wxe");
- if (!f)
- return log_error_errno(errno, "Failed to create unit file %s: %m", p);
+ r = generator_open_unit_file(arg_dest, NULL, SYSTEMD_VERITYSETUP_SERVICE, &f);
+ if (r < 0)
+ return r;
fprintf(f,
- "# Automatically generated by systemd-veritysetup-generator\n\n"
"[Unit]\n"
"Description=Integrity Protection Setup for %%I\n"
"Documentation=man:systemd-veritysetup-generator(8) man:systemd-veritysetup@.service(8)\n"
@@ -121,12 +121,12 @@ static int create_device(void) {
r = fflush_and_check(f);
if (r < 0)
- return log_error_errno(r, "Failed to write file %s: %m", p);
+ return log_error_errno(r, "Failed to write file unit "SYSTEMD_VERITYSETUP_SERVICE": %m");
- to = strjoina(arg_dest, "/cryptsetup.target.requires/systemd-veritysetup@root.service");
+ to = strjoina(arg_dest, "/cryptsetup.target.requires/" SYSTEMD_VERITYSETUP_SERVICE);
(void) mkdir_parents(to, 0755);
- if (symlink("../systemd-veritysetup@root.service", to) < 0)
+ if (symlink("../" SYSTEMD_VERITYSETUP_SERVICE, to) < 0)
return log_error_errno(errno, "Failed to create symlink %s: %m", to);
return 0;