| /* 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; |
| } |