code:
diff --git a/arch/aarch64/bits/hwcap.h b/arch/aarch64/bits/hwcap.h
index 7ab73f99..424cc4d4 100644
--- a/arch/aarch64/bits/hwcap.h
+++ b/arch/aarch64/bits/hwcap.h
@@ -48,3 +48,5 @@
 #define HWCAP2_BF16		(1 << 14)
 #define HWCAP2_DGH		(1 << 15)
 #define HWCAP2_RNG		(1 << 16)
+#define HWCAP2_BTI		(1 << 17)
+#define HWCAP2_MTE		(1 << 18)
diff --git a/arch/aarch64/bits/mman.h b/arch/aarch64/bits/mman.h
new file mode 100644
index 00000000..8fad5ceb
--- /dev/null
+++ b/arch/aarch64/bits/mman.h
@@ -0,0 +1,2 @@
+#define PROT_BTI 0x10
+#define PROT_MTE 0x20
diff --git a/arch/aarch64/bits/syscall.h.in b/arch/aarch64/bits/syscall.h.in
index f9457c18..1ad467c0 100644
--- a/arch/aarch64/bits/syscall.h.in
+++ b/arch/aarch64/bits/syscall.h.in
@@ -293,4 +293,5 @@
 #define __NR_openat2		437
 #define __NR_pidfd_getfd	438
 #define __NR_faccessat2		439
+#define __NR_process_madvise	440

diff --git a/arch/arm/bits/syscall.h.in b/arch/arm/bits/syscall.h.in
index 7e2fc266..cf9e3411 100644
--- a/arch/arm/bits/syscall.h.in
+++ b/arch/arm/bits/syscall.h.in
@@ -393,6 +393,7 @@
 #define __NR_openat2		437
 #define __NR_pidfd_getfd	438
 #define __NR_faccessat2		439
+#define __NR_process_madvise	440

 #define __ARM_NR_breakpoint	0x0f0001
 #define __ARM_NR_cacheflush	0x0f0002
diff --git a/arch/i386/bits/syscall.h.in b/arch/i386/bits/syscall.h.in
index abdb210d..5d1c4d7a 100644
--- a/arch/i386/bits/syscall.h.in
+++ b/arch/i386/bits/syscall.h.in
@@ -430,4 +430,5 @@
 #define __NR_openat2		437
 #define __NR_pidfd_getfd	438
 #define __NR_faccessat2		439
+#define __NR_process_madvise	440

diff --git a/arch/m68k/bits/syscall.h.in b/arch/m68k/bits/syscall.h.in
index e10969a2..6794b1a0 100644
--- a/arch/m68k/bits/syscall.h.in
+++ b/arch/m68k/bits/syscall.h.in
@@ -410,3 +410,4 @@
 #define __NR_openat2		437
 #define __NR_pidfd_getfd	438
 #define __NR_faccessat2		439
+#define __NR_process_madvise	440
diff --git a/arch/microblaze/bits/syscall.h.in b/arch/microblaze/bits/syscall.h.in
index 9d469047..7f71df3b 100644
--- a/arch/microblaze/bits/syscall.h.in
+++ b/arch/microblaze/bits/syscall.h.in
@@ -431,4 +431,5 @@
 #define __NR_openat2		437
 #define __NR_pidfd_getfd	438
 #define __NR_faccessat2		439
+#define __NR_process_madvise	440

diff --git a/arch/mips/bits/syscall.h.in b/arch/mips/bits/syscall.h.in
index 2bb03f06..d54845b2 100644
--- a/arch/mips/bits/syscall.h.in
+++ b/arch/mips/bits/syscall.h.in
@@ -412,4 +412,5 @@
 #define __NR_openat2		4437
 #define __NR_pidfd_getfd	4438
 #define __NR_faccessat2		4439
+#define __NR_process_madvise	4440

diff --git a/arch/mips/pthread_arch.h b/arch/mips/pthread_arch.h
index c45347ab..376b7741 100644
--- a/arch/mips/pthread_arch.h
+++ b/arch/mips/pthread_arch.h
@@ -1,10 +1,9 @@
 static inline uintptr_t __get_tp()
 {
-#if __mips_isa_rev < 2
 	register uintptr_t tp __asm__("$3");
+#if __mips_isa_rev < 2
 	__asm__ (".word 0x7c03e83b" : "=r" (tp) );
 #else
-	uintptr_t tp;
 	__asm__ ("rdhwr %0, $29" : "=r" (tp) );
 #endif
 	return tp;
diff --git a/arch/mips64/bits/syscall.h.in b/arch/mips64/bits/syscall.h.in
index 045e8238..920b4358 100644
--- a/arch/mips64/bits/syscall.h.in
+++ b/arch/mips64/bits/syscall.h.in
@@ -342,4 +342,5 @@
 #define __NR_openat2		5437
 #define __NR_pidfd_getfd	5438
 #define __NR_faccessat2		5439
+#define __NR_process_madvise	5440

diff --git a/arch/mipsn32/bits/syscall.h.in b/arch/mipsn32/bits/syscall.h.in
index 5b322558..e6dad688 100644
--- a/arch/mipsn32/bits/syscall.h.in
+++ b/arch/mipsn32/bits/syscall.h.in
@@ -366,4 +366,5 @@
 #define __NR_openat2		6437
 #define __NR_pidfd_getfd	6438
 #define __NR_faccessat2		6439
+#define __NR_process_madvise	6440

diff --git a/arch/or1k/bits/syscall.h.in b/arch/or1k/bits/syscall.h.in
index b3603891..463ee901 100644
--- a/arch/or1k/bits/syscall.h.in
+++ b/arch/or1k/bits/syscall.h.in
@@ -315,4 +315,5 @@
 #define __NR_openat2		437
 #define __NR_pidfd_getfd	438
 #define __NR_faccessat2		439
+#define __NR_process_madvise	440

diff --git a/arch/powerpc/bits/fenv.h b/arch/powerpc/bits/fenv.h
index c5a3e5c5..5b15c69a 100644
--- a/arch/powerpc/bits/fenv.h
+++ b/arch/powerpc/bits/fenv.h
@@ -1,4 +1,4 @@
-#ifdef _SOFT_FLOAT
+#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__)
 #define FE_ALL_EXCEPT 0
 #define FE_TONEAREST  0
 #else
diff --git a/arch/powerpc/bits/shm.h b/arch/powerpc/bits/shm.h
index fb1d4020..7f1ca17e 100644
--- a/arch/powerpc/bits/shm.h
+++ b/arch/powerpc/bits/shm.h
@@ -8,11 +8,11 @@ struct shmid_ds {
 	unsigned long __shm_dtime_lo;
 	unsigned long __shm_ctime_hi;
 	unsigned long __shm_ctime_lo;
+	unsigned long __pad1;
 	size_t shm_segsz;
 	pid_t shm_cpid;
 	pid_t shm_lpid;
 	unsigned long shm_nattch;
-	unsigned long __pad1;
 	unsigned long __pad2;
 	time_t shm_atime;
 	time_t shm_dtime;
diff --git a/arch/powerpc/bits/syscall.h.in b/arch/powerpc/bits/syscall.h.in
index 5c6fae3e..db4d0ca4 100644
--- a/arch/powerpc/bits/syscall.h.in
+++ b/arch/powerpc/bits/syscall.h.in
@@ -419,4 +419,5 @@
 #define __NR_openat2		437
 #define __NR_pidfd_getfd	438
 #define __NR_faccessat2		439
+#define __NR_process_madvise	440

diff --git a/arch/powerpc/reloc.h b/arch/powerpc/reloc.h
index 527b6b7c..fdfbf827 100644
--- a/arch/powerpc/reloc.h
+++ b/arch/powerpc/reloc.h
@@ -1,4 +1,4 @@
-#ifdef _SOFT_FLOAT
+#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__)
 #define FP_SUFFIX "-sf"
 #else
 #define FP_SUFFIX ""
diff --git a/arch/powerpc64/bits/syscall.h.in b/arch/powerpc64/bits/syscall.h.in
index edf73d3d..a128890b 100644
--- a/arch/powerpc64/bits/syscall.h.in
+++ b/arch/powerpc64/bits/syscall.h.in
@@ -391,4 +391,5 @@
 #define __NR_openat2		437
 #define __NR_pidfd_getfd	438
 #define __NR_faccessat2		439
+#define __NR_process_madvise	440

diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in
index 5def016b..39c0d650 100644
--- a/arch/riscv64/bits/syscall.h.in
+++ b/arch/riscv64/bits/syscall.h.in
@@ -76,7 +76,7 @@
 #define __NR_splice 76
 #define __NR_tee 77
 #define __NR_readlinkat 78
-#define __NR_fstatat 79
+#define __NR_newfstatat 79
 #define __NR_fstat 80
 #define __NR_sync 81
 #define __NR_fsync 82
@@ -293,6 +293,7 @@
 #define __NR_openat2		437
 #define __NR_pidfd_getfd	438
 #define __NR_faccessat2		439
+#define __NR_process_madvise	440

 #define __NR_sysriscv __NR_arch_specific_syscall
 #define __NR_riscv_flush_icache (__NR_sysriscv + 15)
diff --git a/arch/riscv64/bits/user.h b/arch/riscv64/bits/user.h
index 2da743ea..0d37de0b 100644
--- a/arch/riscv64/bits/user.h
+++ b/arch/riscv64/bits/user.h
@@ -1,5 +1,6 @@
 #include <signal.h>

 #define ELF_NGREG 32
+#define ELF_NFPREG 33
 typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG];
 typedef union __riscv_mc_fp_state elf_fpregset_t;
diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in
index fb2e60e3..9c8d984e 100644
--- a/arch/s390x/bits/syscall.h.in
+++ b/arch/s390x/bits/syscall.h.in
@@ -356,4 +356,5 @@
 #define __NR_openat2		437
 #define __NR_pidfd_getfd	438
 #define __NR_faccessat2		439
+#define __NR_process_madvise	440

diff --git a/arch/sh/bits/syscall.h.in b/arch/sh/bits/syscall.h.in
index 158afc09..17dd7e07 100644
--- a/arch/sh/bits/syscall.h.in
+++ b/arch/sh/bits/syscall.h.in
@@ -403,4 +403,5 @@
 #define __NR_openat2		437
 #define __NR_pidfd_getfd	438
 #define __NR_faccessat2		439
+#define __NR_process_madvise	440

diff --git a/arch/x32/bits/syscall.h.in b/arch/x32/bits/syscall.h.in
index cfd9856f..5361442e 100644
--- a/arch/x32/bits/syscall.h.in
+++ b/arch/x32/bits/syscall.h.in
@@ -302,6 +302,7 @@
 #define __NR_openat2		(0x40000000 + 437)
 #define __NR_pidfd_getfd	(0x40000000 + 438)
 #define __NR_faccessat2		(0x40000000 + 439)
+#define __NR_process_madvise	(0x40000000 + 440)

 #define __NR_rt_sigaction (0x40000000 + 512)
diff --git a/arch/x86_64/bits/syscall.h.in b/arch/x86_64/bits/syscall.h.in
index a6117951..e943883d 100644
--- a/arch/x86_64/bits/syscall.h.in
+++ b/arch/x86_64/bits/syscall.h.in
@@ -349,4 +349,5 @@
 #define __NR_openat2		437
 #define __NR_pidfd_getfd	438
 #define __NR_faccessat2		439
+#define __NR_process_madvise	440

diff --git a/configure b/configure
index a5231a0e..ca5cbc0b 100755
--- a/configure
+++ b/configure
@@ -409,7 +409,7 @@ test "$debug" = yes && CFLAGS_AUTO=-g
 #
 printf "checking whether we should preprocess assembly to add debugging information... "
 if fnmatch '-g*|*\ -g*' "$CFLAGS_AUTO $CFLAGS" &&
-   test -f "tools/add-cfi.$ARCH.awk" &&
+   test -f "$srcdir/tools/add-cfi.$ARCH.awk" &&
    printf ".file 1 \"srcfile.s\"\n.line 1\n.cfi_startproc\n.cfi_endproc" | $CC -g -x assembler -c -o /dev/null 2>/dev/null -
 then
   ADD_CFI=yes
@@ -671,9 +671,7 @@ trycppif __mips_soft_float "$t" && SUBARCH=${SUBARCH}-sf
 fi

 if test "$ARCH" = "powerpc" ; then
-trycppif "__NO_FPRS__ && !_SOFT_FLOAT" "$t" && fail \
-  "$0: error: compiler's floating point configuration is unsupported"
-trycppif _SOFT_FLOAT "$t" && SUBARCH=${SUBARCH}-sf
+trycppif "_SOFT_FLOAT || __NO_FPRS__" "$t" && SUBARCH=${SUBARCH}-sf
 printf "checking whether compiler can use 'd' constraint in asm... "
 echo 'double f(double x) { __asm__ ("fabs %0, %1" : "=d"(x) : "d"(x)); return x; }' > "$tmpc"
 if $CC $CFLAGS_C99FSE $CPPFLAGS $CFLAGS -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
diff --git a/include/ctype.h b/include/ctype.h
index 7936536f..32bcef4d 100644
--- a/include/ctype.h
+++ b/include/ctype.h
@@ -64,7 +64,9 @@ int   isascii(int);
 int   toascii(int);
 #define _tolower(a) ((a)|0x20)
 #define _toupper(a) ((a)&0x5f)
+#ifndef __cplusplus
 #define isascii(a) (0 ? isascii(a) : (unsigned)(a) < 128)
+#endif

 #endif

diff --git a/include/elf.h b/include/elf.h
index b5e7befb..5170f3e2 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -686,6 +686,7 @@ typedef struct {
 #define NT_ARM_PAC_MASK	0x406
 #define NT_ARM_PACA_KEYS	0x407
 #define NT_ARM_PACG_KEYS	0x408
+#define NT_ARM_TAGGED_ADDR_CTRL	0x409
 #define NT_METAG_CBUF	0x500
 #define NT_METAG_RPIPE	0x501
 #define NT_METAG_TLS	0x502
diff --git a/include/locale.h b/include/locale.h
index ce384381..11106fea 100644
--- a/include/locale.h
+++ b/include/locale.h
@@ -7,7 +7,9 @@ extern "C" {

 #include <features.h>

-#ifdef __cplusplus
+#if __cplusplus >= 201103L
+#define NULL nullptr
+#elif defined(__cplusplus)
 #define NULL 0L
 #else
 #define NULL ((void*)0)
diff --git a/include/pthread.h b/include/pthread.h
index 0492f26a..89fd9ff7 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -221,6 +221,7 @@ int pthread_getaffinity_np(pthread_t, size_t, struct cpu_set_t *);
 int pthread_setaffinity_np(pthread_t, size_t, const struct cpu_set_t *);
 int pthread_getattr_np(pthread_t, pthread_attr_t *);
 int pthread_setname_np(pthread_t, const char *);
+int pthread_getname_np(pthread_t, char *, size_t);
 int pthread_getattr_default_np(pthread_attr_t *);
 int pthread_setattr_default_np(const pthread_attr_t *);
 int pthread_tryjoin_np(pthread_t, void **);
diff --git a/include/setjmp.h b/include/setjmp.h
index 2d43abf8..1976af23 100644
--- a/include/setjmp.h
+++ b/include/setjmp.h
@@ -15,25 +15,33 @@ typedef struct __jmp_buf_tag {
 	unsigned long __ss[128/sizeof(long)];
 } jmp_buf[1];

+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
+#define __setjmp_attr __attribute__((__returns_twice__))
+#else
+#define __setjmp_attr
+#endif
+
 #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
  || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
  || defined(_BSD_SOURCE)
 typedef jmp_buf sigjmp_buf;
-int sigsetjmp (sigjmp_buf, int);
+int sigsetjmp (sigjmp_buf, int) __setjmp_attr;
 _Noreturn void siglongjmp (sigjmp_buf, int);
 #endif

 #if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
  || defined(_BSD_SOURCE)
-int _setjmp (jmp_buf);
+int _setjmp (jmp_buf) __setjmp_attr;
 _Noreturn void _longjmp (jmp_buf, int);
 #endif

-int setjmp (jmp_buf);
+int setjmp (jmp_buf) __setjmp_attr;
 _Noreturn void longjmp (jmp_buf, int);

 #define setjmp setjmp

+#undef __setjmp_attr
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/signal.h b/include/signal.h
index 9ed929e4..f270a594 100644
--- a/include/signal.h
+++ b/include/signal.h
@@ -75,6 +75,8 @@ typedef struct sigaltstack stack_t;
 #define SEGV_ACCERR 2
 #define SEGV_BNDERR 3
 #define SEGV_PKUERR 4
+#define SEGV_MTEAERR 8
+#define SEGV_MTESERR 9

 #define BUS_ADRALN 1
 #define BUS_ADRERR 2
diff --git a/include/stdc-predef.h b/include/stdc-predef.h
index f8cd4b89..af1a2799 100644
--- a/include/stdc-predef.h
+++ b/include/stdc-predef.h
@@ -7,4 +7,7 @@
 #define __STDC_IEC_559__ 1
 #endif

+#define __STDC_UTF_16__ 1
+#define __STDC_UTF_32__ 1
+
 #endif
diff --git a/include/stddef.h b/include/stddef.h
index bd753853..f25b8639 100644
--- a/include/stddef.h
+++ b/include/stddef.h
@@ -1,7 +1,9 @@
 #ifndef _STDDEF_H
 #define _STDDEF_H

-#ifdef __cplusplus
+#if __cplusplus >= 201103L
+#define NULL nullptr
+#elif defined(__cplusplus)
 #define NULL 0L
 #else
 #define NULL ((void*)0)
diff --git a/include/stdio.h b/include/stdio.h
index 3604198c..d1ed01f0 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -25,7 +25,9 @@ extern "C" {

 #include <bits/alltypes.h>

-#ifdef __cplusplus
+#if __cplusplus >= 201103L
+#define NULL nullptr
+#elif defined(__cplusplus)
 #define NULL 0L
 #else
 #define NULL ((void*)0)
diff --git a/include/stdlib.h b/include/stdlib.h
index b54a051f..b507ca33 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -7,7 +7,9 @@ extern "C" {

 #include <features.h>

-#ifdef __cplusplus
+#if __cplusplus >= 201103L
+#define NULL nullptr
+#elif defined(__cplusplus)
 #define NULL 0L
 #else
 #define NULL ((void*)0)
@@ -146,6 +148,7 @@ int clearenv(void);
 #define WCOREDUMP(s) ((s) & 0x80)
 #define WIFCONTINUED(s) ((s) == 0xffff)
 void *reallocarray (void *, size_t, size_t);
+void qsort_r (void *, size_t, size_t, int (*)(const void *, const void *, void *), void *);
 #endif

 #ifdef _GNU_SOURCE
diff --git a/include/string.h b/include/string.h
index 795a2abc..43ad0942 100644
--- a/include/string.h
+++ b/include/string.h
@@ -7,7 +7,9 @@ extern "C" {

 #include <features.h>

-#ifdef __cplusplus
+#if __cplusplus >= 201103L
+#define NULL nullptr
+#elif defined(__cplusplus)
 #define NULL 0L
 #else
 #define NULL ((void*)0)
diff --git a/include/sys/membarrier.h b/include/sys/membarrier.h
index 10cb3108..11193eda 100644
--- a/include/sys/membarrier.h
+++ b/include/sys/membarrier.h
@@ -9,9 +9,13 @@
 #define MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED 16
 #define MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE 32
 #define MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE 64
+#define MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ 128
+#define MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ 256

 #define MEMBARRIER_CMD_SHARED MEMBARRIER_CMD_GLOBAL

+#define MEMBARRIER_CMD_FLAG_CPU 1
+
 int membarrier(int, int);

 #endif
diff --git a/include/sys/mman.h b/include/sys/mman.h
index 4d603e91..80a3baae 100644
--- a/include/sys/mman.h
+++ b/include/sys/mman.h
@@ -40,6 +40,7 @@ extern "C" {

 #define MAP_HUGE_SHIFT 26
 #define MAP_HUGE_MASK  0x3f
+#define MAP_HUGE_16KB  (14 << 26)
 #define MAP_HUGE_64KB  (16 << 26)
 #define MAP_HUGE_512KB (19 << 26)
 #define MAP_HUGE_1MB   (20 << 26)
diff --git a/include/sys/mount.h b/include/sys/mount.h
index 57a89c09..09bd6e9d 100644
--- a/include/sys/mount.h
+++ b/include/sys/mount.h
@@ -31,6 +31,7 @@ extern "C" {
 #define MS_REMOUNT     32
 #define MS_MANDLOCK    64
 #define MS_DIRSYNC     128
+#define MS_NOSYMFOLLOW 256
 #define MS_NOATIME     1024
 #define MS_NODIRATIME  2048
 #define MS_BIND        4096
diff --git a/include/sys/prctl.h b/include/sys/prctl.h
index 4b9fcc05..4ba73f42 100644
--- a/include/sys/prctl.h
+++ b/include/sys/prctl.h
@@ -157,6 +157,13 @@ struct prctl_mm_map {
 #define PR_SET_TAGGED_ADDR_CTRL 55
 #define PR_GET_TAGGED_ADDR_CTRL 56
 #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
+#define PR_MTE_TCF_SHIFT 1
+#define PR_MTE_TCF_NONE  (0UL << 1)
+#define PR_MTE_TCF_SYNC  (1UL << 1)
+#define PR_MTE_TCF_ASYNC (2UL << 1)
+#define PR_MTE_TCF_MASK  (3UL << 1)
+#define PR_MTE_TAG_SHIFT 3
+#define PR_MTE_TAG_MASK  (0xffffUL << 3)

 #define PR_SET_IO_FLUSHER 57
 #define PR_GET_IO_FLUSHER 58
diff --git a/include/time.h b/include/time.h
index 5494df18..3d948372 100644
--- a/include/time.h
+++ b/include/time.h
@@ -7,7 +7,9 @@ extern "C" {

 #include <features.h>

-#ifdef __cplusplus
+#if __cplusplus >= 201103L
+#define NULL nullptr
+#elif defined(__cplusplus)
 #define NULL 0L
 #else
 #define NULL ((void*)0)
diff --git a/include/unistd.h b/include/unistd.h
index 13064026..212263a7 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -14,8 +14,12 @@ extern "C" {
 #define SEEK_SET 0
 #define SEEK_CUR 1
 #define SEEK_END 2
+#define SEEK_DATA 3
+#define SEEK_HOLE 4

-#ifdef __cplusplus
+#if __cplusplus >= 201103L
+#define NULL nullptr
+#elif defined(__cplusplus)
 #define NULL 0L
 #else
 #define NULL ((void*)0)
diff --git a/include/wchar.h b/include/wchar.h
index 88eb55b1..ed5d774d 100644
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -38,7 +38,9 @@ extern "C" {
 #define WCHAR_MIN (-1-0x7fffffff+L'\0')
 #endif

-#ifdef __cplusplus
+#if __cplusplus >= 201103L
+#define NULL nullptr
+#elif defined(__cplusplus)
 #define NULL 0L
 #else
 #define NULL ((void*)0)
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 6b868c84..5b9c8be4 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -579,6 +579,7 @@ static void *mmap_fixed(void *p, size_t n, int prot, int flags, int fd, off_t of
 {
 	static int no_map_fixed;
 	char *q;
+	if (!n) return p;
 	if (!no_map_fixed) {
 		q = mmap(p, n, prot, flags|MAP_FIXED, fd, off);
 		if (!DL_NOMMU_SUPPORT || q != MAP_FAILED || errno != EINVAL)
@@ -1830,7 +1831,7 @@ void __dls3(size_t *sp, size_t *auxv)
 			dprintf(2, "%s: cannot load %s: %s\n", ldname, argv[0], strerror(errno));
 			_exit(1);
 		}
-		Ehdr *ehdr = (void *)map_library(fd, &app);
+		Ehdr *ehdr = map_library(fd, &app);
 		if (!ehdr) {
 			dprintf(2, "%s: %s: Not a valid dynamic program\n", ldname, argv[0]);
 			_exit(1);
@@ -2330,7 +2331,8 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void
 		info.dlpi_adds      = gencnt;
 		info.dlpi_subs      = 0;
 		info.dlpi_tls_modid = current->tls_id;
-		info.dlpi_tls_data  = current->tls.image;
+		info.dlpi_tls_data = !current->tls_id ? 0 :
+			__tls_get_addr((tls_mod_off_t[]){current->tls_id,0});

 		ret = (callback)(&info, sizeof (info), data);

diff --git a/src/complex/cproj.c b/src/complex/cproj.c
index 9ae1e17c..d2b8f5a9 100644
--- a/src/complex/cproj.c
+++ b/src/complex/cproj.c
@@ -3,6 +3,6 @@
 double complex cproj(double complex z)
 {
 	if (isinf(creal(z)) || isinf(cimag(z)))
-		return CMPLX(INFINITY, copysign(0.0, creal(z)));
+		return CMPLX(INFINITY, copysign(0.0, cimag(z)));
 	return z;
 }
diff --git a/src/complex/cprojf.c b/src/complex/cprojf.c
index 03fab339..15a874bb 100644
--- a/src/complex/cprojf.c
+++ b/src/complex/cprojf.c
@@ -3,6 +3,6 @@
 float complex cprojf(float complex z)
 {
 	if (isinf(crealf(z)) || isinf(cimagf(z)))
-		return CMPLXF(INFINITY, copysignf(0.0, crealf(z)));
+		return CMPLXF(INFINITY, copysignf(0.0, cimagf(z)));
 	return z;
 }
diff --git a/src/complex/cprojl.c b/src/complex/cprojl.c
index 38a494c5..531ffa1c 100644
--- a/src/complex/cprojl.c
+++ b/src/complex/cprojl.c
@@ -9,7 +9,7 @@ long double complex cprojl(long double complex z)
 long double complex cprojl(long double complex z)
 {
 	if (isinf(creall(z)) || isinf(cimagl(z)))
-		return CMPLXL(INFINITY, copysignl(0.0, creall(z)));
+		return CMPLXL(INFINITY, copysignl(0.0, cimagl(z)));
 	return z;
 }
 #endif
diff --git a/src/ctype/nonspacing.h b/src/ctype/nonspacing.h
index 5d05a3d1..7746f3b6 100644
--- a/src/ctype/nonspacing.h
+++ b/src/ctype/nonspacing.h
@@ -1,23 +1,23 @@
-16,16,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,16,16,32,16,16,16,33,34,35,
-36,37,38,39,16,16,40,16,16,16,16,16,16,16,16,16,16,16,41,42,16,16,43,16,16,16,
+16,16,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,16,33,16,16,16,34,35,36,
+37,38,39,40,16,16,41,16,16,16,16,16,16,16,16,16,16,16,42,43,16,16,44,16,16,16,
 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,44,16,45,46,47,48,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,45,16,46,47,48,49,16,16,16,16,16,16,16,16,16,16,
 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,50,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,51,16,16,52,
+53,16,54,55,56,16,16,16,16,16,16,57,16,16,58,16,59,60,61,62,63,64,65,66,67,68,
+69,70,16,71,72,73,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,74,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,49,16,16,50,
-51,16,52,53,54,16,16,16,16,16,16,55,16,16,56,16,57,58,59,60,61,62,63,64,65,66,
-67,68,16,69,70,71,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,72,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,75,76,16,16,16,77,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,73,74,16,16,16,75,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,76,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,77,78,16,16,16,16,16,16,16,79,16,16,16,16,16,80,81,82,16,16,16,16,16,83,
-84,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,78,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,79,80,16,16,16,16,16,16,16,81,16,16,16,16,16,82,83,84,16,16,16,16,16,85,
+86,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
 16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,
 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
@@ -35,55 +35,57 @@
 242,7,128,127,0,0,0,0,0,0,0,0,0,0,0,0,242,31,0,63,0,0,0,0,0,0,0,0,0,3,0,0,160,
 2,0,0,0,0,0,0,254,127,223,224,255,254,255,255,255,31,64,0,0,0,0,0,0,0,0,0,0,0,
 0,224,253,102,0,0,0,195,1,0,30,0,100,32,0,32,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,
-0,0,28,0,0,0,12,0,0,0,12,0,0,0,0,0,0,0,176,63,64,254,15,32,0,0,0,0,0,120,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,135,1,4,14,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,9,0,0,0,0,0,0,64,127,
-229,31,248,159,0,0,0,0,0,0,255,127,0,0,0,0,0,0,0,0,15,0,0,0,0,0,208,23,4,0,0,
-0,0,248,15,0,3,0,0,0,60,59,0,0,0,0,0,0,64,163,3,0,0,0,0,0,0,240,207,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,255,253,33,16,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,
+0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,28,0,0,0,28,0,0,0,12,0,0,0,12,0,0,0,0,0,0,0,176,63,64,254,
+15,32,0,0,0,0,0,120,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,2,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,135,1,4,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+128,9,0,0,0,0,0,0,64,127,229,31,248,159,0,0,0,0,0,0,255,127,0,0,0,0,0,0,0,0,
+15,0,0,0,0,0,208,23,4,0,0,0,0,248,15,0,3,0,0,0,60,59,0,0,0,0,0,0,64,163,3,0,0,
+0,0,0,0,240,207,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,255,253,33,16,
+3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,
 251,0,248,0,0,0,124,0,0,0,0,0,0,223,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,
 255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,0,0,0,
 0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,
 0,60,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 0,0,0,128,247,63,0,0,0,192,0,0,0,0,0,0,0,0,0,0,3,0,68,8,0,0,96,0,0,0,0,0,0,0,
 0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,255,255,3,128,0,0,0,0,192,63,0,0,128,255,3,0,
-0,0,0,0,7,0,0,0,0,0,200,51,0,0,0,0,32,0,0,0,0,0,0,0,0,126,102,0,8,16,0,0,0,0,
-0,16,0,0,0,0,0,0,157,193,2,0,0,0,0,48,64,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,33,0,0,0,0,0,64,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,255,255,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,110,240,0,0,0,0,0,135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,
-0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,192,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,255,
-127,0,0,0,0,0,0,128,3,0,0,0,0,0,120,38,0,32,0,0,0,0,0,0,7,0,0,0,128,239,31,0,
-0,0,0,0,0,0,8,0,3,0,0,0,0,0,192,127,0,30,0,0,0,0,0,0,0,0,0,0,0,128,211,64,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,248,7,0,0,3,0,0,0,0,0,0,24,1,0,0,0,192,
-31,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,92,0,0,64,0,0,0,0,0,
-0,0,0,0,0,248,133,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,60,176,1,0,0,48,0,0,0,
-0,0,0,0,0,0,0,248,167,1,0,0,0,0,0,0,0,0,0,0,0,0,40,191,0,0,0,0,0,0,0,0,0,0,0,
-0,224,188,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-128,255,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,12,1,0,0,0,254,7,0,0,0,0,248,121,128,0,
-126,14,0,0,0,0,0,252,127,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,191,0,0,0,
-0,0,0,0,0,0,0,252,255,255,252,109,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,126,180,191,0,
-0,0,0,0,0,0,0,0,163,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,
-0,0,0,0,0,0,0,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,0,0,0,0,127,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,
-0,128,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,15,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,248,255,231,15,0,0,0,60,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,255,255,255,255,255,255,127,248,255,255,255,255,255,31,32,0,16,0,0,248,
-254,255,0,0,0,0,0,0,0,0,0,
-0,127,255,255,249,219,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,240,7,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,7,0,0,0,0,0,200,51,0,0,0,0,32,0,0,
+0,0,0,0,0,0,126,102,0,8,16,0,0,0,0,0,16,0,0,0,0,0,0,157,193,2,0,0,0,0,48,64,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,33,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,0,0,0,
+64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,255,
+255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,1,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,110,240,0,
+0,0,0,0,135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,0,0,0,240,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,255,1,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,255,127,0,0,0,0,0,0,128,
+3,0,0,0,0,0,120,38,0,32,0,0,0,0,0,0,7,0,0,0,128,239,31,0,0,0,0,0,0,0,8,0,3,0,
+0,0,0,0,192,127,0,30,0,0,0,0,0,0,0,0,0,0,0,128,211,64,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,128,248,7,0,0,3,0,0,0,0,0,0,24,1,0,0,0,192,31,31,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,255,92,0,0,64,0,0,0,0,0,0,0,0,0,0,248,133,13,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60,176,1,0,0,48,0,0,0,0,0,0,0,0,0,0,
+248,167,1,0,0,0,0,0,0,0,0,0,0,0,0,40,191,0,0,0,0,0,0,0,0,0,0,0,0,224,188,15,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,255,6,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,240,12,1,0,0,0,254,7,0,0,0,0,248,121,128,0,126,14,0,0,0,0,0,252,
+127,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,191,0,0,0,0,0,0,0,0,0,0,252,255,
+255,252,109,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,126,180,191,0,0,0,0,0,0,0,0,0,163,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,255,
+1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,128,7,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,15,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,248,255,231,15,0,0,0,60,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,
+255,255,255,255,127,248,255,255,255,255,255,31,32,0,16,0,0,248,254,255,0,0,0,
+0,0,0,0,0,0,0,127,255,255,249,219,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,240,7,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c
index 8fbe5262..c5b277bd 100644
--- a/src/env/__libc_start_main.c
+++ b/src/env/__libc_start_main.c
@@ -69,7 +69,8 @@ weak_alias(libc_start_init, __libc_start_init);
 typedef int lsm2_fn(int (*)(int,char **,char **), int, char **);
 static lsm2_fn libc_start_main_stage2;

-int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv)
+int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv,
+	void (*init_dummy)(), void(*fini_dummy)(), void(*ldso_dummy)())
 {
 	char **envp = argv+argc+1;

diff --git a/src/errno/__strerror.h b/src/errno/__strerror.h
index 2d992da5..14925907 100644
--- a/src/errno/__strerror.h
+++ b/src/errno/__strerror.h
@@ -102,3 +102,7 @@ E(EDQUOT,       "Quota exceeded")
 E(ENOMEDIUM,    "No medium found")
 E(EMEDIUMTYPE,  "Wrong medium type")
 E(EMULTIHOP,    "Multihop attempted")
+E(ENOKEY,       "Required key not available")
+E(EKEYEXPIRED,  "Key has expired")
+E(EKEYREVOKED,  "Key has been revoked")
+E(EKEYREJECTED, "Key was rejected by service")
diff --git a/src/fenv/powerpc/fenv-sf.c b/src/fenv/powerpc/fenv-sf.c
index 85bef40f..d4248f26 100644
--- a/src/fenv/powerpc/fenv-sf.c
+++ b/src/fenv/powerpc/fenv-sf.c
@@ -1,3 +1,3 @@
-#ifdef _SOFT_FLOAT
+#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__)
 #include "../fenv.c"
 #endif
diff --git a/src/fenv/powerpc/fenv.S b/src/fenv/powerpc/fenv.S
index 22cea216..55055d0b 100644
--- a/src/fenv/powerpc/fenv.S
+++ b/src/fenv/powerpc/fenv.S
@@ -1,4 +1,4 @@
-#ifndef _SOFT_FLOAT
+#if !defined(_SOFT_FLOAT) && !defined(__NO_FPRS__)
 .global feclearexcept
 .type feclearexcept,@function
 feclearexcept:
diff --git a/src/include/stdlib.h b/src/include/stdlib.h
index e9da2015..812b04de 100644
--- a/src/include/stdlib.h
+++ b/src/include/stdlib.h
@@ -8,6 +8,7 @@ hidden void __env_rm_add(char *, char *);
 hidden int __mkostemps(char *, int, int);
 hidden int __ptsname_r(int, char *, size_t);
 hidden char *__randname(char *);
+hidden void __qsort_r (void *, size_t, size_t, int (*)(const void *, const void *, void *), void *);

 hidden void *__libc_malloc(size_t);
 hidden void *__libc_malloc_impl(size_t);
diff --git a/src/ldso/dl_iterate_phdr.c b/src/ldso/dl_iterate_phdr.c
index 86c87ef8..9546dd36 100644
--- a/src/ldso/dl_iterate_phdr.c
+++ b/src/ldso/dl_iterate_phdr.c
@@ -1,5 +1,6 @@
 #include <elf.h>
 #include <link.h>
+#include "pthread_impl.h"
 #include "libc.h"

 #define AUX_CNT 38
@@ -35,7 +36,7 @@ static int static_dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size
 	info.dlpi_subs  = 0;
 	if (tls_phdr) {
 		info.dlpi_tls_modid = 1;
-		info.dlpi_tls_data = (void *)(base + tls_phdr->p_vaddr);
+		info.dlpi_tls_data = __tls_get_addr((tls_mod_off_t[]){1,0});
 	} else {
 		info.dlpi_tls_modid = 0;
 		info.dlpi_tls_data = 0;
diff --git a/src/legacy/cuserid.c b/src/legacy/cuserid.c
index 4e78798d..dcaf73d4 100644
--- a/src/legacy/cuserid.c
+++ b/src/legacy/cuserid.c
@@ -2,13 +2,21 @@
 #include <pwd.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <string.h>

 char *cuserid(char *buf)
 {
+	static char usridbuf[L_cuserid];
 	struct passwd pw, *ppw;
 	long pwb[256];
-	if (getpwuid_r(geteuid(), &pw, (void *)pwb, sizeof pwb, &ppw))
-		return 0;
-	snprintf(buf, L_cuserid, "%s", pw.pw_name);
+	if (buf) *buf = 0;
+	getpwuid_r(geteuid(), &pw, (void *)pwb, sizeof pwb, &ppw);
+	if (!ppw)
+		return buf;
+	size_t len = strnlen(pw.pw_name, L_cuserid);
+	if (len == L_cuserid)
+		return buf;
+	if (!buf) buf = usridbuf;
+	memcpy(buf, pw.pw_name, len+1);
 	return buf;
 }
diff --git a/src/linux/epoll.c b/src/linux/epoll.c
index deff5b10..93baa814 100644
--- a/src/linux/epoll.c
+++ b/src/linux/epoll.c
@@ -24,9 +24,9 @@ int epoll_ctl(int fd, int op, int fd2, struct epoll_event *ev)

 int epoll_pwait(int fd, struct epoll_event *ev, int cnt, int to, const sigset_t *sigs)
 {
-	int r = __syscall(SYS_epoll_pwait, fd, ev, cnt, to, sigs, _NSIG/8);
+	int r = __syscall_cp(SYS_epoll_pwait, fd, ev, cnt, to, sigs, _NSIG/8);
 #ifdef SYS_epoll_wait
-	if (r==-ENOSYS && !sigs) r = __syscall(SYS_epoll_wait, fd, ev, cnt, to);
+	if (r==-ENOSYS && !sigs) r = __syscall_cp(SYS_epoll_wait, fd, ev, cnt, to);
 #endif
 	return __syscall_ret(r);
 }
diff --git a/src/locale/strtod_l.c b/src/locale/strtod_l.c
new file mode 100644
index 00000000..574ba148
--- /dev/null
+++ b/src/locale/strtod_l.c
@@ -0,0 +1,22 @@
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <locale.h>
+
+float strtof_l(const char *restrict s, char **restrict p, locale_t l)
+{
+	return strtof(s, p);
+}
+
+double strtod_l(const char *restrict s, char **restrict p, locale_t l)
+{
+	return strtod(s, p);
+}
+
+long double strtold_l(const char *restrict s, char **restrict p, locale_t l)
+{
+	return strtold(s, p);
+}
+
+weak_alias(strtof_l, __strtof_l);
+weak_alias(strtod_l, __strtod_l);
+weak_alias(strtold_l, __strtold_l);
diff --git a/src/malloc/free.c b/src/malloc/free.c
index f17a952c..3944f7b2 100644
--- a/src/malloc/free.c
+++ b/src/malloc/free.c
@@ -2,5 +2,5 @@

 void free(void *p)
 {
-	return __libc_free(p);
+	__libc_free(p);
 }
diff --git a/src/malloc/mallocng/aligned_alloc.c b/src/malloc/mallocng/aligned_alloc.c
index 34116896..e0862a83 100644
--- a/src/malloc/mallocng/aligned_alloc.c
+++ b/src/malloc/mallocng/aligned_alloc.c
@@ -22,6 +22,9 @@ void *aligned_alloc(size_t align, size_t len)
 	if (align <= UNIT) align = UNIT;

 	unsigned char *p = malloc(len + align - UNIT);
+	if (!p)
+		return 0;
+
 	struct meta *g = get_meta(p);
 	int idx = get_slot_index(p);
 	size_t stride = get_stride(g);
diff --git a/src/malloc/mallocng/free.c b/src/malloc/mallocng/free.c
index 40745f97..418a085c 100644
--- a/src/malloc/mallocng/free.c
+++ b/src/malloc/mallocng/free.c
@@ -119,7 +119,11 @@ void free(void *p)
 	if (((uintptr_t)(start-1) ^ (uintptr_t)end) >= 2*PGSZ && g->last_idx) {
 		unsigned char *base = start + (-(uintptr_t)start & (PGSZ-1));
 		size_t len = (end-base) & -PGSZ;
-		if (len) madvise(base, len, MADV_FREE);
+		if (len) {
+			int e = errno;
+			madvise(base, len, MADV_FREE);
+			errno = e;
+		}
 	}

 	// atomic free without locking if this is neither first or last slot
@@ -139,5 +143,9 @@ void free(void *p)
 	wrlock();
 	struct mapinfo mi = nontrivial_free(g, idx);
 	unlock();
-	if (mi.len) munmap(mi.base, mi.len);
+	if (mi.len) {
+		int e = errno;
+		munmap(mi.base, mi.len);
+		errno = e;
+	}
 }
diff --git a/src/malloc/oldmalloc/malloc.c b/src/malloc/oldmalloc/malloc.c
index 53f5f959..25d00d44 100644
--- a/src/malloc/oldmalloc/malloc.c
+++ b/src/malloc/oldmalloc/malloc.c
@@ -11,7 +11,7 @@
 #include "malloc_impl.h"
 #include "fork_impl.h"

-#define malloc __libc_malloc
+#define malloc __libc_malloc_impl
 #define realloc __libc_realloc
 #define free __libc_free

@@ -481,12 +481,14 @@ void __bin_chunk(struct chunk *self)
 	if (size > RECLAIM && (size^(size-osize)) > size-osize) {
 		uintptr_t a = (uintptr_t)self + SIZE_ALIGN+PAGE_SIZE-1 & -PAGE_SIZE;
 		uintptr_t b = (uintptr_t)next - SIZE_ALIGN & -PAGE_SIZE;
+		int e = errno;
 #if 1
 		__madvise((void *)a, b-a, MADV_DONTNEED);
 #else
 		__mmap((void *)a, b-a, PROT_READ|PROT_WRITE,
 			MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
 #endif
+		errno = e;
 	}

 	unlock_bin(i);
@@ -499,7 +501,9 @@ static void unmap_chunk(struct chunk *self)
 	size_t len = CHUNK_SIZE(self) + extra;
 	/* Crash on double free */
 	if (extra & 1) a_crash();
+	int e = errno;
 	__munmap(base, len);
+	errno = e;
 }

 void free(void *p)
diff --git a/src/math/acoshf.c b/src/math/acoshf.c
index 8a4ec4d5..b773d48e 100644
--- a/src/math/acoshf.c
+++ b/src/math/acoshf.c
@@ -15,12 +15,12 @@ float acoshf(float x)
 	uint32_t a = u.i & 0x7fffffff;

 	if (a < 0x3f800000+(1<<23))
-		/* |x| < 2, invalid if x < 1 or nan */
+		/* |x| < 2, invalid if x < 1 */
 		/* up to 2ulp error in [1,1.125] */
 		return log1pf(x-1 + sqrtf((x-1)*(x-1)+2*(x-1)));
-	if (a < 0x3f800000+(12<<23))
-		/* |x| < 0x1p12 */
+	if (u.i < 0x3f800000+(12<<23))
+		/* 2 <= x < 0x1p12 */
 		return logf(2*x - 1/(x+sqrtf(x*x-1)));
-	/* x >= 0x1p12 */
+	/* x >= 0x1p12 or x <= -2 or nan */
 	return logf(x) + 0.693147180559945309417232121458176568f;
 }
diff --git a/src/math/expm1f.c b/src/math/expm1f.c
index 297e0b44..09a41afe 100644
--- a/src/math/expm1f.c
+++ b/src/math/expm1f.c
@@ -16,7 +16,6 @@
 #include "libm.h"

 static const float
-o_threshold = 8.8721679688e+01, /* 0x42b17180 */
 ln2_hi      = 6.9313812256e-01, /* 0x3f317180 */
 ln2_lo      = 9.0580006145e-06, /* 0x3717f7d1 */
 invln2      = 1.4426950216e+00, /* 0x3fb8aa3b */
@@ -41,7 +40,7 @@ float expm1f(float x)
 			return x;
 		if (sign)
 			return -1;
-		if (x > o_threshold) {
+		if (hx > 0x42b17217) { /* x > log(FLT_MAX) */
 			x *= 0x1p127f;
 			return x;
 		}
diff --git a/src/math/fmaf.c b/src/math/fmaf.c
index 80f5cd8a..7c65acf1 100644
--- a/src/math/fmaf.c
+++ b/src/math/fmaf.c
@@ -77,17 +77,16 @@ float fmaf(float x, float y, float z)
 	 * If result is inexact, and exactly halfway between two float values,
 	 * we need to adjust the low-order bit in the direction of the error.
 	 */
-#ifdef FE_TOWARDZERO
-	fesetround(FE_TOWARDZERO);
-#endif
-	volatile double vxy = xy;  /* XXX work around gcc CSE bug */
-	double adjusted_result = vxy + z;
-	fesetround(FE_TONEAREST);
-	if (result == adjusted_result) {
-		u.f = adjusted_result;
+	double err;
+	int neg = u.i >> 63;
+	if (neg == (z > xy))
+		err = xy - result + z;
+	else
+		err = z - result + xy;
+	if (neg == (err < 0))
 		u.i++;
-		adjusted_result = u.f;
-	}
-	z = adjusted_result;
+	else
+		u.i--;
+	z = u.f;
 	return z;
 }
diff --git a/src/math/powerpc/fabs.c b/src/math/powerpc/fabs.c
index 0efc21ef..9453a3aa 100644
--- a/src/math/powerpc/fabs.c
+++ b/src/math/powerpc/fabs.c
@@ -1,6 +1,6 @@
 #include <math.h>

-#if defined(_SOFT_FLOAT) || defined(BROKEN_PPC_D_ASM)
+#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) || defined(BROKEN_PPC_D_ASM)

 #include "../fabs.c"

diff --git a/src/math/powerpc/fabsf.c b/src/math/powerpc/fabsf.c
index d88b5911..2e9da588 100644
--- a/src/math/powerpc/fabsf.c
+++ b/src/math/powerpc/fabsf.c
@@ -1,6 +1,6 @@
 #include <math.h>

-#ifdef _SOFT_FLOAT
+#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__)

 #include "../fabsf.c"

diff --git a/src/math/powerpc/fma.c b/src/math/powerpc/fma.c
index 135c9903..0eb2ba1e 100644
--- a/src/math/powerpc/fma.c
+++ b/src/math/powerpc/fma.c
@@ -1,6 +1,6 @@
 #include <math.h>

-#if defined(_SOFT_FLOAT) || defined(BROKEN_PPC_D_ASM)
+#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__) || defined(BROKEN_PPC_D_ASM)

 #include "../fma.c"

diff --git a/src/math/powerpc/fmaf.c b/src/math/powerpc/fmaf.c
index a99a2a3b..dc1a749d 100644
--- a/src/math/powerpc/fmaf.c
+++ b/src/math/powerpc/fmaf.c
@@ -1,6 +1,6 @@
 #include <math.h>

-#ifdef _SOFT_FLOAT
+#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__)

 #include "../fmaf.c"

diff --git a/src/misc/ioctl.c b/src/misc/ioctl.c
index 49282811..35804f02 100644
--- a/src/misc/ioctl.c
+++ b/src/misc/ioctl.c
@@ -6,6 +6,7 @@
 #include <stddef.h>
 #include <stdint.h>
 #include <string.h>
+#include <endian.h>
 #include "syscall.h"

 #define alignof(t) offsetof(struct { char c; t x; }, x)
@@ -53,7 +54,7 @@ static const struct ioctl_compat_map compat_map[] = {
 	{ _IOWR('A', 0x23, char[136]), _IOWR('A', 0x23, char[132]), 0, WR, 1, 0 },
 	{ 0, 0, 4, WR, 1, 0 }, /* snd_pcm_sync_ptr (flags only) */
 	{ 0, 0, 32, WR, 1, OFFS(8,12,16,24,28) }, /* snd_pcm_mmap_status */
-	{ 0, 0, 8, WR, 1, OFFS(0,4) }, /* snd_pcm_mmap_control */
+	{ 0, 0, 4, WR, 1, 0 }, /* snd_pcm_mmap_control (each member) */

 	/* VIDIOC_QUERYBUF, VIDIOC_QBUF, VIDIOC_DQBUF, VIDIOC_PREPARE_BUF */
 	{ _IOWR('V',  9, new_misaligned(68)), _IOWR('V',  9, char[68]), 68, WR, 1, OFFS(20, 24) },
@@ -90,7 +91,11 @@ static void convert_ioctl_struct(const struct ioctl_compat_map *map, char *old,
 		 * if another exception appears this needs changing. */
 		convert_ioctl_struct(map+1, old, new, dir);
 		convert_ioctl_struct(map+2, old+4, new+8, dir);
-		convert_ioctl_struct(map+3, old+68, new+72, dir);
+		/* snd_pcm_mmap_control, special-cased due to kernel
+		 * type definition having been botched. */
+		int adj = BYTE_ORDER==BIG_ENDIAN ? 4 : 0;
+		convert_ioctl_struct(map+3, old+68, new+72+adj, dir);
+		convert_ioctl_struct(map+3, old+72, new+76+3*adj, dir);
 		return;
 	}
 	for (int i=0; i < map->noffs; i++) {
diff --git a/src/passwd/nscd_query.c b/src/passwd/nscd_query.c
index d38e371b..dc3406b8 100644
--- a/src/passwd/nscd_query.c
+++ b/src/passwd/nscd_query.c
@@ -40,7 +40,15 @@ retry:
 	buf[0] = NSCDVERSION;

 	fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
-	if (fd < 0) return NULL;
+	if (fd < 0) {
+		if (errno == EAFNOSUPPORT) {
+			f = fopen("/dev/null", "re");
+			if (f)
+				errno = errno_save;
+			return f;
+		}
+		return 0;
+	}

 	if(!(f = fdopen(fd, "r"))) {
 		close(fd);
diff --git a/src/process/fdop.h b/src/process/fdop.h
index 5adf1443..7cf733b2 100644
--- a/src/process/fdop.h
+++ b/src/process/fdop.h
@@ -10,3 +10,8 @@ struct fdop {
 	mode_t mode;
 	char path[];
 };
+
+#define malloc __libc_malloc
+#define calloc __libc_calloc
+#define realloc undef
+#define free __libc_free
diff --git a/src/process/posix_spawn_file_actions_addclose.c b/src/process/posix_spawn_file_actions_addclose.c
index cdda5979..0c2ef8fa 100644
--- a/src/process/posix_spawn_file_actions_addclose.c
+++ b/src/process/posix_spawn_file_actions_addclose.c
@@ -5,6 +5,7 @@

 int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, int fd)
 {
+	if (fd < 0) return EBADF;
 	struct fdop *op = malloc(sizeof *op);
 	if (!op) return ENOMEM;
 	op->cmd = FDOP_CLOSE;
diff --git a/src/process/posix_spawn_file_actions_adddup2.c b/src/process/posix_spawn_file_actions_adddup2.c
index 0367498f..addca4d4 100644
--- a/src/process/posix_spawn_file_actions_adddup2.c
+++ b/src/process/posix_spawn_file_actions_adddup2.c
@@ -5,6 +5,7 @@

 int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, int srcfd, int fd)
 {
+	if (srcfd < 0 || fd < 0) return EBADF;
 	struct fdop *op = malloc(sizeof *op);
 	if (!op) return ENOMEM;
 	op->cmd = FDOP_DUP2;
diff --git a/src/process/posix_spawn_file_actions_addfchdir.c b/src/process/posix_spawn_file_actions_addfchdir.c
index 436c683d..e89ede8c 100644
--- a/src/process/posix_spawn_file_actions_addfchdir.c
+++ b/src/process/posix_spawn_file_actions_addfchdir.c
@@ -6,6 +6,7 @@

 int posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t *fa, int fd)
 {
+	if (fd < 0) return EBADF;
 	struct fdop *op = malloc(sizeof *op);
 	if (!op) return ENOMEM;
 	op->cmd = FDOP_FCHDIR;
diff --git a/src/process/posix_spawn_file_actions_addopen.c b/src/process/posix_spawn_file_actions_addopen.c
index 368922c7..82bbcec9 100644
--- a/src/process/posix_spawn_file_actions_addopen.c
+++ b/src/process/posix_spawn_file_actions_addopen.c
@@ -6,6 +6,7 @@

 int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *restrict fa, int fd, const char *restrict path, int flags, mode_t mode)
 {
+	if (fd < 0) return EBADF;
 	struct fdop *op = malloc(sizeof *op + strlen(path) + 1);
 	if (!op) return ENOMEM;
 	op->cmd = FDOP_OPEN;
diff --git a/src/setjmp/powerpc/longjmp.S b/src/setjmp/powerpc/longjmp.S
index e598bd05..611389fe 100644
--- a/src/setjmp/powerpc/longjmp.S
+++ b/src/setjmp/powerpc/longjmp.S
@@ -37,7 +37,37 @@ longjmp:
 	lwz 29, 72(3)
 	lwz 30, 76(3)
 	lwz 31, 80(3)
-#ifndef _SOFT_FLOAT
+#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__)
+	mflr 0
+	bl 1f
+	.hidden __hwcap
+	.long __hwcap-.
+1:	mflr 4
+	lwz 5, 0(4)
+	lwzx 4, 4, 5
+	andis. 4, 4, 0x80
+	beq 1f
+	.long 0x11c35b01 /* evldd 14,88(3) */
+	.long 0x11e36301 /* ... */
+	.long 0x12036b01
+	.long 0x12237301
+	.long 0x12437b01
+	.long 0x12638301
+	.long 0x12838b01
+	.long 0x12a39301
+	.long 0x12c39b01
+	.long 0x12e3a301
+	.long 0x1303ab01
+	.long 0x1323b301
+	.long 0x1343bb01
+	.long 0x1363c301
+	.long 0x1383cb01
+	.long 0x13a3d301
+	.long 0x13c3db01
+	.long 0x13e3e301 /* evldd 31,224(3) */
+	.long 0x11a3eb01 /* evldd 13,232(3) */
+1:	mtlr 0
+#else
 	lfd 14,88(3)
 	lfd 15,96(3)
 	lfd 16,104(3)
diff --git a/src/setjmp/powerpc/setjmp.S b/src/setjmp/powerpc/setjmp.S
index cd91a207..f1fcce33 100644
--- a/src/setjmp/powerpc/setjmp.S
+++ b/src/setjmp/powerpc/setjmp.S
@@ -37,7 +37,37 @@ setjmp:
 	stw 29, 72(3)
 	stw 30, 76(3)
 	stw 31, 80(3)
-#ifndef _SOFT_FLOAT
+#if defined(_SOFT_FLOAT) || defined(__NO_FPRS__)
+	mflr 0
+	bl 1f
+	.hidden __hwcap
+	.long __hwcap-.
+1:	mflr 4
+	lwz 5, 0(4)
+	lwzx 4, 4, 5
+	andis. 4, 4, 0x80
+	beq 1f
+	.long 0x11c35b21 /* evstdd 14,88(3) */
+	.long 0x11e36321 /* ... */
+	.long 0x12036b21
+	.long 0x12237321
+	.long 0x12437b21
+	.long 0x12638321
+	.long 0x12838b21
+	.long 0x12a39321
+	.long 0x12c39b21
+	.long 0x12e3a321
+	.long 0x1303ab21
+	.long 0x1323b321
+	.long 0x1343bb21
+	.long 0x1363c321
+	.long 0x1383cb21
+	.long 0x13a3d321
+	.long 0x13c3db21
+	.long 0x13e3e321 /* evstdd 31,224(3) */
+	.long 0x11a3eb21 /* evstdd 13,232(3) */
+1:	mtlr 0
+#else
 	stfd 14,88(3)
 	stfd 15,96(3)
 	stfd 16,104(3)
diff --git a/src/signal/block.c b/src/signal/block.c
index d7f61001..cc8698f0 100644
--- a/src/signal/block.c
+++ b/src/signal/block.c
@@ -3,9 +3,9 @@
 #include <signal.h>

 static const unsigned long all_mask[] = {
-#if ULONG_MAX == 0xffffffff && _NSIG == 129
+#if ULONG_MAX == 0xffffffff && _NSIG > 65
 	-1UL, -1UL, -1UL, -1UL
-#elif ULONG_MAX == 0xffffffff
+#elif ULONG_MAX == 0xffffffff || _NSIG > 65
 	-1UL, -1UL
 #else
 	-1UL
diff --git a/src/stdio/fgetws.c b/src/stdio/fgetws.c
index b08b3049..195cb435 100644
--- a/src/stdio/fgetws.c
+++ b/src/stdio/fgetws.c
@@ -1,6 +1,5 @@
 #include "stdio_impl.h"
 #include <wchar.h>
-#include <errno.h>

 wint_t __fgetwc_unlocked(FILE *);

@@ -12,10 +11,6 @@ wchar_t *fgetws(wchar_t *restrict s, int n, FILE *restrict f)

 	FLOCK(f);

-	/* Setup a dummy errno so we can detect EILSEQ. This is
-	 * the only way to catch encoding errors in the form of a
-	 * partial character just before EOF. */
-	errno = EAGAIN;
 	for (; n; n--) {
 		wint_t c = __fgetwc_unlocked(f);
 		if (c == WEOF) break;
@@ -23,7 +18,7 @@ wchar_t *fgetws(wchar_t *restrict s, int n, FILE *restrict f)
 		if (c == '\n') break;
 	}
 	*p = 0;
-	if (ferror(f) || errno==EILSEQ) p = s;
+	if (ferror(f)) p = s;

 	FUNLOCK(f);

diff --git a/src/stdio/fseek.c b/src/stdio/fseek.c
index 439308f7..c07f7e95 100644
--- a/src/stdio/fseek.c
+++ b/src/stdio/fseek.c
@@ -1,7 +1,14 @@
 #include "stdio_impl.h"
+#include <errno.h>

 int __fseeko_unlocked(FILE *f, off_t off, int whence)
 {
+	/* Fail immediately for invalid whence argument. */
+	if (whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END) {
+		errno = EINVAL;
+		return -1;
+	}
+
 	/* Adjust relative offset for unread data in buffer, if any. */
 	if (whence == SEEK_CUR && f->rend) off -= f->rend - f->rpos;

diff --git a/src/stdio/getdelim.c b/src/stdio/getdelim.c
index d2f5b15a..df114441 100644
--- a/src/stdio/getdelim.c
+++ b/src/stdio/getdelim.c
@@ -55,9 +55,11 @@ ssize_t getdelim(char **restrict s, size_t *restrict n, int delim, FILE *restric
 			*s = tmp;
 			*n = m;
 		}
-		memcpy(*s+i, f->rpos, k);
-		f->rpos += k;
-		i += k;
+		if (k) {
+			memcpy(*s+i, f->rpos, k);
+			f->rpos += k;
+			i += k;
+		}
 		if (z) break;
 		if ((c = getc_unlocked(f)) == EOF) {
 			if (!i || !feof(f)) {
diff --git a/src/stdio/popen.c b/src/stdio/popen.c
index 92cb57ee..3ec83394 100644
--- a/src/stdio/popen.c
+++ b/src/stdio/popen.c
@@ -31,25 +31,12 @@ FILE *popen(const char *cmd, const char *mode)
 		__syscall(SYS_close, p[1]);
 		return NULL;
 	}
-	FLOCK(f);
-
-	/* If the child's end of the pipe happens to already be on the final
-	 * fd number to which it will be assigned (either 0 or 1), it must
-	 * be moved to a different fd. Otherwise, there is no safe way to
-	 * remove the close-on-exec flag in the child without also creating
-	 * a file descriptor leak race condition in the parent. */
-	if (p[1-op] == 1-op) {
-		int tmp = fcntl(1-op, F_DUPFD_CLOEXEC, 0);
-		if (tmp < 0) {
-			e = errno;
-			goto fail;
-		}
-		__syscall(SYS_close, p[1-op]);
-		p[1-op] = tmp;
-	}

 	e = ENOMEM;
 	if (!posix_spawn_file_actions_init(&fa)) {
+		for (FILE *l = *__ofl_lock(); l; l=l->next)
+			if (l->pipe_pid && posix_spawn_file_actions_addclose(&fa, l->fd))
+				goto fail;
 		if (!posix_spawn_file_actions_adddup2(&fa, p[1-op], 1-op)) {
 			if (!(e = posix_spawn(&pid, "/bin/sh", &fa, 0,
 			    (char *[]){ "sh", "-c", (char *)cmd, 0 }, __environ))) {
@@ -58,13 +45,14 @@ FILE *popen(const char *cmd, const char *mode)
 				if (!strchr(mode, 'e'))
 					fcntl(p[op], F_SETFD, 0);
 				__syscall(SYS_close, p[1-op]);
-				FUNLOCK(f);
+				__ofl_unlock();
 				return f;
 			}
 		}
+fail:
+		__ofl_unlock();
 		posix_spawn_file_actions_destroy(&fa);
 	}
-fail:
 	fclose(f);
 	__syscall(SYS_close, p[1-op]);

diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c
index da58fd31..314ddc29 100644
--- a/src/stdlib/qsort.c
+++ b/src/stdlib/qsort.c
@@ -24,6 +24,7 @@
 /* Smoothsort, an adaptive variant of Heapsort.  Memory usage: O(1).
    Run time: Worst case O(n log n), close to O(n) in the mostly-sorted case. */

+#define _BSD_SOURCE
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -31,7 +32,7 @@
 #include "atomic.h"
 #define ntz(x) a_ctz_l((x))

-typedef int (*cmpfun)(const void *, const void *);
+typedef int (*cmpfun)(const void *, const void *, void *);

 static inline int pntz(size_t p[2]) {
 	int r = ntz(p[0] - 1);
@@ -88,7 +89,7 @@ static inline void shr(size_t p[2], int n)
 	p[1] >>= n;
 }

-static void sift(unsigned char *head, size_t width, cmpfun cmp, int pshift, size_t lp[])
+static void sift(unsigned char *head, size_t width, cmpfun cmp, void *arg, int pshift, size_t lp[])
 {
 	unsigned char *rt, *lf;
 	unsigned char *ar[14 * sizeof(size_t) + 1];
@@ -99,10 +100,10 @@ static void sift(unsigned char *head, size_t width, cmpfun cmp, int pshift, size
 		rt = head - width;
 		lf = head - width - lp[pshift - 2];

-		if((*cmp)(ar[0], lf) >= 0 && (*cmp)(ar[0], rt) >= 0) {
+		if(cmp(ar[0], lf, arg) >= 0 && cmp(ar[0], rt, arg) >= 0) {
 			break;
 		}
-		if((*cmp)(lf, rt) >= 0) {
+		if(cmp(lf, rt, arg) >= 0) {
 			ar[i++] = lf;
 			head = lf;
 			pshift -= 1;
@@ -115,7 +116,7 @@ static void sift(unsigned char *head, size_t width, cmpfun cmp, int pshift, size
 	cycle(width, ar, i);
 }

-static void trinkle(unsigned char *head, size_t width, cmpfun cmp, size_t pp[2], int pshift, int trusty, size_t lp[])
+static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, size_t pp[2], int pshift, int trusty, size_t lp[])
 {
 	unsigned char *stepson,
 	              *rt, *lf;
@@ -130,13 +131,13 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, size_t pp[2],
 	ar[0] = head;
 	while(p[0] != 1 || p[1] != 0) {
 		stepson = head - lp[pshift];
-		if((*cmp)(stepson, ar[0]) <= 0) {
+		if(cmp(stepson, ar[0], arg) <= 0) {
 			break;
 		}
 		if(!trusty && pshift > 1) {
 			rt = head - width;
 			lf = head - width - lp[pshift - 2];
-			if((*cmp)(rt, stepson) >= 0 || (*cmp)(lf, stepson) >= 0) {
+			if(cmp(rt, stepson, arg) >= 0 || cmp(lf, stepson, arg) >= 0) {
 				break;
 			}
 		}
@@ -150,11 +151,11 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, size_t pp[2],
 	}
 	if(!trusty) {
 		cycle(width, ar, i);
-		sift(head, width, cmp, pshift, lp);
+		sift(head, width, cmp, arg, pshift, lp);
 	}
 }

-void qsort(void *base, size_t nel, size_t width, cmpfun cmp)
+void __qsort_r(void *base, size_t nel, size_t width, cmpfun cmp, void *arg)
 {
 	size_t lp[12*sizeof(size_t)];
 	size_t i, size = width * nel;
@@ -173,16 +174,16 @@ void qsort(void *base, size_t nel, size_t width, cmpfun cmp)

 	while(head < high) {
 		if((p[0] & 3) == 3) {
-			sift(head, width, cmp, pshift, lp);
+			sift(head, width, cmp, arg, pshift, lp);
 			shr(p, 2);
 			pshift += 2;
 		} else {
 			if(lp[pshift - 1] >= high - head) {
-				trinkle(head, width, cmp, p, pshift, 0, lp);
+				trinkle(head, width, cmp, arg, p, pshift, 0, lp);
 			} else {
-				sift(head, width, cmp, pshift, lp);
+				sift(head, width, cmp, arg, pshift, lp);
 			}
-
+
 			if(pshift == 1) {
 				shl(p, 1);
 				pshift = 0;
@@ -191,12 +192,12 @@ void qsort(void *base, size_t nel, size_t width, cmpfun cmp)
 				pshift = 1;
 			}
 		}
-
+
 		p[0] |= 1;
 		head += width;
 	}

-	trinkle(head, width, cmp, p, pshift, 0, lp);
+	trinkle(head, width, cmp, arg, p, pshift, 0, lp);

 	while(pshift != 1 || p[0] != 1 || p[1] != 0) {
 		if(pshift <= 1) {
@@ -208,11 +209,13 @@ void qsort(void *base, size_t nel, size_t width, cmpfun cmp)
 			pshift -= 2;
 			p[0] ^= 7;
 			shr(p, 1);
-			trinkle(head - lp[pshift] - width, width, cmp, p, pshift + 1, 1, lp);
+			trinkle(head - lp[pshift] - width, width, cmp, arg, p, pshift + 1, 1, lp);
 			shl(p, 1);
 			p[0] |= 1;
-			trinkle(head - width, width, cmp, p, pshift, 1, lp);
+			trinkle(head - width, width, cmp, arg, p, pshift, 1, lp);
 		}
 		head -= width;
 	}
 }
+
+weak_alias(__qsort_r, qsort_r);
diff --git a/src/stdlib/qsort_nr.c b/src/stdlib/qsort_nr.c
new file mode 100644
index 00000000..efe7ccec
--- /dev/null
+++ b/src/stdlib/qsort_nr.c
@@ -0,0 +1,14 @@
+#define _BSD_SOURCE
+#include <stdlib.h>
+
+typedef int (*cmpfun)(const void *, const void *);
+
+static int wrapper_cmp(const void *v1, const void *v2, void *cmp)
+{
+	return ((cmpfun)cmp)(v1, v2);
+}
+
+void qsort(void *base, size_t nel, size_t width, cmpfun cmp)
+{
+	__qsort_r(base, nel, width, wrapper_cmp, cmp);
+}
diff --git a/src/stdlib/strtod.c b/src/stdlib/strtod.c
index a5d0118a..39b9daad 100644
--- a/src/stdlib/strtod.c
+++ b/src/stdlib/strtod.c
@@ -28,10 +28,3 @@ long double strtold(const char *restrict s, char **restrict p)
 {
 	return strtox(s, p, 2);
 }
-
-weak_alias(strtof, strtof_l);
-weak_alias(strtod, strtod_l);
-weak_alias(strtold, strtold_l);
-weak_alias(strtof, __strtof_l);
-weak_alias(strtod, __strtod_l);
-weak_alias(strtold, __strtold_l);
diff --git a/src/thread/pthread_getname_np.c b/src/thread/pthread_getname_np.c
new file mode 100644
index 00000000..85504e45
--- /dev/null
+++ b/src/thread/pthread_getname_np.c
@@ -0,0 +1,25 @@
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/prctl.h>
+
+#include "pthread_impl.h"
+
+int pthread_getname_np(pthread_t thread, char *name, size_t len)
+{
+	int fd, cs, status = 0;
+	char f[sizeof "/proc/self/task//comm" + 3*sizeof(int)];
+
+	if (len < 16) return ERANGE;
+
+	if (thread == pthread_self())
+		return prctl(PR_GET_NAME, (unsigned long)name, 0UL, 0UL, 0UL) ? errno : 0;
+
+	snprintf(f, sizeof f, "/proc/self/task/%d/comm", thread->tid);
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+	if ((fd = open(f, O_RDONLY|O_CLOEXEC)) < 0 || (len = read(fd, name, len)) == -1) status = errno;
+	else name[len-1] = 0; /* remove trailing new line only if successful */
+	if (fd >= 0) close(fd);
+	pthread_setcancelstate(cs, 0);
+	return status;
+}
diff --git a/src/thread/pthread_setname_np.c b/src/thread/pthread_setname_np.c
index 82d35e17..fc2d2306 100644
--- a/src/thread/pthread_setname_np.c
+++ b/src/thread/pthread_setname_np.c
@@ -19,7 +19,7 @@ int pthread_setname_np(pthread_t thread, const char *name)

 	snprintf(f, sizeof f, "/proc/self/task/%d/comm", thread->tid);
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
-	if ((fd = open(f, O_WRONLY)) < 0 || write(fd, name, len) < 0) status = errno;
+	if ((fd = open(f, O_WRONLY|O_CLOEXEC)) < 0 || write(fd, name, len) < 0) status = errno;
 	if (fd >= 0) close(fd);
 	pthread_setcancelstate(cs, 0);
 	return status;
diff --git a/src/time/__tz.c b/src/time/__tz.c
index 09a6317e..c34b3eb7 100644
--- a/src/time/__tz.c
+++ b/src/time/__tz.c
@@ -4,6 +4,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/mman.h>
+#include <ctype.h>
 #include "libc.h"
 #include "lock.h"
 #include "fork_impl.h"
@@ -154,10 +155,21 @@ static void do_tzset()
 	}
 	if (old_tz) memcpy(old_tz, s, i+1);

+	int posix_form = 0;
+	if (*s != ':') {
+		p = s;
+		char dummy_name[TZNAME_MAX+1];
+		getname(dummy_name, &p);
+		if (p!=s && (*p == '+' || *p == '-' || isdigit(*p)
+		             || !strcmp(dummy_name, "UTC")
+		             || !strcmp(dummy_name, "GMT")))
+			posix_form = 1;
+	}
+
 	/* Non-suid can use an absolute tzfile pathname or a relative
 	 * pathame beginning with "."; in secure mode, only the
 	 * standard path will be searched. */
-	if (*s == ':' || ((p=strchr(s, '/')) && !memchr(s, ',', p-s))) {
+	if (!posix_form) {
 		if (*s == ':') s++;
 		if (*s == '/' || *s == '.') {
 			if (!libc.secure || !strcmp(s, "/etc/localtime"))
@@ -281,22 +293,20 @@ static size_t scan_trans(long long t, int local, size_t *alt)
 	n = (index-trans)>>scale;
 	if (a == n-1) return -1;
 	if (a == 0) {
-		x = zi_read32(trans + (a<<scale));
-		if (scale == 3) x = x<<32 | zi_read32(trans + (a<<scale) + 4);
+		x = zi_read32(trans);
+		if (scale == 3) x = x<<32 | zi_read32(trans + 4);
 		else x = (int32_t)x;
-		if (local) off = (int32_t)zi_read32(types + 6 * index[a-1]);
+		/* Find the lowest non-DST type, or 0 if none. */
+		size_t j = 0;
+		for (size_t i=abbrevs-types; i; i-=6) {
+			if (!types[i-6+4]) j = i-6;
+		}
+		if (local) off = (int32_t)zi_read32(types + j);
+		/* If t is before first transition, use the above-found type
+		 * and the index-zero (after transition) type as the alt. */
 		if (t - off < (int64_t)x) {
-			for (a=0; a<(abbrevs-types)/6; a++) {
-				if (types[6*a+4] != types[4]) break;
-			}
-			if (a == (abbrevs-types)/6) a = 0;
-			if (types[6*a+4]) {
-				*alt = a;
-				return 0;
-			} else {
-				*alt = 0;
-				return a;
-			}
+			if (alt) *alt = index[0];
+			return j/6;
 		}
 	}

repo_name: dustdfg/dragora

license: mit


code:
--- musl-1.1.19/configure~	2018-02-22 15:39:19.000000000 -0300
+++ musl-1.1.19/configure	2018-02-25 16:09:04.477036114 -0300
@@ -598,8 +598,6 @@
 # Find compiler runtime library
 test -z "$LIBCC" && tryldflag LIBCC -lgcc && tryldflag LIBCC -lgcc_eh
 test -z "$LIBCC" && tryldflag LIBCC -lcompiler_rt
-test -z "$LIBCC" && try_libcc=`$CC -print-libgcc-file-name 2>/dev/null` \
-                 && tryldflag LIBCC "$try_libcc"
 test -z "$LIBCC" && try_libcc=`$CC -print-file-name=libpcc.a 2>/dev/null` \
                  && tryldflag LIBCC "$try_libcc"
 printf "using compiler runtime libraries: %s\n" "$LIBCC"


code:
--- include/utmp.h.orig	2017-01-01 00:27:17.000000000 -0300
+++ include/utmp.h	2017-07-20 17:49:30.000000000 -0300
@@ -37,8 +37,8 @@

 int login_tty(int);

-#define _PATH_UTMP "/dev/null/utmp"
-#define _PATH_WTMP "/dev/null/wtmp"
+#define _PATH_UTMP "/var/run/utmp"
+#define _PATH_WTMP "/var/log/wtmp"

 #define UTMP_FILE _PATH_UTMP
 #define WTMP_FILE _PATH_WTMP


code:
Description: Fix sh/autoconfall.sh
Author: Helmut Grohne <helmut@subdivi.de>
Author: Adrian Bunk <bunk@debian.org>
Bug-Debian: https://bugs.debian.org/874261

--- ncftp-3.2.5.orig/sh/autoconfall.sh
+++ ncftp-3.2.5/sh/autoconfall.sh
@@ -1,13 +1,5 @@
 #!/bin/sh

-PROJECT_HOME="$HOME/src/ncftp/current"
-AUTOCONF_BIN="/usr/local/autoconf-2.13/bin"
-if [ ! -d "$PROJECT_HOME" ] ; then
-	/bin/ls -ld "$PROJECT_HOME"
-	exit 1
-fi
-cd "$PROJECT_HOME"
-
 a=`pwd`
 first=yes
 didone=no
@@ -16,7 +8,6 @@ for f in \
 	sio/configure.in \
 	Strn/configure.in \
 	libncftp/configure.in \
-	"$HOME"/src/libncftp/current/libncftp/configure.in \
 ; do
 	abs=no
 	case "$f" in
@@ -32,7 +23,7 @@ for f in \
 		is_diff=no

 		/bin/mv config.h.in config.h.in.orig 2>/dev/null
-		"$AUTOCONF_BIN"/autoheader 2>&1 | fgrep -v AC_TRY_RUN
+		autoheader2.13 2>&1 | fgrep -v AC_TRY_RUN
 		if [ ! -f config.h.in ] ; then
 			echo "* Warning: config.h.in not generated"
 			if [ -f config.h.in.orig ] ; then
@@ -51,7 +42,7 @@ for f in \
 		fi

 		/bin/mv configure configure.orig 2>/dev/null
-		"$AUTOCONF_BIN"/autoconf 2>&1 | fgrep -v AC_TRY_RUN
+		autoconf2.13 -l autoconf_local 2>&1 | fgrep -v AC_TRY_RUN
 		if [ ! -f configure ] ; then
 			echo "* Warning: configure not generated"
 			if [ -f configure.orig ] ; then


code:
Description: Fix ftbfs with GCC-10

Author: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Bug-Debian: https://bugs.debian.org/957582
Forwarded: no

---

--- ncftp-3.2.5.orig/sh_util/gpshare.c
+++ ncftp-3.2.5/sh_util/gpshare.c
@@ -28,7 +28,7 @@

 static int gIsAtty1 = 1, gIsAtty2 = 1;
 extern int gLoadedBm, gBookmarkMatchMode;
-Bookmark gBm;
+extern Bookmark gBm;

 double
 FileSize(double size, const char **uStr0, double *uMult0)


code:
Author: Bart Martens <bart.martens@advalvas.be>
Date: 2006-02-11 20:48:08 UTC
Bug-Debian: https://bugs.debian.org/352425

	fix rmdir fails on trailing slash added by tab completion

diff -ruN orig/ncftp-3.1.9/libncftp/c_rmdir.c ncftp-3.1.9/libncftp/c_rmdir.c
--- orig/ncftp-3.1.9/libncftp/c_rmdir.c	2005-01-01 22:29:02.000000000 +0100
+++ ncftp-3.1.9/libncftp/c_rmdir.c	2006-02-11 21:50:05.000000000 +0100
@@ -15,7 +15,7 @@
 {
 	FTPLineList fileList;
 	FTPLinePtr filePtr;
-	char *file;
+	char *file, *tail;
 	int onceResult, batchResult;

 	if (cip == NULL)
@@ -37,6 +37,9 @@
 			cip->errNo = kErrBadLineList;
 			break;
 		}
+		tail = file + strlen( file );
+		while( tail > file + 1 && *(--tail) == '/' )
+			*tail = '\0';
 		onceResult = FTPCmd(cip, "RMD %s", file);
 		if (onceResult < 0) {
 			batchResult = onceResult;


code:
Author: Reiner Herrmann <reiner@reiner-h.de>
Date: 2016-07-01 16:00:02 UTC
Bug-Debian: https://bugs.debian.org/829249

	make ncftp build reproducible.

diff --git a/ncftp/main.c b/ncftp/main.c
index a7fccac..b27a94e 100644
--- a/ncftp/main.c
+++ b/ncftp/main.c
@@ -62,7 +62,7 @@ static void
 Usage(void)
 {
 	FILE *fp;
-#ifdef UNAME
+#if 0
 	char s[80];
 #endif

@@ -76,7 +76,7 @@ Usage(void)
   -F     Dump a sample $HOME/.ncftp/firewall prefs file to stdout and exit.\n");

 	(void) fprintf(fp, "\nProgram version:  %s\nLibrary version:  %s\n", gVersion + 5, gLibNcFTPVersion + 5);
-#ifdef UNAME
+#if 0
 	AbbrevStr(s, UNAME, 60, 1);
 	(void) fprintf(fp, "Build system:     %s\n", s);
 #endif


code:
ncftp-352425.patch
ncftp-reproducible.patch
autoreconf.patch
fix_ftbfs.patch

path: patches/ncftp/series


code:
Submitted By:            Xi Ruoyao <xry111_AT_mengyan1223_DOT_wang>
Date:                    2020-08-22
Initial Package Version: 3.12.4
Upstream Status:         Not applicable
Origin:                  Self, adjusted for nss-3.56.
Description:             Adds auto-generated nss.pc and nss-config script, and
                         allows building without nspr in the source tree.
                         Minimum NSPR version is now read out from package,
                         instead of hardcoded value in the patch.

diff --color -uNar nss-3.55.orig/nss/config/Makefile nss-3.55/nss/config/Makefile
--- nss-3.55.orig/nss/config/Makefile	1970-01-01 08:00:00.000000000 +0800
+++ nss-3.55/nss/config/Makefile	2020-07-25 19:34:36.272982957 +0800
@@ -0,0 +1,42 @@
+CORE_DEPTH = ..
+DEPTH      = ..
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+NSS_MAJOR_VERSION = `grep "NSS_VMAJOR" ../lib/nss/nss.h | awk '{print $$3}'`
+NSS_MINOR_VERSION = `grep "NSS_VMINOR" ../lib/nss/nss.h | awk '{print $$3}'`
+NSS_PATCH_VERSION = `grep "NSS_VPATCH" ../lib/nss/nss.h | awk '{print $$3}'`
+NSS_NSPR_MINIMUM = `head -n1 ../automation/release/nspr-version.txt`
+PREFIX = /usr
+
+all: export libs
+
+export:
+	# Create the nss.pc file
+	mkdir -p $(DIST)/lib/pkgconfig
+	sed -e "s,@prefix@,$(PREFIX)," \
+	    -e "s,@exec_prefix@,\$${prefix}," \
+	    -e "s,@libdir@,\$${prefix}/lib," \
+	    -e "s,@includedir@,\$${prefix}/include/nss," \
+	    -e "s,@NSS_MAJOR_VERSION@,$(NSS_MAJOR_VERSION),g" \
+	    -e "s,@NSS_MINOR_VERSION@,$(NSS_MINOR_VERSION)," \
+	    -e "s,@NSS_PATCH_VERSION@,$(NSS_PATCH_VERSION)," \
+	    -e "s,@NSS_NSPR_MINIMUM@,$(NSS_NSPR_MINIMUM)," \
+	    nss.pc.in > nss.pc
+	chmod 0644 nss.pc
+	ln -sf ../../../../nss/config/nss.pc $(DIST)/lib/pkgconfig
+
+	# Create the nss-config script
+	mkdir -p $(DIST)/bin
+	sed -e "s,@prefix@,$(PREFIX)," \
+	    -e "s,@NSS_MAJOR_VERSION@,$(NSS_MAJOR_VERSION)," \
+	    -e "s,@NSS_MINOR_VERSION@,$(NSS_MINOR_VERSION)," \
+	    -e "s,@NSS_PATCH_VERSION@,$(NSS_PATCH_VERSION)," \
+	    nss-config.in > nss-config
+	chmod 0755 nss-config
+	ln -sf ../../../nss/config/nss-config $(DIST)/bin
+
+libs:
+
+dummy: all export libs
+
diff --color -uNar nss-3.55.orig/nss/config/nss-config.in nss-3.55/nss/config/nss-config.in
--- nss-3.55.orig/nss/config/nss-config.in	1970-01-01 08:00:00.000000000 +0800
+++ nss-3.55/nss/config/nss-config.in	2020-07-25 19:32:37.239032214 +0800
@@ -0,0 +1,153 @@
+#!/bin/sh
+
+prefix=@prefix@
+
+major_version=@NSS_MAJOR_VERSION@
+minor_version=@NSS_MINOR_VERSION@
+patch_version=@NSS_PATCH_VERSION@
+
+usage()
+{
+	cat <<EOF
+Usage: nss-config [OPTIONS] [LIBRARIES]
+Options:
+	[--prefix[=DIR]]
+	[--exec-prefix[=DIR]]
+	[--includedir[=DIR]]
+	[--libdir[=DIR]]
+	[--version]
+	[--libs]
+	[--cflags]
+Dynamic Libraries:
+	nss
+	nssutil
+	smime
+	ssl
+	softokn
+EOF
+	exit $1
+}
+
+if test $# -eq 0; then
+	usage 1 1>&2
+fi
+
+lib_nss=yes
+lib_nssutil=yes
+lib_smime=yes
+lib_ssl=yes
+lib_softokn=yes
+
+while test $# -gt 0; do
+  case "$1" in
+  -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  case $1 in
+    --prefix=*)
+      prefix=$optarg
+      ;;
+    --prefix)
+      echo_prefix=yes
+      ;;
+    --exec-prefix=*)
+      exec_prefix=$optarg
+      ;;
+    --exec-prefix)
+      echo_exec_prefix=yes
+      ;;
+    --includedir=*)
+      includedir=$optarg
+      ;;
+    --includedir)
+      echo_includedir=yes
+      ;;
+    --libdir=*)
+      libdir=$optarg
+      ;;
+    --libdir)
+      echo_libdir=yes
+      ;;
+    --version)
+      echo ${major_version}.${minor_version}.${patch_version}
+      ;;
+    --cflags)
+      echo_cflags=yes
+      ;;
+    --libs)
+      echo_libs=yes
+      ;;
+    nss)
+      lib_nss=yes
+      ;;
+    nssutil)
+      lib_nssutil=yes
+      ;;
+    smime)
+      lib_smime=yes
+      ;;
+    ssl)
+      lib_ssl=yes
+      ;;
+    softokn)
+      lib_softokn=yes
+      ;;
+    *)
+      usage 1 1>&2
+      ;;
+  esac
+  shift
+done
+
+# Set variables that may be dependent upon other variables
+if test -z "$exec_prefix"; then
+    exec_prefix=`pkg-config --variable=exec_prefix nss`
+fi
+if test -z "$includedir"; then
+    includedir=`pkg-config --variable=includedir nss`
+fi
+if test -z "$libdir"; then
+    libdir=`pkg-config --variable=libdir nss`
+fi
+
+if test "$echo_prefix" = "yes"; then
+    echo $prefix
+fi
+
+if test "$echo_exec_prefix" = "yes"; then
+    echo $exec_prefix
+fi
+
+if test "$echo_includedir" = "yes"; then
+    echo $includedir
+fi
+
+if test "$echo_libdir" = "yes"; then
+    echo $libdir
+fi
+
+if test "$echo_cflags" = "yes"; then
+    echo -I$includedir
+fi
+
+if test "$echo_libs" = "yes"; then
+      libdirs="-L$libdir"
+      if test -n "$lib_nss"; then
+	libdirs="$libdirs -lnss${major_version}"
+      fi
+      if test -n "$lib_nssutil"; then
+        libdirs="$libdirs -lnssutil${major_version}"
+      fi
+      if test -n "$lib_smime"; then
+	libdirs="$libdirs -lsmime${major_version}"
+      fi
+      if test -n "$lib_ssl"; then
+	libdirs="$libdirs -lssl${major_version}"
+      fi
+      if test -n "$lib_softokn"; then
+        libdirs="$libdirs -lsoftokn${major_version}"
+      fi
+      echo $libdirs
+fi
+
diff --color -uNar nss-3.55.orig/nss/config/nss.pc.in nss-3.55/nss/config/nss.pc.in
--- nss-3.55.orig/nss/config/nss.pc.in	1970-01-01 08:00:00.000000000 +0800
+++ nss-3.55/nss/config/nss.pc.in	2020-07-25 19:33:05.958889937 +0800
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: NSS
+Description: Network Security Services
+Version: @NSS_MAJOR_VERSION@.@NSS_MINOR_VERSION@.@NSS_PATCH_VERSION@
+Requires: nspr >= @NSS_NSPR_MINIMUM@
+Libs: -L@libdir@ -lnss@NSS_MAJOR_VERSION@ -lnssutil@NSS_MAJOR_VERSION@ -lsmime@NSS_MAJOR_VERSION@ -lssl@NSS_MAJOR_VERSION@ -lsoftokn@NSS_MAJOR_VERSION@
+Cflags: -I${includedir}
+
diff --color -uNar nss-3.55.orig/nss/Makefile nss-3.55/nss/Makefile
--- nss-3.55.orig/nss/Makefile	2020-07-24 23:10:32.000000000 +0800
+++ nss-3.55/nss/Makefile	2020-07-25 19:32:37.239032214 +0800
@@ -4,6 +4,8 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.

+default: nss_build_all
+
 #######################################################################
 # (1) Include initial platform-independent assignments (MANDATORY).   #
 #######################################################################
@@ -48,12 +50,10 @@
 #######################################################################

 nss_build_all:
-	$(MAKE) build_nspr
 	$(MAKE) all
 	$(MAKE) latest

 nss_clean_all:
-	$(MAKE) clobber_nspr
 	$(MAKE) clobber

 NSPR_CONFIG_STATUS = $(CORE_DEPTH)/../nspr/$(OBJDIR_NAME)/config.status
diff --color -uNar nss-3.55.orig/nss/manifest.mn nss-3.55/nss/manifest.mn
--- nss-3.55.orig/nss/manifest.mn	2020-07-24 23:10:32.000000000 +0800
+++ nss-3.55/nss/manifest.mn	2020-07-25 19:32:37.240032237 +0800
@@ -10,7 +10,7 @@

 RELEASE = nss

-DIRS = coreconf lib cmd cpputil gtests
+DIRS = coreconf lib cmd cpputil gtests config

 lib: coreconf
 cmd: lib


code:
diff -urNp openjade-1.3.2/grove/Makefile.sub devel/grove/Makefile.sub
--- openjade-1.3.2/grove/Makefile.sub	2002-10-20 23:47:24.000000000 +0200
+++ devel/grove/Makefile.sub	2007-07-23 15:39:23.000000000 +0200
@@ -1,4 +1,4 @@
 LTVERSION=0:1:0
 LIB=ogrove
-DEPLIBS=-lm
+DEPLIBS=-lm -lstdc++
 OBJS=Node.o LocNode.o
diff -urNp openjade-1.3.2/spgrove/Makefile.sub devel/spgrove/Makefile.sub
--- openjade-1.3.2/spgrove/Makefile.sub	2002-11-15 23:46:50.000000000 +0100
+++ devel/spgrove/Makefile.sub	2007-07-23 16:06:13.000000000 +0200
@@ -1,9 +1,10 @@
 LTVERSION=0:1:0
 LIB=ospgrove
 INCLUDE=-I$(srcdir)/../grove
-DEPLIBS=-lm -L$(TOP)/grove -L$(TOP)/grove/.libs \
+DEPLIBS=$(TOP)/grove/libogrove.la \
+       -lm -losp -L$(TOP)/grove/.libs \
 	-L$(TOP)/lib -L$(TOP)/lib/.libs \
-	$(LIB_THREADS)
+	$(LIB_THREADS) -lstdc++
 OBJS=GroveApp.o GroveBuilder.o SdNode.o
 GENSRCS=grove_inst.cxx

diff -urNp openjade-1.3.2/style/Makefile.sub devel/style/Makefile.sub
--- openjade-1.3.2/style/Makefile.sub	2003-04-18 19:18:10.000000000 +0200
+++ devel/style/Makefile.sub	2007-07-23 16:08:26.000000000 +0200
@@ -1,8 +1,8 @@
 LTVERSION=0:1:0
 LIB=ostyle
-DEPLIBS=-lm -L$(TOP)/grove -L$(TOP)/grove/.libs \
-  -L$(TOP)/lib -L$(TOP)/lib/.libs \
-  -L$(TOP)/spgrove -L$(TOP)/spgrove/.libs
+DEPLIBS=$(TOP)/grove/libogrove.la $(TOP)/spgrove/libospgrove.la \
+  -lm -losp -L$(TOP)/lib -L$(TOP)/lib/.libs -L$(TOP)/grove/.libs \
+  -L$(TOP)/spgrove -L$(TOP)/spgrove/.libs -lstdc++
 OBJS=LangObj.o \
   Collector.o \
   DssslApp.o \


code:
--- openjade-1.3.2-orig//jade/TeXFOTBuilder.cxx	2011-05-02 22:08:49.274006803 +0000
+++ openjade-1.3.2-orig//jade/TeXFOTBuilder.cxx	2011-05-02 22:14:09.849006939 +0000
@@ -88,6 +88,8 @@
       value.convertString(nic_.placement);
       }
     ExtensionFlowObj *copy() const { return new PageFloatFlowObj(*this); }
+  public:
+    PageFloatFlowObj() {}
   private:
     PageFloatNIC nic_;
     StringC name_;
@@ -101,6 +103,8 @@
       fotb.endPageFootnote();
     }
     ExtensionFlowObj *copy() const { return new PageFootnoteFlowObj(*this); }
+  public:
+    PageFootnoteFlowObj() {}
   private:
   };
   //////////////////////////////////////////////////////////////////////
--- openjade-1.3.2-orig//jade/TransformFOTBuilder.cxx	2011-05-02 22:08:49.275006803 +0000
+++ openjade-1.3.2-orig//jade/TransformFOTBuilder.cxx	2011-05-02 22:18:31.614007052 +0000
@@ -41,6 +41,7 @@
   };
   class EntityRefFlowObj : public TransformExtensionFlowObj {
   public:
+    EntityRefFlowObj() {}
     void atomic(TransformFOTBuilder &fotb, const NodePtr &) const {
       fotb.entityRef(name_);
     }
@@ -56,6 +57,7 @@
   };
   class ProcessingInstructionFlowObj : public TransformExtensionFlowObj {
   public:
+    ProcessingInstructionFlowObj() {}
     void atomic(TransformFOTBuilder &fotb, const NodePtr &) const {
       fotb.processingInstruction(data_);
     }
@@ -98,6 +100,8 @@
       }
     }
     ExtensionFlowObj *copy() const { return new EmptyElementFlowObj(*this); }
+  public:
+    EmptyElementFlowObj() {}
   private:
     ElementNIC nic_;
   };
@@ -133,6 +137,8 @@
       }
     }
     ExtensionFlowObj *copy() const { return new ElementFlowObj(*this); }
+  public:
+    ElementFlowObj() {}
   private:
     ElementNIC nic_;
   };
@@ -150,6 +156,8 @@
       value.convertString(systemId_);
     }
     ExtensionFlowObj *copy() const { return new EntityFlowObj(*this); }
+  public:
+    EntityFlowObj() {};
   private:
     StringC systemId_;
   };
@@ -174,6 +182,8 @@
       }
     }
     ExtensionFlowObj *copy() const { return new DocumentTypeFlowObj(*this); }
+  public:
+    DocumentTypeFlowObj() {}
   private:
     DocumentTypeNIC nic_;
   };


code:
Index: openjade-1.3.2/jade/Makefile.sub
===================================================================
--- openjade-1.3.2.orig/jade/Makefile.sub
+++ openjade-1.3.2/jade/Makefile.sub
@@ -4,7 +4,7 @@ OBJS=jade.o SgmlFOTBuilder.o RtfFOTBuild
 INCLUDE=-I$(srcdir)/../grove -I$(srcdir)/../spgrove -I$(srcdir)/../style
 # XLIBS=../style/libostyle.a ../spgrove/libospgrove.a ../grove/libogrove.a \
 #   ../lib/libosp.a
-XLIBS=../style/libostyle.a ../spgrove/libospgrove.a ../grove/libogrove.a $(splibdir)/libosp.a
+XLIBS=../style/libostyle.a ../grove/libogrove.a ../spgrove/libospgrove.a $(splibdir)/libosp.a
 GENSRCS=JadeMessages.h HtmlMessages.h RtfMessages.h TeXMessages.h \
  HtmlFOTBuilder_inst.cxx RtfFOTBuilder_inst.cxx  TeXFOTBuilder_inst.cxx \
  TransformFOTBuilder_inst.cxx MifMessages.h MifFOTBuilder_inst.cxx


code:
diff -u /var/tmp/portage/app-text/openjade-1.3.2-r1/work/openjade-1.3.2/jade/Makefile.sub /tmp/buffer-content-5978gFR
--- a/jade/Makefile.sub	2009-11-19 17:21:46.000000000 -0500
+++ b/jade/Makefile.sub	2009-11-19 17:23:24.000000000 -0500
@@ -4,7 +4,8 @@
 INCLUDE=-I$(srcdir)/../grove -I$(srcdir)/../spgrove -I$(srcdir)/../style
 # XLIBS=../style/libostyle.a ../spgrove/libospgrove.a ../grove/libogrove.a \
 #   ../lib/libosp.a
-XLIBS=../style/libostyle.a ../grove/libogrove.a ../spgrove/libospgrove.a $(splibdir)/libosp.a
+XLIBS=../style/libostyle.a ../grove/libogrove.a ../spgrove/libospgrove.a -losp
+EXT_LIBS=-L$(splibdir) -losp $(LIBS)
 GENSRCS=JadeMessages.h HtmlMessages.h RtfMessages.h TeXMessages.h \
  HtmlFOTBuilder_inst.cxx RtfFOTBuilder_inst.cxx  TeXFOTBuilder_inst.cxx \
  TransformFOTBuilder_inst.cxx MifMessages.h MifFOTBuilder_inst.cxx

diff -u /var/tmp/portage/app-text/openjade-1.3.2-r1/work/openjade-1.3.2/Makefile.prog.in /tmp/buffer-content-5978T7K
--- a/Makefile.prog.in	2002-01-22 06:57:53.000000000 -0500
+++ b/Makefile.prog.in	2009-11-19 17:23:05.000000000 -0500
@@ -10,16 +10,15 @@
 top_builddir=@TOP@
 LINKFLAGS = @LINKFLAGS@

-ALL_LIBS = $(XLIBS) $(LIBS)
 Makefile.lt:
-	echo 'LT_LIBS='`echo $(ALL_LIBS)|sed 's/\.a/.la/g'` >Makefile.lt
+	echo 'LT_LIBS='`echo $(XLIBS)|sed 's/\.a/.la/g'` >Makefile.lt

 PROG:=$(shell echo "$(PROG)" | sed '@program_transform_name@')

 all: $(PROG)

 $(PROG): $(OBJS) $(COBJS) $(LT_LIBS)
-	$(LIBTOOL) --mode=link $(CXX) $(LINKFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(COBJS) $(LT_LIBS)
+	$(LIBTOOL) --mode=link $(CXX) $(LINKFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(COBJS) $(LT_LIBS) $(EXT_LIBS)

 install: $(PROG)
 	-test -d $(DESTDIR)$(bindir) || \


code:
Use Getopt::Std in place of getopts.pl.
https://bugs.gentoo.org/show_bug.cgi?id=420083

--- a/msggen.pl
+++ b/msggen.pl
@@ -4,6 +4,7 @@
 # See the file COPYING for copying permission.

 use POSIX;
+use Getopt::Std;

 # Package and version.
 $package = 'openjade';
@@ -18,8 +19,7 @@
 undef $opt_l;
 undef $opt_p;
 undef $opt_t;
-do 'getopts.pl';
-&Getopts('l:p:t:');
+getopts('l:p:t:');
 $module = $opt_l;
 $pot_file = $opt_p;

@@ -72,7 +72,7 @@
     else {
 	$field[0] =~ /^[IWQXE][0-9]$/ || &error("invalid first field");;
 	$type[$num] = substr($field[0], 0, 1);
-	$argc = int(substr($field[0], 1, 1));
+	$argc = substr($field[0], 1, 1);
     }
     $nargs[$num] = $argc;
     $field[1] =~ /^[a-zA-Z_][a-zA-Z0-9_]+$/ || &error("invalid tag");


code:
--- a/Makefile.lib.in.orig	2016-05-19 17:20:25.164931700 +0200
+++ b/Makefile.lib.in	2016-05-19 17:20:56.539989400 +0200
@@ -24,7 +24,7 @@

 lib$(LIB).la: $(LT_OBJS)
 	$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINKFLAGS) -o lib$(LIB).la $(LT_OBJS) \
-	    -rpath $(libdir) -version-info $(LTVERSION) $(DEPLIBS)
+	    -no-undefined -rpath $(libdir) -version-info $(LTVERSION) $(DEPLIBS)

 install:
 	$(mkinstalldirs) $(DESTDIR)$(libdir)


code:
diff -ru a/Makefile.lib.in b/Makefile.lib.in
--- a/Makefile.lib.in	2002-01-22 05:57:53.000000000 -0600
+++ b/Makefile.lib.in	2009-01-04 16:15:41.000000000 -0600
@@ -23,7 +23,7 @@
 	echo 'LT_OBJS='`echo $(OBJS)|sed 's/\.o/.lo/g'` >Makefile.lt

 lib$(LIB).la: $(LT_OBJS)
-	$(LIBTOOL) --mode=link $(CC) $(LINKFLAGS) -o lib$(LIB).la $(LT_OBJS) \
+	$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINKFLAGS) -o lib$(LIB).la $(LT_OBJS) \
 	    -rpath $(libdir) -version-info $(LTVERSION) $(DEPLIBS)

 install:


code:
This fixes Cygwin, where wchar_t is ushort.

--- a/grove/Node.h
+++ b/grove/Node.h
@@ -8,6 +8,7 @@
 #endif

 #include <stddef.h>
+#include <limits.h>
 #include "IList.h"

 #ifdef SP_USE_DLL
@@ -34,10 +35,10 @@
 #endif

 #ifdef SP_MULTI_BYTE
-#ifdef SP_WCHAR_T_USHORT
-typedef wchar_t GroveChar;
-#else
+#if UINT_MAX >= 0xffffffffL /* 2^32 - 1 */
 typedef unsigned int GroveChar;
+#else
+typedef unsigned long GroveChar;
 #endif
 #else /* not SP_MULTI_BYTE */
 typedef unsigned char GroveChar;


code:
Index: os-prober/common.sh
===================================================================
--- os-prober.orig/common.sh
+++ os-prober/common.sh
@@ -269,7 +269,7 @@ linux_mount_boot () {
 				if [ "$bindfrom" != "$tmpmnt/boot" ]; then
 					if mount --bind "$bindfrom" "$tmpmnt/boot"; then
 						mounted=1
-						bootpart="$1"
+						bootpart="$tmppart"
 					else
 						debug "failed to bind-mount $bindfrom onto $tmpmnt/boot"
 					fi
@@ -277,6 +277,15 @@ linux_mount_boot () {
 			fi
 			if [ "$mounted" ]; then
 				:
+			elif [ -e "$tmppart" ]; then
+				bootpart="$tmppart"
+				boottomnt="$tmppart"
+			elif [ -e "$tmpmnt/$tmppart" ]; then
+				bootpart="$tmppart"
+				boottomnt="$tmpmnt/$tmppart"
+			elif [ -e "/target/$tmppart" ]; then
+				bootpart="$tmppart"
+				boottomnt="/target/$tmppart"
 			elif [ -e "$1" ]; then
 				bootpart="$1"
 				boottomnt="$1"


code:
diff --git a/common.sh b/common.sh
index c2c5f46..8fb3c5f 100644
--- a/common.sh
+++ b/common.sh
@@ -155,6 +155,7 @@ parse_proc_mounts () {
 	done
 }

+# add forth parameter to pickup btrfs subvol info
 parsefstab () {
 	while read -r line; do
 		case "$line" in
@@ -165,12 +166,22 @@ parsefstab () {
 				set -f
 				set -- $line
 				set +f
-				printf '%s %s %s\n' "$1" "$2" "$3"
+				printf '%s %s %s %s\n' "$1" "$2" "$3" "$4"
 			;;
 		esac
 	done
 }

+#check_btrfs_mounted $bootsv $bootuuid)
+check_btrfs_mounted () {
+	bootsv="$1"
+	bootuuid="$2"
+	bootdev=$(blkid | grep "$bootuuid" | cut -d ':' -f  1)
+	bindfrom=$(grep " btrfs " /proc/self/mountinfo |
+		   grep " $bootdev " | grep " /$bootsv " | cut -d ' ' -f 5)
+	printf "%s" "$bindfrom"
+}
+
 unescape_mount () {
 	printf %s "$1" | \
 		sed 's/\\011/	/g; s/\\012/\n/g; s/\\040/ /g; s/\\134/\\/g'
diff --git a/linux-boot-prober b/linux-boot-prober
index e32dc84..2a60fa2 100755
--- a/linux-boot-prober
+++ b/linux-boot-prober
@@ -5,16 +5,143 @@ set -e

 newns "$@"
 require_tmpdir
+ERR="n"
+
+tmpmnt=/var/lib/os-prober/mount
+if [ ! -d "$tmpmnt" ]; then
+	mkdir "$tmpmnt"
+fi
+
+mounted=
+bootmnt=
+bootsv=
+bootuuid=

 grep "^/dev/" /proc/mounts | parse_proc_mounts >"$OS_PROBER_TMP/mounted-map" || true

-partition="$1"
+if [ -z "$1" ]; then
+	ERR=y
+elif [ "$1" = btrfs -a -z "$2" ]; then
+	ERR=y
+elif [ "$1" = btrfs -a -z "$3" ]; then
+	ERR=y
+elif [ "$1" = btrfs ]; then
+	type=btrfs
+	echo "$2" | grep -q "^UUID=" || ERR=y
+	echo "$3" | grep -q "^subvol=" || ERR=y
+	export "$2"
+	export "$3"
+	partition=$(blkid | grep "$UUID" | cut -d ':' -f 1 | tr '\n' ' ' | cut -d ' ' -f 1)
+	debug "btrfs: partition=$partition, UUID=$UUID, subvol=$subvol"
+else
+	partition="$1"
+	type=other
+fi

-if [ -z "$partition" ]; then
+if [ "x$ERR" != xn ]; then
 	echo "usage: linux-boot-prober partition" >&2
+	echo "       linux-boot-prober btrfs UUID=<> subvol=<>" >&2
 	exit 1
 fi

+if [ "$type" = btrfs ]; then
+	# handle all of the btrfs stuff here
+	if [ ! -e "/proc/self/mountinfo" ]; then
+		warn "/proc/self/mountinfo does not exist, exiting"
+		umount "$tmpmnt" 2>/dev/null
+		rmdir "$tmpmnt" 2>/dev/null
+		exit 1
+	fi
+	mpoint=$(grep "btrfs" /proc/self/mountinfo | grep " /$subvol " | grep " $partition " | cut -d ' ' -f 5)
+	if [ "$mpoint" = "/" ]; then
+		warn "specifying active root not valid, exiting"
+		umount "$tmpmnt" 2>/dev/null
+		rmdir "$tmpmnt" 2>/dev/null
+		exit 1
+	fi
+	if [ "$mpoint" = "$tmpmnt" ]; then
+		warn "btrfs subvol=$subvool, UUID=$UUID, already mounted on $tmpmnt **ERROR**"
+		umount "$tmpmnt" 2>/dev/null
+		rmdir "$tmpmnt" 2>/dev/null
+		exit 1
+	fi
+	if [ -z "$mpoint" ]; then
+		# mount the btrfs root
+		if ! mount -o subvol=$subvol -t btrfs -U $UUID "$tmpmnt" 2>/dev/null; then
+			warn "error mounting btrfs subvol=$subvol UUID=$UUID"
+			umount "$tmpmnt/boot" 2>/dev/null
+			umount "$tmpmnt" 2>/dev/null
+			rmdir "$tmpmnt" 2>/dev/null
+			exit 1
+		fi
+	else
+		# bind-mount
+		if ! mount -o bind "$mpoint" "$tmpmnt" 2>/dev/null; then
+			warn "error mounting btrfs bindfrom=$mpoint subvol=$subvol UUID=$UUID"
+			umount "$tmpmnt/boot" 2>/dev/null
+			umount "$tmpmnt" 2>/dev/null
+			rmdir "$tmpmnt" 2>/dev/null
+			exit 1
+		fi
+	fi
+	debug "mounted btrfs $partition, subvol=$subvol on $tmpmnt"
+	if [ ! -e "$tmpmnt/etc/fstab" ]; then
+		warn "btrfs subvol=$subvol not root"
+		umount "$tmpmnt" 2>/dev/null
+		rmdir "$tmpmnt" 2>/dev/null
+		exit 1
+	fi
+	bootmnt=$(parsefstab < "$tmpmnt/etc/fstab" | grep " /boot ") || true
+	if [ -z "$bootmnt" ]; then
+		# /boot is part of the root
+		bootpart="$partition"
+		bootsv="$subvol"
+	elif echo "$bootmnt" | cut -d ' ' -f 3 | grep -q "btrfs"; then
+		# separate btrfs /boot subvolume
+		bootsv=$(echo "$bootmnt" | cut -d ' ' -f 4 | grep "^subvol=" | sed "s/subvol=//" )
+		bootuuid=$(echo "$bootmnt" | cut -d ' ' -f 1 | grep "^UUID=" | sed "s/UUID=//" )
+		debug "mounting btrfs $tmpmnt/boot UUID=$bootuuid subvol=$bootsv"
+		bindfrom=$(check_btrfs_mounted $bootsv $bootuuid)
+		if [ -n "$bindfrom" ]; then
+			# already mounted some place
+			if ! mount -o bind $bindfrom "$tmpmnt/boot" 2>/dev/null; then
+				warn "error bind mounting btrfs boot subvol=$bootsv, from=$bindfrom"
+				umount "$tmpmnt/boot" 2>/dev/null
+				umount "$tmpmnt" 2>/dev/null
+				rmdir "$tmpmnt" 2>/dev/null
+				exit 1
+			fi
+		elif ! mount -o subvol=$bootsv -t btrfs -U $bootuuid "$tmpmnt/boot" 2>/dev/null; then
+			warn "error mounting btrfs boot partition subvol=$bootsv, UUID=$bootuuid"
+			umount "$tmpmnt/boot" 2>/dev/null
+			umount "$tmpmnt" 2>/dev/null
+			rmdir "$tmpmnt" 2>/dev/null
+			exit 1
+		fi
+		bootpart=$(grep " btrfs " /proc/self/mountinfo | grep " /$bootsv " | cut -d ' ' -f 10)
+	else
+		# non-btrfs partition or logical volume
+		linux_mount_boot $partition $tmpmnt
+		bootpart="${mountboot%% *}"
+		bootsv=
+	fi
+
+	test="/usr/lib/linux-boot-probes/mounted/40grub2"
+	if [ -f $test ] && [ -x $test ]; then
+		debug "running $test $partition $bootpart $tmpmnt $type $subvol $bootsv"
+		if $test "$partition" "$bootpart" "$tmpmnt" "$type" "$subvol" "$bootsv"; then
+			debug "$test succeeded"
+		fi
+	fi
+	umount "$tmpmnt/boot" 2>/dev/null || true
+	if ! umount "$tmpmnt" 2>/dev/null; then
+		warn "problem umount $tmpmnt"
+	fi
+	rmdir "$tmpmnt" 2>/dev/null || true
+
+	exit 0
+fi
+
 if ! mapped="$(mapdevfs "$partition")"; then
 	log "Device '$partition' does not exist; skipping"
 	continue
@@ -22,8 +149,8 @@ fi

 if ! grep -q "^$mapped " "$OS_PROBER_TMP/mounted-map"; then
 	for test in /usr/lib/linux-boot-probes/*; do
-		debug "running $test"
 		if [ -x $test ] && [ -f $test ]; then
+			debug "running $test"
 			if $test "$partition"; then
 				debug "linux detected by $test"
 				break
diff --git a/linux-boot-probes/mounted/common/40grub2 b/linux-boot-probes/mounted/common/40grub2
index 885614e..db5cbfd 100755
--- a/linux-boot-probes/mounted/common/40grub2
+++ b/linux-boot-probes/mounted/common/40grub2
@@ -2,17 +2,30 @@
 . /usr/share/os-prober/common.sh
 set -e

+# add support for btrfs with no separate /boot
+# that is, rootsv = bootsv
 partition="$1"
 bootpart="$2"
 mpoint="$3"
 type="$4"
+rootsv="$5"
+bootsv="$6"

 found_item=0

 entry_result () {
+	if [ "x$type" = "xbtrfs" -a "$partition" = "$bootpart" ]; then
+		# trim off the leading subvol
+		kernelfile=$(echo "$kernel" | cut -d '/' -f 2- | cut -d '/' -f 2-)
+		if [ "x$rootsv" != "x$bootsv" ]; then
+		   kernelfile="/boot/$kernelfile"
+		fi
+	else
+		kernelfile=$kernel
+	fi
 	if [ "$ignore_item" = 0 ] && \
 	   [ -n "$kernel" ] && \
-	   [ -e "$mpoint/$kernel" ]; then
+	   [ -e "$mpoint/$kernelfile" ]; then
 		result "$rootpart:$bootpart:$title:$kernel:$initrd:$parameters"
 		found_item=1
 	fi
diff --git a/os-prober b/os-prober
index 8852887..482c3c2 100755
--- a/os-prober
+++ b/os-prober
@@ -76,9 +76,12 @@ partitions () {

 	# Also detect OSes on LVM volumes (assumes LVM is active)
 	if type lvs >/dev/null 2>&1; then
-		echo "$(LVM_SUPPRESS_FD_WARNINGS=1 log_output lvs --noheadings --separator : -o vg_name,lv_name |
+		echo "$(LVM_SUPPRESS_FD_WARNINGS=1 log_output lvs --noheadings --separator : -o vg_name,lv_name 2>/dev/null |
 			sed "s|-|--|g;s|^[[:space:]]*\(.*\):\(.*\)$|/dev/mapper/\1-\2|")"
 	fi
+
+	# now lets make sure we got all of the btrfs partitions and disks
+	blkid | grep 'TYPE="btrfs"' | cut -d ':' -f 1
 }

 parse_proc_swaps () {
@@ -136,6 +139,8 @@ if [ -f /proc/mdstat ] ; then
 	grep "^md" /proc/mdstat | cut -d: -f2- | parse_proc_mdstat >"$OS_PROBER_TMP/raided-map" || true
 fi

+: >"$OS_PROBER_TMP/btrfs-vols"
+
 for partition in $(partitions); do
 	if ! mapped="$(mapdevfs "$partition")"; then
 		log "Device '$partition' does not exist; skipping"
@@ -154,7 +159,26 @@ for partition in $(partitions); do
 		continue
 	fi

-	if ! grep -q "^$mapped " "$OS_PROBER_TMP/mounted-map" ; then
+	# do btrfs processing here; both mounted and unmounted will
+	# be handled by 50mounted-tests so we can do a subvol only once.
+	type=$(blkid -o value -s TYPE $mapped || true)
+	if [ "$type" = btrfs ]; then
+		uuid=$(blkid -o value -s UUID $mapped)
+		if grep -q "^$uuid" "$OS_PROBER_TMP/btrfs-vols" ; then
+			continue
+		fi
+		debug "btrfs volume uuid=$uuid partition=$partition"
+		echo "$uuid" >>"$OS_PROBER_TMP/btrfs-vols"
+		test="/usr/lib/os-probes/50mounted-tests"
+		if [ -f "$test" ] && [ -x "$test" ]; then
+			debug "running $test on btrfs $partition"
+			if "$test" btrfs "$uuid" "$partition"; then
+				debug "os detected by $test"
+				continue
+			fi
+		fi
+
+	elif ! grep -q "^$mapped " "$OS_PROBER_TMP/mounted-map" ; then
 		for test in /usr/lib/os-probes/*; do
 			if [ -f "$test" ] && [ -x "$test" ]; then
 				debug "running $test on $partition"
diff --git a/os-probes/common/50mounted-tests b/os-probes/common/50mounted-tests
index 2951ef9..e33eb82 100755
--- a/os-probes/common/50mounted-tests
+++ b/os-probes/common/50mounted-tests
@@ -19,19 +19,31 @@ do_unmount() {
 	rmdir "$tmpmnt" || true
 }

-types="$(fs_type "$partition")"
+if [ "x$1" = xbtrfs ]; then
+	types=btrfs
+	if [ -z "$2" -o -z "$3" ]; then
+		debug "missing btrfs parameters, exiting"
+		exit 1
+	fi
+	UUID="$2"
+	BTRFSDEV="$3"
+else
+	partition="$1"
+	types="$(fs_type "$partition")" || types=NOT-DETECTED
+fi
+
 if [ "$types" = NOT-DETECTED ]; then
 	debug "$1 type not recognised; skipping"
-	exit 0
+	exit 1
 elif [ "$types" = swap ]; then
 	debug "$1 is a swap partition; skipping"
-	exit 0
+	exit 1
 elif [ "$types" = crypto_LUKS ]; then
 	debug "$1 is a LUKS partition; skipping"
-	exit 0
+	exit 1
 elif [ "$types" = LVM2_member ]; then
 	debug "$1 is an LVM member; skipping"
-	exit 0
+	exit 1
 elif [ "$types" = ntfs ]; then
 	if type ntfs-3g >/dev/null 2>&1; then
 		types='ntfs-3g ntfs'
@@ -40,7 +52,7 @@ elif [ -z "$types" ]; then
 	if type cryptsetup >/dev/null 2>&1 && \
 	   cryptsetup luksDump "$partition" >/dev/null 2>&1; then
 		debug "$1 is a LUKS partition; skipping"
-		exit 0
+		exit 1
 	fi
 	for type in $(grep -v nodev /proc/filesystems); do
 		# hfsplus filesystems are mountable as hfs. Try hfs last so
@@ -63,6 +75,108 @@ if [ ! -d "$tmpmnt" ]; then
 fi

 mounted=
+
+# all btrfs processing here.  Handle both unmounted and
+# mounted subvolumes.
+if [ "$types" = btrfs ]; then
+	partition="$BTRFSDEV"
+	debug "begin btrfs processing for $UUID"
+	# note that the btrfs volume must not be mounted ro
+	if mount -t btrfs -U "$UUID" "$tmpmnt"  2>/dev/null; then
+		debug "btrfs volume $UUID mounted"
+	else
+		warn "cannot mount btrfs volume $UUID, exiting"
+		rmdir "$tmpmnt" || true
+		exit 1
+	fi
+	# besides regular subvols, get ro and snapshot so thet can be excluded
+        subvols=$(btrfs subvolume list "$tmpmnt" | cut -d ' ' -f 9)
+        rosubvols=$(btrfs subvolume list -r "$tmpmnt" | cut -d ' ' -f 9)
+        sssubvols=$(btrfs subvolume list -s "$tmpmnt" | cut -d ' ' -f 14)
+        if ! umount "$tmpmnt"; then
+            warn "failed to umount btrfs volume on $tmpmnt"
+            rmdir "$tmpmnt" || true
+            exit 1
+        fi
+
+	found=
+	mounted=
+
+	mpoint="$(grep btrfs /proc/self/mountinfo | grep "$partition " | cut -d ' ' -f 5)"
+	if [ -n "$mpoint" -a "x$mpoint" = "x/" ]; then
+		debug "This is the root for the running system" #running system must be done elsewhere
+	else
+	    #partition was not root of running system, so lets look for bootable subvols
+	    if [ -n "$mpoint" ] ; then
+		mounted=1  #partition was already mounted,so lets not unmount it when done
+	    else
+		# again, do not mount btrfs ro
+		mount -t btrfs -U "$UUID" "$tmpmnt"
+		mpoint="$tmpmnt"
+	    fi
+
+	    test="/usr/lib/os-probes/mounted/90linux-distro"
+	    if [ -f "$test" ] && [ -x "$test" ]; then
+		debug "running subtest $test"
+		if "$test" "$partition" "$mpoint" btrfs "UUID=$UUID"; then
+		    debug "os found by subtest $test on $partition"
+		    found=1
+		fi
+	    fi
+	    if [ -z "$mounted" ]; then
+		if ! umount "$tmpmnt"; then
+		    warn "failed to umount $tmpmnt"
+		fi
+	    fi
+	fi
+
+	if [ -z "$subvols" ]; then
+	        debug "no subvols found on btrfs volume $UUID"
+	else
+		found=
+                for subvol in $subvols; do
+			debug "begin btrfs processing for $UUID subvol=$subvol"
+			if echo "$rosubvols" | grep -q -x "$subvol"; then
+				continue
+			fi
+			if echo "$sssubvols" | grep -q -x "$subvol"; then
+				continue
+			fi
+			mounted=
+			mpoint="$(grep btrfs /proc/self/mountinfo | grep "$partition " | grep "/$subvol " | cut -d ' ' -f 5)"
+			if [ -n "$mpoint" ]; then
+				if [ "x$mpoint" = "x/" ]; then
+					continue # this is the root for the running system
+				fi
+				mounted=1
+			else
+				# again, do not mount btrfs ro
+				mount -t btrfs -o subvol="$subvol" -U "$UUID" "$tmpmnt"
+				mpoint="$tmpmnt"
+			fi
+			test="/usr/lib/os-probes/mounted/90linux-distro"
+			if [ -f "$test" ] && [ -x "$test" ]; then
+				debug "running subtest $test"
+				if "$test" "$partition" "$mpoint" btrfs "UUID=$UUID" "subvol=$subvol"; then
+					debug "os found by subtest $test on subvol $subvol"
+					found=1
+				fi
+			fi
+			if [ -z "$mounted" ]; then
+				if ! umount "$tmpmnt"; then
+				    warn "failed to umount $tmpmnt"
+				fi
+			fi
+		done
+	fi
+	rmdir "$tmpmnt" || true
+	if [ "$found" ]; then
+		exit 0
+	else
+		exit 1
+	fi
+fi
+
 if type grub-mount >/dev/null 2>&1 && \
    type grub-probe >/dev/null 2>&1 && \
    grub-mount "$partition" "$tmpmnt" 2>/dev/null; then
diff --git a/os-probes/mounted/common/90linux-distro b/os-probes/mounted/common/90linux-distro
index badfbb1..9bc5154 100755
--- a/os-probes/mounted/common/90linux-distro
+++ b/os-probes/mounted/common/90linux-distro
@@ -7,6 +7,8 @@ set -e
 partition="$1"
 dir="$2"
 type="$3"
+uuid="$4"
+subvol="$5"

 # This test is inaccurate, but given separate / and /boot partitions and the
 # fact that only some architectures have ld-linux.so, I can't see anything
@@ -143,7 +145,11 @@ if (ls "$dir"/lib*/ld*.so* && [ -d "$dir/boot" ] || ls "$dir"/usr/lib*/ld*.so*)
 	fi

         label="$(count_next_label "$short")"
-	result "$partition:$long:$label:linux"
+	if [ "x$type" = "xbtrfs" -a "x$uuid" != "x" -a "x$subvol" != "x" ]; then
+		result "$partition:$long:$label:linux:$type:$uuid:$subvol"
+	else
+		result "$partition:$long:$label:linux"
+	fi
 	exit 0
 else
 	exit 1


code:
Index: os-prober/common.sh
===================================================================
--- os-prober.orig/common.sh
+++ os-prober/common.sh
@@ -62,10 +62,14 @@ cache_progname() {
   esac
 }

-log() {
-  cache_progname
-  logger -t "$progname" "$@"
-}
+# fd_logger: bind value now, possibly after assigning default.
+eval '
+  log() {
+    cache_progname
+    echo "$progname: $@"  1>&'${fd_logger:=9}'
+  }
+'
+export fd_logger  # so subshells inherit current value by default

 error() {
   log "error: $@"
@@ -81,10 +85,14 @@ debug() {
   fi
 }

-result () {
-  log "result:" "$@"
-  echo "$@"
-}
+# fd_result: bind value now, possibly after assigning default.
+eval '
+  result() {
+    log "result:" "$@"
+    echo "$@"  1>&'${fd_result:=1}'
+  }
+'
+export fd_result  # so subshells inherit current value by default

 # shim to make it easier to use os-prober outside d-i
 if ! type mapdevfs >/dev/null 2>&1; then
Index: os-prober/linux-boot-prober
===================================================================
--- os-prober.orig/linux-boot-prober
+++ os-prober/linux-boot-prober
@@ -1,4 +1,12 @@
 #!/bin/sh
+
+# dash shell does not have "{varname}>&1" feature that bash shell has
+# for auto-assignment of new filedescriptors.
+# It is cumbersome to write the 'eval' to use our own variables in redirections.
+# Therefore use fixed numbers.
+export fd_result=3  # file descriptor for external results
+export fd_logger=9  # file descriptor for input to logger
+
 . /usr/share/os-prober/common.sh

 set -e
@@ -19,6 +27,7 @@ bootuuid=

 grep "^/dev/" /proc/mounts | parse_proc_mounts >"$OS_PROBER_TMP/mounted-map" || true

+( (
 if [ -z "$1" ]; then
 	ERR=y
 elif [ "$1" = btrfs -a -z "$2" ]; then
@@ -186,3 +195,5 @@ else
 		fi
 	fi
 fi
+) 9>&1 | logger 1>&-  # fd_logger
+) 3>&1  # fd_result
Index: os-prober/os-prober
===================================================================
--- os-prober.orig/os-prober
+++ os-prober/os-prober
@@ -1,7 +1,14 @@
 #!/bin/sh
 set -e

-. /usr/share/os-prober/common.sh
+# dash shell does not have "{varname}>&1" feature that bash shell has
+# for auto-assignment of new filedescriptors.
+# It is cumbersome to write the 'eval' to use our own variables in redirections.
+# Therefore use fixed numbers.
+export fd_result=3  # file descriptor for external results
+export fd_logger=9  # file descriptor for input to logger
+
+ . /usr/share/os-prober/common.sh

 newns "$@"
 require_tmpdir
@@ -136,6 +143,7 @@ fi

 : >"$OS_PROBER_TMP/btrfs-vols"

+( (
 for partition in $(partitions); do
 	if ! mapped="$(mapdevfs "$partition")"; then
 		log "Device '$partition' does not exist; skipping"
@@ -200,3 +208,5 @@ for partition in $(partitions); do
 		fi
 	fi
 done
+) 9>&1 | logger 1>&-  # fd_logger
+) 3>&1  # fd_result


code:
Index: os-prober/os-probes/mounted/x86/05efi
===================================================================
--- os-prober.orig/os-probes/mounted/x86/05efi
+++ os-prober/os-probes/mounted/x86/05efi
@@ -59,7 +59,11 @@ ret=1
 for test in /usr/lib/os-probes/mounted/efi/*; do
 	debug "running subtest $test"
 	if [ -f "$test" ] && [ -x "$test" ]; then
+		# we need results of subtest in stdout
+		orig_fd_res=$fd_result
+		export fd_result=1
 		entry=$("$test" "$mpoint/$efi")
+		export fd_result=$orig_fd_res
 		if [ -n "$entry" ]; then
 			debug "bootloader $entry found by subtest $test"
 			ret=0


code:
Index: os-prober/linux-boot-probes/mounted/common/90fallback
===================================================================
--- os-prober.orig/linux-boot-probes/mounted/common/90fallback
+++ os-prober/linux-boot-probes/mounted/common/90fallback
@@ -33,7 +33,7 @@ for kernpat in /vmlinuz /vmlinux /boot/v
 			# Dracut initramfses are named differently again.
 			initrdname3=$(echo "$kernfile" | sed "s/vmlinu[zx]/initramfs\*/" | sed 's/$/.img/')
 			# And Gentoo's also
-			initrdname4=$(echo "$kernfile" | sed "s/kernel/initramfs\*/")
+			initrdname4=$(echo "$kernfile" | sed "s/kernel\|vmlinu[zx]/initramfs\*/")
 			foundinitrd=0
 			for initrd in $(eval ls "$initrdname" "$initrdname1" "$initrdname2" "$initrdname3" "$initrdname4" 2>/dev/null); do
 				if [ "$initrd" != "$kernfile" ] && [ -f "$initrd" ] && [ ! -L "$initrd" ]; then


code:
Index: os-prober/os-probes/mounted/x86/83haiku
===================================================================
--- os-prober.orig/os-probes/mounted/x86/83haiku
+++ os-prober/os-probes/mounted/x86/83haiku
@@ -13,7 +13,7 @@ case "$type" in
 	*) debug "$partition is not a BeFS partition: exiting"; exit 1 ;;
 esac

-if head -c 512 "$partition" | grep -qs "system.haiku_loader"; then
+if head -c 512 "$partition" | grep -aqs "system.haiku_loader"; then
 	debug "Stage 1 bootloader found"
 else
 	debug "Stage 1 bootloader not found: exiting"