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