From 049af8ad0c6d8c6471ad2d13f29514ecc1bf10c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 29 Nov 2018 10:24:39 +0100 Subject: [PATCH 1/2] Split out part of mount-util.c into mountpoint-util.c The idea is that anything which is related to actually manipulating mounts is in mount-util.c, but functions for mountpoint introspection are moved to the new file. Anything which requires libmount must be in mount-util.c. This was supposed to be a preparation for further changes, with no functional difference, but it results in a significant change in linkage: $ ldd build/libnss_*.so.2 (before) build/libnss_myhostname.so.2: linux-vdso.so.1 (0x00007fff77bf5000) librt.so.1 => /lib64/librt.so.1 (0x00007f4bbb7b2000) libmount.so.1 => /lib64/libmount.so.1 (0x00007f4bbb755000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f4bbb734000) libc.so.6 => /lib64/libc.so.6 (0x00007f4bbb56e000) /lib64/ld-linux-x86-64.so.2 (0x00007f4bbb8c1000) libblkid.so.1 => /lib64/libblkid.so.1 (0x00007f4bbb51b000) libuuid.so.1 => /lib64/libuuid.so.1 (0x00007f4bbb512000) libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f4bbb4e3000) libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007f4bbb45e000) libdl.so.2 => /lib64/libdl.so.2 (0x00007f4bbb458000) build/libnss_mymachines.so.2: linux-vdso.so.1 (0x00007ffc19cc0000) librt.so.1 => /lib64/librt.so.1 (0x00007fdecb74b000) libcap.so.2 => /lib64/libcap.so.2 (0x00007fdecb744000) libmount.so.1 => /lib64/libmount.so.1 (0x00007fdecb6e7000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fdecb6c6000) libc.so.6 => /lib64/libc.so.6 (0x00007fdecb500000) /lib64/ld-linux-x86-64.so.2 (0x00007fdecb8a9000) libblkid.so.1 => /lib64/libblkid.so.1 (0x00007fdecb4ad000) libuuid.so.1 => /lib64/libuuid.so.1 (0x00007fdecb4a2000) libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fdecb475000) libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007fdecb3f0000) libdl.so.2 => /lib64/libdl.so.2 (0x00007fdecb3ea000) build/libnss_resolve.so.2: linux-vdso.so.1 (0x00007ffe8ef8e000) librt.so.1 => /lib64/librt.so.1 (0x00007fcf314bd000) libcap.so.2 => /lib64/libcap.so.2 (0x00007fcf314b6000) libmount.so.1 => /lib64/libmount.so.1 (0x00007fcf31459000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fcf31438000) libc.so.6 => /lib64/libc.so.6 (0x00007fcf31272000) /lib64/ld-linux-x86-64.so.2 (0x00007fcf31615000) libblkid.so.1 => /lib64/libblkid.so.1 (0x00007fcf3121f000) libuuid.so.1 => /lib64/libuuid.so.1 (0x00007fcf31214000) libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fcf311e7000) libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007fcf31162000) libdl.so.2 => /lib64/libdl.so.2 (0x00007fcf3115c000) build/libnss_systemd.so.2: linux-vdso.so.1 (0x00007ffda6d17000) librt.so.1 => /lib64/librt.so.1 (0x00007f610b83c000) libcap.so.2 => /lib64/libcap.so.2 (0x00007f610b835000) libmount.so.1 => /lib64/libmount.so.1 (0x00007f610b7d8000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f610b7b7000) libc.so.6 => /lib64/libc.so.6 (0x00007f610b5f1000) /lib64/ld-linux-x86-64.so.2 (0x00007f610b995000) libblkid.so.1 => /lib64/libblkid.so.1 (0x00007f610b59e000) libuuid.so.1 => /lib64/libuuid.so.1 (0x00007f610b593000) libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f610b566000) libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007f610b4e1000) libdl.so.2 => /lib64/libdl.so.2 (0x00007f610b4db000) (after) build/libnss_myhostname.so.2: linux-vdso.so.1 (0x00007fff0b5e2000) librt.so.1 => /lib64/librt.so.1 (0x00007fde0c328000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fde0c307000) libc.so.6 => /lib64/libc.so.6 (0x00007fde0c141000) /lib64/ld-linux-x86-64.so.2 (0x00007fde0c435000) build/libnss_mymachines.so.2: linux-vdso.so.1 (0x00007ffdc30a7000) librt.so.1 => /lib64/librt.so.1 (0x00007f06ecabb000) libcap.so.2 => /lib64/libcap.so.2 (0x00007f06ecab4000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f06eca93000) libc.so.6 => /lib64/libc.so.6 (0x00007f06ec8cd000) /lib64/ld-linux-x86-64.so.2 (0x00007f06ecc15000) build/libnss_resolve.so.2: linux-vdso.so.1 (0x00007ffe95747000) librt.so.1 => /lib64/librt.so.1 (0x00007fa56a80f000) libcap.so.2 => /lib64/libcap.so.2 (0x00007fa56a808000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fa56a7e7000) libc.so.6 => /lib64/libc.so.6 (0x00007fa56a621000) /lib64/ld-linux-x86-64.so.2 (0x00007fa56a964000) build/libnss_systemd.so.2: linux-vdso.so.1 (0x00007ffe67b51000) librt.so.1 => /lib64/librt.so.1 (0x00007ffb32113000) libcap.so.2 => /lib64/libcap.so.2 (0x00007ffb3210c000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007ffb320eb000) libc.so.6 => /lib64/libc.so.6 (0x00007ffb31f25000) /lib64/ld-linux-x86-64.so.2 (0x00007ffb3226a000) I don't quite understand what is going on here, but let's not be too picky. --- src/basic/copy.c | 2 +- src/basic/meson.build | 2 + src/basic/mount-util.c | 428 +------------------ src/basic/mount-util.h | 26 +- src/basic/mountpoint-util.c | 444 ++++++++++++++++++++ src/basic/mountpoint-util.h | 24 ++ src/basic/rm-rf.c | 2 +- src/core/automount.c | 1 + src/core/dbus-execute.c | 2 +- src/core/load-fragment.c | 2 +- src/core/machine-id-setup.c | 2 +- src/core/mount-setup.c | 2 +- src/core/mount.c | 2 +- src/core/namespace.c | 1 + src/core/umount.c | 1 + src/fstab-generator/fstab-generator.c | 1 + src/gpt-auto-generator/gpt-auto-generator.c | 2 +- src/libsystemd/sd-device/device-monitor.c | 2 +- src/login/user-runtime-dir.c | 2 +- src/mount/mount-tool.c | 1 + src/nspawn/nspawn-cgroup.c | 1 + src/nspawn/nspawn-mount.c | 1 + src/nspawn/nspawn.c | 1 + src/partition/growfs.c | 2 +- src/shared/bus-unit-util.c | 2 +- src/shared/bus-util.c | 2 +- src/shared/condition.c | 2 +- src/shared/dissect-image.c | 1 + src/shared/switch-root.c | 1 + src/test/meson.build | 4 + src/test/test-mount-util.c | 244 ----------- src/test/test-mountpoint-util.c | 258 ++++++++++++ src/test/test-path-util.c | 2 +- src/test/test-stat-util.c | 2 +- src/tmpfiles/tmpfiles.c | 2 +- src/volatile-root/volatile-root.c | 1 + 36 files changed, 762 insertions(+), 713 deletions(-) create mode 100644 src/basic/mountpoint-util.c create mode 100644 src/basic/mountpoint-util.h create mode 100644 src/test/test-mountpoint-util.c diff --git a/src/basic/copy.c b/src/basic/copy.c index 7a4db459e3b..50240de8b6e 100644 --- a/src/basic/copy.c +++ b/src/basic/copy.c @@ -24,7 +24,7 @@ #include "io-util.h" #include "macro.h" #include "missing.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" diff --git a/src/basic/meson.build b/src/basic/meson.build index b13897f334a..906d1c1b3d6 100644 --- a/src/basic/meson.build +++ b/src/basic/meson.build @@ -96,6 +96,8 @@ basic_sources = files(''' mkdir.h mount-util.c mount-util.h + mountpoint-util.c + mountpoint-util.h nss-util.h ordered-set.c ordered-set.h diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c index ec607c7360a..9fa995f6935 100644 --- a/src/basic/mount-util.c +++ b/src/basic/mount-util.c @@ -20,6 +20,7 @@ #include "fs-util.h" #include "hashmap.h" #include "mount-util.h" +#include "mountpoint-util.h" #include "parse-util.h" #include "path-util.h" #include "set.h" @@ -27,279 +28,6 @@ #include "string-util.h" #include "strv.h" -/* This is the original MAX_HANDLE_SZ definition from the kernel, when the API was introduced. We use that in place of - * any more currently defined value to future-proof things: if the size is increased in the API headers, and our code - * is recompiled then it would cease working on old kernels, as those refuse any sizes larger than this value with - * EINVAL right-away. Hence, let's disconnect ourselves from any such API changes, and stick to the original definition - * from when it was introduced. We use it as a start value only anyway (see below), and hence should be able to deal - * with large file handles anyway. */ -#define ORIGINAL_MAX_HANDLE_SZ 128 - -int name_to_handle_at_loop( - int fd, - const char *path, - struct file_handle **ret_handle, - int *ret_mnt_id, - int flags) { - - _cleanup_free_ struct file_handle *h = NULL; - size_t n = ORIGINAL_MAX_HANDLE_SZ; - - /* We need to invoke name_to_handle_at() in a loop, given that it might return EOVERFLOW when the specified - * buffer is too small. Note that in contrast to what the docs might suggest, MAX_HANDLE_SZ is only good as a - * start value, it is not an upper bound on the buffer size required. - * - * This improves on raw name_to_handle_at() also in one other regard: ret_handle and ret_mnt_id can be passed - * as NULL if there's no interest in either. */ - - for (;;) { - int mnt_id = -1; - - h = malloc0(offsetof(struct file_handle, f_handle) + n); - if (!h) - return -ENOMEM; - - h->handle_bytes = n; - - if (name_to_handle_at(fd, path, h, &mnt_id, flags) >= 0) { - - if (ret_handle) - *ret_handle = TAKE_PTR(h); - - if (ret_mnt_id) - *ret_mnt_id = mnt_id; - - return 0; - } - if (errno != EOVERFLOW) - return -errno; - - if (!ret_handle && ret_mnt_id && mnt_id >= 0) { - - /* As it appears, name_to_handle_at() fills in mnt_id even when it returns EOVERFLOW when the - * buffer is too small, but that's undocumented. Hence, let's make use of this if it appears to - * be filled in, and the caller was interested in only the mount ID an nothing else. */ - - *ret_mnt_id = mnt_id; - return 0; - } - - /* If name_to_handle_at() didn't increase the byte size, then this EOVERFLOW is caused by something - * else (apparently EOVERFLOW is returned for untriggered nfs4 mounts sometimes), not by the too small - * buffer. In that case propagate EOVERFLOW */ - if (h->handle_bytes <= n) - return -EOVERFLOW; - - /* The buffer was too small. Size the new buffer by what name_to_handle_at() returned. */ - n = h->handle_bytes; - if (offsetof(struct file_handle, f_handle) + n < n) /* check for addition overflow */ - return -EOVERFLOW; - - h = mfree(h); - } -} - -static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) { - char path[STRLEN("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)]; - _cleanup_free_ char *fdinfo = NULL; - _cleanup_close_ int subfd = -1; - char *p; - int r; - - if ((flags & AT_EMPTY_PATH) && isempty(filename)) - xsprintf(path, "/proc/self/fdinfo/%i", fd); - else { - subfd = openat(fd, filename, O_CLOEXEC|O_PATH); - if (subfd < 0) - return -errno; - - xsprintf(path, "/proc/self/fdinfo/%i", subfd); - } - - r = read_full_file(path, &fdinfo, NULL); - if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */ - return -EOPNOTSUPP; - if (r < 0) - return r; - - p = startswith(fdinfo, "mnt_id:"); - if (!p) { - p = strstr(fdinfo, "\nmnt_id:"); - if (!p) /* The mnt_id field is a relatively new addition */ - return -EOPNOTSUPP; - - p += 8; - } - - p += strspn(p, WHITESPACE); - p[strcspn(p, WHITESPACE)] = 0; - - return safe_atoi(p, mnt_id); -} - -int fd_is_mount_point(int fd, const char *filename, int flags) { - _cleanup_free_ struct file_handle *h = NULL, *h_parent = NULL; - int mount_id = -1, mount_id_parent = -1; - bool nosupp = false, check_st_dev = true; - struct stat a, b; - int r; - - assert(fd >= 0); - assert(filename); - - /* First we will try the name_to_handle_at() syscall, which - * tells us the mount id and an opaque file "handle". It is - * not supported everywhere though (kernel compile-time - * option, not all file systems are hooked up). If it works - * the mount id is usually good enough to tell us whether - * something is a mount point. - * - * If that didn't work we will try to read the mount id from - * /proc/self/fdinfo/. This is almost as good as - * name_to_handle_at(), however, does not return the - * opaque file handle. The opaque file handle is pretty useful - * to detect the root directory, which we should always - * consider a mount point. Hence we use this only as - * fallback. Exporting the mnt_id in fdinfo is a pretty recent - * kernel addition. - * - * As last fallback we do traditional fstat() based st_dev - * comparisons. This is how things were traditionally done, - * but unionfs breaks this since it exposes file - * systems with a variety of st_dev reported. Also, btrfs - * subvolumes have different st_dev, even though they aren't - * real mounts of their own. */ - - r = name_to_handle_at_loop(fd, filename, &h, &mount_id, flags); - if (IN_SET(r, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL)) - /* This kernel does not support name_to_handle_at() at all (ENOSYS), or the syscall was blocked - * (EACCES/EPERM; maybe through seccomp, because we are running inside of a container?), or the mount - * point is not triggered yet (EOVERFLOW, think nfs4), or some general name_to_handle_at() flakiness - * (EINVAL): fall back to simpler logic. */ - goto fallback_fdinfo; - else if (r == -EOPNOTSUPP) - /* This kernel or file system does not support name_to_handle_at(), hence let's see if the upper fs - * supports it (in which case it is a mount point), otherwise fallback to the traditional stat() - * logic */ - nosupp = true; - else if (r < 0) - return r; - - r = name_to_handle_at_loop(fd, "", &h_parent, &mount_id_parent, AT_EMPTY_PATH); - if (r == -EOPNOTSUPP) { - if (nosupp) - /* Neither parent nor child do name_to_handle_at()? We have no choice but to fall back. */ - goto fallback_fdinfo; - else - /* The parent can't do name_to_handle_at() but the directory we are interested in can? If so, - * it must be a mount point. */ - return 1; - } else if (r < 0) - return r; - - /* The parent can do name_to_handle_at() but the - * directory we are interested in can't? If so, it - * must be a mount point. */ - if (nosupp) - return 1; - - /* If the file handle for the directory we are - * interested in and its parent are identical, we - * assume this is the root directory, which is a mount - * point. */ - - if (h->handle_bytes == h_parent->handle_bytes && - h->handle_type == h_parent->handle_type && - memcmp(h->f_handle, h_parent->f_handle, h->handle_bytes) == 0) - return 1; - - return mount_id != mount_id_parent; - -fallback_fdinfo: - r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id); - if (IN_SET(r, -EOPNOTSUPP, -EACCES, -EPERM)) - goto fallback_fstat; - if (r < 0) - return r; - - r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent); - if (r < 0) - return r; - - if (mount_id != mount_id_parent) - return 1; - - /* Hmm, so, the mount ids are the same. This leaves one - * special case though for the root file system. For that, - * let's see if the parent directory has the same inode as we - * are interested in. Hence, let's also do fstat() checks now, - * too, but avoid the st_dev comparisons, since they aren't - * that useful on unionfs mounts. */ - check_st_dev = false; - -fallback_fstat: - /* yay for fstatat() taking a different set of flags than the other - * _at() above */ - if (flags & AT_SYMLINK_FOLLOW) - flags &= ~AT_SYMLINK_FOLLOW; - else - flags |= AT_SYMLINK_NOFOLLOW; - if (fstatat(fd, filename, &a, flags) < 0) - return -errno; - - if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0) - return -errno; - - /* A directory with same device and inode as its parent? Must - * be the root directory */ - if (a.st_dev == b.st_dev && - a.st_ino == b.st_ino) - return 1; - - return check_st_dev && (a.st_dev != b.st_dev); -} - -/* flags can be AT_SYMLINK_FOLLOW or 0 */ -int path_is_mount_point(const char *t, const char *root, int flags) { - _cleanup_free_ char *canonical = NULL; - _cleanup_close_ int fd = -1; - int r; - - assert(t); - assert((flags & ~AT_SYMLINK_FOLLOW) == 0); - - if (path_equal(t, "/")) - return 1; - - /* we need to resolve symlinks manually, we can't just rely on - * fd_is_mount_point() to do that for us; if we have a structure like - * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we - * look at needs to be /usr, not /. */ - if (flags & AT_SYMLINK_FOLLOW) { - r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical); - if (r < 0) - return r; - - t = canonical; - } - - fd = open_parent(t, O_PATH|O_CLOEXEC, 0); - if (fd < 0) - return -errno; - - return fd_is_mount_point(fd, last_path_component(t), flags); -} - -int path_get_mnt_id(const char *path, int *ret) { - int r; - - r = name_to_handle_at_loop(AT_FDCWD, path, NULL, ret, 0); - if (IN_SET(r, -EOPNOTSUPP, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL)) /* kernel/fs don't support this, or seccomp blocks access, or untriggered mount, or name_to_handle_at() is flaky */ - return fd_fdinfo_mnt_id(AT_FDCWD, path, 0, ret); - - return r; -} - int umount_recursive(const char *prefix, int flags) { bool again; int n = 0, r; @@ -601,86 +329,6 @@ int mount_move_root(const char *path) { return 0; } -bool fstype_is_network(const char *fstype) { - const char *x; - - x = startswith(fstype, "fuse."); - if (x) - fstype = x; - - return STR_IN_SET(fstype, - "afs", - "cifs", - "smbfs", - "sshfs", - "ncpfs", - "ncp", - "nfs", - "nfs4", - "gfs", - "gfs2", - "glusterfs", - "pvfs2", /* OrangeFS */ - "ocfs2", - "lustre"); -} - -bool fstype_is_api_vfs(const char *fstype) { - return STR_IN_SET(fstype, - "autofs", - "bpf", - "cgroup", - "cgroup2", - "configfs", - "cpuset", - "debugfs", - "devpts", - "devtmpfs", - "efivarfs", - "fusectl", - "hugetlbfs", - "mqueue", - "proc", - "pstore", - "ramfs", - "securityfs", - "sysfs", - "tmpfs", - "tracefs"); -} - -bool fstype_is_ro(const char *fstype) { - /* All Linux file systems that are necessarily read-only */ - return STR_IN_SET(fstype, - "DM_verity_hash", - "iso9660", - "squashfs"); -} - -bool fstype_can_discard(const char *fstype) { - return STR_IN_SET(fstype, - "btrfs", - "ext4", - "vfat", - "xfs"); -} - -bool fstype_can_uid_gid(const char *fstype) { - - /* All file systems that have a uid=/gid= mount option that fixates the owners of all files and directories, - * current and future. */ - - return STR_IN_SET(fstype, - "adfs", - "fat", - "hfs", - "hpfs", - "iso9660", - "msdos", - "ntfs", - "vfat"); -} - int repeat_unmount(const char *path, int flags) { bool done = false; @@ -852,37 +500,6 @@ int umount_verbose(const char *what) { return 0; } -const char *mount_propagation_flags_to_string(unsigned long flags) { - - switch (flags & (MS_SHARED|MS_SLAVE|MS_PRIVATE)) { - case 0: - return ""; - case MS_SHARED: - return "shared"; - case MS_SLAVE: - return "slave"; - case MS_PRIVATE: - return "private"; - } - - return NULL; -} - -int mount_propagation_flags_from_string(const char *name, unsigned long *ret) { - - if (isempty(name)) - *ret = 0; - else if (streq(name, "shared")) - *ret = MS_SHARED; - else if (streq(name, "slave")) - *ret = MS_SLAVE; - else if (streq(name, "private")) - *ret = MS_PRIVATE; - else - return -EINVAL; - return 0; -} - int mount_option_mangle( const char *options, unsigned long mount_flags, @@ -951,46 +568,3 @@ int mount_option_mangle( return 0; } - -int dev_is_devtmpfs(void) { - _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; - int mount_id, r; - char *e; - - r = path_get_mnt_id("/dev", &mount_id); - if (r < 0) - return r; - - proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); - if (!proc_self_mountinfo) - return -errno; - - (void) __fsetlocking(proc_self_mountinfo, FSETLOCKING_BYCALLER); - - for (;;) { - _cleanup_free_ char *line = NULL; - int mid; - - r = read_line(proc_self_mountinfo, LONG_LINE_MAX, &line); - if (r < 0) - return r; - if (r == 0) - break; - - if (sscanf(line, "%i", &mid) != 1) - continue; - - if (mid != mount_id) - continue; - - e = strstr(line, " - "); - if (!e) - continue; - - /* accept any name that starts with the currently expected type */ - if (startswith(e + 3, "devtmpfs")) - return true; - } - - return false; -} diff --git a/src/basic/mount-util.h b/src/basic/mount-util.h index ad8c47cb325..00df1b0e55e 100644 --- a/src/basic/mount-util.h +++ b/src/basic/mount-util.h @@ -1,25 +1,12 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -#include #include -#include #include -#include -#include #include "macro.h" -#include "missing.h" - -int name_to_handle_at_loop(int fd, const char *path, struct file_handle **ret_handle, int *ret_mnt_id, int flags); - -int path_get_mnt_id(const char *path, int *ret); - -int fd_is_mount_point(int fd, const char *filename, int flags); -int path_is_mount_point(const char *path, const char *root, int flags); int repeat_unmount(const char *path, int flags); - int umount_recursive(const char *target, int flags); int bind_remount_recursive(const char *prefix, bool ro, char **blacklist); int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **blacklist, FILE *proc_self_mountinfo); @@ -29,14 +16,6 @@ int mount_move_root(const char *path); DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent); #define _cleanup_endmntent_ _cleanup_(endmntentp) -bool fstype_is_network(const char *fstype); -bool fstype_is_api_vfs(const char *fstype); -bool fstype_is_ro(const char *fsype); -bool fstype_can_discard(const char *fstype); -bool fstype_can_uid_gid(const char *fstype); - -const char* mode_to_inaccessible_node(mode_t mode); - int mount_verbose( int error_log_level, const char *what, @@ -46,13 +25,10 @@ int mount_verbose( const char *options); int umount_verbose(const char *where); -const char *mount_propagation_flags_to_string(unsigned long flags); -int mount_propagation_flags_from_string(const char *name, unsigned long *ret); - int mount_option_mangle( const char *options, unsigned long mount_flags, unsigned long *ret_mount_flags, char **ret_remaining_options); -int dev_is_devtmpfs(void); +const char* mode_to_inaccessible_node(mode_t mode); diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c new file mode 100644 index 00000000000..0a9f479e42a --- /dev/null +++ b/src/basic/mountpoint-util.c @@ -0,0 +1,444 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "missing.h" +#include "mountpoint-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "stdio-util.h" +#include "strv.h" + +/* This is the original MAX_HANDLE_SZ definition from the kernel, when the API was introduced. We use that in place of + * any more currently defined value to future-proof things: if the size is increased in the API headers, and our code + * is recompiled then it would cease working on old kernels, as those refuse any sizes larger than this value with + * EINVAL right-away. Hence, let's disconnect ourselves from any such API changes, and stick to the original definition + * from when it was introduced. We use it as a start value only anyway (see below), and hence should be able to deal + * with large file handles anyway. */ +#define ORIGINAL_MAX_HANDLE_SZ 128 + +int name_to_handle_at_loop( + int fd, + const char *path, + struct file_handle **ret_handle, + int *ret_mnt_id, + int flags) { + + _cleanup_free_ struct file_handle *h = NULL; + size_t n = ORIGINAL_MAX_HANDLE_SZ; + + /* We need to invoke name_to_handle_at() in a loop, given that it might return EOVERFLOW when the specified + * buffer is too small. Note that in contrast to what the docs might suggest, MAX_HANDLE_SZ is only good as a + * start value, it is not an upper bound on the buffer size required. + * + * This improves on raw name_to_handle_at() also in one other regard: ret_handle and ret_mnt_id can be passed + * as NULL if there's no interest in either. */ + + for (;;) { + int mnt_id = -1; + + h = malloc0(offsetof(struct file_handle, f_handle) + n); + if (!h) + return -ENOMEM; + + h->handle_bytes = n; + + if (name_to_handle_at(fd, path, h, &mnt_id, flags) >= 0) { + + if (ret_handle) + *ret_handle = TAKE_PTR(h); + + if (ret_mnt_id) + *ret_mnt_id = mnt_id; + + return 0; + } + if (errno != EOVERFLOW) + return -errno; + + if (!ret_handle && ret_mnt_id && mnt_id >= 0) { + + /* As it appears, name_to_handle_at() fills in mnt_id even when it returns EOVERFLOW when the + * buffer is too small, but that's undocumented. Hence, let's make use of this if it appears to + * be filled in, and the caller was interested in only the mount ID an nothing else. */ + + *ret_mnt_id = mnt_id; + return 0; + } + + /* If name_to_handle_at() didn't increase the byte size, then this EOVERFLOW is caused by something + * else (apparently EOVERFLOW is returned for untriggered nfs4 mounts sometimes), not by the too small + * buffer. In that case propagate EOVERFLOW */ + if (h->handle_bytes <= n) + return -EOVERFLOW; + + /* The buffer was too small. Size the new buffer by what name_to_handle_at() returned. */ + n = h->handle_bytes; + if (offsetof(struct file_handle, f_handle) + n < n) /* check for addition overflow */ + return -EOVERFLOW; + + h = mfree(h); + } +} + +static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) { + char path[STRLEN("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)]; + _cleanup_free_ char *fdinfo = NULL; + _cleanup_close_ int subfd = -1; + char *p; + int r; + + if ((flags & AT_EMPTY_PATH) && isempty(filename)) + xsprintf(path, "/proc/self/fdinfo/%i", fd); + else { + subfd = openat(fd, filename, O_CLOEXEC|O_PATH); + if (subfd < 0) + return -errno; + + xsprintf(path, "/proc/self/fdinfo/%i", subfd); + } + + r = read_full_file(path, &fdinfo, NULL); + if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */ + return -EOPNOTSUPP; + if (r < 0) + return r; + + p = startswith(fdinfo, "mnt_id:"); + if (!p) { + p = strstr(fdinfo, "\nmnt_id:"); + if (!p) /* The mnt_id field is a relatively new addition */ + return -EOPNOTSUPP; + + p += 8; + } + + p += strspn(p, WHITESPACE); + p[strcspn(p, WHITESPACE)] = 0; + + return safe_atoi(p, mnt_id); +} + +int fd_is_mount_point(int fd, const char *filename, int flags) { + _cleanup_free_ struct file_handle *h = NULL, *h_parent = NULL; + int mount_id = -1, mount_id_parent = -1; + bool nosupp = false, check_st_dev = true; + struct stat a, b; + int r; + + assert(fd >= 0); + assert(filename); + + /* First we will try the name_to_handle_at() syscall, which + * tells us the mount id and an opaque file "handle". It is + * not supported everywhere though (kernel compile-time + * option, not all file systems are hooked up). If it works + * the mount id is usually good enough to tell us whether + * something is a mount point. + * + * If that didn't work we will try to read the mount id from + * /proc/self/fdinfo/. This is almost as good as + * name_to_handle_at(), however, does not return the + * opaque file handle. The opaque file handle is pretty useful + * to detect the root directory, which we should always + * consider a mount point. Hence we use this only as + * fallback. Exporting the mnt_id in fdinfo is a pretty recent + * kernel addition. + * + * As last fallback we do traditional fstat() based st_dev + * comparisons. This is how things were traditionally done, + * but unionfs breaks this since it exposes file + * systems with a variety of st_dev reported. Also, btrfs + * subvolumes have different st_dev, even though they aren't + * real mounts of their own. */ + + r = name_to_handle_at_loop(fd, filename, &h, &mount_id, flags); + if (IN_SET(r, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL)) + /* This kernel does not support name_to_handle_at() at all (ENOSYS), or the syscall was blocked + * (EACCES/EPERM; maybe through seccomp, because we are running inside of a container?), or the mount + * point is not triggered yet (EOVERFLOW, think nfs4), or some general name_to_handle_at() flakiness + * (EINVAL): fall back to simpler logic. */ + goto fallback_fdinfo; + else if (r == -EOPNOTSUPP) + /* This kernel or file system does not support name_to_handle_at(), hence let's see if the upper fs + * supports it (in which case it is a mount point), otherwise fallback to the traditional stat() + * logic */ + nosupp = true; + else if (r < 0) + return r; + + r = name_to_handle_at_loop(fd, "", &h_parent, &mount_id_parent, AT_EMPTY_PATH); + if (r == -EOPNOTSUPP) { + if (nosupp) + /* Neither parent nor child do name_to_handle_at()? We have no choice but to fall back. */ + goto fallback_fdinfo; + else + /* The parent can't do name_to_handle_at() but the directory we are interested in can? If so, + * it must be a mount point. */ + return 1; + } else if (r < 0) + return r; + + /* The parent can do name_to_handle_at() but the + * directory we are interested in can't? If so, it + * must be a mount point. */ + if (nosupp) + return 1; + + /* If the file handle for the directory we are + * interested in and its parent are identical, we + * assume this is the root directory, which is a mount + * point. */ + + if (h->handle_bytes == h_parent->handle_bytes && + h->handle_type == h_parent->handle_type && + memcmp(h->f_handle, h_parent->f_handle, h->handle_bytes) == 0) + return 1; + + return mount_id != mount_id_parent; + +fallback_fdinfo: + r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id); + if (IN_SET(r, -EOPNOTSUPP, -EACCES, -EPERM)) + goto fallback_fstat; + if (r < 0) + return r; + + r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent); + if (r < 0) + return r; + + if (mount_id != mount_id_parent) + return 1; + + /* Hmm, so, the mount ids are the same. This leaves one + * special case though for the root file system. For that, + * let's see if the parent directory has the same inode as we + * are interested in. Hence, let's also do fstat() checks now, + * too, but avoid the st_dev comparisons, since they aren't + * that useful on unionfs mounts. */ + check_st_dev = false; + +fallback_fstat: + /* yay for fstatat() taking a different set of flags than the other + * _at() above */ + if (flags & AT_SYMLINK_FOLLOW) + flags &= ~AT_SYMLINK_FOLLOW; + else + flags |= AT_SYMLINK_NOFOLLOW; + if (fstatat(fd, filename, &a, flags) < 0) + return -errno; + + if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0) + return -errno; + + /* A directory with same device and inode as its parent? Must + * be the root directory */ + if (a.st_dev == b.st_dev && + a.st_ino == b.st_ino) + return 1; + + return check_st_dev && (a.st_dev != b.st_dev); +} + +/* flags can be AT_SYMLINK_FOLLOW or 0 */ +int path_is_mount_point(const char *t, const char *root, int flags) { + _cleanup_free_ char *canonical = NULL; + _cleanup_close_ int fd = -1; + int r; + + assert(t); + assert((flags & ~AT_SYMLINK_FOLLOW) == 0); + + if (path_equal(t, "/")) + return 1; + + /* we need to resolve symlinks manually, we can't just rely on + * fd_is_mount_point() to do that for us; if we have a structure like + * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we + * look at needs to be /usr, not /. */ + if (flags & AT_SYMLINK_FOLLOW) { + r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical); + if (r < 0) + return r; + + t = canonical; + } + + fd = open_parent(t, O_PATH|O_CLOEXEC, 0); + if (fd < 0) + return -errno; + + return fd_is_mount_point(fd, last_path_component(t), flags); +} + +int path_get_mnt_id(const char *path, int *ret) { + int r; + + r = name_to_handle_at_loop(AT_FDCWD, path, NULL, ret, 0); + if (IN_SET(r, -EOPNOTSUPP, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL)) /* kernel/fs don't support this, or seccomp blocks access, or untriggered mount, or name_to_handle_at() is flaky */ + return fd_fdinfo_mnt_id(AT_FDCWD, path, 0, ret); + + return r; +} + +bool fstype_is_network(const char *fstype) { + const char *x; + + x = startswith(fstype, "fuse."); + if (x) + fstype = x; + + return STR_IN_SET(fstype, + "afs", + "cifs", + "smbfs", + "sshfs", + "ncpfs", + "ncp", + "nfs", + "nfs4", + "gfs", + "gfs2", + "glusterfs", + "pvfs2", /* OrangeFS */ + "ocfs2", + "lustre"); +} + +bool fstype_is_api_vfs(const char *fstype) { + return STR_IN_SET(fstype, + "autofs", + "bpf", + "cgroup", + "cgroup2", + "configfs", + "cpuset", + "debugfs", + "devpts", + "devtmpfs", + "efivarfs", + "fusectl", + "hugetlbfs", + "mqueue", + "proc", + "pstore", + "ramfs", + "securityfs", + "sysfs", + "tmpfs", + "tracefs"); +} + +bool fstype_is_ro(const char *fstype) { + /* All Linux file systems that are necessarily read-only */ + return STR_IN_SET(fstype, + "DM_verity_hash", + "iso9660", + "squashfs"); +} + +bool fstype_can_discard(const char *fstype) { + return STR_IN_SET(fstype, + "btrfs", + "ext4", + "vfat", + "xfs"); +} + +bool fstype_can_uid_gid(const char *fstype) { + + /* All file systems that have a uid=/gid= mount option that fixates the owners of all files and directories, + * current and future. */ + + return STR_IN_SET(fstype, + "adfs", + "fat", + "hfs", + "hpfs", + "iso9660", + "msdos", + "ntfs", + "vfat"); +} + +int dev_is_devtmpfs(void) { + _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; + int mount_id, r; + char *e; + + r = path_get_mnt_id("/dev", &mount_id); + if (r < 0) + return r; + + proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); + if (!proc_self_mountinfo) + return -errno; + + (void) __fsetlocking(proc_self_mountinfo, FSETLOCKING_BYCALLER); + + for (;;) { + _cleanup_free_ char *line = NULL; + int mid; + + r = read_line(proc_self_mountinfo, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + if (sscanf(line, "%i", &mid) != 1) + continue; + + if (mid != mount_id) + continue; + + e = strstr(line, " - "); + if (!e) + continue; + + /* accept any name that starts with the currently expected type */ + if (startswith(e + 3, "devtmpfs")) + return true; + } + + return false; +} + +const char *mount_propagation_flags_to_string(unsigned long flags) { + + switch (flags & (MS_SHARED|MS_SLAVE|MS_PRIVATE)) { + case 0: + return ""; + case MS_SHARED: + return "shared"; + case MS_SLAVE: + return "slave"; + case MS_PRIVATE: + return "private"; + } + + return NULL; +} + +int mount_propagation_flags_from_string(const char *name, unsigned long *ret) { + + if (isempty(name)) + *ret = 0; + else if (streq(name, "shared")) + *ret = MS_SHARED; + else if (streq(name, "slave")) + *ret = MS_SLAVE; + else if (streq(name, "private")) + *ret = MS_PRIVATE; + else + return -EINVAL; + return 0; +} diff --git a/src/basic/mountpoint-util.h b/src/basic/mountpoint-util.h new file mode 100644 index 00000000000..5398836fed4 --- /dev/null +++ b/src/basic/mountpoint-util.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +int name_to_handle_at_loop(int fd, const char *path, struct file_handle **ret_handle, int *ret_mnt_id, int flags); + +int path_get_mnt_id(const char *path, int *ret); + +int fd_is_mount_point(int fd, const char *filename, int flags); +int path_is_mount_point(const char *path, const char *root, int flags); + +bool fstype_is_network(const char *fstype); +bool fstype_is_api_vfs(const char *fstype); +bool fstype_is_ro(const char *fsype); +bool fstype_can_discard(const char *fstype); +bool fstype_can_uid_gid(const char *fstype); + +int dev_is_devtmpfs(void); + +const char *mount_propagation_flags_to_string(unsigned long flags); +int mount_propagation_flags_from_string(const char *name, unsigned long *ret); diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c index 1503f1032a8..0c957c9b3a8 100644 --- a/src/basic/rm-rf.c +++ b/src/basic/rm-rf.c @@ -15,7 +15,7 @@ #include "fd-util.h" #include "log.h" #include "macro.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "path-util.h" #include "rm-rf.h" #include "stat-util.h" diff --git a/src/core/automount.c b/src/core/automount.c index 5c1748542e2..3d8348e0b7f 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -23,6 +23,7 @@ #include "mkdir.h" #include "mount-util.h" #include "mount.h" +#include "mountpoint-util.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 31f9099b98e..11301e4b693 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -27,7 +27,7 @@ #include "ioprio.h" #include "journal-util.h" #include "missing.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "namespace.h" #include "parse-util.h" #include "path-util.h" diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 067d36dad51..273d0b96fc7 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -38,7 +38,7 @@ #include "load-fragment.h" #include "log.h" #include "missing.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c index 4dfdc475baf..aae548064e5 100644 --- a/src/core/machine-id-setup.c +++ b/src/core/machine-id-setup.c @@ -15,7 +15,7 @@ #include "machine-id-setup.h" #include "macro.h" #include "mkdir.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "path-util.h" #include "process-util.h" #include "stat-util.h" diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c index e15d94d98a2..a118d83b1b1 100644 --- a/src/core/mount-setup.c +++ b/src/core/mount-setup.c @@ -20,7 +20,7 @@ #include "missing.h" #include "mkdir.h" #include "mount-setup.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "path-util.h" #include "set.h" #include "smack-util.h" diff --git a/src/core/mount.c b/src/core/mount.c index 8c19150112c..99b2aa0904c 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -20,8 +20,8 @@ #include "manager.h" #include "mkdir.h" #include "mount-setup.h" -#include "mount-util.h" #include "mount.h" +#include "mountpoint-util.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" diff --git a/src/core/namespace.c b/src/core/namespace.c index 01516072a05..c2ca3e0334c 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -20,6 +20,7 @@ #include "missing.h" #include "mkdir.h" #include "mount-util.h" +#include "mountpoint-util.h" #include "namespace.h" #include "path-util.h" #include "selinux-util.h" diff --git a/src/core/umount.c b/src/core/umount.c index bd4e4e7257d..7af0195aab8 100644 --- a/src/core/umount.c +++ b/src/core/umount.c @@ -25,6 +25,7 @@ #include "linux-3.13/dm-ioctl.h" #include "mount-setup.h" #include "mount-util.h" +#include "mountpoint-util.h" #include "path-util.h" #include "process-util.h" #include "signal-util.h" diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index c74ad075c04..85cc36d80d5 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -18,6 +18,7 @@ #include "mkdir.h" #include "mount-setup.h" #include "mount-util.h" +#include "mountpoint-util.h" #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index 1ca071e9991..d1889273986 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -23,7 +23,7 @@ #include "gpt.h" #include "missing.h" #include "mkdir.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c index 3ab3ce0dca1..fcf9b761ee9 100644 --- a/src/libsystemd/sd-device/device-monitor.c +++ b/src/libsystemd/sd-device/device-monitor.c @@ -18,7 +18,7 @@ #include "hashmap.h" #include "io-util.h" #include "missing.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "set.h" #include "socket-util.h" #include "string-util.h" diff --git a/src/login/user-runtime-dir.c b/src/login/user-runtime-dir.c index edb62a2d30d..5e58e4baadb 100644 --- a/src/login/user-runtime-dir.c +++ b/src/login/user-runtime-dir.c @@ -10,7 +10,7 @@ #include "label.h" #include "main-func.h" #include "mkdir.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "path-util.h" #include "rm-rf.h" #include "selinux-util.h" diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index 4d53bc5597b..bbbc91c38e3 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -17,6 +17,7 @@ #include "fstab-util.h" #include "main-func.h" #include "mount-util.h" +#include "mountpoint-util.h" #include "pager.h" #include "parse-util.h" #include "path-util.h" diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c index 53c42f0ee47..97fa092caee 100644 --- a/src/nspawn/nspawn-cgroup.c +++ b/src/nspawn/nspawn-cgroup.c @@ -8,6 +8,7 @@ #include "fs-util.h" #include "mkdir.h" #include "mount-util.h" +#include "mountpoint-util.h" #include "nspawn-cgroup.h" #include "nspawn-mount.h" #include "path-util.h" diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 48187079b37..f85c0d9ab30 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -11,6 +11,7 @@ #include "label.h" #include "mkdir.h" #include "mount-util.h" +#include "mountpoint-util.h" #include "nspawn-mount.h" #include "parse-util.h" #include "path-util.h" diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 6eddae49d99..8c6a74bea21 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -60,6 +60,7 @@ #include "missing.h" #include "mkdir.h" #include "mount-util.h" +#include "mountpoint-util.h" #include "netlink-util.h" #include "nspawn-cgroup.h" #include "nspawn-def.h" diff --git a/src/partition/growfs.c b/src/partition/growfs.c index 8e04eb3c23c..7e5642fe800 100644 --- a/src/partition/growfs.c +++ b/src/partition/growfs.c @@ -19,7 +19,7 @@ #include "format-util.h" #include "log.h" #include "missing.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "parse-util.h" #include "path-util.h" #include "pretty-print.h" diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index d11b8c26c74..78a2be341cd 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -17,7 +17,7 @@ #include "in-addr-util.h" #include "list.h" #include "locale-util.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "nsflags.h" #include "parse-util.h" #include "path-util.h" diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 760be38c85d..b9ef0243a3a 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -28,7 +28,7 @@ #include "escape.h" #include "fd-util.h" #include "missing.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "nsflags.h" #include "parse-util.h" #include "proc-cmdline.h" diff --git a/src/shared/condition.c b/src/shared/condition.c index ecc32beadfb..35c9aa4caf5 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -30,7 +30,7 @@ #include "ima-util.h" #include "list.h" #include "macro.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 18620a3b195..384c7ecf4ef 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -26,6 +26,7 @@ #include "id128-util.h" #include "linux-3.13/dm-ioctl.h" #include "missing.h" +#include "mountpoint-util.h" #include "mount-util.h" #include "os-util.h" #include "path-util.h" diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c index c0dfa4bc486..ee31c448fc8 100644 --- a/src/shared/switch-root.c +++ b/src/shared/switch-root.c @@ -16,6 +16,7 @@ #include "missing.h" #include "mkdir.h" #include "mount-util.h" +#include "mountpoint-util.h" #include "path-util.h" #include "rm-rf.h" #include "stdio-util.h" diff --git a/src/test/meson.build b/src/test/meson.build index ade905733ed..410f4fc344c 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -213,6 +213,10 @@ tests += [ [], []], + [['src/test/test-mountpoint-util.c'], + [], + []], + [['src/test/test-exec-util.c'], [], []], diff --git a/src/test/test-mount-util.c b/src/test/test-mount-util.c index 56e385aa117..6986405dc6c 100644 --- a/src/test/test-mount-util.c +++ b/src/test/test-mount-util.c @@ -3,243 +3,10 @@ #include #include "alloc-util.h" -#include "def.h" -#include "fd-util.h" -#include "fileio.h" -#include "hashmap.h" -#include "log.h" -#include "log.h" #include "mount-util.h" -#include "path-util.h" -#include "rm-rf.h" #include "string-util.h" #include "tests.h" -static void test_mount_propagation_flags(const char *name, int ret, unsigned long expected) { - long unsigned flags; - - assert_se(mount_propagation_flags_from_string(name, &flags) == ret); - - if (ret >= 0) { - const char *c; - - assert_se(flags == expected); - - c = mount_propagation_flags_to_string(flags); - if (isempty(name)) - assert_se(isempty(c)); - else - assert_se(streq(c, name)); - } -} - -static void test_mnt_id(void) { - _cleanup_fclose_ FILE *f = NULL; - Hashmap *h; - Iterator i; - char *p; - void *k; - int r; - - assert_se(f = fopen("/proc/self/mountinfo", "re")); - assert_se(h = hashmap_new(&trivial_hash_ops)); - - for (;;) { - _cleanup_free_ char *line = NULL, *path = NULL; - int mnt_id; - - r = read_line(f, LONG_LINE_MAX, &line); - if (r == 0) - break; - assert_se(r > 0); - - assert_se(sscanf(line, "%i %*s %*s %*s %ms", &mnt_id, &path) == 2); - - assert_se(hashmap_put(h, INT_TO_PTR(mnt_id), path) >= 0); - path = NULL; - } - - HASHMAP_FOREACH_KEY(p, k, h, i) { - int mnt_id = PTR_TO_INT(k), mnt_id2; - - r = path_get_mnt_id(p, &mnt_id2); - if (r < 0) { - log_debug_errno(r, "Failed to get the mnt id of %s: %m\n", p); - continue; - } - - log_debug("mnt id of %s is %i\n", p, mnt_id2); - - if (mnt_id == mnt_id2) - continue; - - /* The ids don't match? If so, then there are two mounts on the same path, let's check if that's really - * the case */ - assert_se(path_equal_ptr(hashmap_get(h, INT_TO_PTR(mnt_id2)), p)); - } - - hashmap_free_free(h); -} - -static void test_path_is_mount_point(void) { - int fd; - char tmp_dir[] = "/tmp/test-path-is-mount-point-XXXXXX"; - _cleanup_free_ char *file1 = NULL, *file2 = NULL, *link1 = NULL, *link2 = NULL; - _cleanup_free_ char *dir1 = NULL, *dir1file = NULL, *dirlink1 = NULL, *dirlink1file = NULL; - _cleanup_free_ char *dir2 = NULL, *dir2file = NULL; - - assert_se(path_is_mount_point("/", NULL, AT_SYMLINK_FOLLOW) > 0); - assert_se(path_is_mount_point("/", NULL, 0) > 0); - assert_se(path_is_mount_point("//", NULL, AT_SYMLINK_FOLLOW) > 0); - assert_se(path_is_mount_point("//", NULL, 0) > 0); - - assert_se(path_is_mount_point("/proc", NULL, AT_SYMLINK_FOLLOW) > 0); - assert_se(path_is_mount_point("/proc", NULL, 0) > 0); - assert_se(path_is_mount_point("/proc/", NULL, AT_SYMLINK_FOLLOW) > 0); - assert_se(path_is_mount_point("/proc/", NULL, 0) > 0); - - assert_se(path_is_mount_point("/proc/1", NULL, AT_SYMLINK_FOLLOW) == 0); - assert_se(path_is_mount_point("/proc/1", NULL, 0) == 0); - assert_se(path_is_mount_point("/proc/1/", NULL, AT_SYMLINK_FOLLOW) == 0); - assert_se(path_is_mount_point("/proc/1/", NULL, 0) == 0); - - assert_se(path_is_mount_point("/sys", NULL, AT_SYMLINK_FOLLOW) > 0); - assert_se(path_is_mount_point("/sys", NULL, 0) > 0); - assert_se(path_is_mount_point("/sys/", NULL, AT_SYMLINK_FOLLOW) > 0); - assert_se(path_is_mount_point("/sys/", NULL, 0) > 0); - - /* we'll create a hierarchy of different kinds of dir/file/link - * layouts: - * - * /file1, /file2 - * /link1 -> file1, /link2 -> file2 - * /dir1/ - * /dir1/file - * /dirlink1 -> dir1 - * /dirlink1file -> dirlink1/file - * /dir2/ - * /dir2/file - */ - - /* file mountpoints */ - assert_se(mkdtemp(tmp_dir) != NULL); - file1 = path_join(NULL, tmp_dir, "file1"); - assert_se(file1); - file2 = path_join(NULL, tmp_dir, "file2"); - assert_se(file2); - fd = open(file1, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); - assert_se(fd > 0); - close(fd); - fd = open(file2, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); - assert_se(fd > 0); - close(fd); - link1 = path_join(NULL, tmp_dir, "link1"); - assert_se(link1); - assert_se(symlink("file1", link1) == 0); - link2 = path_join(NULL, tmp_dir, "link2"); - assert_se(link1); - assert_se(symlink("file2", link2) == 0); - - assert_se(path_is_mount_point(file1, NULL, AT_SYMLINK_FOLLOW) == 0); - assert_se(path_is_mount_point(file1, NULL, 0) == 0); - assert_se(path_is_mount_point(link1, NULL, AT_SYMLINK_FOLLOW) == 0); - assert_se(path_is_mount_point(link1, NULL, 0) == 0); - - /* directory mountpoints */ - dir1 = path_join(NULL, tmp_dir, "dir1"); - assert_se(dir1); - assert_se(mkdir(dir1, 0755) == 0); - dirlink1 = path_join(NULL, tmp_dir, "dirlink1"); - assert_se(dirlink1); - assert_se(symlink("dir1", dirlink1) == 0); - dirlink1file = path_join(NULL, tmp_dir, "dirlink1file"); - assert_se(dirlink1file); - assert_se(symlink("dirlink1/file", dirlink1file) == 0); - dir2 = path_join(NULL, tmp_dir, "dir2"); - assert_se(dir2); - assert_se(mkdir(dir2, 0755) == 0); - - assert_se(path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW) == 0); - assert_se(path_is_mount_point(dir1, NULL, 0) == 0); - assert_se(path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW) == 0); - assert_se(path_is_mount_point(dirlink1, NULL, 0) == 0); - - /* file in subdirectory mountpoints */ - dir1file = path_join(NULL, dir1, "file"); - assert_se(dir1file); - fd = open(dir1file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); - assert_se(fd > 0); - close(fd); - - assert_se(path_is_mount_point(dir1file, NULL, AT_SYMLINK_FOLLOW) == 0); - assert_se(path_is_mount_point(dir1file, NULL, 0) == 0); - assert_se(path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW) == 0); - assert_se(path_is_mount_point(dirlink1file, NULL, 0) == 0); - - /* these tests will only work as root */ - if (mount(file1, file2, NULL, MS_BIND, NULL) >= 0) { - int rf, rt, rdf, rdt, rlf, rlt, rl1f, rl1t; - const char *file2d; - - /* files */ - /* capture results in vars, to avoid dangling mounts on failure */ - log_info("%s: %s", __func__, file2); - rf = path_is_mount_point(file2, NULL, 0); - rt = path_is_mount_point(file2, NULL, AT_SYMLINK_FOLLOW); - - file2d = strjoina(file2, "/"); - log_info("%s: %s", __func__, file2d); - rdf = path_is_mount_point(file2d, NULL, 0); - rdt = path_is_mount_point(file2d, NULL, AT_SYMLINK_FOLLOW); - - log_info("%s: %s", __func__, link2); - rlf = path_is_mount_point(link2, NULL, 0); - rlt = path_is_mount_point(link2, NULL, AT_SYMLINK_FOLLOW); - - assert_se(umount(file2) == 0); - - assert_se(rf == 1); - assert_se(rt == 1); - assert_se(rdf == -ENOTDIR); - assert_se(rdt == -ENOTDIR); - assert_se(rlf == 0); - assert_se(rlt == 1); - - /* dirs */ - dir2file = path_join(NULL, dir2, "file"); - assert_se(dir2file); - fd = open(dir2file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); - assert_se(fd > 0); - close(fd); - - assert_se(mount(dir2, dir1, NULL, MS_BIND, NULL) >= 0); - - log_info("%s: %s", __func__, dir1); - rf = path_is_mount_point(dir1, NULL, 0); - rt = path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW); - log_info("%s: %s", __func__, dirlink1); - rlf = path_is_mount_point(dirlink1, NULL, 0); - rlt = path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW); - log_info("%s: %s", __func__, dirlink1file); - /* its parent is a mount point, but not /file itself */ - rl1f = path_is_mount_point(dirlink1file, NULL, 0); - rl1t = path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW); - - assert_se(umount(dir1) == 0); - - assert_se(rf == 1); - assert_se(rt == 1); - assert_se(rlf == 0); - assert_se(rlt == 1); - assert_se(rl1f == 0); - assert_se(rl1t == 0); - - } else - printf("Skipping bind mount file test: %m\n"); - - assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0); -} - static void test_mount_option_mangle(void) { char *opts = NULL; unsigned long f; @@ -295,19 +62,8 @@ static void test_mount_option_mangle(void) { } int main(int argc, char *argv[]) { - test_setup_logging(LOG_DEBUG); - test_mount_propagation_flags("shared", 0, MS_SHARED); - test_mount_propagation_flags("slave", 0, MS_SLAVE); - test_mount_propagation_flags("private", 0, MS_PRIVATE); - test_mount_propagation_flags(NULL, 0, 0); - test_mount_propagation_flags("", 0, 0); - test_mount_propagation_flags("xxxx", -EINVAL, 0); - test_mount_propagation_flags(" ", -EINVAL, 0); - - test_mnt_id(); - test_path_is_mount_point(); test_mount_option_mangle(); return 0; diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c new file mode 100644 index 00000000000..b8b37cf600d --- /dev/null +++ b/src/test/test-mountpoint-util.c @@ -0,0 +1,258 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "def.h" +#include "fd-util.h" +#include "fileio.h" +#include "hashmap.h" +#include "log.h" +#include "log.h" +#include "mountpoint-util.h" +#include "path-util.h" +#include "rm-rf.h" +#include "string-util.h" +#include "tests.h" + +static void test_mount_propagation_flags(const char *name, int ret, unsigned long expected) { + long unsigned flags; + + assert_se(mount_propagation_flags_from_string(name, &flags) == ret); + + if (ret >= 0) { + const char *c; + + assert_se(flags == expected); + + c = mount_propagation_flags_to_string(flags); + if (isempty(name)) + assert_se(isempty(c)); + else + assert_se(streq(c, name)); + } +} + +static void test_mnt_id(void) { + _cleanup_fclose_ FILE *f = NULL; + Hashmap *h; + Iterator i; + char *p; + void *k; + int r; + + assert_se(f = fopen("/proc/self/mountinfo", "re")); + assert_se(h = hashmap_new(&trivial_hash_ops)); + + for (;;) { + _cleanup_free_ char *line = NULL, *path = NULL; + int mnt_id; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r == 0) + break; + assert_se(r > 0); + + assert_se(sscanf(line, "%i %*s %*s %*s %ms", &mnt_id, &path) == 2); + + assert_se(hashmap_put(h, INT_TO_PTR(mnt_id), path) >= 0); + path = NULL; + } + + HASHMAP_FOREACH_KEY(p, k, h, i) { + int mnt_id = PTR_TO_INT(k), mnt_id2; + + r = path_get_mnt_id(p, &mnt_id2); + if (r < 0) { + log_debug_errno(r, "Failed to get the mnt id of %s: %m\n", p); + continue; + } + + log_debug("mnt id of %s is %i\n", p, mnt_id2); + + if (mnt_id == mnt_id2) + continue; + + /* The ids don't match? If so, then there are two mounts on the same path, let's check if that's really + * the case */ + assert_se(path_equal_ptr(hashmap_get(h, INT_TO_PTR(mnt_id2)), p)); + } + + hashmap_free_free(h); +} + +static void test_path_is_mount_point(void) { + int fd; + char tmp_dir[] = "/tmp/test-path-is-mount-point-XXXXXX"; + _cleanup_free_ char *file1 = NULL, *file2 = NULL, *link1 = NULL, *link2 = NULL; + _cleanup_free_ char *dir1 = NULL, *dir1file = NULL, *dirlink1 = NULL, *dirlink1file = NULL; + _cleanup_free_ char *dir2 = NULL, *dir2file = NULL; + + assert_se(path_is_mount_point("/", NULL, AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("/", NULL, 0) > 0); + assert_se(path_is_mount_point("//", NULL, AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("//", NULL, 0) > 0); + + assert_se(path_is_mount_point("/proc", NULL, AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("/proc", NULL, 0) > 0); + assert_se(path_is_mount_point("/proc/", NULL, AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("/proc/", NULL, 0) > 0); + + assert_se(path_is_mount_point("/proc/1", NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point("/proc/1", NULL, 0) == 0); + assert_se(path_is_mount_point("/proc/1/", NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point("/proc/1/", NULL, 0) == 0); + + assert_se(path_is_mount_point("/sys", NULL, AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("/sys", NULL, 0) > 0); + assert_se(path_is_mount_point("/sys/", NULL, AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("/sys/", NULL, 0) > 0); + + /* we'll create a hierarchy of different kinds of dir/file/link + * layouts: + * + * /file1, /file2 + * /link1 -> file1, /link2 -> file2 + * /dir1/ + * /dir1/file + * /dirlink1 -> dir1 + * /dirlink1file -> dirlink1/file + * /dir2/ + * /dir2/file + */ + + /* file mountpoints */ + assert_se(mkdtemp(tmp_dir) != NULL); + file1 = path_join(NULL, tmp_dir, "file1"); + assert_se(file1); + file2 = path_join(NULL, tmp_dir, "file2"); + assert_se(file2); + fd = open(file1, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); + assert_se(fd > 0); + close(fd); + fd = open(file2, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); + assert_se(fd > 0); + close(fd); + link1 = path_join(NULL, tmp_dir, "link1"); + assert_se(link1); + assert_se(symlink("file1", link1) == 0); + link2 = path_join(NULL, tmp_dir, "link2"); + assert_se(link1); + assert_se(symlink("file2", link2) == 0); + + assert_se(path_is_mount_point(file1, NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(file1, NULL, 0) == 0); + assert_se(path_is_mount_point(link1, NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(link1, NULL, 0) == 0); + + /* directory mountpoints */ + dir1 = path_join(NULL, tmp_dir, "dir1"); + assert_se(dir1); + assert_se(mkdir(dir1, 0755) == 0); + dirlink1 = path_join(NULL, tmp_dir, "dirlink1"); + assert_se(dirlink1); + assert_se(symlink("dir1", dirlink1) == 0); + dirlink1file = path_join(NULL, tmp_dir, "dirlink1file"); + assert_se(dirlink1file); + assert_se(symlink("dirlink1/file", dirlink1file) == 0); + dir2 = path_join(NULL, tmp_dir, "dir2"); + assert_se(dir2); + assert_se(mkdir(dir2, 0755) == 0); + + assert_se(path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(dir1, NULL, 0) == 0); + assert_se(path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(dirlink1, NULL, 0) == 0); + + /* file in subdirectory mountpoints */ + dir1file = path_join(NULL, dir1, "file"); + assert_se(dir1file); + fd = open(dir1file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); + assert_se(fd > 0); + close(fd); + + assert_se(path_is_mount_point(dir1file, NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(dir1file, NULL, 0) == 0); + assert_se(path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(dirlink1file, NULL, 0) == 0); + + /* these tests will only work as root */ + if (mount(file1, file2, NULL, MS_BIND, NULL) >= 0) { + int rf, rt, rdf, rdt, rlf, rlt, rl1f, rl1t; + const char *file2d; + + /* files */ + /* capture results in vars, to avoid dangling mounts on failure */ + log_info("%s: %s", __func__, file2); + rf = path_is_mount_point(file2, NULL, 0); + rt = path_is_mount_point(file2, NULL, AT_SYMLINK_FOLLOW); + + file2d = strjoina(file2, "/"); + log_info("%s: %s", __func__, file2d); + rdf = path_is_mount_point(file2d, NULL, 0); + rdt = path_is_mount_point(file2d, NULL, AT_SYMLINK_FOLLOW); + + log_info("%s: %s", __func__, link2); + rlf = path_is_mount_point(link2, NULL, 0); + rlt = path_is_mount_point(link2, NULL, AT_SYMLINK_FOLLOW); + + assert_se(umount(file2) == 0); + + assert_se(rf == 1); + assert_se(rt == 1); + assert_se(rdf == -ENOTDIR); + assert_se(rdt == -ENOTDIR); + assert_se(rlf == 0); + assert_se(rlt == 1); + + /* dirs */ + dir2file = path_join(NULL, dir2, "file"); + assert_se(dir2file); + fd = open(dir2file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); + assert_se(fd > 0); + close(fd); + + assert_se(mount(dir2, dir1, NULL, MS_BIND, NULL) >= 0); + + log_info("%s: %s", __func__, dir1); + rf = path_is_mount_point(dir1, NULL, 0); + rt = path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW); + log_info("%s: %s", __func__, dirlink1); + rlf = path_is_mount_point(dirlink1, NULL, 0); + rlt = path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW); + log_info("%s: %s", __func__, dirlink1file); + /* its parent is a mount point, but not /file itself */ + rl1f = path_is_mount_point(dirlink1file, NULL, 0); + rl1t = path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW); + + assert_se(umount(dir1) == 0); + + assert_se(rf == 1); + assert_se(rt == 1); + assert_se(rlf == 0); + assert_se(rlt == 1); + assert_se(rl1f == 0); + assert_se(rl1t == 0); + + } else + printf("Skipping bind mount file test: %m\n"); + + assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_mount_propagation_flags("shared", 0, MS_SHARED); + test_mount_propagation_flags("slave", 0, MS_SLAVE); + test_mount_propagation_flags("private", 0, MS_PRIVATE); + test_mount_propagation_flags(NULL, 0, 0); + test_mount_propagation_flags("", 0, 0); + test_mount_propagation_flags("xxxx", -EINVAL, 0); + test_mount_propagation_flags(" ", -EINVAL, 0); + + test_mnt_id(); + test_path_is_mount_point(); + + return 0; +} diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 7feae54068f..d2ccb41fd9e 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -6,7 +6,7 @@ #include "alloc-util.h" #include "fd-util.h" #include "macro.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "path-util.h" #include "rm-rf.h" #include "stat-util.h" diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c index 2b0564d8a05..2f0538a4bba 100644 --- a/src/test/test-stat-util.c +++ b/src/test/test-stat-util.c @@ -9,7 +9,7 @@ #include "fileio.h" #include "macro.h" #include "missing.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "stat-util.h" static void test_files_same(void) { diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index eeeb1d18506..e31af282a4d 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -41,7 +41,7 @@ #include "macro.h" #include "missing.h" #include "mkdir.h" -#include "mount-util.h" +#include "mountpoint-util.h" #include "pager.h" #include "parse-util.h" #include "path-lookup.h" diff --git a/src/volatile-root/volatile-root.c b/src/volatile-root/volatile-root.c index ffe63d5717a..5da9ce1681d 100644 --- a/src/volatile-root/volatile-root.c +++ b/src/volatile-root/volatile-root.c @@ -7,6 +7,7 @@ #include "main-func.h" #include "mkdir.h" #include "mount-util.h" +#include "mountpoint-util.h" #include "path-util.h" #include "stat-util.h" #include "string-util.h" From 77c772f227d866331560a8d0487fba12dd128dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 29 Nov 2018 10:29:34 +0100 Subject: [PATCH 2/2] Move mount-util.c to shared/ libmount dep is moved from libbasic to libshared, potentially removing libmount from some build products. --- src/basic/meson.build | 3 --- src/shared/meson.build | 3 +++ src/{basic => shared}/mount-util.c | 0 src/{basic => shared}/mount-util.h | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename src/{basic => shared}/mount-util.c (100%) rename src/{basic => shared}/mount-util.h (100%) diff --git a/src/basic/meson.build b/src/basic/meson.build index 906d1c1b3d6..124a3e9f847 100644 --- a/src/basic/meson.build +++ b/src/basic/meson.build @@ -94,8 +94,6 @@ basic_sources = files(''' mkdir-label.c mkdir.c mkdir.h - mount-util.c - mount-util.h mountpoint-util.c mountpoint-util.h nss-util.h @@ -259,7 +257,6 @@ libbasic = static_library( include_directories : includes, dependencies : [threads, libcap, - libmount, libselinux, libm], c_args : ['-fvisibility=default'], diff --git a/src/shared/meson.build b/src/shared/meson.build index b7676b6eb97..85c546eb5bb 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -98,6 +98,8 @@ shared_sources = files(''' machine-pool.h main-func.h module-util.h + mount-util.c + mount-util.h nsflags.c nsflags.h os-util.c @@ -235,6 +237,7 @@ libshared_deps = [threads, libgcrypt, libiptc, libkmod, + libmount, libseccomp, libselinux, libidn, diff --git a/src/basic/mount-util.c b/src/shared/mount-util.c similarity index 100% rename from src/basic/mount-util.c rename to src/shared/mount-util.c diff --git a/src/basic/mount-util.h b/src/shared/mount-util.h similarity index 100% rename from src/basic/mount-util.h rename to src/shared/mount-util.h