]> git.ipfire.org Git - thirdparty/util-linux.git/blame_incremental - include/mount-api-utils.h
taskset: Accept 0 pid for current process
[thirdparty/util-linux.git] / include / mount-api-utils.h
... / ...
CommitLineData
1/*
2 * No copyright is claimed. This code is in the public domain; do with
3 * it what you wish.
4 */
5#ifndef UTIL_LINUX_MOUNT_API_UTILS
6#define UTIL_LINUX_MOUNT_API_UTILS
7
8#ifdef HAVE_LINUX_MOUNT_H
9#include <sys/mount.h>
10#include <linux/mount.h>
11#include <linux/unistd.h>
12#include <sys/syscall.h>
13#include <inttypes.h>
14
15/*
16 * File descritors based mount API
17 */
18#ifdef HAVE_MOUNTFD_API
19
20/* Accepted by both open_tree() and mount_setattr(). */
21#ifndef AT_RECURSIVE
22# define AT_RECURSIVE 0x8000
23#endif
24
25#ifndef OPEN_TREE_CLONE
26# define OPEN_TREE_CLONE 1
27#endif
28
29#ifndef OPEN_TREE_CLOEXEC
30# define OPEN_TREE_CLOEXEC O_CLOEXEC
31#endif
32
33#if !defined(HAVE_OPEN_TREE) && defined(SYS_open_tree)
34static inline int open_tree(int dfd, const char *filename, unsigned int flags)
35{
36 return syscall(SYS_open_tree, dfd, filename, flags);
37}
38#endif
39
40#ifndef MOVE_MOUNT_F_SYMLINKS
41# define MOVE_MOUNT_F_SYMLINKS 0x00000001 /* Follow symlinks on from path */
42#endif
43
44#ifndef MOVE_MOUNT_F_AUTOMOUNTS
45# define MOVE_MOUNT_F_AUTOMOUNTS 0x00000002 /* Follow automounts on from path */
46#endif
47
48#ifndef MOVE_MOUNT_F_EMPTY_PATH
49# define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */
50#endif
51
52#ifndef MOVE_MOUNT_T_SYMLINKS
53# define MOVE_MOUNT_T_SYMLINKS 0x00000010 /* Follow symlinks on to path */
54#endif
55
56#ifndef MOVE_MOUNT_T_AUTOMOUNTS
57# define MOVE_MOUNT_T_AUTOMOUNTS 0x00000020 /* Follow automounts on to path */
58#endif
59
60#ifndef MOVE_MOUNT_T_EMPTY_PATH
61# define MOVE_MOUNT_T_EMPTY_PATH 0x00000040 /* Empty to path permitted */
62#endif
63
64#ifndef MOVE_MOUNT_SET_GROUP
65# define MOVE_MOUNT_SET_GROUP 0x00000100 /* Set sharing group instead */
66#endif
67
68#ifndef MOVE_MOUNT__MASK
69# define MOVE_MOUNT__MASK 0x00000077
70#endif
71
72#if !defined(HAVE_MOVE_MOUNT) && defined(SYS_move_mount)
73static inline int move_mount(int from_dfd, const char *from_pathname, int to_dfd,
74 const char *to_pathname, unsigned int flags)
75{
76 return syscall(SYS_move_mount, from_dfd, from_pathname, to_dfd,
77 to_pathname, flags);
78}
79#endif
80
81#ifndef MOUNT_ATTR_RDONLY
82# define MOUNT_ATTR_RDONLY 0x00000001
83#endif
84
85#ifndef MOUNT_ATTR_NOSUID
86# define MOUNT_ATTR_NOSUID 0x00000002
87#endif
88
89#ifndef MOUNT_ATTR_NODEV
90# define MOUNT_ATTR_NODEV 0x00000004
91#endif
92
93#ifndef MOUNT_ATTR_NOEXEC
94# define MOUNT_ATTR_NOEXEC 0x00000008
95#endif
96
97#ifndef MOUNT_ATTR__ATIME
98# define MOUNT_ATTR__ATIME 0x00000070
99#endif
100
101#ifndef MOUNT_ATTR_RELATIME
102# define MOUNT_ATTR_RELATIME 0x00000000
103#endif
104
105#ifndef MOUNT_ATTR_NOATIME
106# define MOUNT_ATTR_NOATIME 0x00000010
107#endif
108
109#ifndef MOUNT_ATTR_STRICTATIME
110# define MOUNT_ATTR_STRICTATIME 0x00000020
111#endif
112
113#ifndef MOUNT_ATTR_NODIRATIME
114# define MOUNT_ATTR_NODIRATIME 0x00000080
115#endif
116
117#ifndef MOUNT_ATTR_IDMAP
118# define MOUNT_ATTR_IDMAP 0x00100000
119#endif
120
121#ifndef MOUNT_ATTR_NOSYMFOLLOW
122# define MOUNT_ATTR_NOSYMFOLLOW 0x00200000
123#endif
124
125#ifndef HAVE_STRUCT_MOUNT_ATTR
126# ifndef MOUNT_ATTR_SIZE_VER0 /* For case mount.h comes from a place invisible for autotools/meson */
127# include <inttypes.h>
128struct mount_attr {
129 uint64_t attr_set;
130 uint64_t attr_clr;
131 uint64_t propagation;
132 uint64_t userns_fd;
133};
134# endif
135#endif
136
137#if !defined(HAVE_MOUNT_SETATTR) && defined(SYS_mount_setattr)
138static inline int mount_setattr(int dfd, const char *path, unsigned int flags,
139 struct mount_attr *attr, size_t size)
140{
141 return syscall(SYS_mount_setattr, dfd, path, flags, attr, size);
142}
143#endif
144
145#ifndef HAVE_ENUM_FSCONFIG_COMMAND
146# ifndef FSOPEN_CLOEXEC /* For case mount.h comes from a place invisible for autotools/meson */
147enum fsconfig_command {
148 FSCONFIG_SET_FLAG = 0, /* Set parameter, supplying no value */
149 FSCONFIG_SET_STRING = 1, /* Set parameter, supplying a string value */
150 FSCONFIG_SET_BINARY = 2, /* Set parameter, supplying a binary blob value */
151 FSCONFIG_SET_PATH = 3, /* Set parameter, supplying an object by path */
152 FSCONFIG_SET_PATH_EMPTY = 4, /* Set parameter, supplying an object by (empty) path */
153 FSCONFIG_SET_FD = 5, /* Set parameter, supplying an object by fd */
154 FSCONFIG_CMD_CREATE = 6, /* Invoke superblock creation */
155 FSCONFIG_CMD_RECONFIGURE = 7, /* Invoke superblock reconfiguration */
156};
157# endif
158#endif
159
160#if !defined(HAVE_FSCONFIG) && defined(SYS_fsconfig)
161static inline int fsconfig(int fd, unsigned int cmd, const char *key,
162 const void *value, int aux)
163{
164 return syscall(SYS_fsconfig, fd, cmd, key, value, aux);
165}
166#endif
167
168#ifndef FSOPEN_CLOEXEC
169# define FSOPEN_CLOEXEC 0x00000001
170#endif
171
172#if !defined(HAVE_FSOPEN) && defined(SYS_fsopen)
173static inline int fsopen(const char *fsname, unsigned int flags)
174{
175 return syscall(SYS_fsopen, fsname, flags);
176}
177#endif
178
179#ifndef FSMOUNT_CLOEXEC
180# define FSMOUNT_CLOEXEC 0x00000001
181#endif
182
183#if !defined(HAVE_FSMOUNT) && defined(SYS_fsmount)
184static inline int fsmount(int fd, unsigned int flags, unsigned int mount_attrs)
185{
186 return syscall(SYS_fsmount, fd, flags, mount_attrs);
187}
188#endif
189
190#ifndef FSPICK_CLOEXEC
191# define FSPICK_CLOEXEC 0x00000001
192#endif
193
194#ifndef FSPICK_SYMLINK_NOFOLLOW
195# define FSPICK_SYMLINK_NOFOLLOW 0x00000002
196#endif
197
198#ifndef FSPICK_NO_AUTOMOUNT
199# define FSPICK_NO_AUTOMOUNT 0x00000004
200#endif
201
202#ifdef FSPICK_EMPTY_PATH
203# define FSPICK_EMPTY_PATH 0x00000008
204#endif
205
206#if !defined(HAVE_FSPICK) && defined(SYS_fspick)
207static inline int fspick(int dfd, const char *pathname, unsigned int flags)
208{
209 return syscall(SYS_fspick, dfd, pathname, flags);
210}
211#endif
212
213#endif /* HAVE_MOUNTFD_API */
214
215/*
216 * statmount() and listmount()
217 */
218#ifdef HAVE_STATMOUNT_API
219
220#ifndef MNT_ID_REQ_SIZE_VER0
221# define MNT_ID_REQ_SIZE_VER0 24 /* sizeof first published struct */
222#endif
223#ifndef MNT_ID_REQ_SIZE_VER1
224# define MNT_ID_REQ_SIZE_VER1 32 /* sizeof second published struct */
225#endif
226
227/*
228 * The structs mnt_id_req and statmount may differ between kernel versions, so
229 * we must ensure that the structs contain everything we need. For now (during
230 * development), it seems best to define local copies of the structs to avoid
231 * relying on installed kernel headers and to avoid a storm of #ifdefs.
232 */
233
234/*
235 * listmount() and statmount() request
236 */
237struct ul_mnt_id_req {
238 uint32_t size;
239 uint32_t spare;
240 uint64_t mnt_id;
241 uint64_t param;
242 uint64_t mnt_ns_id;
243};
244
245/*
246 * Please note that due to the variable length of the statmount buffer, the
247 * struct cannot be versioned by size (like struct mnt_id_req).
248 */
249struct ul_statmount {
250 uint32_t size; /* Total size, including strings */
251 uint32_t mnt_opts; /* [str] Mount options of the mount */
252 uint64_t mask; /* What results were written */
253 uint32_t sb_dev_major; /* Device ID */
254 uint32_t sb_dev_minor;
255 uint64_t sb_magic; /* ..._SUPER_MAGIC */
256 uint32_t sb_flags; /* SB_{RDONLY,SYNCHRONOUS,DIRSYNC,LAZYTIME} */
257 uint32_t fs_type; /* [str] Filesystem type */
258 uint64_t mnt_id; /* Unique ID of mount */
259 uint64_t mnt_parent_id; /* Unique ID of parent (for root == mnt_id) */
260 uint32_t mnt_id_old; /* Reused IDs used in proc/.../mountinfo */
261 uint32_t mnt_parent_id_old;
262 uint64_t mnt_attr; /* MOUNT_ATTR_... */
263 uint64_t mnt_propagation; /* MS_{SHARED,SLAVE,PRIVATE,UNBINDABLE} */
264 uint64_t mnt_peer_group; /* ID of shared peer group */
265 uint64_t mnt_master; /* Mount receives propagation from this ID */
266 uint64_t propagate_from; /* Propagation from in current namespace */
267 uint32_t mnt_root; /* [str] Root of mount relative to root of fs */
268 uint32_t mnt_point; /* [str] Mountpoint relative to current root */
269 uint64_t mnt_ns_id; /* ID of the mount namespace */
270 uint32_t fs_subtype; /* [str] Subtype of fs_type (if any) */
271 uint32_t sb_source; /* [str] Source string of the mount */
272 uint32_t opt_num; /* Number of fs options */
273 uint32_t opt_array; /* [str] Array of nul terminated fs options */
274 uint32_t opt_sec_num; /* Number of security options */
275 uint32_t opt_sec_array; /* [str] Array of nul terminated security options */
276 uint64_t __spare2[46];
277 char str[]; /* Variable size part containing strings */
278};
279
280/* sb_flags (defined in kernel include/linux/fs.h) */
281#ifndef SB_RDONLY
282# define SB_RDONLY BIT(0) /* Mount read-only */
283# define SB_NOSUID BIT(1) /* Ignore suid and sgid bits */
284# define SB_NODEV BIT(2) /* Disallow access to device special files */
285# define SB_NOEXEC BIT(3) /* Disallow program execution */
286# define SB_SYNCHRONOUS BIT(4) /* Writes are synced at once */
287# define SB_MANDLOCK BIT(6) /* Allow mandatory locks on an FS */
288# define SB_DIRSYNC BIT(7) /* Directory modifications are synchronous */
289# define SB_NOATIME BIT(10) /* Do not update access times. */
290# define SB_NODIRATIME BIT(11) /* Do not update directory access times */
291# define SB_SILENT BIT(15)
292# define SB_POSIXACL BIT(16) /* Supports POSIX ACLs */
293# define SB_INLINECRYPT BIT(17) /* Use blk-crypto for encrypted files */
294# define SB_KERNMOUNT BIT(22) /* this is a kern_mount call */
295# define SB_I_VERSION BIT(23) /* Update inode I_version field */
296# define SB_LAZYTIME BIT(25) /* Update the on-disk [acm]times lazily */
297#endif
298
299/*
300 * @mask bits for statmount(2)
301 */
302#ifndef STATMOUNT_SB_BASIC
303# define STATMOUNT_SB_BASIC 0x00000001U /* Want/got sb_... */
304#endif
305#ifndef STATMOUNT_MNT_BASIC
306# define STATMOUNT_MNT_BASIC 0x00000002U /* Want/got mnt_... */
307#endif
308#ifndef STATMOUNT_PROPAGATE_FROM
309# define STATMOUNT_PROPAGATE_FROM 0x00000004U /* Want/got propagate_from */
310#endif
311#ifndef STATMOUNT_MNT_ROOT
312# define STATMOUNT_MNT_ROOT 0x00000008U /* Want/got mnt_root */
313#endif
314#ifndef STATMOUNT_MNT_POINT
315# define STATMOUNT_MNT_POINT 0x00000010U /* Want/got mnt_point */
316#endif
317#ifndef STATMOUNT_FS_TYPE
318# define STATMOUNT_FS_TYPE 0x00000020U /* Want/got fs_type */
319#endif
320#ifndef STATMOUNT_MNT_NS_ID
321# define STATMOUNT_MNT_NS_ID 0x00000040U /* Want/got mnt_ns_id */
322#endif
323#ifndef STATMOUNT_MNT_OPTS
324# define STATMOUNT_MNT_OPTS 0x00000080U /* Want/got mnt_opts */
325#endif
326#ifndef STATMOUNT_FS_SUBTYPE
327# define STATMOUNT_FS_SUBTYPE 0x00000100U /* Want/got fs_subtype */
328#endif
329#ifndef STATMOUNT_SB_SOURCE
330# define STATMOUNT_SB_SOURCE 0x00000200U /* Want/got sb_source */
331#endif
332#ifndef STATMOUNT_OPT_ARRAY
333# define STATMOUNT_OPT_ARRAY 0x00000400U /* Want/got opt_... */
334#endif
335#ifndef STATMOUNT_OPT_SEC_ARRAY
336# define STATMOUNT_OPT_SEC_ARRAY 0x00000800U /* Want/got opt_sec... */
337#endif
338
339
340/*
341 * Special @mnt_id values that can be passed to listmount
342 */
343#ifdef LSMT_ROOT
344# define LSMT_ROOT 0xffffffffffffffff /* root mount */
345#endif
346
347#ifndef LISTMOUNT_REVERSE
348# define LISTMOUNT_REVERSE BIT(0) /* List later mounts first */
349#endif
350
351/* Don't use this "raw" version. See ul_statmount() below. */
352#if defined(SYS_statmount)
353static inline int ul_statmount_syscall(uint64_t mnt_id,
354 uint64_t ns_id,
355 uint64_t mask,
356 struct ul_statmount *buf,
357 size_t bufsize, unsigned int flags)
358{
359 struct ul_mnt_id_req req = {
360 .size = MNT_ID_REQ_SIZE_VER1,
361 .mnt_id = mnt_id,
362 .param = mask,
363 .mnt_ns_id = ns_id
364 };
365
366 return syscall(SYS_statmount, &req, buf, bufsize, flags);
367}
368
369static inline int has_statmount(void)
370{
371 errno = 0;
372
373 if (ul_statmount_syscall(0, 0, 0, NULL, 0, 0) < 0 && errno == ENOSYS)
374 return 0;
375 return 1;
376}
377
378/* This is a version of statmount() that reallocates @buf to be large enough to
379 * store data for the requested @id. This function never deallocates; it is the
380 * caller's responsibility.
381 */
382static inline int ul_statmount(uint64_t id,
383 uint64_t ns_id,
384 uint64_t mask,
385 struct ul_statmount **buf,
386 size_t *bufsiz,
387 unsigned int flags)
388{
389 size_t sz;
390 int rc = 0;
391
392 if (!buf || !bufsiz)
393 return -EINVAL;
394
395 sz = *bufsiz;
396 if (!sz)
397 sz = 32 * 1024;
398
399 do {
400 if (sz > *bufsiz) {
401 struct ul_statmount *tmp = realloc(*buf, sz);
402 if (!tmp)
403 return -ENOMEM;
404 *buf = tmp;
405 *bufsiz = sz;
406 }
407
408 errno = 0;
409 rc = ul_statmount_syscall(id, ns_id, mask, *buf, *bufsiz, flags);
410 if (!rc)
411 break;
412 if (errno != EOVERFLOW)
413 break;
414 if (sz >= SIZE_MAX / 2)
415 break;
416 sz <<= 1;
417 } while (rc);
418
419 return rc;
420}
421#endif /* SYS_statmount */
422
423
424#if defined(SYS_listmount)
425static inline ssize_t ul_listmount(uint64_t mnt_id,
426 uint64_t ns_id,
427 uint64_t last_mnt_id,
428 uint64_t list[], size_t num,
429 unsigned int flags)
430{
431 struct ul_mnt_id_req req = {
432 .size = MNT_ID_REQ_SIZE_VER1,
433 .mnt_id = mnt_id,
434 .param = last_mnt_id,
435 .mnt_ns_id = ns_id
436 };
437
438 return syscall(SYS_listmount, &req, list, num, flags);
439}
440
441static inline int has_listmount(void)
442{
443 uint64_t dummy;
444
445 errno = 0;
446
447 if (ul_listmount(LSMT_ROOT, 0, 0, &dummy, 1, LISTMOUNT_REVERSE) != 1)
448 return 0;
449 return 1;
450}
451#endif
452
453#endif /* HAVE_STATMOUNT_API */
454
455#endif /* HAVE_LINUX_MOUNT_H */
456
457#endif /* UTIL_LINUX_MOUNT_API_UTILS */