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