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