Snap for 8096610 from 2118fe8b9824bf1ccf5c530cc2c0e0634154bf64 to sdk-release
Change-Id: I7ccf085d9b4d167b233f1fa2092e2074bccfe47b
diff --git a/arch/mips/pthread_arch.h b/arch/mips/pthread_arch.h
index c45347a..376b774 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/powerpc/bits/fenv.h b/arch/powerpc/bits/fenv.h
index c5a3e5c..5b15c69 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 fb1d402..7f1ca17 100644
--- a/arch/powerpc/bits/shm.h
+++ b/arch/powerpc/bits/shm.h
@@ -8,11 +8,11 @@
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/reloc.h b/arch/powerpc/reloc.h
index 527b6b7..fdfbf82 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/configure b/configure
index a5231a0..e1aefed 100755
--- a/configure
+++ b/configure
@@ -671,9 +671,7 @@
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/locale.h b/include/locale.h
index ce38438..11106fe 100644
--- a/include/locale.h
+++ b/include/locale.h
@@ -7,7 +7,9 @@
#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/stddef.h b/include/stddef.h
index bd75385..f25b863 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 3604198..d1ed01f 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -25,7 +25,9 @@
#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 b54a051..b507ca3 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -7,7 +7,9 @@
#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 @@
#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 795a2ab..43ad094 100644
--- a/include/string.h
+++ b/include/string.h
@@ -7,7 +7,9 @@
#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/time.h b/include/time.h
index 5494df1..3d94837 100644
--- a/include/time.h
+++ b/include/time.h
@@ -7,7 +7,9 @@
#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 1306402..ee2dbe8 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -15,7 +15,9 @@
#define SEEK_CUR 1
#define SEEK_END 2
-#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 88eb55b..ed5d774 100644
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -38,7 +38,9 @@
#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/sources.bp b/sources.bp
index c9ef3c2..bb55ddb 100644
--- a/sources.bp
+++ b/sources.bp
@@ -990,6 +990,7 @@
"src/stdlib/llabs.c",
"src/stdlib/lldiv.c",
"src/stdlib/qsort.c",
+ "src/stdlib/qsort_nr.c",
"src/stdlib/strtod.c",
"src/stdlib/strtol.c",
"src/stdlib/wcstod.c",
diff --git a/src/fenv/powerpc/fenv-sf.c b/src/fenv/powerpc/fenv-sf.c
index 85bef40..d4248f2 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 22cea21..55055d0 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 e9da201..812b04d 100644
--- a/src/include/stdlib.h
+++ b/src/include/stdlib.h
@@ -8,6 +8,7 @@
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/math/fmaf.c b/src/math/fmaf.c
index 80f5cd8..7c65acf 100644
--- a/src/math/fmaf.c
+++ b/src/math/fmaf.c
@@ -77,17 +77,16 @@
* 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 0efc21e..9453a3a 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 d88b591..2e9da58 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 135c990..0eb2ba1 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 a99a2a3..dc1a749 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 4928281..35804f0 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 @@
{ _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 @@
* 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/setjmp/powerpc/longjmp.S b/src/setjmp/powerpc/longjmp.S
index e598bd0..611389f 100644
--- a/src/setjmp/powerpc/longjmp.S
+++ b/src/setjmp/powerpc/longjmp.S
@@ -37,7 +37,37 @@
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 cd91a20..f1fcce3 100644
--- a/src/setjmp/powerpc/setjmp.S
+++ b/src/setjmp/powerpc/setjmp.S
@@ -37,7 +37,37 @@
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 d7f6100..cc8698f 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/getdelim.c b/src/stdio/getdelim.c
index d2f5b15..df11444 100644
--- a/src/stdio/getdelim.c
+++ b/src/stdio/getdelim.c
@@ -55,9 +55,11 @@
*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/stdlib/qsort.c b/src/stdlib/qsort.c
index da58fd3..314ddc2 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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 0000000..efe7cce
--- /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/thread/pthread_getname_np.c b/src/thread/pthread_getname_np.c
index 48d1a29..85504e4 100644
--- a/src/thread/pthread_getname_np.c
+++ b/src/thread/pthread_getname_np.c
@@ -17,7 +17,7 @@
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)) < 0) status = errno;
+ 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);
diff --git a/src/time/__tz.c b/src/time/__tz.c
index 09a6317..3e2fcdc 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 @@
}
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"))