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))
sys_brk(void * addr)58 void *sys_brk(void *addr)
59 {
60 return (void *)my_syscall1(__NR_brk, addr);
61 }
62
63 static __attribute__((unused))
brk(void * addr)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))
sbrk(intptr_t inc)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))
sys_chdir(const char * path)94 int sys_chdir(const char *path)
95 {
96 return my_syscall1(__NR_chdir, path);
97 }
98
99 static __attribute__((unused))
chdir(const char * path)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))
sys_chmod(const char * path,mode_t mode)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))
chmod(const char * path,mode_t mode)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))
sys_chown(const char * path,uid_t owner,gid_t group)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))
chown(const char * path,uid_t owner,gid_t group)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))
sys_chroot(const char * path)175 int sys_chroot(const char *path)
176 {
177 return my_syscall1(__NR_chroot, path);
178 }
179
180 static __attribute__((unused))
chroot(const char * path)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))
sys_close(int fd)198 int sys_close(int fd)
199 {
200 return my_syscall1(__NR_close, fd);
201 }
202
203 static __attribute__((unused))
close(int fd)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))
sys_dup(int fd)221 int sys_dup(int fd)
222 {
223 return my_syscall1(__NR_dup, fd);
224 }
225
226 static __attribute__((unused))
dup(int fd)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))
sys_dup2(int old,int new)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))
dup2(int old,int new)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))
sys_dup3(int old,int new,int flags)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))
dup3(int old,int new,int flags)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))
sys_execve(const char * filename,char * const argv[],char * const envp[])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))
execve(const char * filename,char * const argv[],char * const envp[])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))
sys_exit(int status)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))
exit(int status)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))
sys_fork(void)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))
fork(void)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))
sys_fsync(int fd)372 int sys_fsync(int fd)
373 {
374 return my_syscall1(__NR_fsync, fd);
375 }
376
377 static __attribute__((unused))
fsync(int fd)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))
sys_getdents64(int fd,struct linux_dirent64 * dirp,int count)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))
getdents64(int fd,struct linux_dirent64 * dirp,int count)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))
sys_getpgid(pid_t pid)418 pid_t sys_getpgid(pid_t pid)
419 {
420 return my_syscall1(__NR_getpgid, pid);
421 }
422
423 static __attribute__((unused))
getpgid(pid_t pid)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))
sys_getpgrp(void)441 pid_t sys_getpgrp(void)
442 {
443 return sys_getpgid(0);
444 }
445
446 static __attribute__((unused))
getpgrp(void)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))
sys_getpid(void)458 pid_t sys_getpid(void)
459 {
460 return my_syscall0(__NR_getpid);
461 }
462
463 static __attribute__((unused))
getpid(void)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))
sys_getppid(void)475 pid_t sys_getppid(void)
476 {
477 return my_syscall0(__NR_getppid);
478 }
479
480 static __attribute__((unused))
getppid(void)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))
sys_gettid(void)492 pid_t sys_gettid(void)
493 {
494 return my_syscall0(__NR_gettid);
495 }
496
497 static __attribute__((unused))
gettid(void)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))
getpagesize(void)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))
sys_gettimeofday(struct timeval * tv,struct timezone * tz)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))
gettimeofday(struct timeval * tv,struct timezone * tz)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))
sys_ioctl(int fd,unsigned long req,void * value)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))
ioctl(int fd,unsigned long req,void * value)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))
sys_kill(pid_t pid,int signal)574 int sys_kill(pid_t pid, int signal)
575 {
576 return my_syscall2(__NR_kill, pid, signal);
577 }
578
579 static __attribute__((unused))
kill(pid_t pid,int signal)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))
sys_link(const char * old,const char * new)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))
link(const char * old,const char * new)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))
sys_lseek(int fd,off_t offset,int whence)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))
lseek(int fd,off_t offset,int whence)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))
sys_mkdir(const char * path,mode_t mode)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))
mkdir(const char * path,mode_t mode)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))
sys_mknod(const char * path,mode_t mode,dev_t dev)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))
mknod(const char * path,mode_t mode,dev_t dev)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))
sys_mmap(void * addr,size_t length,int prot,int flags,int fd,off_t offset)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))
mmap(void * addr,size_t length,int prot,int flags,int fd,off_t offset)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))
sys_munmap(void * addr,size_t length)748 int sys_munmap(void *addr, size_t length)
749 {
750 return my_syscall2(__NR_munmap, addr, length);
751 }
752
753 static __attribute__((unused))
munmap(void * addr,size_t length)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))
sys_mount(const char * src,const char * tgt,const char * fst,unsigned long flags,const void * data)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))
mount(const char * src,const char * tgt,const char * fst,unsigned long flags,const void * data)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))
sys_open(const char * path,int flags,mode_t mode)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))
open(const char * path,int flags,...)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))
sys_pivot_root(const char * new,const char * old)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))
pivot_root(const char * new,const char * old)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))
sys_poll(struct pollfd * fds,int nfds,int timeout)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))
poll(struct pollfd * fds,int nfds,int timeout)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))
sys_read(int fd,void * buf,size_t count)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))
read(int fd,void * buf,size_t count)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))
sys_reboot(int magic1,int magic2,int cmd,void * arg)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))
reboot(int cmd)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))
sys_sched_yield(void)942 int sys_sched_yield(void)
943 {
944 return my_syscall0(__NR_sched_yield);
945 }
946
947 static __attribute__((unused))
sched_yield(void)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))
sys_select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * efds,struct timeval * timeout)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))
select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * efds,struct timeval * timeout)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))
sys_setpgid(pid_t pid,pid_t pgid)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))
setpgid(pid_t pid,pid_t pgid)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))
sys_setsid(void)1034 pid_t sys_setsid(void)
1035 {
1036 return my_syscall0(__NR_setsid);
1037 }
1038
1039 static __attribute__((unused))
setsid(void)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))
sys_stat(const char * path,struct stat * buf)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))
stat(const char * path,struct stat * buf)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))
sys_symlink(const char * old,const char * new)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))
symlink(const char * old,const char * new)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))
sys_umask(mode_t mode)1134 mode_t sys_umask(mode_t mode)
1135 {
1136 return my_syscall1(__NR_umask, mode);
1137 }
1138
1139 static __attribute__((unused))
umask(mode_t mode)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))
sys_umount2(const char * path,int flags)1151 int sys_umount2(const char *path, int flags)
1152 {
1153 return my_syscall2(__NR_umount2, path, flags);
1154 }
1155
1156 static __attribute__((unused))
umount2(const char * path,int flags)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))
sys_unlink(const char * path)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))
unlink(const char * path)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))
sys_wait4(pid_t pid,int * status,int options,struct rusage * rusage)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))
wait(int * status)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))
wait4(pid_t pid,int * status,int options,struct rusage * rusage)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))
waitpid(pid_t pid,int * status,int options)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))
sys_write(int fd,const void * buf,size_t count)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))
write(int fd,const void * buf,size_t count)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