at v6.17 981 lines 19 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/* make sure to include all global symbols */ 8#include "nolibc.h" 9 10#ifndef _NOLIBC_SYS_H 11#define _NOLIBC_SYS_H 12 13#include "std.h" 14 15/* system includes */ 16#include <linux/unistd.h> 17#include <linux/signal.h> /* for SIGCHLD */ 18#include <linux/termios.h> 19#include <linux/mman.h> 20#include <linux/fs.h> 21#include <linux/loop.h> 22#include <linux/time.h> 23#include <linux/auxvec.h> 24#include <linux/fcntl.h> /* for O_* and AT_* */ 25#include <linux/sched.h> /* for clone_args */ 26#include <linux/stat.h> /* for statx() */ 27 28#include "errno.h" 29#include "stdarg.h" 30#include "types.h" 31 32 33/* Syscall return helper: takes the syscall value in argument and checks for an 34 * error in it. This may only be used with signed returns (int or long), but 35 * not with pointers. An error is any value < 0. When an error is encountered, 36 * -ret is set into errno and -1 is returned. Otherwise the returned value is 37 * passed as-is with its type preserved. 38 */ 39 40#define __sysret(arg) \ 41({ \ 42 __typeof__(arg) __sysret_arg = (arg); \ 43 (__sysret_arg < 0) /* error ? */ \ 44 ? (({ SET_ERRNO(-__sysret_arg); }), -1) /* ret -1 with errno = -arg */ \ 45 : __sysret_arg; /* return original value */ \ 46}) 47 48/* Syscall ENOSYS helper: Avoids unused-parameter warnings and provides a 49 * debugging hook. 50 */ 51 52static __inline__ int __nolibc_enosys(const char *syscall, ...) 53{ 54 (void)syscall; 55 return -ENOSYS; 56} 57 58 59/* Functions in this file only describe syscalls. They're declared static so 60 * that the compiler usually decides to inline them while still being allowed 61 * to pass a pointer to one of their instances. Each syscall exists in two 62 * versions: 63 * - the "internal" ones, which matches the raw syscall interface at the 64 * kernel level, which may sometimes slightly differ from the documented 65 * libc-level ones. For example most of them return either a valid value 66 * or -errno. All of these are prefixed with "sys_". They may be called 67 * by non-portable applications if desired. 68 * 69 * - the "exported" ones, whose interface must closely match the one 70 * documented in man(2), that applications are supposed to expect. These 71 * ones rely on the internal ones, and set errno. 72 * 73 * Each syscall will be defined with the two functions, sorted in alphabetical 74 * order applied to the exported names. 75 * 76 * In case of doubt about the relevance of a function here, only those which 77 * set errno should be defined here. Wrappers like those appearing in man(3) 78 * should not be placed here. 79 */ 80 81 82/* 83 * int brk(void *addr); 84 * void *sbrk(intptr_t inc) 85 */ 86 87static __attribute__((unused)) 88void *sys_brk(void *addr) 89{ 90 return (void *)my_syscall1(__NR_brk, addr); 91} 92 93static __attribute__((unused)) 94int brk(void *addr) 95{ 96 void *ret = sys_brk(addr); 97 98 if (!ret) { 99 SET_ERRNO(ENOMEM); 100 return -1; 101 } 102 return 0; 103} 104 105static __attribute__((unused)) 106void *sbrk(intptr_t inc) 107{ 108 /* first call to find current end */ 109 void *ret = sys_brk(0); 110 111 if (ret && sys_brk(ret + inc) == ret + inc) 112 return ret + inc; 113 114 SET_ERRNO(ENOMEM); 115 return (void *)-1; 116} 117 118 119/* 120 * int chdir(const char *path); 121 */ 122 123static __attribute__((unused)) 124int sys_chdir(const char *path) 125{ 126 return my_syscall1(__NR_chdir, path); 127} 128 129static __attribute__((unused)) 130int chdir(const char *path) 131{ 132 return __sysret(sys_chdir(path)); 133} 134 135 136/* 137 * int chmod(const char *path, mode_t mode); 138 */ 139 140static __attribute__((unused)) 141int sys_chmod(const char *path, mode_t mode) 142{ 143#if defined(__NR_fchmodat) 144 return my_syscall4(__NR_fchmodat, AT_FDCWD, path, mode, 0); 145#elif defined(__NR_chmod) 146 return my_syscall2(__NR_chmod, path, mode); 147#else 148 return __nolibc_enosys(__func__, path, mode); 149#endif 150} 151 152static __attribute__((unused)) 153int chmod(const char *path, mode_t mode) 154{ 155 return __sysret(sys_chmod(path, mode)); 156} 157 158 159/* 160 * int chown(const char *path, uid_t owner, gid_t group); 161 */ 162 163static __attribute__((unused)) 164int sys_chown(const char *path, uid_t owner, gid_t group) 165{ 166#if defined(__NR_fchownat) 167 return my_syscall5(__NR_fchownat, AT_FDCWD, path, owner, group, 0); 168#elif defined(__NR_chown) 169 return my_syscall3(__NR_chown, path, owner, group); 170#else 171 return __nolibc_enosys(__func__, path, owner, group); 172#endif 173} 174 175static __attribute__((unused)) 176int chown(const char *path, uid_t owner, gid_t group) 177{ 178 return __sysret(sys_chown(path, owner, group)); 179} 180 181 182/* 183 * int chroot(const char *path); 184 */ 185 186static __attribute__((unused)) 187int sys_chroot(const char *path) 188{ 189 return my_syscall1(__NR_chroot, path); 190} 191 192static __attribute__((unused)) 193int chroot(const char *path) 194{ 195 return __sysret(sys_chroot(path)); 196} 197 198 199/* 200 * int close(int fd); 201 */ 202 203static __attribute__((unused)) 204int sys_close(int fd) 205{ 206 return my_syscall1(__NR_close, fd); 207} 208 209static __attribute__((unused)) 210int close(int fd) 211{ 212 return __sysret(sys_close(fd)); 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 return __sysret(sys_dup(fd)); 230} 231 232 233/* 234 * int dup2(int old, int new); 235 */ 236 237static __attribute__((unused)) 238int sys_dup2(int old, int new) 239{ 240#if defined(__NR_dup3) 241 return my_syscall3(__NR_dup3, old, new, 0); 242#elif defined(__NR_dup2) 243 return my_syscall2(__NR_dup2, old, new); 244#else 245 return __nolibc_enosys(__func__, old, new); 246#endif 247} 248 249static __attribute__((unused)) 250int dup2(int old, int new) 251{ 252 return __sysret(sys_dup2(old, new)); 253} 254 255 256/* 257 * int dup3(int old, int new, int flags); 258 */ 259 260#if defined(__NR_dup3) 261static __attribute__((unused)) 262int sys_dup3(int old, int new, int flags) 263{ 264 return my_syscall3(__NR_dup3, old, new, flags); 265} 266 267static __attribute__((unused)) 268int dup3(int old, int new, int flags) 269{ 270 return __sysret(sys_dup3(old, new, flags)); 271} 272#endif 273 274 275/* 276 * int execve(const char *filename, char *const argv[], char *const envp[]); 277 */ 278 279static __attribute__((unused)) 280int sys_execve(const char *filename, char *const argv[], char *const envp[]) 281{ 282 return my_syscall3(__NR_execve, filename, argv, envp); 283} 284 285static __attribute__((unused)) 286int execve(const char *filename, char *const argv[], char *const envp[]) 287{ 288 return __sysret(sys_execve(filename, argv, envp)); 289} 290 291 292/* 293 * void exit(int status); 294 */ 295 296static __attribute__((noreturn,unused)) 297void sys_exit(int status) 298{ 299 my_syscall1(__NR_exit, status & 255); 300 while(1); /* shut the "noreturn" warnings. */ 301} 302 303static __attribute__((noreturn,unused)) 304void _exit(int status) 305{ 306 sys_exit(status); 307} 308 309static __attribute__((noreturn,unused)) 310void exit(int status) 311{ 312 _exit(status); 313} 314 315 316/* 317 * pid_t fork(void); 318 */ 319 320#ifndef sys_fork 321static __attribute__((unused)) 322pid_t sys_fork(void) 323{ 324#if defined(__NR_clone) 325 /* note: some archs only have clone() and not fork(). Different archs 326 * have a different API, but most archs have the flags on first arg and 327 * will not use the rest with no other flag. 328 */ 329 return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0); 330#elif defined(__NR_fork) 331 return my_syscall0(__NR_fork); 332#else 333 return __nolibc_enosys(__func__); 334#endif 335} 336#endif 337 338static __attribute__((unused)) 339pid_t fork(void) 340{ 341 return __sysret(sys_fork()); 342} 343 344#ifndef sys_vfork 345static __attribute__((unused)) 346pid_t sys_vfork(void) 347{ 348#if defined(__NR_vfork) 349 return my_syscall0(__NR_vfork); 350#elif defined(__NR_clone3) 351 /* 352 * clone() could be used but has different argument orders per 353 * architecture. 354 */ 355 struct clone_args args = { 356 .flags = CLONE_VM | CLONE_VFORK, 357 .exit_signal = SIGCHLD, 358 }; 359 360 return my_syscall2(__NR_clone3, &args, sizeof(args)); 361#else 362 return __nolibc_enosys(__func__); 363#endif 364} 365#endif 366 367static __attribute__((unused)) 368pid_t vfork(void) 369{ 370 return __sysret(sys_vfork()); 371} 372 373/* 374 * int fsync(int fd); 375 */ 376 377static __attribute__((unused)) 378int sys_fsync(int fd) 379{ 380 return my_syscall1(__NR_fsync, fd); 381} 382 383static __attribute__((unused)) 384int fsync(int fd) 385{ 386 return __sysret(sys_fsync(fd)); 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 return __sysret(sys_getdents64(fd, dirp, count)); 404} 405 406 407/* 408 * uid_t geteuid(void); 409 */ 410 411static __attribute__((unused)) 412uid_t sys_geteuid(void) 413{ 414#if defined(__NR_geteuid32) 415 return my_syscall0(__NR_geteuid32); 416#else 417 return my_syscall0(__NR_geteuid); 418#endif 419} 420 421static __attribute__((unused)) 422uid_t geteuid(void) 423{ 424 return sys_geteuid(); 425} 426 427 428/* 429 * pid_t getpgid(pid_t pid); 430 */ 431 432static __attribute__((unused)) 433pid_t sys_getpgid(pid_t pid) 434{ 435 return my_syscall1(__NR_getpgid, pid); 436} 437 438static __attribute__((unused)) 439pid_t getpgid(pid_t pid) 440{ 441 return __sysret(sys_getpgid(pid)); 442} 443 444 445/* 446 * pid_t getpgrp(void); 447 */ 448 449static __attribute__((unused)) 450pid_t sys_getpgrp(void) 451{ 452 return sys_getpgid(0); 453} 454 455static __attribute__((unused)) 456pid_t getpgrp(void) 457{ 458 return sys_getpgrp(); 459} 460 461 462/* 463 * pid_t getpid(void); 464 */ 465 466static __attribute__((unused)) 467pid_t sys_getpid(void) 468{ 469 return my_syscall0(__NR_getpid); 470} 471 472static __attribute__((unused)) 473pid_t getpid(void) 474{ 475 return sys_getpid(); 476} 477 478 479/* 480 * pid_t getppid(void); 481 */ 482 483static __attribute__((unused)) 484pid_t sys_getppid(void) 485{ 486 return my_syscall0(__NR_getppid); 487} 488 489static __attribute__((unused)) 490pid_t getppid(void) 491{ 492 return sys_getppid(); 493} 494 495 496/* 497 * pid_t gettid(void); 498 */ 499 500static __attribute__((unused)) 501pid_t sys_gettid(void) 502{ 503 return my_syscall0(__NR_gettid); 504} 505 506static __attribute__((unused)) 507pid_t gettid(void) 508{ 509 return sys_gettid(); 510} 511 512static unsigned long getauxval(unsigned long key); 513 514/* 515 * int getpagesize(void); 516 */ 517 518static __attribute__((unused)) 519int getpagesize(void) 520{ 521 return __sysret((int)getauxval(AT_PAGESZ) ?: -ENOENT); 522} 523 524 525/* 526 * uid_t getuid(void); 527 */ 528 529static __attribute__((unused)) 530uid_t sys_getuid(void) 531{ 532#if defined(__NR_getuid32) 533 return my_syscall0(__NR_getuid32); 534#else 535 return my_syscall0(__NR_getuid); 536#endif 537} 538 539static __attribute__((unused)) 540uid_t getuid(void) 541{ 542 return sys_getuid(); 543} 544 545 546/* 547 * int kill(pid_t pid, int signal); 548 */ 549 550static __attribute__((unused)) 551int sys_kill(pid_t pid, int signal) 552{ 553 return my_syscall2(__NR_kill, pid, signal); 554} 555 556static __attribute__((unused)) 557int kill(pid_t pid, int signal) 558{ 559 return __sysret(sys_kill(pid, signal)); 560} 561 562 563/* 564 * int link(const char *old, const char *new); 565 */ 566 567static __attribute__((unused)) 568int sys_link(const char *old, const char *new) 569{ 570#if defined(__NR_linkat) 571 return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); 572#elif defined(__NR_link) 573 return my_syscall2(__NR_link, old, new); 574#else 575 return __nolibc_enosys(__func__, old, new); 576#endif 577} 578 579static __attribute__((unused)) 580int link(const char *old, const char *new) 581{ 582 return __sysret(sys_link(old, new)); 583} 584 585 586/* 587 * off_t lseek(int fd, off_t offset, int whence); 588 */ 589 590static __attribute__((unused)) 591off_t sys_lseek(int fd, off_t offset, int whence) 592{ 593#if defined(__NR_lseek) 594 return my_syscall3(__NR_lseek, fd, offset, whence); 595#else 596 return __nolibc_enosys(__func__, fd, offset, whence); 597#endif 598} 599 600static __attribute__((unused)) 601int sys_llseek(int fd, unsigned long offset_high, unsigned long offset_low, 602 __kernel_loff_t *result, int whence) 603{ 604#if defined(__NR_llseek) 605 return my_syscall5(__NR_llseek, fd, offset_high, offset_low, result, whence); 606#else 607 return __nolibc_enosys(__func__, fd, offset_high, offset_low, result, whence); 608#endif 609} 610 611static __attribute__((unused)) 612off_t lseek(int fd, off_t offset, int whence) 613{ 614 __kernel_loff_t loff = 0; 615 off_t result; 616 int ret; 617 618 result = sys_lseek(fd, offset, whence); 619 if (result == -ENOSYS) { 620 /* Only exists on 32bit where nolibc off_t is also 32bit */ 621 ret = sys_llseek(fd, 0, offset, &loff, whence); 622 if (ret < 0) 623 result = ret; 624 else if (loff != (off_t)loff) 625 result = -EOVERFLOW; 626 else 627 result = loff; 628 } 629 630 return __sysret(result); 631} 632 633 634/* 635 * int mkdir(const char *path, mode_t mode); 636 */ 637 638static __attribute__((unused)) 639int sys_mkdir(const char *path, mode_t mode) 640{ 641#if defined(__NR_mkdirat) 642 return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); 643#elif defined(__NR_mkdir) 644 return my_syscall2(__NR_mkdir, path, mode); 645#else 646 return __nolibc_enosys(__func__, path, mode); 647#endif 648} 649 650static __attribute__((unused)) 651int mkdir(const char *path, mode_t mode) 652{ 653 return __sysret(sys_mkdir(path, mode)); 654} 655 656/* 657 * int rmdir(const char *path); 658 */ 659 660static __attribute__((unused)) 661int sys_rmdir(const char *path) 662{ 663#if defined(__NR_rmdir) 664 return my_syscall1(__NR_rmdir, path); 665#elif defined(__NR_unlinkat) 666 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); 667#else 668 return __nolibc_enosys(__func__, path); 669#endif 670} 671 672static __attribute__((unused)) 673int rmdir(const char *path) 674{ 675 return __sysret(sys_rmdir(path)); 676} 677 678 679/* 680 * int mknod(const char *path, mode_t mode, dev_t dev); 681 */ 682 683static __attribute__((unused)) 684long sys_mknod(const char *path, mode_t mode, dev_t dev) 685{ 686#if defined(__NR_mknodat) 687 return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); 688#elif defined(__NR_mknod) 689 return my_syscall3(__NR_mknod, path, mode, dev); 690#else 691 return __nolibc_enosys(__func__, path, mode, dev); 692#endif 693} 694 695static __attribute__((unused)) 696int mknod(const char *path, mode_t mode, dev_t dev) 697{ 698 return __sysret(sys_mknod(path, mode, dev)); 699} 700 701 702/* 703 * int pipe2(int pipefd[2], int flags); 704 * int pipe(int pipefd[2]); 705 */ 706 707static __attribute__((unused)) 708int sys_pipe2(int pipefd[2], int flags) 709{ 710 return my_syscall2(__NR_pipe2, pipefd, flags); 711} 712 713static __attribute__((unused)) 714int pipe2(int pipefd[2], int flags) 715{ 716 return __sysret(sys_pipe2(pipefd, flags)); 717} 718 719static __attribute__((unused)) 720int pipe(int pipefd[2]) 721{ 722 return pipe2(pipefd, 0); 723} 724 725 726/* 727 * int pivot_root(const char *new, const char *old); 728 */ 729 730static __attribute__((unused)) 731int sys_pivot_root(const char *new, const char *old) 732{ 733 return my_syscall2(__NR_pivot_root, new, old); 734} 735 736static __attribute__((unused)) 737int pivot_root(const char *new, const char *old) 738{ 739 return __sysret(sys_pivot_root(new, old)); 740} 741 742 743/* 744 * ssize_t read(int fd, void *buf, size_t count); 745 */ 746 747static __attribute__((unused)) 748ssize_t sys_read(int fd, void *buf, size_t count) 749{ 750 return my_syscall3(__NR_read, fd, buf, count); 751} 752 753static __attribute__((unused)) 754ssize_t read(int fd, void *buf, size_t count) 755{ 756 return __sysret(sys_read(fd, buf, count)); 757} 758 759 760/* 761 * int sched_yield(void); 762 */ 763 764static __attribute__((unused)) 765int sys_sched_yield(void) 766{ 767 return my_syscall0(__NR_sched_yield); 768} 769 770static __attribute__((unused)) 771int sched_yield(void) 772{ 773 return __sysret(sys_sched_yield()); 774} 775 776 777/* 778 * int select(int nfds, fd_set *read_fds, fd_set *write_fds, 779 * fd_set *except_fds, struct timeval *timeout); 780 */ 781 782static __attribute__((unused)) 783int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 784{ 785#if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect) 786 struct sel_arg_struct { 787 unsigned long n; 788 fd_set *r, *w, *e; 789 struct timeval *t; 790 } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout }; 791 return my_syscall1(__NR_select, &arg); 792#elif defined(__NR__newselect) 793 return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); 794#elif defined(__NR_select) 795 return my_syscall5(__NR_select, nfds, rfds, wfds, efds, timeout); 796#elif defined(__NR_pselect6) 797 struct timespec t; 798 799 if (timeout) { 800 t.tv_sec = timeout->tv_sec; 801 t.tv_nsec = timeout->tv_usec * 1000; 802 } 803 return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 804#elif defined(__NR_pselect6_time64) 805 struct __kernel_timespec t; 806 807 if (timeout) { 808 t.tv_sec = timeout->tv_sec; 809 t.tv_nsec = timeout->tv_usec * 1000; 810 } 811 return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 812#else 813 return __nolibc_enosys(__func__, nfds, rfds, wfds, efds, timeout); 814#endif 815} 816 817static __attribute__((unused)) 818int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 819{ 820 return __sysret(sys_select(nfds, rfds, wfds, efds, timeout)); 821} 822 823 824/* 825 * int setpgid(pid_t pid, pid_t pgid); 826 */ 827 828static __attribute__((unused)) 829int sys_setpgid(pid_t pid, pid_t pgid) 830{ 831 return my_syscall2(__NR_setpgid, pid, pgid); 832} 833 834static __attribute__((unused)) 835int setpgid(pid_t pid, pid_t pgid) 836{ 837 return __sysret(sys_setpgid(pid, pgid)); 838} 839 840/* 841 * pid_t setpgrp(void) 842 */ 843 844static __attribute__((unused)) 845pid_t setpgrp(void) 846{ 847 return setpgid(0, 0); 848} 849 850 851/* 852 * pid_t setsid(void); 853 */ 854 855static __attribute__((unused)) 856pid_t sys_setsid(void) 857{ 858 return my_syscall0(__NR_setsid); 859} 860 861static __attribute__((unused)) 862pid_t setsid(void) 863{ 864 return __sysret(sys_setsid()); 865} 866 867 868/* 869 * int symlink(const char *old, const char *new); 870 */ 871 872static __attribute__((unused)) 873int sys_symlink(const char *old, const char *new) 874{ 875#if defined(__NR_symlinkat) 876 return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); 877#elif defined(__NR_symlink) 878 return my_syscall2(__NR_symlink, old, new); 879#else 880 return __nolibc_enosys(__func__, old, new); 881#endif 882} 883 884static __attribute__((unused)) 885int symlink(const char *old, const char *new) 886{ 887 return __sysret(sys_symlink(old, new)); 888} 889 890 891/* 892 * mode_t umask(mode_t mode); 893 */ 894 895static __attribute__((unused)) 896mode_t sys_umask(mode_t mode) 897{ 898 return my_syscall1(__NR_umask, mode); 899} 900 901static __attribute__((unused)) 902mode_t umask(mode_t mode) 903{ 904 return sys_umask(mode); 905} 906 907 908/* 909 * int umount2(const char *path, int flags); 910 */ 911 912static __attribute__((unused)) 913int sys_umount2(const char *path, int flags) 914{ 915 return my_syscall2(__NR_umount2, path, flags); 916} 917 918static __attribute__((unused)) 919int umount2(const char *path, int flags) 920{ 921 return __sysret(sys_umount2(path, flags)); 922} 923 924 925/* 926 * int unlink(const char *path); 927 */ 928 929static __attribute__((unused)) 930int sys_unlink(const char *path) 931{ 932#if defined(__NR_unlinkat) 933 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); 934#elif defined(__NR_unlink) 935 return my_syscall1(__NR_unlink, path); 936#else 937 return __nolibc_enosys(__func__, path); 938#endif 939} 940 941static __attribute__((unused)) 942int unlink(const char *path) 943{ 944 return __sysret(sys_unlink(path)); 945} 946 947 948/* 949 * ssize_t write(int fd, const void *buf, size_t count); 950 */ 951 952static __attribute__((unused)) 953ssize_t sys_write(int fd, const void *buf, size_t count) 954{ 955 return my_syscall3(__NR_write, fd, buf, count); 956} 957 958static __attribute__((unused)) 959ssize_t write(int fd, const void *buf, size_t count) 960{ 961 return __sysret(sys_write(fd, buf, count)); 962} 963 964 965/* 966 * int memfd_create(const char *name, unsigned int flags); 967 */ 968 969static __attribute__((unused)) 970int sys_memfd_create(const char *name, unsigned int flags) 971{ 972 return my_syscall2(__NR_memfd_create, name, flags); 973} 974 975static __attribute__((unused)) 976int memfd_create(const char *name, unsigned int flags) 977{ 978 return __sysret(sys_memfd_create(name, flags)); 979} 980 981#endif /* _NOLIBC_SYS_H */