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