at v6.3 23 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/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 57static __attribute__((unused)) 58void *sys_brk(void *addr) 59{ 60 return (void *)my_syscall1(__NR_brk, addr); 61} 62 63static __attribute__((unused)) 64int 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 75static __attribute__((unused)) 76void *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 93static __attribute__((unused)) 94int sys_chdir(const char *path) 95{ 96 return my_syscall1(__NR_chdir, path); 97} 98 99static __attribute__((unused)) 100int 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 116static __attribute__((unused)) 117int 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 128static __attribute__((unused)) 129int 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 145static __attribute__((unused)) 146int 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 157static __attribute__((unused)) 158int 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 174static __attribute__((unused)) 175int sys_chroot(const char *path) 176{ 177 return my_syscall1(__NR_chroot, path); 178} 179 180static __attribute__((unused)) 181int 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 197static __attribute__((unused)) 198int sys_close(int fd) 199{ 200 return my_syscall1(__NR_close, fd); 201} 202 203static __attribute__((unused)) 204int 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 220static __attribute__((unused)) 221int sys_dup(int fd) 222{ 223 return my_syscall1(__NR_dup, fd); 224} 225 226static __attribute__((unused)) 227int 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 243static __attribute__((unused)) 244int 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 255static __attribute__((unused)) 256int 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 273static __attribute__((unused)) 274int sys_dup3(int old, int new, int flags) 275{ 276 return my_syscall3(__NR_dup3, old, new, flags); 277} 278 279static __attribute__((unused)) 280int 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 297static __attribute__((unused)) 298int sys_execve(const char *filename, char *const argv[], char *const envp[]) 299{ 300 return my_syscall3(__NR_execve, filename, argv, envp); 301} 302 303static __attribute__((unused)) 304int 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 320static __attribute__((noreturn,unused)) 321void sys_exit(int status) 322{ 323 my_syscall1(__NR_exit, status & 255); 324 while(1); // shut the "noreturn" warnings. 325} 326 327static __attribute__((noreturn,unused)) 328void exit(int status) 329{ 330 sys_exit(status); 331} 332 333 334/* 335 * pid_t fork(void); 336 */ 337 338static __attribute__((unused)) 339pid_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 354static __attribute__((unused)) 355pid_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 371static __attribute__((unused)) 372int sys_fsync(int fd) 373{ 374 return my_syscall1(__NR_fsync, fd); 375} 376 377static __attribute__((unused)) 378int 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 394static __attribute__((unused)) 395int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count) 396{ 397 return my_syscall3(__NR_getdents64, fd, dirp, count); 398} 399 400static __attribute__((unused)) 401int 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 417static __attribute__((unused)) 418pid_t sys_getpgid(pid_t pid) 419{ 420 return my_syscall1(__NR_getpgid, pid); 421} 422 423static __attribute__((unused)) 424pid_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 440static __attribute__((unused)) 441pid_t sys_getpgrp(void) 442{ 443 return sys_getpgid(0); 444} 445 446static __attribute__((unused)) 447pid_t getpgrp(void) 448{ 449 return sys_getpgrp(); 450} 451 452 453/* 454 * pid_t getpid(void); 455 */ 456 457static __attribute__((unused)) 458pid_t sys_getpid(void) 459{ 460 return my_syscall0(__NR_getpid); 461} 462 463static __attribute__((unused)) 464pid_t getpid(void) 465{ 466 return sys_getpid(); 467} 468 469 470/* 471 * pid_t getppid(void); 472 */ 473 474static __attribute__((unused)) 475pid_t sys_getppid(void) 476{ 477 return my_syscall0(__NR_getppid); 478} 479 480static __attribute__((unused)) 481pid_t getppid(void) 482{ 483 return sys_getppid(); 484} 485 486 487/* 488 * pid_t gettid(void); 489 */ 490 491static __attribute__((unused)) 492pid_t sys_gettid(void) 493{ 494 return my_syscall0(__NR_gettid); 495} 496 497static __attribute__((unused)) 498pid_t gettid(void) 499{ 500 return sys_gettid(); 501} 502 503static unsigned long getauxval(unsigned long key); 504 505/* 506 * long getpagesize(void); 507 */ 508 509static __attribute__((unused)) 510long 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 528static __attribute__((unused)) 529int sys_gettimeofday(struct timeval *tv, struct timezone *tz) 530{ 531 return my_syscall2(__NR_gettimeofday, tv, tz); 532} 533 534static __attribute__((unused)) 535int 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 551static __attribute__((unused)) 552int sys_ioctl(int fd, unsigned long req, void *value) 553{ 554 return my_syscall3(__NR_ioctl, fd, req, value); 555} 556 557static __attribute__((unused)) 558int 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 573static __attribute__((unused)) 574int sys_kill(pid_t pid, int signal) 575{ 576 return my_syscall2(__NR_kill, pid, signal); 577} 578 579static __attribute__((unused)) 580int 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 596static __attribute__((unused)) 597int 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 608static __attribute__((unused)) 609int 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 625static __attribute__((unused)) 626off_t sys_lseek(int fd, off_t offset, int whence) 627{ 628 return my_syscall3(__NR_lseek, fd, offset, whence); 629} 630 631static __attribute__((unused)) 632off_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 648static __attribute__((unused)) 649int 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 660static __attribute__((unused)) 661int 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 677static __attribute__((unused)) 678long 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 689static __attribute__((unused)) 690int 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 712static __attribute__((unused)) 713void *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 735static __attribute__((unused)) 736void *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 747static __attribute__((unused)) 748int sys_munmap(void *addr, size_t length) 749{ 750 return my_syscall2(__NR_munmap, addr, length); 751} 752 753static __attribute__((unused)) 754int 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 */ 770static __attribute__((unused)) 771int 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 777static __attribute__((unused)) 778int 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 796static __attribute__((unused)) 797int 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 808static __attribute__((unused)) 809int 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 836static __attribute__((unused)) 837int sys_pivot_root(const char *new, const char *old) 838{ 839 return my_syscall2(__NR_pivot_root, new, old); 840} 841 842static __attribute__((unused)) 843int 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 859static __attribute__((unused)) 860int 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 877static __attribute__((unused)) 878int 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 894static __attribute__((unused)) 895ssize_t sys_read(int fd, void *buf, size_t count) 896{ 897 return my_syscall3(__NR_read, fd, buf, count); 898} 899 900static __attribute__((unused)) 901ssize_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 918static __attribute__((unused)) 919ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg) 920{ 921 return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg); 922} 923 924static __attribute__((unused)) 925int 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 941static __attribute__((unused)) 942int sys_sched_yield(void) 943{ 944 return my_syscall0(__NR_sched_yield); 945} 946 947static __attribute__((unused)) 948int 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 965static __attribute__((unused)) 966int 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 993static __attribute__((unused)) 994int 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 1010static __attribute__((unused)) 1011int sys_setpgid(pid_t pid, pid_t pgid) 1012{ 1013 return my_syscall2(__NR_setpgid, pid, pgid); 1014} 1015 1016static __attribute__((unused)) 1017int 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 1033static __attribute__((unused)) 1034pid_t sys_setsid(void) 1035{ 1036 return my_syscall0(__NR_setsid); 1037} 1038 1039static __attribute__((unused)) 1040pid_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 1057static __attribute__((unused)) 1058int 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 1087static __attribute__((unused)) 1088int 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 1104static __attribute__((unused)) 1105int 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 1116static __attribute__((unused)) 1117int 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 1133static __attribute__((unused)) 1134mode_t sys_umask(mode_t mode) 1135{ 1136 return my_syscall1(__NR_umask, mode); 1137} 1138 1139static __attribute__((unused)) 1140mode_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 1150static __attribute__((unused)) 1151int sys_umount2(const char *path, int flags) 1152{ 1153 return my_syscall2(__NR_umount2, path, flags); 1154} 1155 1156static __attribute__((unused)) 1157int 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 1173static __attribute__((unused)) 1174int 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 1185static __attribute__((unused)) 1186int 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 1204static __attribute__((unused)) 1205pid_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 1210static __attribute__((unused)) 1211pid_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 1222static __attribute__((unused)) 1223pid_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 1235static __attribute__((unused)) 1236pid_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 1252static __attribute__((unused)) 1253ssize_t sys_write(int fd, const void *buf, size_t count) 1254{ 1255 return my_syscall3(__NR_write, fd, buf, count); 1256} 1257 1258static __attribute__((unused)) 1259ssize_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 */