| File: | build-scan/../src/basic/mount-util.c |
| Warning: | line 75, column 33 Potential leak of memory pointed to by 'h' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
| 2 | ||||
| 3 | #include <errno(*__errno_location ()).h> | |||
| 4 | #include <stdio_ext.h> | |||
| 5 | #include <stdlib.h> | |||
| 6 | #include <string.h> | |||
| 7 | #include <sys/mount.h> | |||
| 8 | #include <sys/stat.h> | |||
| 9 | #include <sys/statvfs.h> | |||
| 10 | #include <unistd.h> | |||
| 11 | ||||
| 12 | /* Include later */ | |||
| 13 | #include <libmount.h> | |||
| 14 | ||||
| 15 | #include "alloc-util.h" | |||
| 16 | #include "escape.h" | |||
| 17 | #include "extract-word.h" | |||
| 18 | #include "fd-util.h" | |||
| 19 | #include "fileio.h" | |||
| 20 | #include "fs-util.h" | |||
| 21 | #include "hashmap.h" | |||
| 22 | #include "mount-util.h" | |||
| 23 | #include "parse-util.h" | |||
| 24 | #include "path-util.h" | |||
| 25 | #include "set.h" | |||
| 26 | #include "stdio-util.h" | |||
| 27 | #include "string-util.h" | |||
| 28 | #include "strv.h" | |||
| 29 | ||||
| 30 | /* This is the original MAX_HANDLE_SZ definition from the kernel, when the API was introduced. We use that in place of | |||
| 31 | * any more currently defined value to future-proof things: if the size is increased in the API headers, and our code | |||
| 32 | * is recompiled then it would cease working on old kernels, as those refuse any sizes larger than this value with | |||
| 33 | * EINVAL right-away. Hence, let's disconnect ourselves from any such API changes, and stick to the original definition | |||
| 34 | * from when it was introduced. We use it as a start value only anyway (see below), and hence should be able to deal | |||
| 35 | * with large file handles anyway. */ | |||
| 36 | #define ORIGINAL_MAX_HANDLE_SZ128 128 | |||
| 37 | ||||
| 38 | int name_to_handle_at_loop( | |||
| 39 | int fd, | |||
| 40 | const char *path, | |||
| 41 | struct file_handle **ret_handle, | |||
| 42 | int *ret_mnt_id, | |||
| 43 | int flags) { | |||
| 44 | ||||
| 45 | _cleanup_free___attribute__((cleanup(freep))) struct file_handle *h = NULL((void*)0); | |||
| 46 | size_t n = ORIGINAL_MAX_HANDLE_SZ128; | |||
| 47 | ||||
| 48 | /* We need to invoke name_to_handle_at() in a loop, given that it might return EOVERFLOW when the specified | |||
| 49 | * buffer is too small. Note that in contrast to what the docs might suggest, MAX_HANDLE_SZ is only good as a | |||
| 50 | * start value, it is not an upper bound on the buffer size required. | |||
| 51 | * | |||
| 52 | * This improves on raw name_to_handle_at() also in one other regard: ret_handle and ret_mnt_id can be passed | |||
| 53 | * as NULL if there's no interest in either. */ | |||
| 54 | ||||
| 55 | for (;;) { | |||
| 56 | int mnt_id = -1; | |||
| 57 | ||||
| 58 | h = malloc0(offsetof(struct file_handle, f_handle) + n)(calloc(1, (__builtin_offsetof(struct file_handle, f_handle) + n))); | |||
| 59 | if (!h) | |||
| 60 | return -ENOMEM12; | |||
| 61 | ||||
| 62 | h->handle_bytes = n; | |||
| 63 | ||||
| 64 | if (name_to_handle_at(fd, path, h, &mnt_id, flags) >= 0) { | |||
| 65 | ||||
| 66 | if (ret_handle) | |||
| 67 | *ret_handle = TAKE_PTR(h)({ typeof(h) _ptr_ = (h); (h) = ((void*)0); _ptr_; }); | |||
| 68 | ||||
| 69 | if (ret_mnt_id) | |||
| 70 | *ret_mnt_id = mnt_id; | |||
| 71 | ||||
| 72 | return 0; | |||
| 73 | } | |||
| 74 | if (errno(*__errno_location ()) != EOVERFLOW75) | |||
| 75 | return -errno(*__errno_location ()); | |||
| ||||
| 76 | ||||
| 77 | if (!ret_handle && ret_mnt_id && mnt_id >= 0) { | |||
| 78 | ||||
| 79 | /* As it appears, name_to_handle_at() fills in mnt_id even when it returns EOVERFLOW when the | |||
| 80 | * buffer is too small, but that's undocumented. Hence, let's make use of this if it appears to | |||
| 81 | * be filled in, and the caller was interested in only the mount ID an nothing else. */ | |||
| 82 | ||||
| 83 | *ret_mnt_id = mnt_id; | |||
| 84 | return 0; | |||
| 85 | } | |||
| 86 | ||||
| 87 | /* If name_to_handle_at() didn't increase the byte size, then this EOVERFLOW is caused by something | |||
| 88 | * else (apparently EOVERFLOW is returned for untriggered nfs4 mounts sometimes), not by the too small | |||
| 89 | * buffer. In that case propagate EOVERFLOW */ | |||
| 90 | if (h->handle_bytes <= n) | |||
| 91 | return -EOVERFLOW75; | |||
| 92 | ||||
| 93 | /* The buffer was too small. Size the new buffer by what name_to_handle_at() returned. */ | |||
| 94 | n = h->handle_bytes; | |||
| 95 | if (offsetof(struct file_handle, f_handle)__builtin_offsetof(struct file_handle, f_handle) + n < n) /* check for addition overflow */ | |||
| 96 | return -EOVERFLOW75; | |||
| 97 | ||||
| 98 | h = mfree(h); | |||
| 99 | } | |||
| 100 | } | |||
| 101 | ||||
| 102 | static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) { | |||
| 103 | char path[STRLEN("/proc/self/fdinfo/")(sizeof("""/proc/self/fdinfo/""") - 1) + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof (int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2 *(sizeof(int) > 8)])))]; | |||
| 104 | _cleanup_free___attribute__((cleanup(freep))) char *fdinfo = NULL((void*)0); | |||
| 105 | _cleanup_close___attribute__((cleanup(closep))) int subfd = -1; | |||
| 106 | char *p; | |||
| 107 | int r; | |||
| 108 | ||||
| 109 | if ((flags & AT_EMPTY_PATH0x1000) && isempty(filename)) | |||
| 110 | xsprintf(path, "/proc/self/fdinfo/%i", fd)do { if ((__builtin_expect(!!(!(((size_t) snprintf(path, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (path), typeof(&*(path))), sizeof(path)/sizeof((path)[0]) , ((void)0))), "/proc/self/fdinfo/%i", fd) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (path), typeof(&*(path))), sizeof(path)/sizeof((path)[0]) , ((void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("xsprintf: " "path" "[] must be big enough"), "../src/basic/mount-util.c" , 110, __PRETTY_FUNCTION__); } while (0); | |||
| 111 | else { | |||
| 112 | subfd = openat(fd, filename, O_CLOEXEC02000000|O_PATH010000000|(flags & AT_SYMLINK_FOLLOW0x400 ? 0 : O_NOFOLLOW0400000)); | |||
| 113 | if (subfd < 0) | |||
| 114 | return -errno(*__errno_location ()); | |||
| 115 | ||||
| 116 | xsprintf(path, "/proc/self/fdinfo/%i", subfd)do { if ((__builtin_expect(!!(!(((size_t) snprintf(path, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (path), typeof(&*(path))), sizeof(path)/sizeof((path)[0]) , ((void)0))), "/proc/self/fdinfo/%i", subfd) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (path), typeof(&*(path))), sizeof(path)/sizeof((path)[0]) , ((void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("xsprintf: " "path" "[] must be big enough"), "../src/basic/mount-util.c" , 116, __PRETTY_FUNCTION__); } while (0); | |||
| 117 | } | |||
| 118 | ||||
| 119 | r = read_full_file(path, &fdinfo, NULL((void*)0)); | |||
| 120 | if (r == -ENOENT2) /* The fdinfo directory is a relatively new addition */ | |||
| 121 | return -EOPNOTSUPP95; | |||
| 122 | if (r < 0) | |||
| 123 | return r; | |||
| 124 | ||||
| 125 | p = startswith(fdinfo, "mnt_id:"); | |||
| 126 | if (!p) { | |||
| 127 | p = strstr(fdinfo, "\nmnt_id:"); | |||
| 128 | if (!p) /* The mnt_id field is a relatively new addition */ | |||
| 129 | return -EOPNOTSUPP95; | |||
| 130 | ||||
| 131 | p += 8; | |||
| 132 | } | |||
| 133 | ||||
| 134 | p += strspn(p, WHITESPACE" \t\n\r"); | |||
| 135 | p[strcspn(p, WHITESPACE" \t\n\r")] = 0; | |||
| 136 | ||||
| 137 | return safe_atoi(p, mnt_id); | |||
| 138 | } | |||
| 139 | ||||
| 140 | int fd_is_mount_point(int fd, const char *filename, int flags) { | |||
| 141 | _cleanup_free___attribute__((cleanup(freep))) struct file_handle *h = NULL((void*)0), *h_parent = NULL((void*)0); | |||
| 142 | int mount_id = -1, mount_id_parent = -1; | |||
| 143 | bool_Bool nosupp = false0, check_st_dev = true1; | |||
| 144 | struct stat a, b; | |||
| 145 | int r; | |||
| 146 | ||||
| 147 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/basic/mount-util.c" , 147, __PRETTY_FUNCTION__); } while (0); | |||
| 148 | assert(filename)do { if ((__builtin_expect(!!(!(filename)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("filename"), "../src/basic/mount-util.c" , 148, __PRETTY_FUNCTION__); } while (0); | |||
| 149 | ||||
| 150 | /* First we will try the name_to_handle_at() syscall, which | |||
| 151 | * tells us the mount id and an opaque file "handle". It is | |||
| 152 | * not supported everywhere though (kernel compile-time | |||
| 153 | * option, not all file systems are hooked up). If it works | |||
| 154 | * the mount id is usually good enough to tell us whether | |||
| 155 | * something is a mount point. | |||
| 156 | * | |||
| 157 | * If that didn't work we will try to read the mount id from | |||
| 158 | * /proc/self/fdinfo/<fd>. This is almost as good as | |||
| 159 | * name_to_handle_at(), however, does not return the | |||
| 160 | * opaque file handle. The opaque file handle is pretty useful | |||
| 161 | * to detect the root directory, which we should always | |||
| 162 | * consider a mount point. Hence we use this only as | |||
| 163 | * fallback. Exporting the mnt_id in fdinfo is a pretty recent | |||
| 164 | * kernel addition. | |||
| 165 | * | |||
| 166 | * As last fallback we do traditional fstat() based st_dev | |||
| 167 | * comparisons. This is how things were traditionally done, | |||
| 168 | * but unionfs breaks this since it exposes file | |||
| 169 | * systems with a variety of st_dev reported. Also, btrfs | |||
| 170 | * subvolumes have different st_dev, even though they aren't | |||
| 171 | * real mounts of their own. */ | |||
| 172 | ||||
| 173 | r = name_to_handle_at_loop(fd, filename, &h, &mount_id, flags); | |||
| 174 | if (IN_SET(r, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){-38, -13, -1, -75, -22})/sizeof(int)]; switch (r) { case -38: case -13: case -1: case -75: case -22: _found = 1; break; default: break; } _found; })) | |||
| 175 | /* This kernel does not support name_to_handle_at() at all (ENOSYS), or the syscall was blocked | |||
| 176 | * (EACCES/EPERM; maybe through seccomp, because we are running inside of a container?), or the mount | |||
| 177 | * point is not triggered yet (EOVERFLOW, think nfs4), or some general name_to_handle_at() flakiness | |||
| 178 | * (EINVAL): fall back to simpler logic. */ | |||
| 179 | goto fallback_fdinfo; | |||
| 180 | else if (r == -EOPNOTSUPP95) | |||
| 181 | /* This kernel or file system does not support name_to_handle_at(), hence let's see if the upper fs | |||
| 182 | * supports it (in which case it is a mount point), otherwise fallback to the traditional stat() | |||
| 183 | * logic */ | |||
| 184 | nosupp = true1; | |||
| 185 | else if (r < 0) | |||
| 186 | return r; | |||
| 187 | ||||
| 188 | r = name_to_handle_at_loop(fd, "", &h_parent, &mount_id_parent, AT_EMPTY_PATH0x1000); | |||
| 189 | if (r == -EOPNOTSUPP95) { | |||
| 190 | if (nosupp) | |||
| 191 | /* Neither parent nor child do name_to_handle_at()? We have no choice but to fall back. */ | |||
| 192 | goto fallback_fdinfo; | |||
| 193 | else | |||
| 194 | /* The parent can't do name_to_handle_at() but the directory we are interested in can? If so, | |||
| 195 | * it must be a mount point. */ | |||
| 196 | return 1; | |||
| 197 | } else if (r < 0) | |||
| 198 | return r; | |||
| 199 | ||||
| 200 | /* The parent can do name_to_handle_at() but the | |||
| 201 | * directory we are interested in can't? If so, it | |||
| 202 | * must be a mount point. */ | |||
| 203 | if (nosupp) | |||
| 204 | return 1; | |||
| 205 | ||||
| 206 | /* If the file handle for the directory we are | |||
| 207 | * interested in and its parent are identical, we | |||
| 208 | * assume this is the root directory, which is a mount | |||
| 209 | * point. */ | |||
| 210 | ||||
| 211 | if (h->handle_bytes == h_parent->handle_bytes && | |||
| 212 | h->handle_type == h_parent->handle_type && | |||
| 213 | memcmp(h->f_handle, h_parent->f_handle, h->handle_bytes) == 0) | |||
| 214 | return 1; | |||
| 215 | ||||
| 216 | return mount_id != mount_id_parent; | |||
| 217 | ||||
| 218 | fallback_fdinfo: | |||
| 219 | r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id); | |||
| 220 | if (IN_SET(r, -EOPNOTSUPP, -EACCES, -EPERM)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){-95, -13, -1})/sizeof(int)]; switch(r) { case -95: case -13: case -1: _found = 1; break; default: break ; } _found; })) | |||
| 221 | goto fallback_fstat; | |||
| 222 | if (r < 0) | |||
| 223 | return r; | |||
| 224 | ||||
| 225 | r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH0x1000, &mount_id_parent); | |||
| 226 | if (r < 0) | |||
| 227 | return r; | |||
| 228 | ||||
| 229 | if (mount_id != mount_id_parent) | |||
| 230 | return 1; | |||
| 231 | ||||
| 232 | /* Hmm, so, the mount ids are the same. This leaves one | |||
| 233 | * special case though for the root file system. For that, | |||
| 234 | * let's see if the parent directory has the same inode as we | |||
| 235 | * are interested in. Hence, let's also do fstat() checks now, | |||
| 236 | * too, but avoid the st_dev comparisons, since they aren't | |||
| 237 | * that useful on unionfs mounts. */ | |||
| 238 | check_st_dev = false0; | |||
| 239 | ||||
| 240 | fallback_fstat: | |||
| 241 | /* yay for fstatat() taking a different set of flags than the other | |||
| 242 | * _at() above */ | |||
| 243 | if (flags & AT_SYMLINK_FOLLOW0x400) | |||
| 244 | flags &= ~AT_SYMLINK_FOLLOW0x400; | |||
| 245 | else | |||
| 246 | flags |= AT_SYMLINK_NOFOLLOW0x100; | |||
| 247 | if (fstatat(fd, filename, &a, flags) < 0) | |||
| 248 | return -errno(*__errno_location ()); | |||
| 249 | ||||
| 250 | if (fstatat(fd, "", &b, AT_EMPTY_PATH0x1000) < 0) | |||
| 251 | return -errno(*__errno_location ()); | |||
| 252 | ||||
| 253 | /* A directory with same device and inode as its parent? Must | |||
| 254 | * be the root directory */ | |||
| 255 | if (a.st_dev == b.st_dev && | |||
| 256 | a.st_ino == b.st_ino) | |||
| 257 | return 1; | |||
| 258 | ||||
| 259 | return check_st_dev && (a.st_dev != b.st_dev); | |||
| 260 | } | |||
| 261 | ||||
| 262 | /* flags can be AT_SYMLINK_FOLLOW or 0 */ | |||
| 263 | int path_is_mount_point(const char *t, const char *root, int flags) { | |||
| 264 | _cleanup_free___attribute__((cleanup(freep))) char *canonical = NULL((void*)0), *parent = NULL((void*)0); | |||
| 265 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; | |||
| 266 | int r; | |||
| 267 | ||||
| 268 | assert(t)do { if ((__builtin_expect(!!(!(t)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("t"), "../src/basic/mount-util.c", 268, __PRETTY_FUNCTION__ ); } while (0); | |||
| 269 | assert((flags & ~AT_SYMLINK_FOLLOW) == 0)do { if ((__builtin_expect(!!(!((flags & ~0x400) == 0)),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("(flags & ~AT_SYMLINK_FOLLOW) == 0" ), "../src/basic/mount-util.c", 269, __PRETTY_FUNCTION__); } while (0); | |||
| 270 | ||||
| 271 | if (path_equal(t, "/")) | |||
| 272 | return 1; | |||
| 273 | ||||
| 274 | /* we need to resolve symlinks manually, we can't just rely on | |||
| 275 | * fd_is_mount_point() to do that for us; if we have a structure like | |||
| 276 | * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we | |||
| 277 | * look at needs to be /usr, not /. */ | |||
| 278 | if (flags & AT_SYMLINK_FOLLOW0x400) { | |||
| 279 | r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical); | |||
| 280 | if (r < 0) | |||
| 281 | return r; | |||
| 282 | ||||
| 283 | t = canonical; | |||
| 284 | } | |||
| 285 | ||||
| 286 | parent = dirname_malloc(t); | |||
| 287 | if (!parent) | |||
| 288 | return -ENOMEM12; | |||
| 289 | ||||
| 290 | fd = openat(AT_FDCWD-100, parent, O_DIRECTORY0200000|O_CLOEXEC02000000|O_PATH010000000); | |||
| 291 | if (fd < 0) | |||
| 292 | return -errno(*__errno_location ()); | |||
| 293 | ||||
| 294 | return fd_is_mount_point(fd, last_path_component(t), flags); | |||
| 295 | } | |||
| 296 | ||||
| 297 | int path_get_mnt_id(const char *path, int *ret) { | |||
| 298 | int r; | |||
| 299 | ||||
| 300 | r = name_to_handle_at_loop(AT_FDCWD-100, path, NULL((void*)0), ret, 0); | |||
| 301 | if (IN_SET(r, -EOPNOTSUPP, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){-95, -38, -13, -1, -75, -22})/sizeof(int )]; switch(r) { case -95: case -38: case -13: case -1: case - 75: case -22: _found = 1; break; default: break; } _found; })) /* kernel/fs don't support this, or seccomp blocks access, or untriggered mount, or name_to_handle_at() is flaky */ | |||
| 302 | return fd_fdinfo_mnt_id(AT_FDCWD-100, path, 0, ret); | |||
| 303 | ||||
| 304 | return r; | |||
| 305 | } | |||
| 306 | ||||
| 307 | int umount_recursive(const char *prefix, int flags) { | |||
| 308 | bool_Bool again; | |||
| 309 | int n = 0, r; | |||
| 310 | ||||
| 311 | /* Try to umount everything recursively below a | |||
| 312 | * directory. Also, take care of stacked mounts, and keep | |||
| 313 | * unmounting them until they are gone. */ | |||
| 314 | ||||
| 315 | do { | |||
| 316 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *proc_self_mountinfo = NULL((void*)0); | |||
| 317 | ||||
| 318 | again = false0; | |||
| 319 | r = 0; | |||
| 320 | ||||
| 321 | proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); | |||
| 322 | if (!proc_self_mountinfo) | |||
| 323 | return -errno(*__errno_location ()); | |||
| 324 | ||||
| 325 | (void) __fsetlocking(proc_self_mountinfo, FSETLOCKING_BYCALLERFSETLOCKING_BYCALLER); | |||
| 326 | ||||
| 327 | for (;;) { | |||
| 328 | _cleanup_free___attribute__((cleanup(freep))) char *path = NULL((void*)0), *p = NULL((void*)0); | |||
| 329 | int k; | |||
| 330 | ||||
| 331 | k = fscanf(proc_self_mountinfo, | |||
| 332 | "%*s " /* (1) mount id */ | |||
| 333 | "%*s " /* (2) parent id */ | |||
| 334 | "%*s " /* (3) major:minor */ | |||
| 335 | "%*s " /* (4) root */ | |||
| 336 | "%ms " /* (5) mount point */ | |||
| 337 | "%*s" /* (6) mount options */ | |||
| 338 | "%*[^-]" /* (7) optional fields */ | |||
| 339 | "- " /* (8) separator */ | |||
| 340 | "%*s " /* (9) file system type */ | |||
| 341 | "%*s" /* (10) mount source */ | |||
| 342 | "%*s" /* (11) mount options 2 */ | |||
| 343 | "%*[^\n]", /* some rubbish at the end */ | |||
| 344 | &path); | |||
| 345 | if (k != 1) { | |||
| 346 | if (k == EOF(-1)) | |||
| 347 | break; | |||
| 348 | ||||
| 349 | continue; | |||
| 350 | } | |||
| 351 | ||||
| 352 | r = cunescape(path, UNESCAPE_RELAX, &p); | |||
| 353 | if (r < 0) | |||
| 354 | return r; | |||
| 355 | ||||
| 356 | if (!path_startswith(p, prefix)) | |||
| 357 | continue; | |||
| 358 | ||||
| 359 | if (umount2(p, flags) < 0) { | |||
| 360 | r = log_debug_errno(errno, "Failed to umount %s: %m", p)({ int _level = ((7)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/basic/mount-util.c", 360, __func__ , "Failed to umount %s: %m", p) : -abs(_e); }); | |||
| 361 | continue; | |||
| 362 | } | |||
| 363 | ||||
| 364 | log_debug("Successfully unmounted %s", p)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 364, __func__, "Successfully unmounted %s" , p) : -abs(_e); }); | |||
| 365 | ||||
| 366 | again = true1; | |||
| 367 | n++; | |||
| 368 | ||||
| 369 | break; | |||
| 370 | } | |||
| 371 | ||||
| 372 | } while (again); | |||
| 373 | ||||
| 374 | return r ? r : n; | |||
| 375 | } | |||
| 376 | ||||
| 377 | static int get_mount_flags(const char *path, unsigned long *flags) { | |||
| 378 | struct statvfs buf; | |||
| 379 | ||||
| 380 | if (statvfs(path, &buf) < 0) | |||
| 381 | return -errno(*__errno_location ()); | |||
| 382 | *flags = buf.f_flag; | |||
| 383 | return 0; | |||
| 384 | } | |||
| 385 | ||||
| 386 | /* Use this function only if do you have direct access to /proc/self/mountinfo | |||
| 387 | * and need the caller to open it for you. This is the case when /proc is | |||
| 388 | * masked or not mounted. Otherwise, use bind_remount_recursive. */ | |||
| 389 | int bind_remount_recursive_with_mountinfo(const char *prefix, bool_Bool ro, char **blacklist, FILE *proc_self_mountinfo) { | |||
| 390 | _cleanup_set_free_free___attribute__((cleanup(set_free_freep))) Set *done = NULL((void*)0); | |||
| 391 | _cleanup_free___attribute__((cleanup(freep))) char *cleaned = NULL((void*)0); | |||
| 392 | int r; | |||
| 393 | ||||
| 394 | assert(proc_self_mountinfo)do { if ((__builtin_expect(!!(!(proc_self_mountinfo)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("proc_self_mountinfo"), "../src/basic/mount-util.c" , 394, __PRETTY_FUNCTION__); } while (0); | |||
| ||||
| 395 | ||||
| 396 | /* Recursively remount a directory (and all its submounts) read-only or read-write. If the directory is already | |||
| 397 | * mounted, we reuse the mount and simply mark it MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write | |||
| 398 | * operation). If it isn't we first make it one. Afterwards we apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to | |||
| 399 | * all submounts we can access, too. When mounts are stacked on the same mount point we only care for each | |||
| 400 | * individual "top-level" mount on each point, as we cannot influence/access the underlying mounts anyway. We | |||
| 401 | * do not have any effect on future submounts that might get propagated, they migt be writable. This includes | |||
| 402 | * future submounts that have been triggered via autofs. | |||
| 403 | * | |||
| 404 | * If the "blacklist" parameter is specified it may contain a list of subtrees to exclude from the | |||
| 405 | * remount operation. Note that we'll ignore the blacklist for the top-level path. */ | |||
| 406 | ||||
| 407 | cleaned = strdup(prefix); | |||
| 408 | if (!cleaned) | |||
| 409 | return -ENOMEM12; | |||
| 410 | ||||
| 411 | path_simplify(cleaned, false0); | |||
| 412 | ||||
| 413 | done = set_new(&path_hash_ops)internal_set_new(&path_hash_ops ); | |||
| 414 | if (!done) | |||
| 415 | return -ENOMEM12; | |||
| 416 | ||||
| 417 | for (;;) { | |||
| 418 | _cleanup_set_free_free___attribute__((cleanup(set_free_freep))) Set *todo = NULL((void*)0); | |||
| 419 | bool_Bool top_autofs = false0; | |||
| 420 | char *x; | |||
| 421 | unsigned long orig_flags; | |||
| 422 | ||||
| 423 | todo = set_new(&path_hash_ops)internal_set_new(&path_hash_ops ); | |||
| 424 | if (!todo) | |||
| 425 | return -ENOMEM12; | |||
| 426 | ||||
| 427 | rewind(proc_self_mountinfo); | |||
| 428 | ||||
| 429 | for (;;) { | |||
| 430 | _cleanup_free___attribute__((cleanup(freep))) char *path = NULL((void*)0), *p = NULL((void*)0), *type = NULL((void*)0); | |||
| 431 | int k; | |||
| 432 | ||||
| 433 | k = fscanf(proc_self_mountinfo, | |||
| 434 | "%*s " /* (1) mount id */ | |||
| 435 | "%*s " /* (2) parent id */ | |||
| 436 | "%*s " /* (3) major:minor */ | |||
| 437 | "%*s " /* (4) root */ | |||
| 438 | "%ms " /* (5) mount point */ | |||
| 439 | "%*s" /* (6) mount options (superblock) */ | |||
| 440 | "%*[^-]" /* (7) optional fields */ | |||
| 441 | "- " /* (8) separator */ | |||
| 442 | "%ms " /* (9) file system type */ | |||
| 443 | "%*s" /* (10) mount source */ | |||
| 444 | "%*s" /* (11) mount options (bind mount) */ | |||
| 445 | "%*[^\n]", /* some rubbish at the end */ | |||
| 446 | &path, | |||
| 447 | &type); | |||
| 448 | if (k != 2) { | |||
| 449 | if (k == EOF(-1)) | |||
| 450 | break; | |||
| 451 | ||||
| 452 | continue; | |||
| 453 | } | |||
| 454 | ||||
| 455 | r = cunescape(path, UNESCAPE_RELAX, &p); | |||
| 456 | if (r < 0) | |||
| 457 | return r; | |||
| 458 | ||||
| 459 | if (!path_startswith(p, cleaned)) | |||
| 460 | continue; | |||
| 461 | ||||
| 462 | /* Ignore this mount if it is blacklisted, but only if it isn't the top-level mount we shall | |||
| 463 | * operate on. */ | |||
| 464 | if (!path_equal(cleaned, p)) { | |||
| 465 | bool_Bool blacklisted = false0; | |||
| 466 | char **i; | |||
| 467 | ||||
| 468 | STRV_FOREACH(i, blacklist)for ((i) = (blacklist); (i) && *(i); (i)++) { | |||
| 469 | ||||
| 470 | if (path_equal(*i, cleaned)) | |||
| 471 | continue; | |||
| 472 | ||||
| 473 | if (!path_startswith(*i, cleaned)) | |||
| 474 | continue; | |||
| 475 | ||||
| 476 | if (path_startswith(p, *i)) { | |||
| 477 | blacklisted = true1; | |||
| 478 | log_debug("Not remounting %s, because blacklisted by %s, called for %s", p, *i, cleaned)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 478, __func__, "Not remounting %s, because blacklisted by %s, called for %s" , p, *i, cleaned) : -abs(_e); }); | |||
| 479 | break; | |||
| 480 | } | |||
| 481 | } | |||
| 482 | if (blacklisted) | |||
| 483 | continue; | |||
| 484 | } | |||
| 485 | ||||
| 486 | /* Let's ignore autofs mounts. If they aren't | |||
| 487 | * triggered yet, we want to avoid triggering | |||
| 488 | * them, as we don't make any guarantees for | |||
| 489 | * future submounts anyway. If they are | |||
| 490 | * already triggered, then we will find | |||
| 491 | * another entry for this. */ | |||
| 492 | if (streq(type, "autofs")(strcmp((type),("autofs")) == 0)) { | |||
| 493 | top_autofs = top_autofs || path_equal(cleaned, p); | |||
| 494 | continue; | |||
| 495 | } | |||
| 496 | ||||
| 497 | if (!set_contains(done, p)) { | |||
| 498 | r = set_consume(todo, p); | |||
| 499 | p = NULL((void*)0); | |||
| 500 | if (r == -EEXIST17) | |||
| 501 | continue; | |||
| 502 | if (r < 0) | |||
| 503 | return r; | |||
| 504 | } | |||
| 505 | } | |||
| 506 | ||||
| 507 | /* If we have no submounts to process anymore and if | |||
| 508 | * the root is either already done, or an autofs, we | |||
| 509 | * are done */ | |||
| 510 | if (set_isempty(todo) && | |||
| 511 | (top_autofs || set_contains(done, cleaned))) | |||
| 512 | return 0; | |||
| 513 | ||||
| 514 | if (!set_contains(done, cleaned) && | |||
| 515 | !set_contains(todo, cleaned)) { | |||
| 516 | /* The prefix directory itself is not yet a mount, make it one. */ | |||
| 517 | if (mount(cleaned, cleaned, NULL((void*)0), MS_BINDMS_BIND|MS_RECMS_REC, NULL((void*)0)) < 0) | |||
| 518 | return -errno(*__errno_location ()); | |||
| 519 | ||||
| 520 | orig_flags = 0; | |||
| 521 | (void) get_mount_flags(cleaned, &orig_flags); | |||
| 522 | orig_flags &= ~MS_RDONLYMS_RDONLY; | |||
| 523 | ||||
| 524 | if (mount(NULL((void*)0), prefix, NULL((void*)0), orig_flags|MS_BINDMS_BIND|MS_REMOUNTMS_REMOUNT|(ro ? MS_RDONLYMS_RDONLY : 0), NULL((void*)0)) < 0) | |||
| 525 | return -errno(*__errno_location ()); | |||
| 526 | ||||
| 527 | log_debug("Made top-level directory %s a mount point.", prefix)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 527, __func__, "Made top-level directory %s a mount point." , prefix) : -abs(_e); }); | |||
| 528 | ||||
| 529 | x = strdup(cleaned); | |||
| 530 | if (!x) | |||
| 531 | return -ENOMEM12; | |||
| 532 | ||||
| 533 | r = set_consume(done, x); | |||
| 534 | if (r < 0) | |||
| 535 | return r; | |||
| 536 | } | |||
| 537 | ||||
| 538 | while ((x = set_steal_first(todo))) { | |||
| 539 | ||||
| 540 | r = set_consume(done, x); | |||
| 541 | if (IN_SET(r, 0, -EEXIST)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){0, -17})/sizeof(int)]; switch(r) { case 0 : case -17: _found = 1; break; default: break; } _found; })) | |||
| 542 | continue; | |||
| 543 | if (r < 0) | |||
| 544 | return r; | |||
| 545 | ||||
| 546 | /* Deal with mount points that are obstructed by a later mount */ | |||
| 547 | r = path_is_mount_point(x, NULL((void*)0), 0); | |||
| 548 | if (IN_SET(r, 0, -ENOENT)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){0, -2})/sizeof(int)]; switch(r) { case 0 : case -2: _found = 1; break; default: break; } _found; })) | |||
| 549 | continue; | |||
| 550 | if (r < 0) | |||
| 551 | return r; | |||
| 552 | ||||
| 553 | /* Try to reuse the original flag set */ | |||
| 554 | orig_flags = 0; | |||
| 555 | (void) get_mount_flags(x, &orig_flags); | |||
| 556 | orig_flags &= ~MS_RDONLYMS_RDONLY; | |||
| 557 | ||||
| 558 | if (mount(NULL((void*)0), x, NULL((void*)0), orig_flags|MS_BINDMS_BIND|MS_REMOUNTMS_REMOUNT|(ro ? MS_RDONLYMS_RDONLY : 0), NULL((void*)0)) < 0) | |||
| 559 | return -errno(*__errno_location ()); | |||
| 560 | ||||
| 561 | log_debug("Remounted %s read-only.", x)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 561, __func__, "Remounted %s read-only." , x) : -abs(_e); }); | |||
| 562 | } | |||
| 563 | } | |||
| 564 | } | |||
| 565 | ||||
| 566 | int bind_remount_recursive(const char *prefix, bool_Bool ro, char **blacklist) { | |||
| 567 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *proc_self_mountinfo = NULL((void*)0); | |||
| 568 | ||||
| 569 | proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); | |||
| 570 | if (!proc_self_mountinfo) | |||
| 571 | return -errno(*__errno_location ()); | |||
| 572 | ||||
| 573 | (void) __fsetlocking(proc_self_mountinfo, FSETLOCKING_BYCALLERFSETLOCKING_BYCALLER); | |||
| 574 | ||||
| 575 | return bind_remount_recursive_with_mountinfo(prefix, ro, blacklist, proc_self_mountinfo); | |||
| 576 | } | |||
| 577 | ||||
| 578 | int mount_move_root(const char *path) { | |||
| 579 | assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("path"), "../src/basic/mount-util.c", 579 , __PRETTY_FUNCTION__); } while (0); | |||
| 580 | ||||
| 581 | if (chdir(path) < 0) | |||
| 582 | return -errno(*__errno_location ()); | |||
| 583 | ||||
| 584 | if (mount(path, "/", NULL((void*)0), MS_MOVEMS_MOVE, NULL((void*)0)) < 0) | |||
| 585 | return -errno(*__errno_location ()); | |||
| 586 | ||||
| 587 | if (chroot(".") < 0) | |||
| 588 | return -errno(*__errno_location ()); | |||
| 589 | ||||
| 590 | if (chdir("/") < 0) | |||
| 591 | return -errno(*__errno_location ()); | |||
| 592 | ||||
| 593 | return 0; | |||
| 594 | } | |||
| 595 | ||||
| 596 | bool_Bool fstype_is_network(const char *fstype) { | |||
| 597 | const char *x; | |||
| 598 | ||||
| 599 | x = startswith(fstype, "fuse."); | |||
| 600 | if (x) | |||
| 601 | fstype = x; | |||
| 602 | ||||
| 603 | return STR_IN_SET(fstype,(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 604 | "afs",(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 605 | "cifs",(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 606 | "smb3",(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 607 | "smbfs",(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 608 | "sshfs",(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 609 | "ncpfs",(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 610 | "ncp",(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 611 | "nfs",(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 612 | "nfs4",(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 613 | "gfs",(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 614 | "gfs2",(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 615 | "glusterfs",(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 616 | "pvfs2", /* OrangeFS */(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 617 | "ocfs2",(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))) | |||
| 618 | "lustre")(!!strv_find((((char**) ((const char*[]) { "afs", "cifs", "smb3" , "smbfs", "sshfs", "ncpfs", "ncp", "nfs", "nfs4", "gfs", "gfs2" , "glusterfs", "pvfs2", "ocfs2", "lustre", ((void*)0) }))), ( fstype))); | |||
| 619 | } | |||
| 620 | ||||
| 621 | bool_Bool fstype_is_api_vfs(const char *fstype) { | |||
| 622 | return STR_IN_SET(fstype,(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 623 | "autofs",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 624 | "bpf",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 625 | "cgroup",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 626 | "cgroup2",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 627 | "configfs",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 628 | "cpuset",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 629 | "debugfs",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 630 | "devpts",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 631 | "devtmpfs",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 632 | "efivarfs",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 633 | "fusectl",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 634 | "hugetlbfs",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 635 | "mqueue",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 636 | "proc",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 637 | "pstore",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 638 | "ramfs",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 639 | "securityfs",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 640 | "sysfs",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 641 | "tmpfs",(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))) | |||
| 642 | "tracefs")(!!strv_find((((char**) ((const char*[]) { "autofs", "bpf", "cgroup" , "cgroup2", "configfs", "cpuset", "debugfs", "devpts", "devtmpfs" , "efivarfs", "fusectl", "hugetlbfs", "mqueue", "proc", "pstore" , "ramfs", "securityfs", "sysfs", "tmpfs", "tracefs", ((void* )0) }))), (fstype))); | |||
| 643 | } | |||
| 644 | ||||
| 645 | bool_Bool fstype_is_ro(const char *fstype) { | |||
| 646 | /* All Linux file systems that are necessarily read-only */ | |||
| 647 | return STR_IN_SET(fstype,(!!strv_find((((char**) ((const char*[]) { "DM_verity_hash", "iso9660" , "squashfs", ((void*)0) }))), (fstype))) | |||
| 648 | "DM_verity_hash",(!!strv_find((((char**) ((const char*[]) { "DM_verity_hash", "iso9660" , "squashfs", ((void*)0) }))), (fstype))) | |||
| 649 | "iso9660",(!!strv_find((((char**) ((const char*[]) { "DM_verity_hash", "iso9660" , "squashfs", ((void*)0) }))), (fstype))) | |||
| 650 | "squashfs")(!!strv_find((((char**) ((const char*[]) { "DM_verity_hash", "iso9660" , "squashfs", ((void*)0) }))), (fstype))); | |||
| 651 | } | |||
| 652 | ||||
| 653 | bool_Bool fstype_can_discard(const char *fstype) { | |||
| 654 | return STR_IN_SET(fstype,(!!strv_find((((char**) ((const char*[]) { "btrfs", "ext4", "vfat" , "xfs", ((void*)0) }))), (fstype))) | |||
| 655 | "btrfs",(!!strv_find((((char**) ((const char*[]) { "btrfs", "ext4", "vfat" , "xfs", ((void*)0) }))), (fstype))) | |||
| 656 | "ext4",(!!strv_find((((char**) ((const char*[]) { "btrfs", "ext4", "vfat" , "xfs", ((void*)0) }))), (fstype))) | |||
| 657 | "vfat",(!!strv_find((((char**) ((const char*[]) { "btrfs", "ext4", "vfat" , "xfs", ((void*)0) }))), (fstype))) | |||
| 658 | "xfs")(!!strv_find((((char**) ((const char*[]) { "btrfs", "ext4", "vfat" , "xfs", ((void*)0) }))), (fstype))); | |||
| 659 | } | |||
| 660 | ||||
| 661 | bool_Bool fstype_can_uid_gid(const char *fstype) { | |||
| 662 | ||||
| 663 | /* All file systems that have a uid=/gid= mount option that fixates the owners of all files and directories, | |||
| 664 | * current and future. */ | |||
| 665 | ||||
| 666 | return STR_IN_SET(fstype,(!!strv_find((((char**) ((const char*[]) { "adfs", "fat", "hfs" , "hpfs", "iso9660", "msdos", "ntfs", "vfat", ((void*)0) }))) , (fstype))) | |||
| 667 | "adfs",(!!strv_find((((char**) ((const char*[]) { "adfs", "fat", "hfs" , "hpfs", "iso9660", "msdos", "ntfs", "vfat", ((void*)0) }))) , (fstype))) | |||
| 668 | "fat",(!!strv_find((((char**) ((const char*[]) { "adfs", "fat", "hfs" , "hpfs", "iso9660", "msdos", "ntfs", "vfat", ((void*)0) }))) , (fstype))) | |||
| 669 | "hfs",(!!strv_find((((char**) ((const char*[]) { "adfs", "fat", "hfs" , "hpfs", "iso9660", "msdos", "ntfs", "vfat", ((void*)0) }))) , (fstype))) | |||
| 670 | "hpfs",(!!strv_find((((char**) ((const char*[]) { "adfs", "fat", "hfs" , "hpfs", "iso9660", "msdos", "ntfs", "vfat", ((void*)0) }))) , (fstype))) | |||
| 671 | "iso9660",(!!strv_find((((char**) ((const char*[]) { "adfs", "fat", "hfs" , "hpfs", "iso9660", "msdos", "ntfs", "vfat", ((void*)0) }))) , (fstype))) | |||
| 672 | "msdos",(!!strv_find((((char**) ((const char*[]) { "adfs", "fat", "hfs" , "hpfs", "iso9660", "msdos", "ntfs", "vfat", ((void*)0) }))) , (fstype))) | |||
| 673 | "ntfs",(!!strv_find((((char**) ((const char*[]) { "adfs", "fat", "hfs" , "hpfs", "iso9660", "msdos", "ntfs", "vfat", ((void*)0) }))) , (fstype))) | |||
| 674 | "vfat")(!!strv_find((((char**) ((const char*[]) { "adfs", "fat", "hfs" , "hpfs", "iso9660", "msdos", "ntfs", "vfat", ((void*)0) }))) , (fstype))); | |||
| 675 | } | |||
| 676 | ||||
| 677 | int repeat_unmount(const char *path, int flags) { | |||
| 678 | bool_Bool done = false0; | |||
| 679 | ||||
| 680 | assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("path"), "../src/basic/mount-util.c", 680 , __PRETTY_FUNCTION__); } while (0); | |||
| 681 | ||||
| 682 | /* If there are multiple mounts on a mount point, this | |||
| 683 | * removes them all */ | |||
| 684 | ||||
| 685 | for (;;) { | |||
| 686 | if (umount2(path, flags) < 0) { | |||
| 687 | ||||
| 688 | if (errno(*__errno_location ()) == EINVAL22) | |||
| 689 | return done; | |||
| 690 | ||||
| 691 | return -errno(*__errno_location ()); | |||
| 692 | } | |||
| 693 | ||||
| 694 | done = true1; | |||
| 695 | } | |||
| 696 | } | |||
| 697 | ||||
| 698 | const char* mode_to_inaccessible_node(mode_t mode) { | |||
| 699 | /* This function maps a node type to a corresponding inaccessible file node. These nodes are created during | |||
| 700 | * early boot by PID 1. In some cases we lacked the privs to create the character and block devices (maybe | |||
| 701 | * because we run in an userns environment, or miss CAP_SYS_MKNOD, or run with a devices policy that excludes | |||
| 702 | * device nodes with major and minor of 0), but that's fine, in that case we use an AF_UNIX file node instead, | |||
| 703 | * which is not the same, but close enough for most uses. And most importantly, the kernel allows bind mounts | |||
| 704 | * from socket nodes to any non-directory file nodes, and that's the most important thing that matters. */ | |||
| 705 | ||||
| 706 | switch(mode & S_IFMT0170000) { | |||
| 707 | case S_IFREG0100000: | |||
| 708 | return "/run/systemd/inaccessible/reg"; | |||
| 709 | ||||
| 710 | case S_IFDIR0040000: | |||
| 711 | return "/run/systemd/inaccessible/dir"; | |||
| 712 | ||||
| 713 | case S_IFCHR0020000: | |||
| 714 | if (access("/run/systemd/inaccessible/chr", F_OK0) == 0) | |||
| 715 | return "/run/systemd/inaccessible/chr"; | |||
| 716 | return "/run/systemd/inaccessible/sock"; | |||
| 717 | ||||
| 718 | case S_IFBLK0060000: | |||
| 719 | if (access("/run/systemd/inaccessible/blk", F_OK0) == 0) | |||
| 720 | return "/run/systemd/inaccessible/blk"; | |||
| 721 | return "/run/systemd/inaccessible/sock"; | |||
| 722 | ||||
| 723 | case S_IFIFO0010000: | |||
| 724 | return "/run/systemd/inaccessible/fifo"; | |||
| 725 | ||||
| 726 | case S_IFSOCK0140000: | |||
| 727 | return "/run/systemd/inaccessible/sock"; | |||
| 728 | } | |||
| 729 | return NULL((void*)0); | |||
| 730 | } | |||
| 731 | ||||
| 732 | #define FLAG(name)(flags & name ? "name" "|" : "") (flags & name ? STRINGIFY(name)"name" "|" : "") | |||
| 733 | static char* mount_flags_to_string(long unsigned flags) { | |||
| 734 | char *x; | |||
| 735 | _cleanup_free___attribute__((cleanup(freep))) char *y = NULL((void*)0); | |||
| 736 | long unsigned overflow; | |||
| 737 | ||||
| 738 | overflow = flags & ~(MS_RDONLYMS_RDONLY | | |||
| 739 | MS_NOSUIDMS_NOSUID | | |||
| 740 | MS_NODEVMS_NODEV | | |||
| 741 | MS_NOEXECMS_NOEXEC | | |||
| 742 | MS_SYNCHRONOUSMS_SYNCHRONOUS | | |||
| 743 | MS_REMOUNTMS_REMOUNT | | |||
| 744 | MS_MANDLOCKMS_MANDLOCK | | |||
| 745 | MS_DIRSYNCMS_DIRSYNC | | |||
| 746 | MS_NOATIMEMS_NOATIME | | |||
| 747 | MS_NODIRATIMEMS_NODIRATIME | | |||
| 748 | MS_BINDMS_BIND | | |||
| 749 | MS_MOVEMS_MOVE | | |||
| 750 | MS_RECMS_REC | | |||
| 751 | MS_SILENTMS_SILENT | | |||
| 752 | MS_POSIXACLMS_POSIXACL | | |||
| 753 | MS_UNBINDABLEMS_UNBINDABLE | | |||
| 754 | MS_PRIVATEMS_PRIVATE | | |||
| 755 | MS_SLAVEMS_SLAVE | | |||
| 756 | MS_SHAREDMS_SHARED | | |||
| 757 | MS_RELATIMEMS_RELATIME | | |||
| 758 | MS_KERNMOUNTMS_KERNMOUNT | | |||
| 759 | MS_I_VERSIONMS_I_VERSION | | |||
| 760 | MS_STRICTATIMEMS_STRICTATIME | | |||
| 761 | MS_LAZYTIMEMS_LAZYTIME); | |||
| 762 | ||||
| 763 | if (flags == 0 || overflow != 0) | |||
| 764 | if (asprintf(&y, "%lx", overflow) < 0) | |||
| 765 | return NULL((void*)0); | |||
| 766 | ||||
| 767 | x = strjoin(FLAG(MS_RDONLY),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 768 | FLAG(MS_NOSUID),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 769 | FLAG(MS_NODEV),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 770 | FLAG(MS_NOEXEC),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 771 | FLAG(MS_SYNCHRONOUS),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 772 | FLAG(MS_REMOUNT),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 773 | FLAG(MS_MANDLOCK),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 774 | FLAG(MS_DIRSYNC),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 775 | FLAG(MS_NOATIME),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 776 | FLAG(MS_NODIRATIME),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 777 | FLAG(MS_BIND),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 778 | FLAG(MS_MOVE),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 779 | FLAG(MS_REC),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 780 | FLAG(MS_SILENT),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 781 | FLAG(MS_POSIXACL),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 782 | FLAG(MS_UNBINDABLE),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 783 | FLAG(MS_PRIVATE),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 784 | FLAG(MS_SLAVE),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 785 | FLAG(MS_SHARED),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 786 | FLAG(MS_RELATIME),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 787 | FLAG(MS_KERNMOUNT),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 788 | FLAG(MS_I_VERSION),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 789 | FLAG(MS_STRICTATIME),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 790 | FLAG(MS_LAZYTIME),strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)) | |||
| 791 | y)strjoin_real(((flags & MS_RDONLY ? "MS_RDONLY" "|" : "")) , (flags & MS_NOSUID ? "MS_NOSUID" "|" : ""), (flags & MS_NODEV ? "MS_NODEV" "|" : ""), (flags & MS_NOEXEC ? "MS_NOEXEC" "|" : ""), (flags & MS_SYNCHRONOUS ? "MS_SYNCHRONOUS" "|" : ""), (flags & MS_REMOUNT ? "MS_REMOUNT" "|" : ""), (flags & MS_MANDLOCK ? "MS_MANDLOCK" "|" : ""), (flags & MS_DIRSYNC ? "MS_DIRSYNC" "|" : ""), (flags & MS_NOATIME ? "MS_NOATIME" "|" : ""), (flags & MS_NODIRATIME ? "MS_NODIRATIME" "|" : ""), (flags & MS_BIND ? "MS_BIND" "|" : ""), (flags & MS_MOVE ? "MS_MOVE" "|" : ""), (flags & MS_REC ? "MS_REC" "|" : ""), (flags & MS_SILENT ? "MS_SILENT" "|" : ""), ( flags & MS_POSIXACL ? "MS_POSIXACL" "|" : ""), (flags & MS_UNBINDABLE ? "MS_UNBINDABLE" "|" : ""), (flags & MS_PRIVATE ? "MS_PRIVATE" "|" : ""), (flags & MS_SLAVE ? "MS_SLAVE" "|" : ""), (flags & MS_SHARED ? "MS_SHARED" "|" : ""), ( flags & MS_RELATIME ? "MS_RELATIME" "|" : ""), (flags & MS_KERNMOUNT ? "MS_KERNMOUNT" "|" : ""), (flags & MS_I_VERSION ? "MS_I_VERSION" "|" : ""), (flags & MS_STRICTATIME ? "MS_STRICTATIME" "|" : ""), (flags & MS_LAZYTIME ? "MS_LAZYTIME" "|" : "" ), y, ((void*)0)); | |||
| 792 | if (!x) | |||
| 793 | return NULL((void*)0); | |||
| 794 | if (!y) | |||
| 795 | x[strlen(x) - 1] = '\0'; /* truncate the last | */ | |||
| 796 | return x; | |||
| 797 | } | |||
| 798 | ||||
| 799 | int mount_verbose( | |||
| 800 | int error_log_level, | |||
| 801 | const char *what, | |||
| 802 | const char *where, | |||
| 803 | const char *type, | |||
| 804 | unsigned long flags, | |||
| 805 | const char *options) { | |||
| 806 | ||||
| 807 | _cleanup_free___attribute__((cleanup(freep))) char *fl = NULL((void*)0), *o = NULL((void*)0); | |||
| 808 | unsigned long f; | |||
| 809 | int r; | |||
| 810 | ||||
| 811 | r = mount_option_mangle(options, flags, &f, &o); | |||
| 812 | if (r < 0) | |||
| 813 | return log_full_errno(error_log_level, r,({ int _level = ((error_log_level)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 815, __func__, "Failed to mangle mount options %s: %m" , strempty(options)) : -abs(_e); }) | |||
| 814 | "Failed to mangle mount options %s: %m",({ int _level = ((error_log_level)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 815, __func__, "Failed to mangle mount options %s: %m" , strempty(options)) : -abs(_e); }) | |||
| 815 | strempty(options))({ int _level = ((error_log_level)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 815, __func__, "Failed to mangle mount options %s: %m" , strempty(options)) : -abs(_e); }); | |||
| 816 | ||||
| 817 | fl = mount_flags_to_string(f); | |||
| 818 | ||||
| 819 | if ((f & MS_REMOUNTMS_REMOUNT) && !what && !type) | |||
| 820 | log_debug("Remounting %s (%s \"%s\")...",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 821, __func__, "Remounting %s (%s \"%s\")..." , where, strnull(fl), strempty(o)) : -abs(_e); }) | |||
| 821 | where, strnull(fl), strempty(o))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 821, __func__, "Remounting %s (%s \"%s\")..." , where, strnull(fl), strempty(o)) : -abs(_e); }); | |||
| 822 | else if (!what && !type) | |||
| 823 | log_debug("Mounting %s (%s \"%s\")...",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 824, __func__, "Mounting %s (%s \"%s\")..." , where, strnull(fl), strempty(o)) : -abs(_e); }) | |||
| 824 | where, strnull(fl), strempty(o))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 824, __func__, "Mounting %s (%s \"%s\")..." , where, strnull(fl), strempty(o)) : -abs(_e); }); | |||
| 825 | else if ((f & MS_BINDMS_BIND) && !type) | |||
| 826 | log_debug("Bind-mounting %s on %s (%s \"%s\")...",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 827, __func__, "Bind-mounting %s on %s (%s \"%s\")..." , what, where, strnull(fl), strempty(o)) : -abs(_e); }) | |||
| 827 | what, where, strnull(fl), strempty(o))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 827, __func__, "Bind-mounting %s on %s (%s \"%s\")..." , what, where, strnull(fl), strempty(o)) : -abs(_e); }); | |||
| 828 | else if (f & MS_MOVEMS_MOVE) | |||
| 829 | log_debug("Moving mount %s → %s (%s \"%s\")...",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 830, __func__, "Moving mount %s → %s (%s \"%s\")..." , what, where, strnull(fl), strempty(o)) : -abs(_e); }) | |||
| 830 | what, where, strnull(fl), strempty(o))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 830, __func__, "Moving mount %s → %s (%s \"%s\")..." , what, where, strnull(fl), strempty(o)) : -abs(_e); }); | |||
| 831 | else | |||
| 832 | log_debug("Mounting %s on %s (%s \"%s\")...",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 833, __func__, "Mounting %s on %s (%s \"%s\")..." , strna(type), where, strnull(fl), strempty(o)) : -abs(_e); } ) | |||
| 833 | strna(type), where, strnull(fl), strempty(o))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 833, __func__, "Mounting %s on %s (%s \"%s\")..." , strna(type), where, strnull(fl), strempty(o)) : -abs(_e); } ); | |||
| 834 | if (mount(what, where, type, f, o) < 0) | |||
| 835 | return log_full_errno(error_log_level, errno,({ int _level = ((error_log_level)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/basic/mount-util.c" , 837, __func__, "Failed to mount %s on %s (%s \"%s\"): %m", strna (type), where, strnull(fl), strempty(o)) : -abs(_e); }) | |||
| 836 | "Failed to mount %s on %s (%s \"%s\"): %m",({ int _level = ((error_log_level)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/basic/mount-util.c" , 837, __func__, "Failed to mount %s on %s (%s \"%s\"): %m", strna (type), where, strnull(fl), strempty(o)) : -abs(_e); }) | |||
| 837 | strna(type), where, strnull(fl), strempty(o))({ int _level = ((error_log_level)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/basic/mount-util.c" , 837, __func__, "Failed to mount %s on %s (%s \"%s\"): %m", strna (type), where, strnull(fl), strempty(o)) : -abs(_e); }); | |||
| 838 | return 0; | |||
| 839 | } | |||
| 840 | ||||
| 841 | int umount_verbose(const char *what) { | |||
| 842 | log_debug("Umounting %s...", what)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/mount-util.c", 842, __func__, "Umounting %s..." , what) : -abs(_e); }); | |||
| 843 | if (umount(what) < 0) | |||
| 844 | return log_error_errno(errno, "Failed to unmount %s: %m", what)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/basic/mount-util.c", 844, __func__ , "Failed to unmount %s: %m", what) : -abs(_e); }); | |||
| 845 | return 0; | |||
| 846 | } | |||
| 847 | ||||
| 848 | const char *mount_propagation_flags_to_string(unsigned long flags) { | |||
| 849 | ||||
| 850 | switch (flags & (MS_SHAREDMS_SHARED|MS_SLAVEMS_SLAVE|MS_PRIVATEMS_PRIVATE)) { | |||
| 851 | case 0: | |||
| 852 | return ""; | |||
| 853 | case MS_SHAREDMS_SHARED: | |||
| 854 | return "shared"; | |||
| 855 | case MS_SLAVEMS_SLAVE: | |||
| 856 | return "slave"; | |||
| 857 | case MS_PRIVATEMS_PRIVATE: | |||
| 858 | return "private"; | |||
| 859 | } | |||
| 860 | ||||
| 861 | return NULL((void*)0); | |||
| 862 | } | |||
| 863 | ||||
| 864 | int mount_propagation_flags_from_string(const char *name, unsigned long *ret) { | |||
| 865 | ||||
| 866 | if (isempty(name)) | |||
| 867 | *ret = 0; | |||
| 868 | else if (streq(name, "shared")(strcmp((name),("shared")) == 0)) | |||
| 869 | *ret = MS_SHAREDMS_SHARED; | |||
| 870 | else if (streq(name, "slave")(strcmp((name),("slave")) == 0)) | |||
| 871 | *ret = MS_SLAVEMS_SLAVE; | |||
| 872 | else if (streq(name, "private")(strcmp((name),("private")) == 0)) | |||
| 873 | *ret = MS_PRIVATEMS_PRIVATE; | |||
| 874 | else | |||
| 875 | return -EINVAL22; | |||
| 876 | return 0; | |||
| 877 | } | |||
| 878 | ||||
| 879 | int mount_option_mangle( | |||
| 880 | const char *options, | |||
| 881 | unsigned long mount_flags, | |||
| 882 | unsigned long *ret_mount_flags, | |||
| 883 | char **ret_remaining_options) { | |||
| 884 | ||||
| 885 | const struct libmnt_optmap *map; | |||
| 886 | _cleanup_free___attribute__((cleanup(freep))) char *ret = NULL((void*)0); | |||
| 887 | const char *p; | |||
| 888 | int r; | |||
| 889 | ||||
| 890 | /* This extracts mount flags from the mount options, and store | |||
| 891 | * non-mount-flag options to '*ret_remaining_options'. | |||
| 892 | * E.g., | |||
| 893 | * "rw,nosuid,nodev,relatime,size=1630748k,mode=700,uid=1000,gid=1000" | |||
| 894 | * is split to MS_NOSUID|MS_NODEV|MS_RELATIME and | |||
| 895 | * "size=1630748k,mode=700,uid=1000,gid=1000". | |||
| 896 | * See more examples in test-mount-utils.c. | |||
| 897 | * | |||
| 898 | * Note that if 'options' does not contain any non-mount-flag options, | |||
| 899 | * then '*ret_remaining_options' is set to NULL instread of empty string. | |||
| 900 | * Note that this does not check validity of options stored in | |||
| 901 | * '*ret_remaining_options'. | |||
| 902 | * Note that if 'options' is NULL, then this just copies 'mount_flags' | |||
| 903 | * to '*ret_mount_flags'. */ | |||
| 904 | ||||
| 905 | assert(ret_mount_flags)do { if ((__builtin_expect(!!(!(ret_mount_flags)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret_mount_flags"), "../src/basic/mount-util.c" , 905, __PRETTY_FUNCTION__); } while (0); | |||
| 906 | assert(ret_remaining_options)do { if ((__builtin_expect(!!(!(ret_remaining_options)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret_remaining_options"), "../src/basic/mount-util.c" , 906, __PRETTY_FUNCTION__); } while (0); | |||
| 907 | ||||
| 908 | map = mnt_get_builtin_optmap(MNT_LINUX_MAP); | |||
| 909 | if (!map) | |||
| 910 | return -EINVAL22; | |||
| 911 | ||||
| 912 | p = options; | |||
| 913 | for (;;) { | |||
| 914 | _cleanup_free___attribute__((cleanup(freep))) char *word = NULL((void*)0); | |||
| 915 | const struct libmnt_optmap *ent; | |||
| 916 | ||||
| 917 | r = extract_first_word(&p, &word, ",", EXTRACT_QUOTES); | |||
| 918 | if (r < 0) | |||
| 919 | return r; | |||
| 920 | if (r == 0) | |||
| 921 | break; | |||
| 922 | ||||
| 923 | for (ent = map; ent->name; ent++) { | |||
| 924 | /* All entries in MNT_LINUX_MAP do not take any argument. | |||
| 925 | * Thus, ent->name does not contain "=" or "[=]". */ | |||
| 926 | if (!streq(word, ent->name)(strcmp((word),(ent->name)) == 0)) | |||
| 927 | continue; | |||
| 928 | ||||
| 929 | if (!(ent->mask & MNT_INVERT(1 << 1))) | |||
| 930 | mount_flags |= ent->id; | |||
| 931 | else if (mount_flags & ent->id) | |||
| 932 | mount_flags ^= ent->id; | |||
| 933 | ||||
| 934 | break; | |||
| 935 | } | |||
| 936 | ||||
| 937 | /* If 'word' is not a mount flag, then store it in '*ret_remaining_options'. */ | |||
| 938 | if (!ent->name && !strextend_with_separator(&ret, ",", word, NULL((void*)0))) | |||
| 939 | return -ENOMEM12; | |||
| 940 | } | |||
| 941 | ||||
| 942 | *ret_mount_flags = mount_flags; | |||
| 943 | *ret_remaining_options = TAKE_PTR(ret)({ typeof(ret) _ptr_ = (ret); (ret) = ((void*)0); _ptr_; }); | |||
| 944 | ||||
| 945 | return 0; | |||
| 946 | } |