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