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