Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
0002 /*
0003  * Syscall definitions for NOLIBC (those in man(2))
0004  * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
0005  */
0006 
0007 #ifndef _NOLIBC_SYS_H
0008 #define _NOLIBC_SYS_H
0009 
0010 #include <stdarg.h>
0011 #include "std.h"
0012 
0013 /* system includes */
0014 #include <asm/unistd.h>
0015 #include <asm/signal.h>  // for SIGCHLD
0016 #include <asm/ioctls.h>
0017 #include <asm/mman.h>
0018 #include <linux/fs.h>
0019 #include <linux/loop.h>
0020 #include <linux/time.h>
0021 
0022 #include "arch.h"
0023 #include "errno.h"
0024 #include "types.h"
0025 
0026 
0027 /* Functions in this file only describe syscalls. They're declared static so
0028  * that the compiler usually decides to inline them while still being allowed
0029  * to pass a pointer to one of their instances. Each syscall exists in two
0030  * versions:
0031  *   - the "internal" ones, which matches the raw syscall interface at the
0032  *     kernel level, which may sometimes slightly differ from the documented
0033  *     libc-level ones. For example most of them return either a valid value
0034  *     or -errno. All of these are prefixed with "sys_". They may be called
0035  *     by non-portable applications if desired.
0036  *
0037  *   - the "exported" ones, whose interface must closely match the one
0038  *     documented in man(2), that applications are supposed to expect. These
0039  *     ones rely on the internal ones, and set errno.
0040  *
0041  * Each syscall will be defined with the two functions, sorted in alphabetical
0042  * order applied to the exported names.
0043  *
0044  * In case of doubt about the relevance of a function here, only those which
0045  * set errno should be defined here. Wrappers like those appearing in man(3)
0046  * should not be placed here.
0047  */
0048 
0049 
0050 /*
0051  * int brk(void *addr);
0052  * void *sbrk(intptr_t inc)
0053  */
0054 
0055 static __attribute__((unused))
0056 void *sys_brk(void *addr)
0057 {
0058     return (void *)my_syscall1(__NR_brk, addr);
0059 }
0060 
0061 static __attribute__((unused))
0062 int brk(void *addr)
0063 {
0064     void *ret = sys_brk(addr);
0065 
0066     if (!ret) {
0067         SET_ERRNO(ENOMEM);
0068         return -1;
0069     }
0070     return 0;
0071 }
0072 
0073 static __attribute__((unused))
0074 void *sbrk(intptr_t inc)
0075 {
0076     void *ret;
0077 
0078     /* first call to find current end */
0079     if ((ret = sys_brk(0)) && (sys_brk(ret + inc) == ret + inc))
0080         return ret + inc;
0081 
0082     SET_ERRNO(ENOMEM);
0083     return (void *)-1;
0084 }
0085 
0086 
0087 /*
0088  * int chdir(const char *path);
0089  */
0090 
0091 static __attribute__((unused))
0092 int sys_chdir(const char *path)
0093 {
0094     return my_syscall1(__NR_chdir, path);
0095 }
0096 
0097 static __attribute__((unused))
0098 int chdir(const char *path)
0099 {
0100     int ret = sys_chdir(path);
0101 
0102     if (ret < 0) {
0103         SET_ERRNO(-ret);
0104         ret = -1;
0105     }
0106     return ret;
0107 }
0108 
0109 
0110 /*
0111  * int chmod(const char *path, mode_t mode);
0112  */
0113 
0114 static __attribute__((unused))
0115 int sys_chmod(const char *path, mode_t mode)
0116 {
0117 #ifdef __NR_fchmodat
0118     return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0);
0119 #elif defined(__NR_chmod)
0120     return my_syscall2(__NR_chmod, path, mode);
0121 #else
0122 #error Neither __NR_fchmodat nor __NR_chmod defined, cannot implement sys_chmod()
0123 #endif
0124 }
0125 
0126 static __attribute__((unused))
0127 int chmod(const char *path, mode_t mode)
0128 {
0129     int ret = sys_chmod(path, mode);
0130 
0131     if (ret < 0) {
0132         SET_ERRNO(-ret);
0133         ret = -1;
0134     }
0135     return ret;
0136 }
0137 
0138 
0139 /*
0140  * int chown(const char *path, uid_t owner, gid_t group);
0141  */
0142 
0143 static __attribute__((unused))
0144 int sys_chown(const char *path, uid_t owner, gid_t group)
0145 {
0146 #ifdef __NR_fchownat
0147     return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0);
0148 #elif defined(__NR_chown)
0149     return my_syscall3(__NR_chown, path, owner, group);
0150 #else
0151 #error Neither __NR_fchownat nor __NR_chown defined, cannot implement sys_chown()
0152 #endif
0153 }
0154 
0155 static __attribute__((unused))
0156 int chown(const char *path, uid_t owner, gid_t group)
0157 {
0158     int ret = sys_chown(path, owner, group);
0159 
0160     if (ret < 0) {
0161         SET_ERRNO(-ret);
0162         ret = -1;
0163     }
0164     return ret;
0165 }
0166 
0167 
0168 /*
0169  * int chroot(const char *path);
0170  */
0171 
0172 static __attribute__((unused))
0173 int sys_chroot(const char *path)
0174 {
0175     return my_syscall1(__NR_chroot, path);
0176 }
0177 
0178 static __attribute__((unused))
0179 int chroot(const char *path)
0180 {
0181     int ret = sys_chroot(path);
0182 
0183     if (ret < 0) {
0184         SET_ERRNO(-ret);
0185         ret = -1;
0186     }
0187     return ret;
0188 }
0189 
0190 
0191 /*
0192  * int close(int fd);
0193  */
0194 
0195 static __attribute__((unused))
0196 int sys_close(int fd)
0197 {
0198     return my_syscall1(__NR_close, fd);
0199 }
0200 
0201 static __attribute__((unused))
0202 int close(int fd)
0203 {
0204     int ret = sys_close(fd);
0205 
0206     if (ret < 0) {
0207         SET_ERRNO(-ret);
0208         ret = -1;
0209     }
0210     return ret;
0211 }
0212 
0213 
0214 /*
0215  * int dup(int fd);
0216  */
0217 
0218 static __attribute__((unused))
0219 int sys_dup(int fd)
0220 {
0221     return my_syscall1(__NR_dup, fd);
0222 }
0223 
0224 static __attribute__((unused))
0225 int dup(int fd)
0226 {
0227     int ret = sys_dup(fd);
0228 
0229     if (ret < 0) {
0230         SET_ERRNO(-ret);
0231         ret = -1;
0232     }
0233     return ret;
0234 }
0235 
0236 
0237 /*
0238  * int dup2(int old, int new);
0239  */
0240 
0241 static __attribute__((unused))
0242 int sys_dup2(int old, int new)
0243 {
0244 #ifdef __NR_dup3
0245     return my_syscall3(__NR_dup3, old, new, 0);
0246 #elif defined(__NR_dup2)
0247     return my_syscall2(__NR_dup2, old, new);
0248 #else
0249 #error Neither __NR_dup3 nor __NR_dup2 defined, cannot implement sys_dup2()
0250 #endif
0251 }
0252 
0253 static __attribute__((unused))
0254 int dup2(int old, int new)
0255 {
0256     int ret = sys_dup2(old, new);
0257 
0258     if (ret < 0) {
0259         SET_ERRNO(-ret);
0260         ret = -1;
0261     }
0262     return ret;
0263 }
0264 
0265 
0266 /*
0267  * int dup3(int old, int new, int flags);
0268  */
0269 
0270 #ifdef __NR_dup3
0271 static __attribute__((unused))
0272 int sys_dup3(int old, int new, int flags)
0273 {
0274     return my_syscall3(__NR_dup3, old, new, flags);
0275 }
0276 
0277 static __attribute__((unused))
0278 int dup3(int old, int new, int flags)
0279 {
0280     int ret = sys_dup3(old, new, flags);
0281 
0282     if (ret < 0) {
0283         SET_ERRNO(-ret);
0284         ret = -1;
0285     }
0286     return ret;
0287 }
0288 #endif
0289 
0290 
0291 /*
0292  * int execve(const char *filename, char *const argv[], char *const envp[]);
0293  */
0294 
0295 static __attribute__((unused))
0296 int sys_execve(const char *filename, char *const argv[], char *const envp[])
0297 {
0298     return my_syscall3(__NR_execve, filename, argv, envp);
0299 }
0300 
0301 static __attribute__((unused))
0302 int execve(const char *filename, char *const argv[], char *const envp[])
0303 {
0304     int ret = sys_execve(filename, argv, envp);
0305 
0306     if (ret < 0) {
0307         SET_ERRNO(-ret);
0308         ret = -1;
0309     }
0310     return ret;
0311 }
0312 
0313 
0314 /*
0315  * void exit(int status);
0316  */
0317 
0318 static __attribute__((noreturn,unused))
0319 void sys_exit(int status)
0320 {
0321     my_syscall1(__NR_exit, status & 255);
0322     while(1); // shut the "noreturn" warnings.
0323 }
0324 
0325 static __attribute__((noreturn,unused))
0326 void exit(int status)
0327 {
0328     sys_exit(status);
0329 }
0330 
0331 
0332 /*
0333  * pid_t fork(void);
0334  */
0335 
0336 static __attribute__((unused))
0337 pid_t sys_fork(void)
0338 {
0339 #ifdef __NR_clone
0340     /* note: some archs only have clone() and not fork(). Different archs
0341      * have a different API, but most archs have the flags on first arg and
0342      * will not use the rest with no other flag.
0343      */
0344     return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0);
0345 #elif defined(__NR_fork)
0346     return my_syscall0(__NR_fork);
0347 #else
0348 #error Neither __NR_clone nor __NR_fork defined, cannot implement sys_fork()
0349 #endif
0350 }
0351 
0352 static __attribute__((unused))
0353 pid_t fork(void)
0354 {
0355     pid_t ret = sys_fork();
0356 
0357     if (ret < 0) {
0358         SET_ERRNO(-ret);
0359         ret = -1;
0360     }
0361     return ret;
0362 }
0363 
0364 
0365 /*
0366  * int fsync(int fd);
0367  */
0368 
0369 static __attribute__((unused))
0370 int sys_fsync(int fd)
0371 {
0372     return my_syscall1(__NR_fsync, fd);
0373 }
0374 
0375 static __attribute__((unused))
0376 int fsync(int fd)
0377 {
0378     int ret = sys_fsync(fd);
0379 
0380     if (ret < 0) {
0381         SET_ERRNO(-ret);
0382         ret = -1;
0383     }
0384     return ret;
0385 }
0386 
0387 
0388 /*
0389  * int getdents64(int fd, struct linux_dirent64 *dirp, int count);
0390  */
0391 
0392 static __attribute__((unused))
0393 int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count)
0394 {
0395     return my_syscall3(__NR_getdents64, fd, dirp, count);
0396 }
0397 
0398 static __attribute__((unused))
0399 int getdents64(int fd, struct linux_dirent64 *dirp, int count)
0400 {
0401     int ret = sys_getdents64(fd, dirp, count);
0402 
0403     if (ret < 0) {
0404         SET_ERRNO(-ret);
0405         ret = -1;
0406     }
0407     return ret;
0408 }
0409 
0410 
0411 /*
0412  * pid_t getpgid(pid_t pid);
0413  */
0414 
0415 static __attribute__((unused))
0416 pid_t sys_getpgid(pid_t pid)
0417 {
0418     return my_syscall1(__NR_getpgid, pid);
0419 }
0420 
0421 static __attribute__((unused))
0422 pid_t getpgid(pid_t pid)
0423 {
0424     pid_t ret = sys_getpgid(pid);
0425 
0426     if (ret < 0) {
0427         SET_ERRNO(-ret);
0428         ret = -1;
0429     }
0430     return ret;
0431 }
0432 
0433 
0434 /*
0435  * pid_t getpgrp(void);
0436  */
0437 
0438 static __attribute__((unused))
0439 pid_t sys_getpgrp(void)
0440 {
0441     return sys_getpgid(0);
0442 }
0443 
0444 static __attribute__((unused))
0445 pid_t getpgrp(void)
0446 {
0447     return sys_getpgrp();
0448 }
0449 
0450 
0451 /*
0452  * pid_t getpid(void);
0453  */
0454 
0455 static __attribute__((unused))
0456 pid_t sys_getpid(void)
0457 {
0458     return my_syscall0(__NR_getpid);
0459 }
0460 
0461 static __attribute__((unused))
0462 pid_t getpid(void)
0463 {
0464     return sys_getpid();
0465 }
0466 
0467 
0468 /*
0469  * pid_t getppid(void);
0470  */
0471 
0472 static __attribute__((unused))
0473 pid_t sys_getppid(void)
0474 {
0475     return my_syscall0(__NR_getppid);
0476 }
0477 
0478 static __attribute__((unused))
0479 pid_t getppid(void)
0480 {
0481     return sys_getppid();
0482 }
0483 
0484 
0485 /*
0486  * pid_t gettid(void);
0487  */
0488 
0489 static __attribute__((unused))
0490 pid_t sys_gettid(void)
0491 {
0492     return my_syscall0(__NR_gettid);
0493 }
0494 
0495 static __attribute__((unused))
0496 pid_t gettid(void)
0497 {
0498     return sys_gettid();
0499 }
0500 
0501 
0502 /*
0503  * int gettimeofday(struct timeval *tv, struct timezone *tz);
0504  */
0505 
0506 static __attribute__((unused))
0507 int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
0508 {
0509     return my_syscall2(__NR_gettimeofday, tv, tz);
0510 }
0511 
0512 static __attribute__((unused))
0513 int gettimeofday(struct timeval *tv, struct timezone *tz)
0514 {
0515     int ret = sys_gettimeofday(tv, tz);
0516 
0517     if (ret < 0) {
0518         SET_ERRNO(-ret);
0519         ret = -1;
0520     }
0521     return ret;
0522 }
0523 
0524 
0525 /*
0526  * int ioctl(int fd, unsigned long req, void *value);
0527  */
0528 
0529 static __attribute__((unused))
0530 int sys_ioctl(int fd, unsigned long req, void *value)
0531 {
0532     return my_syscall3(__NR_ioctl, fd, req, value);
0533 }
0534 
0535 static __attribute__((unused))
0536 int ioctl(int fd, unsigned long req, void *value)
0537 {
0538     int ret = sys_ioctl(fd, req, value);
0539 
0540     if (ret < 0) {
0541         SET_ERRNO(-ret);
0542         ret = -1;
0543     }
0544     return ret;
0545 }
0546 
0547 /*
0548  * int kill(pid_t pid, int signal);
0549  */
0550 
0551 static __attribute__((unused))
0552 int sys_kill(pid_t pid, int signal)
0553 {
0554     return my_syscall2(__NR_kill, pid, signal);
0555 }
0556 
0557 static __attribute__((unused))
0558 int kill(pid_t pid, int signal)
0559 {
0560     int ret = sys_kill(pid, signal);
0561 
0562     if (ret < 0) {
0563         SET_ERRNO(-ret);
0564         ret = -1;
0565     }
0566     return ret;
0567 }
0568 
0569 
0570 /*
0571  * int link(const char *old, const char *new);
0572  */
0573 
0574 static __attribute__((unused))
0575 int sys_link(const char *old, const char *new)
0576 {
0577 #ifdef __NR_linkat
0578     return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0);
0579 #elif defined(__NR_link)
0580     return my_syscall2(__NR_link, old, new);
0581 #else
0582 #error Neither __NR_linkat nor __NR_link defined, cannot implement sys_link()
0583 #endif
0584 }
0585 
0586 static __attribute__((unused))
0587 int link(const char *old, const char *new)
0588 {
0589     int ret = sys_link(old, new);
0590 
0591     if (ret < 0) {
0592         SET_ERRNO(-ret);
0593         ret = -1;
0594     }
0595     return ret;
0596 }
0597 
0598 
0599 /*
0600  * off_t lseek(int fd, off_t offset, int whence);
0601  */
0602 
0603 static __attribute__((unused))
0604 off_t sys_lseek(int fd, off_t offset, int whence)
0605 {
0606     return my_syscall3(__NR_lseek, fd, offset, whence);
0607 }
0608 
0609 static __attribute__((unused))
0610 off_t lseek(int fd, off_t offset, int whence)
0611 {
0612     off_t ret = sys_lseek(fd, offset, whence);
0613 
0614     if (ret < 0) {
0615         SET_ERRNO(-ret);
0616         ret = -1;
0617     }
0618     return ret;
0619 }
0620 
0621 
0622 /*
0623  * int mkdir(const char *path, mode_t mode);
0624  */
0625 
0626 static __attribute__((unused))
0627 int sys_mkdir(const char *path, mode_t mode)
0628 {
0629 #ifdef __NR_mkdirat
0630     return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode);
0631 #elif defined(__NR_mkdir)
0632     return my_syscall2(__NR_mkdir, path, mode);
0633 #else
0634 #error Neither __NR_mkdirat nor __NR_mkdir defined, cannot implement sys_mkdir()
0635 #endif
0636 }
0637 
0638 static __attribute__((unused))
0639 int mkdir(const char *path, mode_t mode)
0640 {
0641     int ret = sys_mkdir(path, mode);
0642 
0643     if (ret < 0) {
0644         SET_ERRNO(-ret);
0645         ret = -1;
0646     }
0647     return ret;
0648 }
0649 
0650 
0651 /*
0652  * int mknod(const char *path, mode_t mode, dev_t dev);
0653  */
0654 
0655 static __attribute__((unused))
0656 long sys_mknod(const char *path, mode_t mode, dev_t dev)
0657 {
0658 #ifdef __NR_mknodat
0659     return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev);
0660 #elif defined(__NR_mknod)
0661     return my_syscall3(__NR_mknod, path, mode, dev);
0662 #else
0663 #error Neither __NR_mknodat nor __NR_mknod defined, cannot implement sys_mknod()
0664 #endif
0665 }
0666 
0667 static __attribute__((unused))
0668 int mknod(const char *path, mode_t mode, dev_t dev)
0669 {
0670     int ret = sys_mknod(path, mode, dev);
0671 
0672     if (ret < 0) {
0673         SET_ERRNO(-ret);
0674         ret = -1;
0675     }
0676     return ret;
0677 }
0678 
0679 #ifndef MAP_SHARED
0680 #define MAP_SHARED      0x01    /* Share changes */
0681 #define MAP_PRIVATE     0x02    /* Changes are private */
0682 #define MAP_SHARED_VALIDATE 0x03    /* share + validate extension flags */
0683 #endif
0684 
0685 #ifndef MAP_FAILED
0686 #define MAP_FAILED ((void *)-1)
0687 #endif
0688 
0689 static __attribute__((unused))
0690 void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd,
0691            off_t offset)
0692 {
0693 #ifndef my_syscall6
0694     /* Function not implemented. */
0695     return -ENOSYS;
0696 #else
0697 
0698     int n;
0699 
0700 #if defined(__i386__)
0701     n = __NR_mmap2;
0702     offset >>= 12;
0703 #else
0704     n = __NR_mmap;
0705 #endif
0706 
0707     return (void *)my_syscall6(n, addr, length, prot, flags, fd, offset);
0708 #endif
0709 }
0710 
0711 static __attribute__((unused))
0712 void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
0713 {
0714     void *ret = sys_mmap(addr, length, prot, flags, fd, offset);
0715 
0716     if ((unsigned long)ret >= -4095UL) {
0717         SET_ERRNO(-(long)ret);
0718         ret = MAP_FAILED;
0719     }
0720     return ret;
0721 }
0722 
0723 static __attribute__((unused))
0724 int sys_munmap(void *addr, size_t length)
0725 {
0726     return my_syscall2(__NR_munmap, addr, length);
0727 }
0728 
0729 static __attribute__((unused))
0730 int munmap(void *addr, size_t length)
0731 {
0732     int ret = sys_munmap(addr, length);
0733 
0734     if (ret < 0) {
0735         SET_ERRNO(-ret);
0736         ret = -1;
0737     }
0738     return ret;
0739 }
0740 
0741 /*
0742  * int mount(const char *source, const char *target,
0743  *           const char *fstype, unsigned long flags,
0744  *           const void *data);
0745  */
0746 static __attribute__((unused))
0747 int sys_mount(const char *src, const char *tgt, const char *fst,
0748                      unsigned long flags, const void *data)
0749 {
0750     return my_syscall5(__NR_mount, src, tgt, fst, flags, data);
0751 }
0752 
0753 static __attribute__((unused))
0754 int mount(const char *src, const char *tgt,
0755           const char *fst, unsigned long flags,
0756           const void *data)
0757 {
0758     int ret = sys_mount(src, tgt, fst, flags, data);
0759 
0760     if (ret < 0) {
0761         SET_ERRNO(-ret);
0762         ret = -1;
0763     }
0764     return ret;
0765 }
0766 
0767 
0768 /*
0769  * int open(const char *path, int flags[, mode_t mode]);
0770  */
0771 
0772 static __attribute__((unused))
0773 int sys_open(const char *path, int flags, mode_t mode)
0774 {
0775 #ifdef __NR_openat
0776     return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode);
0777 #elif defined(__NR_open)
0778     return my_syscall3(__NR_open, path, flags, mode);
0779 #else
0780 #error Neither __NR_openat nor __NR_open defined, cannot implement sys_open()
0781 #endif
0782 }
0783 
0784 static __attribute__((unused))
0785 int open(const char *path, int flags, ...)
0786 {
0787     mode_t mode = 0;
0788     int ret;
0789 
0790     if (flags & O_CREAT) {
0791         va_list args;
0792 
0793         va_start(args, flags);
0794         mode = va_arg(args, mode_t);
0795         va_end(args);
0796     }
0797 
0798     ret = sys_open(path, flags, mode);
0799 
0800     if (ret < 0) {
0801         SET_ERRNO(-ret);
0802         ret = -1;
0803     }
0804     return ret;
0805 }
0806 
0807 
0808 /*
0809  * int pivot_root(const char *new, const char *old);
0810  */
0811 
0812 static __attribute__((unused))
0813 int sys_pivot_root(const char *new, const char *old)
0814 {
0815     return my_syscall2(__NR_pivot_root, new, old);
0816 }
0817 
0818 static __attribute__((unused))
0819 int pivot_root(const char *new, const char *old)
0820 {
0821     int ret = sys_pivot_root(new, old);
0822 
0823     if (ret < 0) {
0824         SET_ERRNO(-ret);
0825         ret = -1;
0826     }
0827     return ret;
0828 }
0829 
0830 
0831 /*
0832  * int poll(struct pollfd *fds, int nfds, int timeout);
0833  */
0834 
0835 static __attribute__((unused))
0836 int sys_poll(struct pollfd *fds, int nfds, int timeout)
0837 {
0838 #if defined(__NR_ppoll)
0839     struct timespec t;
0840 
0841     if (timeout >= 0) {
0842         t.tv_sec  = timeout / 1000;
0843         t.tv_nsec = (timeout % 1000) * 1000000;
0844     }
0845     return my_syscall4(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL);
0846 #elif defined(__NR_poll)
0847     return my_syscall3(__NR_poll, fds, nfds, timeout);
0848 #else
0849 #error Neither __NR_ppoll nor __NR_poll defined, cannot implement sys_poll()
0850 #endif
0851 }
0852 
0853 static __attribute__((unused))
0854 int poll(struct pollfd *fds, int nfds, int timeout)
0855 {
0856     int ret = sys_poll(fds, nfds, timeout);
0857 
0858     if (ret < 0) {
0859         SET_ERRNO(-ret);
0860         ret = -1;
0861     }
0862     return ret;
0863 }
0864 
0865 
0866 /*
0867  * ssize_t read(int fd, void *buf, size_t count);
0868  */
0869 
0870 static __attribute__((unused))
0871 ssize_t sys_read(int fd, void *buf, size_t count)
0872 {
0873     return my_syscall3(__NR_read, fd, buf, count);
0874 }
0875 
0876 static __attribute__((unused))
0877 ssize_t read(int fd, void *buf, size_t count)
0878 {
0879     ssize_t ret = sys_read(fd, buf, count);
0880 
0881     if (ret < 0) {
0882         SET_ERRNO(-ret);
0883         ret = -1;
0884     }
0885     return ret;
0886 }
0887 
0888 
0889 /*
0890  * int reboot(int cmd);
0891  * <cmd> is among LINUX_REBOOT_CMD_*
0892  */
0893 
0894 static __attribute__((unused))
0895 ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg)
0896 {
0897     return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg);
0898 }
0899 
0900 static __attribute__((unused))
0901 int reboot(int cmd)
0902 {
0903     int ret = sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0);
0904 
0905     if (ret < 0) {
0906         SET_ERRNO(-ret);
0907         ret = -1;
0908     }
0909     return ret;
0910 }
0911 
0912 
0913 /*
0914  * int sched_yield(void);
0915  */
0916 
0917 static __attribute__((unused))
0918 int sys_sched_yield(void)
0919 {
0920     return my_syscall0(__NR_sched_yield);
0921 }
0922 
0923 static __attribute__((unused))
0924 int sched_yield(void)
0925 {
0926     int ret = sys_sched_yield();
0927 
0928     if (ret < 0) {
0929         SET_ERRNO(-ret);
0930         ret = -1;
0931     }
0932     return ret;
0933 }
0934 
0935 
0936 /*
0937  * int select(int nfds, fd_set *read_fds, fd_set *write_fds,
0938  *            fd_set *except_fds, struct timeval *timeout);
0939  */
0940 
0941 static __attribute__((unused))
0942 int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
0943 {
0944 #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect)
0945     struct sel_arg_struct {
0946         unsigned long n;
0947         fd_set *r, *w, *e;
0948         struct timeval *t;
0949     } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout };
0950     return my_syscall1(__NR_select, &arg);
0951 #elif defined(__ARCH_WANT_SYS_PSELECT6) && defined(__NR_pselect6)
0952     struct timespec t;
0953 
0954     if (timeout) {
0955         t.tv_sec  = timeout->tv_sec;
0956         t.tv_nsec = timeout->tv_usec * 1000;
0957     }
0958     return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
0959 #elif defined(__NR__newselect) || defined(__NR_select)
0960 #ifndef __NR__newselect
0961 #define __NR__newselect __NR_select
0962 #endif
0963     return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout);
0964 #else
0965 #error None of __NR_select, __NR_pselect6, nor __NR__newselect defined, cannot implement sys_select()
0966 #endif
0967 }
0968 
0969 static __attribute__((unused))
0970 int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
0971 {
0972     int ret = sys_select(nfds, rfds, wfds, efds, timeout);
0973 
0974     if (ret < 0) {
0975         SET_ERRNO(-ret);
0976         ret = -1;
0977     }
0978     return ret;
0979 }
0980 
0981 
0982 /*
0983  * int setpgid(pid_t pid, pid_t pgid);
0984  */
0985 
0986 static __attribute__((unused))
0987 int sys_setpgid(pid_t pid, pid_t pgid)
0988 {
0989     return my_syscall2(__NR_setpgid, pid, pgid);
0990 }
0991 
0992 static __attribute__((unused))
0993 int setpgid(pid_t pid, pid_t pgid)
0994 {
0995     int ret = sys_setpgid(pid, pgid);
0996 
0997     if (ret < 0) {
0998         SET_ERRNO(-ret);
0999         ret = -1;
1000     }
1001     return ret;
1002 }
1003 
1004 
1005 /*
1006  * pid_t setsid(void);
1007  */
1008 
1009 static __attribute__((unused))
1010 pid_t sys_setsid(void)
1011 {
1012     return my_syscall0(__NR_setsid);
1013 }
1014 
1015 static __attribute__((unused))
1016 pid_t setsid(void)
1017 {
1018     pid_t ret = sys_setsid();
1019 
1020     if (ret < 0) {
1021         SET_ERRNO(-ret);
1022         ret = -1;
1023     }
1024     return ret;
1025 }
1026 
1027 
1028 /*
1029  * int stat(const char *path, struct stat *buf);
1030  * Warning: the struct stat's layout is arch-dependent.
1031  */
1032 
1033 static __attribute__((unused))
1034 int sys_stat(const char *path, struct stat *buf)
1035 {
1036     struct sys_stat_struct stat;
1037     long ret;
1038 
1039 #ifdef __NR_newfstatat
1040     /* only solution for arm64 */
1041     ret = my_syscall4(__NR_newfstatat, AT_FDCWD, path, &stat, 0);
1042 #elif defined(__NR_stat)
1043     ret = my_syscall2(__NR_stat, path, &stat);
1044 #else
1045 #error Neither __NR_newfstatat nor __NR_stat defined, cannot implement sys_stat()
1046 #endif
1047     buf->st_dev     = stat.st_dev;
1048     buf->st_ino     = stat.st_ino;
1049     buf->st_mode    = stat.st_mode;
1050     buf->st_nlink   = stat.st_nlink;
1051     buf->st_uid     = stat.st_uid;
1052     buf->st_gid     = stat.st_gid;
1053     buf->st_rdev    = stat.st_rdev;
1054     buf->st_size    = stat.st_size;
1055     buf->st_blksize = stat.st_blksize;
1056     buf->st_blocks  = stat.st_blocks;
1057     buf->st_atime   = stat.st_atime;
1058     buf->st_mtime   = stat.st_mtime;
1059     buf->st_ctime   = stat.st_ctime;
1060     return ret;
1061 }
1062 
1063 static __attribute__((unused))
1064 int stat(const char *path, struct stat *buf)
1065 {
1066     int ret = sys_stat(path, buf);
1067 
1068     if (ret < 0) {
1069         SET_ERRNO(-ret);
1070         ret = -1;
1071     }
1072     return ret;
1073 }
1074 
1075 
1076 /*
1077  * int symlink(const char *old, const char *new);
1078  */
1079 
1080 static __attribute__((unused))
1081 int sys_symlink(const char *old, const char *new)
1082 {
1083 #ifdef __NR_symlinkat
1084     return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new);
1085 #elif defined(__NR_symlink)
1086     return my_syscall2(__NR_symlink, old, new);
1087 #else
1088 #error Neither __NR_symlinkat nor __NR_symlink defined, cannot implement sys_symlink()
1089 #endif
1090 }
1091 
1092 static __attribute__((unused))
1093 int symlink(const char *old, const char *new)
1094 {
1095     int ret = sys_symlink(old, new);
1096 
1097     if (ret < 0) {
1098         SET_ERRNO(-ret);
1099         ret = -1;
1100     }
1101     return ret;
1102 }
1103 
1104 
1105 /*
1106  * mode_t umask(mode_t mode);
1107  */
1108 
1109 static __attribute__((unused))
1110 mode_t sys_umask(mode_t mode)
1111 {
1112     return my_syscall1(__NR_umask, mode);
1113 }
1114 
1115 static __attribute__((unused))
1116 mode_t umask(mode_t mode)
1117 {
1118     return sys_umask(mode);
1119 }
1120 
1121 
1122 /*
1123  * int umount2(const char *path, int flags);
1124  */
1125 
1126 static __attribute__((unused))
1127 int sys_umount2(const char *path, int flags)
1128 {
1129     return my_syscall2(__NR_umount2, path, flags);
1130 }
1131 
1132 static __attribute__((unused))
1133 int umount2(const char *path, int flags)
1134 {
1135     int ret = sys_umount2(path, flags);
1136 
1137     if (ret < 0) {
1138         SET_ERRNO(-ret);
1139         ret = -1;
1140     }
1141     return ret;
1142 }
1143 
1144 
1145 /*
1146  * int unlink(const char *path);
1147  */
1148 
1149 static __attribute__((unused))
1150 int sys_unlink(const char *path)
1151 {
1152 #ifdef __NR_unlinkat
1153     return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0);
1154 #elif defined(__NR_unlink)
1155     return my_syscall1(__NR_unlink, path);
1156 #else
1157 #error Neither __NR_unlinkat nor __NR_unlink defined, cannot implement sys_unlink()
1158 #endif
1159 }
1160 
1161 static __attribute__((unused))
1162 int unlink(const char *path)
1163 {
1164     int ret = sys_unlink(path);
1165 
1166     if (ret < 0) {
1167         SET_ERRNO(-ret);
1168         ret = -1;
1169     }
1170     return ret;
1171 }
1172 
1173 
1174 /*
1175  * pid_t wait(int *status);
1176  * pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);
1177  * pid_t waitpid(pid_t pid, int *status, int options);
1178  */
1179 
1180 static __attribute__((unused))
1181 pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
1182 {
1183     return my_syscall4(__NR_wait4, pid, status, options, rusage);
1184 }
1185 
1186 static __attribute__((unused))
1187 pid_t wait(int *status)
1188 {
1189     pid_t ret = sys_wait4(-1, status, 0, NULL);
1190 
1191     if (ret < 0) {
1192         SET_ERRNO(-ret);
1193         ret = -1;
1194     }
1195     return ret;
1196 }
1197 
1198 static __attribute__((unused))
1199 pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage)
1200 {
1201     pid_t ret = sys_wait4(pid, status, options, rusage);
1202 
1203     if (ret < 0) {
1204         SET_ERRNO(-ret);
1205         ret = -1;
1206     }
1207     return ret;
1208 }
1209 
1210 
1211 static __attribute__((unused))
1212 pid_t waitpid(pid_t pid, int *status, int options)
1213 {
1214     pid_t ret = sys_wait4(pid, status, options, NULL);
1215 
1216     if (ret < 0) {
1217         SET_ERRNO(-ret);
1218         ret = -1;
1219     }
1220     return ret;
1221 }
1222 
1223 
1224 /*
1225  * ssize_t write(int fd, const void *buf, size_t count);
1226  */
1227 
1228 static __attribute__((unused))
1229 ssize_t sys_write(int fd, const void *buf, size_t count)
1230 {
1231     return my_syscall3(__NR_write, fd, buf, count);
1232 }
1233 
1234 static __attribute__((unused))
1235 ssize_t write(int fd, const void *buf, size_t count)
1236 {
1237     ssize_t ret = sys_write(fd, buf, count);
1238 
1239     if (ret < 0) {
1240         SET_ERRNO(-ret);
1241         ret = -1;
1242     }
1243     return ret;
1244 }
1245 
1246 
1247 #endif /* _NOLIBC_SYS_H */