]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
util-lib: move mount related utility calls to mount-util.[ch]
authorLennart Poettering <lennart@poettering.net>
Mon, 26 Oct 2015 17:44:13 +0000 (18:44 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 27 Oct 2015 12:25:55 +0000 (13:25 +0100)
24 files changed:
Makefile.am
src/basic/mount-util.c [new file with mode: 0644]
src/basic/mount-util.h [new file with mode: 0644]
src/basic/path-util.c
src/basic/path-util.h
src/basic/rm-rf.c
src/basic/util.c
src/basic/util.h
src/core/automount.c
src/core/machine-id-setup.c
src/core/mount-setup.c
src/core/namespace.c
src/cryptsetup/cryptsetup.c
src/fstab-generator/fstab-generator.c
src/gpt-auto-generator/gpt-auto-generator.c
src/login/logind-user.c
src/nspawn/nspawn-mount.c
src/nspawn/nspawn.c
src/remount-fs/remount-fs.c
src/shared/condition.c
src/shared/fstab-util.c
src/shared/generator.c
src/shared/machine-pool.c
src/test/test-path-util.c

index 26d5587b11d1ab52ad8187f498d987ad0a7a5bfd..275b85619146c2de800fbfb1a67396c513a0017b 100644 (file)
@@ -791,6 +791,8 @@ libbasic_la_SOURCES = \
        src/basic/parse-util.h \
        src/basic/user-util.c \
        src/basic/user-util.h \
+       src/basic/mount-util.c \
+       src/basic/mount-util.h \
        src/basic/hexdecoct.c \
        src/basic/hexdecoct.h \
        src/basic/extract-word.c \
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
new file mode 100644 (file)
index 0000000..6b33d43
--- /dev/null
@@ -0,0 +1,483 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 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 <string.h>
+#include <sys/mount.h>
+#include <sys/statvfs.h>
+
+#include "escape.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "mount-util.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "set.h"
+#include "string-util.h"
+#include "util.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_RDONLY|O_CLOEXEC|O_NOCTTY|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 -errno;
+
+        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) {
+        union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT;
+        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/<fd>. 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 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(fd, filename, &h.handle, &mount_id, flags);
+        if (r < 0) {
+                if (errno == ENOSYS)
+                        /* This kernel does not support name_to_handle_at()
+                         * fall back to simpler logic. */
+                        goto fallback_fdinfo;
+                else if (errno == 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
+                        return -errno;
+        }
+
+        r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH);
+        if (r < 0) {
+                if (errno == 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
+                        return -errno;
+        }
+
+        /* 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.handle_bytes == h_parent.handle.handle_bytes &&
+            h.handle.handle_type == h_parent.handle.handle_type &&
+            memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0)
+                return 1;
+
+        return mount_id != mount_id_parent;
+
+fallback_fdinfo:
+        r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id);
+        if (r == -EOPNOTSUPP)
+                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, int flags) {
+        _cleanup_close_ int fd = -1;
+        _cleanup_free_ char *canonical = NULL, *parent = NULL;
+
+        assert(t);
+
+        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) {
+                canonical = canonicalize_file_name(t);
+                if (!canonical)
+                        return -errno;
+
+                t = canonical;
+        }
+
+        parent = dirname_malloc(t);
+        if (!parent)
+                return -ENOMEM;
+
+        fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH);
+        if (fd < 0)
+                return -errno;
+
+        return fd_is_mount_point(fd, basename(t), flags);
+}
+
+int umount_recursive(const char *prefix, int flags) {
+        bool again;
+        int n = 0, r;
+
+        /* Try to umount everything recursively below a
+         * directory. Also, take care of stacked mounts, and keep
+         * unmounting them until they are gone. */
+
+        do {
+                _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
+
+                again = false;
+                r = 0;
+
+                proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
+                if (!proc_self_mountinfo)
+                        return -errno;
+
+                for (;;) {
+                        _cleanup_free_ char *path = NULL, *p = NULL;
+                        int k;
+
+                        k = fscanf(proc_self_mountinfo,
+                                   "%*s "       /* (1) mount id */
+                                   "%*s "       /* (2) parent id */
+                                   "%*s "       /* (3) major:minor */
+                                   "%*s "       /* (4) root */
+                                   "%ms "       /* (5) mount point */
+                                   "%*s"        /* (6) mount options */
+                                   "%*[^-]"     /* (7) optional fields */
+                                   "- "         /* (8) separator */
+                                   "%*s "       /* (9) file system type */
+                                   "%*s"        /* (10) mount source */
+                                   "%*s"        /* (11) mount options 2 */
+                                   "%*[^\n]",   /* some rubbish at the end */
+                                   &path);
+                        if (k != 1) {
+                                if (k == EOF)
+                                        break;
+
+                                continue;
+                        }
+
+                        r = cunescape(path, UNESCAPE_RELAX, &p);
+                        if (r < 0)
+                                return r;
+
+                        if (!path_startswith(p, prefix))
+                                continue;
+
+                        if (umount2(p, flags) < 0) {
+                                r = -errno;
+                                continue;
+                        }
+
+                        again = true;
+                        n++;
+
+                        break;
+                }
+
+        } while (again);
+
+        return r ? r : n;
+}
+
+static int get_mount_flags(const char *path, unsigned long *flags) {
+        struct statvfs buf;
+
+        if (statvfs(path, &buf) < 0)
+                return -errno;
+        *flags = buf.f_flag;
+        return 0;
+}
+
+int bind_remount_recursive(const char *prefix, bool ro) {
+        _cleanup_set_free_free_ Set *done = NULL;
+        _cleanup_free_ char *cleaned = NULL;
+        int r;
+
+        /* Recursively remount a directory (and all its submounts)
+         * read-only or read-write. If the directory is already
+         * mounted, we reuse the mount and simply mark it
+         * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
+         * operation). If it isn't we first make it one. Afterwards we
+         * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all
+         * submounts we can access, too. When mounts are stacked on
+         * the same mount point we only care for each individual
+         * "top-level" mount on each point, as we cannot
+         * influence/access the underlying mounts anyway. We do not
+         * have any effect on future submounts that might get
+         * propagated, they migt be writable. This includes future
+         * submounts that have been triggered via autofs. */
+
+        cleaned = strdup(prefix);
+        if (!cleaned)
+                return -ENOMEM;
+
+        path_kill_slashes(cleaned);
+
+        done = set_new(&string_hash_ops);
+        if (!done)
+                return -ENOMEM;
+
+        for (;;) {
+                _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
+                _cleanup_set_free_free_ Set *todo = NULL;
+                bool top_autofs = false;
+                char *x;
+                unsigned long orig_flags;
+
+                todo = set_new(&string_hash_ops);
+                if (!todo)
+                        return -ENOMEM;
+
+                proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
+                if (!proc_self_mountinfo)
+                        return -errno;
+
+                for (;;) {
+                        _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
+                        int k;
+
+                        k = fscanf(proc_self_mountinfo,
+                                   "%*s "       /* (1) mount id */
+                                   "%*s "       /* (2) parent id */
+                                   "%*s "       /* (3) major:minor */
+                                   "%*s "       /* (4) root */
+                                   "%ms "       /* (5) mount point */
+                                   "%*s"        /* (6) mount options (superblock) */
+                                   "%*[^-]"     /* (7) optional fields */
+                                   "- "         /* (8) separator */
+                                   "%ms "       /* (9) file system type */
+                                   "%*s"        /* (10) mount source */
+                                   "%*s"        /* (11) mount options (bind mount) */
+                                   "%*[^\n]",   /* some rubbish at the end */
+                                   &path,
+                                   &type);
+                        if (k != 2) {
+                                if (k == EOF)
+                                        break;
+
+                                continue;
+                        }
+
+                        r = cunescape(path, UNESCAPE_RELAX, &p);
+                        if (r < 0)
+                                return r;
+
+                        /* Let's ignore autofs mounts.  If they aren't
+                         * triggered yet, we want to avoid triggering
+                         * them, as we don't make any guarantees for
+                         * future submounts anyway.  If they are
+                         * already triggered, then we will find
+                         * another entry for this. */
+                        if (streq(type, "autofs")) {
+                                top_autofs = top_autofs || path_equal(cleaned, p);
+                                continue;
+                        }
+
+                        if (path_startswith(p, cleaned) &&
+                            !set_contains(done, p)) {
+
+                                r = set_consume(todo, p);
+                                p = NULL;
+
+                                if (r == -EEXIST)
+                                        continue;
+                                if (r < 0)
+                                        return r;
+                        }
+                }
+
+                /* If we have no submounts to process anymore and if
+                 * the root is either already done, or an autofs, we
+                 * are done */
+                if (set_isempty(todo) &&
+                    (top_autofs || set_contains(done, cleaned)))
+                        return 0;
+
+                if (!set_contains(done, cleaned) &&
+                    !set_contains(todo, cleaned)) {
+                        /* The prefix directory itself is not yet a
+                         * mount, make it one. */
+                        if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0)
+                                return -errno;
+
+                        orig_flags = 0;
+                        (void) get_mount_flags(cleaned, &orig_flags);
+                        orig_flags &= ~MS_RDONLY;
+
+                        if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
+                                return -errno;
+
+                        x = strdup(cleaned);
+                        if (!x)
+                                return -ENOMEM;
+
+                        r = set_consume(done, x);
+                        if (r < 0)
+                                return r;
+                }
+
+                while ((x = set_steal_first(todo))) {
+
+                        r = set_consume(done, x);
+                        if (r == -EEXIST || r == 0)
+                                continue;
+                        if (r < 0)
+                                return r;
+
+                        /* Try to reuse the original flag set, but
+                         * don't care for errors, in case of
+                         * obstructed mounts */
+                        orig_flags = 0;
+                        (void) get_mount_flags(x, &orig_flags);
+                        orig_flags &= ~MS_RDONLY;
+
+                        if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) {
+
+                                /* Deal with mount points that are
+                                 * obstructed by a later mount */
+
+                                if (errno != ENOENT)
+                                        return -errno;
+                        }
+
+                }
+        }
+}
+
+int mount_move_root(const char *path) {
+        assert(path);
+
+        if (chdir(path) < 0)
+                return -errno;
+
+        if (mount(path, "/", NULL, MS_MOVE, NULL) < 0)
+                return -errno;
+
+        if (chroot(".") < 0)
+                return -errno;
+
+        if (chdir("/") < 0)
+                return -errno;
+
+        return 0;
+}
diff --git a/src/basic/mount-util.h b/src/basic/mount-util.h
new file mode 100644 (file)
index 0000000..b415d00
--- /dev/null
@@ -0,0 +1,36 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 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 <stdbool.h>
+#include <mntent.h>
+
+int fd_is_mount_point(int fd, const char *filename, int flags);
+int path_is_mount_point(const char *path, int flags);
+
+int umount_recursive(const char *target, int flags);
+int bind_remount_recursive(const char *prefix, bool ro);
+
+int mount_move_root(const char *path);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
+#define _cleanup_endmntent_ _cleanup_(endmntentp)
index 7abb3a7b9e7c153c66d4caea884aefa2c250e0b3..b1cab7356c2c0284640657ec04f3e0f2170b9636 100644 (file)
@@ -454,205 +454,6 @@ char* path_join(const char *root, const char *path, const char *rest) {
                                NULL);
 }
 
-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_RDONLY|O_CLOEXEC|O_NOCTTY|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 -errno;
-
-        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) {
-        union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT;
-        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/<fd>. 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 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(fd, filename, &h.handle, &mount_id, flags);
-        if (r < 0) {
-                if (errno == ENOSYS)
-                        /* This kernel does not support name_to_handle_at()
-                         * fall back to simpler logic. */
-                        goto fallback_fdinfo;
-                else if (errno == 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
-                        return -errno;
-        }
-
-        r = name_to_handle_at(fd, "", &h_parent.handle, &mount_id_parent, AT_EMPTY_PATH);
-        if (r < 0) {
-                if (errno == 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
-                        return -errno;
-        }
-
-        /* 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.handle_bytes == h_parent.handle.handle_bytes &&
-            h.handle.handle_type == h_parent.handle.handle_type &&
-            memcmp(h.handle.f_handle, h_parent.handle.f_handle, h.handle.handle_bytes) == 0)
-                return 1;
-
-        return mount_id != mount_id_parent;
-
-fallback_fdinfo:
-        r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id);
-        if (r == -EOPNOTSUPP)
-                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, int flags) {
-        _cleanup_close_ int fd = -1;
-        _cleanup_free_ char *canonical = NULL, *parent = NULL;
-
-        assert(t);
-
-        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) {
-                canonical = canonicalize_file_name(t);
-                if (!canonical)
-                        return -errno;
-
-                t = canonical;
-        }
-
-        parent = dirname_malloc(t);
-        if (!parent)
-                return -ENOMEM;
-
-        fd = openat(AT_FDCWD, parent, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_PATH);
-        if (fd < 0)
-                return -errno;
-
-        return fd_is_mount_point(fd, basename(t), flags);
-}
-
 int path_is_read_only_fs(const char *path) {
         struct statvfs st;
 
index 708cdc1707ebcf8bb810699d3887c0d184681ee5..1ff47ab19304c18cd2be93c2830d4d55e09ed8bb 100644 (file)
@@ -52,8 +52,6 @@ int path_strv_make_absolute_cwd(char **l);
 char** path_strv_resolve(char **l, const char *prefix);
 char** path_strv_resolve_uniq(char **l, const char *prefix);
 
-int fd_is_mount_point(int fd, const char *filename, int flags);
-int path_is_mount_point(const char *path, int flags);
 int path_is_read_only_fs(const char *path);
 int path_is_os_tree(const char *path);
 
index a5daa23f869d4ff35f6407e4adc5a07cfc803dbd..f1850ea8a30e831a1df2ba9bbdf4e5ae70f9e3b0 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "btrfs-util.h"
 #include "fd-util.h"
+#include "mount-util.h"
 #include "path-util.h"
 #include "rm-rf.h"
 #include "string-util.h"
index 607d9cd933ad25483542dba1869a40039ac02be2..06fe307ba02b533349a3b40d2d729eb070c60397 100644 (file)
@@ -2137,237 +2137,6 @@ int update_reboot_param_file(const char *param) {
         return 0;
 }
 
-int umount_recursive(const char *prefix, int flags) {
-        bool again;
-        int n = 0, r;
-
-        /* Try to umount everything recursively below a
-         * directory. Also, take care of stacked mounts, and keep
-         * unmounting them until they are gone. */
-
-        do {
-                _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
-
-                again = false;
-                r = 0;
-
-                proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
-                if (!proc_self_mountinfo)
-                        return -errno;
-
-                for (;;) {
-                        _cleanup_free_ char *path = NULL, *p = NULL;
-                        int k;
-
-                        k = fscanf(proc_self_mountinfo,
-                                   "%*s "       /* (1) mount id */
-                                   "%*s "       /* (2) parent id */
-                                   "%*s "       /* (3) major:minor */
-                                   "%*s "       /* (4) root */
-                                   "%ms "       /* (5) mount point */
-                                   "%*s"        /* (6) mount options */
-                                   "%*[^-]"     /* (7) optional fields */
-                                   "- "         /* (8) separator */
-                                   "%*s "       /* (9) file system type */
-                                   "%*s"        /* (10) mount source */
-                                   "%*s"        /* (11) mount options 2 */
-                                   "%*[^\n]",   /* some rubbish at the end */
-                                   &path);
-                        if (k != 1) {
-                                if (k == EOF)
-                                        break;
-
-                                continue;
-                        }
-
-                        r = cunescape(path, UNESCAPE_RELAX, &p);
-                        if (r < 0)
-                                return r;
-
-                        if (!path_startswith(p, prefix))
-                                continue;
-
-                        if (umount2(p, flags) < 0) {
-                                r = -errno;
-                                continue;
-                        }
-
-                        again = true;
-                        n++;
-
-                        break;
-                }
-
-        } while (again);
-
-        return r ? r : n;
-}
-
-static int get_mount_flags(const char *path, unsigned long *flags) {
-        struct statvfs buf;
-
-        if (statvfs(path, &buf) < 0)
-                return -errno;
-        *flags = buf.f_flag;
-        return 0;
-}
-
-int bind_remount_recursive(const char *prefix, bool ro) {
-        _cleanup_set_free_free_ Set *done = NULL;
-        _cleanup_free_ char *cleaned = NULL;
-        int r;
-
-        /* Recursively remount a directory (and all its submounts)
-         * read-only or read-write. If the directory is already
-         * mounted, we reuse the mount and simply mark it
-         * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write
-         * operation). If it isn't we first make it one. Afterwards we
-         * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all
-         * submounts we can access, too. When mounts are stacked on
-         * the same mount point we only care for each individual
-         * "top-level" mount on each point, as we cannot
-         * influence/access the underlying mounts anyway. We do not
-         * have any effect on future submounts that might get
-         * propagated, they migt be writable. This includes future
-         * submounts that have been triggered via autofs. */
-
-        cleaned = strdup(prefix);
-        if (!cleaned)
-                return -ENOMEM;
-
-        path_kill_slashes(cleaned);
-
-        done = set_new(&string_hash_ops);
-        if (!done)
-                return -ENOMEM;
-
-        for (;;) {
-                _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
-                _cleanup_set_free_free_ Set *todo = NULL;
-                bool top_autofs = false;
-                char *x;
-                unsigned long orig_flags;
-
-                todo = set_new(&string_hash_ops);
-                if (!todo)
-                        return -ENOMEM;
-
-                proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
-                if (!proc_self_mountinfo)
-                        return -errno;
-
-                for (;;) {
-                        _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
-                        int k;
-
-                        k = fscanf(proc_self_mountinfo,
-                                   "%*s "       /* (1) mount id */
-                                   "%*s "       /* (2) parent id */
-                                   "%*s "       /* (3) major:minor */
-                                   "%*s "       /* (4) root */
-                                   "%ms "       /* (5) mount point */
-                                   "%*s"        /* (6) mount options (superblock) */
-                                   "%*[^-]"     /* (7) optional fields */
-                                   "- "         /* (8) separator */
-                                   "%ms "       /* (9) file system type */
-                                   "%*s"        /* (10) mount source */
-                                   "%*s"        /* (11) mount options (bind mount) */
-                                   "%*[^\n]",   /* some rubbish at the end */
-                                   &path,
-                                   &type);
-                        if (k != 2) {
-                                if (k == EOF)
-                                        break;
-
-                                continue;
-                        }
-
-                        r = cunescape(path, UNESCAPE_RELAX, &p);
-                        if (r < 0)
-                                return r;
-
-                        /* Let's ignore autofs mounts.  If they aren't
-                         * triggered yet, we want to avoid triggering
-                         * them, as we don't make any guarantees for
-                         * future submounts anyway.  If they are
-                         * already triggered, then we will find
-                         * another entry for this. */
-                        if (streq(type, "autofs")) {
-                                top_autofs = top_autofs || path_equal(cleaned, p);
-                                continue;
-                        }
-
-                        if (path_startswith(p, cleaned) &&
-                            !set_contains(done, p)) {
-
-                                r = set_consume(todo, p);
-                                p = NULL;
-
-                                if (r == -EEXIST)
-                                        continue;
-                                if (r < 0)
-                                        return r;
-                        }
-                }
-
-                /* If we have no submounts to process anymore and if
-                 * the root is either already done, or an autofs, we
-                 * are done */
-                if (set_isempty(todo) &&
-                    (top_autofs || set_contains(done, cleaned)))
-                        return 0;
-
-                if (!set_contains(done, cleaned) &&
-                    !set_contains(todo, cleaned)) {
-                        /* The prefix directory itself is not yet a
-                         * mount, make it one. */
-                        if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0)
-                                return -errno;
-
-                        orig_flags = 0;
-                        (void) get_mount_flags(cleaned, &orig_flags);
-                        orig_flags &= ~MS_RDONLY;
-
-                        if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
-                                return -errno;
-
-                        x = strdup(cleaned);
-                        if (!x)
-                                return -ENOMEM;
-
-                        r = set_consume(done, x);
-                        if (r < 0)
-                                return r;
-                }
-
-                while ((x = set_steal_first(todo))) {
-
-                        r = set_consume(done, x);
-                        if (r == -EEXIST || r == 0)
-                                continue;
-                        if (r < 0)
-                                return r;
-
-                        /* Try to reuse the original flag set, but
-                         * don't care for errors, in case of
-                         * obstructed mounts */
-                        orig_flags = 0;
-                        (void) get_mount_flags(x, &orig_flags);
-                        orig_flags &= ~MS_RDONLY;
-
-                        if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) {
-
-                                /* Deal with mount points that are
-                                 * obstructed by a later mount */
-
-                                if (errno != ENOENT)
-                                        return -errno;
-                        }
-
-                }
-        }
-}
-
 int take_password_lock(const char *root) {
 
         struct flock flock = {
@@ -2710,24 +2479,6 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
         return 0;
 }
 
-int mount_move_root(const char *path) {
-        assert(path);
-
-        if (chdir(path) < 0)
-                return -errno;
-
-        if (mount(path, "/", NULL, MS_MOVE, NULL) < 0)
-                return -errno;
-
-        if (chroot(".") < 0)
-                return -errno;
-
-        if (chdir("/") < 0)
-                return -errno;
-
-        return 0;
-}
-
 int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) {
         char *v;
         size_t l;
index c6c3ba99f245db6d5e99ef6717c2ce04386521b4..9388ba7d749c91d56059409f2bedc0aceb2b2814 100644 (file)
@@ -27,7 +27,6 @@
 #include <inttypes.h>
 #include <limits.h>
 #include <locale.h>
-#include <mntent.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stddef.h>
@@ -279,12 +278,9 @@ static inline void umaskp(mode_t *u) {
         umask(*u);
 }
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
-
 #define _cleanup_free_ _cleanup_(freep)
 #define _cleanup_umask_ _cleanup_(umaskp)
 #define _cleanup_globfree_ _cleanup_(globfree)
-#define _cleanup_endmntent_ _cleanup_(endmntentp)
 
 _malloc_  _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) {
         if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
@@ -525,10 +521,6 @@ union file_handle_union {
 
 int update_reboot_param_file(const char *param);
 
-int umount_recursive(const char *target, int flags);
-
-int bind_remount_recursive(const char *prefix, bool ro);
-
 int take_password_lock(const char *root);
 
 int is_symlink(const char *path);
@@ -568,8 +560,6 @@ int syslog_parse_priority(const char **p, int *priority, bool with_facility);
 
 int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
 
-int mount_move_root(const char *path);
-
 int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink);
 int fgetxattr_malloc(int fd, const char *name, char **value);
 
index df98711d9681febe6743450731fa3bacb95fab80..00911118e6111cc1faff3e4bf74db90aa24c2f18 100644 (file)
@@ -39,6 +39,7 @@
 #include "io-util.h"
 #include "label.h"
 #include "mkdir.h"
+#include "mount-util.h"
 #include "mount.h"
 #include "parse-util.h"
 #include "path-util.h"
index ea4bdc54147d0b9efb529c512789d7c4fb3a96e3..764728c804c6398c3180701d87e5c5da7d4a7c22 100644 (file)
 
 #include "fd-util.h"
 #include "fileio.h"
+#include "hexdecoct.h"
 #include "io-util.h"
 #include "log.h"
 #include "machine-id-setup.h"
 #include "macro.h"
 #include "mkdir.h"
-#include "hexdecoct.h"
+#include "mount-util.h"
 #include "path-util.h"
 #include "process-util.h"
 #include "string-util.h"
index 9b16eaa0e2d9ae0679164017995922fce9a1bf05..7486ec398580532f3cb5aabb2ddafc8d9ee6bfb7 100644 (file)
 #include <unistd.h>
 #include <ftw.h>
 
-#include "mount-setup.h"
-#include "dev-setup.h"
 #include "bus-util.h"
+#include "cgroup-util.h"
+#include "dev-setup.h"
+#include "efivars.h"
+#include "label.h"
 #include "log.h"
 #include "macro.h"
-#include "util.h"
-#include "label.h"
-#include "set.h"
-#include "strv.h"
+#include "missing.h"
 #include "mkdir.h"
+#include "mount-setup.h"
+#include "mount-util.h"
 #include "path-util.h"
-#include "missing.h"
-#include "virt.h"
-#include "efivars.h"
+#include "set.h"
 #include "smack-util.h"
-#include "cgroup-util.h"
+#include "strv.h"
+#include "util.h"
+#include "virt.h"
 
 typedef enum MountMode {
         MNT_NONE  =        0,
index 4d11d54bfed35a760a003255d962f11b5ce0a1be..e6c381800b92921fa91c9dd9d91798bd6dfaf226 100644 (file)
@@ -33,6 +33,7 @@
 #include "loopback-setup.h"
 #include "missing.h"
 #include "mkdir.h"
+#include "mount-util.h"
 #include "namespace.h"
 #include "path-util.h"
 #include "selinux-util.h"
index 4c1d8a8e74655b39bbd1c093ee7e04299aafe087..8531b6b1251522a7f8eefaa3e9b40fa685249b9e 100644 (file)
@@ -32,6 +32,7 @@
 #include "escape.h"
 #include "fileio.h"
 #include "log.h"
+#include "mount-util.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "string-util.h"
index 732b3d1704a3355ed5ed94d16ab2ba08466e6c36..fd0d01153a6cbf4fad1f4b7e601e6eaac6019197 100644 (file)
@@ -32,6 +32,7 @@
 #include "log.h"
 #include "mkdir.h"
 #include "mount-setup.h"
+#include "mount-util.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "special.h"
index ac6d731753ef3ae6dfed6fe86deae2a579fc55d5..6440fd654e0caa0e45b6770ae16b65c8f91c3a6b 100644 (file)
@@ -37,6 +37,7 @@
 #include "gpt.h"
 #include "missing.h"
 #include "mkdir.h"
+#include "mount-util.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "special.h"
index 9f3af59b545095df27fc2b738928796b5976451f..5a7ae11ec149753e7336c9390ba976aa134aac65 100644 (file)
@@ -36,6 +36,7 @@
 #include "label.h"
 #include "logind-user.h"
 #include "mkdir.h"
+#include "mount-util.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "rm-rf.h"
index 5d8172092a651afee094f547647af7998839fd01..ac9c31b931fcf223a2016494c11c5d47aff60207 100644 (file)
@@ -26,6 +26,7 @@
 #include "escape.h"
 #include "label.h"
 #include "mkdir.h"
+#include "mount-util.h"
 #include "nspawn-mount.h"
 #include "parse-util.h"
 #include "path-util.h"
index a4eefe5eb88c071d53981734bfcbd4351f09e763..c34d52293de6640739300006d237630fa803f6da 100644 (file)
@@ -69,6 +69,7 @@
 #include "macro.h"
 #include "missing.h"
 #include "mkdir.h"
+#include "mount-util.h"
 #include "netlink-util.h"
 #include "nspawn-cgroup.h"
 #include "nspawn-expose-ports.h"
index f904e48e753d35c5a80c40ef16f5c2b8f03e444e..57f99c9ef0cc83c17f7b7a0361d3a45278f3ea63 100644 (file)
 #include <sys/wait.h>
 #include <mntent.h>
 
+#include "exit-status.h"
 #include "log.h"
-#include "util.h"
+#include "mount-setup.h"
+#include "mount-util.h"
 #include "path-util.h"
 #include "signal-util.h"
-#include "mount-setup.h"
-#include "exit-status.h"
+#include "util.h"
 
 /* Goes through /etc/fstab and remounts all API file systems, applying
  * options that are in /etc/fstab that systemd might not have
index 145ea410956d35fedfe5a6ae138237d2bbe860c5..700bc92438f6b89d2c37c6b1dbd41d06131644ff 100644 (file)
@@ -36,6 +36,7 @@
 #include "fd-util.h"
 #include "hostname-util.h"
 #include "ima-util.h"
+#include "mount-util.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "selinux-util.h"
index 77faa7bc3502f21e8b0b5259f606ec39247bb06e..1ea11ea5a45810de6902c626b77a38b49b9a40fa 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "device-nodes.h"
 #include "fstab-util.h"
+#include "mount-util.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "string-util.h"
index 0a8e282949e16d3107c2b6e9e5a93e9453c022de..203e01318bd29a04d8923eb21bb9eeb586456783 100644 (file)
@@ -28,6 +28,7 @@
 #include "fstab-util.h"
 #include "generator.h"
 #include "mkdir.h"
+#include "mount-util.h"
 #include "path-util.h"
 #include "special.h"
 #include "string-util.h"
index 6d726a687a4671fc14cc717df58b3e3c2f189765..9270f224793184ce080558b9cfba44858258cb96 100644 (file)
@@ -36,6 +36,7 @@
 #include "signal-util.h"
 #include "string-util.h"
 #include "util.h"
+#include "mount-util.h"
 
 #define VAR_LIB_MACHINES_SIZE_START (1024UL*1024UL*500UL)
 #define VAR_LIB_MACHINES_FREE_MIN (1024UL*1024UL*750UL)
index 86d61b2efba6387008906789b82e1a3d4ced5914..e2979a8710b779a62de3a23fc89c0038d6fbb485 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "fd-util.h"
 #include "macro.h"
+#include "mount-util.h"
 #include "path-util.h"
 #include "rm-rf.h"
 #include "string-util.h"