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