summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/complex/catan.c25
-rw-r--r--src/complex/catanf.c28
-rw-r--r--src/complex/catanl.c24
-rw-r--r--src/conf/sysconf.c9
-rw-r--r--src/dirent/posix_getdents.c2
-rw-r--r--src/errno/__strerror.h2
-rw-r--r--src/exit/atexit.c12
-rw-r--r--src/exit/exit.c14
-rw-r--r--src/internal/syscall.h11
-rw-r--r--src/ldso/loongarch64/tlsdesc.s37
-rw-r--r--src/legacy/getusershell.c6
-rw-r--r--src/linux/renameat2.c11
-rw-r--r--src/linux/statx.c4
-rw-r--r--src/locale/bind_textdomain_codeset.c6
-rw-r--r--src/locale/codepages.h11
-rw-r--r--src/locale/iconv.c8
-rw-r--r--src/math/powl.c8
-rw-r--r--src/misc/mntent.c12
-rw-r--r--src/mq/x32/mq_open.c22
-rw-r--r--src/mq/x32/mq_setattr.c14
-rw-r--r--src/multibyte/mbsnrtowcs.c6
-rw-r--r--src/network/inet_ntop.c7
-rw-r--r--src/network/res_msend.c2
-rw-r--r--src/signal/riscv32/restore.s2
-rw-r--r--src/signal/riscv64/restore.s2
-rw-r--r--src/signal/sigaltstack.c4
-rw-r--r--src/signal/siglongjmp.c5
-rw-r--r--src/signal/sigpause.c2
-rw-r--r--src/stdio/__stdio_write.c5
-rw-r--r--src/stdio/vfprintf.c18
-rw-r--r--src/stdlib/qsort.c2
-rw-r--r--src/string/strcasestr.c1
-rw-r--r--src/termios/cfgetospeed.c2
-rw-r--r--src/termios/cfsetospeed.c10
-rw-r--r--src/termios/cfsetspeed.c11
-rw-r--r--src/thread/aarch64/clone.s3
-rw-r--r--src/thread/arm/clone.s3
-rw-r--r--src/thread/loongarch64/clone.s1
-rw-r--r--src/thread/m68k/clone.s3
-rw-r--r--src/thread/microblaze/clone.s3
-rw-r--r--src/thread/mips/clone.s3
-rw-r--r--src/thread/mips64/clone.s3
-rw-r--r--src/thread/mipsn32/clone.s3
-rw-r--r--src/thread/or1k/clone.s5
-rw-r--r--src/thread/riscv32/clone.s1
-rw-r--r--src/thread/riscv64/clone.s1
-rw-r--r--src/thread/s390x/__tls_get_offset.s20
-rw-r--r--src/thread/sem_post.c2
-rw-r--r--src/time/__tz.c1
-rw-r--r--src/time/__utc.c3
-rw-r--r--src/time/timer_create.c29
-rw-r--r--src/unistd/isatty.c6
-rw-r--r--src/unistd/pause.c6
53 files changed, 296 insertions, 145 deletions
diff --git a/src/complex/catan.c b/src/complex/catan.c
index ccc2fb53..b4fe552a 100644
--- a/src/complex/catan.c
+++ b/src/complex/catan.c
@@ -60,29 +60,6 @@
#include "complex_impl.h"
-#define MAXNUM 1.0e308
-
-static const double DP1 = 3.14159265160560607910E0;
-static const double DP2 = 1.98418714791870343106E-9;
-static const double DP3 = 1.14423774522196636802E-17;
-
-static double _redupi(double x)
-{
- double t;
- long i;
-
- t = x/M_PI;
- if (t >= 0.0)
- t += 0.5;
- else
- t -= 0.5;
-
- i = t; /* the multiple */
- t = i;
- t = ((x - t * DP1) - t * DP2) - t * DP3;
- return t;
-}
-
double complex catan(double complex z)
{
double complex w;
@@ -95,7 +72,7 @@ double complex catan(double complex z)
a = 1.0 - x2 - (y * y);
t = 0.5 * atan2(2.0 * x, a);
- w = _redupi(t);
+ w = t;
t = y - 1.0;
a = x2 + (t * t);
diff --git a/src/complex/catanf.c b/src/complex/catanf.c
index 1d569f2d..faaa907a 100644
--- a/src/complex/catanf.c
+++ b/src/complex/catanf.c
@@ -55,32 +55,6 @@
#include "complex_impl.h"
-#define MAXNUMF 1.0e38F
-
-static const double DP1 = 3.140625;
-static const double DP2 = 9.67502593994140625E-4;
-static const double DP3 = 1.509957990978376432E-7;
-
-static const float float_pi = M_PI;
-
-static float _redupif(float xx)
-{
- float x, t;
- long i;
-
- x = xx;
- t = x/float_pi;
- if (t >= 0.0f)
- t += 0.5f;
- else
- t -= 0.5f;
-
- i = t; /* the multiple */
- t = i;
- t = ((x - t * DP1) - t * DP2) - t * DP3;
- return t;
-}
-
float complex catanf(float complex z)
{
float complex w;
@@ -93,7 +67,7 @@ float complex catanf(float complex z)
a = 1.0f - x2 - (y * y);
t = 0.5f * atan2f(2.0f * x, a);
- w = _redupif(t);
+ w = t;
t = y - 1.0f;
a = x2 + (t * t);
diff --git a/src/complex/catanl.c b/src/complex/catanl.c
index e62526c0..cd2d2b00 100644
--- a/src/complex/catanl.c
+++ b/src/complex/catanl.c
@@ -67,28 +67,6 @@ long double complex catanl(long double complex z)
return catan(z);
}
#else
-static const long double PIL = 3.141592653589793238462643383279502884197169L;
-static const long double DP1 = 3.14159265358979323829596852490908531763125L;
-static const long double DP2 = 1.6667485837041756656403424829301998703007e-19L;
-static const long double DP3 = 1.8830410776607851167459095484560349402753e-39L;
-
-static long double redupil(long double x)
-{
- long double t;
- long i;
-
- t = x / PIL;
- if (t >= 0.0L)
- t += 0.5L;
- else
- t -= 0.5L;
-
- i = t; /* the multiple */
- t = i;
- t = ((x - t * DP1) - t * DP2) - t * DP3;
- return t;
-}
-
long double complex catanl(long double complex z)
{
long double complex w;
@@ -101,7 +79,7 @@ long double complex catanl(long double complex z)
a = 1.0L - x2 - (y * y);
t = atan2l(2.0L * x, a) * 0.5L;
- w = redupil(t);
+ w = t;
t = y - 1.0L;
a = x2 + (t * t);
diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c
index 60d3e745..8dd5c725 100644
--- a/src/conf/sysconf.c
+++ b/src/conf/sysconf.c
@@ -220,8 +220,13 @@ long sysconf(int name)
return (mem > LONG_MAX) ? LONG_MAX : mem;
case JT_MINSIGSTKSZ & 255:
case JT_SIGSTKSZ & 255: ;
- long val = __getauxval(AT_MINSIGSTKSZ);
- if (val < MINSIGSTKSZ) val = MINSIGSTKSZ;
+ /* Value from auxv/kernel is only sigfame size. Clamp it
+ * to at least 1k below arch's traditional MINSIGSTKSZ,
+ * then add 1k of working space for signal handler. */
+ unsigned long sigframe_sz = __getauxval(AT_MINSIGSTKSZ);
+ if (sigframe_sz < MINSIGSTKSZ - 1024)
+ sigframe_sz = MINSIGSTKSZ - 1024;
+ unsigned val = sigframe_sz + 1024;
if (values[name] == JT_SIGSTKSZ)
val += SIGSTKSZ - MINSIGSTKSZ;
return val;
diff --git a/src/dirent/posix_getdents.c b/src/dirent/posix_getdents.c
index b19e8127..26c16ac6 100644
--- a/src/dirent/posix_getdents.c
+++ b/src/dirent/posix_getdents.c
@@ -3,7 +3,7 @@
#include <errno.h>
#include "syscall.h"
-int posix_getdents(int fd, void *buf, size_t len, int flags)
+ssize_t posix_getdents(int fd, void *buf, size_t len, int flags)
{
if (flags) return __syscall_ret(-EOPNOTSUPP);
if (len>INT_MAX) len = INT_MAX;
diff --git a/src/errno/__strerror.h b/src/errno/__strerror.h
index 14925907..0398b5b6 100644
--- a/src/errno/__strerror.h
+++ b/src/errno/__strerror.h
@@ -97,6 +97,8 @@ E(ESHUTDOWN, "Cannot send after socket shutdown")
E(EALREADY, "Operation already in progress")
E(EINPROGRESS, "Operation in progress")
E(ESTALE, "Stale file handle")
+E(EUCLEAN, "Data consistency error")
+E(ENAVAIL, "Resource not available")
E(EREMOTEIO, "Remote I/O error")
E(EDQUOT, "Quota exceeded")
E(ENOMEDIUM, "No medium found")
diff --git a/src/exit/atexit.c b/src/exit/atexit.c
index 854e9fdd..92c91c9d 100644
--- a/src/exit/atexit.c
+++ b/src/exit/atexit.c
@@ -19,6 +19,7 @@ static struct fl
void *a[COUNT];
} builtin, *head;
+static int finished_atexit;
static int slot;
static volatile int lock[1];
volatile int *const __atexit_lockptr = lock;
@@ -34,6 +35,10 @@ void __funcs_on_exit()
func(arg);
LOCK(lock);
}
+ /* Unlock to prevent deadlock if a global dtor
+ * attempts to call atexit. */
+ finished_atexit = 1;
+ UNLOCK(lock);
}
void __cxa_finalize(void *dso)
@@ -44,6 +49,13 @@ int __cxa_atexit(void (*func)(void *), void *arg, void *dso)
{
LOCK(lock);
+ /* Prevent dtors from registering further atexit
+ * handlers that would never be run. */
+ if (finished_atexit) {
+ UNLOCK(lock);
+ return -1;
+ }
+
/* Defer initialization of head so it can be in BSS */
if (!head) head = &builtin;
diff --git a/src/exit/exit.c b/src/exit/exit.c
index a6869b37..17b33cc6 100644
--- a/src/exit/exit.c
+++ b/src/exit/exit.c
@@ -1,6 +1,9 @@
#include <stdlib.h>
#include <stdint.h>
#include "libc.h"
+#include "pthread_impl.h"
+#include "atomic.h"
+#include "syscall.h"
static void dummy()
{
@@ -26,6 +29,17 @@ weak_alias(libc_exit_fini, __libc_exit_fini);
_Noreturn void exit(int code)
{
+ /* Handle potentially concurrent or recursive calls to exit,
+ * whose behaviors have traditionally been undefined by the
+ * standards. Using a custom lock here avoids pulling in lock
+ * machinery and lets us trap recursive calls while supporting
+ * multiple threads contending to be the one to exit(). */
+ static volatile int exit_lock[1];
+ int tid = __pthread_self()->tid;
+ int prev = a_cas(exit_lock, 0, tid);
+ if (prev == tid) a_crash();
+ else if (prev) for (;;) __sys_pause();
+
__funcs_on_exit();
__libc_exit_fini();
__stdio_exit();
diff --git a/src/internal/syscall.h b/src/internal/syscall.h
index 33d981f9..2d8a5c13 100644
--- a/src/internal/syscall.h
+++ b/src/internal/syscall.h
@@ -391,6 +391,17 @@ static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a,
#define __sys_open_cp(...) __SYSCALL_DISP(__sys_open_cp,,__VA_ARGS__)
#define sys_open_cp(...) __syscall_ret(__sys_open_cp(__VA_ARGS__))
+#ifdef SYS_pause
+#define __sys_pause() __syscall(SYS_pause)
+#define __sys_pause_cp() __syscall_cp(SYS_pause)
+#else
+#define __sys_pause() __syscall(SYS_ppoll, 0, 0, 0, 0)
+#define __sys_pause_cp() __syscall_cp(SYS_ppoll, 0, 0, 0, 0)
+#endif
+
+#define sys_pause() __syscall_ret(__sys_pause())
+#define sys_pause_cp() __syscall_ret(__sys_pause_cp())
+
#ifdef SYS_wait4
#define __sys_wait4(a,b,c,d) __syscall(SYS_wait4,a,b,c,d)
#define __sys_wait4_cp(a,b,c,d) __syscall_cp(SYS_wait4,a,b,c,d)
diff --git a/src/ldso/loongarch64/tlsdesc.s b/src/ldso/loongarch64/tlsdesc.s
new file mode 100644
index 00000000..4b6ea0e5
--- /dev/null
+++ b/src/ldso/loongarch64/tlsdesc.s
@@ -0,0 +1,37 @@
+.text
+.global __tlsdesc_static
+.hidden __tlsdesc_static
+.type __tlsdesc_static,%function
+__tlsdesc_static:
+ ld.d $a0, $a0, 8
+ jr $ra
+# size_t __tlsdesc_dynamic(size_t *a)
+# {
+# struct {size_t modidx,off;} *p = (void*)a[1];
+# size_t *dtv = *(size_t**)(tp - 8);
+# return dtv[p->modidx] + p->off - tp;
+# }
+.global __tlsdesc_dynamic
+.hidden __tlsdesc_dynamic
+.type __tlsdesc_dynamic,%function
+__tlsdesc_dynamic:
+ addi.d $sp, $sp, -16
+ st.d $t1, $sp, 0
+ st.d $t2, $sp, 8
+
+ ld.d $t2, $tp, -8 # t2=dtv
+
+ ld.d $a0, $a0, 8 # a0=&{modidx,off}
+ ld.d $t1, $a0, 8 # t1=off
+ ld.d $a0, $a0, 0 # a0=modidx
+ slli.d $a0, $a0, 3 # a0=8*modidx
+
+ add.d $a0, $a0, $t2 # a0=dtv+8*modidx
+ ld.d $a0, $a0, 0 # a0=dtv[modidx]
+ add.d $a0, $a0, $t1 # a0=dtv[modidx]+off
+ sub.d $a0, $a0, $tp # a0=dtv[modidx]+off-tp
+
+ ld.d $t1, $sp, 0
+ ld.d $t2, $sp, 8
+ addi.d $sp, $sp, 16
+ jr $ra
diff --git a/src/legacy/getusershell.c b/src/legacy/getusershell.c
index 5fecdec2..1c5d98ec 100644
--- a/src/legacy/getusershell.c
+++ b/src/legacy/getusershell.c
@@ -25,8 +25,10 @@ char *getusershell(void)
ssize_t l;
if (!f) setusershell();
if (!f) return 0;
- l = getline(&line, &linesize, f);
- if (l <= 0) return 0;
+ do {
+ l = getline(&line, &linesize, f);
+ if (l <= 0) return 0;
+ } while (line[0] == '#' || line[0] == '\n');
if (line[l-1]=='\n') line[l-1]=0;
return line;
}
diff --git a/src/linux/renameat2.c b/src/linux/renameat2.c
new file mode 100644
index 00000000..b8060388
--- /dev/null
+++ b/src/linux/renameat2.c
@@ -0,0 +1,11 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include "syscall.h"
+
+int renameat2(int oldfd, const char *old, int newfd, const char *new, unsigned flags)
+{
+#ifdef SYS_renameat
+ if (!flags) return syscall(SYS_renameat, oldfd, old, newfd, new);
+#endif
+ return syscall(SYS_renameat2, oldfd, old, newfd, new, flags);
+}
diff --git a/src/linux/statx.c b/src/linux/statx.c
index 4616bff4..4fb96e4b 100644
--- a/src/linux/statx.c
+++ b/src/linux/statx.c
@@ -19,8 +19,11 @@ int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct
ret = fstatat(dirfd, path, &st, flags);
if (ret) return ret;
+ *stx = (struct statx){0};
stx->stx_dev_major = major(st.st_dev);
stx->stx_dev_minor = minor(st.st_dev);
+ stx->stx_rdev_major = major(st.st_rdev);
+ stx->stx_rdev_minor = minor(st.st_rdev);
stx->stx_ino = st.st_ino;
stx->stx_mode = st.st_mode;
stx->stx_nlink = st.st_nlink;
@@ -35,7 +38,6 @@ int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct
stx->stx_mtime.tv_nsec = st.st_mtim.tv_nsec;
stx->stx_ctime.tv_sec = st.st_ctim.tv_sec;
stx->stx_ctime.tv_nsec = st.st_ctim.tv_nsec;
- stx->stx_btime = (struct statx_timestamp){.tv_sec=0, .tv_nsec=0};
stx->stx_mask = STATX_BASIC_STATS;
return 0;
diff --git a/src/locale/bind_textdomain_codeset.c b/src/locale/bind_textdomain_codeset.c
index 5ebfd5e8..240e83ed 100644
--- a/src/locale/bind_textdomain_codeset.c
+++ b/src/locale/bind_textdomain_codeset.c
@@ -5,7 +5,9 @@
char *bind_textdomain_codeset(const char *domainname, const char *codeset)
{
- if (codeset && strcasecmp(codeset, "UTF-8"))
+ if (codeset && strcasecmp(codeset, "UTF-8")) {
errno = EINVAL;
- return NULL;
+ return 0;
+ }
+ return "UTF-8";
}
diff --git a/src/locale/codepages.h b/src/locale/codepages.h
index 4e236ef3..a254f0f5 100644
--- a/src/locale/codepages.h
+++ b/src/locale/codepages.h
@@ -286,6 +286,17 @@
"\323\174\103\215\64\365\124\123\213\77\336\150\263\115\66\375\164\363\12\55"
"\255\304\42\261\57\266\234\162\17\56\260\240\162\113\56\263\310\62\66\50"
+"cp858\0"
+"\0\40"
+"\307\360\223\216\70\344\200\123\316\71\352\254\203\316\73\356\260\103\114\61"
+"\311\230\143\14\75\366\310\263\117\76\377\130\303\15\76\243\140\163\15\135"
+"\341\264\63\217\76\361\104\243\212\56\277\270\302\112\57\274\204\262\312\56"
+"\140\207\55\66\315\72\7\43\14\60\251\104\375\163\321\113\213\122\212\315"
+"\67\363\274\163\316\63\367\74\316\60\110\13\175\65\325\116\373\254\65\51"
+"\360\100\243\314\62\310\220\334\214\63\317\340\134\163\327\134\233\302\314\326"
+"\323\174\103\215\64\365\124\123\213\77\336\150\263\115\66\375\164\363\12\55"
+"\255\304\42\261\57\266\234\162\17\56\260\240\162\113\56\263\310\62\66\50"
+
"cp866\0"
"\0\40"
"\337\201\27\236\170\343\221\127\236\171\347\241\227\236\172"
diff --git a/src/locale/iconv.c b/src/locale/iconv.c
index 7fb2e1ef..52178950 100644
--- a/src/locale/iconv.c
+++ b/src/locale/iconv.c
@@ -339,6 +339,8 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
} else if (d-159 <= 252-159) {
c++;
d -= 159;
+ } else {
+ goto ilseq;
}
if (c>=84) goto ilseq;
c = jis0208[c][d];
@@ -500,7 +502,7 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
if (c >= 93 || d >= 94) {
c += (0xa1-0x81);
d += 0xa1;
- if (c >= 93 || c>=0xc6-0x81 && d>0x52)
+ if (c > 0xc6-0x81 || c==0xc6-0x81 && d>0x52)
goto ilseq;
if (d-'A'<26) d = d-'A';
else if (d-'a'<26) d = d-'a'+26;
@@ -543,6 +545,10 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
if (*outb < k) goto toobig;
memcpy(*out, tmp, k);
} else k = wctomb_utf8(*out, c);
+ /* This failure condition should be unreachable, but
+ * is included to prevent decoder bugs from translating
+ * into advancement outside the output buffer range. */
+ if (k>4) goto ilseq;
*out += k;
*outb -= k;
break;
diff --git a/src/math/powl.c b/src/math/powl.c
index 6f64ea71..9eb22162 100644
--- a/src/math/powl.c
+++ b/src/math/powl.c
@@ -57,14 +57,6 @@
* IEEE 0,8700 60000 6.5e-18 1.0e-18
* 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed.
*
- *
- * ERROR MESSAGES:
- *
- * message condition value returned
- * pow overflow x**y > MAXNUM INFINITY
- * pow underflow x**y < 1/MAXNUM 0.0
- * pow domain x<0 and y noninteger 0.0
- *
*/
#include "libm.h"
diff --git a/src/misc/mntent.c b/src/misc/mntent.c
index 78bf0cd0..76f9c162 100644
--- a/src/misc/mntent.c
+++ b/src/misc/mntent.c
@@ -81,7 +81,7 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle
len = strlen(linebuf);
if (len > INT_MAX) continue;
for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len;
- sscanf(linebuf, " %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %n%*[^ \t]%n %d %d",
+ sscanf(linebuf, " %n%*[^ \t\n]%n %n%*[^ \t\n]%n %n%*[^ \t\n]%n %n%*[^ \t\n]%n %d %d",
n, n+1, n+2, n+3, n+4, n+5, n+6, n+7,
&mnt->mnt_freq, &mnt->mnt_passno);
} while (linebuf[n[0]] == '#' || n[1]==len);
@@ -115,5 +115,13 @@ int addmntent(FILE *f, const struct mntent *mnt)
char *hasmntopt(const struct mntent *mnt, const char *opt)
{
- return strstr(mnt->mnt_opts, opt);
+ size_t l = strlen(opt);
+ char *p = mnt->mnt_opts;
+ for (;;) {
+ if (!strncmp(p, opt, l) && (!p[l] || p[l]==',' || p[l]=='='))
+ return p;
+ p = strchr(p, ',');
+ if (!p) return 0;
+ p++;
+ }
}
diff --git a/src/mq/x32/mq_open.c b/src/mq/x32/mq_open.c
new file mode 100644
index 00000000..23481959
--- /dev/null
+++ b/src/mq/x32/mq_open.c
@@ -0,0 +1,22 @@
+#include <mqueue.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include "syscall.h"
+
+mqd_t mq_open(const char *name, int flags, ...)
+{
+ mode_t mode = 0;
+ struct mq_attr *attr = 0;
+ long long attrbuf[8];
+ if (*name == '/') name++;
+ if (flags & O_CREAT) {
+ va_list ap;
+ va_start(ap, flags);
+ mode = va_arg(ap, mode_t);
+ attr = va_arg(ap, struct mq_attr *);
+ if (attr) for (int i=0; i<8; i++)
+ attrbuf[i] = *(long *)((char *)attr + i*sizeof(long));
+ va_end(ap);
+ }
+ return syscall(SYS_mq_open, name, flags, mode, attr?attrbuf:0);
+}
diff --git a/src/mq/x32/mq_setattr.c b/src/mq/x32/mq_setattr.c
new file mode 100644
index 00000000..0c631175
--- /dev/null
+++ b/src/mq/x32/mq_setattr.c
@@ -0,0 +1,14 @@
+#include <mqueue.h>
+#include "syscall.h"
+
+int mq_setattr(mqd_t mqd, const struct mq_attr *restrict new, struct mq_attr *restrict old)
+{
+ long long attr[8];
+ if (new) for (int i=0; i<8; i++)
+ attr[i] = *(long *)((char *)new + i*sizeof(long));
+ int ret = __syscall(SYS_mq_getsetattr, mqd, new?attr:0, old?attr:0);
+ if (ret < 0) return __syscall_ret(ret);
+ if (old) for (int i=0; i<8; i++)
+ *(long *)((char *)old + i*sizeof(long)) = attr[i];
+ return 0;
+}
diff --git a/src/multibyte/mbsnrtowcs.c b/src/multibyte/mbsnrtowcs.c
index 931192e2..47cbdc00 100644
--- a/src/multibyte/mbsnrtowcs.c
+++ b/src/multibyte/mbsnrtowcs.c
@@ -2,11 +2,13 @@
size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, size_t wn, mbstate_t *restrict st)
{
+ static unsigned internal_state;
size_t l, cnt=0, n2;
wchar_t *ws, wbuf[256];
const char *s = *src;
const char *tmp_s;
+ if (!st) st = (void *)&internal_state;
if (!wcs) ws = wbuf, wn = sizeof wbuf / sizeof *wbuf;
else ws = wcs;
@@ -41,8 +43,8 @@ size_t mbsnrtowcs(wchar_t *restrict wcs, const char **restrict src, size_t n, si
s = 0;
break;
}
- /* have to roll back partial character */
- *(unsigned *)st = 0;
+ s += n;
+ n -= n;
break;
}
s += l; n -= l;
diff --git a/src/network/inet_ntop.c b/src/network/inet_ntop.c
index 4bfef2c5..f442f47d 100644
--- a/src/network/inet_ntop.c
+++ b/src/network/inet_ntop.c
@@ -34,7 +34,12 @@ const char *inet_ntop(int af, const void *restrict a0, char *restrict s, socklen
for (i=best=0, max=2; buf[i]; i++) {
if (i && buf[i] != ':') continue;
j = strspn(buf+i, ":0");
- if (j>max) best=i, max=j;
+ /* The leading sequence of zeros (best==0) is
+ * disadvantaged compared to sequences elsewhere
+ * as it doesn't have a leading colon. One extra
+ * character is required for another sequence to
+ * beat it fairly. */
+ if (j>max+(best==0)) best=i, max=j;
}
if (max>3) {
buf[best] = buf[best+1] = ':';
diff --git a/src/network/res_msend.c b/src/network/res_msend.c
index 86c2fcf4..fcb52513 100644
--- a/src/network/res_msend.c
+++ b/src/network/res_msend.c
@@ -83,8 +83,8 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
int fd;
int timeout, attempts, retry_interval, servfail_retry;
union {
- struct sockaddr_in sin;
struct sockaddr_in6 sin6;
+ struct sockaddr_in sin;
} sa = {0}, ns[MAXNS] = {{0}};
socklen_t sl = sizeof sa.sin;
int nns = 0;
diff --git a/src/signal/riscv32/restore.s b/src/signal/riscv32/restore.s
index 40012c75..5a0af695 100644
--- a/src/signal/riscv32/restore.s
+++ b/src/signal/riscv32/restore.s
@@ -1,7 +1,9 @@
.global __restore
+.hidden __restore
.type __restore, %function
__restore:
.global __restore_rt
+.hidden __restore_rt
.type __restore_rt, %function
__restore_rt:
li a7, 139 # SYS_rt_sigreturn
diff --git a/src/signal/riscv64/restore.s b/src/signal/riscv64/restore.s
index 40012c75..5a0af695 100644
--- a/src/signal/riscv64/restore.s
+++ b/src/signal/riscv64/restore.s
@@ -1,7 +1,9 @@
.global __restore
+.hidden __restore
.type __restore, %function
__restore:
.global __restore_rt
+.hidden __restore_rt
.type __restore_rt, %function
__restore_rt:
li a7, 139 # SYS_rt_sigreturn
diff --git a/src/signal/sigaltstack.c b/src/signal/sigaltstack.c
index d3a6e821..616625c5 100644
--- a/src/signal/sigaltstack.c
+++ b/src/signal/sigaltstack.c
@@ -1,11 +1,13 @@
#include <signal.h>
#include <errno.h>
+#include <unistd.h>
#include "syscall.h"
int sigaltstack(const stack_t *restrict ss, stack_t *restrict old)
{
if (ss) {
- if (!(ss->ss_flags & SS_DISABLE) && ss->ss_size < MINSIGSTKSZ) {
+ size_t min = sysconf(_SC_MINSIGSTKSZ);
+ if (!(ss->ss_flags & SS_DISABLE) && ss->ss_size < min) {
errno = ENOMEM;
return -1;
}
diff --git a/src/signal/siglongjmp.c b/src/signal/siglongjmp.c
index bc317acc..53789b23 100644
--- a/src/signal/siglongjmp.c
+++ b/src/signal/siglongjmp.c
@@ -5,5 +5,10 @@
_Noreturn void siglongjmp(sigjmp_buf buf, int ret)
{
+ /* If sigsetjmp was called with nonzero savemask flag, the address
+ * longjmp will return to is inside of sigsetjmp. The signal mask
+ * will then be restored in the returned-to context instead of here,
+ * which matters if the context we are returning from may not have
+ * sufficient stack space for signal delivery. */
longjmp(buf, ret);
}
diff --git a/src/signal/sigpause.c b/src/signal/sigpause.c
index 363d2fec..1587c391 100644
--- a/src/signal/sigpause.c
+++ b/src/signal/sigpause.c
@@ -4,6 +4,6 @@ int sigpause(int sig)
{
sigset_t mask;
sigprocmask(0, 0, &mask);
- sigdelset(&mask, sig);
+ if (sigdelset(&mask, sig)) return -1;
return sigsuspend(&mask);
}
diff --git a/src/stdio/__stdio_write.c b/src/stdio/__stdio_write.c
index d2d89475..5356553d 100644
--- a/src/stdio/__stdio_write.c
+++ b/src/stdio/__stdio_write.c
@@ -11,6 +11,11 @@ size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
size_t rem = iov[0].iov_len + iov[1].iov_len;
int iovcnt = 2;
ssize_t cnt;
+
+ if (!iov->iov_len) {
+ iov++;
+ iovcnt--;
+ }
for (;;) {
cnt = syscall(SYS_writev, f->fd, iov, iovcnt);
if (cnt == rem) {
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index 360d723a..76733997 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -178,10 +178,14 @@ static char *fmt_u(uintmax_t x, char *s)
typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)];
#endif
-static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
+static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t, int ps)
{
- uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion
- + (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion
+ int bufsize = (ps==BIGLPRE)
+ ? (LDBL_MANT_DIG+28)/29 + 1 + // mantissa expansion
+ (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9 // exponent expansion
+ : (DBL_MANT_DIG+28)/29 + 1 +
+ (DBL_MAX_EXP+DBL_MANT_DIG+28+8)/9;
+ uint32_t big[bufsize];
uint32_t *a, *d, *r, *z;
int e2=0, e, i, j, l;
char buf[9+LDBL_MANT_DIG/4], *s;
@@ -557,11 +561,11 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
case 'x': case 'X':
a = fmt_x(arg.i, z, t&32);
if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
- if (0) {
+ goto ifmt_tail;
case 'o':
a = fmt_o(arg.i, z);
if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1;
- } if (0) {
+ goto ifmt_tail;
case 'd': case 'i':
pl=1;
if (arg.i>INTMAX_MAX) {
@@ -573,7 +577,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
} else pl=0;
case 'u':
a = fmt_u(arg.i, z);
- }
+ ifmt_tail:
if (xp && p<0) goto overflow;
if (xp) fl &= ~ZERO_PAD;
if (!arg.i && !p) {
@@ -618,7 +622,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
case 'e': case 'f': case 'g': case 'a':
case 'E': case 'F': case 'G': case 'A':
if (xp && p<0) goto overflow;
- l = fmt_fp(f, arg.f, w, p, fl, t);
+ l = fmt_fp(f, arg.f, w, p, fl, t, ps);
if (l<0) goto overflow;
continue;
}
diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c
index 314ddc29..ab79dc6f 100644
--- a/src/stdlib/qsort.c
+++ b/src/stdlib/qsort.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 by Valentin Ochs
+/* Copyright (C) 2011 by Lynn Ochs
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
diff --git a/src/string/strcasestr.c b/src/string/strcasestr.c
index af109f36..dc598bc3 100644
--- a/src/string/strcasestr.c
+++ b/src/string/strcasestr.c
@@ -4,6 +4,7 @@
char *strcasestr(const char *h, const char *n)
{
size_t l = strlen(n);
+ if (!l) return (char *)h;
for (; *h; h++) if (!strncasecmp(h, n, l)) return (char *)h;
return 0;
}
diff --git a/src/termios/cfgetospeed.c b/src/termios/cfgetospeed.c
index 55fa6f55..de46a1d8 100644
--- a/src/termios/cfgetospeed.c
+++ b/src/termios/cfgetospeed.c
@@ -9,5 +9,5 @@ speed_t cfgetospeed(const struct termios *tio)
speed_t cfgetispeed(const struct termios *tio)
{
- return cfgetospeed(tio);
+ return (tio->c_cflag & CIBAUD) / (CIBAUD/CBAUD);
}
diff --git a/src/termios/cfsetospeed.c b/src/termios/cfsetospeed.c
index c9cbdd9d..3eab092a 100644
--- a/src/termios/cfsetospeed.c
+++ b/src/termios/cfsetospeed.c
@@ -16,7 +16,11 @@ int cfsetospeed(struct termios *tio, speed_t speed)
int cfsetispeed(struct termios *tio, speed_t speed)
{
- return speed ? cfsetospeed(tio, speed) : 0;
+ if (speed & ~CBAUD) {
+ errno = EINVAL;
+ return -1;
+ }
+ tio->c_cflag &= ~CIBAUD;
+ tio->c_cflag |= speed * (CIBAUD/CBAUD);
+ return 0;
}
-
-weak_alias(cfsetospeed, cfsetspeed);
diff --git a/src/termios/cfsetspeed.c b/src/termios/cfsetspeed.c
new file mode 100644
index 00000000..2c369db9
--- /dev/null
+++ b/src/termios/cfsetspeed.c
@@ -0,0 +1,11 @@
+#define _BSD_SOURCE
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+int cfsetspeed(struct termios *tio, speed_t speed)
+{
+ int r = cfsetospeed(tio, speed);
+ if (!r) cfsetispeed(tio, 0);
+ return r;
+}
diff --git a/src/thread/aarch64/clone.s b/src/thread/aarch64/clone.s
index e3c83395..9ac272bd 100644
--- a/src/thread/aarch64/clone.s
+++ b/src/thread/aarch64/clone.s
@@ -24,7 +24,8 @@ __clone:
// parent
ret
// child
-1: ldp x1,x0,[sp],#16
+1: mov fp, 0
+ ldp x1,x0,[sp],#16
blr x1
mov x8,#93 // SYS_exit
svc #0
diff --git a/src/thread/arm/clone.s b/src/thread/arm/clone.s
index bb0965da..4ff0c0e8 100644
--- a/src/thread/arm/clone.s
+++ b/src/thread/arm/clone.s
@@ -19,7 +19,8 @@ __clone:
ldmfd sp!,{r4,r5,r6,r7}
bx lr
-1: mov r0,r6
+1: mov fp,#0
+ mov r0,r6
bl 3f
2: mov r7,#1
svc 0
diff --git a/src/thread/loongarch64/clone.s b/src/thread/loongarch64/clone.s
index a165b365..cb4aacfc 100644
--- a/src/thread/loongarch64/clone.s
+++ b/src/thread/loongarch64/clone.s
@@ -22,6 +22,7 @@ __clone:
beqz $a0, 1f # whether child process
jirl $zero, $ra, 0 # parent process return
1:
+ move $fp, $zero
ld.d $t8, $sp, 0 # function pointer
ld.d $a0, $sp, 8 # argument pointer
jirl $ra, $t8, 0 # call the user's function
diff --git a/src/thread/m68k/clone.s b/src/thread/m68k/clone.s
index f6dfa06f..0134cf4e 100644
--- a/src/thread/m68k/clone.s
+++ b/src/thread/m68k/clone.s
@@ -18,7 +18,8 @@ __clone:
beq 1f
movem.l (%sp)+,%d2-%d5
rts
-1: move.l %a1,-(%sp)
+1: suba.l %fp,%fp
+ move.l %a1,-(%sp)
jsr (%a0)
move.l #1,%d0
trap #0
diff --git a/src/thread/microblaze/clone.s b/src/thread/microblaze/clone.s
index b68cc5fc..64e3f074 100644
--- a/src/thread/microblaze/clone.s
+++ b/src/thread/microblaze/clone.s
@@ -22,7 +22,8 @@ __clone:
rtsd r15, 8
nop
-1: lwi r3, r1, 0
+1: add r19, r0, r0
+ lwi r3, r1, 0
lwi r5, r1, 4
brald r15, r3
nop
diff --git a/src/thread/mips/clone.s b/src/thread/mips/clone.s
index 04463385..229b987e 100644
--- a/src/thread/mips/clone.s
+++ b/src/thread/mips/clone.s
@@ -27,7 +27,8 @@ __clone:
addu $sp, $sp, 16
jr $ra
nop
-1: lw $25, 0($sp)
+1: move $fp, $0
+ lw $25, 0($sp)
lw $4, 4($sp)
jalr $25
nop
diff --git a/src/thread/mips64/clone.s b/src/thread/mips64/clone.s
index 2d86899a..8de3db6c 100644
--- a/src/thread/mips64/clone.s
+++ b/src/thread/mips64/clone.s
@@ -25,7 +25,8 @@ __clone:
nop
jr $ra
nop
-1: ld $25, 0($sp) # function pointer
+1: move $fp, $0
+ ld $25, 0($sp) # function pointer
ld $4, 8($sp) # argument pointer
jalr $25 # call the user's function
nop
diff --git a/src/thread/mipsn32/clone.s b/src/thread/mipsn32/clone.s
index 4d3c8c7a..9571231a 100644
--- a/src/thread/mipsn32/clone.s
+++ b/src/thread/mipsn32/clone.s
@@ -25,7 +25,8 @@ __clone:
nop
jr $ra
nop
-1: lw $25, 0($sp) # function pointer
+1: move $fp, $0
+ lw $25, 0($sp) # function pointer
lw $4, 4($sp) # argument pointer
jalr $25 # call the user's function
nop
diff --git a/src/thread/or1k/clone.s b/src/thread/or1k/clone.s
index 2473ac20..b41488a2 100644
--- a/src/thread/or1k/clone.s
+++ b/src/thread/or1k/clone.s
@@ -6,6 +6,8 @@
.hidden __clone
.type __clone,@function
__clone:
+ l.xori r11, r0, -4
+ l.and r4, r4, r11
l.addi r4, r4, -8
l.sw 0(r4), r3
l.sw 4(r4), r6
@@ -23,7 +25,8 @@ __clone:
l.jr r9
l.nop
-1: l.lwz r11, 0(r1)
+1: l.ori r2, r0, 0
+ l.lwz r11, 0(r1)
l.jalr r11
l.lwz r3, 4(r1)
diff --git a/src/thread/riscv32/clone.s b/src/thread/riscv32/clone.s
index 3102239d..e2116e33 100644
--- a/src/thread/riscv32/clone.s
+++ b/src/thread/riscv32/clone.s
@@ -8,6 +8,7 @@
.type __clone, %function
__clone:
# Save func and arg to stack
+ andi a1, a1, -16
addi a1, a1, -16
sw a0, 0(a1)
sw a3, 4(a1)
diff --git a/src/thread/riscv64/clone.s b/src/thread/riscv64/clone.s
index db908248..0e6f41a8 100644
--- a/src/thread/riscv64/clone.s
+++ b/src/thread/riscv64/clone.s
@@ -8,6 +8,7 @@
.type __clone, %function
__clone:
# Save func and arg to stack
+ andi a1, a1, -16
addi a1, a1, -16
sd a0, 0(a1)
sd a3, 8(a1)
diff --git a/src/thread/s390x/__tls_get_offset.s b/src/thread/s390x/__tls_get_offset.s
index 8ee92de8..405f118b 100644
--- a/src/thread/s390x/__tls_get_offset.s
+++ b/src/thread/s390x/__tls_get_offset.s
@@ -1,17 +1,17 @@
.global __tls_get_offset
.type __tls_get_offset,%function
__tls_get_offset:
- stmg %r14, %r15, 112(%r15)
- aghi %r15, -160
+ ear %r0, %a0
+ sllg %r0, %r0, 32
+ ear %r0, %a1
- la %r2, 0(%r2, %r12)
- brasl %r14, __tls_get_addr
+ la %r1, 0(%r2, %r12)
- ear %r1, %a0
- sllg %r1, %r1, 32
- ear %r1, %a1
+ lg %r3, 0(%r1)
+ sllg %r4, %r3, 3
+ lg %r5, 8(%r0)
+ lg %r2, 0(%r4, %r5)
+ ag %r2, 8(%r1)
+ sgr %r2, %r0
- sgr %r2, %r1
-
- lmg %r14, %r15, 272(%r15)
br %r14
diff --git a/src/thread/sem_post.c b/src/thread/sem_post.c
index 5c2517f2..1c8f763c 100644
--- a/src/thread/sem_post.c
+++ b/src/thread/sem_post.c
@@ -16,6 +16,6 @@ int sem_post(sem_t *sem)
if (waiters <= 1)
new &= ~0x80000000;
} while (a_cas(sem->__val, val, new) != val);
- if (val<0) __wake(sem->__val, waiters>1 ? 1 : -1, priv);
+ if (val<0 || waiters) __wake(sem->__val, waiters>1 ? 1 : -1, priv);
return 0;
}
diff --git a/src/time/__tz.c b/src/time/__tz.c
index c34b3eb7..54ed4cf6 100644
--- a/src/time/__tz.c
+++ b/src/time/__tz.c
@@ -24,7 +24,6 @@ weak_alias(__tzname, tzname);
static char std_name[TZNAME_MAX+1];
static char dst_name[TZNAME_MAX+1];
-const char __utc[] = "UTC";
static int dst_off;
static int r0[5], r1[5];
diff --git a/src/time/__utc.c b/src/time/__utc.c
new file mode 100644
index 00000000..9e8bfc58
--- /dev/null
+++ b/src/time/__utc.c
@@ -0,0 +1,3 @@
+#include "time_impl.h"
+
+const char __utc[] = "UTC";
diff --git a/src/time/timer_create.c b/src/time/timer_create.c
index 9216b3ab..cc6c2236 100644
--- a/src/time/timer_create.c
+++ b/src/time/timer_create.c
@@ -1,6 +1,7 @@
#include <time.h>
#include <setjmp.h>
#include <limits.h>
+#include <semaphore.h>
#include "pthread_impl.h"
#include "atomic.h"
@@ -12,7 +13,7 @@ struct ksigevent {
};
struct start_args {
- pthread_barrier_t b;
+ sem_t sem1, sem2;
struct sigevent *sev;
};
@@ -21,10 +22,16 @@ static void dummy_0()
}
weak_alias(dummy_0, __pthread_tsd_run_dtors);
+static void timer_handler(int sig, siginfo_t *si, void *ctx)
+{
+}
+
static void cleanup_fromsig(void *p)
{
pthread_t self = __pthread_self();
__pthread_tsd_run_dtors();
+ __block_app_sigs(0);
+ __syscall(SYS_rt_sigprocmask, SIG_BLOCK, SIGTIMER_SET, 0, _NSIG/8);
self->cancel = 0;
self->cancelbuf = 0;
self->canceldisable = 0;
@@ -42,7 +49,14 @@ static void *start(void *arg)
void (*notify)(union sigval) = args->sev->sigev_notify_function;
union sigval val = args->sev->sigev_value;
- pthread_barrier_wait(&args->b);
+ /* The two-way semaphore synchronization ensures that we see
+ * self->cancel set by the parent if timer creation failed or
+ * self->timer_id if it succeeded, and informs the parent that
+ * we are done accessing the arguments so that the parent can
+ * proceed past their block lifetime. */
+ while (sem_wait(&args->sem1));
+ sem_post(&args->sem2);
+
if (self->cancel)
return 0;
for (;;) {
@@ -90,7 +104,10 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
break;
case SIGEV_THREAD:
if (!init) {
- struct sigaction sa = { .sa_handler = SIG_DFL };
+ struct sigaction sa = {
+ .sa_sigaction = timer_handler,
+ .sa_flags = SA_SIGINFO | SA_RESTART
+ };
__libc_sigaction(SIGTIMER, &sa, 0);
a_store(&init, 1);
}
@@ -99,7 +116,8 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
else
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_barrier_init(&args.b, 0, 2);
+ sem_init(&args.sem1, 0, 0);
+ sem_init(&args.sem2, 0, 0);
args.sev = evp;
__block_app_sigs(&set);
@@ -120,7 +138,8 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
td->cancel = 1;
}
td->timer_id = timerid;
- pthread_barrier_wait(&args.b);
+ sem_post(&args.sem1);
+ while (sem_wait(&args.sem2));
if (timerid < 0) return -1;
*res = (void *)(INTPTR_MIN | (uintptr_t)td>>1);
break;
diff --git a/src/unistd/isatty.c b/src/unistd/isatty.c
index 75a9c186..21222eda 100644
--- a/src/unistd/isatty.c
+++ b/src/unistd/isatty.c
@@ -6,8 +6,6 @@
int isatty(int fd)
{
struct winsize wsz;
- unsigned long r = syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz);
- if (r == 0) return 1;
- if (errno != EBADF) errno = ENOTTY;
- return 0;
+ /* +1 converts from error status (0/-1) to boolean (1/0) */
+ return syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz) + 1;
}
diff --git a/src/unistd/pause.c b/src/unistd/pause.c
index 90bbf4ca..90cc8db5 100644
--- a/src/unistd/pause.c
+++ b/src/unistd/pause.c
@@ -3,9 +3,5 @@
int pause(void)
{
-#ifdef SYS_pause
- return syscall_cp(SYS_pause);
-#else
- return syscall_cp(SYS_ppoll, 0, 0, 0, 0);
-#endif
+ return sys_pause_cp();
}