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.in3
-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/ipc.h9
-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/msq.h10
-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.h29
-rw-r--r--libc/sysdeps/linux/common/bits/shm.h18
-rw-r--r--libc/sysdeps/linux/common/bits/stab.def4
-rw-r--r--libc/sysdeps/linux/common/bits/stat.h4
-rw-r--r--libc/sysdeps/linux/common/bits/statx.h93
-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_arch_features.h3
-rw-r--r--libc/sysdeps/linux/common/bits/uClibc_uwchar.h1
-rw-r--r--libc/sysdeps/linux/common/bits/utmp.h2
-rw-r--r--libc/sysdeps/linux/common/bits/utmpx.h2
-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/fexecve.c52
-rw-r--r--libc/sysdeps/linux/common/fstat.c21
-rw-r--r--libc/sysdeps/linux/common/fstat64.c19
-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.c22
-rw-r--r--libc/sysdeps/linux/common/lstat64.c19
-rw-r--r--libc/sysdeps/linux/common/name_to_handle_at.c36
-rw-r--r--libc/sysdeps/linux/common/nanosleep.c16
-rw-r--r--libc/sysdeps/linux/common/not-cancel.h6
-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/open_by_handle_at.c34
-rw-r--r--libc/sysdeps/linux/common/openat64.c10
-rw-r--r--libc/sysdeps/linux/common/poll.c7
-rw-r--r--libc/sysdeps/linux/common/ppoll.c11
-rw-r--r--libc/sysdeps/linux/common/preadv.c2
-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/pwritev.c2
-rw-r--r--libc/sysdeps/linux/common/renameat.c14
-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.c20
-rw-r--r--libc/sysdeps/linux/common/stat64.c18
-rw-r--r--libc/sysdeps/linux/common/statx_cp.c76
-rw-r--r--libc/sysdeps/linux/common/statx_cp.h22
-rw-r--r--libc/sysdeps/linux/common/stubs.c6
-rw-r--r--libc/sysdeps/linux/common/sys/ptrace.h2
-rw-r--r--libc/sysdeps/linux/common/sys/random.h1
-rw-r--r--libc/sysdeps/linux/common/sysctl.c2
-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/umount2.c2
-rw-r--r--libc/sysdeps/linux/common/utime.c4
-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
77 files changed, 1349 insertions, 131 deletions
diff --git a/libc/sysdeps/linux/common/Makefile.in b/libc/sysdeps/linux/common/Makefile.in
index f114a5bd1..848bc1e4a 100644
--- a/libc/sysdeps/linux/common/Makefile.in
+++ b/libc/sysdeps/linux/common/Makefile.in
@@ -32,10 +32,13 @@ CSRC-$(UCLIBC_LINUX_SPECIFIC) += \
iopl.c \
modify_ldt.c \
module.c \
+ name_to_handle_at.c \
+ open_by_handle_at.c \
personality.c \
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/ipc.h b/libc/sysdeps/linux/common/bits/ipc.h
index 3bd5f1b6f..cf7da2a29 100644
--- a/libc/sysdeps/linux/common/bits/ipc.h
+++ b/libc/sysdeps/linux/common/bits/ipc.h
@@ -20,6 +20,7 @@
#endif
#include <bits/types.h>
+#include <bits/wordsize.h>
/* Mode bits for `msgget', `semget', and `shmget'. */
#define IPC_CREAT 01000 /* Create key if key does not exist. */
@@ -46,10 +47,14 @@ struct ipc_perm
__gid_t gid; /* Owner's group ID. */
__uid_t cuid; /* Creator's user ID. */
__gid_t cgid; /* Creator's group ID. */
+#if __WORDSIZE == 64
+ unsigned int mode;
+#else
unsigned short int mode; /* Read/write permission. */
unsigned short int __pad1;
+#endif
unsigned short int __seq; /* Sequence number. */
unsigned short int __pad2;
- unsigned long int __unused1;
- unsigned long int __unused2;
+ unsigned long int __uclibc_unused1;
+ unsigned long int __uclibc_unused2;
};
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/msq.h b/libc/sysdeps/linux/common/bits/msq.h
index a1c3ea43d..b594cfff2 100644
--- a/libc/sysdeps/linux/common/bits/msq.h
+++ b/libc/sysdeps/linux/common/bits/msq.h
@@ -38,18 +38,18 @@ struct msqid_ds
{
struct ipc_perm msg_perm; /* structure describing operation permission */
__time_t msg_stime; /* time of last msgsnd command */
- unsigned long int __unused1;
+ unsigned long int __uclibc_unused1;
__time_t msg_rtime; /* time of last msgrcv command */
- unsigned long int __unused2;
+ unsigned long int __uclibc_unused2;
__time_t msg_ctime; /* time of last change */
- unsigned long int __unused3;
+ unsigned long int __uclibc_unused3;
unsigned long int __msg_cbytes; /* current number of bytes on queue */
msgqnum_t msg_qnum; /* number of messages currently on queue */
msglen_t msg_qbytes; /* max number of bytes allowed on queue */
__pid_t msg_lspid; /* pid of last msgsnd() */
__pid_t msg_lrpid; /* pid of last msgrcv() */
- unsigned long int __unused4;
- unsigned long int __unused5;
+ unsigned long int __uclibc_unused4;
+ unsigned long int __uclibc_unused5;
};
#ifdef __USE_MISC
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 501e0803b..24a130981 100644
--- a/libc/sysdeps/linux/common/bits/sem.h
+++ b/libc/sysdeps/linux/common/bits/sem.h
@@ -20,6 +20,7 @@
#endif
#include <sys/types.h>
+#include <bits/wordsize.h>
/* Flags for `semop'. */
#define SEM_UNDO 0x1000 /* undo the operation on exit */
@@ -38,13 +39,33 @@
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 */
- unsigned long int __unused1;
+#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() */
- unsigned long int __unused2;
+#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 */
- unsigned long int __unused3;
- unsigned long int __unused4;
+#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;
};
/* The user should define a union like the following to use it for arguments
diff --git a/libc/sysdeps/linux/common/bits/shm.h b/libc/sysdeps/linux/common/bits/shm.h
index 88bf7a8aa..8906e262b 100644
--- a/libc/sysdeps/linux/common/bits/shm.h
+++ b/libc/sysdeps/linux/common/bits/shm.h
@@ -50,16 +50,16 @@ struct shmid_ds
struct ipc_perm shm_perm; /* operation permission struct */
size_t shm_segsz; /* size of segment in bytes */
__time_t shm_atime; /* time of last shmat() */
- unsigned long int __unused1;
+ unsigned long int __uclibc_unused1;
__time_t shm_dtime; /* time of last shmdt() */
- unsigned long int __unused2;
+ unsigned long int __uclibc_unused2;
__time_t shm_ctime; /* time of last change by shmctl() */
- unsigned long int __unused3;
+ unsigned long int __uclibc_unused3;
__pid_t shm_cpid; /* pid of creator */
__pid_t shm_lpid; /* pid of last shmop */
shmatt_t shm_nattch; /* number of current attaches */
- unsigned long int __unused4;
- unsigned long int __unused5;
+ unsigned long int __uclibc_unused4;
+ unsigned long int __uclibc_unused5;
};
#ifdef __USE_MISC
@@ -81,10 +81,10 @@ struct shminfo
unsigned long int shmmni;
unsigned long int shmseg;
unsigned long int shmall;
- unsigned long int __unused1;
- unsigned long int __unused2;
- unsigned long int __unused3;
- unsigned long int __unused4;
+ unsigned long int __uclibc_unused1;
+ unsigned long int __uclibc_unused2;
+ unsigned long int __uclibc_unused3;
+ unsigned long int __uclibc_unused4;
};
struct shm_info
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/stat.h b/libc/sysdeps/linux/common/bits/stat.h
index 19e2f4e13..07c09f50a 100644
--- a/libc/sysdeps/linux/common/bits/stat.h
+++ b/libc/sysdeps/linux/common/bits/stat.h
@@ -83,8 +83,8 @@ struct stat
unsigned long int st_ctimensec; /* Nsecs of last status change. */
#endif
#ifndef __USE_FILE_OFFSET64
- unsigned long int __unused4;
- unsigned long int __unused5;
+ unsigned long int __uclibc_unused4;
+ unsigned long int __uclibc_unused5;
#else
__ino64_t st_ino; /* File serial number. */
#endif
diff --git a/libc/sysdeps/linux/common/bits/statx.h b/libc/sysdeps/linux/common/bits/statx.h
new file mode 100644
index 000000000..eb9b8535c
--- /dev/null
+++ b/libc/sysdeps/linux/common/bits/statx.h
@@ -0,0 +1,93 @@
+/* Generic statx-related definitions and declarations.
+ Copyright (C) 2018-2019 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/>. */
+
+/* This interface is based on <linux/stat.h> in Linux. */
+
+#ifndef _SYS_STAT_H
+# error Never include <bits/statx.h> directly, include <sys/stat.h> instead.
+#endif
+
+struct statx_timestamp
+{
+ __int64_t tv_sec;
+ __uint32_t tv_nsec;
+ __int32_t __statx_timestamp_pad1[1];
+};
+
+/* Warning: The kernel may add additional fields to this struct in the
+ future. Only use this struct for calling the statx function, not
+ for storing data. (Expansion will be controlled by the mask
+ argument of the statx function.) */
+struct statx
+{
+ __uint32_t stx_mask;
+ __uint32_t stx_blksize;
+ __uint64_t stx_attributes;
+ __uint32_t stx_nlink;
+ __uint32_t stx_uid;
+ __uint32_t stx_gid;
+ __uint16_t stx_mode;
+ __uint16_t __statx_pad1[1];
+ __uint64_t stx_ino;
+ __uint64_t stx_size;
+ __uint64_t stx_blocks;
+ __uint64_t stx_attributes_mask;
+ struct statx_timestamp stx_atime;
+ struct statx_timestamp stx_btime;
+ struct statx_timestamp stx_ctime;
+ struct statx_timestamp stx_mtime;
+ __uint32_t stx_rdev_major;
+ __uint32_t stx_rdev_minor;
+ __uint32_t stx_dev_major;
+ __uint32_t stx_dev_minor;
+ __uint64_t __statx_pad2[14];
+};
+
+#ifndef STATX_TYPE
+# define STATX_TYPE 0x0001U
+# define STATX_MODE 0x0002U
+# define STATX_NLINK 0x0004U
+# define STATX_UID 0x0008U
+# define STATX_GID 0x0010U
+# define STATX_ATIME 0x0020U
+# define STATX_MTIME 0x0040U
+# define STATX_CTIME 0x0080U
+# define STATX_INO 0x0100U
+# define STATX_SIZE 0x0200U
+# define STATX_BLOCKS 0x0400U
+# define STATX_BASIC_STATS 0x07ffU
+# define STATX_ALL 0x0fffU
+# define STATX_BTIME 0x0800U
+# define STATX__RESERVED 0x80000000U
+
+# define STATX_ATTR_COMPRESSED 0x0004
+# define STATX_ATTR_IMMUTABLE 0x0010
+# define STATX_ATTR_APPEND 0x0020
+# define STATX_ATTR_NODUMP 0x0040
+# define STATX_ATTR_ENCRYPTED 0x0800
+# define STATX_ATTR_AUTOMOUNT 0x1000
+#endif /* !STATX_TYPE */
+
+__BEGIN_DECLS
+
+/* Fill *BUF with information about PATH in DIRFD. */
+int statx (int __dirfd, const char *__restrict __path, int __flags,
+ unsigned int __mask, struct statx *__restrict __buf)
+ __THROW __nonnull ((2, 5));
+
+__END_DECLS
+
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_arch_features.h b/libc/sysdeps/linux/common/bits/uClibc_arch_features.h
index 37c7ceb60..c79ca7dfa 100644
--- a/libc/sysdeps/linux/common/bits/uClibc_arch_features.h
+++ b/libc/sysdeps/linux/common/bits/uClibc_arch_features.h
@@ -14,6 +14,9 @@
/* can your target use syscall6() for mmap ? */
#undef __UCLIBC_MMAP_HAS_6_ARGS__
+/* does your target use statx */
+#undef __UCLIBC_HAVE_STATX__
+
/* does your target align 64bit values in register pairs ? (32bit arches only) */
#undef __UCLIBC_SYSCALL_ALIGN_64BIT__
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/utmp.h b/libc/sysdeps/linux/common/bits/utmp.h
index 6ece31e34..9671d9382 100644
--- a/libc/sysdeps/linux/common/bits/utmp.h
+++ b/libc/sysdeps/linux/common/bits/utmp.h
@@ -82,7 +82,7 @@ struct utmp
#endif
int32_t ut_addr_v6[4]; /* Internet address of remote host. */
- char __unused[20]; /* Reserved for future use. */
+ char __uclibc_unused[20]; /* Reserved for future use. */
};
/* Backwards compatibility hacks. */
diff --git a/libc/sysdeps/linux/common/bits/utmpx.h b/libc/sysdeps/linux/common/bits/utmpx.h
index 815fc90b8..3315ef5e6 100644
--- a/libc/sysdeps/linux/common/bits/utmpx.h
+++ b/libc/sysdeps/linux/common/bits/utmpx.h
@@ -78,7 +78,7 @@ struct utmpx
struct timeval ut_tv; /* Time entry was made. */
#endif
__int32_t ut_addr_v6[4]; /* Internet address of remote host. */
- char __unused[20]; /* Reserved for future use. */
+ char __uclibc_unused[20]; /* Reserved for future use. */
};
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/fexecve.c b/libc/sysdeps/linux/common/fexecve.c
new file mode 100644
index 000000000..99a35c5b8
--- /dev/null
+++ b/libc/sysdeps/linux/common/fexecve.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 1994-2019 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 <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+int
+fexecve (int fd, char *const argv[], char *const envp[])
+{
+ if (fd < 0 || argv == NULL || envp == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+ /* We use the /proc filesystem to get the information. If it is not
+ mounted we fail. */
+ char buf[sizeof "/proc/self/fd/" + sizeof (int) * 3];
+ snprintf (buf, sizeof (buf), "/proc/self/fd/%d", fd);
+
+ /* We do not need the return value. */
+ execve (buf, argv, envp);
+
+ int save = errno;
+
+ /* We come here only if the 'execve' call fails. Determine whether
+ /proc is mounted. If not we return ENOSYS. */
+ struct stat st;
+ if (stat ("/proc/self/fd", &st) != 0 && errno == ENOENT)
+ save = ENOSYS;
+
+ __set_errno (save);
+
+ return -1;
+}
+libc_hidden_def(fexecve)
diff --git a/libc/sysdeps/linux/common/fstat.c b/libc/sysdeps/linux/common/fstat.c
index 030360dfc..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,6 +30,22 @@ int fstat(int fd, struct stat *buf)
}
libc_hidden_def(fstat)
+#elif defined __NR_statx && defined __UCLIBC_HAVE_STATX__
+# include <fcntl.h>
+# include <statx_cp.h>
+
+int fstat(int fd, struct stat *buf)
+{
+ struct statx tmp;
+ int rc = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
+ STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat_statx ((struct stat *)buf, &tmp);
+
+ return rc;
+}
+libc_hidden_def(fstat)
+
#elif defined __NR_fstat
int fstat(int fd, struct stat *buf)
{
@@ -57,7 +74,7 @@ int fstat(int fd, struct stat *buf)
libc_hidden_def(fstat)
#endif
-# if ! defined __NR_fstat64
+# if ! defined __NR_fstat64 && ! defined __UCLIBC_HAVE_STATX__
strong_alias_untyped(fstat,fstat64)
libc_hidden_def(fstat64)
#endif
diff --git a/libc/sysdeps/linux/common/fstat64.c b/libc/sysdeps/linux/common/fstat64.c
index 62995b2dc..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"
@@ -28,9 +28,26 @@ int fstat64(int fd, struct stat64 *buf)
__xstat64_conv(&kbuf, buf);
}
return result;
+
#else
return __syscall_fstat64(fd, buf);
#endif
}
libc_hidden_def(fstat64)
+
+#elif __NR_statx && defined __UCLIBC_HAVE_STATX__
+# include <fcntl.h>
+# include <statx_cp.h>
+
+int fstat64(int fd, struct stat64 *buf)
+{
+ struct statx tmp;
+ int rc = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
+ STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat64_statx ((struct stat64 *)buf, &tmp);
+
+ return rc;
+}
+libc_hidden_def(fstat64)
#endif
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 9d2024972..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)
@@ -28,6 +29,23 @@ int lstat(const char *file_name, struct stat *buf)
}
libc_hidden_def(lstat)
+#elif defined __NR_statx && defined __UCLIBC_HAVE_STATX__
+# include <fcntl.h>
+# include <statx_cp.h>
+
+int lstat(const char *file_name, struct stat *buf)
+{
+ struct statx tmp;
+ int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, file_name,
+ AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW,
+ STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat_statx ((struct stat *)buf, &tmp);
+
+ return rc;
+}
+libc_hidden_def(lstat)
+
/* For systems which have both, prefer the old one */
#else
# include "xstatconv.h"
@@ -57,7 +75,7 @@ int lstat(const char *file_name, struct stat *buf)
}
libc_hidden_def(lstat)
-# if ! defined __NR_fstatat64 && ! defined __NR_lstat64
+# if ! defined __NR_fstatat64 && ! defined __NR_lstat64 && ! defined __UCLIBC_HAS_STATX__
strong_alias_untyped(lstat,lstat64)
libc_hidden_def(lstat64)
# endif
diff --git a/libc/sysdeps/linux/common/lstat64.c b/libc/sysdeps/linux/common/lstat64.c
index 2f66e7ca2..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)
@@ -29,6 +29,23 @@ int lstat64(const char *file_name, struct stat64 *buf)
}
libc_hidden_def(lstat64)
+#elif defined __NR_statx && defined __UCLIBC_HAVE_STATX__
+# include <fcntl.h>
+# include <statx_cp.h>
+
+int lstat64(const char *file_name, struct stat64 *buf)
+{
+ struct statx tmp;
+ int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, file_name,
+ AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW,
+ STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat64_statx ((struct stat64 *)buf, &tmp);
+
+ return rc;
+}
+libc_hidden_def(lstat64)
+
/* For systems which have both, prefer the old one */
#elif defined __NR_lstat64
# include "xstatconv.h"
diff --git a/libc/sysdeps/linux/common/name_to_handle_at.c b/libc/sysdeps/linux/common/name_to_handle_at.c
new file mode 100644
index 000000000..20c67cbca
--- /dev/null
+++ b/libc/sysdeps/linux/common/name_to_handle_at.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2005-2020 Rich Felker, et al.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Imported from musl C library
+ */
+
+#include <sys/syscall.h>
+
+#ifdef __NR_open_by_handle_at
+#include <fcntl.h>
+int name_to_handle_at(int dirfd, const char *pathname,
+ struct file_handle *handle, int *mount_id, int flags)
+{
+ return INLINE_SYSCALL(name_to_handle_at, 5, dirfd, pathname, handle,
+ mount_id, flags);
+}
+#endif
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..426edcc46 100644
--- a/libc/sysdeps/linux/common/not-cancel.h
+++ b/libc/sysdeps/linux/common/not-cancel.h
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <sysdep.h>
+#include <time.h>
#ifdef NOT_IN_libc
@@ -113,9 +114,10 @@ extern __typeof(pause) __pause_nocancel;
#ifdef __NR_nanosleep
# define nanosleep_not_cancel(requested_time, remaining) \
INLINE_SYSCALL (nanosleep, 2, requested_time, remaining)
-/*#else
+#else
+extern int __nanosleep_nocancel (const struct timespec *requested_time, struct timespec *remaining);
# 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/open_by_handle_at.c b/libc/sysdeps/linux/common/open_by_handle_at.c
new file mode 100644
index 000000000..5e65648a6
--- /dev/null
+++ b/libc/sysdeps/linux/common/open_by_handle_at.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2005-2020 Rich Felker, et al.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Imported from musl C library
+ */
+
+#include <sys/syscall.h>
+
+#ifdef __NR_open_by_handle_at
+#include <fcntl.h>
+int open_by_handle_at(int mount_fd, struct file_handle *handle, int flags)
+{
+ return INLINE_SYSCALL(open_by_handle_at, 3, mount_fd, handle, flags);
+}
+#endif
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/poll.c b/libc/sysdeps/linux/common/poll.c
index d1f1f1723..3d46d5bee 100644
--- a/libc/sysdeps/linux/common/poll.c
+++ b/libc/sysdeps/linux/common/poll.c
@@ -53,6 +53,7 @@ int __NC(poll)(struct pollfd *fds, nfds_t nfds, int timeout)
fd_set *rset, *wset, *xset;
struct pollfd *f;
int ready;
+ int error_num;
int maxfd = 0;
int bytes;
@@ -142,6 +143,7 @@ int __NC(poll)(struct pollfd *fds, nfds_t nfds, int timeout)
/* Reset the return value. */
ready = 0;
+ error_num = 0;
for (f = fds; f < &fds[nfds]; ++f)
if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI))
@@ -178,8 +180,13 @@ int __NC(poll)(struct pollfd *fds, nfds_t nfds, int timeout)
++ready;
}
else if (errno == EBADF)
+ {
f->revents |= POLLNVAL;
+ error_num++;
+ }
}
+ if (ready == 0)
+ return error_num;
/* Try again. */
continue;
}
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/preadv.c b/libc/sysdeps/linux/common/preadv.c
index fd9dde4b9..6a07d5df8 100644
--- a/libc/sysdeps/linux/common/preadv.c
+++ b/libc/sysdeps/linux/common/preadv.c
@@ -21,7 +21,7 @@
#ifdef __NR_preadv
ssize_t
-preadv (int fd, const struct iovec *vector, int count, off_t offset)
+preadv (int fd, const struct iovec *vector, int count, __off64_t offset)
{
unsigned long pos_l, pos_h;
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/pwritev.c b/libc/sysdeps/linux/common/pwritev.c
index bef5bcf69..f07c40e6d 100644
--- a/libc/sysdeps/linux/common/pwritev.c
+++ b/libc/sysdeps/linux/common/pwritev.c
@@ -21,7 +21,7 @@
#ifdef __NR_pwritev
ssize_t
-pwritev (int fd, const struct iovec *vector, int count, off_t offset)
+pwritev (int fd, const struct iovec *vector, int count, __off64_t offset)
{
unsigned long pos_l, pos_h;
diff --git a/libc/sysdeps/linux/common/renameat.c b/libc/sysdeps/linux/common/renameat.c
index b0b91fa3e..0156981de 100644
--- a/libc/sysdeps/linux/common/renameat.c
+++ b/libc/sysdeps/linux/common/renameat.c
@@ -6,12 +6,18 @@
* Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
*/
-#include <sys/syscall.h>
#include <stdio.h>
+#include <fcntl.h>
+#include <sysdep.h>
+#include <errno.h>
+int
+renameat (int oldfd, const char *old, int newfd, const char *new)
+{
#ifdef __NR_renameat
-_syscall4(int, renameat, int, oldfd, const char *, old, int, newfd, const char *, new)
-libc_hidden_def(renameat)
+ return INLINE_SYSCALL (renameat, 4, oldfd, old, newfd, new);
#else
-/* should add emulation with rename() and /proc/self/fd/ ... */
+ return INLINE_SYSCALL (renameat2, 5, oldfd, old, newfd, new, 0);
#endif
+}
+libc_hidden_def (renameat)
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 6489d229b..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,9 +26,22 @@ 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>
+# include <statx_cp.h>
+int stat(const char *file_name, struct stat *buf)
+{
+ struct statx tmp;
+ int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, file_name, AT_NO_AUTOMOUNT,
+ STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat_statx ((struct stat *)buf, &tmp);
+
+ return rc;
+}
#else
# include "xstatconv.h"
@@ -58,7 +72,7 @@ int stat(const char *file_name, struct stat *buf)
#endif /* __NR_fstat64 */
libc_hidden_def(stat)
-#if ! defined __NR_stat64 && ! defined __NR_fstatat64
+#if ! defined __NR_stat64 && ! defined __NR_fstatat64 && ! defined __UCLIBC_HAVE_STATX__
strong_alias_untyped(stat,stat64)
libc_hidden_def(stat64)
#endif
diff --git a/libc/sysdeps/linux/common/stat64.c b/libc/sysdeps/linux/common/stat64.c
index ef365c7e7..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>
@@ -20,6 +20,22 @@ int stat64(const char *file_name, struct stat64 *buf)
}
libc_hidden_def(stat64)
+#elif __NR_statx && defined __UCLIBC_HAVE_STATX__
+# include <fcntl.h>
+# include <statx_cp.h>
+
+int stat64(const char *file_name, struct stat64 *buf)
+{
+ struct statx tmp;
+ int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, file_name, AT_NO_AUTOMOUNT,
+ STATX_BASIC_STATS, &tmp);
+ if (rc == 0)
+ __cp_stat64_statx ((struct stat64 *)buf, &tmp);
+
+ return rc;
+}
+libc_hidden_def(stat64)
+
/* For systems which have both, prefer the old one */
# elif defined __NR_stat64
# define __NR___syscall_stat64 __NR_stat64
diff --git a/libc/sysdeps/linux/common/statx_cp.c b/libc/sysdeps/linux/common/statx_cp.c
new file mode 100644
index 000000000..c50d28ecb
--- /dev/null
+++ b/libc/sysdeps/linux/common/statx_cp.c
@@ -0,0 +1,76 @@
+/* Struct statx to stat/stat64 conversion for Linux.
+ Copyright (C) 2018 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <bits/uClibc_arch_features.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#if defined __UCLIBC_HAVE_STATX__
+
+#include <statx_cp.h>
+
+#if (!defined(__NR_fstat64) || !defined(__NR_fstatat64)) || defined(__UCLIBC_USE_TIME64__)
+void
+__cp_stat64_statx (struct stat64 *to, struct statx *from)
+{
+ memset (to, 0, sizeof (struct stat64));
+ to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8)
+ | ((from->stx_dev_minor & ~0xff) << 12));
+ to->st_rdev = ((from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8)
+ | ((from->stx_rdev_minor & ~0xff) << 12));
+ to->st_ino = from->stx_ino;
+ to->st_mode = from->stx_mode;
+ to->st_nlink = from->stx_nlink;
+ to->st_uid = from->stx_uid;
+ to->st_gid = from->stx_gid;
+ to->st_atime = from->stx_atime.tv_sec;
+ to->st_atim.tv_nsec = from->stx_atime.tv_nsec;
+ to->st_mtime = from->stx_mtime.tv_sec;
+ to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec;
+ to->st_ctime = from->stx_ctime.tv_sec;
+ to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec;
+ to->st_size = from->stx_size;
+ to->st_blocks = from->stx_blocks;
+ to->st_blksize = from->stx_blksize;
+}
+
+void
+__cp_stat_statx (struct stat *to, struct statx *from)
+{
+ memset (to, 0, sizeof (struct stat));
+ to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8)
+ | ((from->stx_dev_minor & ~0xff) << 12));
+ to->st_rdev = ((from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8)
+ | ((from->stx_rdev_minor & ~0xff) << 12));
+ to->st_ino = from->stx_ino;
+ to->st_mode = from->stx_mode;
+ to->st_nlink = from->stx_nlink;
+ to->st_uid = from->stx_uid;
+ to->st_gid = from->stx_gid;
+ to->st_atime = from->stx_atime.tv_sec;
+ to->st_atim.tv_nsec = from->stx_atime.tv_nsec;
+ to->st_mtime = from->stx_mtime.tv_sec;
+ to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec;
+ to->st_ctime = from->stx_ctime.tv_sec;
+ to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec;
+ to->st_size = from->stx_size;
+ to->st_blocks = from->stx_blocks;
+ to->st_blksize = from->stx_blksize;
+}
+#endif
+#endif
diff --git a/libc/sysdeps/linux/common/statx_cp.h b/libc/sysdeps/linux/common/statx_cp.h
new file mode 100644
index 000000000..ff8fc9931
--- /dev/null
+++ b/libc/sysdeps/linux/common/statx_cp.h
@@ -0,0 +1,22 @@
+/* Struct statx to stat/stat64 conversion for Linux.
+ Copyright (C) 2018 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
+ <http://www.gnu.org/licenses/>. */
+
+extern void __cp_stat64_statx (struct stat64 *to, struct statx *from)
+ attribute_hidden;
+
+extern void __cp_stat_statx (struct stat *to, struct statx *from)
+ attribute_hidden;
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/sys/ptrace.h b/libc/sysdeps/linux/common/sys/ptrace.h
index 6b3c7b574..ebafe4e27 100644
--- a/libc/sysdeps/linux/common/sys/ptrace.h
+++ b/libc/sysdeps/linux/common/sys/ptrace.h
@@ -171,7 +171,7 @@ enum __ptrace_eventcodes
PTRACE_EVENT_EXEC = 4,
PTRACE_EVENT_VFORK_DONE = 5,
PTRACE_EVENT_EXIT = 6,
- PTRAVE_EVENT_SECCOMP = 7
+ PTRACE_EVENT_SECCOMP = 7
};
/* Perform process tracing functions. REQUEST is one of the values
diff --git a/libc/sysdeps/linux/common/sys/random.h b/libc/sysdeps/linux/common/sys/random.h
index 42f802576..3d12744ad 100644
--- a/libc/sysdeps/linux/common/sys/random.h
+++ b/libc/sysdeps/linux/common/sys/random.h
@@ -5,6 +5,7 @@
#ifndef _SYS_RANDOM_H
#define _SYS_RANDOM_H 1
#include <features.h>
+#include <stddef.h>
__BEGIN_DECLS
diff --git a/libc/sysdeps/linux/common/sysctl.c b/libc/sysdeps/linux/common/sysctl.c
index 75f9236d0..d3e28f919 100644
--- a/libc/sysdeps/linux/common/sysctl.c
+++ b/libc/sysdeps/linux/common/sysctl.c
@@ -17,7 +17,7 @@ struct __sysctl_args {
size_t *oldlenp;
void *newval;
size_t newlen;
- unsigned long __unused[4];
+ unsigned long __uclibc_unused[4];
};
extern int sysctl (int *__name, int __nlen, void *__oldval,
size_t *__oldlenp, void *__newval, size_t __newlen) __THROW;
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/umount2.c b/libc/sysdeps/linux/common/umount2.c
index b39d8ef73..507171f24 100644
--- a/libc/sysdeps/linux/common/umount2.c
+++ b/libc/sysdeps/linux/common/umount2.c
@@ -14,7 +14,7 @@ _syscall2(int, umount2, const char *, special_file, int, flags)
libc_hidden_def(umount2)
#endif
-#if defined __UCLIBC_LINUX_SPECIFIC__ && defined __NR_oldumount
+#if defined __UCLIBC_LINUX_SPECIFIC__ && defined __NR_oldumount && !defined __NR_umount2
_syscall2(int, umount, const char *, special_file, int, flags)
strong_alias(umount,umount2)
#endif
diff --git a/libc/sysdeps/linux/common/utime.c b/libc/sysdeps/linux/common/utime.c
index e4ac0b269..c716388e8 100644
--- a/libc/sysdeps/linux/common/utime.c
+++ b/libc/sysdeps/linux/common/utime.c
@@ -9,7 +9,7 @@
#include <sys/syscall.h>
#include <utime.h>
-#if defined __NR_utimensat && !defined __NR_utime
+#if (defined(__NR_utimensat) || defined(__NR_utimensat_time64)) && !defined __NR_utime
# include <fcntl.h>
# include <stddef.h>
@@ -51,7 +51,7 @@ int utime(const char *file, const struct utimbuf *times)
}
#endif
-#if (defined __NR_utimensat && !defined __NR_utime) || \
+#if ((defined(__NR_utimensat) || defined(__NR_utimensat_time64)) && !defined __NR_utime) || \
defined __NR_utime || defined __NR_utimes
libc_hidden_def(utime)
#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