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