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