diff options
Diffstat (limited to 'src/home/homework-mount.c')
-rw-r--r-- | src/home/homework-mount.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/home/homework-mount.c b/src/home/homework-mount.c new file mode 100644 index 0000000..5e73768 --- /dev/null +++ b/src/home/homework-mount.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include <sched.h> +#include <sys/mount.h> + +#include "alloc-util.h" +#include "homework-mount.h" +#include "mkdir.h" +#include "mount-util.h" +#include "path-util.h" +#include "string-util.h" + +static const char *mount_options_for_fstype(const char *fstype) { + if (streq(fstype, "ext4")) + return "noquota,user_xattr"; + if (streq(fstype, "xfs")) + return "noquota"; + if (streq(fstype, "btrfs")) + return "noacl"; + return NULL; +} + +int home_mount_node(const char *node, const char *fstype, bool discard, unsigned long flags) { + _cleanup_free_ char *joined = NULL; + const char *options, *discard_option; + int r; + + options = mount_options_for_fstype(fstype); + + discard_option = discard ? "discard" : "nodiscard"; + + if (options) { + joined = strjoin(options, ",", discard_option); + if (!joined) + return log_oom(); + + options = joined; + } else + options = discard_option; + + r = mount_nofollow_verbose(LOG_ERR, node, "/run/systemd/user-home-mount", fstype, flags|MS_RELATIME, strempty(options)); + if (r < 0) + return r; + + log_info("Mounting file system completed."); + return 0; +} + +int home_unshare_and_mount(const char *node, const char *fstype, bool discard, unsigned long flags) { + int r; + + if (unshare(CLONE_NEWNS) < 0) + return log_error_errno(errno, "Couldn't unshare file system namespace: %m"); + + r = mount_nofollow_verbose(LOG_ERR, "/run", "/run", NULL, MS_SLAVE|MS_REC, NULL); /* Mark /run as MS_SLAVE in our new namespace */ + if (r < 0) + return r; + + (void) mkdir_p("/run/systemd/user-home-mount", 0700); + + if (node) + return home_mount_node(node, fstype, discard, flags); + + return 0; +} + +int home_move_mount(const char *user_name_and_realm, const char *target) { + _cleanup_free_ char *subdir = NULL; + const char *d; + int r; + + assert(user_name_and_realm); + assert(target); + + if (user_name_and_realm) { + subdir = path_join("/run/systemd/user-home-mount/", user_name_and_realm); + if (!subdir) + return log_oom(); + + d = subdir; + } else + d = "/run/systemd/user-home-mount/"; + + (void) mkdir_p(target, 0700); + + r = mount_nofollow_verbose(LOG_ERR, d, target, NULL, MS_BIND, NULL); + if (r < 0) + return r; + + r = umount_verbose(LOG_ERR, "/run/systemd/user-home-mount", UMOUNT_NOFOLLOW); + if (r < 0) + return r; + + log_info("Moving to final mount point %s completed.", target); + return 0; +} |