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