Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
57static __attribute__((unused))
58void *sys_brk(void *addr)
59{
60 return (void *)my_syscall1(__NR_brk, addr);
61}
62
63static __attribute__((unused))
64int 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
75static __attribute__((unused))
76void *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
93static __attribute__((unused))
94int sys_chdir(const char *path)
95{
96 return my_syscall1(__NR_chdir, path);
97}
98
99static __attribute__((unused))
100int 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
116static __attribute__((unused))
117int 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
128static __attribute__((unused))
129int 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
145static __attribute__((unused))
146int 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
157static __attribute__((unused))
158int 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
174static __attribute__((unused))
175int sys_chroot(const char *path)
176{
177 return my_syscall1(__NR_chroot, path);
178}
179
180static __attribute__((unused))
181int 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
197static __attribute__((unused))
198int sys_close(int fd)
199{
200 return my_syscall1(__NR_close, fd);
201}
202
203static __attribute__((unused))
204int 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
220static __attribute__((unused))
221int sys_dup(int fd)
222{
223 return my_syscall1(__NR_dup, fd);
224}
225
226static __attribute__((unused))
227int 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
243static __attribute__((unused))
244int 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
255static __attribute__((unused))
256int 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
273static __attribute__((unused))
274int sys_dup3(int old, int new, int flags)
275{
276 return my_syscall3(__NR_dup3, old, new, flags);
277}
278
279static __attribute__((unused))
280int 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
297static __attribute__((unused))
298int sys_execve(const char *filename, char *const argv[], char *const envp[])
299{
300 return my_syscall3(__NR_execve, filename, argv, envp);
301}
302
303static __attribute__((unused))
304int 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
320static __attribute__((noreturn,unused))
321void sys_exit(int status)
322{
323 my_syscall1(__NR_exit, status & 255);
324 while(1); // shut the "noreturn" warnings.
325}
326
327static __attribute__((noreturn,unused))
328void exit(int status)
329{
330 sys_exit(status);
331}
332
333
334/*
335 * pid_t fork(void);
336 */
337
338static __attribute__((unused))
339pid_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
354static __attribute__((unused))
355pid_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
371static __attribute__((unused))
372int sys_fsync(int fd)
373{
374 return my_syscall1(__NR_fsync, fd);
375}
376
377static __attribute__((unused))
378int 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
394static __attribute__((unused))
395int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count)
396{
397 return my_syscall3(__NR_getdents64, fd, dirp, count);
398}
399
400static __attribute__((unused))
401int 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
417static __attribute__((unused))
418pid_t sys_getpgid(pid_t pid)
419{
420 return my_syscall1(__NR_getpgid, pid);
421}
422
423static __attribute__((unused))
424pid_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
440static __attribute__((unused))
441pid_t sys_getpgrp(void)
442{
443 return sys_getpgid(0);
444}
445
446static __attribute__((unused))
447pid_t getpgrp(void)
448{
449 return sys_getpgrp();
450}
451
452
453/*
454 * pid_t getpid(void);
455 */
456
457static __attribute__((unused))
458pid_t sys_getpid(void)
459{
460 return my_syscall0(__NR_getpid);
461}
462
463static __attribute__((unused))
464pid_t getpid(void)
465{
466 return sys_getpid();
467}
468
469
470/*
471 * pid_t getppid(void);
472 */
473
474static __attribute__((unused))
475pid_t sys_getppid(void)
476{
477 return my_syscall0(__NR_getppid);
478}
479
480static __attribute__((unused))
481pid_t getppid(void)
482{
483 return sys_getppid();
484}
485
486
487/*
488 * pid_t gettid(void);
489 */
490
491static __attribute__((unused))
492pid_t sys_gettid(void)
493{
494 return my_syscall0(__NR_gettid);
495}
496
497static __attribute__((unused))
498pid_t gettid(void)
499{
500 return sys_gettid();
501}
502
503static unsigned long getauxval(unsigned long key);
504
505/*
506 * long getpagesize(void);
507 */
508
509static __attribute__((unused))
510long 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
528static __attribute__((unused))
529int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
530{
531 return my_syscall2(__NR_gettimeofday, tv, tz);
532}
533
534static __attribute__((unused))
535int 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
551static __attribute__((unused))
552int sys_ioctl(int fd, unsigned long req, void *value)
553{
554 return my_syscall3(__NR_ioctl, fd, req, value);
555}
556
557static __attribute__((unused))
558int 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
573static __attribute__((unused))
574int sys_kill(pid_t pid, int signal)
575{
576 return my_syscall2(__NR_kill, pid, signal);
577}
578
579static __attribute__((unused))
580int 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
596static __attribute__((unused))
597int 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
608static __attribute__((unused))
609int 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
625static __attribute__((unused))
626off_t sys_lseek(int fd, off_t offset, int whence)
627{
628 return my_syscall3(__NR_lseek, fd, offset, whence);
629}
630
631static __attribute__((unused))
632off_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
648static __attribute__((unused))
649int 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
660static __attribute__((unused))
661int 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
677static __attribute__((unused))
678long 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
689static __attribute__((unused))
690int 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
712static __attribute__((unused))
713void *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
735static __attribute__((unused))
736void *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
747static __attribute__((unused))
748int sys_munmap(void *addr, size_t length)
749{
750 return my_syscall2(__NR_munmap, addr, length);
751}
752
753static __attribute__((unused))
754int 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 */
770static __attribute__((unused))
771int 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
777static __attribute__((unused))
778int 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
796static __attribute__((unused))
797int 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
808static __attribute__((unused))
809int 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
836static __attribute__((unused))
837int sys_pivot_root(const char *new, const char *old)
838{
839 return my_syscall2(__NR_pivot_root, new, old);
840}
841
842static __attribute__((unused))
843int 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
859static __attribute__((unused))
860int 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
877static __attribute__((unused))
878int 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
894static __attribute__((unused))
895ssize_t sys_read(int fd, void *buf, size_t count)
896{
897 return my_syscall3(__NR_read, fd, buf, count);
898}
899
900static __attribute__((unused))
901ssize_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
918static __attribute__((unused))
919ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg)
920{
921 return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg);
922}
923
924static __attribute__((unused))
925int 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
941static __attribute__((unused))
942int sys_sched_yield(void)
943{
944 return my_syscall0(__NR_sched_yield);
945}
946
947static __attribute__((unused))
948int 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
965static __attribute__((unused))
966int 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
993static __attribute__((unused))
994int 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
1010static __attribute__((unused))
1011int sys_setpgid(pid_t pid, pid_t pgid)
1012{
1013 return my_syscall2(__NR_setpgid, pid, pgid);
1014}
1015
1016static __attribute__((unused))
1017int 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
1033static __attribute__((unused))
1034pid_t sys_setsid(void)
1035{
1036 return my_syscall0(__NR_setsid);
1037}
1038
1039static __attribute__((unused))
1040pid_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
1057static __attribute__((unused))
1058int 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
1087static __attribute__((unused))
1088int 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
1104static __attribute__((unused))
1105int 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
1116static __attribute__((unused))
1117int 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
1133static __attribute__((unused))
1134mode_t sys_umask(mode_t mode)
1135{
1136 return my_syscall1(__NR_umask, mode);
1137}
1138
1139static __attribute__((unused))
1140mode_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
1150static __attribute__((unused))
1151int sys_umount2(const char *path, int flags)
1152{
1153 return my_syscall2(__NR_umount2, path, flags);
1154}
1155
1156static __attribute__((unused))
1157int 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
1173static __attribute__((unused))
1174int 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
1185static __attribute__((unused))
1186int 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
1204static __attribute__((unused))
1205pid_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
1210static __attribute__((unused))
1211pid_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
1222static __attribute__((unused))
1223pid_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
1235static __attribute__((unused))
1236pid_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
1252static __attribute__((unused))
1253ssize_t sys_write(int fd, const void *buf, size_t count)
1254{
1255 return my_syscall3(__NR_write, fd, buf, count);
1256}
1257
1258static __attribute__((unused))
1259ssize_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 */