xref: /openbmc/linux/tools/include/nolibc/sys.h (revision 6591be4a)
1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2 /*
3  * Syscall definitions for NOLIBC (those in man(2))
4  * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
5  */
6 
7 #ifndef _NOLIBC_SYS_H
8 #define _NOLIBC_SYS_H
9 
10 #include <stdarg.h>
11 #include "std.h"
12 
13 /* system includes */
14 #include <asm/unistd.h>
15 #include <asm/signal.h>  /* for SIGCHLD */
16 #include <asm/ioctls.h>
17 #include <asm/mman.h>
18 #include <linux/fs.h>
19 #include <linux/loop.h>
20 #include <linux/time.h>
21 #include <linux/auxvec.h>
22 #include <linux/fcntl.h> /* for O_* and AT_* */
23 #include <linux/stat.h>  /* for statx() */
24 #include <linux/reboot.h> /* for LINUX_REBOOT_* */
25 #include <linux/prctl.h>
26 
27 #include "arch.h"
28 #include "errno.h"
29 #include "types.h"
30 
31 
32 /* Syscall return helper for library routines, set errno as -ret when ret is in
33  * range of [-MAX_ERRNO, -1]
34  *
35  * Note, No official reference states the errno range here aligns with musl
36  * (src/internal/syscall_ret.c) and glibc (sysdeps/unix/sysv/linux/sysdep.h)
37  */
38 
39 static __inline__ __attribute__((unused, always_inline))
40 long __sysret(unsigned long ret)
41 {
42 	if (ret >= (unsigned long)-MAX_ERRNO) {
43 		SET_ERRNO(-(long)ret);
44 		return -1;
45 	}
46 	return ret;
47 }
48 
49 /* Functions in this file only describe syscalls. They're declared static so
50  * that the compiler usually decides to inline them while still being allowed
51  * to pass a pointer to one of their instances. Each syscall exists in two
52  * versions:
53  *   - the "internal" ones, which matches the raw syscall interface at the
54  *     kernel level, which may sometimes slightly differ from the documented
55  *     libc-level ones. For example most of them return either a valid value
56  *     or -errno. All of these are prefixed with "sys_". They may be called
57  *     by non-portable applications if desired.
58  *
59  *   - the "exported" ones, whose interface must closely match the one
60  *     documented in man(2), that applications are supposed to expect. These
61  *     ones rely on the internal ones, and set errno.
62  *
63  * Each syscall will be defined with the two functions, sorted in alphabetical
64  * order applied to the exported names.
65  *
66  * In case of doubt about the relevance of a function here, only those which
67  * set errno should be defined here. Wrappers like those appearing in man(3)
68  * should not be placed here.
69  */
70 
71 
72 /*
73  * int brk(void *addr);
74  * void *sbrk(intptr_t inc)
75  */
76 
77 static __attribute__((unused))
78 void *sys_brk(void *addr)
79 {
80 	return (void *)my_syscall1(__NR_brk, addr);
81 }
82 
83 static __attribute__((unused))
84 int brk(void *addr)
85 {
86 	return __sysret(sys_brk(addr) ? 0 : -ENOMEM);
87 }
88 
89 static __attribute__((unused))
90 void *sbrk(intptr_t inc)
91 {
92 	void *ret;
93 
94 	/* first call to find current end */
95 	if ((ret = sys_brk(0)) && (sys_brk(ret + inc) == ret + inc))
96 		return ret + inc;
97 
98 	SET_ERRNO(ENOMEM);
99 	return (void *)-1;
100 }
101 
102 
103 /*
104  * int chdir(const char *path);
105  */
106 
107 static __attribute__((unused))
108 int sys_chdir(const char *path)
109 {
110 	return my_syscall1(__NR_chdir, path);
111 }
112 
113 static __attribute__((unused))
114 int chdir(const char *path)
115 {
116 	return __sysret(sys_chdir(path));
117 }
118 
119 
120 /*
121  * int chmod(const char *path, mode_t mode);
122  */
123 
124 static __attribute__((unused))
125 int sys_chmod(const char *path, mode_t mode)
126 {
127 #ifdef __NR_fchmodat
128 	return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0);
129 #elif defined(__NR_chmod)
130 	return my_syscall2(__NR_chmod, path, mode);
131 #else
132 	return -ENOSYS;
133 #endif
134 }
135 
136 static __attribute__((unused))
137 int chmod(const char *path, mode_t mode)
138 {
139 	return __sysret(sys_chmod(path, mode));
140 }
141 
142 
143 /*
144  * int chown(const char *path, uid_t owner, gid_t group);
145  */
146 
147 static __attribute__((unused))
148 int sys_chown(const char *path, uid_t owner, gid_t group)
149 {
150 #ifdef __NR_fchownat
151 	return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0);
152 #elif defined(__NR_chown)
153 	return my_syscall3(__NR_chown, path, owner, group);
154 #else
155 	return -ENOSYS;
156 #endif
157 }
158 
159 static __attribute__((unused))
160 int chown(const char *path, uid_t owner, gid_t group)
161 {
162 	return __sysret(sys_chown(path, owner, group));
163 }
164 
165 
166 /*
167  * int chroot(const char *path);
168  */
169 
170 static __attribute__((unused))
171 int sys_chroot(const char *path)
172 {
173 	return my_syscall1(__NR_chroot, path);
174 }
175 
176 static __attribute__((unused))
177 int chroot(const char *path)
178 {
179 	return __sysret(sys_chroot(path));
180 }
181 
182 
183 /*
184  * int close(int fd);
185  */
186 
187 static __attribute__((unused))
188 int sys_close(int fd)
189 {
190 	return my_syscall1(__NR_close, fd);
191 }
192 
193 static __attribute__((unused))
194 int close(int fd)
195 {
196 	return __sysret(sys_close(fd));
197 }
198 
199 
200 /*
201  * int dup(int fd);
202  */
203 
204 static __attribute__((unused))
205 int sys_dup(int fd)
206 {
207 	return my_syscall1(__NR_dup, fd);
208 }
209 
210 static __attribute__((unused))
211 int dup(int fd)
212 {
213 	return __sysret(sys_dup(fd));
214 }
215 
216 
217 /*
218  * int dup2(int old, int new);
219  */
220 
221 static __attribute__((unused))
222 int sys_dup2(int old, int new)
223 {
224 #ifdef __NR_dup3
225 	return my_syscall3(__NR_dup3, old, new, 0);
226 #elif defined(__NR_dup2)
227 	return my_syscall2(__NR_dup2, old, new);
228 #else
229 	return -ENOSYS;
230 #endif
231 }
232 
233 static __attribute__((unused))
234 int dup2(int old, int new)
235 {
236 	return __sysret(sys_dup2(old, new));
237 }
238 
239 
240 /*
241  * int dup3(int old, int new, int flags);
242  */
243 
244 #ifdef __NR_dup3
245 static __attribute__((unused))
246 int sys_dup3(int old, int new, int flags)
247 {
248 	return my_syscall3(__NR_dup3, old, new, flags);
249 }
250 
251 static __attribute__((unused))
252 int dup3(int old, int new, int flags)
253 {
254 	return __sysret(sys_dup3(old, new, flags));
255 }
256 #endif
257 
258 
259 /*
260  * int execve(const char *filename, char *const argv[], char *const envp[]);
261  */
262 
263 static __attribute__((unused))
264 int sys_execve(const char *filename, char *const argv[], char *const envp[])
265 {
266 	return my_syscall3(__NR_execve, filename, argv, envp);
267 }
268 
269 static __attribute__((unused))
270 int execve(const char *filename, char *const argv[], char *const envp[])
271 {
272 	return __sysret(sys_execve(filename, argv, envp));
273 }
274 
275 
276 /*
277  * void exit(int status);
278  */
279 
280 static __attribute__((noreturn,unused))
281 void sys_exit(int status)
282 {
283 	my_syscall1(__NR_exit, status & 255);
284 	while(1); /* shut the "noreturn" warnings. */
285 }
286 
287 static __attribute__((noreturn,unused))
288 void exit(int status)
289 {
290 	sys_exit(status);
291 }
292 
293 
294 /*
295  * pid_t fork(void);
296  */
297 
298 #ifndef sys_fork
299 static __attribute__((unused))
300 pid_t sys_fork(void)
301 {
302 #ifdef __NR_clone
303 	/* note: some archs only have clone() and not fork(). Different archs
304 	 * have a different API, but most archs have the flags on first arg and
305 	 * will not use the rest with no other flag.
306 	 */
307 	return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0);
308 #elif defined(__NR_fork)
309 	return my_syscall0(__NR_fork);
310 #else
311 	return -ENOSYS;
312 #endif
313 }
314 #endif
315 
316 static __attribute__((unused))
317 pid_t fork(void)
318 {
319 	return __sysret(sys_fork());
320 }
321 
322 
323 /*
324  * int fsync(int fd);
325  */
326 
327 static __attribute__((unused))
328 int sys_fsync(int fd)
329 {
330 	return my_syscall1(__NR_fsync, fd);
331 }
332 
333 static __attribute__((unused))
334 int fsync(int fd)
335 {
336 	return __sysret(sys_fsync(fd));
337 }
338 
339 
340 /*
341  * int getdents64(int fd, struct linux_dirent64 *dirp, int count);
342  */
343 
344 static __attribute__((unused))
345 int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count)
346 {
347 	return my_syscall3(__NR_getdents64, fd, dirp, count);
348 }
349 
350 static __attribute__((unused))
351 int getdents64(int fd, struct linux_dirent64 *dirp, int count)
352 {
353 	return __sysret(sys_getdents64(fd, dirp, count));
354 }
355 
356 
357 /*
358  * uid_t geteuid(void);
359  */
360 
361 static __attribute__((unused))
362 uid_t sys_geteuid(void)
363 {
364 #ifdef __NR_geteuid32
365 	return my_syscall0(__NR_geteuid32);
366 #else
367 	return my_syscall0(__NR_geteuid);
368 #endif
369 }
370 
371 static __attribute__((unused))
372 uid_t geteuid(void)
373 {
374 	return sys_geteuid();
375 }
376 
377 
378 /*
379  * pid_t getpgid(pid_t pid);
380  */
381 
382 static __attribute__((unused))
383 pid_t sys_getpgid(pid_t pid)
384 {
385 	return my_syscall1(__NR_getpgid, pid);
386 }
387 
388 static __attribute__((unused))
389 pid_t getpgid(pid_t pid)
390 {
391 	return __sysret(sys_getpgid(pid));
392 }
393 
394 
395 /*
396  * pid_t getpgrp(void);
397  */
398 
399 static __attribute__((unused))
400 pid_t sys_getpgrp(void)
401 {
402 	return sys_getpgid(0);
403 }
404 
405 static __attribute__((unused))
406 pid_t getpgrp(void)
407 {
408 	return sys_getpgrp();
409 }
410 
411 
412 /*
413  * pid_t getpid(void);
414  */
415 
416 static __attribute__((unused))
417 pid_t sys_getpid(void)
418 {
419 	return my_syscall0(__NR_getpid);
420 }
421 
422 static __attribute__((unused))
423 pid_t getpid(void)
424 {
425 	return sys_getpid();
426 }
427 
428 
429 /*
430  * pid_t getppid(void);
431  */
432 
433 static __attribute__((unused))
434 pid_t sys_getppid(void)
435 {
436 	return my_syscall0(__NR_getppid);
437 }
438 
439 static __attribute__((unused))
440 pid_t getppid(void)
441 {
442 	return sys_getppid();
443 }
444 
445 
446 /*
447  * pid_t gettid(void);
448  */
449 
450 static __attribute__((unused))
451 pid_t sys_gettid(void)
452 {
453 	return my_syscall0(__NR_gettid);
454 }
455 
456 static __attribute__((unused))
457 pid_t gettid(void)
458 {
459 	return sys_gettid();
460 }
461 
462 static unsigned long getauxval(unsigned long key);
463 
464 /*
465  * long getpagesize(void);
466  */
467 
468 static __attribute__((unused))
469 long getpagesize(void)
470 {
471 	return __sysret(getauxval(AT_PAGESZ) ?: -ENOENT);
472 }
473 
474 
475 /*
476  * int gettimeofday(struct timeval *tv, struct timezone *tz);
477  */
478 
479 static __attribute__((unused))
480 int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
481 {
482 #ifdef __NR_gettimeofday
483 	return my_syscall2(__NR_gettimeofday, tv, tz);
484 #else
485 	return -ENOSYS;
486 #endif
487 }
488 
489 static __attribute__((unused))
490 int gettimeofday(struct timeval *tv, struct timezone *tz)
491 {
492 	return __sysret(sys_gettimeofday(tv, tz));
493 }
494 
495 
496 /*
497  * uid_t getuid(void);
498  */
499 
500 static __attribute__((unused))
501 uid_t sys_getuid(void)
502 {
503 #ifdef __NR_getuid32
504 	return my_syscall0(__NR_getuid32);
505 #else
506 	return my_syscall0(__NR_getuid);
507 #endif
508 }
509 
510 static __attribute__((unused))
511 uid_t getuid(void)
512 {
513 	return sys_getuid();
514 }
515 
516 
517 /*
518  * int ioctl(int fd, unsigned long req, void *value);
519  */
520 
521 static __attribute__((unused))
522 int sys_ioctl(int fd, unsigned long req, void *value)
523 {
524 	return my_syscall3(__NR_ioctl, fd, req, value);
525 }
526 
527 static __attribute__((unused))
528 int ioctl(int fd, unsigned long req, void *value)
529 {
530 	return __sysret(sys_ioctl(fd, req, value));
531 }
532 
533 /*
534  * int kill(pid_t pid, int signal);
535  */
536 
537 static __attribute__((unused))
538 int sys_kill(pid_t pid, int signal)
539 {
540 	return my_syscall2(__NR_kill, pid, signal);
541 }
542 
543 static __attribute__((unused))
544 int kill(pid_t pid, int signal)
545 {
546 	return __sysret(sys_kill(pid, signal));
547 }
548 
549 
550 /*
551  * int link(const char *old, const char *new);
552  */
553 
554 static __attribute__((unused))
555 int sys_link(const char *old, const char *new)
556 {
557 #ifdef __NR_linkat
558 	return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0);
559 #elif defined(__NR_link)
560 	return my_syscall2(__NR_link, old, new);
561 #else
562 	return -ENOSYS;
563 #endif
564 }
565 
566 static __attribute__((unused))
567 int link(const char *old, const char *new)
568 {
569 	return __sysret(sys_link(old, new));
570 }
571 
572 
573 /*
574  * off_t lseek(int fd, off_t offset, int whence);
575  */
576 
577 static __attribute__((unused))
578 off_t sys_lseek(int fd, off_t offset, int whence)
579 {
580 #ifdef __NR_lseek
581 	return my_syscall3(__NR_lseek, fd, offset, whence);
582 #else
583 	return -ENOSYS;
584 #endif
585 }
586 
587 static __attribute__((unused))
588 off_t lseek(int fd, off_t offset, int whence)
589 {
590 	return __sysret(sys_lseek(fd, offset, whence));
591 }
592 
593 
594 /*
595  * int mkdir(const char *path, mode_t mode);
596  */
597 
598 static __attribute__((unused))
599 int sys_mkdir(const char *path, mode_t mode)
600 {
601 #ifdef __NR_mkdirat
602 	return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode);
603 #elif defined(__NR_mkdir)
604 	return my_syscall2(__NR_mkdir, path, mode);
605 #else
606 	return -ENOSYS;
607 #endif
608 }
609 
610 static __attribute__((unused))
611 int mkdir(const char *path, mode_t mode)
612 {
613 	return __sysret(sys_mkdir(path, mode));
614 }
615 
616 
617 /*
618  * int mknod(const char *path, mode_t mode, dev_t dev);
619  */
620 
621 static __attribute__((unused))
622 long sys_mknod(const char *path, mode_t mode, dev_t dev)
623 {
624 #ifdef __NR_mknodat
625 	return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev);
626 #elif defined(__NR_mknod)
627 	return my_syscall3(__NR_mknod, path, mode, dev);
628 #else
629 	return -ENOSYS;
630 #endif
631 }
632 
633 static __attribute__((unused))
634 int mknod(const char *path, mode_t mode, dev_t dev)
635 {
636 	return __sysret(sys_mknod(path, mode, dev));
637 }
638 
639 #ifndef MAP_SHARED
640 #define MAP_SHARED		0x01	/* Share changes */
641 #define MAP_PRIVATE		0x02	/* Changes are private */
642 #define MAP_SHARED_VALIDATE	0x03	/* share + validate extension flags */
643 #endif
644 
645 #ifndef MAP_FAILED
646 #define MAP_FAILED ((void *)-1)
647 #endif
648 
649 #ifndef sys_mmap
650 static __attribute__((unused))
651 void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd,
652 	       off_t offset)
653 {
654 #ifndef my_syscall6
655 	/* Function not implemented. */
656 	return (void *)-ENOSYS;
657 #else
658 
659 	int n;
660 
661 #if defined(__NR_mmap2)
662 	n = __NR_mmap2;
663 	offset >>= 12;
664 #else
665 	n = __NR_mmap;
666 #endif
667 
668 	return (void *)my_syscall6(n, addr, length, prot, flags, fd, offset);
669 #endif
670 }
671 #endif
672 
673 static __attribute__((unused))
674 void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
675 {
676 	void *ret = sys_mmap(addr, length, prot, flags, fd, offset);
677 
678 	if ((unsigned long)ret >= -4095UL) {
679 		SET_ERRNO(-(long)ret);
680 		ret = MAP_FAILED;
681 	}
682 	return ret;
683 }
684 
685 static __attribute__((unused))
686 int sys_munmap(void *addr, size_t length)
687 {
688 	return my_syscall2(__NR_munmap, addr, length);
689 }
690 
691 static __attribute__((unused))
692 int munmap(void *addr, size_t length)
693 {
694 	return __sysret(sys_munmap(addr, length));
695 }
696 
697 /*
698  * int mount(const char *source, const char *target,
699  *           const char *fstype, unsigned long flags,
700  *           const void *data);
701  */
702 static __attribute__((unused))
703 int sys_mount(const char *src, const char *tgt, const char *fst,
704                      unsigned long flags, const void *data)
705 {
706 	return my_syscall5(__NR_mount, src, tgt, fst, flags, data);
707 }
708 
709 static __attribute__((unused))
710 int mount(const char *src, const char *tgt,
711           const char *fst, unsigned long flags,
712           const void *data)
713 {
714 	return __sysret(sys_mount(src, tgt, fst, flags, data));
715 }
716 
717 
718 /*
719  * int open(const char *path, int flags[, mode_t mode]);
720  */
721 
722 static __attribute__((unused))
723 int sys_open(const char *path, int flags, mode_t mode)
724 {
725 #ifdef __NR_openat
726 	return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode);
727 #elif defined(__NR_open)
728 	return my_syscall3(__NR_open, path, flags, mode);
729 #else
730 	return -ENOSYS;
731 #endif
732 }
733 
734 static __attribute__((unused))
735 int open(const char *path, int flags, ...)
736 {
737 	mode_t mode = 0;
738 	int ret;
739 
740 	if (flags & O_CREAT) {
741 		va_list args;
742 
743 		va_start(args, flags);
744 		mode = va_arg(args, int);
745 		va_end(args);
746 	}
747 
748 	return __sysret(sys_open(path, flags, mode));
749 }
750 
751 
752 /*
753  * int prctl(int option, unsigned long arg2, unsigned long arg3,
754  *                       unsigned long arg4, unsigned long arg5);
755  */
756 
757 static __attribute__((unused))
758 int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
759 		          unsigned long arg4, unsigned long arg5)
760 {
761 	return my_syscall5(__NR_prctl, option, arg2, arg3, arg4, arg5);
762 }
763 
764 static __attribute__((unused))
765 int prctl(int option, unsigned long arg2, unsigned long arg3,
766 		      unsigned long arg4, unsigned long arg5)
767 {
768 	return __sysret(sys_prctl(option, arg2, arg3, arg4, arg5));
769 }
770 
771 
772 /*
773  * int pivot_root(const char *new, const char *old);
774  */
775 
776 static __attribute__((unused))
777 int sys_pivot_root(const char *new, const char *old)
778 {
779 	return my_syscall2(__NR_pivot_root, new, old);
780 }
781 
782 static __attribute__((unused))
783 int pivot_root(const char *new, const char *old)
784 {
785 	return __sysret(sys_pivot_root(new, old));
786 }
787 
788 
789 /*
790  * int poll(struct pollfd *fds, int nfds, int timeout);
791  */
792 
793 static __attribute__((unused))
794 int sys_poll(struct pollfd *fds, int nfds, int timeout)
795 {
796 #if defined(__NR_ppoll)
797 	struct timespec t;
798 
799 	if (timeout >= 0) {
800 		t.tv_sec  = timeout / 1000;
801 		t.tv_nsec = (timeout % 1000) * 1000000;
802 	}
803 	return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
804 #elif defined(__NR_poll)
805 	return my_syscall3(__NR_poll, fds, nfds, timeout);
806 #else
807 	return -ENOSYS;
808 #endif
809 }
810 
811 static __attribute__((unused))
812 int poll(struct pollfd *fds, int nfds, int timeout)
813 {
814 	return __sysret(sys_poll(fds, nfds, timeout));
815 }
816 
817 
818 /*
819  * ssize_t read(int fd, void *buf, size_t count);
820  */
821 
822 static __attribute__((unused))
823 ssize_t sys_read(int fd, void *buf, size_t count)
824 {
825 	return my_syscall3(__NR_read, fd, buf, count);
826 }
827 
828 static __attribute__((unused))
829 ssize_t read(int fd, void *buf, size_t count)
830 {
831 	return __sysret(sys_read(fd, buf, count));
832 }
833 
834 
835 /*
836  * int reboot(int cmd);
837  * <cmd> is among LINUX_REBOOT_CMD_*
838  */
839 
840 static __attribute__((unused))
841 ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg)
842 {
843 	return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg);
844 }
845 
846 static __attribute__((unused))
847 int reboot(int cmd)
848 {
849 	return __sysret(sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0));
850 }
851 
852 
853 /*
854  * int sched_yield(void);
855  */
856 
857 static __attribute__((unused))
858 int sys_sched_yield(void)
859 {
860 	return my_syscall0(__NR_sched_yield);
861 }
862 
863 static __attribute__((unused))
864 int sched_yield(void)
865 {
866 	return __sysret(sys_sched_yield());
867 }
868 
869 
870 /*
871  * int select(int nfds, fd_set *read_fds, fd_set *write_fds,
872  *            fd_set *except_fds, struct timeval *timeout);
873  */
874 
875 static __attribute__((unused))
876 int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
877 {
878 #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect)
879 	struct sel_arg_struct {
880 		unsigned long n;
881 		fd_set *r, *w, *e;
882 		struct timeval *t;
883 	} arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout };
884 	return my_syscall1(__NR_select, &arg);
885 #elif defined(__ARCH_WANT_SYS_PSELECT6) && defined(__NR_pselect6)
886 	struct timespec t;
887 
888 	if (timeout) {
889 		t.tv_sec  = timeout->tv_sec;
890 		t.tv_nsec = timeout->tv_usec * 1000;
891 	}
892 	return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
893 #elif defined(__NR__newselect) || defined(__NR_select)
894 #ifndef __NR__newselect
895 #define __NR__newselect __NR_select
896 #endif
897 	return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout);
898 #else
899 	return -ENOSYS;
900 #endif
901 }
902 
903 static __attribute__((unused))
904 int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
905 {
906 	return __sysret(sys_select(nfds, rfds, wfds, efds, timeout));
907 }
908 
909 
910 /*
911  * int setpgid(pid_t pid, pid_t pgid);
912  */
913 
914 static __attribute__((unused))
915 int sys_setpgid(pid_t pid, pid_t pgid)
916 {
917 	return my_syscall2(__NR_setpgid, pid, pgid);
918 }
919 
920 static __attribute__((unused))
921 int setpgid(pid_t pid, pid_t pgid)
922 {
923 	return __sysret(sys_setpgid(pid, pgid));
924 }
925 
926 
927 /*
928  * pid_t setsid(void);
929  */
930 
931 static __attribute__((unused))
932 pid_t sys_setsid(void)
933 {
934 	return my_syscall0(__NR_setsid);
935 }
936 
937 static __attribute__((unused))
938 pid_t setsid(void)
939 {
940 	return __sysret(sys_setsid());
941 }
942 
943 #if defined(__NR_statx)
944 /*
945  * int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf);
946  */
947 
948 static __attribute__((unused))
949 int sys_statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf)
950 {
951 	return my_syscall5(__NR_statx, fd, path, flags, mask, buf);
952 }
953 
954 static __attribute__((unused))
955 int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf)
956 {
957 	return __sysret(sys_statx(fd, path, flags, mask, buf));
958 }
959 #endif
960 
961 /*
962  * int stat(const char *path, struct stat *buf);
963  * Warning: the struct stat's layout is arch-dependent.
964  */
965 
966 #if defined(__NR_statx) && !defined(__NR_newfstatat) && !defined(__NR_stat)
967 /*
968  * Maybe we can just use statx() when available for all architectures?
969  */
970 static __attribute__((unused))
971 int sys_stat(const char *path, struct stat *buf)
972 {
973 	struct statx statx;
974 	long ret;
975 
976 	ret = sys_statx(AT_FDCWD, path, AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &statx);
977 	buf->st_dev          = ((statx.stx_dev_minor & 0xff)
978 			       | (statx.stx_dev_major << 8)
979 			       | ((statx.stx_dev_minor & ~0xff) << 12));
980 	buf->st_ino          = statx.stx_ino;
981 	buf->st_mode         = statx.stx_mode;
982 	buf->st_nlink        = statx.stx_nlink;
983 	buf->st_uid          = statx.stx_uid;
984 	buf->st_gid          = statx.stx_gid;
985 	buf->st_rdev         = ((statx.stx_rdev_minor & 0xff)
986 			       | (statx.stx_rdev_major << 8)
987 			       | ((statx.stx_rdev_minor & ~0xff) << 12));
988 	buf->st_size         = statx.stx_size;
989 	buf->st_blksize      = statx.stx_blksize;
990 	buf->st_blocks       = statx.stx_blocks;
991 	buf->st_atim.tv_sec  = statx.stx_atime.tv_sec;
992 	buf->st_atim.tv_nsec = statx.stx_atime.tv_nsec;
993 	buf->st_mtim.tv_sec  = statx.stx_mtime.tv_sec;
994 	buf->st_mtim.tv_nsec = statx.stx_mtime.tv_nsec;
995 	buf->st_ctim.tv_sec  = statx.stx_ctime.tv_sec;
996 	buf->st_ctim.tv_nsec = statx.stx_ctime.tv_nsec;
997 	return ret;
998 }
999 #else
1000 static __attribute__((unused))
1001 int sys_stat(const char *path, struct stat *buf)
1002 {
1003 	struct sys_stat_struct stat;
1004 	long ret;
1005 
1006 #ifdef __NR_newfstatat
1007 	/* only solution for arm64 */
1008 	ret = my_syscall4(__NR_newfstatat, AT_FDCWD, path, &stat, 0);
1009 #elif defined(__NR_stat)
1010 	ret = my_syscall2(__NR_stat, path, &stat);
1011 #else
1012 	return -ENOSYS;
1013 #endif
1014 	buf->st_dev          = stat.st_dev;
1015 	buf->st_ino          = stat.st_ino;
1016 	buf->st_mode         = stat.st_mode;
1017 	buf->st_nlink        = stat.st_nlink;
1018 	buf->st_uid          = stat.st_uid;
1019 	buf->st_gid          = stat.st_gid;
1020 	buf->st_rdev         = stat.st_rdev;
1021 	buf->st_size         = stat.st_size;
1022 	buf->st_blksize      = stat.st_blksize;
1023 	buf->st_blocks       = stat.st_blocks;
1024 	buf->st_atim.tv_sec  = stat.st_atime;
1025 	buf->st_atim.tv_nsec = stat.st_atime_nsec;
1026 	buf->st_mtim.tv_sec  = stat.st_mtime;
1027 	buf->st_mtim.tv_nsec = stat.st_mtime_nsec;
1028 	buf->st_ctim.tv_sec  = stat.st_ctime;
1029 	buf->st_ctim.tv_nsec = stat.st_ctime_nsec;
1030 	return ret;
1031 }
1032 #endif
1033 
1034 static __attribute__((unused))
1035 int stat(const char *path, struct stat *buf)
1036 {
1037 	return __sysret(sys_stat(path, buf));
1038 }
1039 
1040 
1041 /*
1042  * int symlink(const char *old, const char *new);
1043  */
1044 
1045 static __attribute__((unused))
1046 int sys_symlink(const char *old, const char *new)
1047 {
1048 #ifdef __NR_symlinkat
1049 	return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new);
1050 #elif defined(__NR_symlink)
1051 	return my_syscall2(__NR_symlink, old, new);
1052 #else
1053 	return -ENOSYS;
1054 #endif
1055 }
1056 
1057 static __attribute__((unused))
1058 int symlink(const char *old, const char *new)
1059 {
1060 	return __sysret(sys_symlink(old, new));
1061 }
1062 
1063 
1064 /*
1065  * mode_t umask(mode_t mode);
1066  */
1067 
1068 static __attribute__((unused))
1069 mode_t sys_umask(mode_t mode)
1070 {
1071 	return my_syscall1(__NR_umask, mode);
1072 }
1073 
1074 static __attribute__((unused))
1075 mode_t umask(mode_t mode)
1076 {
1077 	return sys_umask(mode);
1078 }
1079 
1080 
1081 /*
1082  * int umount2(const char *path, int flags);
1083  */
1084 
1085 static __attribute__((unused))
1086 int sys_umount2(const char *path, int flags)
1087 {
1088 	return my_syscall2(__NR_umount2, path, flags);
1089 }
1090 
1091 static __attribute__((unused))
1092 int umount2(const char *path, int flags)
1093 {
1094 	return __sysret(sys_umount2(path, flags));
1095 }
1096 
1097 
1098 /*
1099  * int unlink(const char *path);
1100  */
1101 
1102 static __attribute__((unused))
1103 int sys_unlink(const char *path)
1104 {
1105 #ifdef __NR_unlinkat
1106 	return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0);
1107 #elif defined(__NR_unlink)
1108 	return my_syscall1(__NR_unlink, path);
1109 #else
1110 	return -ENOSYS;
1111 #endif
1112 }
1113 
1114 static __attribute__((unused))
1115 int unlink(const char *path)
1116 {
1117 	return __sysret(sys_unlink(path));
1118 }
1119 
1120 
1121 /*
1122  * pid_t wait(int *status);
1123  * pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);
1124  * pid_t waitpid(pid_t pid, int *status, int options);
1125  */
1126 
1127 static __attribute__((unused))
1128 pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
1129 {
1130 #ifdef __NR_wait4
1131 	return my_syscall4(__NR_wait4, pid, status, options, rusage);
1132 #else
1133 	return -ENOSYS;
1134 #endif
1135 }
1136 
1137 static __attribute__((unused))
1138 pid_t wait(int *status)
1139 {
1140 	return __sysret(sys_wait4(-1, status, 0, NULL));
1141 }
1142 
1143 static __attribute__((unused))
1144 pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage)
1145 {
1146 	return __sysret(sys_wait4(pid, status, options, rusage));
1147 }
1148 
1149 
1150 static __attribute__((unused))
1151 pid_t waitpid(pid_t pid, int *status, int options)
1152 {
1153 	return __sysret(sys_wait4(pid, status, options, NULL));
1154 }
1155 
1156 
1157 /*
1158  * ssize_t write(int fd, const void *buf, size_t count);
1159  */
1160 
1161 static __attribute__((unused))
1162 ssize_t sys_write(int fd, const void *buf, size_t count)
1163 {
1164 	return my_syscall3(__NR_write, fd, buf, count);
1165 }
1166 
1167 static __attribute__((unused))
1168 ssize_t write(int fd, const void *buf, size_t count)
1169 {
1170 	return __sysret(sys_write(fd, buf, count));
1171 }
1172 
1173 
1174 /*
1175  * int memfd_create(const char *name, unsigned int flags);
1176  */
1177 
1178 static __attribute__((unused))
1179 int sys_memfd_create(const char *name, unsigned int flags)
1180 {
1181 	return my_syscall2(__NR_memfd_create, name, flags);
1182 }
1183 
1184 static __attribute__((unused))
1185 int memfd_create(const char *name, unsigned int flags)
1186 {
1187 	return __sysret(sys_memfd_create(name, flags));
1188 }
1189 
1190 /* make sure to include all global symbols */
1191 #include "nolibc.h"
1192 
1193 #endif /* _NOLIBC_SYS_H */
1194