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
__nolibc_enosys(const char * syscall,...)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))
sys_brk(void * addr)87 void *sys_brk(void *addr)
88 {
89 return (void *)my_syscall1(__NR_brk, addr);
90 }
91
92 static __attribute__((unused))
brk(void * addr)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))
sbrk(intptr_t inc)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))
sys_chdir(const char * path)123 int sys_chdir(const char *path)
124 {
125 return my_syscall1(__NR_chdir, path);
126 }
127
128 static __attribute__((unused))
chdir(const char * path)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))
sys_chmod(const char * path,mode_t mode)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))
chmod(const char * path,mode_t mode)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))
sys_chown(const char * path,uid_t owner,gid_t group)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))
chown(const char * path,uid_t owner,gid_t group)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))
sys_chroot(const char * path)186 int sys_chroot(const char *path)
187 {
188 return my_syscall1(__NR_chroot, path);
189 }
190
191 static __attribute__((unused))
chroot(const char * path)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))
sys_close(int fd)203 int sys_close(int fd)
204 {
205 return my_syscall1(__NR_close, fd);
206 }
207
208 static __attribute__((unused))
close(int fd)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))
sys_dup(int fd)220 int sys_dup(int fd)
221 {
222 return my_syscall1(__NR_dup, fd);
223 }
224
225 static __attribute__((unused))
dup(int fd)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))
sys_dup2(int old,int new)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))
dup2(int old,int new)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))
sys_dup3(int old,int new,int flags)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))
dup3(int old,int new,int flags)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))
sys_execve(const char * filename,char * const argv[],char * const envp[])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))
execve(const char * filename,char * const argv[],char * const envp[])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))
sys_exit(int status)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))
_exit(int status)303 void _exit(int status)
304 {
305 sys_exit(status);
306 }
307
308 static __attribute__((noreturn,unused))
exit(int status)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))
sys_fork(void)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))
fork(void)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))
sys_fsync(int fd)349 int sys_fsync(int fd)
350 {
351 return my_syscall1(__NR_fsync, fd);
352 }
353
354 static __attribute__((unused))
fsync(int fd)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))
sys_getdents64(int fd,struct linux_dirent64 * dirp,int count)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))
getdents64(int fd,struct linux_dirent64 * dirp,int count)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))
sys_geteuid(void)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))
geteuid(void)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))
sys_getpgid(pid_t pid)404 pid_t sys_getpgid(pid_t pid)
405 {
406 return my_syscall1(__NR_getpgid, pid);
407 }
408
409 static __attribute__((unused))
getpgid(pid_t pid)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))
sys_getpgrp(void)421 pid_t sys_getpgrp(void)
422 {
423 return sys_getpgid(0);
424 }
425
426 static __attribute__((unused))
getpgrp(void)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))
sys_getpid(void)438 pid_t sys_getpid(void)
439 {
440 return my_syscall0(__NR_getpid);
441 }
442
443 static __attribute__((unused))
getpid(void)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))
sys_getppid(void)455 pid_t sys_getppid(void)
456 {
457 return my_syscall0(__NR_getppid);
458 }
459
460 static __attribute__((unused))
getppid(void)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))
sys_gettid(void)472 pid_t sys_gettid(void)
473 {
474 return my_syscall0(__NR_gettid);
475 }
476
477 static __attribute__((unused))
gettid(void)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))
getpagesize(void)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))
sys_getuid(void)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))
getuid(void)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))
sys_kill(pid_t pid,int signal)522 int sys_kill(pid_t pid, int signal)
523 {
524 return my_syscall2(__NR_kill, pid, signal);
525 }
526
527 static __attribute__((unused))
kill(pid_t pid,int signal)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))
sys_link(const char * old,const char * new)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))
link(const char * old,const char * new)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))
sys_lseek(int fd,off_t offset,int whence)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))
sys_llseek(int fd,unsigned long offset_high,unsigned long offset_low,__kernel_loff_t * result,int whence)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))
lseek(int fd,off_t offset,int whence)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))
sys_mkdir(const char * path,mode_t mode)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))
mkdir(const char * path,mode_t mode)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))
sys_rmdir(const char * path)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))
rmdir(const char * path)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))
sys_mknod(const char * path,mode_t mode,dev_t dev)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))
mknod(const char * path,mode_t mode,dev_t dev)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))
sys_pipe2(int pipefd[2],int flags)679 int sys_pipe2(int pipefd[2], int flags)
680 {
681 return my_syscall2(__NR_pipe2, pipefd, flags);
682 }
683
684 static __attribute__((unused))
pipe2(int pipefd[2],int flags)685 int pipe2(int pipefd[2], int flags)
686 {
687 return __sysret(sys_pipe2(pipefd, flags));
688 }
689
690 static __attribute__((unused))
pipe(int pipefd[2])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))
sys_pivot_root(const char * new,const char * old)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))
pivot_root(const char * new,const char * old)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))
sys_read(int fd,void * buf,size_t count)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))
read(int fd,void * buf,size_t count)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))
sys_sched_yield(void)736 int sys_sched_yield(void)
737 {
738 return my_syscall0(__NR_sched_yield);
739 }
740
741 static __attribute__((unused))
sched_yield(void)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))
sys_select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * efds,struct timeval * timeout)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))
select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * efds,struct timeval * timeout)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))
sys_setpgid(pid_t pid,pid_t pgid)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))
setpgid(pid_t pid,pid_t pgid)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))
setpgrp(void)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))
sys_setsid(void)827 pid_t sys_setsid(void)
828 {
829 return my_syscall0(__NR_setsid);
830 }
831
832 static __attribute__((unused))
setsid(void)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))
sys_symlink(const char * old,const char * new)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))
symlink(const char * old,const char * new)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))
sys_umask(mode_t mode)867 mode_t sys_umask(mode_t mode)
868 {
869 return my_syscall1(__NR_umask, mode);
870 }
871
872 static __attribute__((unused))
umask(mode_t mode)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))
sys_umount2(const char * path,int flags)884 int sys_umount2(const char *path, int flags)
885 {
886 return my_syscall2(__NR_umount2, path, flags);
887 }
888
889 static __attribute__((unused))
umount2(const char * path,int flags)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))
sys_unlink(const char * path)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))
unlink(const char * path)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))
sys_write(int fd,const void * buf,size_t count)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))
write(int fd,const void * buf,size_t count)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))
sys_memfd_create(const char * name,unsigned int flags)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))
memfd_create(const char * name,unsigned int flags)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