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