diff options
Diffstat (limited to 'libc/sysdeps/linux/common')
50 files changed, 827 insertions, 98 deletions
diff --git a/libc/sysdeps/linux/common/__rt_sigtimedwait.c b/libc/sysdeps/linux/common/__rt_sigtimedwait.c index f4244148d..aff5299a1 100644 --- a/libc/sysdeps/linux/common/__rt_sigtimedwait.c +++ b/libc/sysdeps/linux/common/__rt_sigtimedwait.c @@ -9,7 +9,7 @@ #include <sys/syscall.h> -#ifdef __NR_rt_sigtimedwait +#if defined(__NR_rt_sigtimedwait) || (defined(__NR_rt_sigtimedwait_time64) && defined(__UCLIBC_USE_TIME64__)) # include <signal.h> # include <cancel.h> # ifdef __UCLIBC_HAS_THREADS_NATIVE__ @@ -21,6 +21,10 @@ # include <string.h> # endif +#if defined(__UCLIBC_USE_TIME64__) +#include "internal/time64_helpers.h" +#endif + int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info, const struct timespec *timeout) { @@ -52,8 +56,13 @@ int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info, /* XXX The size argument hopefully will have to be changed to the real size of the user-level sigset_t. */ /* on uClibc we use the kernel sigset_t size */ +# if defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64) + result = INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info, + TO_TS64_P(timeout), __SYSCALL_SIGSET_T_SIZE); +# else result = INLINE_SYSCALL(rt_sigtimedwait, 4, set, info, timeout, __SYSCALL_SIGSET_T_SIZE); +# endif /* The kernel generates a SI_TKILL code in si_code in case tkill is used. tkill is transparently used in raise(). Since having @@ -65,9 +74,14 @@ int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info, return result; # else /* on uClibc we use the kernel sigset_t size */ +# if defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64) + return INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info, + TO_TS64_P(timeout), __SYSCALL_SIGSET_T_SIZE); +# else return INLINE_SYSCALL(rt_sigtimedwait, 4, set, info, timeout, __SYSCALL_SIGSET_T_SIZE); # endif +# endif } CANCELLABLE_SYSCALL(int, sigtimedwait, (const sigset_t *set, siginfo_t *info, const struct timespec *timeout), diff --git a/libc/sysdeps/linux/common/__rt_sigwaitinfo.c b/libc/sysdeps/linux/common/__rt_sigwaitinfo.c index d2d176a64..7830b2e2c 100644 --- a/libc/sysdeps/linux/common/__rt_sigwaitinfo.c +++ b/libc/sysdeps/linux/common/__rt_sigwaitinfo.c @@ -9,7 +9,7 @@ #include <sys/syscall.h> -#ifdef __NR_rt_sigtimedwait +#if defined(__NR_rt_sigtimedwait) || (defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64)) # define __need_NULL # include <stddef.h> # include <signal.h> diff --git a/libc/sysdeps/linux/common/adjtimex.c b/libc/sysdeps/linux/common/adjtimex.c index f45d54371..2fd7977f6 100644 --- a/libc/sysdeps/linux/common/adjtimex.c +++ b/libc/sysdeps/linux/common/adjtimex.c @@ -9,8 +9,16 @@ #include <sys/syscall.h> #include <sys/timex.h> - +#if defined(__NR_adjtimex) _syscall1(int, adjtimex, struct timex *, buf) +#else +#include <time.h> +int adjtimex(struct timex *buf) +{ + return clock_adjtime(CLOCK_REALTIME, buf); +} +#endif + libc_hidden_def(adjtimex) weak_alias(adjtimex,__adjtimex) #if defined __UCLIBC_NTP_LEGACY__ diff --git a/libc/sysdeps/linux/common/alarm.c b/libc/sysdeps/linux/common/alarm.c index dc43fe732..861f6ad8e 100644 --- a/libc/sysdeps/linux/common/alarm.c +++ b/libc/sysdeps/linux/common/alarm.c @@ -9,7 +9,7 @@ #include <sys/syscall.h> #include <unistd.h> -#ifdef __NR_alarm +#if defined(__NR_alarm) && !defined(__UCLIBC_USE_TIME64__) _syscall1(unsigned int, alarm, unsigned int, seconds) #else # include <sys/time.h> diff --git a/libc/sysdeps/linux/common/bits/hwcap.h b/libc/sysdeps/linux/common/bits/hwcap.h new file mode 100644 index 000000000..e7b899df0 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/hwcap.h @@ -0,0 +1,22 @@ +/* Defines for bits in AT_HWCAP. + Copyright (C) 2012-2023 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _SYS_AUXV_H +# error "Never include <bits/hwcap.h> directly; use <sys/auxv.h> instead." +#endif + +/* No bits defined for this architecture. */ diff --git a/libc/sysdeps/linux/common/bits/jmp_buf_tag.h b/libc/sysdeps/linux/common/bits/jmp_buf_tag.h new file mode 100644 index 000000000..367b7bc66 --- /dev/null +++ b/libc/sysdeps/linux/common/bits/jmp_buf_tag.h @@ -0,0 +1,37 @@ +/* Define struct __jmp_buf_tag. + Copyright (C) 1991-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef __jmp_buf_tag_defined +#define __jmp_buf_tag_defined 1 + +#include <bits/setjmp.h> +#include <bits/sigset.h> + +/* Calling environment, plus possibly a saved signal mask. */ +struct __jmp_buf_tag + { + /* NOTE: The machine-dependent definitions of `__sigsetjmp' + assume that a `jmp_buf' begins with a `__jmp_buf' and that + `__mask_was_saved' follows it. Do not move these members + or add others before it. */ + __jmp_buf __jmpbuf; /* Calling environment. */ + int __mask_was_saved; /* Saved the signal mask? */ + __sigset_t __saved_mask; /* Saved signal mask. */ + }; + +#endif diff --git a/libc/sysdeps/linux/common/bits/mman-linux.h b/libc/sysdeps/linux/common/bits/mman-linux.h index 6ca08415a..4947ddd89 100644 --- a/libc/sysdeps/linux/common/bits/mman-linux.h +++ b/libc/sysdeps/linux/common/bits/mman-linux.h @@ -46,6 +46,7 @@ /* Other flags. */ #define MAP_FIXED 0x10 /* Interpret addr exactly. */ +# define MAP_FIXED_NOREPLACE 0x100000 /* Used to solve problem with MAP_FIXED */ #ifdef __USE_MISC # define MAP_FILE 0 # ifdef __MAP_ANONYMOUS diff --git a/libc/sysdeps/linux/common/bits/resource.h b/libc/sysdeps/linux/common/bits/resource.h index 92b67eb23..89c3d4e41 100644 --- a/libc/sysdeps/linux/common/bits/resource.h +++ b/libc/sysdeps/linux/common/bits/resource.h @@ -165,6 +165,15 @@ enum __rusage_who /* All of its terminated child processes. */ RUSAGE_CHILDREN = -1 #define RUSAGE_CHILDREN RUSAGE_CHILDREN + +#ifdef __USE_GNU + , + /* The calling thread. */ + RUSAGE_THREAD = 1 +# define RUSAGE_THREAD RUSAGE_THREAD + /* Name for the same functionality on Solaris. */ +# define RUSAGE_LWP RUSAGE_THREAD +#endif }; #define __need_timeval diff --git a/libc/sysdeps/linux/common/bits/sem.h b/libc/sysdeps/linux/common/bits/sem.h index 910c4b714..24a130981 100644 --- a/libc/sysdeps/linux/common/bits/sem.h +++ b/libc/sysdeps/linux/common/bits/sem.h @@ -39,15 +39,31 @@ struct semid_ds { struct ipc_perm sem_perm; /* operation permission struct */ +#if defined(__UCLIBC_USE_TIME64__) + unsigned long int __sem_otime_internal_1; + unsigned long int __sem_otime_internal_2; +#else __time_t sem_otime; /* last semop() time */ -#if __WORDSIZE == 32 +#endif +#if (__WORDSIZE == 32 && !defined(__ARC64_ARCH32__) && !defined(__arc__) && !defined(__arm__) && !defined(__or1k__) && !defined(__xtensa__)) || \ + ((defined(__ARC64_ARCH32__) || defined(__arc__) || defined(__arm__) || defined(__or1k__) || defined(__xtensa__)) && !defined(__UCLIBC_USE_TIME64__)) unsigned long int __uclibc_unused1; #endif +#if defined(__UCLIBC_USE_TIME64__) + unsigned long int __sem_ctime_internal_1; + unsigned long int __sem_ctime_internal_2; +#else __time_t sem_ctime; /* last time changed by semctl() */ -#if __WORDSIZE == 32 +#endif +#if (__WORDSIZE == 32 && !defined(__ARC64_ARCH32__) && !defined(__arc__) && !defined(__arm__) && !defined(__or1k__) && !defined(__xtensa__)) || \ + ((defined(__ARC64_ARCH32__) || defined(__arc__) || defined(__arm__) || defined(__or1k__) || defined(__xtensa__)) && !defined(__UCLIBC_USE_TIME64__)) unsigned long int __uclibc_unused2; #endif unsigned long int sem_nsems; /* number of semaphores in set */ +#if defined(__UCLIBC_USE_TIME64__) + __time_t sem_otime; /* last semop() time */ + __time_t sem_ctime; /* last time changed by semctl() */ +#endif unsigned long int __uclibc_unused3; unsigned long int __uclibc_unused4; }; diff --git a/libc/sysdeps/linux/common/bits/stab.def b/libc/sysdeps/linux/common/bits/stab.def index 8a2b8f39d..8d16c5c2c 100644 --- a/libc/sysdeps/linux/common/bits/stab.def +++ b/libc/sysdeps/linux/common/bits/stab.def @@ -17,7 +17,7 @@ <http://www.gnu.org/licenses/>. */ /* This contains contribution from Cygnus Support. */ - + /* Global variable. Only the name is significant. To find the address, look in the corresponding external symbol. */ __define_stab (N_GSYM, 0x20, "GSYM") @@ -177,7 +177,7 @@ __define_stab (N_NBLCS, 0xF8, "NBLCS") /* Second symbol entry containing a length-value for the preceding entry. The value is the length. */ __define_stab (N_LENG, 0xfe, "LENG") - + /* The above information, in matrix format. STAB MATRIX diff --git a/libc/sysdeps/linux/common/bits/syscalls-common.h b/libc/sysdeps/linux/common/bits/syscalls-common.h index 3665345a6..c3b193e6f 100644..100755 --- a/libc/sysdeps/linux/common/bits/syscalls-common.h +++ b/libc/sysdeps/linux/common/bits/syscalls-common.h @@ -99,21 +99,75 @@ type name(C_DECL_ARGS_##nargs(args)) { \ return (type)INLINE_SYSCALL(name, nargs, C_ARGS_##nargs(args)); \ } +#define SYSCALL_FUNC_TIME64(nargs, type, name, args...) \ +type name(C_DECL_ARGS_##nargs(args)) { \ + return (type)INLINE_SYSCALL(name##_time64, nargs, C_ARGS_##nargs(args)); \ +} + +#define SYSCALL_FUNC_64(nargs, type, name, args...) \ +type name(C_DECL_ARGS_##nargs(args)) { \ + return (type)INLINE_SYSCALL(name##64, nargs, C_ARGS_##nargs(args)); \ +} + + #define SYSCALL_NOERR_FUNC(nargs, type, name, args...) \ type name(C_DECL_ARGS_##nargs(args)) { \ return (type)INLINE_SYSCALL_NOERR(name, nargs, C_ARGS_##nargs(args)); \ } +#define SYSCALL_NOERR_FUNC_TIME64(nargs, type, name, args...) \ +type name(C_DECL_ARGS_##nargs(args)) { \ + return (type)INLINE_SYSCALL_NOERR(name##_time64, nargs, C_ARGS_##nargs(args)); \ +} + +#define SYSCALL_NOERR_FUNC_64(nargs, type, name, args...) \ +type name(C_DECL_ARGS_##nargs(args)) { \ + return (type)INLINE_SYSCALL_NOERR(name##64, nargs, C_ARGS_##nargs(args)); \ +} + +#define SYSCALL_FUNC_BODY(nargs, type, name, args...) \ + return (type)INLINE_SYSCALL(name, nargs, C_ARGS_##nargs(args)); + +#define SYSCALL_FUNC_BODY_TIME64(nargs, type, name, args...) \ + return (type)INLINE_SYSCALL(name##_time64, nargs, C_ARGS_##nargs(args)); + +#define SYSCALL_FUNC_BODY_64(nargs, type, name, args...) \ + return (type)INLINE_SYSCALL(name##64, nargs, C_ARGS_##nargs(args)); + #define _syscall0(args...) SYSCALL_FUNC(0, args) #define _syscall_noerr0(args...) SYSCALL_NOERR_FUNC(0, args) #define _syscall1(args...) SYSCALL_FUNC(1, args) #define _syscall_noerr1(args...) SYSCALL_NOERR_FUNC(1, args) #define _syscall2(args...) SYSCALL_FUNC(2, args) +#define _syscall2_body(args...) SYSCALL_FUNC_BODY(2, args) #define _syscall3(args...) SYSCALL_FUNC(3, args) #define _syscall4(args...) SYSCALL_FUNC(4, args) #define _syscall5(args...) SYSCALL_FUNC(5, args) #define _syscall6(args...) SYSCALL_FUNC(6, args) +#define _syscall0_time64(args...) SYSCALL_FUNC_TIME64(0, args) +#define _syscall_noerr0_time64(args...) SYSCALL_NOERR_FUNC_TIME64(0, args) +#define _syscall1_time64(args...) SYSCALL_FUNC_TIME64(1, args) +#define _syscall_noerr1_time64(args...) SYSCALL_NOERR_FUNC_TIME64(1, args) +#define _syscall2_time64(args...) SYSCALL_FUNC_TIME64(2, args) +#define _syscall2_body_time64(args...) SYSCALL_FUNC_BODY_TIME64(2, args) +#define _syscall3_time64(args...) SYSCALL_FUNC_TIME64(3, args) +#define _syscall4_time64(args...) SYSCALL_FUNC_TIME64(4, args) +#define _syscall5_time64(args...) SYSCALL_FUNC_TIME64(5, args) +#define _syscall6_time64(args...) SYSCALL_FUNC_TIME64(6, args) + +#define _syscall0_64(args...) SYSCALL_FUNC_64(0, args) +#define _syscall_noerr0_64(args...) SYSCALL_NOERR_FUNC_64(0, args) +#define _syscall1_64(args...) SYSCALL_FUNC_64(1, args) +#define _syscall_noerr1_64(args...) SYSCALL_NOERR_FUNC_64(1, args) +#define _syscall2_64(args...) SYSCALL_FUNC_64(2, args) +#define _syscall2_body_64(args...) SYSCALL_FUNC_BODY_64(2, args) +#define _syscall3_64(args...) SYSCALL_FUNC_64(3, args) +#define _syscall4_64(args...) SYSCALL_FUNC_64(4, args) +#define _syscall5_64(args...) SYSCALL_FUNC_64(5, args) +#define _syscall6_64(args...) SYSCALL_FUNC_64(6, args) + + #endif /* _syscall0 */ #endif /* __ASSEMBLER__ */ diff --git a/libc/sysdeps/linux/common/bits/typesizes.h b/libc/sysdeps/linux/common/bits/typesizes.h index e1c5a27bb..dcb2c3b0a 100644 --- a/libc/sysdeps/linux/common/bits/typesizes.h +++ b/libc/sysdeps/linux/common/bits/typesizes.h @@ -46,9 +46,21 @@ #define __FSFILCNT64_T_TYPE __UQUAD_TYPE #define __ID_T_TYPE __U32_TYPE #define __CLOCK_T_TYPE __SLONGWORD_TYPE + +#ifdef __UCLIBC_USE_TIME64__ +#define __TIME_T_TYPE __S64_TYPE +#else #define __TIME_T_TYPE __SLONGWORD_TYPE +#endif /* __UCLIBC_USE_TIME64__ */ + #define __USECONDS_T_TYPE __U32_TYPE + +#ifdef __UCLIBC_USE_TIME64__ +#define __SUSECONDS_T_TYPE __S64_TYPE +#else #define __SUSECONDS_T_TYPE __SLONGWORD_TYPE +#endif + #define __DADDR_T_TYPE __S32_TYPE #define __SWBLK_T_TYPE __SLONGWORD_TYPE #define __KEY_T_TYPE __S32_TYPE diff --git a/libc/sysdeps/linux/common/bits/uClibc_uwchar.h b/libc/sysdeps/linux/common/bits/uClibc_uwchar.h index 47ea3cda1..91b789c80 100644 --- a/libc/sysdeps/linux/common/bits/uClibc_uwchar.h +++ b/libc/sysdeps/linux/common/bits/uClibc_uwchar.h @@ -36,6 +36,7 @@ #include <limits.h> #include <stdint.h> +#include <wchar.h> #if WCHAR_MIN == 0 typedef wchar_t __uwchar_t; diff --git a/libc/sysdeps/linux/common/bits/wchar.h b/libc/sysdeps/linux/common/bits/wchar.h index a3ff5319e..ce951d9b6 100644 --- a/libc/sysdeps/linux/common/bits/wchar.h +++ b/libc/sysdeps/linux/common/bits/wchar.h @@ -1,5 +1,5 @@ /* wchar_t type related definitions. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000-2023 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -14,12 +14,36 @@ You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ + <https://www.gnu.org/licenses/>. */ #ifndef _BITS_WCHAR_H #define _BITS_WCHAR_H 1 -#define __WCHAR_MIN (-2147483647 - 1) -#define __WCHAR_MAX (2147483647) +/* The fallback definitions, for when __WCHAR_MAX__ or __WCHAR_MIN__ + are not defined, give the right value and type as long as both int + and wchar_t are 32-bit types. Adding L'\0' to a constant value + ensures that the type is correct; it is necessary to use (L'\0' + + 0) rather than just L'\0' so that the type in C++ is the promoted + version of wchar_t rather than the distinct wchar_t type itself. + Because wchar_t in preprocessor #if expressions is treated as + intmax_t or uintmax_t, the expression (L'\0' - 1) would have the + wrong value for WCHAR_MAX in such expressions and so cannot be used + to define __WCHAR_MAX in the unsigned case. */ + +#ifdef __WCHAR_MAX__ +# define __WCHAR_MAX __WCHAR_MAX__ +#elif L'\0' - 1 > 0 +# define __WCHAR_MAX (0xffffffffu + L'\0') +#else +# define __WCHAR_MAX (0x7fffffff + L'\0') +#endif + +#ifdef __WCHAR_MIN__ +# define __WCHAR_MIN __WCHAR_MIN__ +#elif L'\0' - 1 > 0 +# define __WCHAR_MIN (L'\0' + 0) +#else +# define __WCHAR_MIN (-__WCHAR_MAX - 1) +#endif #endif /* bits/wchar.h */ diff --git a/libc/sysdeps/linux/common/clock_adjtime.c b/libc/sysdeps/linux/common/clock_adjtime.c index 9f55d4527..53f64e9d5 100644 --- a/libc/sysdeps/linux/common/clock_adjtime.c +++ b/libc/sysdeps/linux/common/clock_adjtime.c @@ -10,6 +10,10 @@ #include <sys/syscall.h> #include <sys/timex.h> -#ifdef __NR_clock_adjtime +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_adjtime64) +_syscall2_64(int, clock_adjtime, clockid_t, clock_id, struct timex*, ntx) +#elif defined(__NR_clock_adjtime) _syscall2(int, clock_adjtime, clockid_t, clock_id, struct timex*, ntx) +#else +#error "clock_adjtime syscall is not defined!" #endif diff --git a/libc/sysdeps/linux/common/clock_getres.c b/libc/sysdeps/linux/common/clock_getres.c index 532047ede..fd0f8c14c 100644 --- a/libc/sysdeps/linux/common/clock_getres.c +++ b/libc/sysdeps/linux/common/clock_getres.c @@ -10,7 +10,21 @@ #include <sys/syscall.h> #include <time.h> -#ifdef __NR_clock_getres +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_getres_time64) +#include "internal/time64_helpers.h" + +int clock_getres(clockid_t clock_id, struct timespec *res) +{ + struct __ts64_struct __ts64; + int __ret = INLINE_SYSCALL(clock_getres_time64, 2, clock_id, &__ts64); + if (__ret == 0 && res) { + res->tv_sec = __ts64.tv_sec; + res->tv_nsec = __ts64.tv_nsec; + }; + + return __ret; +} +#elif defined(__NR_clock_getres) _syscall2(int, clock_getres, clockid_t, clock_id, struct timespec*, res) #else # include <unistd.h> diff --git a/libc/sysdeps/linux/common/clock_gettime.c b/libc/sysdeps/linux/common/clock_gettime.c index 95d398239..b924d860b 100644 --- a/libc/sysdeps/linux/common/clock_gettime.c +++ b/libc/sysdeps/linux/common/clock_gettime.c @@ -11,12 +11,33 @@ #include <sys/syscall.h> #include <time.h> -#ifdef __NR_clock_gettime -_syscall2(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp) +#ifdef __VDSO_SUPPORT__ +#include "ldso.h" +#endif + +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64) +#include "internal/time64_helpers.h" + +int __libc_clock_gettime(clockid_t clock_id, struct timespec *tp) +{ + struct __ts64_struct __ts64; + int __ret = INLINE_SYSCALL(clock_gettime64, 2, clock_id, &__ts64); + if (tp) { + tp->tv_sec = __ts64.tv_sec; + tp->tv_nsec = __ts64.tv_nsec; + } + + return __ret; +} +#elif defined(__NR_clock_gettime) +int __libc_clock_gettime(clockid_t clock_id, struct timespec *tp) +{ + return INLINE_SYSCALL(clock_gettime, 2, clock_id, tp); +} #else # include <sys/time.h> -int clock_gettime(clockid_t clock_id, struct timespec* tp) +int __libc_clock_gettime(clockid_t clock_id, struct timespec* tp) { struct timeval tv; int retval = -1; @@ -39,3 +60,12 @@ int clock_gettime(clockid_t clock_id, struct timespec* tp) return retval; } #endif + +int clock_gettime(clockid_t clock_id, struct timespec *tp) +{ +#if defined(__VDSO_SUPPORT__) && defined(ARCH_VDSO_CLOCK_GETTIME) + return ARCH_VDSO_CLOCK_GETTIME(clock_id, tp); +#else + return __libc_clock_gettime(clock_id, tp); +#endif +} diff --git a/libc/sysdeps/linux/common/clock_settime.c b/libc/sysdeps/linux/common/clock_settime.c index 636f18417..3abc5f49b 100644 --- a/libc/sysdeps/linux/common/clock_settime.c +++ b/libc/sysdeps/linux/common/clock_settime.c @@ -10,7 +10,15 @@ #include <sys/syscall.h> #include <time.h> -#ifdef __NR_clock_settime + +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_settime64) +#include "internal/time64_helpers.h" + +int clock_settime(clockid_t clock_id, const struct timespec *tp) +{ + return INLINE_SYSCALL(clock_settime64, 2, clock_id, TO_TS64_P(tp)); +} +#elif defined(__NR_clock_settime) _syscall2(int, clock_settime, clockid_t, clock_id, const struct timespec*, tp) #else # include <sys/time.h> diff --git a/libc/sysdeps/linux/common/fstat.c b/libc/sysdeps/linux/common/fstat.c index 0b2798ad4..65e879799 100644 --- a/libc/sysdeps/linux/common/fstat.c +++ b/libc/sysdeps/linux/common/fstat.c @@ -10,10 +10,11 @@ #include <unistd.h> #include <sys/stat.h> #include <sys/syscall.h> +#include <bits/uClibc_arch_features.h> #include "xstatconv.h" -#if defined __NR_fstat64 && !defined __NR_fstat +#if defined __NR_fstat64 && !defined __NR_fstat && !defined(__UCLIBC_USE_TIME64__) int fstat(int fd, struct stat *buf) { return INLINE_SYSCALL(fstat64, 2, fd, buf); @@ -29,7 +30,7 @@ int fstat(int fd, struct stat *buf) } libc_hidden_def(fstat) -#elif __NR_statx && defined __UCLIBC_HAVE_STATX__ +#elif defined __NR_statx && defined __UCLIBC_HAVE_STATX__ # include <fcntl.h> # include <statx_cp.h> @@ -40,6 +41,8 @@ int fstat(int fd, struct stat *buf) STATX_BASIC_STATS, &tmp); if (rc == 0) __cp_stat_statx ((struct stat *)buf, &tmp); + + return rc; } libc_hidden_def(fstat) diff --git a/libc/sysdeps/linux/common/fstat64.c b/libc/sysdeps/linux/common/fstat64.c index fe1cb4fe5..359c22af6 100644 --- a/libc/sysdeps/linux/common/fstat64.c +++ b/libc/sysdeps/linux/common/fstat64.c @@ -9,7 +9,7 @@ #include <_lfs_64.h> #include <sys/syscall.h> -#ifdef __NR_fstat64 +#if defined(__NR_fstat64) && !defined(__UCLIBC_USE_TIME64__) # include <unistd.h> # include <sys/stat.h> # include "xstatconv.h" @@ -45,7 +45,7 @@ int fstat64(int fd, struct stat64 *buf) int rc = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH, STATX_BASIC_STATS, &tmp); if (rc == 0) - __cp_stat_statx ((struct stat64 *)buf, &tmp); + __cp_stat64_statx ((struct stat64 *)buf, &tmp); return rc; } diff --git a/libc/sysdeps/linux/common/fstatat.c b/libc/sysdeps/linux/common/fstatat.c index 13673d76c..14b118cc0 100644 --- a/libc/sysdeps/linux/common/fstatat.c +++ b/libc/sysdeps/linux/common/fstatat.c @@ -9,13 +9,14 @@ #include <sys/syscall.h> #include <sys/stat.h> #include "xstatconv.h" +#include <bits/uClibc_arch_features.h> /* 64bit ports tend to favor newfstatat() */ #if __WORDSIZE == 64 && defined __NR_newfstatat # define __NR_fstatat64 __NR_newfstatat #endif -#ifdef __NR_fstatat64 +#if defined(__NR_fstatat64) && !defined(__UCLIBC_USE_TIME64__) int fstatat(int fd, const char *file, struct stat *buf, int flag) { int ret; @@ -31,5 +32,44 @@ int fstatat(int fd, const char *file, struct stat *buf, int flag) } libc_hidden_def(fstatat) #else + +#if defined(__NR_statx) && defined __UCLIBC_HAVE_STATX__ +#include <sys/sysmacros.h> // for makedev + +int fstatat(int fd, const char *file, struct stat *buf, int flag) +{ + int ret; + struct statx tmp; + + ret = INLINE_SYSCALL(statx, 5, fd, file, flag, + STATX_BASIC_STATS, &tmp); + if (ret != 0) + return ret; + + *buf = (struct stat) { + .st_dev = makedev(tmp.stx_dev_major, tmp.stx_dev_minor), + .st_ino = tmp.stx_ino, + .st_mode = tmp.stx_mode, + .st_nlink = tmp.stx_nlink, + .st_uid = tmp.stx_uid, + .st_gid = tmp.stx_gid, + .st_rdev = makedev(tmp.stx_rdev_major, tmp.stx_rdev_minor), + .st_size = tmp.stx_size, + .st_blksize = tmp.stx_blksize, + .st_blocks = tmp.stx_blocks, + .st_atim.tv_sec = tmp.stx_atime.tv_sec, + .st_atim.tv_nsec = tmp.stx_atime.tv_nsec, + .st_mtim.tv_sec = tmp.stx_mtime.tv_sec, + .st_mtim.tv_nsec = tmp.stx_mtime.tv_nsec, + .st_ctim.tv_sec = tmp.stx_ctime.tv_sec, + .st_ctim.tv_nsec = tmp.stx_ctime.tv_nsec, + }; + + return ret; +} +libc_hidden_def(fstatat) + +#endif + /* should add emulation with fstat() and /proc/self/fd/ ... */ #endif diff --git a/libc/sysdeps/linux/common/fstatat64.c b/libc/sysdeps/linux/common/fstatat64.c index 711521a6a..16dbf9215 100644 --- a/libc/sysdeps/linux/common/fstatat64.c +++ b/libc/sysdeps/linux/common/fstatat64.c @@ -23,7 +23,7 @@ # define __NR_fstatat64 __NR_newfstatat #endif -#ifdef __NR_fstatat64 +#if defined(__NR_fstatat64) && !defined(__UCLIBC_USE_TIME64__) # include <sys/stat.h> # include "xstatconv.h" int fstatat64(int fd, const char *file, struct stat64 *buf, int flag) @@ -43,5 +43,26 @@ int fstatat64(int fd, const char *file, struct stat64 *buf, int flag) } libc_hidden_def(fstatat64) #else + +#if defined(__NR_statx) && defined(__UCLIBC_HAVE_STATX__) +# include <sys/stat.h> +# include <statx_cp.h> +# include <fcntl.h> // for AT_NO_AUTOMOUNT + +int fstatat64(int fd, const char *file, struct stat64 *buf, int flag) +{ + struct statx tmp; + + int r = INLINE_SYSCALL(statx, 5, fd, file, AT_NO_AUTOMOUNT | flag, + STATX_BASIC_STATS, &tmp); + + if (r == 0) + __cp_stat64_statx ((struct stat64 *)buf, &tmp); + + return r; +} +libc_hidden_def(fstatat64) +#endif + /* should add emulation with fstat64() and /proc/self/fd/ ... */ #endif diff --git a/libc/sysdeps/linux/common/futimens.c b/libc/sysdeps/linux/common/futimens.c index 03e58f4b5..2f3d72420 100644 --- a/libc/sysdeps/linux/common/futimens.c +++ b/libc/sysdeps/linux/common/futimens.c @@ -8,7 +8,7 @@ #include <sys/syscall.h> #include <time.h> -#ifdef __NR_utimensat +#if defined(__NR_utimensat) || defined(__NR_utimensat_time64) /* To avoid superfluous warnings about passing NULL to the non-null annotated * 2nd param "__path" below, we bypass inclusion of sys/stat.h and use * a non annotated, local decl. diff --git a/libc/sysdeps/linux/common/futimesat.c b/libc/sysdeps/linux/common/futimesat.c index bd73eae7e..bf36550dd 100644 --- a/libc/sysdeps/linux/common/futimesat.c +++ b/libc/sysdeps/linux/common/futimesat.c @@ -7,10 +7,33 @@ */ #include <sys/syscall.h> +#include <sys/stat.h> #include <sys/time.h> #ifdef __NR_futimesat _syscall3(int, futimesat, int, fd, const char *, file, const struct timeval *, tvp) -#else -/* should add emulation with futimes() and /proc/self/fd/ ... */ +#elif defined __NR_utimensat +#include <errno.h> +#define __need_NULL +#include <stddef.h> + +int futimesat(int dirfd, const char *file, const struct timeval tvp[2]) +{ + struct timespec ts[2]; + + if (tvp != NULL) + { + if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000 + || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000) + { + __set_errno(EINVAL); + return -1; + } + + TIMEVAL_TO_TIMESPEC(&tvp[0], &ts[0]); + TIMEVAL_TO_TIMESPEC(&tvp[1], &ts[1]); + } + + return utimensat(dirfd, file, tvp ? ts : NULL, 0); +} #endif diff --git a/libc/sysdeps/linux/common/getrlimit.c b/libc/sysdeps/linux/common/getrlimit.c index 26d3d2946..46726fcbd 100644 --- a/libc/sysdeps/linux/common/getrlimit.c +++ b/libc/sysdeps/linux/common/getrlimit.c @@ -9,10 +9,11 @@ #include <sys/syscall.h> #include <sys/resource.h> #include <bits/wordsize.h> +#include <stddef.h> // needed for NULL to be defined /* Only wrap getrlimit if the new ugetrlimit is not present and getrlimit sucks */ -#if defined __NR_ugetrlimit +#if defined(__NR_ugetrlimit) /* just call ugetrlimit() */ # define __NR___syscall_ugetrlimit __NR_ugetrlimit @@ -23,17 +24,58 @@ int getrlimit(__rlimit_resource_t resource, struct rlimit *rlimits) { return __syscall_ugetrlimit(resource, rlimits); } +libc_hidden_def(getrlimit) + +#elif defined(__NR_prlimit64) +/* Use prlimit64 if present, the prlimit64 syscall is free from a back + compatibility stuff for an old getrlimit */ + +# if __WORDSIZE == 32 && !defined(__USE_FILE_OFFSET64) +/* If struct rlimit has 64-bit fields (if __WORDSIZE == 64 or __USE_FILE_OFFSET64 + is defined), then use getrlimit as an alias to getrlimit64, see getrlimit64.c */ +int getrlimit(__rlimit_resource_t resource, struct rlimit *rlimits) +{ + struct rlimit64 rlimits64; + int res = INLINE_SYSCALL (prlimit64, 4, 0, resource, NULL, &rlimits64); + + if (res == 0) { + /* If the syscall succeeds but the values do not fit into a + rlimit structure set EOVERFLOW errno and retrun -1. */ + rlimits->rlim_cur = rlimits64.rlim_cur; + if (rlimits64.rlim_cur != rlimits->rlim_cur) { + if (rlimits64.rlim_cur != RLIM64_INFINITY) { + __set_errno(EOVERFLOW); + return -1; + } + rlimits->rlim_cur = RLIM_INFINITY; + } -#elif !defined(__UCLIBC_HANDLE_OLDER_RLIMIT__) + rlimits->rlim_max = rlimits64.rlim_max; + if (rlimits64.rlim_max != rlimits->rlim_max) { + if (rlimits64.rlim_max != RLIM64_INFINITY) { + __set_errno(EOVERFLOW); + return -1; + } + rlimits->rlim_max = RLIM_INFINITY; + } + } + return res; +} +libc_hidden_def(getrlimit) +# endif + +#else + +# if !defined(__UCLIBC_HANDLE_OLDER_RLIMIT__) /* We don't need to wrap getrlimit() */ _syscall2(int, getrlimit, __rlimit_resource_t, resource, struct rlimit *, rlim) -#else +# else /* we have to handle old style getrlimit() */ -# define __NR___syscall_getrlimit __NR_getrlimit +# define __NR___syscall_getrlimit __NR_getrlimit static __always_inline _syscall2(int, __syscall_getrlimit, int, resource, struct rlimit *, rlim) @@ -54,9 +96,7 @@ int getrlimit(__rlimit_resource_t resource, struct rlimit *rlimits) rlimits->rlim_max = RLIM_INFINITY; return result; } -#endif -libc_hidden_def(getrlimit) +# endif -#if __WORDSIZE == 64 -strong_alias_untyped(getrlimit, getrlimit64) +libc_hidden_def(getrlimit) #endif diff --git a/libc/sysdeps/linux/common/getrlimit64.c b/libc/sysdeps/linux/common/getrlimit64.c index be98098a1..47f1410fb 100644 --- a/libc/sysdeps/linux/common/getrlimit64.c +++ b/libc/sysdeps/linux/common/getrlimit64.c @@ -17,14 +17,31 @@ #include <_lfs_64.h> #include <bits/wordsize.h> +#include <sys/resource.h> +#include <sys/syscall.h> +#include <stddef.h> // needed for NULL to be defined -/* the regular getrlimit will work just fine for 64bit users */ -#if __WORDSIZE == 32 -# include <sys/resource.h> +#if defined(__NR_prlimit64) + +/* the regular prlimit64 will work just fine for 64-bit users */ +int getrlimit64 (__rlimit_resource_t resource, struct rlimit64 *rlimits) +{ + return INLINE_SYSCALL (prlimit64, 4, 0, resource, NULL, rlimits); +} + +# if !defined(__NR_ugetrlimit) && (__WORDSIZE == 64 || defined (__USE_FILE_OFFSET64)) +/* If getrlimit is not implemented through the __NR_ugetrlimit and size of + rlimit_t == rlimit64_t then use getrlimit as an alias to getrlimit64 */ +strong_alias_untyped(getrlimit64, getrlimit) +libc_hidden_def(getrlimit) +# endif + +#else /* Put the soft and hard limits for RESOURCE in *RLIMITS. - Returns 0 if successful, -1 if not (and sets errno). */ + Returns 0 if successful, -1 if not (and sets errno). + The regular getrlimit will work just fine for 64-bit users */ int getrlimit64 (__rlimit_resource_t resource, struct rlimit64 *rlimits) { struct rlimit rlimits32; @@ -44,3 +61,4 @@ int getrlimit64 (__rlimit_resource_t resource, struct rlimit64 *rlimits) return 0; } #endif + diff --git a/libc/sysdeps/linux/common/gettimeofday.c b/libc/sysdeps/linux/common/gettimeofday.c index 1c62b3937..9b29fe5a0 100644..100755 --- a/libc/sysdeps/linux/common/gettimeofday.c +++ b/libc/sysdeps/linux/common/gettimeofday.c @@ -8,6 +8,25 @@ #include <sys/syscall.h> #include <sys/time.h> +#include <time.h> + +#ifdef __VDSO_SUPPORT__ +#include "ldso.h" +#endif + +int gettimeofday(struct timeval * tv, __timezone_ptr_t tz) { + if (!tv) + return 0; +#if defined(__VDSO_SUPPORT__) && defined(ARCH_VDSO_GETTIMEOFDAY) + return ARCH_VDSO_GETTIMEOFDAY(tv, tz); +#else + struct timespec __ts; + int __ret = clock_gettime(CLOCK_REALTIME, &__ts); + tv->tv_sec = __ts.tv_sec; + tv->tv_usec = (suseconds_t)__ts.tv_nsec / 1000; + return __ret; +#endif +} + -_syscall2(int, gettimeofday, struct timeval *, tv, __timezone_ptr_t, tz) libc_hidden_def(gettimeofday) diff --git a/libc/sysdeps/linux/common/lstat.c b/libc/sysdeps/linux/common/lstat.c index 8a0baf85f..2ebd8615e 100644 --- a/libc/sysdeps/linux/common/lstat.c +++ b/libc/sysdeps/linux/common/lstat.c @@ -9,8 +9,9 @@ #include <sys/syscall.h> #include <unistd.h> #include <sys/stat.h> +#include <bits/uClibc_arch_features.h> -#if defined __NR_fstatat64 && !defined __NR_lstat +#if defined __NR_fstatat64 && !defined __NR_lstat && !defined(__UCLIBC_USE_TIME64__) # include <fcntl.h> int lstat(const char *file_name, struct stat *buf) diff --git a/libc/sysdeps/linux/common/lstat64.c b/libc/sysdeps/linux/common/lstat64.c index 61892994e..efc5b1b7f 100644 --- a/libc/sysdeps/linux/common/lstat64.c +++ b/libc/sysdeps/linux/common/lstat64.c @@ -11,7 +11,7 @@ #include <unistd.h> #include <sys/stat.h> -#if defined __NR_fstatat64 && !defined __NR_lstat +#if defined __NR_fstatat64 && !defined __NR_lstat && !defined(__UCLIBC_USE_TIME64__) # include <fcntl.h> int lstat64(const char *file_name, struct stat64 *buf) diff --git a/libc/sysdeps/linux/common/nanosleep.c b/libc/sysdeps/linux/common/nanosleep.c index 4463e108a..2b59fefef 100644 --- a/libc/sysdeps/linux/common/nanosleep.c +++ b/libc/sysdeps/linux/common/nanosleep.c @@ -10,11 +10,21 @@ #include <time.h> #include <cancel.h> -#define __NR___nanosleep_nocancel __NR_nanosleep -static _syscall2(int, __NC(nanosleep), const struct timespec *, req, - struct timespec *, rem); + +int _NC(nanosleep)(const struct timespec *req, struct timespec *rem) +{ + int __ret = clock_nanosleep(CLOCK_REALTIME, 0, req, rem); + + if (__ret != 0) { + __set_errno(__ret); + return -1; + } + + return __ret; +}; CANCELLABLE_SYSCALL(int, nanosleep, (const struct timespec *req, struct timespec *rem), (req, rem)) + lt_libc_hidden(nanosleep) diff --git a/libc/sysdeps/linux/common/not-cancel.h b/libc/sysdeps/linux/common/not-cancel.h index 9d1588494..e4fb1d7fe 100644 --- a/libc/sysdeps/linux/common/not-cancel.h +++ b/libc/sysdeps/linux/common/not-cancel.h @@ -113,9 +113,9 @@ extern __typeof(pause) __pause_nocancel; #ifdef __NR_nanosleep # define nanosleep_not_cancel(requested_time, remaining) \ INLINE_SYSCALL (nanosleep, 2, requested_time, remaining) -/*#else +#else # define nanosleep_not_cancel(requested_time, remaining) \ - __nanosleep_nocancel (requested_time, remaining)*/ + __nanosleep_nocancel (requested_time, remaining) #endif #if 0 diff --git a/libc/sysdeps/linux/common/ppoll.c b/libc/sysdeps/linux/common/ppoll.c index 781f1ff1c..870717bd7 100644 --- a/libc/sysdeps/linux/common/ppoll.c +++ b/libc/sysdeps/linux/common/ppoll.c @@ -18,7 +18,7 @@ #include <sys/syscall.h> -#if defined __NR_ppoll && defined __UCLIBC_LINUX_SPECIFIC__ && defined __USE_GNU +#if (defined __NR_ppoll || defined(__NR_ppoll_time64)) && defined __UCLIBC_LINUX_SPECIFIC__ && defined __USE_GNU #define __need_NULL #include <stddef.h> @@ -26,6 +26,10 @@ #include <sys/poll.h> #include <cancel.h> +#if defined(__UCLIBC_USE_TIME64__) +#include "internal/time64_helpers.h" +#endif + static int __NC(ppoll)(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, const sigset_t *sigmask) @@ -37,11 +41,14 @@ __NC(ppoll)(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, tval = *timeout; timeout = &tval; } +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_ppoll_time64) + return INLINE_SYSCALL(ppoll_time64, 5, fds, nfds, TO_TS64_P(timeout), sigmask, __SYSCALL_SIGSET_T_SIZE); +#else return INLINE_SYSCALL(ppoll, 5, fds, nfds, timeout, sigmask, __SYSCALL_SIGSET_T_SIZE); +#endif } CANCELLABLE_SYSCALL(int, ppoll, (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, const sigset_t *sigmask), (fds, nfds, timeout, sigmask)) - #endif diff --git a/libc/sysdeps/linux/common/prlimit.c b/libc/sysdeps/linux/common/prlimit.c index f44dc1664..81c0f4619 100644 --- a/libc/sysdeps/linux/common/prlimit.c +++ b/libc/sysdeps/linux/common/prlimit.c @@ -17,14 +17,60 @@ #include <sys/resource.h> #include <sysdep.h> -#include <bits/kernel-features.h> +#include <stddef.h> // needed for NULL to be defined -#if defined __ASSUME_PRLIMIT64 +#if defined(__NR_prlimit64) && __WORDSIZE == 32 && !defined(__USE_FILE_OFFSET64) int prlimit (__pid_t pid, enum __rlimit_resource resource, - const struct rlimit *new_rlimit, struct rlimit *old_rlimit) + const struct rlimit *new_rlimit, struct rlimit *old_rlimit) { - return INLINE_SYSCALL (prlimit64, 4, pid, resource, new_rlimit, - old_rlimit); + struct rlimit64 new_rlimit64; + struct rlimit64 *new_rlimit64_ptr = NULL; + struct rlimit64 old_rlimit64; + struct rlimit64 *old_rlimit64_ptr = (old_rlimit != NULL ? &old_rlimit64 : NULL); + int res; + + if (new_rlimit != NULL) { + if (new_rlimit->rlim_cur == RLIM_INFINITY) + new_rlimit64.rlim_cur = RLIM64_INFINITY; + else + new_rlimit64.rlim_cur = new_rlimit->rlim_cur; + if (new_rlimit->rlim_max == RLIM_INFINITY) + new_rlimit64.rlim_max = RLIM64_INFINITY; + else + new_rlimit64.rlim_max = new_rlimit->rlim_max; + new_rlimit64_ptr = &new_rlimit64; + } + + res = INLINE_SYSCALL (prlimit64, 4, pid, resource, new_rlimit64_ptr, + old_rlimit64_ptr); + + if (res == 0 && old_rlimit != NULL) { + /* If the syscall succeeds but the values do not fit into a + rlimit structure set EOVERFLOW errno and retrun -1. + With current Linux implementation of the prlimit64 syscall, + overflow can't happen. An extra condition has been added to get + the same behavior as in glibc for future potential overflows. */ + old_rlimit->rlim_cur = old_rlimit64.rlim_cur; + if (old_rlimit64.rlim_cur != old_rlimit->rlim_cur) { + if (new_rlimit == NULL && + old_rlimit64.rlim_cur != RLIM64_INFINITY) { + __set_errno(EOVERFLOW); + return -1; + } + old_rlimit->rlim_cur = RLIM_INFINITY; + } + old_rlimit->rlim_max = old_rlimit64.rlim_max; + if (old_rlimit64.rlim_max != old_rlimit->rlim_max) { + if (new_rlimit == NULL && + old_rlimit64.rlim_max != RLIM64_INFINITY) { + __set_errno(EOVERFLOW); + return -1; + } + old_rlimit->rlim_max = RLIM_INFINITY; + } + } + + return res; } #endif diff --git a/libc/sysdeps/linux/common/prlimit64.c b/libc/sysdeps/linux/common/prlimit64.c new file mode 100644 index 000000000..6f57b939e --- /dev/null +++ b/libc/sysdeps/linux/common/prlimit64.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2023 uClibc-ng + * An prlimit64() - get/set resource limits Linux specific syscall. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <sys/resource.h> +#include <sysdep.h> + +#if defined(__NR_prlimit64) + +int +prlimit64 (__pid_t pid, enum __rlimit_resource resource, + const struct rlimit64 *new_rlimit, struct rlimit64 *old_rlimit) +{ + return INLINE_SYSCALL (prlimit64, 4, pid, resource, new_rlimit, + old_rlimit); +} + +# if __WORDSIZE == 64 || defined (__USE_FILE_OFFSET64) +strong_alias_untyped(prlimit64, prlimit) +# endif + +#endif
\ No newline at end of file diff --git a/libc/sysdeps/linux/common/pselect.c b/libc/sysdeps/linux/common/pselect.c index bf2c08375..f9d16d6c8 100644 --- a/libc/sysdeps/linux/common/pselect.c +++ b/libc/sysdeps/linux/common/pselect.c @@ -26,11 +26,15 @@ #include <signal.h> #include <cancel.h> +#if defined(__UCLIBC_USE_TIME64__) +#include "internal/time64_helpers.h" +#endif + static int __NC(pselect)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask) { -#ifdef __NR_pselect6 +#if defined(__NR_pselect6) || defined(__NR_pselect6_time64) /* The Linux kernel can in some situations update the timeout value. * We do not want that so use a local variable. */ @@ -56,8 +60,11 @@ static int __NC(pselect)(int nfds, fd_set *readfds, fd_set *writefds, sigmask = (void *)&data; } - +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_pselect6_time64) + return INLINE_SYSCALL(pselect6_time64, 6, nfds, readfds, writefds, exceptfds, TO_TS64_P(timeout), sigmask); +#else return INLINE_SYSCALL(pselect6, 6, nfds, readfds, writefds, exceptfds, timeout, sigmask); +#endif #else struct timeval tval; int retval; @@ -88,6 +95,7 @@ static int __NC(pselect)(int nfds, fd_set *readfds, fd_set *writefds, return retval; #endif } + CANCELLABLE_SYSCALL(int, pselect, (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask), (nfds, readfds, writefds, exceptfds, timeout, sigmask)) diff --git a/libc/sysdeps/linux/common/sched_rr_get_interval.c b/libc/sysdeps/linux/common/sched_rr_get_interval.c index 7a7de2bc5..c9be134cb 100644 --- a/libc/sysdeps/linux/common/sched_rr_get_interval.c +++ b/libc/sysdeps/linux/common/sched_rr_get_interval.c @@ -10,7 +10,12 @@ #include <sys/types.h> #include <sys/syscall.h> +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_sched_rr_get_interval_time64) +#define __NR___syscall_sched_rr_get_interval __NR_sched_rr_get_interval_time64 +#else #define __NR___syscall_sched_rr_get_interval __NR_sched_rr_get_interval +#endif + static __inline__ _syscall2(int, __syscall_sched_rr_get_interval, __kernel_pid_t, pid, struct timespec *, tp) diff --git a/libc/sysdeps/linux/common/select.c b/libc/sysdeps/linux/common/select.c index 3132a109c..84016dd0b 100644 --- a/libc/sysdeps/linux/common/select.c +++ b/libc/sysdeps/linux/common/select.c @@ -15,17 +15,19 @@ # define __NR_select __NR__newselect #endif -#if !defined __NR_select && defined __NR_pselect6 +#if defined(__NR_pselect6) || defined(__NR_pselect6_time64) # include <stdint.h> # define USEC_PER_SEC 1000000L #endif +#if defined(__UCLIBC_USE_TIME64__) +#include "internal/time64_helpers.h" +#endif + int __NC(select)(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { -#ifdef __NR_select - return INLINE_SYSCALL(select, 5, n, readfds, writefds, exceptfds, timeout); -#elif defined __NR_pselect6 +#if defined(__NR_pselect6) || defined(__NR_pselect6_time64) struct timespec _ts, *ts = 0; if (timeout) { uint32_t usec; @@ -47,8 +49,14 @@ int __NC(select)(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, ts = &_ts; } +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_pselect6_time64) + return INLINE_SYSCALL(pselect6_time64, 6, n, readfds, writefds, exceptfds, TO_TS64_P(ts), 0); +#else return INLINE_SYSCALL(pselect6, 6, n, readfds, writefds, exceptfds, ts, 0); #endif +#elif defined(__NR_select) + return INLINE_SYSCALL(select, 5, n, readfds, writefds, exceptfds, ts); +#endif } /* we should guard it, but we need it in other files, so let it fail * if we miss any of the syscalls */ diff --git a/libc/sysdeps/linux/common/setitimer.c b/libc/sysdeps/linux/common/setitimer.c index 2febabbc8..eab541329 100644 --- a/libc/sysdeps/linux/common/setitimer.c +++ b/libc/sysdeps/linux/common/setitimer.c @@ -10,6 +10,38 @@ #include <sys/time.h> +#if defined(__UCLIBC_USE_TIME64__) + +struct itimerval32_struct { + __S32_TYPE __interval_sec; + __S32_TYPE __interval_usec; + __S32_TYPE __value_sec; + __S32_TYPE __value_usec; +}; + +int setitimer(__itimer_which_t which, const struct itimerval *restrict new, struct itimerval *restrict old) +{ + struct itimerval32_struct __itv32 = { + .__interval_sec = new->it_interval.tv_sec, + .__interval_usec = new->it_interval.tv_usec, + .__value_sec = new->it_value.tv_sec, + .__value_usec = new->it_value.tv_usec + }; + struct itimerval32_struct __itv32_old; + + int __ret = INLINE_SYSCALL(setitimer, 3, which, &__itv32, &__itv32_old); + if (__ret == 0 && old) { + old->it_interval.tv_sec = __itv32_old.__interval_sec; + old->it_interval.tv_usec = __itv32_old.__interval_usec; + old->it_value.tv_sec = __itv32_old.__value_sec; + old->it_value.tv_usec = __itv32_old.__value_usec; + } + + return __ret; +} +#else _syscall3(int, setitimer, __itimer_which_t, which, const struct itimerval *, new, struct itimerval *, old) + +#endif libc_hidden_def(setitimer) diff --git a/libc/sysdeps/linux/common/setrlimit.c b/libc/sysdeps/linux/common/setrlimit.c index 8f4973b72..9c6707235 100644 --- a/libc/sysdeps/linux/common/setrlimit.c +++ b/libc/sysdeps/linux/common/setrlimit.c @@ -9,36 +9,65 @@ #include <sys/syscall.h> #include <sys/resource.h> #include <bits/wordsize.h> +#include <stddef.h> // needed for NULL to be defined /* Only wrap setrlimit if the new usetrlimit is not present and setrlimit sucks */ #if defined(__NR_usetrlimit) - /* just call usetrlimit() */ # define __NR___syscall_usetrlimit __NR_usetrlimit static __always_inline _syscall2(int, __syscall_usetrlimit, enum __rlimit_resource, resource, const struct rlimit *, rlim) -int setrlimit(__rlimit_resource_t resource, struct rlimit *rlimits) +int setrlimit(__rlimit_resource_t resource, const struct rlimit *rlimits) { return __syscall_usetrlimit(resource, rlimits); } +libc_hidden_def(setrlimit) + +#elif defined(__NR_prlimit64) + +/* Use prlimit64 if present, the prlimit64 syscall is free from a back + compatibility stuff for setrlimit */ + + # if __WORDSIZE == 32 && !defined(__USE_FILE_OFFSET64) +/* If struct rlimit has 64-bit fields (if __WORDSIZE == 64 or __USE_FILE_OFFSET64 + is defined), then use setrlimit as an alias to setrlimit64, see setrlimit64.c */ +int setrlimit(__rlimit_resource_t resource, const struct rlimit *rlimits) +{ + struct rlimit64 rlimits64; + + if (rlimits->rlim_cur == RLIM_INFINITY) + rlimits64.rlim_cur = RLIM64_INFINITY; + else + rlimits64.rlim_cur = rlimits->rlim_cur; + if (rlimits->rlim_max == RLIM_INFINITY) + rlimits64.rlim_max = RLIM64_INFINITY; + else + rlimits64.rlim_max = rlimits->rlim_max; + + return INLINE_SYSCALL (prlimit64, 4, 0, resource, &rlimits64, NULL); +} +libc_hidden_def(setrlimit) +# endif + +#else -#elif !defined(__UCLIBC_HANDLE_OLDER_RLIMIT__) +# if !defined(__UCLIBC_HANDLE_OLDER_RLIMIT__) /* We don't need to wrap setrlimit() */ _syscall2(int, setrlimit, __rlimit_resource_t, resource, const struct rlimit *, rlim) -#else +# else -# define __need_NULL -# include <stddef.h> -# include <errno.h> -# include <sys/param.h> +# define __need_NULL +# include <stddef.h> +# include <errno.h> +# include <sys/param.h> /* we have to handle old style setrlimit() */ -# define __NR___syscall_setrlimit __NR_setrlimit +# define __NR___syscall_setrlimit __NR_setrlimit static __always_inline _syscall2(int, __syscall_setrlimit, int, resource, const struct rlimit *, rlim) @@ -59,9 +88,7 @@ int setrlimit(__rlimit_resource_t resource, const struct rlimit *rlimits) RLIM_INFINITY >> 1); return __syscall_setrlimit(resource, &rlimits_small); } -#endif -libc_hidden_def(setrlimit) +# endif -#if __WORDSIZE == 64 -strong_alias_untyped(setrlimit, setrlimit64) +libc_hidden_def(setrlimit) #endif diff --git a/libc/sysdeps/linux/common/setrlimit64.c b/libc/sysdeps/linux/common/setrlimit64.c index fee14f4ad..3446c58fe 100644 --- a/libc/sysdeps/linux/common/setrlimit64.c +++ b/libc/sysdeps/linux/common/setrlimit64.c @@ -17,15 +17,31 @@ #include <_lfs_64.h> #include <bits/wordsize.h> +#include <sys/resource.h> +#include <sys/syscall.h> +#include <stddef.h> // needed for NULL to be defined -/* the regular setrlimit will work just fine for 64bit users */ -#if __WORDSIZE == 32 -# include <sys/resource.h> +#if defined(__NR_prlimit64) + +int setrlimit64 (__rlimit_resource_t resource, const struct rlimit64 *rlimits) +{ + return INLINE_SYSCALL (prlimit64, 4, 0, resource, rlimits, NULL); +} + +# if !defined(__NR_usetrlimit) && (__WORDSIZE == 64 || defined (__USE_FILE_OFFSET64)) +/* If setrlimit is not implemented through the __NR_usetrlimit and size of + rlimit_t == rlimit64_t then use setrlimit as an alias to setrlimit64 */ +strong_alias_untyped(setrlimit64, setrlimit) +libc_hidden_def(setrlimit) +# endif + +#else /* Set the soft and hard limits for RESOURCE to *RLIMITS. Only the super-user can increase hard limits. - Return 0 if successful, -1 if not (and sets errno). */ + Return 0 if successful, -1 if not (and sets errno). + The regular setrlimit will work just fine for 64bit users */ int setrlimit64 (__rlimit_resource_t resource, const struct rlimit64 *rlimits) { struct rlimit rlimits32; diff --git a/libc/sysdeps/linux/common/settimeofday.c b/libc/sysdeps/linux/common/settimeofday.c index 14a261794..75d18ffc2 100644 --- a/libc/sysdeps/linux/common/settimeofday.c +++ b/libc/sysdeps/linux/common/settimeofday.c @@ -10,9 +10,21 @@ #ifdef __USE_BSD # include <sys/time.h> -# ifdef __NR_settimeofday -_syscall2(int, settimeofday, const struct timeval *, tv, - const struct timezone *, tz) +# include <time.h> + +int settimeofday(const struct timeval *tv, const struct timezone *tz) +{ + if (!tv) + return 0; + + struct timespec __ts = { + .tv_sec = tv->tv_sec, + .tv_nsec = tv->tv_usec * 1000 + }; + + return clock_settime(CLOCK_REALTIME, &__ts); +} + # elif defined __USE_SVID && defined __NR_stime # define __need_NULL # include <stddef.h> @@ -36,7 +48,6 @@ int settimeofday(const struct timeval *tv, const struct timezone *tz) return stime(&when); } # endif -# if defined __NR_settimeofday || (defined __USE_SVID && defined __NR_stime) +# if defined __NR_settimeofday || defined(__UCLIBC_USE_TIME64__) || (defined __USE_SVID && defined __NR_stime) libc_hidden_def(settimeofday) # endif -#endif diff --git a/libc/sysdeps/linux/common/stat.c b/libc/sysdeps/linux/common/stat.c index 99ce8d2dd..42f39aea6 100644 --- a/libc/sysdeps/linux/common/stat.c +++ b/libc/sysdeps/linux/common/stat.c @@ -9,10 +9,11 @@ #include <sys/syscall.h> #include <unistd.h> #include <sys/stat.h> +#include <bits/uClibc_arch_features.h> #undef stat -#if defined __NR_fstatat64 && !defined __NR_stat +#if defined __NR_fstatat64 && !defined __NR_stat && !defined(__UCLIBC_USE_TIME64__) # include <fcntl.h> int stat(const char *file_name, struct stat *buf) diff --git a/libc/sysdeps/linux/common/stat64.c b/libc/sysdeps/linux/common/stat64.c index 47d938b11..0875ba39d 100644 --- a/libc/sysdeps/linux/common/stat64.c +++ b/libc/sysdeps/linux/common/stat64.c @@ -10,7 +10,7 @@ #include <sys/syscall.h> #include <sys/stat.h> -#if defined __NR_fstatat64 && !defined __NR_stat64 +#if defined __NR_fstatat64 && !defined __NR_stat64 && !defined(__UCLIBC_USE_TIME64__) #include <fcntl.h> #include <unistd.h> @@ -30,7 +30,7 @@ int stat64(const char *file_name, struct stat64 *buf) int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, file_name, AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &tmp); if (rc == 0) - __cp_stat_statx ((struct stat64 *)buf, &tmp); + __cp_stat64_statx ((struct stat64 *)buf, &tmp); return rc; } diff --git a/libc/sysdeps/linux/common/statx_cp.c b/libc/sysdeps/linux/common/statx_cp.c index 9f024eec8..c50d28ecb 100644 --- a/libc/sysdeps/linux/common/statx_cp.c +++ b/libc/sysdeps/linux/common/statx_cp.c @@ -24,7 +24,7 @@ #include <statx_cp.h> -#if !defined(__NR_fstat64) || !defined(__NR_fstatat64) +#if (!defined(__NR_fstat64) || !defined(__NR_fstatat64)) || defined(__UCLIBC_USE_TIME64__) void __cp_stat64_statx (struct stat64 *to, struct statx *from) { diff --git a/libc/sysdeps/linux/common/stubs.c b/libc/sysdeps/linux/common/stubs.c index c17e509b9..634dcde0d 100644 --- a/libc/sysdeps/linux/common/stubs.c +++ b/libc/sysdeps/linux/common/stubs.c @@ -34,10 +34,6 @@ __attribute_used__ static int ret_enosys_stub(void) link_warning(stub, #stub ": this function is not implemented") \ strong_alias(ret_enosys_stub, stub) -#ifndef __ARCH_USE_MMU__ -# undef __NR_fork -#endif - #ifdef __arm__ # define __NR_fadvise64_64 __NR_arm_fadvise64_64 # define __NR_fadvise64 __NR_arm_fadvise64_64 @@ -120,7 +116,7 @@ make_stub(fgetxattr) make_stub(flistxattr) #endif -#if !defined __NR_fork && !defined __NR_clone +#if !defined __ARCH_USE_MMU__ || (!defined __NR_fork && !defined __NR_clone) make_stub(fork) #endif diff --git a/libc/sysdeps/linux/common/time.c b/libc/sysdeps/linux/common/time.c index 22403f174..d084ffaad 100644 --- a/libc/sysdeps/linux/common/time.c +++ b/libc/sysdeps/linux/common/time.c @@ -9,7 +9,7 @@ #include <sys/syscall.h> #include <time.h> -#ifdef __NR_time +#if defined(__NR_time) && !defined(__UCLIBC_USE_TIME64__) _syscall_noerr1(time_t, time, time_t *, t) #else # include <sys/time.h> diff --git a/libc/sysdeps/linux/common/timerfd.c b/libc/sysdeps/linux/common/timerfd.c index f4854ac90..b4a9e1a93 100644 --- a/libc/sysdeps/linux/common/timerfd.c +++ b/libc/sysdeps/linux/common/timerfd.c @@ -9,6 +9,10 @@ #include <sys/syscall.h> #include <sys/timerfd.h> +#if defined(__UCLIBC_USE_TIME64__) +#include "internal/time64_helpers.h" +#endif + /* * timerfd_create() */ @@ -19,13 +23,24 @@ _syscall2(int, timerfd_create, int, clockid, int, flags) /* * timerfd_settime() */ -#ifdef __NR_timerfd_settime -_syscall4(int,timerfd_settime, int, ufd, int, flags, const struct itimerspec *, utmr, struct itimerspec *, otmr) +#if defined(__NR_timerfd_settime) || defined(__NR_timerfd_settime64) +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timerfd_settime64) +int timerfd_settime(int ufd, int flags, const struct itimerspec *utmr, struct itimerspec *otmr) +{ + return INLINE_SYSCALL(timerfd_settime64, 4, ufd, flags, TO_ITS64_P(utmr), otmr); +} +#else +_syscall4(int, timerfd_settime, int, ufd, int, flags, const struct itimerspec *, utmr, struct itimerspec *, otmr) +#endif #endif /* * timerfd_gettime() */ -#ifdef __NR_timerfd_gettime +#if defined(__NR_timerfd_gettime) || defined(__NR_timerfd_gettime64) +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timerfd_gettime64) +_syscall2_64(int, timerfd_gettime, int, ufd, struct itimerspec *, otmr) +#else _syscall2(int, timerfd_gettime, int, ufd, struct itimerspec *, otmr) #endif +#endif diff --git a/libc/sysdeps/linux/common/utimensat.c b/libc/sysdeps/linux/common/utimensat.c index 2cfb8247d..5816c7890 100644 --- a/libc/sysdeps/linux/common/utimensat.c +++ b/libc/sysdeps/linux/common/utimensat.c @@ -8,9 +8,32 @@ #include <sys/syscall.h> #include <sys/stat.h> +#include <stdint.h> -#ifdef __NR_utimensat +#if defined(__UCLIBC_USE_TIME64__) +#include "internal/time64_helpers.h" +#endif + +#if defined(__NR_utimensat) || defined(__NR_utimensat_time64) +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_utimensat_time64) +int utimensat(int fd, const char *path, const struct timespec times[2], int flags) +{ + struct __ts64_struct __times64[2] = { + { + .tv_sec = times ? times[0].tv_sec : 0, + .tv_nsec = times ? times[0].tv_nsec : 0 + }, + { + .tv_sec = times ? times[1].tv_sec : 0, + .tv_nsec = times ? times[1].tv_nsec : 0 + } + }; + + return INLINE_SYSCALL(utimensat_time64, 4, fd, path, times ? (uintptr_t) &__times64 : 0, flags); +} +#else _syscall4(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags) +#endif libc_hidden_def(utimensat) #else /* should add emulation with utimens() and /proc/self/fd/ ... */ diff --git a/libc/sysdeps/linux/common/utimes.c b/libc/sysdeps/linux/common/utimes.c index e6fc578f3..a28594dfd 100644 --- a/libc/sysdeps/linux/common/utimes.c +++ b/libc/sysdeps/linux/common/utimes.c @@ -9,7 +9,7 @@ #include <sys/syscall.h> #include <sys/time.h> -#if defined __NR_utimensat && !defined __NR_utimes +#if (defined (__NR_utimensat) || defined(__NR_utimensat_time64)) && !defined __NR_utimes # include <fcntl.h> # include <stddef.h> int utimes(const char *file, const struct timeval tvp[2]) @@ -50,6 +50,6 @@ int utimes(const char *file, const struct timeval tvp[2]) } #endif -#if defined __NR_utimensat || defined __NR_utimes || defined __NR_utime +#if defined __NR_utimensat || defined __NR_utimensat_time64 || defined __NR_utimes || defined __NR_utime libc_hidden_def(utimes) #endif diff --git a/libc/sysdeps/linux/common/wait4.c b/libc/sysdeps/linux/common/wait4.c index 19f02ae22..486ffaab8 100644 --- a/libc/sysdeps/linux/common/wait4.c +++ b/libc/sysdeps/linux/common/wait4.c @@ -8,15 +8,84 @@ #include <sys/syscall.h> #include <sys/wait.h> +#include <sys/resource.h> +#if defined(__NR_wait4) # define __NR___syscall_wait4 __NR_wait4 static __always_inline _syscall4(int, __syscall_wait4, __kernel_pid_t, pid, int *, status, int, opts, struct rusage *, rusage) pid_t __wait4_nocancel(pid_t pid, int *status, int opts, struct rusage *rusage) { +#if defined(__UCLIBC_USE_TIME64__) + char *arg_rusage = rusage ? (char *)&rusage->ru_maxrss - 4 * sizeof(__S32_TYPE) : 0; + int __ret = __syscall_wait4(pid, status, opts, (struct rusage *)arg_rusage); + if (__ret > 0 && rusage) { + __S32_TYPE __rusage[4]; + memcpy(__rusage, arg_rusage, 4 * sizeof(__S32_TYPE)); + struct timeval tv_utime = {.tv_sec = __rusage[0], .tv_usec = __rusage[1]}; + struct timeval tv_stime = {.tv_sec = __rusage[2], .tv_usec = __rusage[2]}; + rusage->ru_utime = tv_utime; + rusage->ru_stime = tv_stime; + } + return __ret; +#else return __syscall_wait4(pid, status, opts, rusage); +#endif } + +#else +pid_t __wait4_nocancel(pid_t pid, int *status, int opts, struct rusage *rusage) +{ + idtype_t type; + int __res; + siginfo_t info; + + info.si_pid = 0; + + if (pid < -1) { + type = P_PGID; + pid = -pid; + } else if (pid == -1) { + type = P_ALL; + } else if (pid == 0) { + type = P_PGID; + } else { + type = P_PID; + } + + __res = INLINE_SYSCALL(waitid, 5, type, pid, &info, opts|WEXITED, rusage); + + if ( __res < 0 ) + return __res; + + if (info.si_pid && status) { + int sw = 0; + switch (info.si_code) { + case CLD_CONTINUED: + sw = 0xffff; + break; + case CLD_DUMPED: + sw = (info.si_status & 0x7f) | 0x80; + break; + case CLD_EXITED: + sw = (info.si_status & 0xff) << 8; + break; + case CLD_KILLED: + sw = info.si_status & 0x7f; + break; + case CLD_STOPPED: + case CLD_TRAPPED: + sw = (info.si_status << 8) + 0x7f; + break; + } + *status = sw; + } + + return info.si_pid; +} +#endif + #ifdef __USE_BSD strong_alias(__wait4_nocancel,wait4) #endif |