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