summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/common
diff options
context:
space:
mode:
Diffstat (limited to 'libc/sysdeps/linux/common')
-rw-r--r--libc/sysdeps/linux/common/Makefile.in1
-rw-r--r--libc/sysdeps/linux/common/__rt_sigtimedwait.c16
-rw-r--r--libc/sysdeps/linux/common/__rt_sigwaitinfo.c2
-rw-r--r--libc/sysdeps/linux/common/adjtimex.c10
-rw-r--r--libc/sysdeps/linux/common/alarm.c2
-rw-r--r--libc/sysdeps/linux/common/bits/hwcap.h22
-rw-r--r--libc/sysdeps/linux/common/bits/jmp_buf_tag.h37
-rw-r--r--libc/sysdeps/linux/common/bits/kernel-features.h5
-rw-r--r--libc/sysdeps/linux/common/bits/mman-linux.h1
-rw-r--r--libc/sysdeps/linux/common/bits/resource.h17
-rw-r--r--libc/sysdeps/linux/common/bits/sched.h1
-rw-r--r--libc/sysdeps/linux/common/bits/sem.h20
-rw-r--r--libc/sysdeps/linux/common/bits/stab.def4
-rwxr-xr-x[-rw-r--r--]libc/sysdeps/linux/common/bits/syscalls-common.h54
-rw-r--r--libc/sysdeps/linux/common/bits/typesizes.h12
-rw-r--r--libc/sysdeps/linux/common/bits/uClibc_uwchar.h1
-rw-r--r--libc/sysdeps/linux/common/bits/wchar.h32
-rw-r--r--libc/sysdeps/linux/common/clock_adjtime.c6
-rw-r--r--libc/sysdeps/linux/common/clock_getres.c16
-rw-r--r--libc/sysdeps/linux/common/clock_gettime.c36
-rw-r--r--libc/sysdeps/linux/common/clock_settime.c10
-rw-r--r--libc/sysdeps/linux/common/fstat.c7
-rw-r--r--libc/sysdeps/linux/common/fstat64.c4
-rw-r--r--libc/sysdeps/linux/common/fstatat.c42
-rw-r--r--libc/sysdeps/linux/common/fstatat64.c23
-rw-r--r--libc/sysdeps/linux/common/futimens.c2
-rw-r--r--libc/sysdeps/linux/common/futimesat.c27
-rw-r--r--libc/sysdeps/linux/common/getrlimit.c56
-rw-r--r--libc/sysdeps/linux/common/getrlimit64.c26
-rwxr-xr-x[-rw-r--r--]libc/sysdeps/linux/common/gettimeofday.c21
-rw-r--r--libc/sysdeps/linux/common/lstat.c3
-rw-r--r--libc/sysdeps/linux/common/lstat64.c2
-rw-r--r--libc/sysdeps/linux/common/nanosleep.c16
-rw-r--r--libc/sysdeps/linux/common/not-cancel.h4
-rw-r--r--libc/sysdeps/linux/common/open.c2
-rw-r--r--libc/sysdeps/linux/common/open64.c4
-rw-r--r--libc/sysdeps/linux/common/openat64.c10
-rw-r--r--libc/sysdeps/linux/common/ppoll.c11
-rw-r--r--libc/sysdeps/linux/common/prlimit.c76
-rw-r--r--libc/sysdeps/linux/common/prlimit64.c36
-rw-r--r--libc/sysdeps/linux/common/pselect.c12
-rw-r--r--libc/sysdeps/linux/common/sched_rr_get_interval.c5
-rw-r--r--libc/sysdeps/linux/common/select.c16
-rw-r--r--libc/sysdeps/linux/common/setitimer.c32
-rw-r--r--libc/sysdeps/linux/common/setrlimit.c53
-rw-r--r--libc/sysdeps/linux/common/setrlimit64.c24
-rw-r--r--libc/sysdeps/linux/common/settimeofday.c21
-rw-r--r--libc/sysdeps/linux/common/stat.c5
-rw-r--r--libc/sysdeps/linux/common/stat64.c4
-rw-r--r--libc/sysdeps/linux/common/statx_cp.c2
-rw-r--r--libc/sysdeps/linux/common/stubs.c6
-rw-r--r--libc/sysdeps/linux/common/time.c2
-rw-r--r--libc/sysdeps/linux/common/timerfd.c21
-rw-r--r--libc/sysdeps/linux/common/utimensat.c25
-rw-r--r--libc/sysdeps/linux/common/utimes.c4
-rw-r--r--libc/sysdeps/linux/common/wait4.c69
56 files changed, 879 insertions, 99 deletions
diff --git a/libc/sysdeps/linux/common/Makefile.in b/libc/sysdeps/linux/common/Makefile.in
index 9562de52c..848bc1e4a 100644
--- a/libc/sysdeps/linux/common/Makefile.in
+++ b/libc/sysdeps/linux/common/Makefile.in
@@ -38,6 +38,7 @@ CSRC-$(UCLIBC_LINUX_SPECIFIC) += \
pipe2.c \
ppoll.c \
prctl.c \
+ prlimit.c \
readahead.c \
reboot.c \
remap_file_pages.c \
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/kernel-features.h b/libc/sysdeps/linux/common/bits/kernel-features.h
index f1ebe0204..2f4f407bd 100644
--- a/libc/sysdeps/linux/common/bits/kernel-features.h
+++ b/libc/sysdeps/linux/common/bits/kernel-features.h
@@ -490,6 +490,11 @@
# define __ASSUME_FALLOCATE 1
#endif
+/* prlimit64 is available in 2.6.36. */
+#if __LINUX_KERNEL_VERSION >= 0x020624
+# define __ASSUME_PRLIMIT64 1
+#endif
+
/* getcpu is a syscall for x86-64 since 3.1. */
#if defined __x86_64__ && __LINUX_KERNEL_VERSION >= 0x030100
# define __ASSUME_GETCPU_SYSCALL 1
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 df0ba56d9..89c3d4e41 100644
--- a/libc/sysdeps/linux/common/bits/resource.h
+++ b/libc/sysdeps/linux/common/bits/resource.h
@@ -99,7 +99,13 @@ enum __rlimit_resource
__RLIMIT_RTPRIO = 14,
#define RLIMIT_RTPRIO __RLIMIT_RTPRIO
- __RLIMIT_NLIMITS = 15,
+ /* Maximum CPU time in µs that a process scheduled under a real-time
+ scheduling policy may consume without making a blocking system
+ call before being forcibly descheduled. */
+ __RLIMIT_RTTIME = 15,
+#define RLIMIT_RTTIME __RLIMIT_RTTIME
+
+ __RLIMIT_NLIMITS = 16,
__RLIM_NLIMITS = __RLIMIT_NLIMITS
#define RLIMIT_NLIMITS __RLIMIT_NLIMITS
#define RLIM_NLIMITS __RLIM_NLIMITS
@@ -159,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/sched.h b/libc/sysdeps/linux/common/bits/sched.h
index 9d05314f5..18a9fb98d 100644
--- a/libc/sysdeps/linux/common/bits/sched.h
+++ b/libc/sysdeps/linux/common/bits/sched.h
@@ -31,6 +31,7 @@
#ifdef __USE_GNU
# define SCHED_BATCH 3
# define SCHED_IDLE 5
+# define SCHED_DEADLINE 6
# define SCHED_RESET_ON_FORK 0x40000000
#endif
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/open.c b/libc/sysdeps/linux/common/open.c
index ccdcf3848..ac09d40f0 100644
--- a/libc/sysdeps/linux/common/open.c
+++ b/libc/sysdeps/linux/common/open.c
@@ -31,7 +31,7 @@ int open(const char *file, int oflag, ...)
int oldtype, result;
#endif
- if (oflag & O_CREAT) {
+ if (oflag & (O_CREAT | (O_TMPFILE &~ O_DIRECTORY))) {
va_list arg;
va_start(arg, oflag);
mode = va_arg(arg, mode_t);
diff --git a/libc/sysdeps/linux/common/open64.c b/libc/sysdeps/linux/common/open64.c
index 6e65a988e..9d4c06b18 100644
--- a/libc/sysdeps/linux/common/open64.c
+++ b/libc/sysdeps/linux/common/open64.c
@@ -10,13 +10,13 @@
#include <stdarg.h>
#include <cancel.h>
-/* Open FILE with access OFLAG. If OFLAG includes O_CREAT,
+/* Open FILE with access OFLAG. If OFLAG includes O_CREAT or O_TMPFILE,
a third argument is the file protection. */
int open64(const char *file, int oflag, ...)
{
mode_t mode = 0;
- if (oflag & O_CREAT) {
+ if (oflag & (O_CREAT | (O_TMPFILE &~ O_DIRECTORY))) {
va_list arg;
va_start (arg, oflag);
mode = va_arg (arg, mode_t);
diff --git a/libc/sysdeps/linux/common/openat64.c b/libc/sysdeps/linux/common/openat64.c
index eda3e7db1..cd1b23fa5 100644
--- a/libc/sysdeps/linux/common/openat64.c
+++ b/libc/sysdeps/linux/common/openat64.c
@@ -9,10 +9,18 @@
#include <_lfs_64.h>
#include <sys/syscall.h>
#include <fcntl.h>
+#include <stdarg.h>
#ifdef __NR_openat
-static int __openat64(int fd, const char *file, int oflag, mode_t mode)
+static int __openat64(int fd, const char *file, int oflag, ...)
{
+ va_list ap;
+ mode_t mode;
+
+ va_start(ap, oflag);
+ mode = va_arg(ap, int);
+ va_end(ap);
+
return openat(fd, file, oflag | O_LARGEFILE, mode);
}
strong_alias_untyped(__openat64,openat64)
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
new file mode 100644
index 000000000..81c0f4619
--- /dev/null
+++ b/libc/sysdeps/linux/common/prlimit.c
@@ -0,0 +1,76 @@
+/* Get/set resource limits. Linux specific syscall.
+ Copyright (C) 2021-2022 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/>. */
+
+#include <sys/resource.h>
+#include <sysdep.h>
+#include <stddef.h> // needed for NULL to be defined
+
+#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)
+{
+ 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 a860c0c7f..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)
@@ -25,7 +26,7 @@ int stat(const char *file_name, struct stat *buf)
int stat(const char *file_name, struct stat *buf)
{
- return fstatat64(AT_FDCWD, file_name, buf, 0);
+ return fstatat64(AT_FDCWD, file_name, (struct stat64 *)buf, 0);
}
#elif __NR_statx && defined __UCLIBC_HAVE_STATX__
# include <fcntl.h>
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