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