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