]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2f368e4a ZJS |
2 | #pragma once |
3 | ||
2f368e4a ZJS |
4 | /* Missing glibc definitions to access certain kernel APIs */ |
5 | ||
e2d94d0c | 6 | #include <errno.h> |
36dd5ffd | 7 | #include <fcntl.h> |
420297c9 LP |
8 | #if HAVE_LINUX_TIME_TYPES_H |
9 | /* This header defines __kernel_timespec for us, but is only available since Linux 5.1, hence conditionally | |
10 | * include this. */ | |
11 | #include <linux/time_types.h> | |
12 | #endif | |
5f152f43 | 13 | #include <signal.h> |
36dd5ffd | 14 | #include <sys/syscall.h> |
71e5200f | 15 | #include <sys/types.h> |
5f152f43 | 16 | #include <sys/wait.h> |
851d66fa YW |
17 | #include <unistd.h> |
18 | ||
19 | #ifdef ARCH_MIPS | |
20 | #include <asm/sgidefs.h> | |
21 | #endif | |
71e5200f | 22 | |
4768cc45 | 23 | #include "macro.h" |
d7276b61 | 24 | #include "missing_keyctl.h" |
e01819f8 | 25 | #include "missing_stat.h" |
35b42e56 | 26 | #include "missing_syscall_def.h" |
d7276b61 | 27 | |
851d66fa YW |
28 | /* linux/kcmp.h */ |
29 | #ifndef KCMP_FILE /* 3f4994cfc15f38a3159c6e3a4b3ab2e1481a6b02 (3.19) */ | |
30 | #define KCMP_FILE 0 | |
31 | #endif | |
32 | ||
35b42e56 ZJS |
33 | /* ======================================================================= */ |
34 | ||
4b9545f1 | 35 | #if !HAVE_PIVOT_ROOT |
5187dd2c | 36 | static inline int missing_pivot_root(const char *new_root, const char *put_old) { |
d06f3829 | 37 | return syscall(__NR_pivot_root, new_root, put_old); |
2f368e4a | 38 | } |
5187dd2c ZJS |
39 | |
40 | # define pivot_root missing_pivot_root | |
2f368e4a ZJS |
41 | #endif |
42 | ||
43 | /* ======================================================================= */ | |
44 | ||
51fe206f ZJS |
45 | #if !HAVE_IOPRIO_GET |
46 | static inline int missing_ioprio_get(int which, int who) { | |
47 | return syscall(__NR_ioprio_get, which, who); | |
48 | } | |
49 | ||
50 | # define ioprio_get missing_ioprio_get | |
51 | #endif | |
52 | ||
53 | /* ======================================================================= */ | |
54 | ||
55 | #if !HAVE_IOPRIO_SET | |
56 | static inline int missing_ioprio_set(int which, int who, int ioprio) { | |
57 | return syscall(__NR_ioprio_set, which, who, ioprio); | |
58 | } | |
59 | ||
60 | # define ioprio_set missing_ioprio_set | |
61 | #endif | |
62 | ||
63 | /* ======================================================================= */ | |
64 | ||
5134e18e | 65 | #if !HAVE_MEMFD_CREATE |
5187dd2c | 66 | static inline int missing_memfd_create(const char *name, unsigned int flags) { |
2f368e4a ZJS |
67 | # ifdef __NR_memfd_create |
68 | return syscall(__NR_memfd_create, name, flags); | |
69 | # else | |
70 | errno = ENOSYS; | |
71 | return -1; | |
72 | # endif | |
73 | } | |
5187dd2c ZJS |
74 | |
75 | # define memfd_create missing_memfd_create | |
2f368e4a ZJS |
76 | #endif |
77 | ||
78 | /* ======================================================================= */ | |
79 | ||
5134e18e | 80 | #if !HAVE_GETRANDOM |
289b41aa MG |
81 | /* glibc says getrandom() returns ssize_t */ |
82 | static inline ssize_t missing_getrandom(void *buffer, size_t count, unsigned flags) { | |
2f368e4a ZJS |
83 | # ifdef __NR_getrandom |
84 | return syscall(__NR_getrandom, buffer, count, flags); | |
85 | # else | |
86 | errno = ENOSYS; | |
87 | return -1; | |
88 | # endif | |
89 | } | |
5187dd2c ZJS |
90 | |
91 | # define getrandom missing_getrandom | |
2f368e4a ZJS |
92 | #endif |
93 | ||
94 | /* ======================================================================= */ | |
95 | ||
5134e18e | 96 | /* The syscall has been defined since forever, but the glibc wrapper was missing. */ |
4b9545f1 | 97 | #if !HAVE_GETTID |
5187dd2c | 98 | static inline pid_t missing_gettid(void) { |
5134e18e | 99 | # if defined __NR_gettid && __NR_gettid >= 0 |
d06f3829 | 100 | return (pid_t) syscall(__NR_gettid); |
5134e18e ZJS |
101 | # else |
102 | # error "__NR_gettid not defined" | |
103 | # endif | |
2f368e4a | 104 | } |
5187dd2c ZJS |
105 | |
106 | # define gettid missing_gettid | |
2f368e4a ZJS |
107 | #endif |
108 | ||
109 | /* ======================================================================= */ | |
110 | ||
5134e18e | 111 | #if !HAVE_NAME_TO_HANDLE_AT |
2f368e4a ZJS |
112 | struct file_handle { |
113 | unsigned int handle_bytes; | |
114 | int handle_type; | |
115 | unsigned char f_handle[0]; | |
116 | }; | |
117 | ||
5187dd2c | 118 | static inline int missing_name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) { |
2f368e4a ZJS |
119 | # ifdef __NR_name_to_handle_at |
120 | return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags); | |
121 | # else | |
122 | errno = ENOSYS; | |
123 | return -1; | |
124 | # endif | |
125 | } | |
5187dd2c ZJS |
126 | |
127 | # define name_to_handle_at missing_name_to_handle_at | |
2f368e4a ZJS |
128 | #endif |
129 | ||
130 | /* ======================================================================= */ | |
131 | ||
5134e18e | 132 | #if !HAVE_SETNS |
5187dd2c | 133 | static inline int missing_setns(int fd, int nstype) { |
2f368e4a ZJS |
134 | # ifdef __NR_setns |
135 | return syscall(__NR_setns, fd, nstype); | |
136 | # else | |
137 | errno = ENOSYS; | |
138 | return -1; | |
139 | # endif | |
140 | } | |
5187dd2c ZJS |
141 | |
142 | # define setns missing_setns | |
2f368e4a ZJS |
143 | #endif |
144 | ||
145 | /* ======================================================================= */ | |
146 | ||
2f368e4a ZJS |
147 | static inline pid_t raw_getpid(void) { |
148 | #if defined(__alpha__) | |
149 | return (pid_t) syscall(__NR_getxpid); | |
150 | #else | |
151 | return (pid_t) syscall(__NR_getpid); | |
152 | #endif | |
153 | } | |
154 | ||
155 | /* ======================================================================= */ | |
156 | ||
5134e18e | 157 | #if !HAVE_RENAMEAT2 |
5187dd2c | 158 | static inline int missing_renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) { |
2f368e4a ZJS |
159 | # ifdef __NR_renameat2 |
160 | return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags); | |
161 | # else | |
162 | errno = ENOSYS; | |
163 | return -1; | |
164 | # endif | |
165 | } | |
5187dd2c ZJS |
166 | |
167 | # define renameat2 missing_renameat2 | |
2f368e4a ZJS |
168 | #endif |
169 | ||
170 | /* ======================================================================= */ | |
171 | ||
4b9545f1 | 172 | #if !HAVE_KCMP |
5187dd2c | 173 | static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) { |
fb4b0465 | 174 | # if defined __NR_kcmp && __NR_kcmp >= 0 |
2f368e4a ZJS |
175 | return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); |
176 | # else | |
177 | errno = ENOSYS; | |
178 | return -1; | |
179 | # endif | |
180 | } | |
5187dd2c ZJS |
181 | |
182 | # define kcmp missing_kcmp | |
2f368e4a ZJS |
183 | #endif |
184 | ||
185 | /* ======================================================================= */ | |
186 | ||
4b9545f1 | 187 | #if !HAVE_KEYCTL |
851d66fa | 188 | static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { |
fb4b0465 | 189 | # if defined __NR_keyctl && __NR_keyctl >= 0 |
2f368e4a ZJS |
190 | return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5); |
191 | # else | |
192 | errno = ENOSYS; | |
193 | return -1; | |
194 | # endif | |
5187dd2c ZJS |
195 | |
196 | # define keyctl missing_keyctl | |
2f368e4a ZJS |
197 | } |
198 | ||
5187dd2c | 199 | static inline key_serial_t missing_add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) { |
fb4b0465 | 200 | # if defined __NR_add_key && __NR_add_key >= 0 |
2f368e4a ZJS |
201 | return syscall(__NR_add_key, type, description, payload, plen, ringid); |
202 | # else | |
203 | errno = ENOSYS; | |
204 | return -1; | |
205 | # endif | |
5187dd2c ZJS |
206 | |
207 | # define add_key missing_add_key | |
2f368e4a ZJS |
208 | } |
209 | ||
5187dd2c | 210 | static inline key_serial_t missing_request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) { |
fb4b0465 | 211 | # if defined __NR_request_key && __NR_request_key >= 0 |
2f368e4a ZJS |
212 | return syscall(__NR_request_key, type, description, callout_info, destringid); |
213 | # else | |
214 | errno = ENOSYS; | |
215 | return -1; | |
216 | # endif | |
5187dd2c ZJS |
217 | |
218 | # define request_key missing_request_key | |
2f368e4a ZJS |
219 | } |
220 | #endif | |
221 | ||
222 | /* ======================================================================= */ | |
223 | ||
5134e18e | 224 | #if !HAVE_COPY_FILE_RANGE |
5187dd2c ZJS |
225 | static inline ssize_t missing_copy_file_range(int fd_in, loff_t *off_in, |
226 | int fd_out, loff_t *off_out, | |
227 | size_t len, | |
228 | unsigned int flags) { | |
2f368e4a ZJS |
229 | # ifdef __NR_copy_file_range |
230 | return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags); | |
231 | # else | |
232 | errno = ENOSYS; | |
233 | return -1; | |
234 | # endif | |
235 | } | |
5187dd2c ZJS |
236 | |
237 | # define copy_file_range missing_copy_file_range | |
2f368e4a | 238 | #endif |
71e5200f | 239 | |
213f2883 ZJS |
240 | /* ======================================================================= */ |
241 | ||
5134e18e | 242 | #if !HAVE_BPF |
71e5200f DM |
243 | union bpf_attr; |
244 | ||
5187dd2c | 245 | static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) { |
71e5200f DM |
246 | #ifdef __NR_bpf |
247 | return (int) syscall(__NR_bpf, cmd, attr, size); | |
248 | #else | |
249 | errno = ENOSYS; | |
250 | return -1; | |
251 | #endif | |
252 | } | |
253 | ||
5187dd2c | 254 | # define bpf missing_bpf |
71e5200f | 255 | #endif |
213f2883 ZJS |
256 | |
257 | /* ======================================================================= */ | |
258 | ||
5187dd2c | 259 | #if !HAVE_STATX |
5134e18e ZJS |
260 | struct statx; |
261 | ||
5187dd2c | 262 | static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flags, unsigned int mask, struct statx *buffer) { |
4c2e1b39 LP |
263 | # ifdef __NR_statx |
264 | return syscall(__NR_statx, dfd, filename, flags, mask, buffer); | |
265 | # else | |
266 | errno = ENOSYS; | |
267 | return -1; | |
268 | # endif | |
269 | } | |
5134e18e ZJS |
270 | #endif |
271 | ||
272 | /* This typedef is supposed to be always defined. */ | |
273 | typedef struct statx struct_statx; | |
5187dd2c | 274 | |
5134e18e | 275 | #if !HAVE_STATX |
69b3fa14 | 276 | # define statx(dfd, filename, flags, mask, buffer) missing_statx(dfd, filename, flags, mask, buffer) |
4c2e1b39 | 277 | #endif |
b070c7c0 | 278 | |
5134e18e | 279 | /* ======================================================================= */ |
b070c7c0 | 280 | |
5134e18e | 281 | #if !HAVE_SET_MEMPOLICY |
b070c7c0 MS |
282 | enum { |
283 | MPOL_DEFAULT, | |
284 | MPOL_PREFERRED, | |
285 | MPOL_BIND, | |
286 | MPOL_INTERLEAVE, | |
287 | MPOL_LOCAL, | |
288 | }; | |
289 | ||
290 | static inline long missing_set_mempolicy(int mode, const unsigned long *nodemask, | |
291 | unsigned long maxnode) { | |
292 | long i; | |
fb4b0465 | 293 | # if defined __NR_set_mempolicy && __NR_set_mempolicy >= 0 |
b070c7c0 MS |
294 | i = syscall(__NR_set_mempolicy, mode, nodemask, maxnode); |
295 | # else | |
296 | errno = ENOSYS; | |
297 | i = -1; | |
298 | # endif | |
299 | return i; | |
300 | } | |
301 | ||
302 | # define set_mempolicy missing_set_mempolicy | |
303 | #endif | |
304 | ||
b070c7c0 MS |
305 | #if !HAVE_GET_MEMPOLICY |
306 | static inline long missing_get_mempolicy(int *mode, unsigned long *nodemask, | |
307 | unsigned long maxnode, void *addr, | |
308 | unsigned long flags) { | |
309 | long i; | |
0e682411 | 310 | # if defined __NR_get_mempolicy && __NR_get_mempolicy >= 0 |
b070c7c0 MS |
311 | i = syscall(__NR_get_mempolicy, mode, nodemask, maxnode, addr, flags); |
312 | # else | |
313 | errno = ENOSYS; | |
314 | i = -1; | |
315 | # endif | |
316 | return i; | |
317 | } | |
318 | ||
faeae444 | 319 | # define get_mempolicy missing_get_mempolicy |
b070c7c0 | 320 | #endif |
5f152f43 | 321 | |
5134e18e ZJS |
322 | /* ======================================================================= */ |
323 | ||
5134e18e | 324 | #if !HAVE_PIDFD_SEND_SIGNAL |
faeae444 | 325 | static inline int missing_pidfd_send_signal(int fd, int sig, siginfo_t *info, unsigned flags) { |
ba28df77 | 326 | # ifdef __NR_pidfd_send_signal |
5f152f43 | 327 | return syscall(__NR_pidfd_send_signal, fd, sig, info, flags); |
23654cee | 328 | # else |
5f152f43 LP |
329 | errno = ENOSYS; |
330 | return -1; | |
23654cee ZJS |
331 | # endif |
332 | } | |
faeae444 ZJS |
333 | |
334 | # define pidfd_send_signal missing_pidfd_send_signal | |
5f152f43 | 335 | #endif |
23654cee | 336 | |
5134e18e | 337 | #if !HAVE_PIDFD_OPEN |
faeae444 | 338 | static inline int missing_pidfd_open(pid_t pid, unsigned flags) { |
23654cee ZJS |
339 | # ifdef __NR_pidfd_open |
340 | return syscall(__NR_pidfd_open, pid, flags); | |
341 | # else | |
342 | errno = ENOSYS; | |
343 | return -1; | |
344 | # endif | |
5f152f43 | 345 | } |
faeae444 ZJS |
346 | |
347 | # define pidfd_open missing_pidfd_open | |
5f152f43 | 348 | #endif |
5ead4e85 | 349 | |
5134e18e ZJS |
350 | /* ======================================================================= */ |
351 | ||
5ead4e85 | 352 | #if !HAVE_RT_SIGQUEUEINFO |
faeae444 | 353 | static inline int missing_rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *info) { |
5134e18e | 354 | # if defined __NR_rt_sigqueueinfo && __NR_rt_sigqueueinfo >= 0 |
5ead4e85 | 355 | return syscall(__NR_rt_sigqueueinfo, tgid, sig, info); |
5134e18e ZJS |
356 | # else |
357 | # error "__NR_rt_sigqueueinfo not defined" | |
358 | # endif | |
5ead4e85 | 359 | } |
faeae444 ZJS |
360 | |
361 | # define rt_sigqueueinfo missing_rt_sigqueueinfo | |
5ead4e85 | 362 | #endif |
441e0fdb | 363 | |
8939eeae | 364 | /* ======================================================================= */ |
a5421953 DDM |
365 | |
366 | #if !HAVE_RT_TGSIGQUEUEINFO | |
367 | static inline int missing_rt_tgsigqueueinfo(pid_t tgid, pid_t tid, int sig, siginfo_t *info) { | |
368 | # if defined __NR_rt_tgsigqueueinfo && __NR_rt_tgsigqueueinfo >= 0 | |
369 | return syscall(__NR_rt_tgsigqueueinfo, tgid, tid, sig, info); | |
370 | # else | |
371 | # error "__NR_rt_tgsigqueueinfo not defined" | |
372 | # endif | |
373 | } | |
374 | ||
375 | # define rt_tgsigqueueinfo missing_rt_tgsigqueueinfo | |
376 | #endif | |
377 | ||
378 | /* ======================================================================= */ | |
b8bcd4c6 | 379 | |
8939eeae ZJS |
380 | #if !HAVE_EXECVEAT |
381 | static inline int missing_execveat(int dirfd, const char *pathname, | |
382 | char *const argv[], char *const envp[], | |
383 | int flags) { | |
384 | # if defined __NR_execveat && __NR_execveat >= 0 | |
385 | return syscall(__NR_execveat, dirfd, pathname, argv, envp, flags); | |
386 | # else | |
387 | errno = ENOSYS; | |
388 | return -1; | |
389 | # endif | |
390 | } | |
b8bcd4c6 | 391 | |
8939eeae ZJS |
392 | # undef AT_EMPTY_PATH |
393 | # define AT_EMPTY_PATH 0x1000 | |
394 | # define execveat missing_execveat | |
395 | #endif | |
396 | ||
441e0fdb LP |
397 | /* ======================================================================= */ |
398 | ||
441e0fdb LP |
399 | #if !HAVE_CLOSE_RANGE |
400 | static inline int missing_close_range(int first_fd, int end_fd, unsigned flags) { | |
401 | # ifdef __NR_close_range | |
402 | /* Kernel-side the syscall expects fds as unsigned integers (just like close() actually), while | |
403 | * userspace exclusively uses signed integers for fds. We don't know just yet how glibc is going to | |
404 | * wrap this syscall, but let's assume it's going to be similar to what they do for close(), | |
405 | * i.e. make the same unsigned → signed type change from the raw kernel syscall compared to the | |
406 | * userspace wrapper. There's only one caveat for this: unlike for close() there's the special | |
407 | * UINT_MAX fd value for the 'end_fd' argument. Let's safely map that to -1 here. And let's refuse | |
408 | * any other negative values. */ | |
409 | if ((first_fd < 0) || (end_fd < 0 && end_fd != -1)) { | |
410 | errno = -EBADF; | |
411 | return -1; | |
412 | } | |
413 | ||
414 | return syscall(__NR_close_range, | |
415 | (unsigned) first_fd, | |
416 | end_fd == -1 ? UINT_MAX : (unsigned) end_fd, /* Of course, the compiler should figure out that this is the identity mapping IRL */ | |
417 | flags); | |
418 | # else | |
419 | errno = ENOSYS; | |
420 | return -1; | |
421 | # endif | |
422 | } | |
423 | ||
424 | # define close_range missing_close_range | |
425 | #endif | |
420297c9 LP |
426 | |
427 | /* ======================================================================= */ | |
428 | ||
84e8edec LP |
429 | #if !HAVE_MOUNT_SETATTR |
430 | ||
431 | #if !HAVE_STRUCT_MOUNT_ATTR | |
432 | struct mount_attr { | |
433 | uint64_t attr_set; | |
434 | uint64_t attr_clr; | |
435 | uint64_t propagation; | |
436 | uint64_t userns_fd; | |
437 | }; | |
438 | #else | |
439 | struct mount_attr; | |
440 | #endif | |
441 | ||
0764e3a3 YW |
442 | #ifndef MOUNT_ATTR_RDONLY |
443 | #define MOUNT_ATTR_RDONLY 0x00000001 /* Mount read-only */ | |
444 | #endif | |
445 | ||
446 | #ifndef MOUNT_ATTR_NOSUID | |
447 | #define MOUNT_ATTR_NOSUID 0x00000002 /* Ignore suid and sgid bits */ | |
448 | #endif | |
449 | ||
450 | #ifndef MOUNT_ATTR_NODEV | |
451 | #define MOUNT_ATTR_NODEV 0x00000004 /* Disallow access to device special files */ | |
452 | #endif | |
453 | ||
454 | #ifndef MOUNT_ATTR_NOEXEC | |
455 | #define MOUNT_ATTR_NOEXEC 0x00000008 /* Disallow program execution */ | |
456 | #endif | |
457 | ||
458 | #ifndef MOUNT_ATTR__ATIME | |
459 | #define MOUNT_ATTR__ATIME 0x00000070 /* Setting on how atime should be updated */ | |
460 | #endif | |
461 | ||
462 | #ifndef MOUNT_ATTR_RELATIME | |
463 | #define MOUNT_ATTR_RELATIME 0x00000000 /* - Update atime relative to mtime/ctime. */ | |
464 | #endif | |
465 | ||
466 | #ifndef MOUNT_ATTR_NOATIME | |
467 | #define MOUNT_ATTR_NOATIME 0x00000010 /* - Do not update access times. */ | |
468 | #endif | |
469 | ||
470 | #ifndef MOUNT_ATTR_STRICTATIME | |
471 | #define MOUNT_ATTR_STRICTATIME 0x00000020 /* - Always perform atime updates */ | |
472 | #endif | |
473 | ||
474 | #ifndef MOUNT_ATTR_NODIRATIME | |
475 | #define MOUNT_ATTR_NODIRATIME 0x00000080 /* Do not update directory access times */ | |
476 | #endif | |
477 | ||
84e8edec | 478 | #ifndef MOUNT_ATTR_IDMAP |
0764e3a3 | 479 | #define MOUNT_ATTR_IDMAP 0x00100000 /* Idmap mount to @userns_fd in struct mount_attr. */ |
84e8edec LP |
480 | #endif |
481 | ||
4f5644db | 482 | #ifndef MOUNT_ATTR_NOSYMFOLLOW |
0764e3a3 | 483 | #define MOUNT_ATTR_NOSYMFOLLOW 0x00200000 /* Do not follow symlinks */ |
4f5644db LP |
484 | #endif |
485 | ||
0764e3a3 YW |
486 | #ifndef MOUNT_ATTR_SIZE_VER0 |
487 | #define MOUNT_ATTR_SIZE_VER0 32 /* sizeof first published struct */ | |
84e8edec LP |
488 | #endif |
489 | ||
0764e3a3 YW |
490 | #ifndef AT_RECURSIVE |
491 | #define AT_RECURSIVE 0x8000 | |
4f5644db LP |
492 | #endif |
493 | ||
84e8edec LP |
494 | static inline int missing_mount_setattr( |
495 | int dfd, | |
496 | const char *path, | |
497 | unsigned flags, | |
498 | struct mount_attr *attr, | |
499 | size_t size) { | |
500 | ||
501 | # if defined __NR_mount_setattr && __NR_mount_setattr >= 0 | |
502 | return syscall(__NR_mount_setattr, dfd, path, flags, attr, size); | |
503 | # else | |
504 | errno = ENOSYS; | |
505 | return -1; | |
506 | # endif | |
507 | } | |
508 | ||
509 | # define mount_setattr missing_mount_setattr | |
510 | #endif | |
511 | ||
512 | /* ======================================================================= */ | |
513 | ||
514 | #if !HAVE_OPEN_TREE | |
515 | ||
516 | #ifndef OPEN_TREE_CLONE | |
517 | #define OPEN_TREE_CLONE 1 | |
518 | #endif | |
519 | ||
520 | #ifndef OPEN_TREE_CLOEXEC | |
521 | #define OPEN_TREE_CLOEXEC O_CLOEXEC | |
522 | #endif | |
523 | ||
524 | static inline int missing_open_tree( | |
525 | int dfd, | |
526 | const char *filename, | |
527 | unsigned flags) { | |
528 | ||
529 | # if defined __NR_open_tree && __NR_open_tree >= 0 | |
530 | return syscall(__NR_open_tree, dfd, filename, flags); | |
531 | # else | |
532 | errno = ENOSYS; | |
533 | return -1; | |
534 | # endif | |
535 | } | |
536 | ||
537 | # define open_tree missing_open_tree | |
538 | #endif | |
539 | ||
540 | /* ======================================================================= */ | |
541 | ||
7c83d42e LB |
542 | #ifndef MOVE_MOUNT_BENEATH |
543 | #define MOVE_MOUNT_BENEATH 0x00000200 | |
544 | #endif | |
545 | ||
84e8edec LP |
546 | #if !HAVE_MOVE_MOUNT |
547 | ||
548 | #ifndef MOVE_MOUNT_F_EMPTY_PATH | |
549 | #define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */ | |
550 | #endif | |
551 | ||
608c3b02 RN |
552 | #ifndef MOVE_MOUNT_T_EMPTY_PATH |
553 | #define MOVE_MOUNT_T_EMPTY_PATH 0x00000040 /* Empty to path permitted */ | |
554 | #endif | |
555 | ||
84e8edec LP |
556 | static inline int missing_move_mount( |
557 | int from_dfd, | |
558 | const char *from_pathname, | |
559 | int to_dfd, | |
560 | const char *to_pathname, | |
561 | unsigned flags) { | |
562 | ||
563 | # if defined __NR_move_mount && __NR_move_mount >= 0 | |
564 | return syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd, to_pathname, flags); | |
565 | # else | |
566 | errno = ENOSYS; | |
567 | return -1; | |
568 | # endif | |
569 | } | |
570 | ||
571 | # define move_mount missing_move_mount | |
572 | #endif | |
aab35b1e LP |
573 | |
574 | /* ======================================================================= */ | |
575 | ||
1c265fcd DDM |
576 | #if !HAVE_FSOPEN |
577 | ||
578 | #ifndef FSOPEN_CLOEXEC | |
579 | #define FSOPEN_CLOEXEC 0x00000001 | |
580 | #endif | |
581 | ||
582 | static inline int missing_fsopen(const char *fsname, unsigned flags) { | |
583 | # if defined __NR_fsopen && __NR_fsopen >= 0 | |
584 | return syscall(__NR_fsopen, fsname, flags); | |
585 | # else | |
586 | errno = ENOSYS; | |
587 | return -1; | |
588 | # endif | |
589 | } | |
590 | ||
591 | # define fsopen missing_fsopen | |
592 | #endif | |
593 | ||
594 | /* ======================================================================= */ | |
595 | ||
596 | #if !HAVE_FSCONFIG | |
597 | ||
c115e161 LP |
598 | #ifndef FSCONFIG_SET_FLAG |
599 | #define FSCONFIG_SET_FLAG 0 /* Set parameter, supplying no value */ | |
600 | #endif | |
601 | ||
1c265fcd DDM |
602 | #ifndef FSCONFIG_SET_STRING |
603 | #define FSCONFIG_SET_STRING 1 /* Set parameter, supplying a string value */ | |
604 | #endif | |
605 | ||
c115e161 LP |
606 | #ifndef FSCONFIG_SET_FD |
607 | #define FSCONFIG_SET_FD 5 /* Set parameter, supplying an object by fd */ | |
608 | #endif | |
609 | ||
610 | #ifndef FSCONFIG_CMD_CREATE | |
611 | #define FSCONFIG_CMD_CREATE 6 /* Invoke superblock creation */ | |
612 | #endif | |
613 | ||
1c265fcd DDM |
614 | static inline int missing_fsconfig(int fd, unsigned cmd, const char *key, const void *value, int aux) { |
615 | # if defined __NR_fsconfig && __NR_fsconfig >= 0 | |
616 | return syscall(__NR_fsconfig, fd, cmd, key, value, aux); | |
617 | # else | |
618 | errno = ENOSYS; | |
619 | return -1; | |
620 | # endif | |
621 | } | |
622 | ||
623 | # define fsconfig missing_fsconfig | |
624 | #endif | |
625 | ||
626 | /* ======================================================================= */ | |
627 | ||
34a9da0d LP |
628 | #if !HAVE_FSMOUNT |
629 | ||
630 | #ifndef FSMOUNT_CLOEXEC | |
631 | #define FSMOUNT_CLOEXEC 0x00000001 | |
632 | #endif | |
633 | ||
634 | static inline int missing_fsmount(int fd, unsigned flags, unsigned ms_flags) { | |
635 | # if defined __NR_fsmount && __NR_fsmount >= 0 | |
636 | return syscall(__NR_fsmount, fd, flags, ms_flags); | |
637 | # else | |
638 | errno = ENOSYS; | |
639 | return -1; | |
640 | # endif | |
641 | } | |
642 | ||
643 | # define fsmount missing_fsmount | |
644 | #endif | |
645 | ||
646 | /* ======================================================================= */ | |
647 | ||
aab35b1e LP |
648 | #if !HAVE_GETDENTS64 |
649 | ||
650 | static inline ssize_t missing_getdents64(int fd, void *buffer, size_t length) { | |
651 | # if defined __NR_getdents64 && __NR_getdents64 >= 0 | |
652 | return syscall(__NR_getdents64, fd, buffer, length); | |
653 | # else | |
654 | errno = ENOSYS; | |
655 | return -1; | |
656 | # endif | |
657 | } | |
658 | ||
659 | # define getdents64 missing_getdents64 | |
660 | #endif | |
840ac5cd LB |
661 | |
662 | /* ======================================================================= */ | |
663 | ||
664 | /* glibc does not provide clone() on ia64, only clone2(). Not only that, but it also doesn't provide a | |
665 | * prototype, only the symbol in the shared library (it provides a prototype for clone(), but not the | |
666 | * symbol in the shared library). */ | |
667 | #if defined(__ia64__) | |
668 | int __clone2(int (*fn)(void *), void *stack_base, size_t stack_size, int flags, void *arg); | |
669 | #define HAVE_CLONE 0 | |
670 | #else | |
671 | /* We know that everywhere else clone() is available, so we don't bother with a meson check (that takes time | |
672 | * at build time) and just define it. Once the kernel drops ia64 support, we can drop this too. */ | |
673 | #define HAVE_CLONE 1 | |
674 | #endif |