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