Merge tag 'nolibc-20250526-for-6.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/nolibc/linux-nolibc
Pull nolibc updates from Thomas Weißschuh: - New supported architectures: m68k, SPARC (32 and 64 bit) - Compatibility with kselftest_harness.h - A more robust mechanism to include all of nolibc from each header - Split existing features into new headers to simplify adoption - Compatibility with UBSAN and it is used in the testsuite - Many small new features focussing on usage in kselftests * tag 'nolibc-20250526-for-6.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/nolibc/linux-nolibc: (83 commits) selftests: harness: Stop using setjmp()/longjmp() selftests: harness: Add "variant" and "self" to test metadata selftests: harness: Add teardown callback to test metadata selftests: harness: Move teardown conditional into test metadata selftests: harness: Don't set setup_completed for fixtureless tests selftests: harness: Implement test timeouts through pidfd selftests: harness: Remove dependency on libatomic selftests: harness: Remove inline qualifier for wrappers selftests: harness: Mark functions without prototypes static selftests: harness: Ignore unused variant argument warning selftests: harness: Use C89 comment style selftests: harness: Add kselftest harness selftest selftests/nolibc: drop include guards around standard headers tools/nolibc: move NULL and offsetof() to sys/stddef.h tools/nolibc: move uname() and friends to sys/utsname.h tools/nolibc: move makedev() and friends to sys/sysmacros.h tools/nolibc: move getrlimit() and friends to sys/resource.h tools/nolibc: move reboot() to sys/reboot.h tools/nolibc: move prctl() to sys/prctl.h tools/nolibc: move mount() to sys/mount.h ...
This commit is contained in:
@@ -30,18 +30,41 @@ all_files := \
|
||||
crt.h \
|
||||
ctype.h \
|
||||
dirent.h \
|
||||
elf.h \
|
||||
errno.h \
|
||||
fcntl.h \
|
||||
getopt.h \
|
||||
limits.h \
|
||||
math.h \
|
||||
nolibc.h \
|
||||
poll.h \
|
||||
sched.h \
|
||||
signal.h \
|
||||
stackprotector.h \
|
||||
std.h \
|
||||
stdarg.h \
|
||||
stdbool.h \
|
||||
stddef.h \
|
||||
stdint.h \
|
||||
stdlib.h \
|
||||
string.h \
|
||||
sys.h \
|
||||
sys/auxv.h \
|
||||
sys/ioctl.h \
|
||||
sys/mman.h \
|
||||
sys/mount.h \
|
||||
sys/prctl.h \
|
||||
sys/random.h \
|
||||
sys/reboot.h \
|
||||
sys/resource.h \
|
||||
sys/stat.h \
|
||||
sys/syscall.h \
|
||||
sys/sysmacros.h \
|
||||
sys/time.h \
|
||||
sys/timerfd.h \
|
||||
sys/types.h \
|
||||
sys/utsname.h \
|
||||
sys/wait.h \
|
||||
time.h \
|
||||
types.h \
|
||||
unistd.h \
|
||||
@@ -72,7 +95,7 @@ help:
|
||||
headers:
|
||||
$(Q)mkdir -p $(OUTPUT)sysroot
|
||||
$(Q)mkdir -p $(OUTPUT)sysroot/include
|
||||
$(Q)cp $(all_files) $(OUTPUT)sysroot/include/
|
||||
$(Q)cp --parents $(all_files) $(OUTPUT)sysroot/include/
|
||||
$(Q)if [ "$(ARCH)" = "x86" ]; then \
|
||||
sed -e \
|
||||
's,^#ifndef _NOLIBC_ARCH_X86_64_H,#if !defined(_NOLIBC_ARCH_X86_64_H) \&\& defined(__x86_64__),' \
|
||||
@@ -91,5 +114,14 @@ headers_standalone: headers
|
||||
$(Q)$(MAKE) -C $(srctree) headers
|
||||
$(Q)$(MAKE) -C $(srctree) headers_install INSTALL_HDR_PATH=$(OUTPUT)sysroot
|
||||
|
||||
# GCC uses "s390", clang "systemz"
|
||||
CLANG_CROSS_FLAGS := $(subst --target=s390-linux,--target=systemz-linux,$(CLANG_CROSS_FLAGS))
|
||||
|
||||
headers_check: headers_standalone
|
||||
for header in $(filter-out crt.h std.h,$(all_files)); do \
|
||||
$(CC) $(CLANG_CROSS_FLAGS) -Wall -Werror -nostdinc -fsyntax-only -x c /dev/null \
|
||||
-I$(or $(objtree),$(srctree))/usr/include -include $$header -include $$header || exit 1; \
|
||||
done
|
||||
|
||||
clean:
|
||||
$(call QUIET_CLEAN, nolibc) rm -rf "$(OUTPUT)sysroot"
|
||||
|
||||
@@ -146,7 +146,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
|
||||
{
|
||||
__asm__ volatile (
|
||||
"mov x0, sp\n" /* save stack pointer to x0, as arg1 of _start_c */
|
||||
"and sp, x0, -16\n" /* sp must be 16-byte aligned in the callee */
|
||||
"bl _start_c\n" /* transfer to c runtime */
|
||||
);
|
||||
__nolibc_entrypoint_epilogue();
|
||||
|
||||
@@ -189,8 +189,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
|
||||
{
|
||||
__asm__ volatile (
|
||||
"mov r0, sp\n" /* save stack pointer to %r0, as arg1 of _start_c */
|
||||
"and ip, r0, #-8\n" /* sp must be 8-byte aligned in the callee */
|
||||
"mov sp, ip\n"
|
||||
"bl _start_c\n" /* transfer to c runtime */
|
||||
);
|
||||
__nolibc_entrypoint_epilogue();
|
||||
|
||||
@@ -167,8 +167,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
|
||||
__asm__ volatile (
|
||||
"xor %ebp, %ebp\n" /* zero the stack frame */
|
||||
"mov %esp, %eax\n" /* save stack pointer to %eax, as arg1 of _start_c */
|
||||
"add $12, %esp\n" /* avoid over-estimating after the 'and' & 'sub' below */
|
||||
"and $-16, %esp\n" /* the %esp must be 16-byte aligned on 'call' */
|
||||
"sub $12, %esp\n" /* sub 12 to keep it aligned after the push %eax */
|
||||
"push %eax\n" /* push arg1 on stack to support plain stack modes too */
|
||||
"call _start_c\n" /* transfer to c runtime */
|
||||
|
||||
@@ -142,18 +142,11 @@
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#if __loongarch_grlen == 32
|
||||
#define LONG_BSTRINS "bstrins.w"
|
||||
#else /* __loongarch_grlen == 64 */
|
||||
#define LONG_BSTRINS "bstrins.d"
|
||||
#endif
|
||||
|
||||
/* startup code */
|
||||
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"move $a0, $sp\n" /* save stack pointer to $a0, as arg1 of _start_c */
|
||||
LONG_BSTRINS " $sp, $zero, 3, 0\n" /* $sp must be 16-byte aligned */
|
||||
"bl _start_c\n" /* transfer to c runtime */
|
||||
);
|
||||
__nolibc_entrypoint_epilogue();
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* m68k specific definitions for NOLIBC
|
||||
* Copyright (C) 2025 Daniel Palmer<daniel@thingy.jp>
|
||||
*
|
||||
* Roughly based on one or more of the other arch files.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NOLIBC_ARCH_M68K_H
|
||||
#define _NOLIBC_ARCH_M68K_H
|
||||
|
||||
#include "compiler.h"
|
||||
#include "crt.h"
|
||||
|
||||
#define _NOLIBC_SYSCALL_CLOBBERLIST "memory"
|
||||
|
||||
#define my_syscall0(num) \
|
||||
({ \
|
||||
register long _num __asm__ ("d0") = (num); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap #0\n" \
|
||||
: "+r"(_num) \
|
||||
: "r"(_num) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_num; \
|
||||
})
|
||||
|
||||
#define my_syscall1(num, arg1) \
|
||||
({ \
|
||||
register long _num __asm__ ("d0") = (num); \
|
||||
register long _arg1 __asm__ ("d1") = (long)(arg1); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap #0\n" \
|
||||
: "+r"(_num) \
|
||||
: "r"(_arg1) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_num; \
|
||||
})
|
||||
|
||||
#define my_syscall2(num, arg1, arg2) \
|
||||
({ \
|
||||
register long _num __asm__ ("d0") = (num); \
|
||||
register long _arg1 __asm__ ("d1") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("d2") = (long)(arg2); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap #0\n" \
|
||||
: "+r"(_num) \
|
||||
: "r"(_arg1), "r"(_arg2) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_num; \
|
||||
})
|
||||
|
||||
#define my_syscall3(num, arg1, arg2, arg3) \
|
||||
({ \
|
||||
register long _num __asm__ ("d0") = (num); \
|
||||
register long _arg1 __asm__ ("d1") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("d2") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("d3") = (long)(arg3); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap #0\n" \
|
||||
: "+r"(_num) \
|
||||
: "r"(_arg1), "r"(_arg2), "r"(_arg3) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_num; \
|
||||
})
|
||||
|
||||
#define my_syscall4(num, arg1, arg2, arg3, arg4) \
|
||||
({ \
|
||||
register long _num __asm__ ("d0") = (num); \
|
||||
register long _arg1 __asm__ ("d1") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("d2") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("d3") = (long)(arg3); \
|
||||
register long _arg4 __asm__ ("d4") = (long)(arg4); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap #0\n" \
|
||||
: "+r" (_num) \
|
||||
: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_num; \
|
||||
})
|
||||
|
||||
#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
|
||||
({ \
|
||||
register long _num __asm__ ("d0") = (num); \
|
||||
register long _arg1 __asm__ ("d1") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("d2") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("d3") = (long)(arg3); \
|
||||
register long _arg4 __asm__ ("d4") = (long)(arg4); \
|
||||
register long _arg5 __asm__ ("d5") = (long)(arg5); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap #0\n" \
|
||||
: "+r" (_num) \
|
||||
: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_num; \
|
||||
})
|
||||
|
||||
#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
|
||||
({ \
|
||||
register long _num __asm__ ("d0") = (num); \
|
||||
register long _arg1 __asm__ ("d1") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("d2") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("d3") = (long)(arg3); \
|
||||
register long _arg4 __asm__ ("d4") = (long)(arg4); \
|
||||
register long _arg5 __asm__ ("d5") = (long)(arg5); \
|
||||
register long _arg6 __asm__ ("a0") = (long)(arg6); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
"trap #0\n" \
|
||||
: "+r" (_num) \
|
||||
: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
|
||||
"r"(_arg6) \
|
||||
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
||||
); \
|
||||
_num; \
|
||||
})
|
||||
|
||||
void _start(void);
|
||||
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"movel %sp, %sp@-\n"
|
||||
"jsr _start_c\n"
|
||||
);
|
||||
__nolibc_entrypoint_epilogue();
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_ARCH_M68K_H */
|
||||
@@ -201,7 +201,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
|
||||
|
||||
__asm__ volatile (
|
||||
"mr 3, 1\n" /* save stack pointer to r3, as arg1 of _start_c */
|
||||
"clrrdi 1, 1, 4\n" /* align the stack to 16 bytes */
|
||||
"li 0, 0\n" /* zero the frame pointer */
|
||||
"stdu 1, -32(1)\n" /* the initial stack frame */
|
||||
"bl _start_c\n" /* transfer to c runtime */
|
||||
@@ -209,7 +208,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
|
||||
#else
|
||||
__asm__ volatile (
|
||||
"mr 3, 1\n" /* save stack pointer to r3, as arg1 of _start_c */
|
||||
"clrrwi 1, 1, 4\n" /* align the stack to 16 bytes */
|
||||
"li 0, 0\n" /* zero the frame pointer */
|
||||
"stwu 1, -16(1)\n" /* the initial stack frame */
|
||||
"bl _start_c\n" /* transfer to c runtime */
|
||||
|
||||
@@ -148,7 +148,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
|
||||
"lla gp, __global_pointer$\n"
|
||||
".option pop\n"
|
||||
"mv a0, sp\n" /* save stack pointer to a0, as arg1 of _start_c */
|
||||
"andi sp, a0, -16\n" /* sp must be 16-byte aligned */
|
||||
"call _start_c\n" /* transfer to c runtime */
|
||||
);
|
||||
__nolibc_entrypoint_epilogue();
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* SPARC (32bit and 64bit) specific definitions for NOLIBC
|
||||
* Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
|
||||
*/
|
||||
|
||||
#ifndef _NOLIBC_ARCH_SPARC_H
|
||||
#define _NOLIBC_ARCH_SPARC_H
|
||||
|
||||
#include <linux/unistd.h>
|
||||
|
||||
#include "compiler.h"
|
||||
#include "crt.h"
|
||||
|
||||
/*
|
||||
* Syscalls for SPARC:
|
||||
* - registers are native word size
|
||||
* - syscall number is passed in g1
|
||||
* - arguments are in o0-o5
|
||||
* - the system call is performed by calling a trap instruction
|
||||
* - syscall return value is in o0
|
||||
* - syscall error flag is in the carry bit of the processor status register
|
||||
*/
|
||||
|
||||
#ifdef __arch64__
|
||||
|
||||
#define _NOLIBC_SYSCALL "t 0x6d\n" \
|
||||
"bcs,a %%xcc, 1f\n" \
|
||||
"sub %%g0, %%o0, %%o0\n" \
|
||||
"1:\n"
|
||||
|
||||
#else
|
||||
|
||||
#define _NOLIBC_SYSCALL "t 0x10\n" \
|
||||
"bcs,a 1f\n" \
|
||||
"sub %%g0, %%o0, %%o0\n" \
|
||||
"1:\n"
|
||||
|
||||
#endif /* __arch64__ */
|
||||
|
||||
#define my_syscall0(num) \
|
||||
({ \
|
||||
register long _num __asm__ ("g1") = (num); \
|
||||
register long _arg1 __asm__ ("o0"); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
_NOLIBC_SYSCALL \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_num) \
|
||||
: "memory", "cc" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define my_syscall1(num, arg1) \
|
||||
({ \
|
||||
register long _num __asm__ ("g1") = (num); \
|
||||
register long _arg1 __asm__ ("o0") = (long)(arg1); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
_NOLIBC_SYSCALL \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_num) \
|
||||
: "memory", "cc" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define my_syscall2(num, arg1, arg2) \
|
||||
({ \
|
||||
register long _num __asm__ ("g1") = (num); \
|
||||
register long _arg1 __asm__ ("o0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("o1") = (long)(arg2); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
_NOLIBC_SYSCALL \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), "r"(_num) \
|
||||
: "memory", "cc" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define my_syscall3(num, arg1, arg2, arg3) \
|
||||
({ \
|
||||
register long _num __asm__ ("g1") = (num); \
|
||||
register long _arg1 __asm__ ("o0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("o1") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("o2") = (long)(arg3); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
_NOLIBC_SYSCALL \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), "r"(_arg3), "r"(_num) \
|
||||
: "memory", "cc" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define my_syscall4(num, arg1, arg2, arg3, arg4) \
|
||||
({ \
|
||||
register long _num __asm__ ("g1") = (num); \
|
||||
register long _arg1 __asm__ ("o0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("o1") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("o2") = (long)(arg3); \
|
||||
register long _arg4 __asm__ ("o3") = (long)(arg4); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
_NOLIBC_SYSCALL \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_num) \
|
||||
: "memory", "cc" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
|
||||
({ \
|
||||
register long _num __asm__ ("g1") = (num); \
|
||||
register long _arg1 __asm__ ("o0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("o1") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("o2") = (long)(arg3); \
|
||||
register long _arg4 __asm__ ("o3") = (long)(arg4); \
|
||||
register long _arg5 __asm__ ("o4") = (long)(arg5); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
_NOLIBC_SYSCALL \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_num) \
|
||||
: "memory", "cc" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
|
||||
({ \
|
||||
register long _num __asm__ ("g1") = (num); \
|
||||
register long _arg1 __asm__ ("o0") = (long)(arg1); \
|
||||
register long _arg2 __asm__ ("o1") = (long)(arg2); \
|
||||
register long _arg3 __asm__ ("o2") = (long)(arg3); \
|
||||
register long _arg4 __asm__ ("o3") = (long)(arg4); \
|
||||
register long _arg5 __asm__ ("o4") = (long)(arg5); \
|
||||
register long _arg6 __asm__ ("o5") = (long)(arg6); \
|
||||
\
|
||||
__asm__ volatile ( \
|
||||
_NOLIBC_SYSCALL \
|
||||
: "+r"(_arg1) \
|
||||
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
|
||||
"r"(_num) \
|
||||
: "memory", "cc" \
|
||||
); \
|
||||
_arg1; \
|
||||
})
|
||||
|
||||
/* startup code */
|
||||
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
/*
|
||||
* Save argc pointer to o0, as arg1 of _start_c.
|
||||
* Account for the window save area, which is 16 registers wide.
|
||||
*/
|
||||
#ifdef __arch64__
|
||||
"add %sp, 128 + 2047, %o0\n" /* on sparc64 / v9 the stack is offset by 2047 */
|
||||
#else
|
||||
"add %sp, 64, %o0\n"
|
||||
#endif
|
||||
"b,a _start_c\n" /* transfer to c runtime */
|
||||
);
|
||||
__nolibc_entrypoint_epilogue();
|
||||
}
|
||||
|
||||
static pid_t getpid(void);
|
||||
|
||||
static __attribute__((unused))
|
||||
pid_t sys_fork(void)
|
||||
{
|
||||
pid_t parent, ret;
|
||||
|
||||
parent = getpid();
|
||||
ret = my_syscall0(__NR_fork);
|
||||
|
||||
/* The syscall returns the parent pid in the child instead of 0 */
|
||||
if (ret == parent)
|
||||
return 0;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
#define sys_fork sys_fork
|
||||
|
||||
#endif /* _NOLIBC_ARCH_SPARC_H */
|
||||
@@ -166,7 +166,6 @@ void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _s
|
||||
__asm__ volatile (
|
||||
"xor %ebp, %ebp\n" /* zero the stack frame */
|
||||
"mov %rsp, %rdi\n" /* save stack pointer to %rdi, as arg1 of _start_c */
|
||||
"and $-16, %rsp\n" /* %rsp must be 16-byte aligned before call */
|
||||
"call _start_c\n" /* transfer to c runtime */
|
||||
"hlt\n" /* ensure it does not return */
|
||||
);
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
#include "arch-s390.h"
|
||||
#elif defined(__loongarch__)
|
||||
#include "arch-loongarch.h"
|
||||
#elif defined(__sparc__)
|
||||
#include "arch-sparc.h"
|
||||
#elif defined(__m68k__)
|
||||
#include "arch-m68k.h"
|
||||
#else
|
||||
#error Unsupported Architecture
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,15 @@
|
||||
# define __nolibc_has_attribute(attr) 0
|
||||
#endif
|
||||
|
||||
#if defined(__has_feature)
|
||||
# define __nolibc_has_feature(feature) __has_feature(feature)
|
||||
#else
|
||||
# define __nolibc_has_feature(feature) 0
|
||||
#endif
|
||||
|
||||
#define __nolibc_aligned(alignment) __attribute__((aligned(alignment)))
|
||||
#define __nolibc_aligned_as(type) __nolibc_aligned(__alignof__(type))
|
||||
|
||||
#if __nolibc_has_attribute(naked)
|
||||
# define __nolibc_entrypoint __attribute__((naked))
|
||||
# define __nolibc_entrypoint_epilogue()
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#ifndef _NOLIBC_CRT_H
|
||||
#define _NOLIBC_CRT_H
|
||||
|
||||
#include "compiler.h"
|
||||
|
||||
char **environ __attribute__((weak));
|
||||
const unsigned long *_auxv __attribute__((weak));
|
||||
|
||||
@@ -25,6 +27,9 @@ extern void (*const __fini_array_end[])(void) __attribute__((weak));
|
||||
|
||||
void _start_c(long *sp);
|
||||
__attribute__((weak,used))
|
||||
#if __nolibc_has_feature(undefined_behavior_sanitizer)
|
||||
__attribute__((no_sanitize("function")))
|
||||
#endif
|
||||
void _start_c(long *sp)
|
||||
{
|
||||
long argc;
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_CTYPE_H
|
||||
#define _NOLIBC_CTYPE_H
|
||||
|
||||
@@ -96,7 +99,4 @@ int ispunct(int c)
|
||||
return isgraph(c) && !isalnum(c);
|
||||
}
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#endif /* _NOLIBC_CTYPE_H */
|
||||
|
||||
@@ -4,11 +4,16 @@
|
||||
* Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_DIRENT_H
|
||||
#define _NOLIBC_DIRENT_H
|
||||
|
||||
#include "compiler.h"
|
||||
#include "stdint.h"
|
||||
#include "types.h"
|
||||
#include "fcntl.h"
|
||||
|
||||
#include <linux/limits.h>
|
||||
|
||||
@@ -58,7 +63,7 @@ int closedir(DIR *dirp)
|
||||
static __attribute__((unused))
|
||||
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
|
||||
{
|
||||
char buf[sizeof(struct linux_dirent64) + NAME_MAX + 1];
|
||||
char buf[sizeof(struct linux_dirent64) + NAME_MAX + 1] __nolibc_aligned_as(struct linux_dirent64);
|
||||
struct linux_dirent64 *ldir = (void *)buf;
|
||||
intptr_t i = (intptr_t)dirp;
|
||||
int fd, ret;
|
||||
@@ -92,7 +97,4 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#endif /* _NOLIBC_DIRENT_H */
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* Shim elf.h header for NOLIBC.
|
||||
* Copyright (C) 2025 Thomas Weißschuh <thomas.weissschuh@linutronix.de>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_ELF_H
|
||||
#define _NOLIBC_SYS_ELF_H
|
||||
|
||||
#include <linux/elf.h>
|
||||
|
||||
#endif /* _NOLIBC_SYS_ELF_H */
|
||||
@@ -4,6 +4,9 @@
|
||||
* Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_ERRNO_H
|
||||
#define _NOLIBC_ERRNO_H
|
||||
|
||||
@@ -22,7 +25,4 @@ int errno __attribute__((weak));
|
||||
*/
|
||||
#define MAX_ERRNO 4095
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#endif /* _NOLIBC_ERRNO_H */
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* fcntl definition for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_FCNTL_H
|
||||
#define _NOLIBC_FCNTL_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "types.h"
|
||||
#include "sys.h"
|
||||
|
||||
/*
|
||||
* int openat(int dirfd, const char *path, int flags[, mode_t mode]);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_openat(int dirfd, const char *path, int flags, mode_t mode)
|
||||
{
|
||||
return my_syscall4(__NR_openat, dirfd, path, flags, mode);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int openat(int dirfd, const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
|
||||
if (flags & O_CREAT) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, flags);
|
||||
mode = va_arg(args, mode_t);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
return __sysret(sys_openat(dirfd, path, flags, mode));
|
||||
}
|
||||
|
||||
/*
|
||||
* int open(const char *path, int flags[, mode_t mode]);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_open(const char *path, int flags, mode_t mode)
|
||||
{
|
||||
return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int open(const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
|
||||
if (flags & O_CREAT) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, flags);
|
||||
mode = va_arg(args, mode_t);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
return __sysret(sys_open(path, flags, mode));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_FCNTL_H */
|
||||
@@ -0,0 +1,101 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* getopt function definitions for NOLIBC, adapted from musl libc
|
||||
* Copyright (C) 2005-2020 Rich Felker, et al.
|
||||
* Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_GETOPT_H
|
||||
#define _NOLIBC_GETOPT_H
|
||||
|
||||
struct FILE;
|
||||
static struct FILE *const stderr;
|
||||
static int fprintf(struct FILE *stream, const char *fmt, ...);
|
||||
|
||||
__attribute__((weak,unused,section(".data.nolibc_getopt")))
|
||||
char *optarg;
|
||||
|
||||
__attribute__((weak,unused,section(".data.nolibc_getopt")))
|
||||
int optind = 1, opterr = 1, optopt;
|
||||
|
||||
static __attribute__((unused))
|
||||
int getopt(int argc, char * const argv[], const char *optstring)
|
||||
{
|
||||
static int __optpos;
|
||||
int i;
|
||||
char c, d;
|
||||
char *optchar;
|
||||
|
||||
if (!optind) {
|
||||
__optpos = 0;
|
||||
optind = 1;
|
||||
}
|
||||
|
||||
if (optind >= argc || !argv[optind])
|
||||
return -1;
|
||||
|
||||
if (argv[optind][0] != '-') {
|
||||
if (optstring[0] == '-') {
|
||||
optarg = argv[optind++];
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!argv[optind][1])
|
||||
return -1;
|
||||
|
||||
if (argv[optind][1] == '-' && !argv[optind][2])
|
||||
return optind++, -1;
|
||||
|
||||
if (!__optpos)
|
||||
__optpos++;
|
||||
c = argv[optind][__optpos];
|
||||
optchar = argv[optind] + __optpos;
|
||||
__optpos++;
|
||||
|
||||
if (!argv[optind][__optpos]) {
|
||||
optind++;
|
||||
__optpos = 0;
|
||||
}
|
||||
|
||||
if (optstring[0] == '-' || optstring[0] == '+')
|
||||
optstring++;
|
||||
|
||||
i = 0;
|
||||
d = 0;
|
||||
do {
|
||||
d = optstring[i++];
|
||||
} while (d && d != c);
|
||||
|
||||
if (d != c || c == ':') {
|
||||
optopt = c;
|
||||
if (optstring[0] != ':' && opterr)
|
||||
fprintf(stderr, "%s: unrecognized option: %c\n", argv[0], *optchar);
|
||||
return '?';
|
||||
}
|
||||
if (optstring[i] == ':') {
|
||||
optarg = 0;
|
||||
if (optstring[i + 1] != ':' || __optpos) {
|
||||
optarg = argv[optind++];
|
||||
if (__optpos)
|
||||
optarg += __optpos;
|
||||
__optpos = 0;
|
||||
}
|
||||
if (optind > argc) {
|
||||
optopt = c;
|
||||
if (optstring[0] == ':')
|
||||
return ':';
|
||||
if (opterr)
|
||||
fprintf(stderr, "%s: option requires argument: %c\n",
|
||||
argv[0], *optchar);
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_GETOPT_H */
|
||||
@@ -0,0 +1,31 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* math definitions for NOLIBC
|
||||
* Copyright (C) 2025 Thomas Weißschuh <thomas.weissschuh@linutronix.de>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_MATH_H
|
||||
#define _NOLIBC_SYS_MATH_H
|
||||
|
||||
static __inline__
|
||||
double fabs(double x)
|
||||
{
|
||||
return x >= 0 ? x : -x;
|
||||
}
|
||||
|
||||
static __inline__
|
||||
float fabsf(float x)
|
||||
{
|
||||
return x >= 0 ? x : -x;
|
||||
}
|
||||
|
||||
static __inline__
|
||||
long double fabsl(long double x)
|
||||
{
|
||||
return x >= 0 ? x : -x;
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_MATH_H */
|
||||
@@ -96,7 +96,24 @@
|
||||
#include "arch.h"
|
||||
#include "types.h"
|
||||
#include "sys.h"
|
||||
#include "sys/auxv.h"
|
||||
#include "sys/ioctl.h"
|
||||
#include "sys/mman.h"
|
||||
#include "sys/mount.h"
|
||||
#include "sys/prctl.h"
|
||||
#include "sys/random.h"
|
||||
#include "sys/reboot.h"
|
||||
#include "sys/resource.h"
|
||||
#include "sys/stat.h"
|
||||
#include "sys/syscall.h"
|
||||
#include "sys/sysmacros.h"
|
||||
#include "sys/time.h"
|
||||
#include "sys/timerfd.h"
|
||||
#include "sys/utsname.h"
|
||||
#include "sys/wait.h"
|
||||
#include "ctype.h"
|
||||
#include "elf.h"
|
||||
#include "sched.h"
|
||||
#include "signal.h"
|
||||
#include "unistd.h"
|
||||
#include "stdio.h"
|
||||
@@ -105,6 +122,10 @@
|
||||
#include "time.h"
|
||||
#include "stackprotector.h"
|
||||
#include "dirent.h"
|
||||
#include "fcntl.h"
|
||||
#include "getopt.h"
|
||||
#include "poll.h"
|
||||
#include "math.h"
|
||||
|
||||
/* Used by programs to avoid std includes */
|
||||
#define NOLIBC
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* poll definitions for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_POLL_H
|
||||
#define _NOLIBC_POLL_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "sys.h"
|
||||
|
||||
#include <linux/poll.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
/*
|
||||
* int poll(struct pollfd *fds, int nfds, int timeout);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_poll(struct pollfd *fds, int nfds, int timeout)
|
||||
{
|
||||
#if defined(__NR_ppoll)
|
||||
struct timespec t;
|
||||
|
||||
if (timeout >= 0) {
|
||||
t.tv_sec = timeout / 1000;
|
||||
t.tv_nsec = (timeout % 1000) * 1000000;
|
||||
}
|
||||
return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
|
||||
#elif defined(__NR_ppoll_time64)
|
||||
struct __kernel_timespec t;
|
||||
|
||||
if (timeout >= 0) {
|
||||
t.tv_sec = timeout / 1000;
|
||||
t.tv_nsec = (timeout % 1000) * 1000000;
|
||||
}
|
||||
return my_syscall5(__NR_ppoll_time64, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
|
||||
#elif defined(__NR_poll)
|
||||
return my_syscall3(__NR_poll, fds, nfds, timeout);
|
||||
#else
|
||||
return __nolibc_enosys(__func__, fds, nfds, timeout);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int poll(struct pollfd *fds, int nfds, int timeout)
|
||||
{
|
||||
return __sysret(sys_poll(fds, nfds, timeout));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_POLL_H */
|
||||
@@ -0,0 +1,50 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* sched function definitions for NOLIBC
|
||||
* Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SCHED_H
|
||||
#define _NOLIBC_SCHED_H
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
/*
|
||||
* int setns(int fd, int nstype);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_setns(int fd, int nstype)
|
||||
{
|
||||
return my_syscall2(__NR_setns, fd, nstype);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int setns(int fd, int nstype)
|
||||
{
|
||||
return __sysret(sys_setns(fd, nstype));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int unshare(int flags);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_unshare(int flags)
|
||||
{
|
||||
return my_syscall1(__NR_unshare, flags);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int unshare(int flags)
|
||||
{
|
||||
return __sysret(sys_unshare(flags));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SCHED_H */
|
||||
@@ -4,6 +4,9 @@
|
||||
* Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SIGNAL_H
|
||||
#define _NOLIBC_SIGNAL_H
|
||||
|
||||
@@ -20,7 +23,4 @@ int raise(int signal)
|
||||
return sys_kill(sys_getpid(), signal);
|
||||
}
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#endif /* _NOLIBC_SIGNAL_H */
|
||||
|
||||
@@ -13,12 +13,8 @@
|
||||
* syscall-specific stuff, as this file is expected to be included very early.
|
||||
*/
|
||||
|
||||
/* note: may already be defined */
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stddef.h"
|
||||
|
||||
/* those are commonly provided by sys/types.h */
|
||||
typedef unsigned int dev_t;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* Stddef definitions for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_STDDEF_H
|
||||
#define _NOLIBC_STDDEF_H
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
/* note: may already be defined */
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(TYPE, FIELD) ((size_t) &((TYPE *)0)->FIELD)
|
||||
#endif
|
||||
|
||||
#endif /* _NOLIBC_STDDEF_H */
|
||||
@@ -39,8 +39,8 @@ typedef size_t uint_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
typedef __INTMAX_TYPE__ intmax_t;
|
||||
typedef __UINTMAX_TYPE__ uintmax_t;
|
||||
|
||||
/* limits of integral types */
|
||||
|
||||
|
||||
+157
-10
@@ -4,12 +4,16 @@
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_STDIO_H
|
||||
#define _NOLIBC_STDIO_H
|
||||
|
||||
#include "std.h"
|
||||
#include "arch.h"
|
||||
#include "errno.h"
|
||||
#include "fcntl.h"
|
||||
#include "types.h"
|
||||
#include "sys.h"
|
||||
#include "stdarg.h"
|
||||
@@ -17,6 +21,8 @@
|
||||
#include "string.h"
|
||||
#include "compiler.h"
|
||||
|
||||
static const char *strerror(int errnum);
|
||||
|
||||
#ifndef EOF
|
||||
#define EOF (-1)
|
||||
#endif
|
||||
@@ -50,6 +56,32 @@ FILE *fdopen(int fd, const char *mode __attribute__((unused)))
|
||||
return (FILE*)(intptr_t)~fd;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
FILE *fopen(const char *pathname, const char *mode)
|
||||
{
|
||||
int flags, fd;
|
||||
|
||||
switch (*mode) {
|
||||
case 'r':
|
||||
flags = O_RDONLY;
|
||||
break;
|
||||
case 'w':
|
||||
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
break;
|
||||
case 'a':
|
||||
flags = O_WRONLY | O_CREAT | O_APPEND;
|
||||
break;
|
||||
default:
|
||||
SET_ERRNO(EINVAL); return NULL;
|
||||
}
|
||||
|
||||
if (mode[1] == '+')
|
||||
flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
|
||||
|
||||
fd = open(pathname, flags, 0666);
|
||||
return fdopen(fd, mode);
|
||||
}
|
||||
|
||||
/* provides the fd of stream. */
|
||||
static __attribute__((unused))
|
||||
int fileno(FILE *stream)
|
||||
@@ -208,28 +240,40 @@ char *fgets(char *s, int size, FILE *stream)
|
||||
}
|
||||
|
||||
|
||||
/* minimal vfprintf(). It supports the following formats:
|
||||
/* minimal printf(). It supports the following formats:
|
||||
* - %[l*]{d,u,c,x,p}
|
||||
* - %s
|
||||
* - unknown modifiers are ignored.
|
||||
*/
|
||||
static __attribute__((unused, format(printf, 2, 0)))
|
||||
int vfprintf(FILE *stream, const char *fmt, va_list args)
|
||||
typedef int (*__nolibc_printf_cb)(intptr_t state, const char *buf, size_t size);
|
||||
|
||||
static __attribute__((unused, format(printf, 4, 0)))
|
||||
int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char *fmt, va_list args)
|
||||
{
|
||||
char escape, lpref, c;
|
||||
unsigned long long v;
|
||||
unsigned int written;
|
||||
size_t len, ofs;
|
||||
unsigned int written, width;
|
||||
size_t len, ofs, w;
|
||||
char tmpbuf[21];
|
||||
const char *outstr;
|
||||
|
||||
written = ofs = escape = lpref = 0;
|
||||
while (1) {
|
||||
c = fmt[ofs++];
|
||||
width = 0;
|
||||
|
||||
if (escape) {
|
||||
/* we're in an escape sequence, ofs == 1 */
|
||||
escape = 0;
|
||||
|
||||
/* width */
|
||||
while (c >= '0' && c <= '9') {
|
||||
width *= 10;
|
||||
width += c - '0';
|
||||
|
||||
c = fmt[ofs++];
|
||||
}
|
||||
|
||||
if (c == 'c' || c == 'd' || c == 'u' || c == 'x' || c == 'p') {
|
||||
char *out = tmpbuf;
|
||||
|
||||
@@ -277,6 +321,11 @@ int vfprintf(FILE *stream, const char *fmt, va_list args)
|
||||
if (!outstr)
|
||||
outstr="(null)";
|
||||
}
|
||||
#ifndef NOLIBC_IGNORE_ERRNO
|
||||
else if (c == 'm') {
|
||||
outstr = strerror(errno);
|
||||
}
|
||||
#endif /* NOLIBC_IGNORE_ERRNO */
|
||||
else if (c == '%') {
|
||||
/* queue it verbatim */
|
||||
continue;
|
||||
@@ -286,6 +335,8 @@ int vfprintf(FILE *stream, const char *fmt, va_list args)
|
||||
if (c == 'l') {
|
||||
/* long format prefix, maintain the escape */
|
||||
lpref++;
|
||||
} else if (c == 'j') {
|
||||
lpref = 2;
|
||||
}
|
||||
escape = 1;
|
||||
goto do_escape;
|
||||
@@ -302,8 +353,17 @@ int vfprintf(FILE *stream, const char *fmt, va_list args)
|
||||
outstr = fmt;
|
||||
len = ofs - 1;
|
||||
flush_str:
|
||||
if (_fwrite(outstr, len, stream) != 0)
|
||||
break;
|
||||
if (n) {
|
||||
w = len < n ? len : n;
|
||||
n -= w;
|
||||
while (width-- > w) {
|
||||
if (cb(state, " ", 1) != 0)
|
||||
break;
|
||||
written += 1;
|
||||
}
|
||||
if (cb(state, outstr, w) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
written += len;
|
||||
do_escape:
|
||||
@@ -319,6 +379,17 @@ int vfprintf(FILE *stream, const char *fmt, va_list args)
|
||||
return written;
|
||||
}
|
||||
|
||||
static int __nolibc_fprintf_cb(intptr_t state, const char *buf, size_t size)
|
||||
{
|
||||
return _fwrite(buf, size, (FILE *)state);
|
||||
}
|
||||
|
||||
static __attribute__((unused, format(printf, 2, 0)))
|
||||
int vfprintf(FILE *stream, const char *fmt, va_list args)
|
||||
{
|
||||
return __nolibc_printf(__nolibc_fprintf_cb, (intptr_t)stream, SIZE_MAX, fmt, args);
|
||||
}
|
||||
|
||||
static __attribute__((unused, format(printf, 1, 0)))
|
||||
int vprintf(const char *fmt, va_list args)
|
||||
{
|
||||
@@ -349,6 +420,85 @@ int printf(const char *fmt, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __attribute__((unused, format(printf, 2, 0)))
|
||||
int vdprintf(int fd, const char *fmt, va_list args)
|
||||
{
|
||||
FILE *stream;
|
||||
|
||||
stream = fdopen(fd, NULL);
|
||||
if (!stream)
|
||||
return -1;
|
||||
/* Technically 'stream' is leaked, but as it's only a wrapper around 'fd' that is fine */
|
||||
return vfprintf(stream, fmt, args);
|
||||
}
|
||||
|
||||
static __attribute__((unused, format(printf, 2, 3)))
|
||||
int dprintf(int fd, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int ret;
|
||||
|
||||
va_start(args, fmt);
|
||||
ret = vdprintf(fd, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __nolibc_sprintf_cb(intptr_t _state, const char *buf, size_t size)
|
||||
{
|
||||
char **state = (char **)_state;
|
||||
|
||||
memcpy(*state, buf, size);
|
||||
*state += size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __attribute__((unused, format(printf, 3, 0)))
|
||||
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
|
||||
{
|
||||
char *state = buf;
|
||||
int ret;
|
||||
|
||||
ret = __nolibc_printf(__nolibc_sprintf_cb, (intptr_t)&state, size, fmt, args);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
buf[(size_t)ret < size ? (size_t)ret : size - 1] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __attribute__((unused, format(printf, 3, 4)))
|
||||
int snprintf(char *buf, size_t size, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int ret;
|
||||
|
||||
va_start(args, fmt);
|
||||
ret = vsnprintf(buf, size, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __attribute__((unused, format(printf, 2, 0)))
|
||||
int vsprintf(char *buf, const char *fmt, va_list args)
|
||||
{
|
||||
return vsnprintf(buf, SIZE_MAX, fmt, args);
|
||||
}
|
||||
|
||||
static __attribute__((unused, format(printf, 2, 3)))
|
||||
int sprintf(char *buf, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int ret;
|
||||
|
||||
va_start(args, fmt);
|
||||
ret = vsprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int vsscanf(const char *str, const char *format, va_list args)
|
||||
{
|
||||
@@ -485,7 +635,4 @@ const char *strerror(int errno)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#endif /* _NOLIBC_STDIO_H */
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_STDLIB_H
|
||||
#define _NOLIBC_STDLIB_H
|
||||
|
||||
@@ -29,6 +32,24 @@ static __attribute__((unused)) char itoa_buffer[21];
|
||||
* As much as possible, please keep functions alphabetically sorted.
|
||||
*/
|
||||
|
||||
static __inline__
|
||||
int abs(int j)
|
||||
{
|
||||
return j >= 0 ? j : -j;
|
||||
}
|
||||
|
||||
static __inline__
|
||||
long labs(long j)
|
||||
{
|
||||
return j >= 0 ? j : -j;
|
||||
}
|
||||
|
||||
static __inline__
|
||||
long long llabs(long long j)
|
||||
{
|
||||
return j >= 0 ? j : -j;
|
||||
}
|
||||
|
||||
/* must be exported, as it's used by libgcc for various divide functions */
|
||||
void abort(void);
|
||||
__attribute__((weak,unused,noreturn,section(".text.nolibc_abort")))
|
||||
@@ -102,32 +123,6 @@ char *getenv(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
unsigned long getauxval(unsigned long type)
|
||||
{
|
||||
const unsigned long *auxv = _auxv;
|
||||
unsigned long ret;
|
||||
|
||||
if (!auxv)
|
||||
return 0;
|
||||
|
||||
while (1) {
|
||||
if (!auxv[0] && !auxv[1]) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (auxv[0] == type) {
|
||||
ret = auxv[1];
|
||||
break;
|
||||
}
|
||||
|
||||
auxv += 2;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
void *malloc(size_t len)
|
||||
{
|
||||
@@ -275,7 +270,7 @@ int itoa_r(long in, char *buffer)
|
||||
int len = 0;
|
||||
|
||||
if (in < 0) {
|
||||
in = -in;
|
||||
in = -(unsigned long)in;
|
||||
*(ptr++) = '-';
|
||||
len++;
|
||||
}
|
||||
@@ -411,7 +406,7 @@ int i64toa_r(int64_t in, char *buffer)
|
||||
int len = 0;
|
||||
|
||||
if (in < 0) {
|
||||
in = -in;
|
||||
in = -(uint64_t)in;
|
||||
*(ptr++) = '-';
|
||||
len++;
|
||||
}
|
||||
@@ -548,7 +543,4 @@ uintmax_t strtoumax(const char *nptr, char **endptr, int base)
|
||||
return __strtox(nptr, endptr, base, 0, UINTMAX_MAX);
|
||||
}
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#endif /* _NOLIBC_STDLIB_H */
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_STRING_H
|
||||
#define _NOLIBC_STRING_H
|
||||
|
||||
@@ -289,7 +292,40 @@ char *strrchr(const char *s, int c)
|
||||
return (char *)ret;
|
||||
}
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
static __attribute__((unused))
|
||||
char *strstr(const char *haystack, const char *needle)
|
||||
{
|
||||
size_t len_haystack, len_needle;
|
||||
|
||||
len_needle = strlen(needle);
|
||||
if (!len_needle)
|
||||
return NULL;
|
||||
|
||||
len_haystack = strlen(haystack);
|
||||
while (len_haystack >= len_needle) {
|
||||
if (!memcmp(haystack, needle, len_needle))
|
||||
return (char *)haystack;
|
||||
haystack++;
|
||||
len_haystack--;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int tolower(int c)
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return c - 'A' + 'a';
|
||||
return c;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int toupper(int c)
|
||||
{
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return c - 'a' + 'A';
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_STRING_H */
|
||||
|
||||
+28
-399
@@ -4,6 +4,9 @@
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_H
|
||||
#define _NOLIBC_SYS_H
|
||||
|
||||
@@ -20,11 +23,7 @@
|
||||
#include <linux/auxvec.h>
|
||||
#include <linux/fcntl.h> /* for O_* and AT_* */
|
||||
#include <linux/stat.h> /* for statx() */
|
||||
#include <linux/prctl.h>
|
||||
#include <linux/resource.h>
|
||||
#include <linux/utsname.h>
|
||||
|
||||
#include "arch.h"
|
||||
#include "errno.h"
|
||||
#include "stdarg.h"
|
||||
#include "types.h"
|
||||
@@ -301,11 +300,17 @@ void sys_exit(int status)
|
||||
}
|
||||
|
||||
static __attribute__((noreturn,unused))
|
||||
void exit(int status)
|
||||
void _exit(int status)
|
||||
{
|
||||
sys_exit(status);
|
||||
}
|
||||
|
||||
static __attribute__((noreturn,unused))
|
||||
void exit(int status)
|
||||
{
|
||||
_exit(status);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pid_t fork(void);
|
||||
@@ -488,27 +493,6 @@ int getpagesize(void)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||
{
|
||||
#ifdef __NR_gettimeofday
|
||||
return my_syscall2(__NR_gettimeofday, tv, tz);
|
||||
#else
|
||||
return __nolibc_enosys(__func__, tv, tz);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||
{
|
||||
return __sysret(sys_gettimeofday(tv, tz));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* uid_t getuid(void);
|
||||
*/
|
||||
@@ -530,18 +514,6 @@ uid_t getuid(void)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int ioctl(int fd, unsigned long cmd, ... arg);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return my_syscall3(__NR_ioctl, fd, cmd, arg);
|
||||
}
|
||||
|
||||
#define ioctl(fd, cmd, arg) __sysret(sys_ioctl(fd, cmd, (unsigned long)(arg)))
|
||||
|
||||
/*
|
||||
* int kill(pid_t pid, int signal);
|
||||
*/
|
||||
@@ -697,125 +669,6 @@ int mknod(const char *path, mode_t mode, dev_t dev)
|
||||
return __sysret(sys_mknod(path, mode, dev));
|
||||
}
|
||||
|
||||
#ifndef sys_mmap
|
||||
static __attribute__((unused))
|
||||
void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd,
|
||||
off_t offset)
|
||||
{
|
||||
int n;
|
||||
|
||||
#if defined(__NR_mmap2)
|
||||
n = __NR_mmap2;
|
||||
offset >>= 12;
|
||||
#else
|
||||
n = __NR_mmap;
|
||||
#endif
|
||||
|
||||
return (void *)my_syscall6(n, addr, length, prot, flags, fd, offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Note that on Linux, MAP_FAILED is -1 so we can use the generic __sysret()
|
||||
* which returns -1 upon error and still satisfy user land that checks for
|
||||
* MAP_FAILED.
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
|
||||
{
|
||||
void *ret = sys_mmap(addr, length, prot, flags, fd, offset);
|
||||
|
||||
if ((unsigned long)ret >= -4095UL) {
|
||||
SET_ERRNO(-(long)ret);
|
||||
ret = MAP_FAILED;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_munmap(void *addr, size_t length)
|
||||
{
|
||||
return my_syscall2(__NR_munmap, addr, length);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int munmap(void *addr, size_t length)
|
||||
{
|
||||
return __sysret(sys_munmap(addr, length));
|
||||
}
|
||||
|
||||
/*
|
||||
* int mount(const char *source, const char *target,
|
||||
* const char *fstype, unsigned long flags,
|
||||
* const void *data);
|
||||
*/
|
||||
static __attribute__((unused))
|
||||
int sys_mount(const char *src, const char *tgt, const char *fst,
|
||||
unsigned long flags, const void *data)
|
||||
{
|
||||
return my_syscall5(__NR_mount, src, tgt, fst, flags, data);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int mount(const char *src, const char *tgt,
|
||||
const char *fst, unsigned long flags,
|
||||
const void *data)
|
||||
{
|
||||
return __sysret(sys_mount(src, tgt, fst, flags, data));
|
||||
}
|
||||
|
||||
/*
|
||||
* int openat(int dirfd, const char *path, int flags[, mode_t mode]);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_openat(int dirfd, const char *path, int flags, mode_t mode)
|
||||
{
|
||||
return my_syscall4(__NR_openat, dirfd, path, flags, mode);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int openat(int dirfd, const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
|
||||
if (flags & O_CREAT) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, flags);
|
||||
mode = va_arg(args, mode_t);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
return __sysret(sys_openat(dirfd, path, flags, mode));
|
||||
}
|
||||
|
||||
/*
|
||||
* int open(const char *path, int flags[, mode_t mode]);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_open(const char *path, int flags, mode_t mode)
|
||||
{
|
||||
return my_syscall4(__NR_openat, AT_FDCWD, path, flags, mode);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int open(const char *path, int flags, ...)
|
||||
{
|
||||
mode_t mode = 0;
|
||||
|
||||
if (flags & O_CREAT) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, flags);
|
||||
mode = va_arg(args, mode_t);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
return __sysret(sys_open(path, flags, mode));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int pipe2(int pipefd[2], int flags);
|
||||
@@ -841,26 +694,6 @@ int pipe(int pipefd[2])
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
* unsigned long arg4, unsigned long arg5);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
unsigned long arg4, unsigned long arg5)
|
||||
{
|
||||
return my_syscall5(__NR_prctl, option, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
unsigned long arg4, unsigned long arg5)
|
||||
{
|
||||
return __sysret(sys_prctl(option, arg2, arg3, arg4, arg5));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int pivot_root(const char *new, const char *old);
|
||||
*/
|
||||
@@ -878,35 +711,6 @@ int pivot_root(const char *new, const char *old)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int poll(struct pollfd *fds, int nfds, int timeout);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_poll(struct pollfd *fds, int nfds, int timeout)
|
||||
{
|
||||
#if defined(__NR_ppoll)
|
||||
struct timespec t;
|
||||
|
||||
if (timeout >= 0) {
|
||||
t.tv_sec = timeout / 1000;
|
||||
t.tv_nsec = (timeout % 1000) * 1000000;
|
||||
}
|
||||
return my_syscall5(__NR_ppoll, fds, nfds, (timeout >= 0) ? &t : NULL, NULL, 0);
|
||||
#elif defined(__NR_poll)
|
||||
return my_syscall3(__NR_poll, fds, nfds, timeout);
|
||||
#else
|
||||
return __nolibc_enosys(__func__, fds, nfds, timeout);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int poll(struct pollfd *fds, int nfds, int timeout)
|
||||
{
|
||||
return __sysret(sys_poll(fds, nfds, timeout));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ssize_t read(int fd, void *buf, size_t count);
|
||||
*/
|
||||
@@ -924,61 +728,6 @@ ssize_t read(int fd, void *buf, size_t count)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int reboot(int cmd);
|
||||
* <cmd> is among LINUX_REBOOT_CMD_*
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg)
|
||||
{
|
||||
return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int reboot(int cmd)
|
||||
{
|
||||
return __sysret(sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int getrlimit(int resource, struct rlimit *rlim);
|
||||
* int setrlimit(int resource, const struct rlimit *rlim);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_prlimit64(pid_t pid, int resource,
|
||||
const struct rlimit64 *new_limit, struct rlimit64 *old_limit)
|
||||
{
|
||||
return my_syscall4(__NR_prlimit64, pid, resource, new_limit, old_limit);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int getrlimit(int resource, struct rlimit *rlim)
|
||||
{
|
||||
struct rlimit64 rlim64;
|
||||
int ret;
|
||||
|
||||
ret = __sysret(sys_prlimit64(0, resource, NULL, &rlim64));
|
||||
rlim->rlim_cur = rlim64.rlim_cur;
|
||||
rlim->rlim_max = rlim64.rlim_max;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int setrlimit(int resource, const struct rlimit *rlim)
|
||||
{
|
||||
struct rlimit64 rlim64 = {
|
||||
.rlim_cur = rlim->rlim_cur,
|
||||
.rlim_max = rlim->rlim_max,
|
||||
};
|
||||
|
||||
return __sysret(sys_prlimit64(0, resource, &rlim64, NULL));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int sched_yield(void);
|
||||
*/
|
||||
@@ -1023,6 +772,14 @@ int sys_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeva
|
||||
t.tv_nsec = timeout->tv_usec * 1000;
|
||||
}
|
||||
return my_syscall6(__NR_pselect6, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
|
||||
#elif defined(__NR_pselect6_time64)
|
||||
struct __kernel_timespec t;
|
||||
|
||||
if (timeout) {
|
||||
t.tv_sec = timeout->tv_sec;
|
||||
t.tv_nsec = timeout->tv_usec * 1000;
|
||||
}
|
||||
return my_syscall6(__NR_pselect6_time64, nfds, rfds, wfds, efds, timeout ? &t : NULL, NULL);
|
||||
#else
|
||||
return __nolibc_enosys(__func__, nfds, rfds, wfds, efds, timeout);
|
||||
#endif
|
||||
@@ -1051,6 +808,16 @@ int setpgid(pid_t pid, pid_t pgid)
|
||||
return __sysret(sys_setpgid(pid, pgid));
|
||||
}
|
||||
|
||||
/*
|
||||
* pid_t setpgrp(void)
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
pid_t setpgrp(void)
|
||||
{
|
||||
return setpgid(0, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pid_t setsid(void);
|
||||
@@ -1068,62 +835,6 @@ pid_t setsid(void)
|
||||
return __sysret(sys_setsid());
|
||||
}
|
||||
|
||||
/*
|
||||
* int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf);
|
||||
* int stat(const char *path, struct stat *buf);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf)
|
||||
{
|
||||
#ifdef __NR_statx
|
||||
return my_syscall5(__NR_statx, fd, path, flags, mask, buf);
|
||||
#else
|
||||
return __nolibc_enosys(__func__, fd, path, flags, mask, buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf)
|
||||
{
|
||||
return __sysret(sys_statx(fd, path, flags, mask, buf));
|
||||
}
|
||||
|
||||
|
||||
static __attribute__((unused))
|
||||
int stat(const char *path, struct stat *buf)
|
||||
{
|
||||
struct statx statx;
|
||||
long ret;
|
||||
|
||||
ret = __sysret(sys_statx(AT_FDCWD, path, AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &statx));
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
buf->st_dev = ((statx.stx_dev_minor & 0xff)
|
||||
| (statx.stx_dev_major << 8)
|
||||
| ((statx.stx_dev_minor & ~0xff) << 12));
|
||||
buf->st_ino = statx.stx_ino;
|
||||
buf->st_mode = statx.stx_mode;
|
||||
buf->st_nlink = statx.stx_nlink;
|
||||
buf->st_uid = statx.stx_uid;
|
||||
buf->st_gid = statx.stx_gid;
|
||||
buf->st_rdev = ((statx.stx_rdev_minor & 0xff)
|
||||
| (statx.stx_rdev_major << 8)
|
||||
| ((statx.stx_rdev_minor & ~0xff) << 12));
|
||||
buf->st_size = statx.stx_size;
|
||||
buf->st_blksize = statx.stx_blksize;
|
||||
buf->st_blocks = statx.stx_blocks;
|
||||
buf->st_atim.tv_sec = statx.stx_atime.tv_sec;
|
||||
buf->st_atim.tv_nsec = statx.stx_atime.tv_nsec;
|
||||
buf->st_mtim.tv_sec = statx.stx_mtime.tv_sec;
|
||||
buf->st_mtim.tv_nsec = statx.stx_mtime.tv_nsec;
|
||||
buf->st_ctim.tv_sec = statx.stx_ctime.tv_sec;
|
||||
buf->st_ctim.tv_nsec = statx.stx_ctime.tv_nsec;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int symlink(const char *old, const char *new);
|
||||
@@ -1182,32 +893,6 @@ int umount2(const char *path, int flags)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int uname(struct utsname *buf);
|
||||
*/
|
||||
|
||||
struct utsname {
|
||||
char sysname[65];
|
||||
char nodename[65];
|
||||
char release[65];
|
||||
char version[65];
|
||||
char machine[65];
|
||||
char domainname[65];
|
||||
};
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_uname(struct utsname *buf)
|
||||
{
|
||||
return my_syscall1(__NR_uname, buf);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int uname(struct utsname *buf)
|
||||
{
|
||||
return __sysret(sys_uname(buf));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int unlink(const char *path);
|
||||
*/
|
||||
@@ -1231,59 +916,6 @@ int unlink(const char *path)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pid_t wait(int *status);
|
||||
* pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);
|
||||
* pid_t waitpid(pid_t pid, int *status, int options);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
|
||||
{
|
||||
#ifdef __NR_wait4
|
||||
return my_syscall4(__NR_wait4, pid, status, options, rusage);
|
||||
#else
|
||||
return __nolibc_enosys(__func__, pid, status, options, rusage);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
pid_t wait(int *status)
|
||||
{
|
||||
return __sysret(sys_wait4(-1, status, 0, NULL));
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage)
|
||||
{
|
||||
return __sysret(sys_wait4(pid, status, options, rusage));
|
||||
}
|
||||
|
||||
|
||||
static __attribute__((unused))
|
||||
pid_t waitpid(pid_t pid, int *status, int options)
|
||||
{
|
||||
return __sysret(sys_wait4(pid, status, options, NULL));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_waitid(int which, pid_t pid, siginfo_t *infop, int options, struct rusage *rusage)
|
||||
{
|
||||
return my_syscall5(__NR_waitid, which, pid, infop, options, rusage);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int waitid(int which, pid_t pid, siginfo_t *infop, int options)
|
||||
{
|
||||
return __sysret(sys_waitid(which, pid, infop, options, NULL));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ssize_t write(int fd, const void *buf, size_t count);
|
||||
*/
|
||||
@@ -1317,7 +949,4 @@ int memfd_create(const char *name, unsigned int flags)
|
||||
return __sysret(sys_memfd_create(name, flags));
|
||||
}
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#endif /* _NOLIBC_SYS_H */
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* auxv definitions for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_AUXV_H
|
||||
#define _NOLIBC_SYS_AUXV_H
|
||||
|
||||
#include "../crt.h"
|
||||
|
||||
static __attribute__((unused))
|
||||
unsigned long getauxval(unsigned long type)
|
||||
{
|
||||
const unsigned long *auxv = _auxv;
|
||||
unsigned long ret;
|
||||
|
||||
if (!auxv)
|
||||
return 0;
|
||||
|
||||
while (1) {
|
||||
if (!auxv[0] && !auxv[1]) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (auxv[0] == type) {
|
||||
ret = auxv[1];
|
||||
break;
|
||||
}
|
||||
|
||||
auxv += 2;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_AUXV_H */
|
||||
@@ -0,0 +1,29 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* Ioctl definitions for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_IOCTL_H
|
||||
#define _NOLIBC_SYS_IOCTL_H
|
||||
|
||||
#include "../sys.h"
|
||||
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
/*
|
||||
* int ioctl(int fd, unsigned long cmd, ... arg);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return my_syscall3(__NR_ioctl, fd, cmd, arg);
|
||||
}
|
||||
|
||||
#define ioctl(fd, cmd, arg) __sysret(sys_ioctl(fd, cmd, (unsigned long)(arg)))
|
||||
|
||||
#endif /* _NOLIBC_SYS_IOCTL_H */
|
||||
@@ -0,0 +1,82 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* mm definition for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_MMAN_H
|
||||
#define _NOLIBC_SYS_MMAN_H
|
||||
|
||||
#include "../arch.h"
|
||||
#include "../sys.h"
|
||||
|
||||
#ifndef sys_mmap
|
||||
static __attribute__((unused))
|
||||
void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd,
|
||||
off_t offset)
|
||||
{
|
||||
int n;
|
||||
|
||||
#if defined(__NR_mmap2)
|
||||
n = __NR_mmap2;
|
||||
offset >>= 12;
|
||||
#else
|
||||
n = __NR_mmap;
|
||||
#endif
|
||||
|
||||
return (void *)my_syscall6(n, addr, length, prot, flags, fd, offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Note that on Linux, MAP_FAILED is -1 so we can use the generic __sysret()
|
||||
* which returns -1 upon error and still satisfy user land that checks for
|
||||
* MAP_FAILED.
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
|
||||
{
|
||||
void *ret = sys_mmap(addr, length, prot, flags, fd, offset);
|
||||
|
||||
if ((unsigned long)ret >= -4095UL) {
|
||||
SET_ERRNO(-(long)ret);
|
||||
ret = MAP_FAILED;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
void *sys_mremap(void *old_address, size_t old_size, size_t new_size, int flags, void *new_address)
|
||||
{
|
||||
return (void *)my_syscall5(__NR_mremap, old_address, old_size,
|
||||
new_size, flags, new_address);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
void *mremap(void *old_address, size_t old_size, size_t new_size, int flags, void *new_address)
|
||||
{
|
||||
void *ret = sys_mremap(old_address, old_size, new_size, flags, new_address);
|
||||
|
||||
if ((unsigned long)ret >= -4095UL) {
|
||||
SET_ERRNO(-(long)ret);
|
||||
ret = MAP_FAILED;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_munmap(void *addr, size_t length)
|
||||
{
|
||||
return my_syscall2(__NR_munmap, addr, length);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int munmap(void *addr, size_t length)
|
||||
{
|
||||
return __sysret(sys_munmap(addr, length));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_MMAN_H */
|
||||
@@ -0,0 +1,37 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* Mount definitions for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_MOUNT_H
|
||||
#define _NOLIBC_SYS_MOUNT_H
|
||||
|
||||
#include "../sys.h"
|
||||
|
||||
#include <linux/mount.h>
|
||||
|
||||
/*
|
||||
* int mount(const char *source, const char *target,
|
||||
* const char *fstype, unsigned long flags,
|
||||
* const void *data);
|
||||
*/
|
||||
static __attribute__((unused))
|
||||
int sys_mount(const char *src, const char *tgt, const char *fst,
|
||||
unsigned long flags, const void *data)
|
||||
{
|
||||
return my_syscall5(__NR_mount, src, tgt, fst, flags, data);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int mount(const char *src, const char *tgt,
|
||||
const char *fst, unsigned long flags,
|
||||
const void *data)
|
||||
{
|
||||
return __sysret(sys_mount(src, tgt, fst, flags, data));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_MOUNT_H */
|
||||
@@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* Prctl definitions for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_PRCTL_H
|
||||
#define _NOLIBC_SYS_PRCTL_H
|
||||
|
||||
#include "../sys.h"
|
||||
|
||||
#include <linux/prctl.h>
|
||||
|
||||
/*
|
||||
* int prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
* unsigned long arg4, unsigned long arg5);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
unsigned long arg4, unsigned long arg5)
|
||||
{
|
||||
return my_syscall5(__NR_prctl, option, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
unsigned long arg4, unsigned long arg5)
|
||||
{
|
||||
return __sysret(sys_prctl(option, arg2, arg3, arg4, arg5));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_PRCTL_H */
|
||||
@@ -0,0 +1,34 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* random definitions for NOLIBC
|
||||
* Copyright (C) 2025 Thomas Weißschuh <thomas.weissschuh@linutronix.de>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_RANDOM_H
|
||||
#define _NOLIBC_SYS_RANDOM_H
|
||||
|
||||
#include "../arch.h"
|
||||
#include "../sys.h"
|
||||
|
||||
#include <linux/random.h>
|
||||
|
||||
/*
|
||||
* ssize_t getrandom(void *buf, size_t buflen, unsigned int flags);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
ssize_t sys_getrandom(void *buf, size_t buflen, unsigned int flags)
|
||||
{
|
||||
return my_syscall3(__NR_getrandom, buf, buflen, flags);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
ssize_t getrandom(void *buf, size_t buflen, unsigned int flags)
|
||||
{
|
||||
return __sysret(sys_getrandom(buf, buflen, flags));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_RANDOM_H */
|
||||
@@ -0,0 +1,34 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* Reboot definitions for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_REBOOT_H
|
||||
#define _NOLIBC_SYS_REBOOT_H
|
||||
|
||||
#include "../sys.h"
|
||||
|
||||
#include <linux/reboot.h>
|
||||
|
||||
/*
|
||||
* int reboot(int cmd);
|
||||
* <cmd> is among LINUX_REBOOT_CMD_*
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
ssize_t sys_reboot(int magic1, int magic2, int cmd, void *arg)
|
||||
{
|
||||
return my_syscall4(__NR_reboot, magic1, magic2, cmd, arg);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int reboot(int cmd)
|
||||
{
|
||||
return __sysret(sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, 0));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_REBOOT_H */
|
||||
@@ -0,0 +1,53 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* Resource definitions for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_RESOURCE_H
|
||||
#define _NOLIBC_SYS_RESOURCE_H
|
||||
|
||||
#include "../sys.h"
|
||||
|
||||
#include <linux/resource.h>
|
||||
|
||||
/*
|
||||
* int getrlimit(int resource, struct rlimit *rlim);
|
||||
* int setrlimit(int resource, const struct rlimit *rlim);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_prlimit64(pid_t pid, int resource,
|
||||
const struct rlimit64 *new_limit, struct rlimit64 *old_limit)
|
||||
{
|
||||
return my_syscall4(__NR_prlimit64, pid, resource, new_limit, old_limit);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int getrlimit(int resource, struct rlimit *rlim)
|
||||
{
|
||||
struct rlimit64 rlim64;
|
||||
int ret;
|
||||
|
||||
ret = __sysret(sys_prlimit64(0, resource, NULL, &rlim64));
|
||||
rlim->rlim_cur = rlim64.rlim_cur;
|
||||
rlim->rlim_max = rlim64.rlim_max;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int setrlimit(int resource, const struct rlimit *rlim)
|
||||
{
|
||||
struct rlimit64 rlim64 = {
|
||||
.rlim_cur = rlim->rlim_cur,
|
||||
.rlim_max = rlim->rlim_max,
|
||||
};
|
||||
|
||||
return __sysret(sys_prlimit64(0, resource, &rlim64, NULL));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_RESOURCE_H */
|
||||
@@ -0,0 +1,94 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* stat definition for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_STAT_H
|
||||
#define _NOLIBC_SYS_STAT_H
|
||||
|
||||
#include "../arch.h"
|
||||
#include "../types.h"
|
||||
#include "../sys.h"
|
||||
|
||||
/*
|
||||
* int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf);
|
||||
* int stat(const char *path, struct stat *buf);
|
||||
* int fstatat(int fd, const char *path, struct stat *buf, int flag);
|
||||
* int fstat(int fildes, struct stat *buf);
|
||||
* int lstat(const char *path, struct stat *buf);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf)
|
||||
{
|
||||
#ifdef __NR_statx
|
||||
return my_syscall5(__NR_statx, fd, path, flags, mask, buf);
|
||||
#else
|
||||
return __nolibc_enosys(__func__, fd, path, flags, mask, buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf)
|
||||
{
|
||||
return __sysret(sys_statx(fd, path, flags, mask, buf));
|
||||
}
|
||||
|
||||
|
||||
static __attribute__((unused))
|
||||
int fstatat(int fd, const char *path, struct stat *buf, int flag)
|
||||
{
|
||||
struct statx statx;
|
||||
long ret;
|
||||
|
||||
ret = __sysret(sys_statx(fd, path, flag | AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &statx));
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
buf->st_dev = ((statx.stx_dev_minor & 0xff)
|
||||
| (statx.stx_dev_major << 8)
|
||||
| ((statx.stx_dev_minor & ~0xff) << 12));
|
||||
buf->st_ino = statx.stx_ino;
|
||||
buf->st_mode = statx.stx_mode;
|
||||
buf->st_nlink = statx.stx_nlink;
|
||||
buf->st_uid = statx.stx_uid;
|
||||
buf->st_gid = statx.stx_gid;
|
||||
buf->st_rdev = ((statx.stx_rdev_minor & 0xff)
|
||||
| (statx.stx_rdev_major << 8)
|
||||
| ((statx.stx_rdev_minor & ~0xff) << 12));
|
||||
buf->st_size = statx.stx_size;
|
||||
buf->st_blksize = statx.stx_blksize;
|
||||
buf->st_blocks = statx.stx_blocks;
|
||||
buf->st_atim.tv_sec = statx.stx_atime.tv_sec;
|
||||
buf->st_atim.tv_nsec = statx.stx_atime.tv_nsec;
|
||||
buf->st_mtim.tv_sec = statx.stx_mtime.tv_sec;
|
||||
buf->st_mtim.tv_nsec = statx.stx_mtime.tv_nsec;
|
||||
buf->st_ctim.tv_sec = statx.stx_ctime.tv_sec;
|
||||
buf->st_ctim.tv_nsec = statx.stx_ctime.tv_nsec;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int stat(const char *path, struct stat *buf)
|
||||
{
|
||||
return fstatat(AT_FDCWD, path, buf, 0);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int fstat(int fildes, struct stat *buf)
|
||||
{
|
||||
return fstatat(fildes, "", buf, AT_EMPTY_PATH);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int lstat(const char *path, struct stat *buf)
|
||||
{
|
||||
return fstatat(AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW);
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_STAT_H */
|
||||
@@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* syscall() definition for NOLIBC
|
||||
* Copyright (C) 2024 Thomas Weißschuh <linux@weissschuh.net>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_SYSCALL_H
|
||||
#define _NOLIBC_SYS_SYSCALL_H
|
||||
|
||||
#define __syscall_narg(_0, _1, _2, _3, _4, _5, _6, N, ...) N
|
||||
#define _syscall_narg(...) __syscall_narg(__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0)
|
||||
#define _syscall(N, ...) __sysret(my_syscall##N(__VA_ARGS__))
|
||||
#define _syscall_n(N, ...) _syscall(N, __VA_ARGS__)
|
||||
#define syscall(...) _syscall_n(_syscall_narg(__VA_ARGS__), ##__VA_ARGS__)
|
||||
|
||||
#endif /* _NOLIBC_SYS_SYSCALL_H */
|
||||
@@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* Sysmacro definitions for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_SYSMACROS_H
|
||||
#define _NOLIBC_SYS_SYSMACROS_H
|
||||
|
||||
#include "../std.h"
|
||||
|
||||
/* WARNING, it only deals with the 4096 first majors and 256 first minors */
|
||||
#define makedev(major, minor) ((dev_t)((((major) & 0xfff) << 8) | ((minor) & 0xff)))
|
||||
#define major(dev) ((unsigned int)(((dev) >> 8) & 0xfff))
|
||||
#define minor(dev) ((unsigned int)((dev) & 0xff))
|
||||
|
||||
#endif /* _NOLIBC_SYS_SYSMACROS_H */
|
||||
@@ -0,0 +1,49 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* time definitions for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_TIME_H
|
||||
#define _NOLIBC_SYS_TIME_H
|
||||
|
||||
#include "../arch.h"
|
||||
#include "../sys.h"
|
||||
|
||||
static int sys_clock_gettime(clockid_t clockid, struct timespec *tp);
|
||||
|
||||
/*
|
||||
* int gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||
{
|
||||
#ifdef __NR_gettimeofday
|
||||
return my_syscall2(__NR_gettimeofday, tv, tz);
|
||||
#else
|
||||
(void) tz; /* Non-NULL tz is undefined behaviour */
|
||||
|
||||
struct timespec tp;
|
||||
int ret;
|
||||
|
||||
ret = sys_clock_gettime(CLOCK_REALTIME, &tp);
|
||||
if (!ret && tv) {
|
||||
tv->tv_sec = tp.tv_sec;
|
||||
tv->tv_usec = tp.tv_nsec / 1000;
|
||||
}
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int gettimeofday(struct timeval *tv, struct timezone *tz)
|
||||
{
|
||||
return __sysret(sys_gettimeofday(tv, tz));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_TIME_H */
|
||||
@@ -0,0 +1,87 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* timerfd definitions for NOLIBC
|
||||
* Copyright (C) 2025 Thomas Weißschuh <thomas.weissschuh@linutronix.de>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_TIMERFD_H
|
||||
#define _NOLIBC_SYS_TIMERFD_H
|
||||
|
||||
#include "../sys.h"
|
||||
#include "../time.h"
|
||||
|
||||
#include <linux/timerfd.h>
|
||||
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_timerfd_create(int clockid, int flags)
|
||||
{
|
||||
return my_syscall2(__NR_timerfd_create, clockid, flags);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int timerfd_create(int clockid, int flags)
|
||||
{
|
||||
return __sysret(sys_timerfd_create(clockid, flags));
|
||||
}
|
||||
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_timerfd_gettime(int fd, struct itimerspec *curr_value)
|
||||
{
|
||||
#if defined(__NR_timerfd_gettime)
|
||||
return my_syscall2(__NR_timerfd_gettime, fd, curr_value);
|
||||
#elif defined(__NR_timerfd_gettime64)
|
||||
struct __kernel_itimerspec kcurr_value;
|
||||
int ret;
|
||||
|
||||
ret = my_syscall2(__NR_timerfd_gettime64, fd, &kcurr_value);
|
||||
__nolibc_timespec_kernel_to_user(&kcurr_value.it_interval, &curr_value->it_interval);
|
||||
__nolibc_timespec_kernel_to_user(&kcurr_value.it_value, &curr_value->it_value);
|
||||
return ret;
|
||||
#else
|
||||
return __nolibc_enosys(__func__, fd, curr_value);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int timerfd_gettime(int fd, struct itimerspec *curr_value)
|
||||
{
|
||||
return __sysret(sys_timerfd_gettime(fd, curr_value));
|
||||
}
|
||||
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_timerfd_settime(int fd, int flags,
|
||||
const struct itimerspec *new_value, struct itimerspec *old_value)
|
||||
{
|
||||
#if defined(__NR_timerfd_settime)
|
||||
return my_syscall4(__NR_timerfd_settime, fd, flags, new_value, old_value);
|
||||
#elif defined(__NR_timerfd_settime64)
|
||||
struct __kernel_itimerspec knew_value, kold_value;
|
||||
int ret;
|
||||
|
||||
__nolibc_timespec_user_to_kernel(&new_value->it_value, &knew_value.it_value);
|
||||
__nolibc_timespec_user_to_kernel(&new_value->it_interval, &knew_value.it_interval);
|
||||
ret = my_syscall4(__NR_timerfd_settime64, fd, flags, &knew_value, &kold_value);
|
||||
if (old_value) {
|
||||
__nolibc_timespec_kernel_to_user(&kold_value.it_interval, &old_value->it_interval);
|
||||
__nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value);
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
return __nolibc_enosys(__func__, fd, flags, new_value, old_value);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int timerfd_settime(int fd, int flags,
|
||||
const struct itimerspec *new_value, struct itimerspec *old_value)
|
||||
{
|
||||
return __sysret(sys_timerfd_settime(fd, flags, new_value, old_value));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_TIMERFD_H */
|
||||
@@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* sys/types.h shim for NOLIBC
|
||||
* Copyright (C) 2025 Thomas Weißschuh <thomas.weissschuh@linutronix.de>
|
||||
*/
|
||||
|
||||
#include "../types.h"
|
||||
@@ -0,0 +1,42 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* Utsname definitions for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_UTSNAME_H
|
||||
#define _NOLIBC_SYS_UTSNAME_H
|
||||
|
||||
#include "../sys.h"
|
||||
|
||||
#include <linux/utsname.h>
|
||||
|
||||
/*
|
||||
* int uname(struct utsname *buf);
|
||||
*/
|
||||
|
||||
struct utsname {
|
||||
char sysname[65];
|
||||
char nodename[65];
|
||||
char release[65];
|
||||
char version[65];
|
||||
char machine[65];
|
||||
char domainname[65];
|
||||
};
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_uname(struct utsname *buf)
|
||||
{
|
||||
return my_syscall1(__NR_uname, buf);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int uname(struct utsname *buf)
|
||||
{
|
||||
return __sysret(sys_uname(buf));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_UTSNAME_H */
|
||||
@@ -0,0 +1,116 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||
/*
|
||||
* wait definitions for NOLIBC
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "../nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_SYS_WAIT_H
|
||||
#define _NOLIBC_SYS_WAIT_H
|
||||
|
||||
#include "../arch.h"
|
||||
#include "../std.h"
|
||||
#include "../types.h"
|
||||
|
||||
/*
|
||||
* pid_t wait(int *status);
|
||||
* pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);
|
||||
* pid_t waitpid(pid_t pid, int *status, int options);
|
||||
* int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
pid_t sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
|
||||
{
|
||||
#ifdef __NR_wait4
|
||||
return my_syscall4(__NR_wait4, pid, status, options, rusage);
|
||||
#else
|
||||
return __nolibc_enosys(__func__, pid, status, options, rusage);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage)
|
||||
{
|
||||
return __sysret(sys_wait4(pid, status, options, rusage));
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_waitid(int which, pid_t pid, siginfo_t *infop, int options, struct rusage *rusage)
|
||||
{
|
||||
return my_syscall5(__NR_waitid, which, pid, infop, options, rusage);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int waitid(int which, pid_t pid, siginfo_t *infop, int options)
|
||||
{
|
||||
return __sysret(sys_waitid(which, pid, infop, options, NULL));
|
||||
}
|
||||
|
||||
|
||||
static __attribute__((unused))
|
||||
pid_t waitpid(pid_t pid, int *status, int options)
|
||||
{
|
||||
int idtype, ret;
|
||||
siginfo_t info;
|
||||
pid_t id;
|
||||
|
||||
if (pid == INT_MIN) {
|
||||
SET_ERRNO(ESRCH);
|
||||
return -1;
|
||||
} else if (pid < -1) {
|
||||
idtype = P_PGID;
|
||||
id = -pid;
|
||||
} else if (pid == -1) {
|
||||
idtype = P_ALL;
|
||||
id = 0;
|
||||
} else if (pid == 0) {
|
||||
idtype = P_PGID;
|
||||
id = 0;
|
||||
} else {
|
||||
idtype = P_PID;
|
||||
id = pid;
|
||||
}
|
||||
|
||||
options |= WEXITED;
|
||||
|
||||
ret = waitid(idtype, id, &info, options);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (info.si_code) {
|
||||
case 0:
|
||||
*status = 0;
|
||||
break;
|
||||
case CLD_EXITED:
|
||||
*status = (info.si_status & 0xff) << 8;
|
||||
break;
|
||||
case CLD_KILLED:
|
||||
*status = info.si_status & 0x7f;
|
||||
break;
|
||||
case CLD_DUMPED:
|
||||
*status = (info.si_status & 0x7f) | 0x80;
|
||||
break;
|
||||
case CLD_STOPPED:
|
||||
case CLD_TRAPPED:
|
||||
*status = (info.si_status << 8) + 0x7f;
|
||||
break;
|
||||
case CLD_CONTINUED:
|
||||
*status = 0xffff;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return info.si_pid;
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
pid_t wait(int *status)
|
||||
{
|
||||
return waitpid(-1, status, 0);
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_SYS_WAIT_H */
|
||||
+187
-2
@@ -4,6 +4,9 @@
|
||||
* Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_TIME_H
|
||||
#define _NOLIBC_TIME_H
|
||||
|
||||
@@ -12,6 +15,106 @@
|
||||
#include "types.h"
|
||||
#include "sys.h"
|
||||
|
||||
#include <linux/signal.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
static __inline__
|
||||
void __nolibc_timespec_user_to_kernel(const struct timespec *ts, struct __kernel_timespec *kts)
|
||||
{
|
||||
kts->tv_sec = ts->tv_sec;
|
||||
kts->tv_nsec = ts->tv_nsec;
|
||||
}
|
||||
|
||||
static __inline__
|
||||
void __nolibc_timespec_kernel_to_user(const struct __kernel_timespec *kts, struct timespec *ts)
|
||||
{
|
||||
ts->tv_sec = kts->tv_sec;
|
||||
ts->tv_nsec = kts->tv_nsec;
|
||||
}
|
||||
|
||||
/*
|
||||
* int clock_getres(clockid_t clockid, struct timespec *res);
|
||||
* int clock_gettime(clockid_t clockid, struct timespec *tp);
|
||||
* int clock_settime(clockid_t clockid, const struct timespec *tp);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_clock_getres(clockid_t clockid, struct timespec *res)
|
||||
{
|
||||
#if defined(__NR_clock_getres)
|
||||
return my_syscall2(__NR_clock_getres, clockid, res);
|
||||
#elif defined(__NR_clock_getres_time64)
|
||||
struct __kernel_timespec kres;
|
||||
int ret;
|
||||
|
||||
ret = my_syscall2(__NR_clock_getres_time64, clockid, &kres);
|
||||
if (res)
|
||||
__nolibc_timespec_kernel_to_user(&kres, res);
|
||||
return ret;
|
||||
#else
|
||||
return __nolibc_enosys(__func__, clockid, res);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int clock_getres(clockid_t clockid, struct timespec *res)
|
||||
{
|
||||
return __sysret(sys_clock_getres(clockid, res));
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_clock_gettime(clockid_t clockid, struct timespec *tp)
|
||||
{
|
||||
#if defined(__NR_clock_gettime)
|
||||
return my_syscall2(__NR_clock_gettime, clockid, tp);
|
||||
#elif defined(__NR_clock_gettime64)
|
||||
struct __kernel_timespec ktp;
|
||||
int ret;
|
||||
|
||||
ret = my_syscall2(__NR_clock_gettime64, clockid, &ktp);
|
||||
if (tp)
|
||||
__nolibc_timespec_kernel_to_user(&ktp, tp);
|
||||
return ret;
|
||||
#else
|
||||
return __nolibc_enosys(__func__, clockid, tp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int clock_gettime(clockid_t clockid, struct timespec *tp)
|
||||
{
|
||||
return __sysret(sys_clock_gettime(clockid, tp));
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_clock_settime(clockid_t clockid, struct timespec *tp)
|
||||
{
|
||||
#if defined(__NR_clock_settime)
|
||||
return my_syscall2(__NR_clock_settime, clockid, tp);
|
||||
#elif defined(__NR_clock_settime64)
|
||||
struct __kernel_timespec ktp;
|
||||
|
||||
__nolibc_timespec_user_to_kernel(tp, &ktp);
|
||||
return my_syscall2(__NR_clock_settime64, clockid, &ktp);
|
||||
#else
|
||||
return __nolibc_enosys(__func__, clockid, tp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int clock_settime(clockid_t clockid, struct timespec *tp)
|
||||
{
|
||||
return __sysret(sys_clock_settime(clockid, tp));
|
||||
}
|
||||
|
||||
|
||||
static __inline__
|
||||
double difftime(time_t time1, time_t time2)
|
||||
{
|
||||
return time1 - time2;
|
||||
}
|
||||
|
||||
|
||||
static __attribute__((unused))
|
||||
time_t time(time_t *tptr)
|
||||
{
|
||||
@@ -25,7 +128,89 @@ time_t time(time_t *tptr)
|
||||
return tv.tv_sec;
|
||||
}
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
/*
|
||||
* int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid);
|
||||
* int timer_gettime(timer_t timerid, struct itimerspec *curr_value);
|
||||
* int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
|
||||
{
|
||||
return my_syscall3(__NR_timer_create, clockid, evp, timerid);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
|
||||
{
|
||||
return __sysret(sys_timer_create(clockid, evp, timerid));
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_timer_delete(timer_t timerid)
|
||||
{
|
||||
return my_syscall1(__NR_timer_delete, timerid);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int timer_delete(timer_t timerid)
|
||||
{
|
||||
return __sysret(sys_timer_delete(timerid));
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value)
|
||||
{
|
||||
#if defined(__NR_timer_gettime)
|
||||
return my_syscall2(__NR_timer_gettime, timerid, curr_value);
|
||||
#elif defined(__NR_timer_gettime64)
|
||||
struct __kernel_itimerspec kcurr_value;
|
||||
int ret;
|
||||
|
||||
ret = my_syscall2(__NR_timer_gettime64, timerid, &kcurr_value);
|
||||
__nolibc_timespec_kernel_to_user(&kcurr_value.it_interval, &curr_value->it_interval);
|
||||
__nolibc_timespec_kernel_to_user(&kcurr_value.it_value, &curr_value->it_value);
|
||||
return ret;
|
||||
#else
|
||||
return __nolibc_enosys(__func__, timerid, curr_value);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int timer_gettime(timer_t timerid, struct itimerspec *curr_value)
|
||||
{
|
||||
return __sysret(sys_timer_gettime(timerid, curr_value));
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_timer_settime(timer_t timerid, int flags,
|
||||
const struct itimerspec *new_value, struct itimerspec *old_value)
|
||||
{
|
||||
#if defined(__NR_timer_settime)
|
||||
return my_syscall4(__NR_timer_settime, timerid, flags, new_value, old_value);
|
||||
#elif defined(__NR_timer_settime64)
|
||||
struct __kernel_itimerspec knew_value, kold_value;
|
||||
int ret;
|
||||
|
||||
__nolibc_timespec_user_to_kernel(&new_value->it_value, &knew_value.it_value);
|
||||
__nolibc_timespec_user_to_kernel(&new_value->it_interval, &knew_value.it_interval);
|
||||
ret = my_syscall4(__NR_timer_settime64, timerid, flags, &knew_value, &kold_value);
|
||||
if (old_value) {
|
||||
__nolibc_timespec_kernel_to_user(&kold_value.it_interval, &old_value->it_interval);
|
||||
__nolibc_timespec_kernel_to_user(&kold_value.it_value, &old_value->it_value);
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
return __nolibc_enosys(__func__, timerid, flags, new_value, old_value);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int timer_settime(timer_t timerid, int flags,
|
||||
const struct itimerspec *new_value, struct itimerspec *old_value)
|
||||
{
|
||||
return __sysret(sys_timer_settime(timerid, flags, new_value, old_value));
|
||||
}
|
||||
|
||||
#endif /* _NOLIBC_TIME_H */
|
||||
|
||||
@@ -4,16 +4,17 @@
|
||||
* Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_TYPES_H
|
||||
#define _NOLIBC_TYPES_H
|
||||
|
||||
#include "std.h"
|
||||
#include <linux/mman.h>
|
||||
#include <linux/reboot.h> /* for LINUX_REBOOT_* */
|
||||
#include <linux/stat.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/resource.h>
|
||||
|
||||
|
||||
/* Only the generic macros and types may be defined here. The arch-specific
|
||||
@@ -156,20 +157,6 @@ typedef struct {
|
||||
__set->fds[__idx] = 0; \
|
||||
} while (0)
|
||||
|
||||
/* for poll() */
|
||||
#define POLLIN 0x0001
|
||||
#define POLLPRI 0x0002
|
||||
#define POLLOUT 0x0004
|
||||
#define POLLERR 0x0008
|
||||
#define POLLHUP 0x0010
|
||||
#define POLLNVAL 0x0020
|
||||
|
||||
struct pollfd {
|
||||
int fd;
|
||||
short int events;
|
||||
short int revents;
|
||||
};
|
||||
|
||||
/* for getdents64() */
|
||||
struct linux_dirent64 {
|
||||
uint64_t d_ino;
|
||||
@@ -198,14 +185,8 @@ struct stat {
|
||||
union { time_t st_ctime; struct timespec st_ctim; }; /* time of last status change */
|
||||
};
|
||||
|
||||
/* WARNING, it only deals with the 4096 first majors and 256 first minors */
|
||||
#define makedev(major, minor) ((dev_t)((((major) & 0xfff) << 8) | ((minor) & 0xff)))
|
||||
#define major(dev) ((unsigned int)(((dev) >> 8) & 0xfff))
|
||||
#define minor(dev) ((unsigned int)(((dev) & 0xff))
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(TYPE, FIELD) ((size_t) &((TYPE *)0)->FIELD)
|
||||
#endif
|
||||
typedef __kernel_clockid_t clockid_t;
|
||||
typedef int timer_t;
|
||||
|
||||
#ifndef container_of
|
||||
#define container_of(PTR, TYPE, FIELD) ({ \
|
||||
@@ -214,7 +195,4 @@ struct stat {
|
||||
})
|
||||
#endif
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#endif /* _NOLIBC_TYPES_H */
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
|
||||
*/
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#ifndef _NOLIBC_UNISTD_H
|
||||
#define _NOLIBC_UNISTD_H
|
||||
|
||||
@@ -17,6 +20,34 @@
|
||||
#define STDOUT_FILENO 1
|
||||
#define STDERR_FILENO 2
|
||||
|
||||
#define F_OK 0
|
||||
#define X_OK 1
|
||||
#define W_OK 2
|
||||
#define R_OK 4
|
||||
|
||||
/*
|
||||
* int access(const char *path, int amode);
|
||||
* int faccessat(int fd, const char *path, int amode, int flag);
|
||||
*/
|
||||
|
||||
static __attribute__((unused))
|
||||
int sys_faccessat(int fd, const char *path, int amode, int flag)
|
||||
{
|
||||
return my_syscall4(__NR_faccessat, fd, path, amode, flag);
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int faccessat(int fd, const char *path, int amode, int flag)
|
||||
{
|
||||
return __sysret(sys_faccessat(fd, path, amode, flag));
|
||||
}
|
||||
|
||||
static __attribute__((unused))
|
||||
int access(const char *path, int amode)
|
||||
{
|
||||
return faccessat(AT_FDCWD, path, amode, 0);
|
||||
}
|
||||
|
||||
|
||||
static __attribute__((unused))
|
||||
int msleep(unsigned int msecs)
|
||||
@@ -56,13 +87,4 @@ int tcsetpgrp(int fd, pid_t pid)
|
||||
return ioctl(fd, TIOCSPGRP, &pid);
|
||||
}
|
||||
|
||||
#define __syscall_narg(_0, _1, _2, _3, _4, _5, _6, N, ...) N
|
||||
#define _syscall_narg(...) __syscall_narg(__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0)
|
||||
#define _syscall(N, ...) __sysret(my_syscall##N(__VA_ARGS__))
|
||||
#define _syscall_n(N, ...) _syscall(N, __VA_ARGS__)
|
||||
#define syscall(...) _syscall_n(_syscall_narg(__VA_ARGS__), ##__VA_ARGS__)
|
||||
|
||||
/* make sure to include all global symbols */
|
||||
#include "nolibc.h"
|
||||
|
||||
#endif /* _NOLIBC_UNISTD_H */
|
||||
|
||||
Reference in New Issue
Block a user