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