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