diff options
Diffstat (limited to 'libc')
42 files changed, 1489 insertions, 283 deletions
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 130a9a505..44685e6b8 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -1892,7 +1892,7 @@ int getnameinfo(const struct sockaddr *sa, socklen_t hostlen, char *serv, socklen_t servlen, - unsigned flags) + int flags) { int serrno = errno; bool ok = 0; diff --git a/libc/misc/sysvipc/ipc.h b/libc/misc/sysvipc/ipc.h index b342dc1cf..58a690ee3 100644 --- a/libc/misc/sysvipc/ipc.h +++ b/libc/misc/sysvipc/ipc.h @@ -1,12 +1,19 @@ #ifndef IPC_H #define IPC_H #include <syscall.h> +#include <bits/kernel-features.h> #include <bits/wordsize.h> #ifndef __ARCH_HAS_DEPRECATED_SYSCALLS__ # define __IPC_64 0x0 +#elif defined __mips__ || defined __m68k__ +# if __LINUX_KERNEL_VERSION < 0x050100 +# define __IPC_64 0x100 +# else +# define __IPC_64 0x0 +# endif #else -# if __WORDSIZE == 32 || defined __alpha__ || defined __mips__ +# if __WORDSIZE == 32 || defined __alpha__ # define __IPC_64 0x100 # else # define __IPC_64 0x0 diff --git a/libc/misc/sysvipc/msgq.c b/libc/misc/sysvipc/msgq.c index 185cd268b..2d8bcae99 100644 --- a/libc/misc/sysvipc/msgq.c +++ b/libc/misc/sysvipc/msgq.c @@ -1,5 +1,6 @@ #include <errno.h> #include <sys/msg.h> +#include <stddef.h> #include "ipc.h" #ifdef __UCLIBC_HAS_THREADS_NATIVE__ #include "sysdep-cancel.h" @@ -7,6 +8,12 @@ #define SINGLE_THREAD_P 1 #endif +#if defined(__UCLIBC_USE_TIME64__) +union msqun { + struct msqid_ds* buff; + void *__pad; +}; +#endif #ifdef L_msgctl @@ -18,9 +25,19 @@ static __inline__ _syscall3(int, __libc_msgctl, int, msqid, int, cmd, struct msq int msgctl(int msqid, int cmd, struct msqid_ds *buf) { #ifdef __NR_msgctl - return __libc_msgctl(msqid, cmd | __IPC_64, buf); + int __ret = __libc_msgctl(msqid, cmd | __IPC_64, buf); +#if (__WORDSIZE == 32) && defined(__UCLIBC_USE_TIME64__) && (defined(__mips) || defined(__riscv)) + union msqun arg = {.buff = buf}; + // When cmd is IPC_RMID, buf should be NULL. + if (arg.__pad != NULL) { + arg.buff->msg_stime = (__time_t)arg.buff->msg_stime_internal_1 | (__time_t)(arg.buff->msg_stime_internal_2) << 32; + arg.buff->msg_rtime = (__time_t)arg.buff->msg_rtime_internal_1 | (__time_t)(arg.buff->msg_rtime_internal_2) << 32; + arg.buff->msg_ctime = (__time_t)arg.buff->msg_ctime_internal_1 | (__time_t)(arg.buff->msg_ctime_internal_2) << 32; + } +#endif + return __ret; #else - return __syscall_ipc(IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf, 0); + return __syscall_ipc(IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf, 0); #endif } #endif diff --git a/libc/misc/sysvipc/sem.c b/libc/misc/sysvipc/sem.c index 07076eff7..66f86f53c 100644 --- a/libc/misc/sysvipc/sem.c +++ b/libc/misc/sysvipc/sem.c @@ -57,9 +57,14 @@ int semctl(int semid, int semnum, int cmd, ...) va_end (ap); #ifdef __NR_semctl int __ret = __semctl(semid, semnum, cmd | __IPC_64, arg.__pad); -#if defined(__UCLIBC_USE_TIME64__) - arg.buf->sem_otime = (__time_t)arg.buf->__sem_otime_internal_1 | (__time_t)(arg.buf->__sem_otime_internal_2) << 32; - arg.buf->sem_ctime = (__time_t)arg.buf->__sem_ctime_internal_1 | (__time_t)(arg.buf->__sem_ctime_internal_2) << 32; +#if (__WORDSIZE == 32) && defined(__UCLIBC_USE_TIME64__) + // Only when cmd is IPC_STAT and IPC_SET, semun points to struct semid_ds. + // At this point, arg.__pad should not be NULL, but a check is added just + // to be safe. + if ((cmd & (IPC_STAT | IPC_SET)) && (arg.__pad != NULL)) { + arg.buf->sem_otime = (__time_t)arg.buf->__sem_otime_internal_1 | (__time_t)(arg.buf->__sem_otime_internal_2) << 32; + arg.buf->sem_ctime = (__time_t)arg.buf->__sem_ctime_internal_1 | (__time_t)(arg.buf->__sem_ctime_internal_2) << 32; + } #endif return __ret; #else diff --git a/libc/misc/sysvipc/shm.c b/libc/misc/sysvipc/shm.c index cd46ff0dd..b3366b301 100644 --- a/libc/misc/sysvipc/shm.c +++ b/libc/misc/sysvipc/shm.c @@ -25,6 +25,13 @@ #include <syscall.h> #include "ipc.h" +#if defined(__UCLIBC_USE_TIME64__) +union shmun { + struct shmid_ds* buff; + void *__pad; +}; +#endif + #ifdef L_shmat /* Attach the shared memory segment associated with SHMID to the data segment of the calling process. SHMADDR and SHMFLG determine how @@ -59,7 +66,17 @@ static __always_inline _syscall3(int, __syscall_shmctl, int, shmid, int, cmd, st int shmctl(int shmid, int cmd, struct shmid_ds *buf) { #ifdef __NR_shmctl - return __syscall_shmctl(shmid, cmd | __IPC_64, buf); + int __ret = __syscall_shmctl(shmid, cmd | __IPC_64, buf); +#if (__WORDSIZE == 32) && defined(__mips) && defined(__UCLIBC_USE_TIME64__) + union shmun arg = {.buff = buf}; + // When cmd is IPC_RMID, buf should be NULL. + if (arg.__pad != NULL) { + arg.buff->shm_atime = (__time_t)arg.buff->shm_atime_internal_1 | (__time_t)(arg.buff->shm_atime_internal_2) << 32; + arg.buff->shm_dtime = (__time_t)arg.buff->shm_dtime_internal_1 | (__time_t)(arg.buff->shm_dtime_internal_2) << 32; + arg.buff->shm_ctime = (__time_t)arg.buff->shm_ctime_internal_1 | (__time_t)(arg.buff->shm_ctime_internal_2) << 32; + } +#endif + return __ret; #else return __syscall_ipc(IPCOP_shmctl, shmid, cmd | __IPC_64, 0, buf, 0); #endif diff --git a/libc/stdlib/malloc-standard/malloc.c b/libc/stdlib/malloc-standard/malloc.c index cecea87ec..e51bc6610 100644 --- a/libc/stdlib/malloc-standard/malloc.c +++ b/libc/stdlib/malloc-standard/malloc.c @@ -29,7 +29,7 @@ __UCLIBC_MUTEX_INIT(__malloc_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); struct malloc_state __malloc_state; /* never directly referenced */ /* forward declaration */ -static int __malloc_largebin_index(unsigned int sz); +static int __malloc_largebin_index(unsigned long sz); #ifdef __UCLIBC_MALLOC_DEBUGGING__ @@ -755,10 +755,10 @@ static void* __malloc_alloc(size_t nb, mstate av) Compute index for size. We expect this to be inlined when compiled with optimization, else not, which works out well. */ -static int __malloc_largebin_index(unsigned int sz) +static int __malloc_largebin_index(unsigned long sz) { - unsigned int x = sz >> SMALLBIN_WIDTH; - unsigned int m; /* bit position of highest set bit of m */ + unsigned long x = sz >> SMALLBIN_WIDTH; + unsigned long m; /* bit position of highest set bit of m */ if (x >= 0x10000) return NBINS-1; @@ -776,7 +776,7 @@ static int __malloc_largebin_index(unsigned int sz) S. Warren Jr's book "Hacker's Delight". */ - unsigned int n = ((x - 0x100) >> 16) & 8; + unsigned long n = ((x - 0x100) >> 16) & 8; x <<= n; m = ((x - 0x1000) >> 16) & 4; n += m; diff --git a/libc/sysdeps/linux/aarch64/bits/shm.h b/libc/sysdeps/linux/aarch64/bits/shm.h new file mode 100644 index 000000000..bfb603499 --- /dev/null +++ b/libc/sysdeps/linux/aarch64/bits/shm.h @@ -0,0 +1,87 @@ +/* + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB + * in this tarball. + */ + +#ifndef _SYS_SHM_H +# error "Never include <bits/shm.h> directly; use <sys/shm.h> instead." +#endif + +#include <bits/types.h> + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from <linux/stat.h> */ +#define SHM_W 0200 /* or S_IWUGO from <linux/stat.h> */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize () << 2) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +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() */ + __time_t shm_dtime; /* time of last shmdt() */ + __time_t shm_ctime; /* time of last change by shmctl() */ + __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 __uclibc_unused1; + unsigned long int __uclibc_unused2; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __uclibc_unused1; + unsigned long int __uclibc_unused2; + unsigned long int __uclibc_unused3; + unsigned long int __uclibc_unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/libc/sysdeps/linux/arc/bits/fenv.h b/libc/sysdeps/linux/arc/bits/fenv.h new file mode 100644 index 000000000..c5c76cb93 --- /dev/null +++ b/libc/sysdeps/linux/arc/bits/fenv.h @@ -0,0 +1,75 @@ +/* Floating point environment. ARC version. + Copyright (C) 2020-2025 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 _FENV_H +# error "Never use <bits/fenv.h> directly; include <fenv.h> instead." +#endif + +enum + { + FE_INVALID = +# define FE_INVALID (0x01) + FE_INVALID, + FE_DIVBYZERO = +# define FE_DIVBYZERO (0x02) + FE_DIVBYZERO, + FE_OVERFLOW = +# define FE_OVERFLOW (0x04) + FE_OVERFLOW, + FE_UNDERFLOW = +# define FE_UNDERFLOW (0x08) + FE_UNDERFLOW, + FE_INEXACT = +# define FE_INEXACT (0x10) + FE_INEXACT + }; + +# define FE_ALL_EXCEPT \ + (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) + +enum + { + FE_TOWARDZERO = +# define FE_TOWARDZERO (0x0) + FE_TOWARDZERO, + FE_TONEAREST = +# define FE_TONEAREST (0x1) /* default */ + FE_TONEAREST, + FE_UPWARD = +# define FE_UPWARD (0x2) + FE_UPWARD, + FE_DOWNWARD = +# define FE_DOWNWARD (0x3) + FE_DOWNWARD + }; + +typedef unsigned int fexcept_t; + +typedef struct +{ + unsigned int __fpcr; + unsigned int __fpsr; +} fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((const fenv_t *) -1) + +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +# define FE_DFL_MODE ((const femode_t *) -1L) diff --git a/libc/sysdeps/linux/arc/fpu_control.h b/libc/sysdeps/linux/arc/fpu_control.h new file mode 100644 index 000000000..e833de3aa --- /dev/null +++ b/libc/sysdeps/linux/arc/fpu_control.h @@ -0,0 +1,104 @@ +/* FPU control word bits. ARC version. + Copyright (C) 2020-2025 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 _FPU_CONTROL_H +#define _FPU_CONTROL_H + +/* ARC FPU control register bits. + + [ 0] -> IVE: Enable invalid operation exception. + if 0, soft exception: status register IV flag set. + if 1, hardware exception trap (not supported in Linux yet). + [ 1] -> DZE: Enable division by zero exception. + if 0, soft exception: status register IV flag set. + if 1, hardware exception: (not supported in Linux yet). + [9:8] -> RM: Rounding Mode: + 00 - Rounding toward zero. + 01 - Rounding to nearest (default). + 10 - Rounding (up) toward plus infinity. + 11 - Rounding (down)toward minus infinity. + + ARC FPU status register bits. + + [ 0] -> IV: flag invalid operation. + [ 1] -> DZ: flag division by zero. + [ 2] -> OV: flag Overflow operation. + [ 3] -> UV: flag Underflow operation. + [ 4] -> IX: flag Inexact operation. + [31] -> FWE: Flag Write Enable. + If 1, above flags writable explicitly (clearing), + else IoW and only writable indirectly via bits [12:7]. */ + +#include <features.h> + +#if !defined(__ARC_FPU_SP__) && !defined(__ARC_FPU_DP__) + +# define _FPU_RESERVED 0xffffffff +# define _FPU_DEFAULT 0x00000000 +typedef unsigned int fpu_control_t; +# define _FPU_GETCW(cw) (cw) = 0 +# define _FPU_SETCW(cw) (void) (cw) +# define _FPU_GETS(cw) (cw) = 0 +# define _FPU_SETS(cw) (void) (cw) +extern fpu_control_t __fpu_control; + +#else + +#define _FPU_RESERVED 0 + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. + So only RM set to b'01. */ +# define _FPU_DEFAULT 0x00000100 + +/* Actually default needs to have FWE bit as 1 but that is already + ingrained into _FPU_SETS macro below. */ +#define _FPU_FPSR_DEFAULT 0x00000000 + +#define __FPU_RND_SHIFT 8 +#define __FPU_RND_MASK 0x3 + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Macros for accessing the hardware control word. */ +# define _FPU_GETCW(cw) __asm__ volatile ("lr %0, [0x300]" : "=r" (cw)) +# define _FPU_SETCW(cw) __asm__ volatile ("sr %0, [0x300]" : : "r" (cw)) + +/* Macros for accessing the hardware status word. + Writing to FPU_STATUS requires a "control" bit FWE to be able to set the + exception flags directly (as opposed to side-effects of FP instructions). + That is done in the macro here to keeps callers agnostic of this detail. + And given FWE is write-only and RAZ, no need to "clear" it in _FPU_GETS + macro. */ +# define _FPU_GETS(cw) \ + __asm__ volatile ("lr %0, [0x301] \r\n" \ + : "=r" (cw)) + +# define _FPU_SETS(cw) \ + do { \ + unsigned int __fwe = 0x80000000 | (cw); \ + __asm__ volatile ("sr %0, [0x301] \r\n" \ + : : "r" (__fwe)); \ + } while (0) + +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; + +#endif + +#endif /* fpu_control.h */ diff --git a/libc/sysdeps/linux/arm/bits/shm.h b/libc/sysdeps/linux/arm/bits/shm.h index 86245faff..aa1a72e54 100644 --- a/libc/sysdeps/linux/arm/bits/shm.h +++ b/libc/sysdeps/linux/arm/bits/shm.h @@ -49,12 +49,18 @@ struct shmid_ds { struct ipc_perm shm_perm; /* operation permission struct */ size_t shm_segsz; /* size of segment in bytes */ +#if defined(__UCLIBC_USE_TIME64__) + __time_t shm_atime; + __time_t shm_dtime; + __time_t shm_ctime; +#else __time_t shm_atime; /* time of last shmat() */ unsigned long int __uclibc_unused1; __time_t shm_dtime; /* time of last shmdt() */ unsigned long int __uclibc_unused2; __time_t shm_ctime; /* time of last change by shmctl() */ unsigned long int __uclibc_unused3; +#endif __pid_t shm_cpid; /* pid of creator */ __pid_t shm_lpid; /* pid of last shmop */ shmatt_t shm_nattch; /* number of current attaches */ diff --git a/libc/sysdeps/linux/common/Makefile.in b/libc/sysdeps/linux/common/Makefile.in index e0b280c33..4a4317432 100644 --- a/libc/sysdeps/linux/common/Makefile.in +++ b/libc/sysdeps/linux/common/Makefile.in @@ -27,6 +27,7 @@ CSRC-$(UCLIBC_LINUX_SPECIFIC) += \ eventfd_write.c \ fanotify.c \ getrandom.c \ + getentropy.c \ inotify.c \ ioperm.c \ iopl.c \ diff --git a/libc/sysdeps/linux/common/bits/msq.h b/libc/sysdeps/linux/common/bits/msq.h index b594cfff2..0cb734263 100644 --- a/libc/sysdeps/linux/common/bits/msq.h +++ b/libc/sysdeps/linux/common/bits/msq.h @@ -37,17 +37,31 @@ typedef unsigned long int msglen_t; struct msqid_ds { struct ipc_perm msg_perm; /* structure describing operation permission */ +#if (__WORDSIZE == 32 && defined(__riscv) && defined(__UCLIBC_USE_TIME64__)) + unsigned long int msg_stime_internal_1; + unsigned long int msg_stime_internal_2; + unsigned long int msg_rtime_internal_1; + unsigned long int msg_rtime_internal_2; + unsigned long int msg_ctime_internal_1; + unsigned long int msg_ctime_internal_2; +#else __time_t msg_stime; /* time of last msgsnd command */ unsigned long int __uclibc_unused1; __time_t msg_rtime; /* time of last msgrcv command */ unsigned long int __uclibc_unused2; __time_t msg_ctime; /* time of last change */ unsigned long int __uclibc_unused3; +#endif 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() */ +#if (__WORDSIZE == 32 && defined(__riscv) && defined(__UCLIBC_USE_TIME64__)) + __time_t msg_stime; /* time of last msgsnd command */ + __time_t msg_rtime; /* time of last msgrcv command */ + __time_t msg_ctime; /* time of last change */ +#endif unsigned long int __uclibc_unused4; unsigned long int __uclibc_unused5; }; diff --git a/libc/sysdeps/linux/common/bits/sem.h b/libc/sysdeps/linux/common/bits/sem.h index 24a130981..d855494ee 100644 --- a/libc/sysdeps/linux/common/bits/sem.h +++ b/libc/sysdeps/linux/common/bits/sem.h @@ -45,8 +45,8 @@ struct semid_ds #else __time_t sem_otime; /* last semop() time */ #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__)) +#if (__WORDSIZE == 32 && !defined(__ARC64_ARCH32__) && !defined(__arc__) && !defined(__arm__) && !defined(__or1k__) && !defined(__xtensa__) && !defined(__riscv)) || \ + ((defined(__ARC64_ARCH32__) || defined(__arc__) || defined(__arm__) || defined(__or1k__) || defined(__xtensa__) || defined(__riscv)) && !defined(__UCLIBC_USE_TIME64__)) unsigned long int __uclibc_unused1; #endif #if defined(__UCLIBC_USE_TIME64__) @@ -55,8 +55,8 @@ struct semid_ds #else __time_t sem_ctime; /* last time changed by semctl() */ #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__)) +#if (__WORDSIZE == 32 && !defined(__ARC64_ARCH32__) && !defined(__arc__) && !defined(__arm__) && !defined(__or1k__) && !defined(__xtensa__) && !defined(__riscv)) || \ + ((defined(__ARC64_ARCH32__) || defined(__arc__) || defined(__arm__) || defined(__or1k__) || defined(__xtensa__) || defined(__riscv)) && !defined(__UCLIBC_USE_TIME64__)) unsigned long int __uclibc_unused2; #endif unsigned long int sem_nsems; /* number of semaphores in set */ diff --git a/libc/sysdeps/linux/common/getentropy.c b/libc/sysdeps/linux/common/getentropy.c new file mode 100644 index 000000000..d255310b6 --- /dev/null +++ b/libc/sysdeps/linux/common/getentropy.c @@ -0,0 +1,46 @@ +/* + * getentropy() by wrapping getrandom(), for µClibc-ng + * + * © 2025 mirabilos Ⓕ CC0 or MirBSD or GNU LGPLv2 + * + * Note: may be a thread cancellation point, unlike the + * implementations in glibc and musl libc. Should this + * ever become a concern, it will need patching. + */ + +#define _DEFAULT_SOURCE +#include <errno.h> +#include <unistd.h> +#include <sys/random.h> +#include <sys/syscall.h> + +#ifdef __NR_getrandom +int +getentropy(void *__buf, size_t __len) +{ + ssize_t n; + + if (__len > 256U) { + errno = EIO; + return (-1); + } + + again: + if ((n = getrandom(__buf, __len, 0)) == -1) + switch (errno) { + case EAGAIN: /* should not happen but better safe than sorry */ + case EINTR: + goto again; + default: + errno = EIO; + /* FALLTHROUGH */ + case EFAULT: + case ENOSYS: + return (-1); + } + if ((size_t)n != __len) + /* also shouldn’t happen (safety net) */ + goto again; + return (0); +} +#endif diff --git a/libc/sysdeps/linux/common/getrandom.c b/libc/sysdeps/linux/common/getrandom.c index bb9841463..1db1663b9 100644 --- a/libc/sysdeps/linux/common/getrandom.c +++ b/libc/sysdeps/linux/common/getrandom.c @@ -8,6 +8,7 @@ #include <sys/syscall.h> #include <sys/random.h> + #ifdef __NR_getrandom -_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags) +_syscall3(ssize_t, getrandom, void *, buf, size_t, buflen, unsigned int, flags) #endif diff --git a/libc/sysdeps/linux/common/sys/random.h b/libc/sysdeps/linux/common/sys/random.h index 3d24e439b..c3d9cf575 100644 --- a/libc/sysdeps/linux/common/sys/random.h +++ b/libc/sysdeps/linux/common/sys/random.h @@ -4,11 +4,19 @@ #ifndef _SYS_RANDOM_H #define _SYS_RANDOM_H 1 + #include <features.h> #include <stddef.h> __BEGIN_DECLS +#include <bits/types.h> + +#ifndef __ssize_t_defined +typedef __ssize_t ssize_t; +# define __ssize_t_defined +#endif + #if defined __UCLIBC_LINUX_SPECIFIC__ # if 0 /*def __ASSUME_GETRANDOM_SYSCALL */ # include <linux/random.h> @@ -26,9 +34,15 @@ __BEGIN_DECLS # define GRND_RANDOM 0x0002 # define GRND_INSECURE 0x0004 # endif -/* FIXME: aren't there a couple of __restrict and const missing ? */ -extern int getrandom(void *__buf, size_t count, unsigned int flags) +extern ssize_t getrandom(void *__buf, size_t count, unsigned int flags) __nonnull ((1)) __wur; + +/* OpenBSD-compatible access to random bytes. + May be a cancellation point here, unlike in glibc/musl. */ +# ifndef __getentropy_defined +extern int getentropy(void *__buf, size_t __len) __nonnull ((1)) __wur; +# define __getentropy_defined +# endif #endif __END_DECLS diff --git a/libc/sysdeps/linux/common/utimes.c b/libc/sysdeps/linux/common/utimes.c index a28594dfd..c471a9b89 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_utimensat_time64)) && !defined __NR_utimes +#if (defined (__NR_utimensat) || defined(__NR_utimensat_time64)) && (!defined __NR_utimes || defined(__UCLIBC_USE_TIME64__)) # 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]) |