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 static __attribute__((unused)) 340 pid_t sys_fork(void) 341 { 342 #ifdef __NR_clone 343 /* note: some archs only have clone() and not fork(). Different archs 344 * have a different API, but most archs have the flags on first arg and 345 * will not use the rest with no other flag. 346 */ 347 return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0); 348 #elif defined(__NR_fork) 349 return my_syscall0(__NR_fork); 350 #else 351 #error Neither __NR_clone nor __NR_fork defined, cannot implement sys_fork() 352 #endif 353 } 354 355 static __attribute__((unused)) 356 pid_t fork(void) 357 { 358 pid_t ret = sys_fork(); 359 360 if (ret < 0) { 361 SET_ERRNO(-ret); 362 ret = -1; 363 } 364 return ret; 365 } 366 367 368 /* 369 * int fsync(int fd); 370 */ 371 372 static __attribute__((unused)) 373 int sys_fsync(int fd) 374 { 375 return my_syscall1(__NR_fsync, fd); 376 } 377 378 static __attribute__((unused)) 379 int fsync(int fd) 380 { 381 int ret = sys_fsync(fd); 382 383 if (ret < 0) { 384 SET_ERRNO(-ret); 385 ret = -1; 386 } 387 return ret; 388 } 389 390 391 /* 392 * int getdents64(int fd, struct linux_dirent64 *dirp, int count); 393 */ 394 395 static __attribute__((unused)) 396 int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count) 397 { 398 return my_syscall3(__NR_getdents64, fd, dirp, count); 399 } 400 401 static __attribute__((unused)) 402 int getdents64(int fd, struct linux_dirent64 *dirp, int count) 403 { 404 int ret = sys_getdents64(fd, dirp, count); 405 406 if (ret < 0) { 407 SET_ERRNO(-ret); 408 ret = -1; 409 } 410 return ret; 411 } 412 413 414 /* 415 * uid_t geteuid(void); 416 */ 417 418 static __attribute__((unused)) 419 uid_t sys_geteuid(void) 420 { 421 #ifdef __NR_geteuid32 422 return my_syscall0(__NR_geteuid32); 423 #else 424 return my_syscall0(__NR_geteuid); 425 #endif 426 } 427 428 static __attribute__((unused)) 429 uid_t geteuid(void) 430 { 431 return sys_geteuid(); 432 } 433 434 435 /* 436 * pid_t getpgid(pid_t pid); 437 */ 438 439 static __attribute__((unused)) 440 pid_t sys_getpgid(pid_t pid) 441 { 442 return my_syscall1(__NR_getpgid, pid); 443 } 444 445 static __attribute__((unused)) 446 pid_t getpgid(pid_t pid) 447 { 448 pid_t ret = sys_getpgid(pid); 449 450 if (ret < 0) { 451 SET_ERRNO(-ret); 452 ret = -1; 453 } 454 return ret; 455 } 456 457 458 /* 459 * pid_t getpgrp(void); 460 */ 461 462 static __attribute__((unused)) 463 pid_t sys_getpgrp(void) 464 { 465 return sys_getpgid(0); 466 } 467 468 static __attribute__((unused)) 469 pid_t getpgrp(void) 470 { 471 return sys_getpgrp(); 472 } 473 474 475 /* 476 * pid_t getpid(void); 477 */ 478 479 static __attribute__((unused)) 480 pid_t sys_getpid(void) 481 { 482 return my_syscall0(__NR_getpid); 483 } 484 485 static __attribute__((unused)) 486 pid_t getpid(void) 487 { 488 return sys_getpid(); 489 } 490 491 492 /* 493 * pid_t getppid(void); 494 */ 495 496 static __attribute__((unused)) 497 pid_t sys_getppid(void) 498 { 499 return my_syscall0(__NR_getppid); 500 } 501 502 static __attribute__((unused)) 503 pid_t getppid(void) 504 { 505 return sys_getppid(); 506 } 507 508 509 /* 510 * pid_t gettid(void); 511 */ 512 513 static __attribute__((unused)) 514 pid_t sys_gettid(void) 515 { 516 return my_syscall0(__NR_gettid); 517 } 518 519 static __attribute__((unused)) 520 pid_t gettid(void) 521 { 522 return sys_gettid(); 523 } 524 525 static unsigned long getauxval(unsigned long key); 526 527 /* 528 * long getpagesize(void); 529 */ 530 531 static __attribute__((unused)) 532 long getpagesize(void) 533 { 534 long ret; 535 536 ret = getauxval(AT_PAGESZ); 537 if (!ret) { 538 SET_ERRNO(ENOENT); 539 return -1; 540 } 541 542 return ret; 543 } 544 545 546 /* 547 * int gettimeofday(struct timeval *tv, struct timezone *tz); 548 */ 549 550 static __attribute__((unused)) 551 int sys_gettimeofday(struct timeval *tv, struct timezone *tz) 552 { 553 return my_syscall2(__NR_gettimeofday, tv, tz); 554 } 555 556 static __attribute__((unused)) 557 int gettimeofday(struct timeval *tv, struct timezone *tz) 558 { 559 int ret = sys_gettimeofday(tv, tz); 560 561 if (ret < 0) { 562 SET_ERRNO(-ret); 563 ret = -1; 564 } 565 return ret; 566 } 567 568 569 /* 570 * uid_t getuid(void); 571 */ 572 573 static __attribute__((unused)) 574 uid_t sys_getuid(void) 575 { 576 #ifdef __NR_getuid32 577 return my_syscall0(__NR_getuid32); 578 #else 579 return my_syscall0(__NR_getuid); 580 #endif 581 } 582 583 static __attribute__((unused)) 584 uid_t getuid(void) 585 { 586 return sys_getuid(); 587 } 588 589 590 /* 591 * int ioctl(int fd, unsigned long req, void *value); 592 */ 593 594 static __attribute__((unused)) 595 int sys_ioctl(int fd, unsigned long req, void *value) 596 { 597 return my_syscall3(__NR_ioctl, fd, req, value); 598 } 599 600 static __attribute__((unused)) 601 int ioctl(int fd, unsigned long req, void *value) 602 { 603 int ret = sys_ioctl(fd, req, value); 604 605 if (ret < 0) { 606 SET_ERRNO(-ret); 607 ret = -1; 608 } 609 return ret; 610 } 611 612 /* 613 * int kill(pid_t pid, int signal); 614 */ 615 616 static __attribute__((unused)) 617 int sys_kill(pid_t pid, int signal) 618 { 619 return my_syscall2(__NR_kill, pid, signal); 620 } 621 622 static __attribute__((unused)) 623 int kill(pid_t pid, int signal) 624 { 625 int ret = sys_kill(pid, signal); 626 627 if (ret < 0) { 628 SET_ERRNO(-ret); 629 ret = -1; 630 } 631 return ret; 632 } 633 634 635 /* 636 * int link(const char *old, const char *new); 637 */ 638 639 static __attribute__((unused)) 640 int sys_link(const char *old, const char *new) 641 { 642 #ifdef __NR_linkat 643 return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); 644 #elif defined(__NR_link) 645 return my_syscall2(__NR_link, old, new); 646 #else 647 #error Neither __NR_linkat nor __NR_link defined, cannot implement sys_link() 648 #endif 649 } 650 651 static __attribute__((unused)) 652 int link(const char *old, const char *new) 653 { 654 int ret = sys_link(old, new); 655 656 if (ret < 0) { 657 SET_ERRNO(-ret); 658 ret = -1; 659 } 660 return ret; 661 } 662 663 664 /* 665 * off_t lseek(int fd, off_t offset, int whence); 666 */ 667 668 static __attribute__((unused)) 669 off_t sys_lseek(int fd, off_t offset, int whence) 670 { 671 return my_syscall3(__NR_lseek, fd, offset, whence); 672 } 673 674 static __attribute__((unused)) 675 off_t lseek(int fd, off_t offset, int whence) 676 { 677 off_t ret = sys_lseek(fd, offset, whence); 678 679 if (ret < 0) { 680 SET_ERRNO(-ret); 681 ret = -1; 682 } 683 return ret; 684 } 685 686 687 /* 688 * int mkdir(const char *path, mode_t mode); 689 */ 690 691 static __attribute__((unused)) 692 int sys_mkdir(const char *path, mode_t mode) 693 { 694 #ifdef __NR_mkdirat 695 return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); 696 #elif defined(__NR_mkdir) 697 return my_syscall2(__NR_mkdir, path, mode); 698 #else 699 #error Neither __NR_mkdirat nor __NR_mkdir defined, cannot implement sys_mkdir() 700 #endif 701 } 702 703 static __attribute__((unused)) 704 int mkdir(const char *path, mode_t mode) 705 { 706 int ret = sys_mkdir(path, mode); 707 708 if (ret < 0) { 709 SET_ERRNO(-ret); 710 ret = -1; 711 } 712 return ret; 713 } 714 715 716 /* 717 * int mknod(const char *path, mode_t mode, dev_t dev); 718 */ 719 720 static __attribute__((unused)) 721 long sys_mknod(const char *path, mode_t mode, dev_t dev) 722 { 723 #ifdef __NR_mknodat 724 return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); 725 #elif defined(__NR_mknod) 726 return my_syscall3(__NR_mknod, path, mode, dev); 727 #else 728 #error Neither __NR_mknodat nor __NR_mknod defined, cannot implement sys_mknod() 729 #endif 730 } 731 732 static __attribute__((unused)) 733 int mknod(const char *path, mode_t mode, dev_t dev) 734 { 735 int ret = sys_mknod(path, mode, dev); 736 737 if (ret < 0) { 738 SET_ERRNO(-ret); 739 ret = -1; 740 } 741 return ret; 742 } 743 744 #ifndef MAP_SHARED 745 #define MAP_SHARED 0x01 /* Share changes */ 746 #define MAP_PRIVATE 0x02 /* Changes are private */ 747 #define MAP_SHARED_VALIDATE 0x03 /* share + validate extension flags */ 748 #endif 749 750 #ifndef MAP_FAILED 751 #define MAP_FAILED ((void *)-1) 752 #endif 753 754 #ifndef sys_mmap 755 static __attribute__((unused)) 756 void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd, 757 off_t offset) 758 { 759 #ifndef my_syscall6 760 /* Function not implemented. */ 761 return (void *)-ENOSYS; 762 #else 763 764 int n; 765 766 #if defined(__NR_mmap2) 767 n = __NR_mmap2; 768 offset >>= 12; 769 #else 770 n = __NR_mmap; 771 #endif 772 773 return (void *)my_syscall6(n, addr, length, prot, flags, fd, offset); 774 #endif 775 } 776 #endif 777 778 static __attribute__((unused)) 779 void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) 780 { 781 void *ret = sys_mmap(addr, length, prot, flags, fd, offset); 782 783 if ((unsigned long)ret >= -4095UL) { 784 SET_ERRNO(-(long)ret); 785 ret = MAP_FAILED; 786 } 787 return ret; 788 } 789 790 static __attribute__((unused)) 791 int sys_munmap(void *addr, size_t length) 792 { 793 return my_syscall2(__NR_munmap, addr, length); 794 } 795 796 static __attribute__((unused)) 797 int munmap(void *addr, size_t length) 798 { 799 int ret = sys_munmap(addr, length); 800 801 if (ret < 0) { 802 SET_ERRNO(-ret); 803 ret = -1; 804 } 805 return ret; 806 } 807 808 /* 809 * int mount(const char *source, const char *target, 810 * const char *fstype, unsigned long flags, 811 * const void *data); 812 */ 813 static __attribute__((unused)) 814 int sys_mount(const char *src, const char *tgt, const char *fst, 815 unsigned long flags, const void *data) 816 { 817 return my_syscall5(__NR_mount, src, tgt, fst, flags, data); 818 } 819 820 static __attribute__((unused)) 821 int mount(const char *src, const char *tgt, 822 const char *fst, unsigned long flags, 823 const void *data) 824 { 825 int ret = sys_mount(src, tgt, fst, flags, data); 826 827 if (ret < 0) { 828 SET_ERRNO(-ret); 829 ret = -1; 830 } 831 return ret; 832 } 833 834 835 /* 836 * int open(const char *path, int flags[, mode_t mode]); 837 */ 838 839 static __attribute__((unused)) 840 int sys_open(const char *path, int flags, mode_t mode) 841 { 842 #ifdef __NR_openat 843 return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode); 844 #elif defined(__NR_open) 845 return my_syscall3(__NR_open, path, flags, mode); 846 #else 847 #error Neither __NR_openat nor __NR_open defined, cannot implement sys_open() 848 #endif 849 } 850 851 static __attribute__((unused)) 852 int open(const char *path, int flags, ...) 853 { 854 mode_t mode = 0; 855 int ret; 856 857 if (flags & O_CREAT) { 858 va_list args; 859 860 va_start(args, flags); 861 mode = va_arg(args, mode_t); 862 va_end(args); 863 } 864 865 ret = sys_open(path, flags, mode); 866 867 if (ret < 0) { 868 SET_ERRNO(-ret); 869 ret = -1; 870 } 871 return ret; 872 } 873 874 875 /* 876 * int pivot_root(const char *new, const char *old); 877 */ 878 879 static __attribute__((unused)) 880 int sys_pivot_root(const char *new, const char *old) 881 { 882 return my_syscall2(__NR_pivot_root, new, old); 883 } 884 885 static __attribute__((unused)) 886 int pivot_root(const char *new, const char *old) 887 { 888 int ret = sys_pivot_root(new, old); 889 890 if (ret < 0) { 891 SET_ERRNO(-ret); 892 ret = -1; 893 } 894 return ret; 895 } 896 897 898 /* 899 * int poll(struct pollfd *fds, int nfds, int timeout); 900 */ 901 902 static __attribute__((unused)) 903 int sys_poll(struct pollfd *fds, int nfds, int timeout) 904 { 905 #if defined(__NR_ppoll) 906 struct timespec t; 907 908 if (timeout >= 0) { 909 t.tv_sec = timeout / 1000; 910 t.tv_nsec = (timeout % 1000) * 1000000; 911 } 912 return my_syscall4(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL); 913 #elif defined(__NR_poll) 914 return my_syscall3(__NR_poll, fds, nfds, timeout); 915 #else 916 #error Neither __NR_ppoll nor __NR_poll defined, cannot implement sys_poll() 917 #endif 918 } 919 920 static __attribute__((unused)) 921 int poll(struct pollfd *fds, int nfds, int timeout) 922 { 923 int ret = sys_poll(fds, nfds, timeout); 924 925 if (ret < 0) { 926 SET_ERRNO(-ret); 927 ret = -1; 928 } 929 return ret; 930 } 931 932 933 /* 934 * ssize_t read(int fd, void *buf, size_t count); 935 */ 936 937 static __attribute__((unused)) 938 ssize_t sys_read(int fd, void *buf, size_t count) 939 { 940 return my_syscall3(__NR_read, fd, buf, count); 941 } 942 943 static __attribute__((unused)) 944 ssize_t read(int fd, void *buf, size_t count) 945 { 946 ssize_t ret = sys_read(fd, buf, count); 947 948 if (ret < 0) { 949 SET_ERRNO(-ret); 950 ret = -1; 951 } 952 return ret; 953 } 954 955 956 /* 957 * int reboot(int cmd); 958 * <cmd> is among LINUX_REBOOT_CMD_* 959 */ 960 961 static __attribute__((unused)) 962 ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg) 963 { 964 return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg); 965 } 966 967 static __attribute__((unused)) 968 int reboot(int cmd) 969 { 970 int ret = sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0); 971 972 if (ret < 0) { 973 SET_ERRNO(-ret); 974 ret = -1; 975 } 976 return ret; 977 } 978 979 980 /* 981 * int sched_yield(void); 982 */ 983 984 static __attribute__((unused)) 985 int sys_sched_yield(void) 986 { 987 return my_syscall0(__NR_sched_yield); 988 } 989 990 static __attribute__((unused)) 991 int sched_yield(void) 992 { 993 int ret = sys_sched_yield(); 994 995 if (ret < 0) { 996 SET_ERRNO(-ret); 997 ret = -1; 998 } 999 return ret; 1000 } 1001 1002 1003 /* 1004 * int select(int nfds, fd_set *read_fds, fd_set *write_fds, 1005 * fd_set *except_fds, struct timeval *timeout); 1006 */ 1007 1008 static __attribute__((unused)) 1009 int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 1010 { 1011 #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect) 1012 struct sel_arg_struct { 1013 unsigned long n; 1014 fd_set *r, *w, *e; 1015 struct timeval *t; 1016 } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout }; 1017 return my_syscall1(__NR_select, &arg); 1018 #elif defined(__ARCH_WANT_SYS_PSELECT6) && defined(__NR_pselect6) 1019 struct timespec t; 1020 1021 if (timeout) { 1022 t.tv_sec = timeout->tv_sec; 1023 t.tv_nsec = timeout->tv_usec * 1000; 1024 } 1025 return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 1026 #elif defined(__NR__newselect) || defined(__NR_select) 1027 #ifndef __NR__newselect 1028 #define __NR__newselect __NR_select 1029 #endif 1030 return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); 1031 #else 1032 #error None of __NR_select, __NR_pselect6, nor __NR__newselect defined, cannot implement sys_select() 1033 #endif 1034 } 1035 1036 static __attribute__((unused)) 1037 int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 1038 { 1039 int ret = sys_select(nfds, rfds, wfds, efds, timeout); 1040 1041 if (ret < 0) { 1042 SET_ERRNO(-ret); 1043 ret = -1; 1044 } 1045 return ret; 1046 } 1047 1048 1049 /* 1050 * int setpgid(pid_t pid, pid_t pgid); 1051 */ 1052 1053 static __attribute__((unused)) 1054 int sys_setpgid(pid_t pid, pid_t pgid) 1055 { 1056 return my_syscall2(__NR_setpgid, pid, pgid); 1057 } 1058 1059 static __attribute__((unused)) 1060 int setpgid(pid_t pid, pid_t pgid) 1061 { 1062 int ret = sys_setpgid(pid, pgid); 1063 1064 if (ret < 0) { 1065 SET_ERRNO(-ret); 1066 ret = -1; 1067 } 1068 return ret; 1069 } 1070 1071 1072 /* 1073 * pid_t setsid(void); 1074 */ 1075 1076 static __attribute__((unused)) 1077 pid_t sys_setsid(void) 1078 { 1079 return my_syscall0(__NR_setsid); 1080 } 1081 1082 static __attribute__((unused)) 1083 pid_t setsid(void) 1084 { 1085 pid_t ret = sys_setsid(); 1086 1087 if (ret < 0) { 1088 SET_ERRNO(-ret); 1089 ret = -1; 1090 } 1091 return ret; 1092 } 1093 1094 #if defined(__NR_statx) 1095 /* 1096 * int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf); 1097 */ 1098 1099 static __attribute__((unused)) 1100 int sys_statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf) 1101 { 1102 return my_syscall5(__NR_statx, fd, path, flags, mask, buf); 1103 } 1104 1105 static __attribute__((unused)) 1106 int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf) 1107 { 1108 int ret = sys_statx(fd, path, flags, mask, buf); 1109 1110 if (ret < 0) { 1111 SET_ERRNO(-ret); 1112 ret = -1; 1113 } 1114 return ret; 1115 } 1116 #endif 1117 1118 /* 1119 * int stat(const char *path, struct stat *buf); 1120 * Warning: the struct stat's layout is arch-dependent. 1121 */ 1122 1123 #if defined(__NR_statx) && !defined(__NR_newfstatat) && !defined(__NR_stat) 1124 /* 1125 * Maybe we can just use statx() when available for all architectures? 1126 */ 1127 static __attribute__((unused)) 1128 int sys_stat(const char *path, struct stat *buf) 1129 { 1130 struct statx statx; 1131 long ret; 1132 1133 ret = sys_statx(AT_FDCWD, path, AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &statx); 1134 buf->st_dev = ((statx.stx_dev_minor & 0xff) 1135 | (statx.stx_dev_major << 8) 1136 | ((statx.stx_dev_minor & ~0xff) << 12)); 1137 buf->st_ino = statx.stx_ino; 1138 buf->st_mode = statx.stx_mode; 1139 buf->st_nlink = statx.stx_nlink; 1140 buf->st_uid = statx.stx_uid; 1141 buf->st_gid = statx.stx_gid; 1142 buf->st_rdev = ((statx.stx_rdev_minor & 0xff) 1143 | (statx.stx_rdev_major << 8) 1144 | ((statx.stx_rdev_minor & ~0xff) << 12)); 1145 buf->st_size = statx.stx_size; 1146 buf->st_blksize = statx.stx_blksize; 1147 buf->st_blocks = statx.stx_blocks; 1148 buf->st_atime = statx.stx_atime.tv_sec; 1149 buf->st_mtime = statx.stx_mtime.tv_sec; 1150 buf->st_ctime = statx.stx_ctime.tv_sec; 1151 return ret; 1152 } 1153 #else 1154 static __attribute__((unused)) 1155 int sys_stat(const char *path, struct stat *buf) 1156 { 1157 struct sys_stat_struct stat; 1158 long ret; 1159 1160 #ifdef __NR_newfstatat 1161 /* only solution for arm64 */ 1162 ret = my_syscall4(__NR_newfstatat, AT_FDCWD, path, &stat, 0); 1163 #elif defined(__NR_stat) 1164 ret = my_syscall2(__NR_stat, path, &stat); 1165 #else 1166 #error Neither __NR_newfstatat nor __NR_stat defined, cannot implement sys_stat() 1167 #endif 1168 buf->st_dev = stat.st_dev; 1169 buf->st_ino = stat.st_ino; 1170 buf->st_mode = stat.st_mode; 1171 buf->st_nlink = stat.st_nlink; 1172 buf->st_uid = stat.st_uid; 1173 buf->st_gid = stat.st_gid; 1174 buf->st_rdev = stat.st_rdev; 1175 buf->st_size = stat.st_size; 1176 buf->st_blksize = stat.st_blksize; 1177 buf->st_blocks = stat.st_blocks; 1178 buf->st_atime = stat.st_atime; 1179 buf->st_mtime = stat.st_mtime; 1180 buf->st_ctime = stat.st_ctime; 1181 return ret; 1182 } 1183 #endif 1184 1185 static __attribute__((unused)) 1186 int stat(const char *path, struct stat *buf) 1187 { 1188 int ret = sys_stat(path, buf); 1189 1190 if (ret < 0) { 1191 SET_ERRNO(-ret); 1192 ret = -1; 1193 } 1194 return ret; 1195 } 1196 1197 1198 /* 1199 * int symlink(const char *old, const char *new); 1200 */ 1201 1202 static __attribute__((unused)) 1203 int sys_symlink(const char *old, const char *new) 1204 { 1205 #ifdef __NR_symlinkat 1206 return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); 1207 #elif defined(__NR_symlink) 1208 return my_syscall2(__NR_symlink, old, new); 1209 #else 1210 #error Neither __NR_symlinkat nor __NR_symlink defined, cannot implement sys_symlink() 1211 #endif 1212 } 1213 1214 static __attribute__((unused)) 1215 int symlink(const char *old, const char *new) 1216 { 1217 int ret = sys_symlink(old, new); 1218 1219 if (ret < 0) { 1220 SET_ERRNO(-ret); 1221 ret = -1; 1222 } 1223 return ret; 1224 } 1225 1226 1227 /* 1228 * mode_t umask(mode_t mode); 1229 */ 1230 1231 static __attribute__((unused)) 1232 mode_t sys_umask(mode_t mode) 1233 { 1234 return my_syscall1(__NR_umask, mode); 1235 } 1236 1237 static __attribute__((unused)) 1238 mode_t umask(mode_t mode) 1239 { 1240 return sys_umask(mode); 1241 } 1242 1243 1244 /* 1245 * int umount2(const char *path, int flags); 1246 */ 1247 1248 static __attribute__((unused)) 1249 int sys_umount2(const char *path, int flags) 1250 { 1251 return my_syscall2(__NR_umount2, path, flags); 1252 } 1253 1254 static __attribute__((unused)) 1255 int umount2(const char *path, int flags) 1256 { 1257 int ret = sys_umount2(path, flags); 1258 1259 if (ret < 0) { 1260 SET_ERRNO(-ret); 1261 ret = -1; 1262 } 1263 return ret; 1264 } 1265 1266 1267 /* 1268 * int unlink(const char *path); 1269 */ 1270 1271 static __attribute__((unused)) 1272 int sys_unlink(const char *path) 1273 { 1274 #ifdef __NR_unlinkat 1275 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); 1276 #elif defined(__NR_unlink) 1277 return my_syscall1(__NR_unlink, path); 1278 #else 1279 #error Neither __NR_unlinkat nor __NR_unlink defined, cannot implement sys_unlink() 1280 #endif 1281 } 1282 1283 static __attribute__((unused)) 1284 int unlink(const char *path) 1285 { 1286 int ret = sys_unlink(path); 1287 1288 if (ret < 0) { 1289 SET_ERRNO(-ret); 1290 ret = -1; 1291 } 1292 return ret; 1293 } 1294 1295 1296 /* 1297 * pid_t wait(int *status); 1298 * pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage); 1299 * pid_t waitpid(pid_t pid, int *status, int options); 1300 */ 1301 1302 static __attribute__((unused)) 1303 pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage) 1304 { 1305 return my_syscall4(__NR_wait4, pid, status, options, rusage); 1306 } 1307 1308 static __attribute__((unused)) 1309 pid_t wait(int *status) 1310 { 1311 pid_t ret = sys_wait4(-1, status, 0, NULL); 1312 1313 if (ret < 0) { 1314 SET_ERRNO(-ret); 1315 ret = -1; 1316 } 1317 return ret; 1318 } 1319 1320 static __attribute__((unused)) 1321 pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage) 1322 { 1323 pid_t ret = sys_wait4(pid, status, options, rusage); 1324 1325 if (ret < 0) { 1326 SET_ERRNO(-ret); 1327 ret = -1; 1328 } 1329 return ret; 1330 } 1331 1332 1333 static __attribute__((unused)) 1334 pid_t waitpid(pid_t pid, int *status, int options) 1335 { 1336 pid_t ret = sys_wait4(pid, status, options, NULL); 1337 1338 if (ret < 0) { 1339 SET_ERRNO(-ret); 1340 ret = -1; 1341 } 1342 return ret; 1343 } 1344 1345 1346 /* 1347 * ssize_t write(int fd, const void *buf, size_t count); 1348 */ 1349 1350 static __attribute__((unused)) 1351 ssize_t sys_write(int fd, const void *buf, size_t count) 1352 { 1353 return my_syscall3(__NR_write, fd, buf, count); 1354 } 1355 1356 static __attribute__((unused)) 1357 ssize_t write(int fd, const void *buf, size_t count) 1358 { 1359 ssize_t ret = sys_write(fd, buf, count); 1360 1361 if (ret < 0) { 1362 SET_ERRNO(-ret); 1363 ret = -1; 1364 } 1365 return ret; 1366 } 1367 1368 /* make sure to include all global symbols */ 1369 #include "nolibc.h" 1370 1371 #endif /* _NOLIBC_SYS_H */ 1372