diff options
Diffstat (limited to 'libc/sysdeps/linux/common')
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 |