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#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 an 34 * error in it. This may only be used with signed returns (int or long), but 35 * 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 is 37 * 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 a 49 * 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 so 60 * that the compiler usually decides to inline them while still being allowed 61 * to pass a pointer to one of their instances. Each syscall exists in two 62 * versions: 63 * - the "internal" ones, which matches the raw syscall interface at the 64 * kernel level, which may sometimes slightly differ from the documented 65 * libc-level ones. For example most of them return either a valid value 66 * or -errno. All of these are prefixed with "sys_". They may be called 67 * by non-portable applications if desired. 68 * 69 * - the "exported" ones, whose interface must closely match the one 70 * documented in man(2), that applications are supposed to expect. These 71 * ones rely on the internal ones, and set errno. 72 * 73 * Each syscall will be defined with the two functions, sorted in alphabetical 74 * order applied to the exported names. 75 * 76 * In case of doubt about the relevance of a function here, only those which 77 * 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_fchmodat 144 return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0); 145#elif defined(__NR_chmod) 146 return my_syscall2(__NR_chmod, path, mode); 147#else 148 return __nolibc_enosys(__func__, path, mode); 149#endif 150} 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_fchownat 167 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#else 171 return __nolibc_enosys(__func__, path, owner, group); 172#endif 173} 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_dup3 241 return my_syscall3(__NR_dup3, old, new, 0); 242#elif defined(__NR_dup2) 243 return my_syscall2(__NR_dup2, old, new); 244#else 245 return __nolibc_enosys(__func__, old, new); 246#endif 247} 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_dup3 261static __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#endif 273 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_fork 315static __attribute__((unused)) 316pid_t sys_fork(void) 317{ 318#ifdef __NR_clone 319 /* note: some archs only have clone() and not fork(). Different archs 320 * have a different API, but most archs have the flags on first arg and 321 * 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#else 327 return __nolibc_enosys(__func__); 328#endif 329} 330#endif 331 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_geteuid32 381 return my_syscall0(__NR_geteuid32); 382#else 383 return my_syscall0(__NR_geteuid); 384#endif 385} 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_gettimeofday 499 return my_syscall2(__NR_gettimeofday, tv, tz); 500#else 501 return __nolibc_enosys(__func__, tv, tz); 502#endif 503} 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_getuid32 520 return my_syscall0(__NR_getuid32); 521#else 522 return my_syscall0(__NR_getuid); 523#endif 524} 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_linkat 574 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#else 578 return __nolibc_enosys(__func__, old, new); 579#endif 580} 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_lseek 597 return my_syscall3(__NR_lseek, fd, offset, whence); 598#else 599 return __nolibc_enosys(__func__, fd, offset, whence); 600#endif 601} 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_mkdirat 618 return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); 619#elif defined(__NR_mkdir) 620 return my_syscall2(__NR_mkdir, path, mode); 621#else 622 return __nolibc_enosys(__func__, path, mode); 623#endif 624} 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_rmdir 640 return my_syscall1(__NR_rmdir, path); 641#elif defined(__NR_unlinkat) 642 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); 643#else 644 return __nolibc_enosys(__func__, path); 645#endif 646} 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_mknodat 663 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#else 667 return __nolibc_enosys(__func__, path, mode, dev); 668#endif 669} 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_mmap 678static __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#else 688 n = __NR_mmap; 689#endif 690 691 return (void *)my_syscall6(n, addr, length, prot, flags, fd, offset); 692} 693#endif 694 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 for 697 * 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_openat 753 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#else 757 return __nolibc_enosys(__func__, path, flags, mode); 758#endif 759} 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#else 857 return __nolibc_enosys(__func__, fds, nfds, timeout); 858#endif 859} 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#else 985 return __nolibc_enosys(__func__, nfds, rfds, wfds, efds, timeout); 986#endif 987} 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_statx 1038 return my_syscall5(__NR_statx, fd, path, flags, mask, buf); 1039#else 1040 return __nolibc_enosys(__func__, fd, path, flags, mask, buf); 1041#endif 1042} 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_symlinkat 1094 return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); 1095#elif defined(__NR_symlink) 1096 return my_syscall2(__NR_symlink, old, new); 1097#else 1098 return __nolibc_enosys(__func__, old, new); 1099#endif 1100} 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_unlinkat 1177 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); 1178#elif defined(__NR_unlink) 1179 return my_syscall1(__NR_unlink, path); 1180#else 1181 return __nolibc_enosys(__func__, path); 1182#endif 1183} 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_wait4 1202 return my_syscall4(__NR_wait4, pid, status, options, rusage); 1203#else 1204 return __nolibc_enosys(__func__, pid, status, options, rusage); 1205#endif 1206} 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