Bug Summary

File:build-scan/../src/basic/mount-util.c
Warning:line 98, column 17
Value stored to 'h' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name mount-util.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/basic/libbasic.a.p -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -I /usr/include/blkid -I /usr/include/libmount -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility default -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/basic/mount-util.c
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
38int 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);
Value stored to 'h' is never read
99 }
100}
101
102static 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
140int 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
218fallback_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
240fallback_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 */
263int 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
297int 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
307int 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
377static 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. */
389int 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
566int 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
578int 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
596bool_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
621bool_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
645bool_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
653bool_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
661bool_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
677int 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
698const 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" "|" : "")
733static 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
799int 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
841int 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
848const 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
864int 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
879int 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}