From 99cab525cb92311fde8d096b776b04799c169832 Mon Sep 17 00:00:00 2001
From: "A. Wilcox" <AWilcox@Wilcox-Tech.com>
Date: Fri, 31 Aug 2018 17:44:22 +0000
Subject: [PATCH] system/musl: further POSIX conformance

---
 system/musl/APKBUILD           |   4 +-
 system/musl/amalgamation.patch | 421 +++++++++++++++++++++++++++++++--
 2 files changed, 399 insertions(+), 26 deletions(-)

diff --git a/system/musl/APKBUILD b/system/musl/APKBUILD
index 0303b3eee0..adb527d8a7 100644
--- a/system/musl/APKBUILD
+++ b/system/musl/APKBUILD
@@ -2,7 +2,7 @@
 # Maintainer: A. Wilcox <awilfox@adelielinux.org>
 pkgname=musl
 pkgver=1.1.19
-pkgrel=12
+pkgrel=13
 pkgdesc="System library (libc) implementation"
 url="http://www.musl-libc.org/"
 arch="all"
@@ -108,7 +108,7 @@ utils() {
 }
 
 sha512sums="abee52d53af4b3c14c9088866c911a24d2b6ef67dc494f38a7a09dfe77250026f77528c24c52469c89cffa8ced2f0fa95badbdcf8d4460c90faba47e3927bcc5  musl-1.1.19.tar.gz
-6e357f1310c30e9631c4b925c33545bb2a5f8888754e73fe8ae37b543018f68e9bed1161ae7e0c06780f2974f9944c9512ae22f6d616f0c74b62cfaf22d0ad14  amalgamation.patch
+b93eb56efadf4ac7e25be6cca22ef99553000e2c2d50f37cfa1430d2f5194cead34b4ca1afc394e97bda0b02eb916c2b85435e58bef686ce8b556546cf957880  amalgamation.patch
 2c8e1dde1834238097b2ee8a7bfb53471a0d9cff4a5e38b55f048b567deff1cdd47c170d0578a67b1a039f95a6c5fbb8cff369c75b6a3e4d7ed171e8e86ebb8c  2000-pthread-internals-increase-DEFAULT_GUARD_SIZE-to-2-p.patch
 88ae443dbb8e0a4368235bdc3a1c5c7b718495afa75e06deb8e01becc76cb1f0d6964589e2204fc749c9c1b3190b8b9ac1ae2c0099cab8e2ce3ec877103d4332  3001-make-real-lastlog-h.patch
 6a7ff16d95b5d1be77e0a0fbb245491817db192176496a57b22ab037637d97a185ea0b0d19da687da66c2a2f5578e4343d230f399d49fe377d8f008410974238  handle-aux-at_base.patch
diff --git a/system/musl/amalgamation.patch b/system/musl/amalgamation.patch
index 08228fb84e..96dd545d97 100644
--- a/system/musl/amalgamation.patch
+++ b/system/musl/amalgamation.patch
@@ -2091,10 +2091,10 @@ index 65a3dd64..c340ceb2 100644
  #endif
  
 diff --git a/arch/sh/pthread_arch.h b/arch/sh/pthread_arch.h
-index 2756e7ec..41fefacf 100644
+index 2756e7ec..a7dd27a6 100644
 --- a/arch/sh/pthread_arch.h
 +++ b/arch/sh/pthread_arch.h
-@@ -2,10 +2,11 @@ static inline struct pthread *__pthread_self()
+@@ -2,10 +2,16 @@ static inline struct pthread *__pthread_self()
  {
  	char *self;
  	__asm__ __volatile__ ("stc gbr,%0" : "=r" (self) );
@@ -2108,6 +2108,11 @@ index 2756e7ec..41fefacf 100644
 +#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
  
  #define MC_PC sc_pc
++
++#ifdef __FDPIC__
++#define MC_GOT sc_regs[12]
++#define CANCEL_GOT (*(uintptr_t *)((char *)__syscall_cp_asm+sizeof(uintptr_t)))
++#endif
 diff --git a/arch/sh/reloc.h b/arch/sh/reloc.h
 index 0238ce07..a1f16cb1 100644
 --- a/arch/sh/reloc.h
@@ -2474,9 +2479,18 @@ index e79915fe..c2297353 100644
  #define STO_PPC64_LOCAL_BIT	5
  #define STO_PPC64_LOCAL_MASK	0xe0
 diff --git a/include/limits.h b/include/limits.h
-index f9805a1e..ab163a22 100644
+index f9805a1e..02c2139d 100644
 --- a/include/limits.h
 +++ b/include/limits.h
+@@ -9,7 +9,7 @@
+ 
+ /* Support signed or unsigned plain-char */
+ 
+-#if '\0'-1 > 0
++#if '\xff' > 0
+ #define CHAR_MIN 0
+ #define CHAR_MAX 255
+ #else
 @@ -40,14 +40,9 @@
   || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
  
@@ -3495,22 +3509,33 @@ index 39ce6cf2..7dc2afeb 100644
  	return w;
  }
 diff --git a/src/conf/confstr.c b/src/conf/confstr.c
-index 02cb1aa2..3d417284 100644
+index 02cb1aa2..8f870a69 100644
 --- a/src/conf/confstr.c
 +++ b/src/conf/confstr.c
-@@ -7,7 +7,7 @@ size_t confstr(int name, char *buf, size_t len)
+@@ -6,8 +6,8 @@ size_t confstr(int name, char *buf, size_t len)
+ {
  	const char *s = "";
  	if (!name) {
- 		s = "/bin:/usr/bin";
+-		s = "/bin:/usr/bin";
 -	} else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>33U) {
++		s = "/usr/5bin:/usr/bin:/bin";
 +	} else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>35U) {
  		errno = EINVAL;
  		return 0;
  	}
 diff --git a/src/conf/fpathconf.c b/src/conf/fpathconf.c
-index 8eb037e6..7e4b8003 100644
+index 8eb037e6..b6a9d63e 100644
 --- a/src/conf/fpathconf.c
 +++ b/src/conf/fpathconf.c
+@@ -4,7 +4,7 @@
+ 
+ long fpathconf(int fd, int name)
+ {
+-	static const short values[] = {
++	static const long values[] = {
+ 		[_PC_LINK_MAX] = _POSIX_LINK_MAX,
+ 		[_PC_MAX_CANON] = _POSIX_MAX_CANON,
+ 		[_PC_MAX_INPUT] = _POSIX_MAX_INPUT,
 @@ -24,8 +24,9 @@ long fpathconf(int fd, int name)
  		[_PC_REC_MIN_XFER_SIZE] = 4096,
  		[_PC_REC_XFER_ALIGN] = 4096,
@@ -3519,15 +3544,74 @@ index 8eb037e6..7e4b8003 100644
 -		[_PC_2_SYMLINKS] = 1
 +		[_PC_SYMLINK_MAX] = -1,
 +		[_PC_2_SYMLINKS] = 1,
-+		[_PC_TIMESTAMP_RESOLUTION] = 1000000,
++		[_PC_TIMESTAMP_RESOLUTION] = 100000000,
  	};
  	if (name >= sizeof(values)/sizeof(values[0])) {
  		errno = EINVAL;
 diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c
-index 9ce330a5..58830a09 100644
+index 9ce330a5..483e1635 100644
 --- a/src/conf/sysconf.c
 +++ b/src/conf/sysconf.c
-@@ -164,6 +164,7 @@ long sysconf(int name)
+@@ -18,6 +18,7 @@
+ #define JT_PHYS_PAGES JT(8)
+ #define JT_AVPHYS_PAGES JT(9)
+ #define JT_ZERO JT(10)
++#define JT_DELAYTIMER_MAX JT(11)
+ 
+ #define RLIM(x) (-32768|(RLIMIT_ ## x))
+ 
+@@ -33,7 +34,7 @@ long sysconf(int name)
+ 		[_SC_TZNAME_MAX] = TZNAME_MAX,
+ 		[_SC_JOB_CONTROL] = 1,
+ 		[_SC_SAVED_IDS] = 1,
+-		[_SC_REALTIME_SIGNALS] = 1,
++		[_SC_REALTIME_SIGNALS] = VER,
+ 		[_SC_PRIORITY_SCHEDULING] = -1,
+ 		[_SC_TIMERS] = VER,
+ 		[_SC_ASYNCHRONOUS_IO] = VER,
+@@ -50,7 +51,7 @@ long sysconf(int name)
+ 		[_SC_AIO_LISTIO_MAX] = -1,
+ 		[_SC_AIO_MAX] = -1,
+ 		[_SC_AIO_PRIO_DELTA_MAX] = JT_ZERO, /* ?? */
+-		[_SC_DELAYTIMER_MAX] = _POSIX_DELAYTIMER_MAX,
++		[_SC_DELAYTIMER_MAX] = JT_DELAYTIMER_MAX,
+ 		[_SC_MQ_OPEN_MAX] = -1,
+ 		[_SC_MQ_PRIO_MAX] = JT_MQ_PRIO_MAX,
+ 		[_SC_VERSION] = VER,
+@@ -111,8 +112,8 @@ long sysconf(int name)
+ 		[_SC_XOPEN_XPG4] = -1,
+ 		[_SC_NZERO] = NZERO,
+ 		[_SC_XBS5_ILP32_OFF32] = -1,
+-		[_SC_XBS5_ILP32_OFFBIG] = sizeof(long)==4 ? 1 : JT_ZERO,
+-		[_SC_XBS5_LP64_OFF64] = sizeof(long)==8 ? 1 : JT_ZERO,
++		[_SC_XBS5_ILP32_OFFBIG] = sizeof(long)==4 ? 1 : -1,
++		[_SC_XBS5_LP64_OFF64] = sizeof(long)==8 ? 1 : -1,
+ 		[_SC_XBS5_LPBIG_OFFBIG] = -1,
+ 		[_SC_XOPEN_LEGACY] = -1,
+ 		[_SC_XOPEN_REALTIME] = -1,
+@@ -141,8 +142,8 @@ long sysconf(int name)
+ 		[_SC_STREAMS] = JT_ZERO,
+ 		[_SC_2_PBS_CHECKPOINT] = -1,
+ 		[_SC_V6_ILP32_OFF32] = -1,
+-		[_SC_V6_ILP32_OFFBIG] = sizeof(long)==4 ? 1 : JT_ZERO,
+-		[_SC_V6_LP64_OFF64] = sizeof(long)==8 ? 1 : JT_ZERO,
++		[_SC_V6_ILP32_OFFBIG] = sizeof(long)==4 ? 1 : -1,
++		[_SC_V6_LP64_OFF64] = sizeof(long)==8 ? 1 : -1,
+ 		[_SC_V6_LPBIG_OFFBIG] = -1,
+ 		[_SC_HOST_NAME_MAX] = HOST_NAME_MAX,
+ 		[_SC_TRACE] = -1,
+@@ -153,8 +154,8 @@ long sysconf(int name)
+ 		[_SC_IPV6] = VER,
+ 		[_SC_RAW_SOCKETS] = VER,
+ 		[_SC_V7_ILP32_OFF32] = -1,
+-		[_SC_V7_ILP32_OFFBIG] = sizeof(long)==4 ? 1 : JT_ZERO,
+-		[_SC_V7_LP64_OFF64] = sizeof(long)==8 ? 1 : JT_ZERO,
++		[_SC_V7_ILP32_OFFBIG] = sizeof(long)==4 ? 1 : -1,
++		[_SC_V7_LP64_OFF64] = sizeof(long)==8 ? 1 : -1,
+ 		[_SC_V7_LPBIG_OFFBIG] = -1,
+ 		[_SC_SS_REPL_MAX] = -1,
+ 		[_SC_TRACE_EVENT_NAME_MAX] = -1,
+@@ -164,6 +165,7 @@ long sysconf(int name)
  		[_SC_XOPEN_STREAMS] = JT_ZERO,
  		[_SC_THREAD_ROBUST_PRIO_INHERIT] = -1,
  		[_SC_THREAD_ROBUST_PRIO_PROTECT] = -1,
@@ -3535,6 +3619,15 @@ index 9ce330a5..58830a09 100644
  	};
  
  	if (name >= sizeof(values)/sizeof(values[0]) || !values[name]) {
+@@ -190,6 +192,8 @@ long sysconf(int name)
+ 		return PAGE_SIZE;
+ 	case JT_SEM_VALUE_MAX & 255:
+ 		return SEM_VALUE_MAX;
++	case JT_DELAYTIMER_MAX & 255:
++		return DELAYTIMER_MAX;
+ 	case JT_NPROCESSORS_CONF & 255:
+ 	case JT_NPROCESSORS_ONLN & 255: ;
+ 		unsigned char set[128] = {1};
 diff --git a/src/dirent/__dirent.h b/src/dirent/__dirent.h
 index 101b0368..828a5f17 100644
 --- a/src/dirent/__dirent.h
@@ -4757,10 +4850,10 @@ index ea65611a..25bb35db 100644
  {
  	return 0;
 diff --git a/src/misc/getopt.c b/src/misc/getopt.c
-index e9bab41c..e921a60e 100644
+index e9bab41c..cd1f292f 100644
 --- a/src/misc/getopt.c
 +++ b/src/misc/getopt.c
-@@ -77,7 +77,7 @@ int getopt(int argc, char * const argv[], const char *optstring)
+@@ -77,15 +77,19 @@ int getopt(int argc, char * const argv[], const char *optstring)
  		if (l>0) i+=l; else i++;
  	} while (l && d != c);
  
@@ -4769,6 +4862,31 @@ index e9bab41c..e921a60e 100644
  		optopt = c;
  		if (optstring[0] != ':' && opterr)
  			__getopt_msg(argv[0], ": unrecognized option: ", optchar, k);
+ 		return '?';
+ 	}
+ 	if (optstring[i] == ':') {
+-		if (optstring[i+1] == ':') optarg = 0;
+-		else if (optind >= argc) {
++		optarg = 0;
++		if (optstring[i+1] != ':' || optpos) {
++			optarg = argv[optind++] + optpos;
++			optpos = 0;
++		}
++		if (optind > argc) {
+ 			optopt = c;
+ 			if (optstring[0] == ':') return ':';
+ 			if (opterr) __getopt_msg(argv[0],
+@@ -93,10 +97,6 @@ int getopt(int argc, char * const argv[], const char *optstring)
+ 				optchar, k);
+ 			return '?';
+ 		}
+-		if (optstring[i+1] != ':' || optpos) {
+-			optarg = argv[optind++] + optpos;
+-			optpos = 0;
+-		}
+ 	}
+ 	return c;
+ }
 diff --git a/src/misc/getopt_long.c b/src/misc/getopt_long.c
 index 008b747c..ddcef949 100644
 --- a/src/misc/getopt_long.c
@@ -5044,10 +5162,16 @@ index 2dddeddb..fdd0ca48 100644
  
  weak_alias(__execvpe, execvpe);
 diff --git a/src/process/system.c b/src/process/system.c
-index 8cbdda06..0569461c 100644
+index 8cbdda06..aa01e13b 100644
 --- a/src/process/system.c
 +++ b/src/process/system.c
-@@ -19,7 +19,9 @@ int system(const char *cmd)
+@@ -14,12 +14,14 @@ int system(const char *cmd)
+ 	pid_t pid;
+ 	sigset_t old, reset;
+ 	struct sigaction sa = { .sa_handler = SIG_IGN }, oldint, oldquit;
+-	int status = 0x7f00, ret;
++	int status = -1, ret;
+ 	posix_spawnattr_t attr;
  
  	pthread_testcancel();
  
@@ -5137,6 +5261,57 @@ index 00000000..09bfa646
 +
 +1:	lea ___setjmp-.-8,%a1
 +	jmp (%pc,%a1)
+diff --git a/src/signal/psiginfo.c b/src/signal/psiginfo.c
+index 57be34cd..2b15982b 100644
+--- a/src/signal/psiginfo.c
++++ b/src/signal/psiginfo.c
+@@ -1,10 +1,6 @@
+-#include <stdio.h>
+-#include <string.h>
+ #include <signal.h>
+ 
+ void psiginfo(const siginfo_t *si, const char *msg)
+ {
+-	char *s = strsignal(si->si_signo);
+-	if (msg) fprintf(stderr, "%s: %s\n", msg, s);
+-	else fprintf(stderr, "%s\n", s);
++	psignal(si->si_signo, msg);
+ }
+diff --git a/src/signal/psignal.c b/src/signal/psignal.c
+index 02f1c760..138dbe00 100644
+--- a/src/signal/psignal.c
++++ b/src/signal/psignal.c
+@@ -1,10 +1,27 @@
+-#include <stdio.h>
++#include "stdio_impl.h"
+ #include <string.h>
+ #include <signal.h>
++#include <errno.h>
+ 
+ void psignal(int sig, const char *msg)
+ {
++	FILE *f = stderr;
+ 	char *s = strsignal(sig);
+-	if (msg) fprintf(stderr, "%s: %s\n", msg, s);
+-	else fprintf(stderr, "%s\n", s);
++
++	FLOCK(f);
++
++	/* Save stderr's orientation and encoding rule, since psignal is not
++	 * permitted to change them. Save errno and restore it if there is no
++	 * error since fprintf might change it even on success but psignal is
++	 * not permitted to do so. */
++	void *old_locale = f->locale;
++	int old_mode = f->mode;
++	int old_errno = errno;
++
++	if (fprintf(f, "%s%s%s\n", msg?msg:"", msg?": ":"", s)>=0)
++		errno = old_errno;
++	f->mode = old_mode;
++	f->locale = old_locale;
++
++	FUNLOCK(f);
+ }
 diff --git a/src/signal/sigisemptyset.c b/src/signal/sigisemptyset.c
 index 312c66cf..68b86624 100644
 --- a/src/signal/sigisemptyset.c
@@ -5207,6 +5382,18 @@ index 9d967d6e..2ff75d8a 100644
 +	if (a_swap(&f->lock, 0) & MAYBE_WAITERS)
 +		__wake(&f->lock, 1, 1);
  }
+diff --git a/src/stdio/__stdio_exit.c b/src/stdio/__stdio_exit.c
+index 191b4454..5741070f 100644
+--- a/src/stdio/__stdio_exit.c
++++ b/src/stdio/__stdio_exit.c
+@@ -19,6 +19,7 @@ void __stdio_exit(void)
+ 	for (f=*__ofl_lock(); f; f=f->next) close_file(f);
+ 	close_file(__stdin_used);
+ 	close_file(__stdout_used);
++	close_file(__stderr_used);
+ }
+ 
+ weak_alias(__stdio_exit, __stdio_exit_needed);
 diff --git a/src/stdio/__stdio_read.c b/src/stdio/__stdio_read.c
 index f8fa6d3b..ea675da3 100644
 --- a/src/stdio/__stdio_read.c
@@ -5265,6 +5452,31 @@ index c3fa0eb0..6eb361e1 100644
  	return 0;
  }
  
+diff --git a/src/stdio/fileno.c b/src/stdio/fileno.c
+index ba7f9391..0bd0e988 100644
+--- a/src/stdio/fileno.c
++++ b/src/stdio/fileno.c
+@@ -1,13 +1,16 @@
+ #include "stdio_impl.h"
++#include <errno.h>
+ 
+ int fileno(FILE *f)
+ {
+-	/* f->fd never changes, but the lock must be obtained and released
+-	 * anyway since this function cannot return while another thread
+-	 * holds the lock. */
+ 	FLOCK(f);
++	int fd = f->fd;
+ 	FUNLOCK(f);
+-	return f->fd;
++	if (fd < 0) {
++		errno = EBADF;
++		return -1;
++	}
++	return fd;
+ }
+ 
+ weak_alias(fileno, fileno_unlocked);
 diff --git a/src/stdio/flockfile.c b/src/stdio/flockfile.c
 index a196c1ef..6806cf8b 100644
 --- a/src/stdio/flockfile.c
@@ -5286,7 +5498,7 @@ index a196c1ef..6806cf8b 100644
 +	__register_locked_file(f, __pthread_self());
  }
 diff --git a/src/stdio/fmemopen.c b/src/stdio/fmemopen.c
-index 2ce43d32..fb2656e3 100644
+index 2ce43d32..5e0eeb50 100644
 --- a/src/stdio/fmemopen.c
 +++ b/src/stdio/fmemopen.c
 @@ -9,6 +9,12 @@ struct cookie {
@@ -5312,7 +5524,7 @@ index 2ce43d32..fb2656e3 100644
  	int plus = !!strchr(mode, '+');
  	
  	if (!size || !strchr("rwa", *mode)) {
-@@ -86,29 +91,34 @@ FILE *fmemopen(void *restrict buf, size_t size, const char *restrict mode)
+@@ -86,29 +91,35 @@ FILE *fmemopen(void *restrict buf, size_t size, const char *restrict mode)
  		return 0;
  	}
  
@@ -5350,6 +5562,7 @@ index 2ce43d32..fb2656e3 100644
 +	if (!plus) f->f.flags = (*mode == 'r') ? F_NOWR : F_NORD;
 +	if (*mode == 'r') f->c.len = size;
 +	else if (*mode == 'a') f->c.len = f->c.pos = strnlen(buf, size);
++	else if (plus) *f->c.buf = 0;
  
 -	f->read = mread;
 -	f->write = mwrite;
@@ -5479,7 +5692,7 @@ index 1ccd8029..d4b23882 100644
  {
  	char *tmp;
 diff --git a/src/stdio/open_memstream.c b/src/stdio/open_memstream.c
-index eab024da..ee834234 100644
+index eab024da..40f5ad60 100644
 --- a/src/stdio/open_memstream.c
 +++ b/src/stdio/open_memstream.c
 @@ -12,6 +12,12 @@ struct cookie {
@@ -5495,7 +5708,7 @@ index eab024da..ee834234 100644
  static off_t ms_seek(FILE *f, off_t off, int whence)
  {
  	ssize_t base;
-@@ -57,34 +63,34 @@ static int ms_close(FILE *f)
+@@ -57,34 +63,35 @@ static int ms_close(FILE *f)
  
  FILE *open_memstream(char **bufp, size_t *sizep)
  {
@@ -5542,6 +5755,7 @@ index eab024da..ee834234 100644
 +	f->f.write = ms_write;
 +	f->f.seek = ms_seek;
 +	f->f.close = ms_close;
++	f->f.mode = -1;
  
 -	if (!libc.threaded) f->lock = -1;
 +	if (!libc.threaded) f->f.lock = -1;
@@ -5550,7 +5764,7 @@ index eab024da..ee834234 100644
 +	return __ofl_add(&f->f);
  }
 diff --git a/src/stdio/open_wmemstream.c b/src/stdio/open_wmemstream.c
-index 4d90cd97..cb693ea7 100644
+index 4d90cd97..a7c3a645 100644
 --- a/src/stdio/open_wmemstream.c
 +++ b/src/stdio/open_wmemstream.c
 @@ -14,6 +14,12 @@ struct cookie {
@@ -5566,7 +5780,7 @@ index 4d90cd97..cb693ea7 100644
  static off_t wms_seek(FILE *f, off_t off, int whence)
  {
  	ssize_t base;
-@@ -59,34 +65,34 @@ static int wms_close(FILE *f)
+@@ -59,34 +65,36 @@ static int wms_close(FILE *f)
  
  FILE *open_wmemstream(wchar_t **bufp, size_t *sizep)
  {
@@ -5613,13 +5827,40 @@ index 4d90cd97..cb693ea7 100644
 +	f->f.write = wms_write;
 +	f->f.seek = wms_seek;
 +	f->f.close = wms_close;
++
++	if (!libc.threaded) f->f.lock = -1;
  
 -	if (!libc.threaded) f->lock = -1;
-+	if (!libc.threaded) f->f.lock = -1;
++	fwide(&f->f, 1);
  
 -	return __ofl_add(f);
 +	return __ofl_add(&f->f);
  }
+diff --git a/src/stdio/perror.c b/src/stdio/perror.c
+index fdcb4d71..d0943f26 100644
+--- a/src/stdio/perror.c
++++ b/src/stdio/perror.c
+@@ -9,6 +9,11 @@ void perror(const char *msg)
+ 	char *errstr = strerror(errno);
+ 
+ 	FLOCK(f);
++
++	/* Save stderr's orientation and encoding rule, since perror is not
++	 * permitted to change them. */
++	void *old_locale = f->locale;
++	int old_mode = f->mode;
+ 	
+ 	if (msg && *msg) {
+ 		fwrite(msg, strlen(msg), 1, f);
+@@ -18,5 +23,8 @@ void perror(const char *msg)
+ 	fwrite(errstr, strlen(errstr), 1, f);
+ 	fputc('\n', f);
+ 
++	f->mode = old_mode;
++	f->locale = old_locale;
++
+ 	FUNLOCK(f);
+ }
 diff --git a/src/stdio/setvbuf.c b/src/stdio/setvbuf.c
 index 541a125f..06ea296c 100644
 --- a/src/stdio/setvbuf.c
@@ -5662,7 +5903,7 @@ index 541a125f..06ea296c 100644
  	f->flags |= F_SVB;
  
 diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
-index 50fb55c1..5e7be717 100644
+index 50fb55c1..2100eb5e 100644
 --- a/src/stdio/vfprintf.c
 +++ b/src/stdio/vfprintf.c
 @@ -220,6 +220,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
@@ -5673,6 +5914,22 @@ index 50fb55c1..5e7be717 100644
  			while (re--) round*=16;
  			if (*prefix=='-') {
  				y=-y;
+@@ -673,11 +674,12 @@ int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap)
+ 	if (f->mode < 1) f->flags &= ~F_ERR;
+ 	if (!f->buf_size) {
+ 		saved_buf = f->buf;
+-		f->wpos = f->wbase = f->buf = internal_buf;
++		f->buf = internal_buf;
+ 		f->buf_size = sizeof internal_buf;
+-		f->wend = internal_buf + sizeof internal_buf;
++		f->wpos = f->wbase = f->wend = 0;
+ 	}
+-	ret = printf_core(f, fmt, &ap2, nl_arg, nl_type);
++	if (!f->wend && __towrite(f)) ret = -1;
++	else ret = printf_core(f, fmt, &ap2, nl_arg, nl_type);
+ 	if (saved_buf) {
+ 		f->write(f, 0, 0);
+ 		if (!f->wpos) ret = -1;
 diff --git a/src/stdio/vfwprintf.c b/src/stdio/vfwprintf.c
 index e87ad42a..9d774fcc 100644
 --- a/src/stdio/vfwprintf.c
@@ -5795,6 +6052,38 @@ index 00000000..f2e12f23
 +	d = memset(d, 0, n);
 +	__asm__ __volatile__ ("" : : "r"(d) : "memory");
 +}
+diff --git a/src/thread/arm/__aeabi_read_tp.s b/src/thread/arm/__aeabi_read_tp.s
+index 9d0cd311..2585620c 100644
+--- a/src/thread/arm/__aeabi_read_tp.s
++++ b/src/thread/arm/__aeabi_read_tp.s
+@@ -2,7 +2,9 @@
+ .global __aeabi_read_tp
+ .type __aeabi_read_tp,%function
+ __aeabi_read_tp:
+-	push {r1,r2,r3,lr}
+-	bl __aeabi_read_tp_c
+-	pop {r1,r2,r3,lr}
+-	bx lr
++	ldr r0,1f
++	add r0,r0,pc
++	ldr r0,[r0]
++2:	bx r0
++	.align 2
++1:	.word __a_gettp_ptr - 2b
+diff --git a/src/thread/arm/__aeabi_read_tp_c.c b/src/thread/arm/__aeabi_read_tp_c.c
+deleted file mode 100644
+index 654bdc57..00000000
+--- a/src/thread/arm/__aeabi_read_tp_c.c
++++ /dev/null
+@@ -1,8 +0,0 @@
+-#include "pthread_impl.h"
+-#include <stdint.h>
+-
+-__attribute__((__visibility__("hidden")))
+-void *__aeabi_read_tp_c(void)
+-{
+-	return (void *)((uintptr_t)__pthread_self()-8+sizeof(struct pthread));
+-}
 diff --git a/src/thread/default_attr.c b/src/thread/default_attr.c
 new file mode 100644
 index 00000000..46fe98ee
@@ -5923,6 +6212,22 @@ index 51035852..ebf5dbea 100644
 +	move 	$4, $2
 +	li	$2, 6058
 +	syscall
+diff --git a/src/thread/powerpc64/syscall_cp.s b/src/thread/powerpc64/syscall_cp.s
+index d420dbde..ef50ed00 100644
+--- a/src/thread/powerpc64/syscall_cp.s
++++ b/src/thread/powerpc64/syscall_cp.s
+@@ -34,4 +34,11 @@ __cp_end:
+ 	blr
+ 
+ __cp_cancel:
++	mflr 0
++	bl 1f
++	.long .TOC.-.
++1:	mflr 3
++	lwa 2, 0(3)
++	add 2, 2, 3
++	mtlr 0
+ 	b __cancel
 diff --git a/src/thread/pthread_attr_init.c b/src/thread/pthread_attr_init.c
 index 8f6e3374..a962b460 100644
 --- a/src/thread/pthread_attr_init.c
@@ -5943,10 +6248,10 @@ index 8f6e3374..a962b460 100644
  	return 0;
  }
 diff --git a/src/thread/pthread_attr_setinheritsched.c b/src/thread/pthread_attr_setinheritsched.c
-index c91d8f83..e540e846 100644
+index c91d8f83..4115e2fe 100644
 --- a/src/thread/pthread_attr_setinheritsched.c
 +++ b/src/thread/pthread_attr_setinheritsched.c
-@@ -1,4 +1,25 @@
+@@ -1,8 +1,29 @@
  #include "pthread_impl.h"
 +#include "syscall.h"
 +
@@ -5972,6 +6277,61 @@ index c91d8f83..e540e846 100644
  
  int pthread_attr_setinheritsched(pthread_attr_t *a, int inherit)
  {
+-	if (inherit > 1U) return EINVAL;
++	if (inherit > 1U) return ENOTSUP;
+ 	a->_a_sched = inherit;
+ 	return 0;
+ }
+diff --git a/src/thread/pthread_attr_setscope.c b/src/thread/pthread_attr_setscope.c
+index 46b520c0..933bdb38 100644
+--- a/src/thread/pthread_attr_setscope.c
++++ b/src/thread/pthread_attr_setscope.c
+@@ -8,6 +8,6 @@ int pthread_attr_setscope(pthread_attr_t *a, int scope)
+ 	case PTHREAD_SCOPE_PROCESS:
+ 		return ENOTSUP;
+ 	default:
+-		return EINVAL;
++		return ENOTSUP;
+ 	}
+ }
+diff --git a/src/thread/pthread_barrierattr_setpshared.c b/src/thread/pthread_barrierattr_setpshared.c
+index b391461e..c2d2929d 100644
+--- a/src/thread/pthread_barrierattr_setpshared.c
++++ b/src/thread/pthread_barrierattr_setpshared.c
+@@ -2,6 +2,7 @@
+ 
+ int pthread_barrierattr_setpshared(pthread_barrierattr_t *a, int pshared)
+ {
++	if (pshared > 1U) return EINVAL;
+ 	a->__attr = pshared ? INT_MIN : 0;
+ 	return 0;
+ }
+diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c
+index 3d229223..5d458af2 100644
+--- a/src/thread/pthread_cancel.c
++++ b/src/thread/pthread_cancel.c
+@@ -61,6 +61,9 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
+ 
+ 	if (self->cancelasync || pc >= (uintptr_t)__cp_begin && pc < (uintptr_t)__cp_end) {
+ 		uc->uc_mcontext.MC_PC = (uintptr_t)__cp_cancel;
++#ifdef CANCEL_GOT
++		uc->uc_mcontext.MC_GOT = CANCEL_GOT;
++#endif
+ 		return;
+ 	}
+ 
+@@ -92,6 +95,10 @@ int pthread_cancel(pthread_t t)
+ 		init = 1;
+ 	}
+ 	a_store(&t->cancel, 1);
+-	if (t == pthread_self() && !t->cancelasync) return 0;
++	if (t == pthread_self()) {
++		if (t->canceldisable == PTHREAD_CANCEL_ENABLE && t->cancelasync)
++			pthread_exit(PTHREAD_CANCELED);
++		return 0;
++	}
+ 	return pthread_kill(t, SIGCANCEL);
+ }
 diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
 index 439ee363..27ace2c6 100644
 --- a/src/thread/pthread_create.c
@@ -6274,6 +6634,19 @@ index dc745b42..c353f6b5 100644
  	UNLOCK(t->killlock);
  	return r;
  }
+diff --git a/src/time/__tz.c b/src/time/__tz.c
+index 1dbb0b8f..814edcdf 100644
+--- a/src/time/__tz.c
++++ b/src/time/__tz.c
+@@ -230,7 +230,7 @@ static void do_tzset()
+ 			dst_off = __timezone - 3600;
+ 	} else {
+ 		__daylight = 0;
+-		dst_off = 0;
++		dst_off = __timezone;
+ 	}
+ 
+ 	if (*s == ',') s++, getrule(&s, r0);
 diff --git a/src/time/strftime.c b/src/time/strftime.c
 index 708875ee..d3f2add9 100644
 --- a/src/time/strftime.c
-- 
GitLab