diff options
-rw-r--r-- | src/time/__tz.c | 20 | ||||
-rw-r--r-- | src/time/gmtime_r.c | 4 | ||||
-rw-r--r-- | src/time/strftime.c | 16 | ||||
-rw-r--r-- | src/time/timegm.c | 4 |
4 files changed, 36 insertions, 8 deletions
diff --git a/src/time/__tz.c b/src/time/__tz.c index 36b59802..dfeac519 100644 --- a/src/time/__tz.c +++ b/src/time/__tz.c @@ -15,11 +15,12 @@ weak_alias(__tzname, tzname); static char std_name[TZNAME_MAX+1]; static char dst_name[TZNAME_MAX+1]; +const char __gmt[] = "GMT"; static int dst_off; static int r0[5], r1[5]; -static const unsigned char *zi, *trans, *index, *types, *abbrevs; +static const unsigned char *zi, *trans, *index, *types, *abbrevs, *abbrevs_end; static size_t map_size; static char old_tz_buf[32]; @@ -127,7 +128,7 @@ static void do_tzset() "/usr/share/zoneinfo/\0/share/zoneinfo/\0/etc/zoneinfo/\0"; s = getenv("TZ"); - if (!s || !*s) s = "GMT0"; + if (!s || !*s) s = __gmt; if (old_tz && !strcmp(s, old_tz)) return; @@ -184,6 +185,7 @@ static void do_tzset() index = trans + (zi_read32(trans-12) << scale); types = index + zi_read32(trans-12); abbrevs = types + 6*zi_read32(trans-8); + abbrevs_end = abbrevs + zi_read32(trans-4); if (zi[map_size-1] == '\n') { for (s = (const char *)zi+map_size-2; *s!='\n'; s--); s++; @@ -192,7 +194,7 @@ static void do_tzset() } } - if (!s) s = "GMT0"; + if (!s) s = __gmt; getname(std_name, &s); __tzname[0] = std_name; __timezone = getoff(&s); @@ -387,3 +389,15 @@ void __tzset() } weak_alias(__tzset, tzset); + +const char *__tm_to_tzname(const struct tm *tm) +{ + const void *p = tm->__tm_zone; + LOCK(lock); + do_tzset(); + if (p != __gmt && p != __tzname[0] && p != __tzname[1] + && (uintptr_t)p-(uintptr_t)abbrevs >= abbrevs_end - abbrevs) + p = ""; + UNLOCK(lock); + return p; +} diff --git a/src/time/gmtime_r.c b/src/time/gmtime_r.c index fee01bd6..8cbdadcb 100644 --- a/src/time/gmtime_r.c +++ b/src/time/gmtime_r.c @@ -2,6 +2,8 @@ #include <errno.h> #include "libc.h" +extern const char __gmt[]; + struct tm *__gmtime_r(const time_t *restrict t, struct tm *restrict tm) { if (__secs_to_tm(*t, tm) < 0) { @@ -10,7 +12,7 @@ struct tm *__gmtime_r(const time_t *restrict t, struct tm *restrict tm) } tm->tm_isdst = 0; tm->__tm_gmtoff = 0; - tm->__tm_zone = "GMT"; + tm->__tm_zone = __gmt; return tm; } diff --git a/src/time/strftime.c b/src/time/strftime.c index 24000f3b..48f65320 100644 --- a/src/time/strftime.c +++ b/src/time/strftime.c @@ -43,6 +43,7 @@ static int week_num(const struct tm *tm) return val; } +const char *__tm_to_tzname(const struct tm *); size_t __strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, locale_t); const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *tm, locale_t loc) @@ -166,11 +167,20 @@ const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm * width = 4; goto number; case 'z': - val = -tm->__tm_gmtoff; - *l = snprintf(*s, sizeof *s, "%+.2d%.2d", val/3600, abs(val%3600)/60); + if (tm->tm_isdst < 0) { + *l = 0; + return ""; + } + *l = snprintf(*s, sizeof *s, "%+.2d%.2d", + (-tm->__tm_gmtoff)/3600, + abs(tm->__tm_gmtoff%3600)/60); return *s; case 'Z': - fmt = tm->__tm_zone; + if (tm->tm_isdst < 0) { + *l = 0; + return ""; + } + fmt = __tm_to_tzname(tm); goto string; case '%': *l = 1; diff --git a/src/time/timegm.c b/src/time/timegm.c index e7a7939b..b5dae8b6 100644 --- a/src/time/timegm.c +++ b/src/time/timegm.c @@ -2,6 +2,8 @@ #include "time_impl.h" #include <errno.h> +extern const char __gmt[]; + time_t timegm(struct tm *tm) { struct tm new; @@ -13,6 +15,6 @@ time_t timegm(struct tm *tm) *tm = new; tm->tm_isdst = 0; tm->__tm_gmtoff = 0; - tm->__tm_zone = "GMT"; + tm->__tm_zone = __gmt; return t; } |