summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYRIGHT4
-rw-r--r--Makefile2
-rw-r--r--arch/i386/crt_arch.h1
-rw-r--r--arch/loongarch64/bits/hwcap.h14
-rw-r--r--arch/loongarch64/reloc.h1
-rw-r--r--arch/m68k/bits/poll.h2
-rw-r--r--arch/powerpc/bits/hwcap.h2
-rw-r--r--arch/powerpc/syscall_arch.h6
-rw-r--r--arch/powerpc64/bits/hwcap.h2
-rw-r--r--arch/powerpc64/syscall_arch.h4
-rw-r--r--arch/riscv32/syscall_arch.h3
-rw-r--r--arch/riscv64/syscall_arch.h3
-rw-r--r--arch/s390x/reloc.h2
-rw-r--r--arch/s390x/syscall_arch.h4
-rw-r--r--arch/x32/crt_arch.h1
-rw-r--r--arch/x86_64/crt_arch.h1
-rw-r--r--crt/arm/crti.s2
-rw-r--r--crt/crt1.c2
-rw-r--r--crt/mips/crtn.s4
-rw-r--r--crt/mips64/crtn.s4
-rw-r--r--crt/mipsn32/crtn.s4
-rw-r--r--include/elf.h1
-rw-r--r--include/sched.h17
-rw-r--r--include/shadow.h1
-rw-r--r--include/stdio.h7
-rw-r--r--include/sys/epoll.h12
-rw-r--r--include/sys/stat.h9
-rw-r--r--include/syslog.h2
-rw-r--r--ldso/dynlink.c14
-rw-r--r--src/complex/catan.c25
-rw-r--r--src/complex/catanf.c28
-rw-r--r--src/complex/catanl.c24
-rw-r--r--src/conf/sysconf.c9
-rw-r--r--src/dirent/posix_getdents.c2
-rw-r--r--src/errno/__strerror.h2
-rw-r--r--src/exit/atexit.c12
-rw-r--r--src/exit/exit.c14
-rw-r--r--src/internal/syscall.h11
-rw-r--r--src/ldso/loongarch64/tlsdesc.s37
-rw-r--r--src/legacy/getusershell.c6
-rw-r--r--src/linux/renameat2.c11
-rw-r--r--src/linux/statx.c4
-rw-r--r--src/locale/bind_textdomain_codeset.c6
-rw-r--r--src/locale/codepages.h11
-rw-r--r--src/locale/iconv.c8
-rw-r--r--src/math/powl.c8
-rw-r--r--src/misc/mntent.c12
-rw-r--r--src/mq/x32/mq_open.c22
-rw-r--r--src/mq/x32/mq_setattr.c14
-rw-r--r--src/multibyte/mbsnrtowcs.c6
-rw-r--r--src/network/inet_ntop.c7
-rw-r--r--src/network/res_msend.c2
-rw-r--r--src/signal/riscv32/restore.s2
-rw-r--r--src/signal/riscv64/restore.s2
-rw-r--r--src/signal/sigaltstack.c4
-rw-r--r--src/signal/siglongjmp.c5
-rw-r--r--src/signal/sigpause.c2
-rw-r--r--src/stdio/__stdio_write.c5
-rw-r--r--src/stdio/vfprintf.c18
-rw-r--r--src/stdlib/qsort.c2
-rw-r--r--src/string/strcasestr.c1
-rw-r--r--src/termios/cfgetospeed.c2
-rw-r--r--src/termios/cfsetospeed.c10
-rw-r--r--src/termios/cfsetspeed.c11
-rw-r--r--src/thread/aarch64/clone.s3
-rw-r--r--src/thread/arm/clone.s3
-rw-r--r--src/thread/loongarch64/clone.s1
-rw-r--r--src/thread/m68k/clone.s3
-rw-r--r--src/thread/microblaze/clone.s3
-rw-r--r--src/thread/mips/clone.s3
-rw-r--r--src/thread/mips64/clone.s3
-rw-r--r--src/thread/mipsn32/clone.s3
-rw-r--r--src/thread/or1k/clone.s5
-rw-r--r--src/thread/riscv32/clone.s1
-rw-r--r--src/thread/riscv64/clone.s1
-rw-r--r--src/thread/s390x/__tls_get_offset.s20
-rw-r--r--src/thread/sem_post.c2
-rw-r--r--src/time/__tz.c1
-rw-r--r--src/time/__utc.c3
-rw-r--r--src/time/timer_create.c29
-rw-r--r--src/unistd/isatty.c6
-rw-r--r--src/unistd/pause.c6
82 files changed, 391 insertions, 181 deletions
diff --git a/COPYRIGHT b/COPYRIGHT
index c1628e9a..2f15edc7 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -74,6 +74,7 @@ Kylie McClain
Leah Neukirchen
Luca Barbato
Luka Perkov
+Lynn Ochs
M Farkas-Dyck (Strake)
Mahesh Bodapati
Markus Wichmann
@@ -103,7 +104,6 @@ Stefan O'Rear
Szabolcs Nagy
Timo Teräs
Trutz Behn
-Valentin Ochs
Will Dietz
William Haddon
William Pitcock
@@ -143,7 +143,7 @@ domain. The code also comes with a fallback permissive license for use
in jurisdictions that may not recognize the public domain.
The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011
-Valentin Ochs and is licensed under an MIT-style license.
+Lynn Ochs and is licensed under an MIT-style license.
The x86_64 port was written by Nicholas J. Kain and is licensed under
the standard MIT terms.
diff --git a/Makefile b/Makefile
index e8cc4436..3ad88b35 100644
--- a/Makefile
+++ b/Makefile
@@ -109,7 +109,7 @@ obj/src/internal/version.o obj/src/internal/version.lo: obj/src/internal/version
obj/crt/rcrt1.o obj/ldso/dlstart.lo obj/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h
-obj/crt/crt1.o obj/crt/scrt1.o obj/crt/rcrt1.o obj/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
+obj/crt/crt1.o obj/crt/Scrt1.o obj/crt/rcrt1.o obj/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h
obj/crt/rcrt1.o: $(srcdir)/ldso/dlstart.c
diff --git a/arch/i386/crt_arch.h b/arch/i386/crt_arch.h
index 43c8477a..1a80fce3 100644
--- a/arch/i386/crt_arch.h
+++ b/arch/i386/crt_arch.h
@@ -3,6 +3,7 @@ __asm__(
".weak _DYNAMIC \n"
".hidden _DYNAMIC \n"
".global " START "\n"
+".type " START ",%function \n"
START ":\n"
" xor %ebp,%ebp \n"
" mov %esp,%eax \n"
diff --git a/arch/loongarch64/bits/hwcap.h b/arch/loongarch64/bits/hwcap.h
new file mode 100644
index 00000000..b8184f69
--- /dev/null
+++ b/arch/loongarch64/bits/hwcap.h
@@ -0,0 +1,14 @@
+#define HWCAP_LOONGARCH_CPUCFG (1 << 0)
+#define HWCAP_LOONGARCH_LAM (1 << 1)
+#define HWCAP_LOONGARCH_UAL (1 << 2)
+#define HWCAP_LOONGARCH_FPU (1 << 3)
+#define HWCAP_LOONGARCH_LSX (1 << 4)
+#define HWCAP_LOONGARCH_LASX (1 << 5)
+#define HWCAP_LOONGARCH_CRC32 (1 << 6)
+#define HWCAP_LOONGARCH_COMPLEX (1 << 7)
+#define HWCAP_LOONGARCH_CRYPTO (1 << 8)
+#define HWCAP_LOONGARCH_LVZ (1 << 9)
+#define HWCAP_LOONGARCH_LBT_X86 (1 << 10)
+#define HWCAP_LOONGARCH_LBT_ARM (1 << 11)
+#define HWCAP_LOONGARCH_LBT_MIPS (1 << 12)
+#define HWCAP_LOONGARCH_PTW (1 << 13)
diff --git a/arch/loongarch64/reloc.h b/arch/loongarch64/reloc.h
index 61eaca9e..a4db6a9c 100644
--- a/arch/loongarch64/reloc.h
+++ b/arch/loongarch64/reloc.h
@@ -17,6 +17,7 @@
#define REL_TPOFF R_LARCH_TLS_TPREL64
#define REL_RELATIVE R_LARCH_RELATIVE
#define REL_SYMBOLIC R_LARCH_64
+#define REL_TLSDESC R_LARCH_TLS_DESC64
#define CRTJMP(pc,sp) __asm__ __volatile__( \
"move $sp, %1 ; jr %0" : : "r"(pc), "r"(sp) : "memory" )
diff --git a/arch/m68k/bits/poll.h b/arch/m68k/bits/poll.h
new file mode 100644
index 00000000..00063f41
--- /dev/null
+++ b/arch/m68k/bits/poll.h
@@ -0,0 +1,2 @@
+#define POLLWRNORM POLLOUT
+#define POLLWRBAND 256
diff --git a/arch/powerpc/bits/hwcap.h b/arch/powerpc/bits/hwcap.h
index 803de9b5..12981623 100644
--- a/arch/powerpc/bits/hwcap.h
+++ b/arch/powerpc/bits/hwcap.h
@@ -41,3 +41,5 @@
#define PPC_FEATURE2_DARN 0x00200000
#define PPC_FEATURE2_SCV 0x00100000
#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000
+#define PPC_FEATURE2_ARCH_3_1 0x00040000
+#define PPC_FEATURE2_MMA 0x00020000
diff --git a/arch/powerpc/syscall_arch.h b/arch/powerpc/syscall_arch.h
index ede97c1c..54c885cb 100644
--- a/arch/powerpc/syscall_arch.h
+++ b/arch/powerpc/syscall_arch.h
@@ -92,3 +92,9 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
#define SO_RCVTIMEO_OLD 18
#define SO_SNDTIMEO_OLD 19
+
+#define VDSO_USEFUL
+#define VDSO_CGT32_SYM "__kernel_clock_gettime"
+#define VDSO_CGT32_VER "LINUX_2.6.15"
+#define VDSO_CGT_SYM "__kernel_clock_gettime64"
+#define VDSO_CGT_VER "LINUX_5.11"
diff --git a/arch/powerpc64/bits/hwcap.h b/arch/powerpc64/bits/hwcap.h
index 803de9b5..12981623 100644
--- a/arch/powerpc64/bits/hwcap.h
+++ b/arch/powerpc64/bits/hwcap.h
@@ -41,3 +41,5 @@
#define PPC_FEATURE2_DARN 0x00200000
#define PPC_FEATURE2_SCV 0x00100000
#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000
+#define PPC_FEATURE2_ARCH_3_1 0x00040000
+#define PPC_FEATURE2_MMA 0x00020000
diff --git a/arch/powerpc64/syscall_arch.h b/arch/powerpc64/syscall_arch.h
index 76b4e335..7d34fbe4 100644
--- a/arch/powerpc64/syscall_arch.h
+++ b/arch/powerpc64/syscall_arch.h
@@ -88,3 +88,7 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
#define SO_RCVTIMEO_OLD 18
#define SO_SNDTIMEO_OLD 19
+
+#define VDSO_USEFUL
+#define VDSO_CGT_SYM "__kernel_clock_gettime"
+#define VDSO_CGT_VER "LINUX_2.6.15"
diff --git a/arch/riscv32/syscall_arch.h b/arch/riscv32/syscall_arch.h
index c507f15f..70d2773f 100644
--- a/arch/riscv32/syscall_arch.h
+++ b/arch/riscv32/syscall_arch.h
@@ -73,8 +73,7 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
}
#define VDSO_USEFUL
-/* We don't have a clock_gettime function.
#define VDSO_CGT_SYM "__vdso_clock_gettime"
-#define VDSO_CGT_VER "LINUX_2.6" */
+#define VDSO_CGT_VER "LINUX_4.15"
#define IPC_64 0
diff --git a/arch/riscv64/syscall_arch.h b/arch/riscv64/syscall_arch.h
index 7fd042cd..81993fc8 100644
--- a/arch/riscv64/syscall_arch.h
+++ b/arch/riscv64/syscall_arch.h
@@ -71,8 +71,7 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
}
#define VDSO_USEFUL
-/* We don't have a clock_gettime function.
#define VDSO_CGT_SYM "__vdso_clock_gettime"
-#define VDSO_CGT_VER "LINUX_2.6" */
+#define VDSO_CGT_VER "LINUX_4.15"
#define IPC_64 0
diff --git a/arch/s390x/reloc.h b/arch/s390x/reloc.h
index 6e5c1fb8..38de9d9b 100644
--- a/arch/s390x/reloc.h
+++ b/arch/s390x/reloc.h
@@ -10,4 +10,4 @@
#define REL_TPOFF R_390_TLS_TPOFF
#define CRTJMP(pc,sp) __asm__ __volatile__( \
- "lgr %%r15,%1; br %0" : : "r"(pc), "r"(sp) : "memory" )
+ "lgr %%r15,%1; br %0" : : "a"(pc), "r"(sp) : "memory" )
diff --git a/arch/s390x/syscall_arch.h b/arch/s390x/syscall_arch.h
index 83cc9a27..d1cfd2e8 100644
--- a/arch/s390x/syscall_arch.h
+++ b/arch/s390x/syscall_arch.h
@@ -72,3 +72,7 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
register long r7 __asm__("r7") = f;
__asm_syscall("+r"(r2), "r"(r1), "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7));
}
+
+#define VDSO_USEFUL
+#define VDSO_CGT_SYM "__kernel_clock_gettime"
+#define VDSO_CGT_VER "LINUX_2.6.29"
diff --git a/arch/x32/crt_arch.h b/arch/x32/crt_arch.h
index 3eec61bd..b1c9c476 100644
--- a/arch/x32/crt_arch.h
+++ b/arch/x32/crt_arch.h
@@ -1,6 +1,7 @@
__asm__(
".text \n"
".global " START " \n"
+".type " START ",%function \n"
START ": \n"
" xor %rbp,%rbp \n"
" mov %rsp,%rdi \n"
diff --git a/arch/x86_64/crt_arch.h b/arch/x86_64/crt_arch.h
index 3eec61bd..b1c9c476 100644
--- a/arch/x86_64/crt_arch.h
+++ b/arch/x86_64/crt_arch.h
@@ -1,6 +1,7 @@
__asm__(
".text \n"
".global " START " \n"
+".type " START ",%function \n"
START ": \n"
" xor %rbp,%rbp \n"
" mov %rsp,%rdi \n"
diff --git a/crt/arm/crti.s b/crt/arm/crti.s
index 18dc1e41..cccda3ea 100644
--- a/crt/arm/crti.s
+++ b/crt/arm/crti.s
@@ -3,11 +3,13 @@
.section .init
.global _init
.type _init,%function
+.align 2
_init:
push {r0,lr}
.section .fini
.global _fini
.type _fini,%function
+.align 2
_fini:
push {r0,lr}
diff --git a/crt/crt1.c b/crt/crt1.c
index 8fe8ab5d..10601215 100644
--- a/crt/crt1.c
+++ b/crt/crt1.c
@@ -11,7 +11,7 @@ weak void _fini();
int __libc_start_main(int (*)(), int, char **,
void (*)(), void(*)(), void(*)());
-void _start_c(long *p)
+hidden void _start_c(long *p)
{
int argc = p[0];
char **argv = (void *)(p+1);
diff --git a/crt/mips/crtn.s b/crt/mips/crtn.s
index 506a04b7..92eb3d0e 100644
--- a/crt/mips/crtn.s
+++ b/crt/mips/crtn.s
@@ -3,11 +3,11 @@
.section .init
lw $gp,24($sp)
lw $ra,28($sp)
- j $ra
+ jr $ra
addu $sp,$sp,32
.section .fini
lw $gp,24($sp)
lw $ra,28($sp)
- j $ra
+ jr $ra
addu $sp,$sp,32
diff --git a/crt/mips64/crtn.s b/crt/mips64/crtn.s
index f3930b24..8f090ed3 100644
--- a/crt/mips64/crtn.s
+++ b/crt/mips64/crtn.s
@@ -3,11 +3,11 @@
.section .init
ld $gp,16($sp)
ld $ra,24($sp)
- j $ra
+ jr $ra
daddu $sp,$sp,32
.section .fini
ld $gp,16($sp)
ld $ra,24($sp)
- j $ra
+ jr $ra
daddu $sp,$sp,32
diff --git a/crt/mipsn32/crtn.s b/crt/mipsn32/crtn.s
index dccd7e89..0679eac3 100644
--- a/crt/mipsn32/crtn.s
+++ b/crt/mipsn32/crtn.s
@@ -2,11 +2,11 @@
.section .init
ld $gp, 16($sp)
ld $ra, 24($sp)
- j $ra
+ jr $ra
addu $sp, $sp, 32
.section .fini
ld $gp, 16($sp)
ld $ra, 24($sp)
- j $ra
+ jr $ra
addu $sp, $sp, 32
diff --git a/include/elf.h b/include/elf.h
index 3d5e13e4..8b622f63 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -3329,6 +3329,7 @@ enum
#define R_LARCH_TLS_TPREL32 10
#define R_LARCH_TLS_TPREL64 11
#define R_LARCH_IRELATIVE 12
+#define R_LARCH_TLS_DESC64 14
#define R_LARCH_MARK_LA 20
#define R_LARCH_MARK_PCREL 21
#define R_LARCH_SOP_PUSH_PCREL 22
diff --git a/include/sched.h b/include/sched.h
index 204c34f5..8c3b53f0 100644
--- a/include/sched.h
+++ b/include/sched.h
@@ -78,11 +78,10 @@ int clone (int (*)(void *), void *, int, void *, ...);
int unshare(int);
int setns(int, int);
-void *memcpy(void *__restrict, const void *__restrict, size_t);
-int memcmp(const void *, const void *, size_t);
-void *memset (void *, int, size_t);
-void *calloc(size_t, size_t);
-void free(void *);
+int (memcmp)(const void *, const void *, size_t);
+void *(memset)(void *, int, size_t);
+void *(calloc)(size_t, size_t);
+void (free)(void *);
typedef struct cpu_set_t { unsigned long __bits[128/sizeof(long)]; } cpu_set_t;
int __sched_cpucount(size_t, const cpu_set_t *);
@@ -116,13 +115,13 @@ __CPU_op_func_S(XOR, ^)
#define CPU_XOR_S(a,b,c,d) __CPU_XOR_S(a,b,c,d)
#define CPU_COUNT_S(size,set) __sched_cpucount(size,set)
-#define CPU_ZERO_S(size,set) memset(set,0,size)
-#define CPU_EQUAL_S(size,set1,set2) (!memcmp(set1,set2,size))
+#define CPU_ZERO_S(size,set) (memset)(set,0,size)
+#define CPU_EQUAL_S(size,set1,set2) (!(memcmp)(set1,set2,size))
#define CPU_ALLOC_SIZE(n) (sizeof(long) * ( (n)/(8*sizeof(long)) \
+ ((n)%(8*sizeof(long)) + 8*sizeof(long)-1)/(8*sizeof(long)) ) )
-#define CPU_ALLOC(n) ((cpu_set_t *)calloc(1,CPU_ALLOC_SIZE(n)))
-#define CPU_FREE(set) free(set)
+#define CPU_ALLOC(n) ((cpu_set_t *)(calloc)(1,CPU_ALLOC_SIZE(n)))
+#define CPU_FREE(set) (free)(set)
#define CPU_SETSIZE 1024
diff --git a/include/shadow.h b/include/shadow.h
index 2b1be413..a9d6940f 100644
--- a/include/shadow.h
+++ b/include/shadow.h
@@ -28,7 +28,6 @@ void setspent(void);
void endspent(void);
struct spwd *getspent(void);
struct spwd *fgetspent(FILE *);
-struct spwd *sgetspent(const char *);
int putspent(const struct spwd *, FILE *);
struct spwd *getspnam(const char *);
diff --git a/include/stdio.h b/include/stdio.h
index cb858618..4ea4c170 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -158,6 +158,13 @@ char *ctermid(char *);
#define L_ctermid 20
#endif
+#if defined(_GNU_SOURCE)
+#define RENAME_NOREPLACE (1 << 0)
+#define RENAME_EXCHANGE (1 << 1)
+#define RENAME_WHITEOUT (1 << 2)
+
+int renameat2(int, const char *, int, const char *, unsigned);
+#endif
#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
|| defined(_BSD_SOURCE)
diff --git a/include/sys/epoll.h b/include/sys/epoll.h
index ac81a841..5f975c4a 100644
--- a/include/sys/epoll.h
+++ b/include/sys/epoll.h
@@ -7,6 +7,7 @@ extern "C" {
#include <stdint.h>
#include <sys/types.h>
+#include <sys/ioctl.h>
#include <fcntl.h>
#define __NEED_sigset_t
@@ -54,6 +55,17 @@ __attribute__ ((__packed__))
#endif
;
+struct epoll_params {
+ uint32_t busy_poll_usecs;
+ uint16_t busy_poll_budget;
+ uint8_t prefer_busy_poll;
+
+ uint8_t __pad;
+};
+
+#define EPOLL_IOC_TYPE 0x8A
+#define EPIOCSPARAMS _IOW(EPOLL_IOC_TYPE, 0x01, struct epoll_params)
+#define EPIOCGPARAMS _IOR(EPOLL_IOC_TYPE, 0x02, struct epoll_params)
int epoll_create(int);
int epoll_create1(int);
diff --git a/include/sys/stat.h b/include/sys/stat.h
index 57d640d7..c924ce2f 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -120,6 +120,9 @@ int lchmod(const char *, mode_t);
#define STATX_BASIC_STATS 0x7ffU
#define STATX_BTIME 0x800U
#define STATX_ALL 0xfffU
+#define STATX_MNT_ID 0x1000U
+#define STATX_DIOALIGN 0x2000U
+#define STATX_MNT_ID_UNIQUE 0x4000U
#define STATX_ATTR_COMPRESSED 0x4
#define STATX_ATTR_IMMUTABLE 0x10
@@ -157,7 +160,11 @@ struct statx {
uint32_t stx_rdev_minor;
uint32_t stx_dev_major;
uint32_t stx_dev_minor;
- uint64_t __pad1[14];
+ uint64_t stx_mnt_id;
+ uint32_t stx_dio_mem_align;
+ uint32_t stx_dio_offset_align;
+ uint64_t stx_subvol;
+ uint64_t __pad1[11];
};
int statx(int, const char *__restrict, int, unsigned, struct statx *__restrict);
diff --git a/include/syslog.h b/include/syslog.h
index 5b4d2964..57599e07 100644
--- a/include/syslog.h
+++ b/include/syslog.h
@@ -18,7 +18,7 @@ extern "C" {
#define LOG_PRIMASK 7
#define LOG_PRI(p) ((p)&LOG_PRIMASK)
-#define LOG_MAKEPRI(f, p) (((f)<<3)|(p))
+#define LOG_MAKEPRI(f, p) ((f)|(p))
#define LOG_MASK(p) (1<<(p))
#define LOG_UPTO(p) ((1<<((p)+1))-1)
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 42687da2..715948f4 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -362,19 +362,14 @@ static struct symdef get_lfs64(const char *name)
"pwritev\0readdir\0scandir\0sendfile\0setrlimit\0"
"stat\0statfs\0statvfs\0tmpfile\0truncate\0versionsort\0"
"__fxstat\0__fxstatat\0__lxstat\0__xstat\0";
- size_t l;
- char buf[16];
- for (l=0; name[l]; l++) {
- if (l >= sizeof buf) goto nomatch;
- buf[l] = name[l];
- }
if (!strcmp(name, "readdir64_r"))
return find_sym(&ldso, "readdir_r", 1);
- if (l<2 || name[l-2]!='6' || name[l-1]!='4')
+ size_t l = strnlen(name, 18);
+ if (l<2 || name[l-2]!='6' || name[l-1]!='4' || name[l])
goto nomatch;
- buf[l-=2] = 0;
for (p=lfs64_list; *p; p++) {
- if (!strcmp(buf, p)) return find_sym(&ldso, buf, 1);
+ if (!strncmp(name, p, l-2) && !p[l-2])
+ return find_sym(&ldso, p, 1);
while (*p) p++;
}
nomatch:
@@ -621,6 +616,7 @@ static void reclaim_gaps(struct dso *dso)
for (; phcnt--; ph=(void *)((char *)ph+dso->phentsize)) {
if (ph->p_type!=PT_LOAD) continue;
if ((ph->p_flags&(PF_R|PF_W))!=(PF_R|PF_W)) continue;
+ if (ph->p_memsz == 0) continue;
reclaim(dso, ph->p_vaddr & -PAGE_SIZE, ph->p_vaddr);
reclaim(dso, ph->p_vaddr+ph->p_memsz,
ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE);
diff --git a/src/complex/catan.c b/src/complex/catan.c
index ccc2fb53..b4fe552a 100644
--- a/src/complex/catan.c
+++ b/src/complex/catan.c
@@ -60,29 +60,6 @@
#include "complex_impl.h"
-#define MAXNUM 1.0e308
-
-static const double DP1 = 3.14159265160560607910E0;
-static const double DP2 = 1.98418714791870343106E-9;
-static const double DP3 = 1.14423774522196636802E-17;
-
-static double _redupi(double x)
-{
- double t;
- long i;
-
- t = x/M_PI;
- if (t >= 0.0)
- t += 0.5;
- else
- t -= 0.5;
-
- i = t; /* the multiple */
- t = i;
- t = ((x - t * DP1) - t * DP2) - t * DP3;
- return t;
-}
-
double complex catan(double complex z)
{
double complex w;
@@ -95,7 +72,7 @@ double complex catan(double complex z)
a = 1.0 - x2 - (y * y);
t = 0.5 * atan2(2.0 * x, a);
- w = _redupi(t);
+ w = t;
t = y - 1.0;
a = x2 + (t * t);
diff --git a/src/complex/catanf.c b/src/complex/catanf.c
index 1d569f2d..faaa907a 100644
--- a/src/complex/catanf.c
+++ b/src/complex/catanf.c
@@ -55,32 +55,6 @@
#include "complex_impl.h"
-#define MAXNUMF 1.0e38F
-
-static const double DP1 = 3.140625;
-static const double DP2 = 9.67502593994140625E-4;
-static const double DP3 = 1.509957990978376432E-7;
-
-static const float float_pi = M_PI;
-
-static float _redupif(float xx)
-{
- float x, t;
- long i;
-
- x = xx;
- t = x/float_pi;
- if (t >= 0.0f)
- t += 0.5f;
- else
- t -= 0.5f;
-
- i = t; /* the multiple */
- t = i;
- t = ((x - t * DP1) - t * DP2) - t * DP3;
- return t;
-}
-
float complex catanf(float complex z)
{
float complex w;
@@ -93,7 +67,7 @@ float complex catanf(float complex z)
a = 1.0f - x2 - (y * y);
t = 0.5f * atan2f(2.0f * x, a);
- w = _redupif(t);
+ w = t;
t = y - 1.0f;
a = x2 + (t * t);
diff --git a/src/complex/catanl.c b/src/complex/catanl.c
index e62526c0..cd2d2b00 100644
--- a/src/complex/catanl.c
+++ b/src/complex/catanl.c
@@ -67,28 +67,6 @@ long double complex catanl(long double complex z)
return catan(z);
}
#else
-static const long double PIL = 3.141592653589793238462643383279502884197169L;
-static const long double DP1 = 3.14159265358979323829596852490908531763125L;
-static const long double DP2 = 1.6667485837041756656403424829301998703007e-19L;
-static const long double DP3 = 1.8830410776607851167459095484560349402753e-39L;
-
-static long double redupil(long double x)
-{
- long double t;
- long i;
-
- t = x / PIL;
- if (t >= 0.0L)
- t += 0.5L;
- else
- t -= 0.5L;
-
- i = t; /* the multiple */
- t = i;
- t = ((x - t * DP1) - t * DP2) - t * DP3;
- return t;
-}
-
long double complex catanl(long double complex z)
{
long double complex w;
@@ -101,7 +79,7 @@ long double complex catanl(long double complex z)
a = 1.0L - x2 - (y * y);
t = atan2l(2.0L * x, a) * 0.5L;
- w = redupil(t);
+ w = t;
t = y - 1.0L;
a = x2 + (t * t);
diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c
index 60d3e745..8dd5c725 100644
--- a/src/conf/sysconf.c
+++ b/src/conf/sysconf.c
@@ -220,8 +220,13 @@ long sysconf(int name)
return (mem > LONG_MAX) ? LONG_MAX : mem;
case JT_MINSIGSTKSZ & 255:
case JT_SIGSTKSZ & 255: ;
- long val = __getauxval(AT_MINSIGSTKSZ);
- if (val < MINSIGSTKSZ) val = MINSIGSTKSZ;
+ /* Value from auxv/kernel is only sigfame size. Clamp it
+ * to at least 1k below arch's traditional MINSIGSTKSZ,
+ * then add 1k of working space for signal handler. */
+ unsigned long sigframe_sz = __getauxval(AT_MINSIGSTKSZ);
+ if (sigframe_sz < MINSIGSTKSZ - 1024)
+ sigframe_sz = MINSIGSTKSZ - 1024;
+ unsigned val = sigframe_sz + 1024;
if (values[name] == JT_SIGSTKSZ)
val += SIGSTKSZ - MINSIGSTKSZ;
return val;
diff --git a/src/dirent/posix_getdents.c b/src/dirent/posix_getdents.c
index b19e8127..26c16ac6 100644
--- a/src/dirent/posix_getdents.c
+++ b/src/dirent/posix_getdents.c
@@ -3,7 +3,7 @@
#include <errno.h>
#include "syscall.h"
-int posix_getdents(int fd, void *buf, size_t len, int flags)
+ssize_t posix_getdents(int fd, void *buf, size_t len, int flags)
{
if (flags) return __syscall_ret(-EOPNOTSUPP);
if (len>INT_MAX) len = INT_MAX;
diff --git a/src/errno/__strerror.h b/src/errno/__strerror.h
index 14925907..0398b5b6 100644
--- a/src/errno/__strerror.h
+++ b/src/errno/__strerror.h
@@ -97,6 +97,8 @@ E(ESHUTDOWN, "Cannot send after socket shutdown")
E(EALREADY, "Operation already in progress")
E(EINPROGRESS, "Operation in progress")
E(ESTALE, "Stale file handle")
+E(EUCLEAN, "Data consistency error")
+E(ENAVAIL, "Resource not available")
E(EREMOTEIO, "Remote I/O error")
E(EDQUOT, "Quota exceeded")
E(ENOMEDIUM, "No medium found")
diff --git a/src/exit/atexit.c b/src/exit/atexit.c
index 854e9fdd..92c91c9d 100644
--- a/src/exit/atexit.c
+++ b/src/exit/atexit.c
@@ -19,6 +19,7 @@ static struct fl
void *a[COUNT];
} builtin, *head;
+static int finished_atexit;
static int slot;
static volatile int lock[1];
volatile int *const __atexit_lockptr = lock;
@@ -34,6 +35,10 @@ void __funcs_on_exit()
func(arg);
LOCK(lock);
}
+ /* Unlock to prevent deadlock if a global dtor
+ * attempts to call atexit. */
+ finished_atexit = 1;
+ UNLOCK(lock);
}
void __cxa_finalize(void *dso)
@@ -44,6 +49,13 @@ int __cxa_atexit(void (*func)(void *), void *arg, void *dso)
{
LOCK(lock);
+ /* Prevent dtors from registering further atexit
+ * handlers that would never be run. */
+ if (finished_atexit) {
+ UNLOCK(lock);
+ return -1;
+ }
+
/* Defer initialization of head so it can be in BSS */
if (!head) head = &builtin;
diff --git a/src/exit/exit.c b/src/exit/exit.c
index a6869b37..17b33cc6 100644
--- a/src/exit/exit.c
+++ b/src/exit/exit.c
@@ -1,6 +1,9 @@
#include <stdlib.h>
#include <stdint.h>
#include "libc.h"
+#include "pthread_impl.h"
+#include "atomic.h"
+#include "syscall.h"
static void dummy()
{
@@ -26,6 +29,17 @@ weak_alias(libc_exit_fini, __libc_exit_fini);
_Noreturn void exit(int code)
{
+ /* Handle potentially concurrent or recursive calls to exit,
+ * whose behaviors have traditionally been undefined by the
+ * standards. Using a custom lock here avoids pulling in lock
+ * machinery and lets us trap recursive calls while supporting
+ * multiple threads contending to be the one to exit(). */
+ static volatile int exit_lock[1];
+ int tid = __pthread_self()->tid;
+ int prev = a_cas(exit_lock, 0, tid);
+ if (prev == tid) a_crash();
+ else if (prev) for (;;) __sys_pause();
+
__funcs_on_exit();
__libc_exit_fini();
__stdio_exit();
diff --git a/src/internal/syscall.h b/src/internal/syscall.h
index 33d981f9..2d8a5c13 100644
--- a/src/internal/syscall.h
+++ b/src/internal/syscall.h
@@ -391,6 +391,17 @@ static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a,
#define __sys_open_cp(...) __SYSCALL_DISP(__sys_open_cp,,__VA_ARGS__)
#define sys_open_cp(...) __syscall_ret(__sys_open_cp(__VA_ARGS__))
+#ifdef SYS_pause
+#define __sys_pause() __syscall(SYS_pause)
+#define __sys_pause_cp() __syscall_cp(SYS_pause)
+#else
+#define __sys_pause() __syscall(SYS_ppoll, 0, 0, 0, 0)
+#define __sys_pause_cp() __syscall_cp(SYS_ppoll, 0, 0, 0, 0)
+#endif
+
+#define sys_pause() __syscall_ret(__sys_pause())
+#define sys_pause_cp() __syscall_ret(__sys_pause_cp())
+
#ifdef SYS_wait4
#define __sys_wait4(a,b,c,d) __syscall(SYS_wait4,a,b,c,d)
#define __sys_wait4_cp(a,b,c,d) __syscall_cp(SYS_wait4,a,b,c,d)
diff --git a/src/ldso/loongarch64/tlsdesc.s b/src/ldso/loongarch64/tlsdesc.s
new file mode 100644
index 00000000..4b6ea0e5
--- /dev/null
+++ b/src/ldso/loongarch64/tlsdesc.s
@@ -0,0 +1,37 @@
+.text
+.global __tlsdesc_static
+.hidden __tlsdesc_static
+.type __tlsdesc_static,%function
+__tlsdesc_static:
+ ld.d $a0, $a0, 8
+ jr $ra
+# size_t __tlsdesc_dynamic(size_t *a)
+# {
+# struct {size_t modidx,off;} *p = (void*)a[1];
+# size_t *dtv = *(size_t**)(tp - 8);
+# return dtv[p->modidx] + p->off - tp;
+# }
+.global __tlsdesc_dynamic
+.hidden __tlsdesc_dynamic
+.type __tlsdesc_dynamic,%function
+__tlsdesc_dynamic:
+ addi.d $sp, $sp, -16
+ st.d $t1, $sp, 0
+ st.d $t2, $sp, 8
+
+ ld.d $t2, $tp, -8 # t2=dtv
+
+ ld.d $a0, $a0, 8 # a0=&{modidx,off}
+ ld.d $t1, $a0, 8 # t1=off
+ ld.d $a0, $a0, 0 # a0=modidx
+ slli.d $a0, $a0, 3 # a0=8*modidx
+
+ add.d $a0, $a0, $t2 # a0=dtv+8*modidx
+ ld.d $a0, $a0, 0 # a0=dtv[modidx]
+ add.d $a0, $a0, $t1 # a0=dtv[modidx]+off
+ sub.d $a0, $a0, $tp # a0=dtv[modidx]+off-tp
+
+ ld.d $t1, $sp, 0
+ ld.d $t2, $sp, 8
+ addi.d $sp, $sp, 16
+ jr $ra
diff --git a/src/legacy/getusershell.c b/src/legacy/getusershell.c
index 5fecdec2..1c5d98ec 100644
--- a/src/legacy/getusershell.c
+++ b/src/legacy/getusershell.c
@@ -25,8 +25,10 @@ char *getusershell(void)
ssize_t l;
if (!f) setusershell();
if (!f) return 0;
- l = getline(&line, &linesize, f);
- if (l <= 0) return 0;
+ do {
+ l = getline(&line, &linesize, f);
+ if (l <= 0) return 0;
+ } while (line[0] == '#' || line[0] == '\n');
if (line[l-1]=='\n') line[l-1]=0;
return line;
}
diff --git a/src/linux/renameat2.c b/src/linux/renameat2.c
new file mode 100644
index 00000000..b8060388
--- /dev/null
+++ b/src/linux/renameat2.c
@@ -0,0 +1,11 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include "syscall.h"
+
+int renameat2(int oldfd, const char *old, int newfd, const char *new, unsigned flags)
+{
+#ifdef SYS_renameat
+ if (!flags) return syscall(SYS_renameat, oldfd, old, newfd, new);
+#endif
+ return syscall(SYS_renameat2, oldfd, old, newfd, new, flags);
+}
diff --git a/src/linux/statx.c b/src/linux/statx.c
index 4616bff4..4fb96e4b 100644
--- a/src/linux/statx.c
+++ b/src/linux/statx.c
@@ -19,8 +19,11 @@ int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct
ret = fstatat(dirfd, path, &st, flags);
if (ret) return ret;
+ *stx = (struct statx){0};
stx->stx_dev_major = major(st.st_dev);
stx->stx_dev_minor = minor(st.st_dev);
+ stx->stx_rdev_major = major(st.st_rdev);
+ stx->stx_rdev_minor = minor(st.st_rdev);
stx->stx_ino = st.st_ino;
stx->stx_mode = st.st_mode;
stx->stx_nlink = st.st_nlink;
@@ -35,7 +38,6 @@ int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct
stx->stx_mtime.tv_nsec = st.st_mtim.tv_nsec;
stx->stx_ctime.tv_sec = st.st_ctim.tv_sec;
stx->stx_ctime.tv_nsec = st.st_ctim.tv_nsec;
- stx->stx_btime = (struct statx_timestamp){.tv_sec=0, .tv_nsec=0};
stx->stx_mask = STATX_BASIC_STATS;
return 0;
diff --git a/src/locale/bind_textdomain_codeset.c b/src/locale/bind_textdomain_codeset.c
index 5ebfd5e8..240e83ed 100644
--- a/src/locale/bind_textdomain_codeset.c
+++ b/src/locale/bind_textdomain_codeset.c
@@ -5,7 +5,9 @@
char *bind_textdomain_codeset(const char *domainname, const char *codeset)
{
- if (codeset && strcasecmp(codeset, "UTF-8"))
+ if (codeset && strcasecmp(codeset, "UTF-8")) {
errno = EINVAL;
- return NULL;
+ return 0;
+ }
+ return "UTF-8";
}
diff --git a/src/locale/codepages.h b/src/locale/codepages.h
index 4e236ef3..a254f0f5 100644
--- a/src/locale/codepages.h
+++ b/src/locale/codepages.h
@@ -286,6 +286,17 @@
"\323\174\103\215\64\365\124\123\213\77\336\150\263\115\66\375\164\363\12\55"
"\255\304\42\261\57\266\234\162\17\56\260\240\162\113\56\263\310\62\66\50"
+"cp858\0"
+"\0\40"
+"\307\360\223\216\70\344\200\123\316\71\352\254\203\316\73\356\260\103\114\61"
+"\311\230\143\14\75\366\310\263\117\76\377\130\303\15\76\243\140\163\15\135"
+"\341\264\63\217\76\361\104\243\212\56\277\270\302\112\57\274\204\262\312\56"
+"\140\207\55\66\315\72\7\43\14\60\251\104\375\163\321\113\213\122\212\315"
+"\67\363\274\163\316\63\367\74\316\60\110\13\175\65\325\116\373\254\65\51"
+"\360\100\243\314\62\310\220\334\214\63\317\340\134\163\327\134\233\302\314\326"
+"\323\174\103\215\64\365\124\123\213\77\336\150\263\115\66\375\164\363\12\55"
+"\255\304\42\261\57\266\234\162\17\56\260\240\162\113\56\263\310\62\66\50"
+
"cp866\0"
"\0\40"
"\337\201\27\236\170\343\221\127\236\171\347\241\227\236\172"
diff --git a/src/locale/iconv.c b/src/locale/iconv.c
index 7fb2e1ef..52178950 100644
--- a/src/locale/iconv.c
+++ b/src/locale/iconv.c
@@ -339,6 +339,8 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
} else if (d-159 <= 252-159) {
c++;
d -= 159;
+ } else {
+ goto ilseq;
}
if (c>=84) goto ilseq;
c = jis0208[c][d];
@@ -500,7 +502,7 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
if (c >= 93 || d >= 94) {
c += (0xa1-0x81);
d += 0xa1;
- if (c >= 93 || c>=0xc6-0x81 && d>0x52)
+ if (c > 0xc6-0x81 || c==0xc6-0x81 && d>0x52)
goto ilseq;
if (d-'A'<26) d = d-'A';
else if (d-'a'<26) d = d-'a'+26;
@@ -543,6 +545,10 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
if (*outb < k) goto toobig;
memcpy(*out, tmp, k);
} else k = wctomb_utf8(*out, c);
+ /* This failure condition should be unreachable, but
+ * is included to prevent decoder bugs from translating
+ * into advancement outside the output buffer range. */
+ if (k>4) goto ilseq;
*out += k;
*outb -= k;
break;
diff --git a/src/math/powl.c b/src/math/powl.c
index 6f64ea71..9eb22162 100644
--- a/src/math/powl.c
+++ b/src/math/powl.c
@@ -57,14 +57,6 @@
* IEEE 0,8700 60000 6.5e-18 1.0e-18
* 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed.
*
- *
- * ERROR MESSAGES:
- *
- * message condition value returned
- * pow overflow x**y > MAXNUM INFINITY
- * pow underflow x**y < 1/MAXNUM 0.0
- * pow domain x<0 and y noninteger 0.0
- *
*/
#include "libm.h"
diff --git a/src/misc/mntent.c b/src/misc/mntent.c
index 78bf0cd0..76f9c162 100644
--- a/src/misc/mntent.c
+++ b/src/misc/mntent.c
@@ -81,7 +81,7 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle
len = strlen(linebuf);
if (len > INT_MAX) continue;
for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len;
- sscanf(linebuf, " %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %d %d",
+ sscanf(linebuf, " %n%*[^ \t\n]%n %n%*[^ \t\n]%n %n%*[^ \t\n]%n %n%*[^ \t\n]%n %d %d",
n, n+1, n+2, n+3, n+4, n+5, n+6, n+7,
&mnt->mnt_freq, &mnt->mnt_passno);
} while (linebuf[n[0]] == '#' || n[1]==len);
@@ -115,5 +115,13 @@ int addmntent(FILE *f, const struct mntent *mnt)
char *hasmntopt(const struct mntent *mnt, const char *opt)
{
- return strstr(mnt->mnt_opts, opt);
+ size_t l = strlen(opt);
+ char *p = mnt->mnt_opts;
+ for (;;) {
+ if (!strncmp(p, opt, l) && (!p[l] || p[l]==',' || p[l]=='='))
+ return p;
+ p = strchr(p, ',');
+ if (!p) return 0;
+ p++;
+ }
}
diff --git a/src/mq/x32/mq_open.c b/src/mq/x32/mq_open.c
new file mode 100644
index 00000000..23481959
--- /dev/null
+++ b/src/mq/x32/mq_open.c
@@ -0,0 +1,22 @@
+#include <mqueue.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include "syscall.h"
+
+mqd_t mq_open(const char *name, int flags, ...)
+{
+ mode_t mode = 0;
+ struct mq_attr *attr = 0;
+ long long attrbuf[8];
+ if (*name == '/') name++;
+ if (flags & O_CREAT) {
+ va_list ap;
+ va_start(ap, flags);
+ mode = va_arg(ap, mode_t);
+ attr = va_arg(ap, struct mq_attr *);
+ if (attr) for (int i=0; i<8; i++)
+ attrbuf[i] = *(long *)((char *)attr + i*sizeof(long));
+ va_end(ap);
+ }
+ return syscall(SYS_mq_open, name, flags, mode, attr?attrbuf:0);
+}
diff --git a/src/mq/x32/mq_setattr.c b/src/mq/x32/mq_setattr.c
new file mode 100644
index 00000000..0c631175
--- /dev/null
+++ b/src/mq/x32/mq_setattr.c
@@ -0,0 +1,14 @@
+#include <mqueue.h>
+#include "syscall.h"
+
+int mq_setattr(mqd_t mqd, const struct mq_attr *restrict new, struct mq_attr *restrict old)
+{
+ long long attr[8];
+ if (new) for (int i=0; i<8; i++)
+ attr[i] = *(long *)((char *)new + i*sizeof(long));
+ int ret = __syscall(SYS_mq_getsetattr, mqd, new?attr:0, old?attr:0);
+ if (ret < 0) return __syscall_ret(ret);
+ if (old) for (int i=0; i<8; i++)
+ *(long *)((char *)old + i*sizeof(long)) = attr[i];
+ return 0;
+}
diff --git a/src/multibyte/mbsnrtowcs.c b/src/multibyte/mbsnrtowcs.c
index 931192e2..47cbdc00 100644
--- a/src/multibyte/mbsnrtowcs.c
+++ b/src/multibyte/mbsnrtowcs.c
@@ -2,11 +2,13 @@
size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, size_t wn, mbstate_t *restrict st)
{
+ static unsigned internal_state;
size_t l, cnt=0, n2;
wchar_t *ws, wbuf[256];
const char *s = *src;
const char *tmp_s;
+ if (!st) st = (void *)&internal_state;
if (!wcs) ws = wbuf, wn = sizeof wbuf / sizeof *wbuf;
else ws = wcs;
@@ -41,8 +43,8 @@ size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, si
s = 0;
break;
}
- /* have to roll back partial character */
- *(unsigned *)st = 0;
+ s += n;
+ n -= n;
break;
}
s += l; n -= l;
diff --git a/src/network/inet_ntop.c b/src/network/inet_ntop.c
index 4bfef2c5..f442f47d 100644
--- a/src/network/inet_ntop.c
+++ b/src/network/inet_ntop.c
@@ -34,7 +34,12 @@ const char *inet_ntop(int af, const void *restrict a0, char *restrict s, socklen
for (i=best=0, max=2; buf[i]; i++) {
if (i && buf[i] != ':') continue;
j = strspn(buf+i, ":0");
- if (j>max) best=i, max=j;
+ /* The leading sequence of zeros (best==0) is
+ * disadvantaged compared to sequences elsewhere
+ * as it doesn't have a leading colon. One extra
+ * character is required for another sequence to
+ * beat it fairly. */
+ if (j>max+(best==0)) best=i, max=j;
}
if (max>3) {
buf[best] = buf[best+1] = ':';
diff --git a/src/network/res_msend.c b/src/network/res_msend.c
index 86c2fcf4..fcb52513 100644
--- a/src/network/res_msend.c
+++ b/src/network/res_msend.c
@@ -83,8 +83,8 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
int fd;
int timeout, attempts, retry_interval, servfail_retry;
union {
- struct sockaddr_in sin;
struct sockaddr_in6 sin6;
+ struct sockaddr_in sin;
} sa = {0}, ns[MAXNS] = {{0}};
socklen_t sl = sizeof sa.sin;
int nns = 0;
diff --git a/src/signal/riscv32/restore.s b/src/signal/riscv32/restore.s
index 40012c75..5a0af695 100644
--- a/src/signal/riscv32/restore.s
+++ b/src/signal/riscv32/restore.s
@@ -1,7 +1,9 @@
.global __restore
+.hidden __restore
.type __restore, %function
__restore:
.global __restore_rt
+.hidden __restore_rt
.type __restore_rt, %function
__restore_rt:
li a7, 139 # SYS_rt_sigreturn
diff --git a/src/signal/riscv64/restore.s b/src/signal/riscv64/restore.s
index 40012c75..5a0af695 100644
--- a/src/signal/riscv64/restore.s
+++ b/src/signal/riscv64/restore.s
@@ -1,7 +1,9 @@
.global __restore
+.hidden __restore
.type __restore, %function
__restore:
.global __restore_rt
+.hidden __restore_rt
.type __restore_rt, %function
__restore_rt:
li a7, 139 # SYS_rt_sigreturn
diff --git a/src/signal/sigaltstack.c b/src/signal/sigaltstack.c
index d3a6e821..616625c5 100644
--- a/src/signal/sigaltstack.c
+++ b/src/signal/sigaltstack.c
@@ -1,11 +1,13 @@
#include <signal.h>
#include <errno.h>
+#include <unistd.h>
#include "syscall.h"
int sigaltstack(const stack_t *restrict ss, stack_t *restrict old)
{
if (ss) {
- if (!(ss->ss_flags & SS_DISABLE) && ss->ss_size < MINSIGSTKSZ) {
+ size_t min = sysconf(_SC_MINSIGSTKSZ);
+ if (!(ss->ss_flags & SS_DISABLE) && ss->ss_size < min) {
errno = ENOMEM;
return -1;
}
diff --git a/src/signal/siglongjmp.c b/src/signal/siglongjmp.c
index bc317acc..53789b23 100644
--- a/src/signal/siglongjmp.c
+++ b/src/signal/siglongjmp.c
@@ -5,5 +5,10 @@
_Noreturn void siglongjmp(sigjmp_buf buf, int ret)
{
+ /* If sigsetjmp was called with nonzero savemask flag, the address
+ * longjmp will return to is inside of sigsetjmp. The signal mask
+ * will then be restored in the returned-to context instead of here,
+ * which matters if the context we are returning from may not have
+ * sufficient stack space for signal delivery. */
longjmp(buf, ret);
}
diff --git a/src/signal/sigpause.c b/src/signal/sigpause.c
index 363d2fec..1587c391 100644
--- a/src/signal/sigpause.c
+++ b/src/signal/sigpause.c
@@ -4,6 +4,6 @@ int sigpause(int sig)
{
sigset_t mask;
sigprocmask(0, 0, &mask);
- sigdelset(&mask, sig);
+ if (sigdelset(&mask, sig)) return -1;
return sigsuspend(&mask);
}
diff --git a/src/stdio/__stdio_write.c b/src/stdio/__stdio_write.c
index d2d89475..5356553d 100644
--- a/src/stdio/__stdio_write.c
+++ b/src/stdio/__stdio_write.c
@@ -11,6 +11,11 @@ size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
size_t rem = iov[0].iov_len + iov[1].iov_len;
int iovcnt = 2;
ssize_t cnt;
+
+ if (!iov->iov_len) {
+ iov++;
+ iovcnt--;
+ }
for (;;) {
cnt = syscall(SYS_writev, f->fd, iov, iovcnt);
if (cnt == rem) {
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index 360d723a..76733997 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -178,10 +178,14 @@ static char *fmt_u(uintmax_t x, char *s)
typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)];
#endif
-static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
+static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t, int ps)
{
- uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion
- + (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion
+ int bufsize = (ps==BIGLPRE)
+ ? (LDBL_MANT_DIG+28)/29 + 1 + // mantissa expansion
+ (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9 // exponent expansion
+ : (DBL_MANT_DIG+28)/29 + 1 +
+ (DBL_MAX_EXP+DBL_MANT_DIG+28+8)/9;
+ uint32_t big[bufsize];
uint32_t *a, *d, *r, *z;
int e2=0, e, i, j, l;
char buf[9+LDBL_MANT_DIG/4], *s;
@@ -557,11 +561,11 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
case 'x': case 'X':
a = fmt_x(arg.i, z, t&32);
if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
- if (0) {
+ goto ifmt_tail;
case 'o':
a = fmt_o(arg.i, z);
if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1;
- } if (0) {
+ goto ifmt_tail;
case 'd': case 'i':
pl=1;
if (arg.i>INTMAX_MAX) {
@@ -573,7 +577,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
} else pl=0;
case 'u':
a = fmt_u(arg.i, z);
- }
+ ifmt_tail:
if (xp && p<0) goto overflow;
if (xp) fl &= ~ZERO_PAD;
if (!arg.i && !p) {
@@ -618,7 +622,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
case 'e': case 'f': case 'g': case 'a':
case 'E': case 'F': case 'G': case 'A':
if (xp && p<0) goto overflow;
- l = fmt_fp(f, arg.f, w, p, fl, t);
+ l = fmt_fp(f, arg.f, w, p, fl, t, ps);
if (l<0) goto overflow;
continue;
}
diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c
index 314ddc29..ab79dc6f 100644
--- a/src/stdlib/qsort.c
+++ b/src/stdlib/qsort.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 by Valentin Ochs
+/* Copyright (C) 2011 by Lynn Ochs
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
diff --git a/src/string/strcasestr.c b/src/string/strcasestr.c
index af109f36..dc598bc3 100644
--- a/src/string/strcasestr.c
+++ b/src/string/strcasestr.c
@@ -4,6 +4,7 @@
char *strcasestr(const char *h, const char *n)
{
size_t l = strlen(n);
+ if (!l) return (char *)h;
for (; *h; h++) if (!strncasecmp(h, n, l)) return (char *)h;
return 0;
}
diff --git a/src/termios/cfgetospeed.c b/src/termios/cfgetospeed.c
index 55fa6f55..de46a1d8 100644
--- a/src/termios/cfgetospeed.c
+++ b/src/termios/cfgetospeed.c
@@ -9,5 +9,5 @@ speed_t cfgetospeed(const struct termios *tio)
speed_t cfgetispeed(const struct termios *tio)
{
- return cfgetospeed(tio);
+ return (tio->c_cflag & CIBAUD) / (CIBAUD/CBAUD);
}
diff --git a/src/termios/cfsetospeed.c b/src/termios/cfsetospeed.c
index c9cbdd9d..3eab092a 100644
--- a/src/termios/cfsetospeed.c
+++ b/src/termios/cfsetospeed.c
@@ -16,7 +16,11 @@ int cfsetospeed(struct termios *tio, speed_t speed)
int cfsetispeed(struct termios *tio, speed_t speed)
{
- return speed ? cfsetospeed(tio, speed) : 0;
+ if (speed & ~CBAUD) {
+ errno = EINVAL;
+ return -1;
+ }
+ tio->c_cflag &= ~CIBAUD;
+ tio->c_cflag |= speed * (CIBAUD/CBAUD);
+ return 0;
}
-
-weak_alias(cfsetospeed, cfsetspeed);
diff --git a/src/termios/cfsetspeed.c b/src/termios/cfsetspeed.c
new file mode 100644
index 00000000..2c369db9
--- /dev/null
+++ b/src/termios/cfsetspeed.c
@@ -0,0 +1,11 @@
+#define _BSD_SOURCE
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+int cfsetspeed(struct termios *tio, speed_t speed)
+{
+ int r = cfsetospeed(tio, speed);
+ if (!r) cfsetispeed(tio, 0);
+ return r;
+}
diff --git a/src/thread/aarch64/clone.s b/src/thread/aarch64/clone.s
index e3c83395..9ac272bd 100644
--- a/src/thread/aarch64/clone.s
+++ b/src/thread/aarch64/clone.s
@@ -24,7 +24,8 @@ __clone:
// parent
ret
// child
-1: ldp x1,x0,[sp],#16
+1: mov fp, 0
+ ldp x1,x0,[sp],#16
blr x1
mov x8,#93 // SYS_exit
svc #0
diff --git a/src/thread/arm/clone.s b/src/thread/arm/clone.s
index bb0965da..4ff0c0e8 100644
--- a/src/thread/arm/clone.s
+++ b/src/thread/arm/clone.s
@@ -19,7 +19,8 @@ __clone:
ldmfd sp!,{r4,r5,r6,r7}
bx lr
-1: mov r0,r6
+1: mov fp,#0
+ mov r0,r6
bl 3f
2: mov r7,#1
svc 0
diff --git a/src/thread/loongarch64/clone.s b/src/thread/loongarch64/clone.s
index a165b365..cb4aacfc 100644
--- a/src/thread/loongarch64/clone.s
+++ b/src/thread/loongarch64/clone.s
@@ -22,6 +22,7 @@ __clone:
beqz $a0, 1f # whether child process
jirl $zero, $ra, 0 # parent process return
1:
+ move $fp, $zero
ld.d $t8, $sp, 0 # function pointer
ld.d $a0, $sp, 8 # argument pointer
jirl $ra, $t8, 0 # call the user's function
diff --git a/src/thread/m68k/clone.s b/src/thread/m68k/clone.s
index f6dfa06f..0134cf4e 100644
--- a/src/thread/m68k/clone.s
+++ b/src/thread/m68k/clone.s
@@ -18,7 +18,8 @@ __clone:
beq 1f
movem.l (%sp)+,%d2-%d5
rts
-1: move.l %a1,-(%sp)
+1: suba.l %fp,%fp
+ move.l %a1,-(%sp)
jsr (%a0)
move.l #1,%d0
trap #0
diff --git a/src/thread/microblaze/clone.s b/src/thread/microblaze/clone.s
index b68cc5fc..64e3f074 100644
--- a/src/thread/microblaze/clone.s
+++ b/src/thread/microblaze/clone.s
@@ -22,7 +22,8 @@ __clone:
rtsd r15, 8
nop
-1: lwi r3, r1, 0
+1: add r19, r0, r0
+ lwi r3, r1, 0
lwi r5, r1, 4
brald r15, r3
nop
diff --git a/src/thread/mips/clone.s b/src/thread/mips/clone.s
index 04463385..229b987e 100644
--- a/src/thread/mips/clone.s
+++ b/src/thread/mips/clone.s
@@ -27,7 +27,8 @@ __clone:
addu $sp, $sp, 16
jr $ra
nop
-1: lw $25, 0($sp)
+1: move $fp, $0
+ lw $25, 0($sp)
lw $4, 4($sp)
jalr $25
nop
diff --git a/src/thread/mips64/clone.s b/src/thread/mips64/clone.s
index 2d86899a..8de3db6c 100644
--- a/src/thread/mips64/clone.s
+++ b/src/thread/mips64/clone.s
@@ -25,7 +25,8 @@ __clone:
nop
jr $ra
nop
-1: ld $25, 0($sp) # function pointer
+1: move $fp, $0
+ ld $25, 0($sp) # function pointer
ld $4, 8($sp) # argument pointer
jalr $25 # call the user's function
nop
diff --git a/src/thread/mipsn32/clone.s b/src/thread/mipsn32/clone.s
index 4d3c8c7a..9571231a 100644
--- a/src/thread/mipsn32/clone.s
+++ b/src/thread/mipsn32/clone.s
@@ -25,7 +25,8 @@ __clone:
nop
jr $ra
nop
-1: lw $25, 0($sp) # function pointer
+1: move $fp, $0
+ lw $25, 0($sp) # function pointer
lw $4, 4($sp) # argument pointer
jalr $25 # call the user's function
nop
diff --git a/src/thread/or1k/clone.s b/src/thread/or1k/clone.s
index 2473ac20..b41488a2 100644
--- a/src/thread/or1k/clone.s
+++ b/src/thread/or1k/clone.s
@@ -6,6 +6,8 @@
.hidden __clone
.type __clone,@function
__clone:
+ l.xori r11, r0, -4
+ l.and r4, r4, r11
l.addi r4, r4, -8
l.sw 0(r4), r3
l.sw 4(r4), r6
@@ -23,7 +25,8 @@ __clone:
l.jr r9
l.nop
-1: l.lwz r11, 0(r1)
+1: l.ori r2, r0, 0
+ l.lwz r11, 0(r1)
l.jalr r11
l.lwz r3, 4(r1)
diff --git a/src/thread/riscv32/clone.s b/src/thread/riscv32/clone.s
index 3102239d..e2116e33 100644
--- a/src/thread/riscv32/clone.s
+++ b/src/thread/riscv32/clone.s
@@ -8,6 +8,7 @@
.type __clone, %function
__clone:
# Save func and arg to stack
+ andi a1, a1, -16
addi a1, a1, -16
sw a0, 0(a1)
sw a3, 4(a1)
diff --git a/src/thread/riscv64/clone.s b/src/thread/riscv64/clone.s
index db908248..0e6f41a8 100644
--- a/src/thread/riscv64/clone.s
+++ b/src/thread/riscv64/clone.s
@@ -8,6 +8,7 @@
.type __clone, %function
__clone:
# Save func and arg to stack
+ andi a1, a1, -16
addi a1, a1, -16
sd a0, 0(a1)
sd a3, 8(a1)
diff --git a/src/thread/s390x/__tls_get_offset.s b/src/thread/s390x/__tls_get_offset.s
index 8ee92de8..405f118b 100644
--- a/src/thread/s390x/__tls_get_offset.s
+++ b/src/thread/s390x/__tls_get_offset.s
@@ -1,17 +1,17 @@
.global __tls_get_offset
.type __tls_get_offset,%function
__tls_get_offset:
- stmg %r14, %r15, 112(%r15)
- aghi %r15, -160
+ ear %r0, %a0
+ sllg %r0, %r0, 32
+ ear %r0, %a1
- la %r2, 0(%r2, %r12)
- brasl %r14, __tls_get_addr
+ la %r1, 0(%r2, %r12)
- ear %r1, %a0
- sllg %r1, %r1, 32
- ear %r1, %a1
+ lg %r3, 0(%r1)
+ sllg %r4, %r3, 3
+ lg %r5, 8(%r0)
+ lg %r2, 0(%r4, %r5)
+ ag %r2, 8(%r1)
+ sgr %r2, %r0
- sgr %r2, %r1
-
- lmg %r14, %r15, 272(%r15)
br %r14
diff --git a/src/thread/sem_post.c b/src/thread/sem_post.c
index 5c2517f2..1c8f763c 100644
--- a/src/thread/sem_post.c
+++ b/src/thread/sem_post.c
@@ -16,6 +16,6 @@ int sem_post(sem_t *sem)
if (waiters <= 1)
new &= ~0x80000000;
} while (a_cas(sem->__val, val, new) != val);
- if (val<0) __wake(sem->__val, waiters>1 ? 1 : -1, priv);
+ if (val<0 || waiters) __wake(sem->__val, waiters>1 ? 1 : -1, priv);
return 0;
}
diff --git a/src/time/__tz.c b/src/time/__tz.c
index c34b3eb7..54ed4cf6 100644
--- a/src/time/__tz.c
+++ b/src/time/__tz.c
@@ -24,7 +24,6 @@ weak_alias(__tzname, tzname);
static char std_name[TZNAME_MAX+1];
static char dst_name[TZNAME_MAX+1];
-const char __utc[] = "UTC";
static int dst_off;
static int r0[5], r1[5];
diff --git a/src/time/__utc.c b/src/time/__utc.c
new file mode 100644
index 00000000..9e8bfc58
--- /dev/null
+++ b/src/time/__utc.c
@@ -0,0 +1,3 @@
+#include "time_impl.h"
+
+const char __utc[] = "UTC";
diff --git a/src/time/timer_create.c b/src/time/timer_create.c
index 9216b3ab..cc6c2236 100644
--- a/src/time/timer_create.c
+++ b/src/time/timer_create.c
@@ -1,6 +1,7 @@
#include <time.h>
#include <setjmp.h>
#include <limits.h>
+#include <semaphore.h>
#include "pthread_impl.h"
#include "atomic.h"
@@ -12,7 +13,7 @@ struct ksigevent {
};
struct start_args {
- pthread_barrier_t b;
+ sem_t sem1, sem2;
struct sigevent *sev;
};
@@ -21,10 +22,16 @@ static void dummy_0()
}
weak_alias(dummy_0, __pthread_tsd_run_dtors);
+static void timer_handler(int sig, siginfo_t *si, void *ctx)
+{
+}
+
static void cleanup_fromsig(void *p)
{
pthread_t self = __pthread_self();
__pthread_tsd_run_dtors();
+ __block_app_sigs(0);
+ __syscall(SYS_rt_sigprocmask, SIG_BLOCK, SIGTIMER_SET, 0, _NSIG/8);
self->cancel = 0;
self->cancelbuf = 0;
self->canceldisable = 0;
@@ -42,7 +49,14 @@ static void *start(void *arg)
void (*notify)(union sigval) = args->sev->sigev_notify_function;
union sigval val = args->sev->sigev_value;
- pthread_barrier_wait(&args->b);
+ /* The two-way semaphore synchronization ensures that we see
+ * self->cancel set by the parent if timer creation failed or
+ * self->timer_id if it succeeded, and informs the parent that
+ * we are done accessing the arguments so that the parent can
+ * proceed past their block lifetime. */
+ while (sem_wait(&args->sem1));
+ sem_post(&args->sem2);
+
if (self->cancel)
return 0;
for (;;) {
@@ -90,7 +104,10 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
break;
case SIGEV_THREAD:
if (!init) {
- struct sigaction sa = { .sa_handler = SIG_DFL };
+ struct sigaction sa = {
+ .sa_sigaction = timer_handler,
+ .sa_flags = SA_SIGINFO | SA_RESTART
+ };
__libc_sigaction(SIGTIMER, &sa, 0);
a_store(&init, 1);
}
@@ -99,7 +116,8 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
else
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_barrier_init(&args.b, 0, 2);
+ sem_init(&args.sem1, 0, 0);
+ sem_init(&args.sem2, 0, 0);
args.sev = evp;
__block_app_sigs(&set);
@@ -120,7 +138,8 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
td->cancel = 1;
}
td->timer_id = timerid;
- pthread_barrier_wait(&args.b);
+ sem_post(&args.sem1);
+ while (sem_wait(&args.sem2));
if (timerid < 0) return -1;
*res = (void *)(INTPTR_MIN | (uintptr_t)td>>1);
break;
diff --git a/src/unistd/isatty.c b/src/unistd/isatty.c
index 75a9c186..21222eda 100644
--- a/src/unistd/isatty.c
+++ b/src/unistd/isatty.c
@@ -6,8 +6,6 @@
int isatty(int fd)
{
struct winsize wsz;
- unsigned long r = syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz);
- if (r == 0) return 1;
- if (errno != EBADF) errno = ENOTTY;
- return 0;
+ /* +1 converts from error status (0/-1) to boolean (1/0) */
+ return syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz) + 1;
}
diff --git a/src/unistd/pause.c b/src/unistd/pause.c
index 90bbf4ca..90cc8db5 100644
--- a/src/unistd/pause.c
+++ b/src/unistd/pause.c
@@ -3,9 +3,5 @@
int pause(void)
{
-#ifdef SYS_pause
- return syscall_cp(SYS_pause);
-#else
- return syscall_cp(SYS_ppoll, 0, 0, 0, 0);
-#endif
+ return sys_pause_cp();
}