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/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
58static __attribute__((unused))
59void *sys_brk(void *addr)
60{
61 return (void *)my_syscall1(__NR_brk, addr);
62}
63
64static __attribute__((unused))
65int 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
76static __attribute__((unused))
77void *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
94static __attribute__((unused))
95int sys_chdir(const char *path)
96{
97 return my_syscall1(__NR_chdir, path);
98}
99
100static __attribute__((unused))
101int 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
117static __attribute__((unused))
118int 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
129static __attribute__((unused))
130int 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
146static __attribute__((unused))
147int 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
158static __attribute__((unused))
159int 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
175static __attribute__((unused))
176int sys_chroot(const char *path)
177{
178 return my_syscall1(__NR_chroot, path);
179}
180
181static __attribute__((unused))
182int 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
198static __attribute__((unused))
199int sys_close(int fd)
200{
201 return my_syscall1(__NR_close, fd);
202}
203
204static __attribute__((unused))
205int 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
221static __attribute__((unused))
222int sys_dup(int fd)
223{
224 return my_syscall1(__NR_dup, fd);
225}
226
227static __attribute__((unused))
228int 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
244static __attribute__((unused))
245int 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
256static __attribute__((unused))
257int 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
274static __attribute__((unused))
275int sys_dup3(int old, int new, int flags)
276{
277 return my_syscall3(__NR_dup3, old, new, flags);
278}
279
280static __attribute__((unused))
281int 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
298static __attribute__((unused))
299int sys_execve(const char *filename, char *const argv[], char *const envp[])
300{
301 return my_syscall3(__NR_execve, filename, argv, envp);
302}
303
304static __attribute__((unused))
305int 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
321static __attribute__((noreturn,unused))
322void sys_exit(int status)
323{
324 my_syscall1(__NR_exit, status & 255);
325 while(1); // shut the "noreturn" warnings.
326}
327
328static __attribute__((noreturn,unused))
329void exit(int status)
330{
331 sys_exit(status);
332}
333
334
335/*
336 * pid_t fork(void);
337 */
338
339static __attribute__((unused))
340pid_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
355static __attribute__((unused))
356pid_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
372static __attribute__((unused))
373int sys_fsync(int fd)
374{
375 return my_syscall1(__NR_fsync, fd);
376}
377
378static __attribute__((unused))
379int 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
395static __attribute__((unused))
396int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count)
397{
398 return my_syscall3(__NR_getdents64, fd, dirp, count);
399}
400
401static __attribute__((unused))
402int 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
418static __attribute__((unused))
419uid_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
428static __attribute__((unused))
429uid_t geteuid(void)
430{
431 return sys_geteuid();
432}
433
434
435/*
436 * pid_t getpgid(pid_t pid);
437 */
438
439static __attribute__((unused))
440pid_t sys_getpgid(pid_t pid)
441{
442 return my_syscall1(__NR_getpgid, pid);
443}
444
445static __attribute__((unused))
446pid_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
462static __attribute__((unused))
463pid_t sys_getpgrp(void)
464{
465 return sys_getpgid(0);
466}
467
468static __attribute__((unused))
469pid_t getpgrp(void)
470{
471 return sys_getpgrp();
472}
473
474
475/*
476 * pid_t getpid(void);
477 */
478
479static __attribute__((unused))
480pid_t sys_getpid(void)
481{
482 return my_syscall0(__NR_getpid);
483}
484
485static __attribute__((unused))
486pid_t getpid(void)
487{
488 return sys_getpid();
489}
490
491
492/*
493 * pid_t getppid(void);
494 */
495
496static __attribute__((unused))
497pid_t sys_getppid(void)
498{
499 return my_syscall0(__NR_getppid);
500}
501
502static __attribute__((unused))
503pid_t getppid(void)
504{
505 return sys_getppid();
506}
507
508
509/*
510 * pid_t gettid(void);
511 */
512
513static __attribute__((unused))
514pid_t sys_gettid(void)
515{
516 return my_syscall0(__NR_gettid);
517}
518
519static __attribute__((unused))
520pid_t gettid(void)
521{
522 return sys_gettid();
523}
524
525static unsigned long getauxval(unsigned long key);
526
527/*
528 * long getpagesize(void);
529 */
530
531static __attribute__((unused))
532long 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
550static __attribute__((unused))
551int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
552{
553 return my_syscall2(__NR_gettimeofday, tv, tz);
554}
555
556static __attribute__((unused))
557int 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
573static __attribute__((unused))
574uid_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
583static __attribute__((unused))
584uid_t getuid(void)
585{
586 return sys_getuid();
587}
588
589
590/*
591 * int ioctl(int fd, unsigned long req, void *value);
592 */
593
594static __attribute__((unused))
595int sys_ioctl(int fd, unsigned long req, void *value)
596{
597 return my_syscall3(__NR_ioctl, fd, req, value);
598}
599
600static __attribute__((unused))
601int 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
616static __attribute__((unused))
617int sys_kill(pid_t pid, int signal)
618{
619 return my_syscall2(__NR_kill, pid, signal);
620}
621
622static __attribute__((unused))
623int 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
639static __attribute__((unused))
640int 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
651static __attribute__((unused))
652int 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
668static __attribute__((unused))
669off_t sys_lseek(int fd, off_t offset, int whence)
670{
671 return my_syscall3(__NR_lseek, fd, offset, whence);
672}
673
674static __attribute__((unused))
675off_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
691static __attribute__((unused))
692int 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
703static __attribute__((unused))
704int 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
720static __attribute__((unused))
721long 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
732static __attribute__((unused))
733int 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
755static __attribute__((unused))
756void *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
778static __attribute__((unused))
779void *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
790static __attribute__((unused))
791int sys_munmap(void *addr, size_t length)
792{
793 return my_syscall2(__NR_munmap, addr, length);
794}
795
796static __attribute__((unused))
797int 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 */
813static __attribute__((unused))
814int 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
820static __attribute__((unused))
821int 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
839static __attribute__((unused))
840int 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
851static __attribute__((unused))
852int 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
879static __attribute__((unused))
880int sys_pivot_root(const char *new, const char *old)
881{
882 return my_syscall2(__NR_pivot_root, new, old);
883}
884
885static __attribute__((unused))
886int 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
902static __attribute__((unused))
903int 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
920static __attribute__((unused))
921int 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
937static __attribute__((unused))
938ssize_t sys_read(int fd, void *buf, size_t count)
939{
940 return my_syscall3(__NR_read, fd, buf, count);
941}
942
943static __attribute__((unused))
944ssize_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
961static __attribute__((unused))
962ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg)
963{
964 return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg);
965}
966
967static __attribute__((unused))
968int 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
984static __attribute__((unused))
985int sys_sched_yield(void)
986{
987 return my_syscall0(__NR_sched_yield);
988}
989
990static __attribute__((unused))
991int 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
1008static __attribute__((unused))
1009int 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
1036static __attribute__((unused))
1037int 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
1053static __attribute__((unused))
1054int sys_setpgid(pid_t pid, pid_t pgid)
1055{
1056 return my_syscall2(__NR_setpgid, pid, pgid);
1057}
1058
1059static __attribute__((unused))
1060int 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
1076static __attribute__((unused))
1077pid_t sys_setsid(void)
1078{
1079 return my_syscall0(__NR_setsid);
1080}
1081
1082static __attribute__((unused))
1083pid_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
1099static __attribute__((unused))
1100int 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
1105static __attribute__((unused))
1106int 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 */
1127static __attribute__((unused))
1128int 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
1154static __attribute__((unused))
1155int 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
1185static __attribute__((unused))
1186int 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
1202static __attribute__((unused))
1203int 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
1214static __attribute__((unused))
1215int 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
1231static __attribute__((unused))
1232mode_t sys_umask(mode_t mode)
1233{
1234 return my_syscall1(__NR_umask, mode);
1235}
1236
1237static __attribute__((unused))
1238mode_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
1248static __attribute__((unused))
1249int sys_umount2(const char *path, int flags)
1250{
1251 return my_syscall2(__NR_umount2, path, flags);
1252}
1253
1254static __attribute__((unused))
1255int 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
1271static __attribute__((unused))
1272int 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
1283static __attribute__((unused))
1284int 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
1302static __attribute__((unused))
1303pid_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
1308static __attribute__((unused))
1309pid_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
1320static __attribute__((unused))
1321pid_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
1333static __attribute__((unused))
1334pid_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
1350static __attribute__((unused))
1351ssize_t sys_write(int fd, const void *buf, size_t count)
1352{
1353 return my_syscall3(__NR_write, fd, buf, count);
1354}
1355
1356static __attribute__((unused))
1357ssize_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 */