projects/linux·blob master · refs

138 lines · 2.8 KiB

1/* SPDX-License-Identifier: GPL-2.0 */
2
3#ifndef __STATMOUNT_H
4#define __STATMOUNT_H
5
6#include <errno.h>
7#include <stdint.h>
8#include <stdlib.h>
9#include <linux/mount.h>
10#include <asm/unistd.h>
11
12#define STATMOUNT_BUFSIZE (1 << 15)
13
14#ifndef __NR_statmount
15 #if defined __alpha__
16 #define __NR_statmount 567
17 #elif defined _MIPS_SIM
18 #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */
19 #define __NR_statmount 4457
20 #endif
21 #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */
22 #define __NR_statmount 6457
23 #endif
24 #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */
25 #define __NR_statmount 5457
26 #endif
27 #else
28 #define __NR_statmount 457
29 #endif
30#endif
31
32#ifndef __NR_listmount
33 #if defined __alpha__
34 #define __NR_listmount 568
35 #elif defined _MIPS_SIM
36 #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */
37 #define __NR_listmount 4458
38 #endif
39 #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */
40 #define __NR_listmount 6458
41 #endif
42 #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */
43 #define __NR_listmount 5458
44 #endif
45 #else
46 #define __NR_listmount 458
47 #endif
48#endif
49
50static inline int statmount(uint64_t mnt_id, uint64_t mnt_ns_id, uint32_t fd,
51 uint64_t mask, struct statmount *buf, size_t bufsize,
52 unsigned int flags)
53{
54 struct mnt_id_req req = {
55 .size = MNT_ID_REQ_SIZE_VER0,
56 .param = mask,
57 };
58
59 if (flags & STATMOUNT_BY_FD) {
60 req.size = MNT_ID_REQ_SIZE_VER1;
61 req.mnt_fd = fd;
62 } else {
63 req.mnt_id = mnt_id;
64 if (mnt_ns_id) {
65 req.size = MNT_ID_REQ_SIZE_VER1;
66 req.mnt_ns_id = mnt_ns_id;
67 }
68 }
69
70 return syscall(__NR_statmount, &req, buf, bufsize, flags);
71}
72
73static inline ssize_t listmount(uint64_t mnt_id, uint64_t mnt_ns_id,
74 uint64_t last_mnt_id, uint64_t list[], size_t num,
75 unsigned int flags)
76{
77 struct mnt_id_req req = {
78 .size = MNT_ID_REQ_SIZE_VER0,
79 .mnt_id = mnt_id,
80 .param = last_mnt_id,
81 };
82
83 if (mnt_ns_id) {
84 req.size = MNT_ID_REQ_SIZE_VER1;
85 req.mnt_ns_id = mnt_ns_id;
86 }
87
88 return syscall(__NR_listmount, &req, list, num, flags);
89}
90
91static inline struct statmount *statmount_alloc(uint64_t mnt_id, uint64_t mnt_ns_id,
92 uint64_t mask, unsigned int flags)
93{
94 struct statmount *buf;
95 size_t bufsize = STATMOUNT_BUFSIZE;
96 int ret;
97
98 for (;;) {
99 buf = malloc(bufsize);
100 if (!buf)
101 return NULL;
102
103 ret = statmount(mnt_id, mnt_ns_id, 0, mask, buf, bufsize, flags);
104 if (ret == 0)
105 return buf;
106
107 free(buf);
108 if (errno != EOVERFLOW)
109 return NULL;
110
111 bufsize <<= 1;
112 }
113}
114
115static inline struct statmount *statmount_alloc_by_fd(int fd, uint64_t mask)
116{
117 struct statmount *buf;
118 size_t bufsize = STATMOUNT_BUFSIZE;
119 int ret;
120
121 for (;;) {
122 buf = malloc(bufsize);
123 if (!buf)
124 return NULL;
125
126 ret = statmount(0, 0, fd, mask, buf, bufsize, STATMOUNT_BY_FD);
127 if (ret == 0)
128 return buf;
129
130 free(buf);
131 if (errno != EOVERFLOW)
132 return NULL;
133
134 bufsize <<= 1;
135 }
136}
137
138#endif /* __STATMOUNT_H */