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