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 75 static __attribute__((unused)) 76 void *sys_brk(void *addr) 77 { 78 return (void *)my_syscall1(__NR_brk, addr); 79 } 80 81 static __attribute__((unused)) 82 int 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 93 static __attribute__((unused)) 94 void *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 111 static __attribute__((unused)) 112 int sys_chdir(const char *path) 113 { 114 return my_syscall1(__NR_chdir, path); 115 } 116 117 static __attribute__((unused)) 118 int 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 128 static __attribute__((unused)) 129 int 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 140 static __attribute__((unused)) 141 int 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 151 static __attribute__((unused)) 152 int 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 163 static __attribute__((unused)) 164 int 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 174 static __attribute__((unused)) 175 int sys_chroot(const char *path) 176 { 177 return my_syscall1(__NR_chroot, path); 178 } 179 180 static __attribute__((unused)) 181 int chroot(const char *path) 182 { 183 return __sysret(sys_chroot(path)); 184 } 185 186 187 /* 188 * int close(int fd); 189 */ 190 191 static __attribute__((unused)) 192 int sys_close(int fd) 193 { 194 return my_syscall1(__NR_close, fd); 195 } 196 197 static __attribute__((unused)) 198 int close(int fd) 199 { 200 return __sysret(sys_close(fd)); 201 } 202 203 204 /* 205 * int dup(int fd); 206 */ 207 208 static __attribute__((unused)) 209 int sys_dup(int fd) 210 { 211 return my_syscall1(__NR_dup, fd); 212 } 213 214 static __attribute__((unused)) 215 int dup(int fd) 216 { 217 return __sysret(sys_dup(fd)); 218 } 219 220 221 /* 222 * int dup2(int old, int new); 223 */ 224 225 static __attribute__((unused)) 226 int 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 237 static __attribute__((unused)) 238 int 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 249 static __attribute__((unused)) 250 int sys_dup3(int old, int new, int flags) 251 { 252 return my_syscall3(__NR_dup3, old, new, flags); 253 } 254 255 static __attribute__((unused)) 256 int 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 267 static __attribute__((unused)) 268 int sys_execve(const char *filename, char *const argv[], char *const envp[]) 269 { 270 return my_syscall3(__NR_execve, filename, argv, envp); 271 } 272 273 static __attribute__((unused)) 274 int 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 284 static __attribute__((noreturn,unused)) 285 void sys_exit(int status) 286 { 287 my_syscall1(__NR_exit, status & 255); 288 while(1); /* shut the "noreturn" warnings. */ 289 } 290 291 static __attribute__((noreturn,unused)) 292 void exit(int status) 293 { 294 sys_exit(status); 295 } 296 297 298 /* 299 * pid_t fork(void); 300 */ 301 302 #ifndef sys_fork 303 static __attribute__((unused)) 304 pid_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 320 static __attribute__((unused)) 321 pid_t fork(void) 322 { 323 return __sysret(sys_fork()); 324 } 325 326 327 /* 328 * int fsync(int fd); 329 */ 330 331 static __attribute__((unused)) 332 int sys_fsync(int fd) 333 { 334 return my_syscall1(__NR_fsync, fd); 335 } 336 337 static __attribute__((unused)) 338 int 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 348 static __attribute__((unused)) 349 int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count) 350 { 351 return my_syscall3(__NR_getdents64, fd, dirp, count); 352 } 353 354 static __attribute__((unused)) 355 int 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 365 static __attribute__((unused)) 366 uid_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 375 static __attribute__((unused)) 376 uid_t geteuid(void) 377 { 378 return sys_geteuid(); 379 } 380 381 382 /* 383 * pid_t getpgid(pid_t pid); 384 */ 385 386 static __attribute__((unused)) 387 pid_t sys_getpgid(pid_t pid) 388 { 389 return my_syscall1(__NR_getpgid, pid); 390 } 391 392 static __attribute__((unused)) 393 pid_t getpgid(pid_t pid) 394 { 395 return __sysret(sys_getpgid(pid)); 396 } 397 398 399 /* 400 * pid_t getpgrp(void); 401 */ 402 403 static __attribute__((unused)) 404 pid_t sys_getpgrp(void) 405 { 406 return sys_getpgid(0); 407 } 408 409 static __attribute__((unused)) 410 pid_t getpgrp(void) 411 { 412 return sys_getpgrp(); 413 } 414 415 416 /* 417 * pid_t getpid(void); 418 */ 419 420 static __attribute__((unused)) 421 pid_t sys_getpid(void) 422 { 423 return my_syscall0(__NR_getpid); 424 } 425 426 static __attribute__((unused)) 427 pid_t getpid(void) 428 { 429 return sys_getpid(); 430 } 431 432 433 /* 434 * pid_t getppid(void); 435 */ 436 437 static __attribute__((unused)) 438 pid_t sys_getppid(void) 439 { 440 return my_syscall0(__NR_getppid); 441 } 442 443 static __attribute__((unused)) 444 pid_t getppid(void) 445 { 446 return sys_getppid(); 447 } 448 449 450 /* 451 * pid_t gettid(void); 452 */ 453 454 static __attribute__((unused)) 455 pid_t sys_gettid(void) 456 { 457 return my_syscall0(__NR_gettid); 458 } 459 460 static __attribute__((unused)) 461 pid_t gettid(void) 462 { 463 return sys_gettid(); 464 } 465 466 static unsigned long getauxval(unsigned long key); 467 468 /* 469 * int getpagesize(void); 470 */ 471 472 static __attribute__((unused)) 473 int 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 483 static __attribute__((unused)) 484 int 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 493 static __attribute__((unused)) 494 int 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 504 static __attribute__((unused)) 505 uid_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 514 static __attribute__((unused)) 515 uid_t getuid(void) 516 { 517 return sys_getuid(); 518 } 519 520 521 /* 522 * int ioctl(int fd, unsigned long req, void *value); 523 */ 524 525 static __attribute__((unused)) 526 int sys_ioctl(int fd, unsigned long req, void *value) 527 { 528 return my_syscall3(__NR_ioctl, fd, req, value); 529 } 530 531 static __attribute__((unused)) 532 int 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 541 static __attribute__((unused)) 542 int sys_kill(pid_t pid, int signal) 543 { 544 return my_syscall2(__NR_kill, pid, signal); 545 } 546 547 static __attribute__((unused)) 548 int 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 558 static __attribute__((unused)) 559 int 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 570 static __attribute__((unused)) 571 int 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 581 static __attribute__((unused)) 582 off_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 591 static __attribute__((unused)) 592 off_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 602 static __attribute__((unused)) 603 int 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 614 static __attribute__((unused)) 615 int 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 624 static __attribute__((unused)) 625 int 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 636 static __attribute__((unused)) 637 int 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 647 static __attribute__((unused)) 648 long 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 659 static __attribute__((unused)) 660 int 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 666 static __attribute__((unused)) 667 void *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 688 static __attribute__((unused)) 689 void *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 700 static __attribute__((unused)) 701 int sys_munmap(void *addr, size_t length) 702 { 703 return my_syscall2(__NR_munmap, addr, length); 704 } 705 706 static __attribute__((unused)) 707 int 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 */ 717 static __attribute__((unused)) 718 int 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 724 static __attribute__((unused)) 725 int 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 737 static __attribute__((unused)) 738 int 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 749 static __attribute__((unused)) 750 int 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 771 static __attribute__((unused)) 772 int sys_pipe2(int pipefd[2], int flags) 773 { 774 return my_syscall2(__NR_pipe2, pipefd, flags); 775 } 776 777 static __attribute__((unused)) 778 int pipe2(int pipefd[2], int flags) 779 { 780 return __sysret(sys_pipe2(pipefd, flags)); 781 } 782 783 static __attribute__((unused)) 784 int 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 795 static __attribute__((unused)) 796 int 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 802 static __attribute__((unused)) 803 int 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 814 static __attribute__((unused)) 815 int sys_pivot_root(const char *new, const char *old) 816 { 817 return my_syscall2(__NR_pivot_root, new, old); 818 } 819 820 static __attribute__((unused)) 821 int 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 831 static __attribute__((unused)) 832 int 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 849 static __attribute__((unused)) 850 int 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 860 static __attribute__((unused)) 861 ssize_t sys_read(int fd, void *buf, size_t count) 862 { 863 return my_syscall3(__NR_read, fd, buf, count); 864 } 865 866 static __attribute__((unused)) 867 ssize_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 878 static __attribute__((unused)) 879 ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg) 880 { 881 return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg); 882 } 883 884 static __attribute__((unused)) 885 int 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 895 static __attribute__((unused)) 896 int sys_sched_yield(void) 897 { 898 return my_syscall0(__NR_sched_yield); 899 } 900 901 static __attribute__((unused)) 902 int 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 913 static __attribute__((unused)) 914 int 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 941 static __attribute__((unused)) 942 int 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 952 static __attribute__((unused)) 953 int sys_setpgid(pid_t pid, pid_t pgid) 954 { 955 return my_syscall2(__NR_setpgid, pid, pgid); 956 } 957 958 static __attribute__((unused)) 959 int 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 969 static __attribute__((unused)) 970 pid_t sys_setsid(void) 971 { 972 return my_syscall0(__NR_setsid); 973 } 974 975 static __attribute__((unused)) 976 pid_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 986 static __attribute__((unused)) 987 int 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 996 static __attribute__((unused)) 997 int 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 1003 static __attribute__((unused)) 1004 int 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 1042 static __attribute__((unused)) 1043 int 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 1054 static __attribute__((unused)) 1055 int 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 1065 static __attribute__((unused)) 1066 mode_t sys_umask(mode_t mode) 1067 { 1068 return my_syscall1(__NR_umask, mode); 1069 } 1070 1071 static __attribute__((unused)) 1072 mode_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 1082 static __attribute__((unused)) 1083 int sys_umount2(const char *path, int flags) 1084 { 1085 return my_syscall2(__NR_umount2, path, flags); 1086 } 1087 1088 static __attribute__((unused)) 1089 int 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 1099 static __attribute__((unused)) 1100 int 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 1111 static __attribute__((unused)) 1112 int 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 1124 static __attribute__((unused)) 1125 pid_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 1134 static __attribute__((unused)) 1135 pid_t wait(int *status) 1136 { 1137 return __sysret(sys_wait4(-1, status, 0, NULL)); 1138 } 1139 1140 static __attribute__((unused)) 1141 pid_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 1147 static __attribute__((unused)) 1148 pid_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 1158 static __attribute__((unused)) 1159 ssize_t sys_write(int fd, const void *buf, size_t count) 1160 { 1161 return my_syscall3(__NR_write, fd, buf, count); 1162 } 1163 1164 static __attribute__((unused)) 1165 ssize_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 1175 static __attribute__((unused)) 1176 int sys_memfd_create(const char *name, unsigned int flags) 1177 { 1178 return my_syscall2(__NR_memfd_create, name, flags); 1179 } 1180 1181 static __attribute__((unused)) 1182 int 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 */ 1191