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