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