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