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