xref: /openbmc/linux/tools/include/nolibc/sys.h (revision 12109610)
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 static __attribute__((unused))
340 pid_t sys_fork(void)
341 {
342 #ifdef __NR_clone
343 	/* note: some archs only have clone() and not fork(). Different archs
344 	 * have a different API, but most archs have the flags on first arg and
345 	 * will not use the rest with no other flag.
346 	 */
347 	return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0);
348 #elif defined(__NR_fork)
349 	return my_syscall0(__NR_fork);
350 #else
351 #error Neither __NR_clone nor __NR_fork defined, cannot implement sys_fork()
352 #endif
353 }
354 
355 static __attribute__((unused))
356 pid_t fork(void)
357 {
358 	pid_t ret = sys_fork();
359 
360 	if (ret < 0) {
361 		SET_ERRNO(-ret);
362 		ret = -1;
363 	}
364 	return ret;
365 }
366 
367 
368 /*
369  * int fsync(int fd);
370  */
371 
372 static __attribute__((unused))
373 int sys_fsync(int fd)
374 {
375 	return my_syscall1(__NR_fsync, fd);
376 }
377 
378 static __attribute__((unused))
379 int fsync(int fd)
380 {
381 	int ret = sys_fsync(fd);
382 
383 	if (ret < 0) {
384 		SET_ERRNO(-ret);
385 		ret = -1;
386 	}
387 	return ret;
388 }
389 
390 
391 /*
392  * int getdents64(int fd, struct linux_dirent64 *dirp, int count);
393  */
394 
395 static __attribute__((unused))
396 int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count)
397 {
398 	return my_syscall3(__NR_getdents64, fd, dirp, count);
399 }
400 
401 static __attribute__((unused))
402 int getdents64(int fd, struct linux_dirent64 *dirp, int count)
403 {
404 	int ret = sys_getdents64(fd, dirp, count);
405 
406 	if (ret < 0) {
407 		SET_ERRNO(-ret);
408 		ret = -1;
409 	}
410 	return ret;
411 }
412 
413 
414 /*
415  * uid_t geteuid(void);
416  */
417 
418 static __attribute__((unused))
419 uid_t sys_geteuid(void)
420 {
421 #ifdef __NR_geteuid32
422 	return my_syscall0(__NR_geteuid32);
423 #else
424 	return my_syscall0(__NR_geteuid);
425 #endif
426 }
427 
428 static __attribute__((unused))
429 uid_t geteuid(void)
430 {
431 	return sys_geteuid();
432 }
433 
434 
435 /*
436  * pid_t getpgid(pid_t pid);
437  */
438 
439 static __attribute__((unused))
440 pid_t sys_getpgid(pid_t pid)
441 {
442 	return my_syscall1(__NR_getpgid, pid);
443 }
444 
445 static __attribute__((unused))
446 pid_t getpgid(pid_t pid)
447 {
448 	pid_t ret = sys_getpgid(pid);
449 
450 	if (ret < 0) {
451 		SET_ERRNO(-ret);
452 		ret = -1;
453 	}
454 	return ret;
455 }
456 
457 
458 /*
459  * pid_t getpgrp(void);
460  */
461 
462 static __attribute__((unused))
463 pid_t sys_getpgrp(void)
464 {
465 	return sys_getpgid(0);
466 }
467 
468 static __attribute__((unused))
469 pid_t getpgrp(void)
470 {
471 	return sys_getpgrp();
472 }
473 
474 
475 /*
476  * pid_t getpid(void);
477  */
478 
479 static __attribute__((unused))
480 pid_t sys_getpid(void)
481 {
482 	return my_syscall0(__NR_getpid);
483 }
484 
485 static __attribute__((unused))
486 pid_t getpid(void)
487 {
488 	return sys_getpid();
489 }
490 
491 
492 /*
493  * pid_t getppid(void);
494  */
495 
496 static __attribute__((unused))
497 pid_t sys_getppid(void)
498 {
499 	return my_syscall0(__NR_getppid);
500 }
501 
502 static __attribute__((unused))
503 pid_t getppid(void)
504 {
505 	return sys_getppid();
506 }
507 
508 
509 /*
510  * pid_t gettid(void);
511  */
512 
513 static __attribute__((unused))
514 pid_t sys_gettid(void)
515 {
516 	return my_syscall0(__NR_gettid);
517 }
518 
519 static __attribute__((unused))
520 pid_t gettid(void)
521 {
522 	return sys_gettid();
523 }
524 
525 static unsigned long getauxval(unsigned long key);
526 
527 /*
528  * long getpagesize(void);
529  */
530 
531 static __attribute__((unused))
532 long getpagesize(void)
533 {
534 	long ret;
535 
536 	ret = getauxval(AT_PAGESZ);
537 	if (!ret) {
538 		SET_ERRNO(ENOENT);
539 		return -1;
540 	}
541 
542 	return ret;
543 }
544 
545 
546 /*
547  * int gettimeofday(struct timeval *tv, struct timezone *tz);
548  */
549 
550 static __attribute__((unused))
551 int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
552 {
553 	return my_syscall2(__NR_gettimeofday, tv, tz);
554 }
555 
556 static __attribute__((unused))
557 int gettimeofday(struct timeval *tv, struct timezone *tz)
558 {
559 	int ret = sys_gettimeofday(tv, tz);
560 
561 	if (ret < 0) {
562 		SET_ERRNO(-ret);
563 		ret = -1;
564 	}
565 	return ret;
566 }
567 
568 
569 /*
570  * uid_t getuid(void);
571  */
572 
573 static __attribute__((unused))
574 uid_t sys_getuid(void)
575 {
576 #ifdef __NR_getuid32
577 	return my_syscall0(__NR_getuid32);
578 #else
579 	return my_syscall0(__NR_getuid);
580 #endif
581 }
582 
583 static __attribute__((unused))
584 uid_t getuid(void)
585 {
586 	return sys_getuid();
587 }
588 
589 
590 /*
591  * int ioctl(int fd, unsigned long req, void *value);
592  */
593 
594 static __attribute__((unused))
595 int sys_ioctl(int fd, unsigned long req, void *value)
596 {
597 	return my_syscall3(__NR_ioctl, fd, req, value);
598 }
599 
600 static __attribute__((unused))
601 int ioctl(int fd, unsigned long req, void *value)
602 {
603 	int ret = sys_ioctl(fd, req, value);
604 
605 	if (ret < 0) {
606 		SET_ERRNO(-ret);
607 		ret = -1;
608 	}
609 	return ret;
610 }
611 
612 /*
613  * int kill(pid_t pid, int signal);
614  */
615 
616 static __attribute__((unused))
617 int sys_kill(pid_t pid, int signal)
618 {
619 	return my_syscall2(__NR_kill, pid, signal);
620 }
621 
622 static __attribute__((unused))
623 int kill(pid_t pid, int signal)
624 {
625 	int ret = sys_kill(pid, signal);
626 
627 	if (ret < 0) {
628 		SET_ERRNO(-ret);
629 		ret = -1;
630 	}
631 	return ret;
632 }
633 
634 
635 /*
636  * int link(const char *old, const char *new);
637  */
638 
639 static __attribute__((unused))
640 int sys_link(const char *old, const char *new)
641 {
642 #ifdef __NR_linkat
643 	return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0);
644 #elif defined(__NR_link)
645 	return my_syscall2(__NR_link, old, new);
646 #else
647 #error Neither __NR_linkat nor __NR_link defined, cannot implement sys_link()
648 #endif
649 }
650 
651 static __attribute__((unused))
652 int link(const char *old, const char *new)
653 {
654 	int ret = sys_link(old, new);
655 
656 	if (ret < 0) {
657 		SET_ERRNO(-ret);
658 		ret = -1;
659 	}
660 	return ret;
661 }
662 
663 
664 /*
665  * off_t lseek(int fd, off_t offset, int whence);
666  */
667 
668 static __attribute__((unused))
669 off_t sys_lseek(int fd, off_t offset, int whence)
670 {
671 	return my_syscall3(__NR_lseek, fd, offset, whence);
672 }
673 
674 static __attribute__((unused))
675 off_t lseek(int fd, off_t offset, int whence)
676 {
677 	off_t ret = sys_lseek(fd, offset, whence);
678 
679 	if (ret < 0) {
680 		SET_ERRNO(-ret);
681 		ret = -1;
682 	}
683 	return ret;
684 }
685 
686 
687 /*
688  * int mkdir(const char *path, mode_t mode);
689  */
690 
691 static __attribute__((unused))
692 int sys_mkdir(const char *path, mode_t mode)
693 {
694 #ifdef __NR_mkdirat
695 	return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode);
696 #elif defined(__NR_mkdir)
697 	return my_syscall2(__NR_mkdir, path, mode);
698 #else
699 #error Neither __NR_mkdirat nor __NR_mkdir defined, cannot implement sys_mkdir()
700 #endif
701 }
702 
703 static __attribute__((unused))
704 int mkdir(const char *path, mode_t mode)
705 {
706 	int ret = sys_mkdir(path, mode);
707 
708 	if (ret < 0) {
709 		SET_ERRNO(-ret);
710 		ret = -1;
711 	}
712 	return ret;
713 }
714 
715 
716 /*
717  * int mknod(const char *path, mode_t mode, dev_t dev);
718  */
719 
720 static __attribute__((unused))
721 long sys_mknod(const char *path, mode_t mode, dev_t dev)
722 {
723 #ifdef __NR_mknodat
724 	return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev);
725 #elif defined(__NR_mknod)
726 	return my_syscall3(__NR_mknod, path, mode, dev);
727 #else
728 #error Neither __NR_mknodat nor __NR_mknod defined, cannot implement sys_mknod()
729 #endif
730 }
731 
732 static __attribute__((unused))
733 int mknod(const char *path, mode_t mode, dev_t dev)
734 {
735 	int ret = sys_mknod(path, mode, dev);
736 
737 	if (ret < 0) {
738 		SET_ERRNO(-ret);
739 		ret = -1;
740 	}
741 	return ret;
742 }
743 
744 #ifndef MAP_SHARED
745 #define MAP_SHARED		0x01	/* Share changes */
746 #define MAP_PRIVATE		0x02	/* Changes are private */
747 #define MAP_SHARED_VALIDATE	0x03	/* share + validate extension flags */
748 #endif
749 
750 #ifndef MAP_FAILED
751 #define MAP_FAILED ((void *)-1)
752 #endif
753 
754 #ifndef sys_mmap
755 static __attribute__((unused))
756 void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd,
757 	       off_t offset)
758 {
759 #ifndef my_syscall6
760 	/* Function not implemented. */
761 	return (void *)-ENOSYS;
762 #else
763 
764 	int n;
765 
766 #if defined(__NR_mmap2)
767 	n = __NR_mmap2;
768 	offset >>= 12;
769 #else
770 	n = __NR_mmap;
771 #endif
772 
773 	return (void *)my_syscall6(n, addr, length, prot, flags, fd, offset);
774 #endif
775 }
776 #endif
777 
778 static __attribute__((unused))
779 void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
780 {
781 	void *ret = sys_mmap(addr, length, prot, flags, fd, offset);
782 
783 	if ((unsigned long)ret >= -4095UL) {
784 		SET_ERRNO(-(long)ret);
785 		ret = MAP_FAILED;
786 	}
787 	return ret;
788 }
789 
790 static __attribute__((unused))
791 int sys_munmap(void *addr, size_t length)
792 {
793 	return my_syscall2(__NR_munmap, addr, length);
794 }
795 
796 static __attribute__((unused))
797 int munmap(void *addr, size_t length)
798 {
799 	int ret = sys_munmap(addr, length);
800 
801 	if (ret < 0) {
802 		SET_ERRNO(-ret);
803 		ret = -1;
804 	}
805 	return ret;
806 }
807 
808 /*
809  * int mount(const char *source, const char *target,
810  *           const char *fstype, unsigned long flags,
811  *           const void *data);
812  */
813 static __attribute__((unused))
814 int sys_mount(const char *src, const char *tgt, const char *fst,
815                      unsigned long flags, const void *data)
816 {
817 	return my_syscall5(__NR_mount, src, tgt, fst, flags, data);
818 }
819 
820 static __attribute__((unused))
821 int mount(const char *src, const char *tgt,
822           const char *fst, unsigned long flags,
823           const void *data)
824 {
825 	int ret = sys_mount(src, tgt, fst, flags, data);
826 
827 	if (ret < 0) {
828 		SET_ERRNO(-ret);
829 		ret = -1;
830 	}
831 	return ret;
832 }
833 
834 
835 /*
836  * int open(const char *path, int flags[, mode_t mode]);
837  */
838 
839 static __attribute__((unused))
840 int sys_open(const char *path, int flags, mode_t mode)
841 {
842 #ifdef __NR_openat
843 	return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode);
844 #elif defined(__NR_open)
845 	return my_syscall3(__NR_open, path, flags, mode);
846 #else
847 #error Neither __NR_openat nor __NR_open defined, cannot implement sys_open()
848 #endif
849 }
850 
851 static __attribute__((unused))
852 int open(const char *path, int flags, ...)
853 {
854 	mode_t mode = 0;
855 	int ret;
856 
857 	if (flags & O_CREAT) {
858 		va_list args;
859 
860 		va_start(args, flags);
861 		mode = va_arg(args, mode_t);
862 		va_end(args);
863 	}
864 
865 	ret = sys_open(path, flags, mode);
866 
867 	if (ret < 0) {
868 		SET_ERRNO(-ret);
869 		ret = -1;
870 	}
871 	return ret;
872 }
873 
874 
875 /*
876  * int pivot_root(const char *new, const char *old);
877  */
878 
879 static __attribute__((unused))
880 int sys_pivot_root(const char *new, const char *old)
881 {
882 	return my_syscall2(__NR_pivot_root, new, old);
883 }
884 
885 static __attribute__((unused))
886 int pivot_root(const char *new, const char *old)
887 {
888 	int ret = sys_pivot_root(new, old);
889 
890 	if (ret < 0) {
891 		SET_ERRNO(-ret);
892 		ret = -1;
893 	}
894 	return ret;
895 }
896 
897 
898 /*
899  * int poll(struct pollfd *fds, int nfds, int timeout);
900  */
901 
902 static __attribute__((unused))
903 int sys_poll(struct pollfd *fds, int nfds, int timeout)
904 {
905 #if defined(__NR_ppoll)
906 	struct timespec t;
907 
908 	if (timeout >= 0) {
909 		t.tv_sec  = timeout / 1000;
910 		t.tv_nsec = (timeout % 1000) * 1000000;
911 	}
912 	return my_syscall4(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL);
913 #elif defined(__NR_poll)
914 	return my_syscall3(__NR_poll, fds, nfds, timeout);
915 #else
916 #error Neither __NR_ppoll nor __NR_poll defined, cannot implement sys_poll()
917 #endif
918 }
919 
920 static __attribute__((unused))
921 int poll(struct pollfd *fds, int nfds, int timeout)
922 {
923 	int ret = sys_poll(fds, nfds, timeout);
924 
925 	if (ret < 0) {
926 		SET_ERRNO(-ret);
927 		ret = -1;
928 	}
929 	return ret;
930 }
931 
932 
933 /*
934  * ssize_t read(int fd, void *buf, size_t count);
935  */
936 
937 static __attribute__((unused))
938 ssize_t sys_read(int fd, void *buf, size_t count)
939 {
940 	return my_syscall3(__NR_read, fd, buf, count);
941 }
942 
943 static __attribute__((unused))
944 ssize_t read(int fd, void *buf, size_t count)
945 {
946 	ssize_t ret = sys_read(fd, buf, count);
947 
948 	if (ret < 0) {
949 		SET_ERRNO(-ret);
950 		ret = -1;
951 	}
952 	return ret;
953 }
954 
955 
956 /*
957  * int reboot(int cmd);
958  * <cmd> is among LINUX_REBOOT_CMD_*
959  */
960 
961 static __attribute__((unused))
962 ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg)
963 {
964 	return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg);
965 }
966 
967 static __attribute__((unused))
968 int reboot(int cmd)
969 {
970 	int ret = sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0);
971 
972 	if (ret < 0) {
973 		SET_ERRNO(-ret);
974 		ret = -1;
975 	}
976 	return ret;
977 }
978 
979 
980 /*
981  * int sched_yield(void);
982  */
983 
984 static __attribute__((unused))
985 int sys_sched_yield(void)
986 {
987 	return my_syscall0(__NR_sched_yield);
988 }
989 
990 static __attribute__((unused))
991 int sched_yield(void)
992 {
993 	int ret = sys_sched_yield();
994 
995 	if (ret < 0) {
996 		SET_ERRNO(-ret);
997 		ret = -1;
998 	}
999 	return ret;
1000 }
1001 
1002 
1003 /*
1004  * int select(int nfds, fd_set *read_fds, fd_set *write_fds,
1005  *            fd_set *except_fds, struct timeval *timeout);
1006  */
1007 
1008 static __attribute__((unused))
1009 int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
1010 {
1011 #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect)
1012 	struct sel_arg_struct {
1013 		unsigned long n;
1014 		fd_set *r, *w, *e;
1015 		struct timeval *t;
1016 	} arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout };
1017 	return my_syscall1(__NR_select, &arg);
1018 #elif defined(__ARCH_WANT_SYS_PSELECT6) && defined(__NR_pselect6)
1019 	struct timespec t;
1020 
1021 	if (timeout) {
1022 		t.tv_sec  = timeout->tv_sec;
1023 		t.tv_nsec = timeout->tv_usec * 1000;
1024 	}
1025 	return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
1026 #elif defined(__NR__newselect) || defined(__NR_select)
1027 #ifndef __NR__newselect
1028 #define __NR__newselect __NR_select
1029 #endif
1030 	return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout);
1031 #else
1032 #error None of __NR_select, __NR_pselect6, nor __NR__newselect defined, cannot implement sys_select()
1033 #endif
1034 }
1035 
1036 static __attribute__((unused))
1037 int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
1038 {
1039 	int ret = sys_select(nfds, rfds, wfds, efds, timeout);
1040 
1041 	if (ret < 0) {
1042 		SET_ERRNO(-ret);
1043 		ret = -1;
1044 	}
1045 	return ret;
1046 }
1047 
1048 
1049 /*
1050  * int setpgid(pid_t pid, pid_t pgid);
1051  */
1052 
1053 static __attribute__((unused))
1054 int sys_setpgid(pid_t pid, pid_t pgid)
1055 {
1056 	return my_syscall2(__NR_setpgid, pid, pgid);
1057 }
1058 
1059 static __attribute__((unused))
1060 int setpgid(pid_t pid, pid_t pgid)
1061 {
1062 	int ret = sys_setpgid(pid, pgid);
1063 
1064 	if (ret < 0) {
1065 		SET_ERRNO(-ret);
1066 		ret = -1;
1067 	}
1068 	return ret;
1069 }
1070 
1071 
1072 /*
1073  * pid_t setsid(void);
1074  */
1075 
1076 static __attribute__((unused))
1077 pid_t sys_setsid(void)
1078 {
1079 	return my_syscall0(__NR_setsid);
1080 }
1081 
1082 static __attribute__((unused))
1083 pid_t setsid(void)
1084 {
1085 	pid_t ret = sys_setsid();
1086 
1087 	if (ret < 0) {
1088 		SET_ERRNO(-ret);
1089 		ret = -1;
1090 	}
1091 	return ret;
1092 }
1093 
1094 #if defined(__NR_statx)
1095 /*
1096  * int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf);
1097  */
1098 
1099 static __attribute__((unused))
1100 int sys_statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf)
1101 {
1102 	return my_syscall5(__NR_statx, fd, path, flags, mask, buf);
1103 }
1104 
1105 static __attribute__((unused))
1106 int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf)
1107 {
1108 	int ret = sys_statx(fd, path, flags, mask, buf);
1109 
1110 	if (ret < 0) {
1111 		SET_ERRNO(-ret);
1112 		ret = -1;
1113 	}
1114 	return ret;
1115 }
1116 #endif
1117 
1118 /*
1119  * int stat(const char *path, struct stat *buf);
1120  * Warning: the struct stat's layout is arch-dependent.
1121  */
1122 
1123 #if defined(__NR_statx) && !defined(__NR_newfstatat) && !defined(__NR_stat)
1124 /*
1125  * Maybe we can just use statx() when available for all architectures?
1126  */
1127 static __attribute__((unused))
1128 int sys_stat(const char *path, struct stat *buf)
1129 {
1130 	struct statx statx;
1131 	long ret;
1132 
1133 	ret = sys_statx(AT_FDCWD, path, AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &statx);
1134 	buf->st_dev     = ((statx.stx_dev_minor & 0xff)
1135 			  | (statx.stx_dev_major << 8)
1136 			  | ((statx.stx_dev_minor & ~0xff) << 12));
1137 	buf->st_ino     = statx.stx_ino;
1138 	buf->st_mode    = statx.stx_mode;
1139 	buf->st_nlink   = statx.stx_nlink;
1140 	buf->st_uid     = statx.stx_uid;
1141 	buf->st_gid     = statx.stx_gid;
1142 	buf->st_rdev    = ((statx.stx_rdev_minor & 0xff)
1143 			  | (statx.stx_rdev_major << 8)
1144 			  | ((statx.stx_rdev_minor & ~0xff) << 12));
1145 	buf->st_size    = statx.stx_size;
1146 	buf->st_blksize = statx.stx_blksize;
1147 	buf->st_blocks  = statx.stx_blocks;
1148 	buf->st_atime   = statx.stx_atime.tv_sec;
1149 	buf->st_mtime   = statx.stx_mtime.tv_sec;
1150 	buf->st_ctime   = statx.stx_ctime.tv_sec;
1151 	return ret;
1152 }
1153 #else
1154 static __attribute__((unused))
1155 int sys_stat(const char *path, struct stat *buf)
1156 {
1157 	struct sys_stat_struct stat;
1158 	long ret;
1159 
1160 #ifdef __NR_newfstatat
1161 	/* only solution for arm64 */
1162 	ret = my_syscall4(__NR_newfstatat, AT_FDCWD, path, &stat, 0);
1163 #elif defined(__NR_stat)
1164 	ret = my_syscall2(__NR_stat, path, &stat);
1165 #else
1166 #error Neither __NR_newfstatat nor __NR_stat defined, cannot implement sys_stat()
1167 #endif
1168 	buf->st_dev     = stat.st_dev;
1169 	buf->st_ino     = stat.st_ino;
1170 	buf->st_mode    = stat.st_mode;
1171 	buf->st_nlink   = stat.st_nlink;
1172 	buf->st_uid     = stat.st_uid;
1173 	buf->st_gid     = stat.st_gid;
1174 	buf->st_rdev    = stat.st_rdev;
1175 	buf->st_size    = stat.st_size;
1176 	buf->st_blksize = stat.st_blksize;
1177 	buf->st_blocks  = stat.st_blocks;
1178 	buf->st_atime   = stat.st_atime;
1179 	buf->st_mtime   = stat.st_mtime;
1180 	buf->st_ctime   = stat.st_ctime;
1181 	return ret;
1182 }
1183 #endif
1184 
1185 static __attribute__((unused))
1186 int stat(const char *path, struct stat *buf)
1187 {
1188 	int ret = sys_stat(path, buf);
1189 
1190 	if (ret < 0) {
1191 		SET_ERRNO(-ret);
1192 		ret = -1;
1193 	}
1194 	return ret;
1195 }
1196 
1197 
1198 /*
1199  * int symlink(const char *old, const char *new);
1200  */
1201 
1202 static __attribute__((unused))
1203 int sys_symlink(const char *old, const char *new)
1204 {
1205 #ifdef __NR_symlinkat
1206 	return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new);
1207 #elif defined(__NR_symlink)
1208 	return my_syscall2(__NR_symlink, old, new);
1209 #else
1210 #error Neither __NR_symlinkat nor __NR_symlink defined, cannot implement sys_symlink()
1211 #endif
1212 }
1213 
1214 static __attribute__((unused))
1215 int symlink(const char *old, const char *new)
1216 {
1217 	int ret = sys_symlink(old, new);
1218 
1219 	if (ret < 0) {
1220 		SET_ERRNO(-ret);
1221 		ret = -1;
1222 	}
1223 	return ret;
1224 }
1225 
1226 
1227 /*
1228  * mode_t umask(mode_t mode);
1229  */
1230 
1231 static __attribute__((unused))
1232 mode_t sys_umask(mode_t mode)
1233 {
1234 	return my_syscall1(__NR_umask, mode);
1235 }
1236 
1237 static __attribute__((unused))
1238 mode_t umask(mode_t mode)
1239 {
1240 	return sys_umask(mode);
1241 }
1242 
1243 
1244 /*
1245  * int umount2(const char *path, int flags);
1246  */
1247 
1248 static __attribute__((unused))
1249 int sys_umount2(const char *path, int flags)
1250 {
1251 	return my_syscall2(__NR_umount2, path, flags);
1252 }
1253 
1254 static __attribute__((unused))
1255 int umount2(const char *path, int flags)
1256 {
1257 	int ret = sys_umount2(path, flags);
1258 
1259 	if (ret < 0) {
1260 		SET_ERRNO(-ret);
1261 		ret = -1;
1262 	}
1263 	return ret;
1264 }
1265 
1266 
1267 /*
1268  * int unlink(const char *path);
1269  */
1270 
1271 static __attribute__((unused))
1272 int sys_unlink(const char *path)
1273 {
1274 #ifdef __NR_unlinkat
1275 	return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0);
1276 #elif defined(__NR_unlink)
1277 	return my_syscall1(__NR_unlink, path);
1278 #else
1279 #error Neither __NR_unlinkat nor __NR_unlink defined, cannot implement sys_unlink()
1280 #endif
1281 }
1282 
1283 static __attribute__((unused))
1284 int unlink(const char *path)
1285 {
1286 	int ret = sys_unlink(path);
1287 
1288 	if (ret < 0) {
1289 		SET_ERRNO(-ret);
1290 		ret = -1;
1291 	}
1292 	return ret;
1293 }
1294 
1295 
1296 /*
1297  * pid_t wait(int *status);
1298  * pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);
1299  * pid_t waitpid(pid_t pid, int *status, int options);
1300  */
1301 
1302 static __attribute__((unused))
1303 pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
1304 {
1305 	return my_syscall4(__NR_wait4, pid, status, options, rusage);
1306 }
1307 
1308 static __attribute__((unused))
1309 pid_t wait(int *status)
1310 {
1311 	pid_t ret = sys_wait4(-1, status, 0, NULL);
1312 
1313 	if (ret < 0) {
1314 		SET_ERRNO(-ret);
1315 		ret = -1;
1316 	}
1317 	return ret;
1318 }
1319 
1320 static __attribute__((unused))
1321 pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage)
1322 {
1323 	pid_t ret = sys_wait4(pid, status, options, rusage);
1324 
1325 	if (ret < 0) {
1326 		SET_ERRNO(-ret);
1327 		ret = -1;
1328 	}
1329 	return ret;
1330 }
1331 
1332 
1333 static __attribute__((unused))
1334 pid_t waitpid(pid_t pid, int *status, int options)
1335 {
1336 	pid_t ret = sys_wait4(pid, status, options, NULL);
1337 
1338 	if (ret < 0) {
1339 		SET_ERRNO(-ret);
1340 		ret = -1;
1341 	}
1342 	return ret;
1343 }
1344 
1345 
1346 /*
1347  * ssize_t write(int fd, const void *buf, size_t count);
1348  */
1349 
1350 static __attribute__((unused))
1351 ssize_t sys_write(int fd, const void *buf, size_t count)
1352 {
1353 	return my_syscall3(__NR_write, fd, buf, count);
1354 }
1355 
1356 static __attribute__((unused))
1357 ssize_t write(int fd, const void *buf, size_t count)
1358 {
1359 	ssize_t ret = sys_write(fd, buf, count);
1360 
1361 	if (ret < 0) {
1362 		SET_ERRNO(-ret);
1363 		ret = -1;
1364 	}
1365 	return ret;
1366 }
1367 
1368 /* make sure to include all global symbols */
1369 #include "nolibc.h"
1370 
1371 #endif /* _NOLIBC_SYS_H */
1372