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