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 52 static __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 87 static __attribute__((unused)) 88 void *sys_brk(void *addr) 89 { 90 return (void *)my_syscall1(__NR_brk, addr); 91 } 92 93 static __attribute__((unused)) 94 int 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 105 static __attribute__((unused)) 106 void *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 123 static __attribute__((unused)) 124 int sys_chdir(const char *path) 125 { 126 return my_syscall1(__NR_chdir, path); 127 } 128 129 static __attribute__((unused)) 130 int 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 140 static __attribute__((unused)) 141 int 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 152 static __attribute__((unused)) 153 int 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 163 static __attribute__((unused)) 164 int 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 175 static __attribute__((unused)) 176 int 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 186 static __attribute__((unused)) 187 int sys_chroot(const char *path) 188 { 189 return my_syscall1(__NR_chroot, path); 190 } 191 192 static __attribute__((unused)) 193 int chroot(const char *path) 194 { 195 return __sysret(sys_chroot(path)); 196 } 197 198 199 /* 200 * int close(int fd); 201 */ 202 203 static __attribute__((unused)) 204 int sys_close(int fd) 205 { 206 return my_syscall1(__NR_close, fd); 207 } 208 209 static __attribute__((unused)) 210 int close(int fd) 211 { 212 return __sysret(sys_close(fd)); 213 } 214 215 216 /* 217 * int dup(int fd); 218 */ 219 220 static __attribute__((unused)) 221 int sys_dup(int fd) 222 { 223 return my_syscall1(__NR_dup, fd); 224 } 225 226 static __attribute__((unused)) 227 int dup(int fd) 228 { 229 return __sysret(sys_dup(fd)); 230 } 231 232 233 /* 234 * int dup2(int old, int new); 235 */ 236 237 static __attribute__((unused)) 238 int sys_dup2(int old, int new) 239 { 240 #if defined(__NR_dup3) 241 int ret, nr_fcntl; 242 243 #ifdef __NR_fcntl64 244 nr_fcntl = __NR_fcntl64; 245 #else 246 nr_fcntl = __NR_fcntl; 247 #endif 248 249 if (old == new) { 250 ret = my_syscall2(nr_fcntl, old, F_GETFD); 251 return ret < 0 ? ret : old; 252 } 253 254 return my_syscall3(__NR_dup3, old, new, 0); 255 #elif defined(__NR_dup2) 256 return my_syscall2(__NR_dup2, old, new); 257 #else 258 return __nolibc_enosys(__func__, old, new); 259 #endif 260 } 261 262 static __attribute__((unused)) 263 int dup2(int old, int new) 264 { 265 return __sysret(sys_dup2(old, new)); 266 } 267 268 269 /* 270 * int dup3(int old, int new, int flags); 271 */ 272 273 #if defined(__NR_dup3) 274 static __attribute__((unused)) 275 int sys_dup3(int old, int new, int flags) 276 { 277 return my_syscall3(__NR_dup3, old, new, flags); 278 } 279 280 static __attribute__((unused)) 281 int dup3(int old, int new, int flags) 282 { 283 return __sysret(sys_dup3(old, new, flags)); 284 } 285 #endif 286 287 288 /* 289 * int execve(const char *filename, char *const argv[], char *const envp[]); 290 */ 291 292 static __attribute__((unused)) 293 int sys_execve(const char *filename, char *const argv[], char *const envp[]) 294 { 295 return my_syscall3(__NR_execve, filename, argv, envp); 296 } 297 298 static __attribute__((unused)) 299 int execve(const char *filename, char *const argv[], char *const envp[]) 300 { 301 return __sysret(sys_execve(filename, argv, envp)); 302 } 303 304 305 /* 306 * void exit(int status); 307 */ 308 309 static __attribute__((noreturn,unused)) 310 void sys_exit(int status) 311 { 312 my_syscall1(__NR_exit, status & 255); 313 while(1); /* shut the "noreturn" warnings. */ 314 } 315 316 static __attribute__((noreturn,unused)) 317 void _exit(int status) 318 { 319 sys_exit(status); 320 } 321 322 static __attribute__((noreturn,unused)) 323 void exit(int status) 324 { 325 _exit(status); 326 } 327 328 329 /* 330 * pid_t fork(void); 331 */ 332 333 #ifndef sys_fork 334 static __attribute__((unused)) 335 pid_t sys_fork(void) 336 { 337 #if defined(__NR_clone) 338 /* note: some archs only have clone() and not fork(). Different archs 339 * have a different API, but most archs have the flags on first arg and 340 * will not use the rest with no other flag. 341 */ 342 return my_syscall5(__NR_clone, SIGCHLD, 0, 0, 0, 0); 343 #elif defined(__NR_fork) 344 return my_syscall0(__NR_fork); 345 #else 346 return __nolibc_enosys(__func__); 347 #endif 348 } 349 #endif 350 351 static __attribute__((unused)) 352 pid_t fork(void) 353 { 354 return __sysret(sys_fork()); 355 } 356 357 #ifndef sys_vfork 358 static __attribute__((unused)) 359 pid_t sys_vfork(void) 360 { 361 #if defined(__NR_vfork) 362 return my_syscall0(__NR_vfork); 363 #elif defined(__NR_clone3) 364 /* 365 * clone() could be used but has different argument orders per 366 * architecture. 367 */ 368 struct clone_args args = { 369 .flags = CLONE_VM | CLONE_VFORK, 370 .exit_signal = SIGCHLD, 371 }; 372 373 return my_syscall2(__NR_clone3, &args, sizeof(args)); 374 #else 375 return __nolibc_enosys(__func__); 376 #endif 377 } 378 #endif 379 380 static __attribute__((unused)) 381 pid_t vfork(void) 382 { 383 return __sysret(sys_vfork()); 384 } 385 386 /* 387 * int fsync(int fd); 388 */ 389 390 static __attribute__((unused)) 391 int sys_fsync(int fd) 392 { 393 return my_syscall1(__NR_fsync, fd); 394 } 395 396 static __attribute__((unused)) 397 int fsync(int fd) 398 { 399 return __sysret(sys_fsync(fd)); 400 } 401 402 403 /* 404 * int getdents64(int fd, struct linux_dirent64 *dirp, int count); 405 */ 406 407 static __attribute__((unused)) 408 int sys_getdents64(int fd, struct linux_dirent64 *dirp, int count) 409 { 410 return my_syscall3(__NR_getdents64, fd, dirp, count); 411 } 412 413 static __attribute__((unused)) 414 int getdents64(int fd, struct linux_dirent64 *dirp, int count) 415 { 416 return __sysret(sys_getdents64(fd, dirp, count)); 417 } 418 419 420 /* 421 * uid_t geteuid(void); 422 */ 423 424 static __attribute__((unused)) 425 uid_t sys_geteuid(void) 426 { 427 #if defined(__NR_geteuid32) 428 return my_syscall0(__NR_geteuid32); 429 #else 430 return my_syscall0(__NR_geteuid); 431 #endif 432 } 433 434 static __attribute__((unused)) 435 uid_t geteuid(void) 436 { 437 return sys_geteuid(); 438 } 439 440 441 /* 442 * pid_t getpgid(pid_t pid); 443 */ 444 445 static __attribute__((unused)) 446 pid_t sys_getpgid(pid_t pid) 447 { 448 return my_syscall1(__NR_getpgid, pid); 449 } 450 451 static __attribute__((unused)) 452 pid_t getpgid(pid_t pid) 453 { 454 return __sysret(sys_getpgid(pid)); 455 } 456 457 458 /* 459 * pid_t getpgrp(void); 460 */ 461 462 static __attribute__((unused)) 463 pid_t sys_getpgrp(void) 464 { 465 return sys_getpgid(0); 466 } 467 468 static __attribute__((unused)) 469 pid_t getpgrp(void) 470 { 471 return sys_getpgrp(); 472 } 473 474 475 /* 476 * pid_t getpid(void); 477 */ 478 479 static __attribute__((unused)) 480 pid_t sys_getpid(void) 481 { 482 return my_syscall0(__NR_getpid); 483 } 484 485 static __attribute__((unused)) 486 pid_t getpid(void) 487 { 488 return sys_getpid(); 489 } 490 491 492 /* 493 * pid_t getppid(void); 494 */ 495 496 static __attribute__((unused)) 497 pid_t sys_getppid(void) 498 { 499 return my_syscall0(__NR_getppid); 500 } 501 502 static __attribute__((unused)) 503 pid_t getppid(void) 504 { 505 return sys_getppid(); 506 } 507 508 509 /* 510 * pid_t gettid(void); 511 */ 512 513 static __attribute__((unused)) 514 pid_t sys_gettid(void) 515 { 516 return my_syscall0(__NR_gettid); 517 } 518 519 static __attribute__((unused)) 520 pid_t gettid(void) 521 { 522 return sys_gettid(); 523 } 524 525 static unsigned long getauxval(unsigned long key); 526 527 /* 528 * int getpagesize(void); 529 */ 530 531 static __attribute__((unused)) 532 int getpagesize(void) 533 { 534 return __sysret((int)getauxval(AT_PAGESZ) ?: -ENOENT); 535 } 536 537 538 /* 539 * uid_t getuid(void); 540 */ 541 542 static __attribute__((unused)) 543 uid_t sys_getuid(void) 544 { 545 #if defined(__NR_getuid32) 546 return my_syscall0(__NR_getuid32); 547 #else 548 return my_syscall0(__NR_getuid); 549 #endif 550 } 551 552 static __attribute__((unused)) 553 uid_t getuid(void) 554 { 555 return sys_getuid(); 556 } 557 558 559 /* 560 * int kill(pid_t pid, int signal); 561 */ 562 563 static __attribute__((unused)) 564 int sys_kill(pid_t pid, int signal) 565 { 566 return my_syscall2(__NR_kill, pid, signal); 567 } 568 569 static __attribute__((unused)) 570 int kill(pid_t pid, int signal) 571 { 572 return __sysret(sys_kill(pid, signal)); 573 } 574 575 576 /* 577 * int link(const char *old, const char *new); 578 */ 579 580 static __attribute__((unused)) 581 int sys_link(const char *old, const char *new) 582 { 583 #if defined(__NR_linkat) 584 return my_syscall5(__NR_linkat, AT_FDCWD, old, AT_FDCWD, new, 0); 585 #elif defined(__NR_link) 586 return my_syscall2(__NR_link, old, new); 587 #else 588 return __nolibc_enosys(__func__, old, new); 589 #endif 590 } 591 592 static __attribute__((unused)) 593 int link(const char *old, const char *new) 594 { 595 return __sysret(sys_link(old, new)); 596 } 597 598 599 /* 600 * off_t lseek(int fd, off_t offset, int whence); 601 */ 602 603 static __attribute__((unused)) 604 off_t sys_lseek(int fd, off_t offset, int whence) 605 { 606 #if defined(__NR_lseek) 607 return my_syscall3(__NR_lseek, fd, offset, whence); 608 #else 609 return __nolibc_enosys(__func__, fd, offset, whence); 610 #endif 611 } 612 613 static __attribute__((unused)) 614 int sys_llseek(int fd, unsigned long offset_high, unsigned long offset_low, 615 __kernel_loff_t *result, int whence) 616 { 617 #if defined(__NR_llseek) 618 return my_syscall5(__NR_llseek, fd, offset_high, offset_low, result, whence); 619 #else 620 return __nolibc_enosys(__func__, fd, offset_high, offset_low, result, whence); 621 #endif 622 } 623 624 static __attribute__((unused)) 625 off_t lseek(int fd, off_t offset, int whence) 626 { 627 __kernel_loff_t loff = 0; 628 off_t result; 629 int ret; 630 631 result = sys_lseek(fd, offset, whence); 632 if (result == -ENOSYS) { 633 /* Only exists on 32bit where nolibc off_t is also 32bit */ 634 ret = sys_llseek(fd, 0, offset, &loff, whence); 635 if (ret < 0) 636 result = ret; 637 else if (loff != (off_t)loff) 638 result = -EOVERFLOW; 639 else 640 result = loff; 641 } 642 643 return __sysret(result); 644 } 645 646 647 /* 648 * int mkdir(const char *path, mode_t mode); 649 */ 650 651 static __attribute__((unused)) 652 int sys_mkdir(const char *path, mode_t mode) 653 { 654 #if defined(__NR_mkdirat) 655 return my_syscall3(__NR_mkdirat, AT_FDCWD, path, mode); 656 #elif defined(__NR_mkdir) 657 return my_syscall2(__NR_mkdir, path, mode); 658 #else 659 return __nolibc_enosys(__func__, path, mode); 660 #endif 661 } 662 663 static __attribute__((unused)) 664 int mkdir(const char *path, mode_t mode) 665 { 666 return __sysret(sys_mkdir(path, mode)); 667 } 668 669 /* 670 * int rmdir(const char *path); 671 */ 672 673 static __attribute__((unused)) 674 int sys_rmdir(const char *path) 675 { 676 #if defined(__NR_rmdir) 677 return my_syscall1(__NR_rmdir, path); 678 #elif defined(__NR_unlinkat) 679 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, AT_REMOVEDIR); 680 #else 681 return __nolibc_enosys(__func__, path); 682 #endif 683 } 684 685 static __attribute__((unused)) 686 int rmdir(const char *path) 687 { 688 return __sysret(sys_rmdir(path)); 689 } 690 691 692 /* 693 * int mknod(const char *path, mode_t mode, dev_t dev); 694 */ 695 696 static __attribute__((unused)) 697 long sys_mknod(const char *path, mode_t mode, dev_t dev) 698 { 699 #if defined(__NR_mknodat) 700 return my_syscall4(__NR_mknodat, AT_FDCWD, path, mode, dev); 701 #elif defined(__NR_mknod) 702 return my_syscall3(__NR_mknod, path, mode, dev); 703 #else 704 return __nolibc_enosys(__func__, path, mode, dev); 705 #endif 706 } 707 708 static __attribute__((unused)) 709 int mknod(const char *path, mode_t mode, dev_t dev) 710 { 711 return __sysret(sys_mknod(path, mode, dev)); 712 } 713 714 715 /* 716 * int pipe2(int pipefd[2], int flags); 717 * int pipe(int pipefd[2]); 718 */ 719 720 static __attribute__((unused)) 721 int sys_pipe2(int pipefd[2], int flags) 722 { 723 return my_syscall2(__NR_pipe2, pipefd, flags); 724 } 725 726 static __attribute__((unused)) 727 int pipe2(int pipefd[2], int flags) 728 { 729 return __sysret(sys_pipe2(pipefd, flags)); 730 } 731 732 static __attribute__((unused)) 733 int pipe(int pipefd[2]) 734 { 735 return pipe2(pipefd, 0); 736 } 737 738 739 /* 740 * int pivot_root(const char *new, const char *old); 741 */ 742 743 static __attribute__((unused)) 744 int sys_pivot_root(const char *new, const char *old) 745 { 746 return my_syscall2(__NR_pivot_root, new, old); 747 } 748 749 static __attribute__((unused)) 750 int pivot_root(const char *new, const char *old) 751 { 752 return __sysret(sys_pivot_root(new, old)); 753 } 754 755 756 /* 757 * ssize_t read(int fd, void *buf, size_t count); 758 */ 759 760 static __attribute__((unused)) 761 ssize_t sys_read(int fd, void *buf, size_t count) 762 { 763 return my_syscall3(__NR_read, fd, buf, count); 764 } 765 766 static __attribute__((unused)) 767 ssize_t read(int fd, void *buf, size_t count) 768 { 769 return __sysret(sys_read(fd, buf, count)); 770 } 771 772 773 /* 774 * int sched_yield(void); 775 */ 776 777 static __attribute__((unused)) 778 int sys_sched_yield(void) 779 { 780 return my_syscall0(__NR_sched_yield); 781 } 782 783 static __attribute__((unused)) 784 int sched_yield(void) 785 { 786 return __sysret(sys_sched_yield()); 787 } 788 789 790 /* 791 * int select(int nfds, fd_set *read_fds, fd_set *write_fds, 792 * fd_set *except_fds, struct timeval *timeout); 793 */ 794 795 static __attribute__((unused)) 796 int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 797 { 798 #if defined(__ARCH_WANT_SYS_OLD_SELECT) && !defined(__NR__newselect) 799 struct sel_arg_struct { 800 unsigned long n; 801 fd_set *r, *w, *e; 802 struct timeval *t; 803 } arg = { .n = nfds, .r = rfds, .w = wfds, .e = efds, .t = timeout }; 804 return my_syscall1(__NR_select, &arg); 805 #elif defined(__NR__newselect) 806 return my_syscall5(__NR__newselect, nfds, rfds, wfds, efds, timeout); 807 #elif defined(__NR_select) 808 return my_syscall5(__NR_select, nfds, rfds, wfds, efds, timeout); 809 #elif defined(__NR_pselect6) 810 struct timespec t; 811 812 if (timeout) { 813 t.tv_sec = timeout->tv_sec; 814 t.tv_nsec = timeout->tv_usec * 1000; 815 } 816 return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 817 #elif defined(__NR_pselect6_time64) 818 struct __kernel_timespec t; 819 820 if (timeout) { 821 t.tv_sec = timeout->tv_sec; 822 t.tv_nsec = timeout->tv_usec * 1000; 823 } 824 return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL); 825 #else 826 return __nolibc_enosys(__func__, nfds, rfds, wfds, efds, timeout); 827 #endif 828 } 829 830 static __attribute__((unused)) 831 int select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout) 832 { 833 return __sysret(sys_select(nfds, rfds, wfds, efds, timeout)); 834 } 835 836 837 /* 838 * int setpgid(pid_t pid, pid_t pgid); 839 */ 840 841 static __attribute__((unused)) 842 int sys_setpgid(pid_t pid, pid_t pgid) 843 { 844 return my_syscall2(__NR_setpgid, pid, pgid); 845 } 846 847 static __attribute__((unused)) 848 int setpgid(pid_t pid, pid_t pgid) 849 { 850 return __sysret(sys_setpgid(pid, pgid)); 851 } 852 853 /* 854 * pid_t setpgrp(void) 855 */ 856 857 static __attribute__((unused)) 858 pid_t setpgrp(void) 859 { 860 return setpgid(0, 0); 861 } 862 863 864 /* 865 * pid_t setsid(void); 866 */ 867 868 static __attribute__((unused)) 869 pid_t sys_setsid(void) 870 { 871 return my_syscall0(__NR_setsid); 872 } 873 874 static __attribute__((unused)) 875 pid_t setsid(void) 876 { 877 return __sysret(sys_setsid()); 878 } 879 880 881 /* 882 * int symlink(const char *old, const char *new); 883 */ 884 885 static __attribute__((unused)) 886 int sys_symlink(const char *old, const char *new) 887 { 888 #if defined(__NR_symlinkat) 889 return my_syscall3(__NR_symlinkat, old, AT_FDCWD, new); 890 #elif defined(__NR_symlink) 891 return my_syscall2(__NR_symlink, old, new); 892 #else 893 return __nolibc_enosys(__func__, old, new); 894 #endif 895 } 896 897 static __attribute__((unused)) 898 int symlink(const char *old, const char *new) 899 { 900 return __sysret(sys_symlink(old, new)); 901 } 902 903 904 /* 905 * mode_t umask(mode_t mode); 906 */ 907 908 static __attribute__((unused)) 909 mode_t sys_umask(mode_t mode) 910 { 911 return my_syscall1(__NR_umask, mode); 912 } 913 914 static __attribute__((unused)) 915 mode_t umask(mode_t mode) 916 { 917 return sys_umask(mode); 918 } 919 920 921 /* 922 * int umount2(const char *path, int flags); 923 */ 924 925 static __attribute__((unused)) 926 int sys_umount2(const char *path, int flags) 927 { 928 return my_syscall2(__NR_umount2, path, flags); 929 } 930 931 static __attribute__((unused)) 932 int umount2(const char *path, int flags) 933 { 934 return __sysret(sys_umount2(path, flags)); 935 } 936 937 938 /* 939 * int unlink(const char *path); 940 */ 941 942 static __attribute__((unused)) 943 int sys_unlink(const char *path) 944 { 945 #if defined(__NR_unlinkat) 946 return my_syscall3(__NR_unlinkat, AT_FDCWD, path, 0); 947 #elif defined(__NR_unlink) 948 return my_syscall1(__NR_unlink, path); 949 #else 950 return __nolibc_enosys(__func__, path); 951 #endif 952 } 953 954 static __attribute__((unused)) 955 int unlink(const char *path) 956 { 957 return __sysret(sys_unlink(path)); 958 } 959 960 961 /* 962 * ssize_t write(int fd, const void *buf, size_t count); 963 */ 964 965 static __attribute__((unused)) 966 ssize_t sys_write(int fd, const void *buf, size_t count) 967 { 968 return my_syscall3(__NR_write, fd, buf, count); 969 } 970 971 static __attribute__((unused)) 972 ssize_t write(int fd, const void *buf, size_t count) 973 { 974 return __sysret(sys_write(fd, buf, count)); 975 } 976 977 978 /* 979 * int memfd_create(const char *name, unsigned int flags); 980 */ 981 982 static __attribute__((unused)) 983 int sys_memfd_create(const char *name, unsigned int flags) 984 { 985 return my_syscall2(__NR_memfd_create, name, flags); 986 } 987 988 static __attribute__((unused)) 989 int memfd_create(const char *name, unsigned int flags) 990 { 991 return __sysret(sys_memfd_create(name, flags)); 992 } 993 994 #endif /* _NOLIBC_SYS_H */ 995