github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/dmz/nolibc/sys.h (about)

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