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