File: | build-scan/../src/basic/mount-util.c |
Warning: | line 211, column 13 Access to field 'handle_bytes' results in a dereference of a null pointer (loaded from variable '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 | } |