]> git.pld-linux.org Git - packages/php.git/blame - php-systzdata.patch
Update obsoletes list to include php 8.0
[packages/php.git] / php-systzdata.patch
CommitLineData
cacce04b
ER
1# License: MIT
2# http://opensource.org/licenses/MIT
3
c0240cb1 4Add support for use of the system timezone database, rather
5than embedding a copy. Discussed upstream but was not desired.
6
7History:
5eb6bcd0 8r21: adapt for timelib 2021.03 (in 8.1.0)
072a47ef 9r20: adapt for timelib 2020.03 (in 8.0.10RC1)
060f741a 10r19: adapt for timelib 2020.02 (in 8.0.0beta2)
5cd8d883 11r18: adapt for autotool change in 7.3.3RC1
539ed3cb
AG
12r17: adapt for timelib 2018.01 (in 7.3.2RC1)
13r16: adapt for timelib 2017.06 (in 7.2.3RC1)
cacce04b
ER
14r15: adapt for timelib 2017.05beta7 (in 7.2.0RC1)
15r14: improve check for valid tz file
909e9211 16r13: adapt for upstream changes to use PHP allocator
a659fa18
ER
17r12: adapt for upstream changes for new zic
18r11: use canonical names to avoid more case sensitivity issues
19 round lat/long from zone.tab towards zero per builtin db
20r10: make timezone case insensitive
361fb152
ER
21r9: fix another compile error without --with-system-tzdata configured (Michael Heimpold)
22r8: fix compile error without --with-system-tzdata configured
c0240cb1 23r7: improve check for valid timezone id to exclude directories
a659fa18 24r6: fix fd leak in r5, fix country code/BC flag use in
c0240cb1 25 timezone_identifiers_list() using system db,
26 fix use of PECL timezonedb to override system db,
27r5: reverts addition of "System/Localtime" fake tzname.
28 updated for 5.3.0, parses zone.tab to pick up mapping between
29 timezone name, country code and long/lat coords
30r4: added "System/Localtime" tzname which uses /etc/localtime
31r3: fix a crash if /usr/share/zoneinfo doesn't exist (Raphael Geissert)
32r2: add filesystem trawl to set up name alias index
33r1: initial revision
34
5eb6bcd0
ER
35diff -up php-8.0.0beta3/ext/date/config0.m4.systzdata php-8.0.0beta3/ext/date/config0.m4
36--- php-8.0.0beta3/ext/date/config0.m4.systzdata 2020-09-01 19:13:26.000000000 +0200
37+++ php-8.0.0beta3/ext/date/config0.m4 2020-09-02 08:07:51.039979873 +0200
060f741a 38@@ -4,6 +4,19 @@ AC_CHECK_HEADERS([io.h])
5cd8d883
AG
39 dnl Check for strtoll, atoll
40 AC_CHECK_FUNCS(strtoll atoll)
41
42+PHP_ARG_WITH(system-tzdata, for use of system timezone data,
43+[ --with-system-tzdata[=DIR] to specify use of system timezone data],
44+no, no)
45+
46+if test "$PHP_SYSTEM_TZDATA" != "no"; then
47+ AC_DEFINE(HAVE_SYSTEM_TZDATA, 1, [Define if system timezone data is used])
48+
49+ if test "$PHP_SYSTEM_TZDATA" != "yes"; then
50+ AC_DEFINE_UNQUOTED(HAVE_SYSTEM_TZDATA_PREFIX, "$PHP_SYSTEM_TZDATA",
51+ [Define for location of system timezone data])
52+ fi
53+fi
54+
da3ee842
AG
55 PHP_DATE_CFLAGS="-Wno-implicit-fallthrough -I@ext_builddir@/lib -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -DHAVE_TIMELIB_CONFIG_H=1"
56 timelib_sources="lib/astro.c lib/dow.c lib/parse_date.c lib/parse_tz.c lib/parse_posix.c
5cd8d883 57 lib/timelib.c lib/tm2unixtime.c lib/unixtime2tm.c lib/parse_iso_intervals.c lib/interval.c"
5eb6bcd0
ER
58diff -up php-8.0.0beta3/ext/date/lib/parse_tz.c.systzdata php-8.0.0beta3/ext/date/lib/parse_tz.c
59--- php-8.0.0beta3/ext/date/lib/parse_tz.c.systzdata 2020-09-01 19:13:26.000000000 +0200
60+++ php-8.0.0beta3/ext/date/lib/parse_tz.c 2020-09-02 08:07:51.039979873 +0200
da3ee842 61@@ -26,9 +26,22 @@
c0240cb1 62 #include "timelib.h"
cacce04b 63 #include "timelib_private.h"
c0240cb1 64
65+#ifdef HAVE_SYSTEM_TZDATA
66+#include <sys/mman.h>
67+#include <sys/stat.h>
68+#include <limits.h>
69+#include <fcntl.h>
70+#include <unistd.h>
71+
72+#include "php_scandir.h"
c0240cb1 73+
cacce04b 74+#else
909e9211 75 #define TIMELIB_SUPPORTS_V2DATA
da3ee842 76 #define TIMELIB_SUPPORT_SLIM_FILE
c0240cb1 77 #include "timezonedb.h"
78+#endif
79+
80+#include <ctype.h>
81
82 #if (defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__))
83 # if defined(__LITTLE_ENDIAN__)
5eb6bcd0 84@@ -95,6 +108,11 @@ static int read_php_preamble(const unsig
c0240cb1 85 {
a659fa18
ER
86 uint32_t version;
87
88+ if (memcmp(*tzf, "TZif", 4) == 0) {
89+ *tzf += 20;
90+ return 0;
91+ }
909e9211 92+
a659fa18
ER
93 /* read ID */
94 version = (*tzf)[3] - '0';
95 *tzf += 4;
5eb6bcd0 96@@ -577,7 +595,429 @@ void timelib_dump_tzinfo(timelib_tzinfo
c0240cb1 97 }
98 }
99
060f741a 100-static int seek_to_tz_position(const unsigned char **tzf, const char *timezone, const timelib_tzdb *tzdb)
c0240cb1 101+#ifdef HAVE_SYSTEM_TZDATA
102+
103+#ifdef HAVE_SYSTEM_TZDATA_PREFIX
104+#define ZONEINFO_PREFIX HAVE_SYSTEM_TZDATA_PREFIX
105+#else
106+#define ZONEINFO_PREFIX "/usr/share/zoneinfo"
107+#endif
108+
109+/* System timezone database pointer. */
7588b36c 110+static const timelib_tzdb *timezonedb_system;
c0240cb1 111+
112+/* Hash table entry for the cache of the zone.tab mapping table. */
113+struct location_info {
114+ char code[2];
115+ double latitude, longitude;
116+ char name[64];
117+ char *comment;
118+ struct location_info *next;
119+};
120+
121+/* Cache of zone.tab. */
122+static struct location_info **system_location_table;
123+
124+/* Size of the zone.tab hash table; a random-ish prime big enough to
125+ * prevent too many collisions. */
126+#define LOCINFO_HASH_SIZE (1021)
127+
7588b36c 128+/* Compute a case insensitive hash of str */
c0240cb1 129+static uint32_t tz_hash(const char *str)
130+{
131+ const unsigned char *p = (const unsigned char *)str;
132+ uint32_t hash = 5381;
133+ int c;
909e9211 134+
7588b36c 135+ while ((c = tolower(*p++)) != '\0') {
c0240cb1 136+ hash = (hash << 5) ^ hash ^ c;
137+ }
909e9211 138+
c0240cb1 139+ return hash % LOCINFO_HASH_SIZE;
140+}
141+
142+/* Parse an ISO-6709 date as used in zone.tab. Returns end of the
143+ * parsed string on success, or NULL on parse error. On success,
144+ * writes the parsed number to *result. */
145+static char *parse_iso6709(char *p, double *result)
146+{
147+ double v, sign;
148+ char *pend;
149+ size_t len;
150+
151+ if (*p == '+')
152+ sign = 1.0;
153+ else if (*p == '-')
154+ sign = -1.0;
155+ else
156+ return NULL;
157+
158+ p++;
159+ for (pend = p; *pend >= '0' && *pend <= '9'; pend++)
160+ ;;
161+
162+ /* Annoying encoding used by zone.tab has no decimal point, so use
163+ * the length to determine the format:
164+ *
165+ * 4 = DDMM
166+ * 5 = DDDMM
167+ * 6 = DDMMSS
168+ * 7 = DDDMMSS
169+ */
170+ len = pend - p;
171+ if (len < 4 || len > 7) {
172+ return NULL;
173+ }
174+
175+ /* p => [D]DD */
176+ v = (p[0] - '0') * 10.0 + (p[1] - '0');
177+ p += 2;
178+ if (len == 5 || len == 7)
179+ v = v * 10.0 + (*p++ - '0');
180+ /* p => MM[SS] */
181+ v += (10.0 * (p[0] - '0')
182+ + p[1] - '0') / 60.0;
183+ p += 2;
184+ /* p => [SS] */
185+ if (len > 5) {
186+ v += (10.0 * (p[0] - '0')
187+ + p[1] - '0') / 3600.0;
188+ p += 2;
189+ }
190+
191+ /* Round to five decimal place, not because it's a good idea,
192+ * but, because the builtin data uses rounded data, so, match
193+ * that. */
a659fa18 194+ *result = trunc(v * sign * 100000.0) / 100000.0;
c0240cb1 195+
196+ return p;
197+}
198+
199+/* This function parses the zone.tab file to build up the mapping of
200+ * timezone to country code and geographic location, and returns a
201+ * hash table. The hash table is indexed by the function:
202+ *
203+ * tz_hash(timezone-name)
204+ */
205+static struct location_info **create_location_table(void)
206+{
207+ struct location_info **li, *i;
208+ char zone_tab[PATH_MAX];
209+ char line[512];
210+ FILE *fp;
211+
212+ strncpy(zone_tab, ZONEINFO_PREFIX "/zone.tab", sizeof zone_tab);
213+
214+ fp = fopen(zone_tab, "r");
215+ if (!fp) {
216+ return NULL;
217+ }
218+
219+ li = calloc(LOCINFO_HASH_SIZE, sizeof *li);
220+
221+ while (fgets(line, sizeof line, fp)) {
222+ char *p = line, *code, *name, *comment;
223+ uint32_t hash;
224+ double latitude, longitude;
225+
226+ while (isspace(*p))
227+ p++;
228+
229+ if (*p == '#' || *p == '\0' || *p == '\n')
230+ continue;
231+
232+ if (!isalpha(p[0]) || !isalpha(p[1]) || p[2] != '\t')
233+ continue;
234+
235+ /* code => AA */
236+ code = p;
237+ p[2] = 0;
238+ p += 3;
239+
240+ /* coords => [+-][D]DDMM[SS][+-][D]DDMM[SS] */
241+ p = parse_iso6709(p, &latitude);
242+ if (!p) {
243+ continue;
244+ }
245+ p = parse_iso6709(p, &longitude);
246+ if (!p) {
247+ continue;
248+ }
249+
250+ if (!p || *p != '\t') {
251+ continue;
252+ }
253+
254+ /* name = string */
255+ name = ++p;
256+ while (*p != '\t' && *p && *p != '\n')
257+ p++;
258+
259+ *p++ = '\0';
260+
261+ /* comment = string */
262+ comment = p;
263+ while (*p != '\t' && *p && *p != '\n')
264+ p++;
265+
266+ if (*p == '\n' || *p == '\t')
267+ *p = '\0';
268+
269+ hash = tz_hash(name);
270+ i = malloc(sizeof *i);
271+ memcpy(i->code, code, 2);
272+ strncpy(i->name, name, sizeof i->name);
273+ i->comment = strdup(comment);
274+ i->longitude = longitude;
275+ i->latitude = latitude;
276+ i->next = li[hash];
277+ li[hash] = i;
278+ /* printf("%s [%u, %f, %f]\n", name, hash, latitude, longitude); */
279+ }
280+
281+ fclose(fp);
282+
283+ return li;
284+}
285+
286+/* Return location info from hash table, using given timezone name.
287+ * Returns NULL if the name could not be found. */
288+const struct location_info *find_zone_info(struct location_info **li,
289+ const char *name)
290+{
291+ uint32_t hash = tz_hash(name);
292+ const struct location_info *l;
293+
294+ if (!li) {
295+ return NULL;
296+ }
297+
298+ for (l = li[hash]; l; l = l->next) {
539ed3cb 299+ if (timelib_strcasecmp(l->name, name) == 0)
c0240cb1 300+ return l;
301+ }
302+
303+ return NULL;
304+}
305+
306+/* Filter out some non-tzdata files and the posix/right databases, if
307+ * present. */
308+static int index_filter(const struct dirent *ent)
309+{
310+ return strcmp(ent->d_name, ".") != 0
311+ && strcmp(ent->d_name, "..") != 0
312+ && strcmp(ent->d_name, "posix") != 0
313+ && strcmp(ent->d_name, "posixrules") != 0
314+ && strcmp(ent->d_name, "right") != 0
cacce04b 315+ && strstr(ent->d_name, ".list") == NULL
c0240cb1 316+ && strstr(ent->d_name, ".tab") == NULL;
317+}
318+
319+static int sysdbcmp(const void *first, const void *second)
320+{
321+ const timelib_tzdb_index_entry *alpha = first, *beta = second;
322+
539ed3cb 323+ return timelib_strcasecmp(alpha->id, beta->id);
c0240cb1 324+}
325+
326+
327+/* Create the zone identifier index by trawling the filesystem. */
328+static void create_zone_index(timelib_tzdb *db)
329+{
330+ size_t dirstack_size, dirstack_top;
331+ size_t index_size, index_next;
332+ timelib_tzdb_index_entry *db_index;
333+ char **dirstack;
334+
335+ /* LIFO stack to hold directory entries to scan; each slot is a
336+ * directory name relative to the zoneinfo prefix. */
337+ dirstack_size = 32;
338+ dirstack = malloc(dirstack_size * sizeof *dirstack);
339+ dirstack_top = 1;
340+ dirstack[0] = strdup("");
341+
342+ /* Index array. */
343+ index_size = 64;
344+ db_index = malloc(index_size * sizeof *db_index);
345+ index_next = 0;
346+
347+ do {
348+ struct dirent **ents;
349+ char name[PATH_MAX], *top;
350+ int count;
351+
352+ /* Pop the top stack entry, and iterate through its contents. */
353+ top = dirstack[--dirstack_top];
354+ snprintf(name, sizeof name, ZONEINFO_PREFIX "/%s", top);
355+
356+ count = php_scandir(name, &ents, index_filter, php_alphasort);
357+
358+ while (count > 0) {
359+ struct stat st;
360+ const char *leaf = ents[count - 1]->d_name;
361+
362+ snprintf(name, sizeof name, ZONEINFO_PREFIX "/%s/%s",
363+ top, leaf);
364+
365+ if (strlen(name) && stat(name, &st) == 0) {
366+ /* Name, relative to the zoneinfo prefix. */
367+ const char *root = top;
368+
369+ if (root[0] == '/') root++;
370+
371+ snprintf(name, sizeof name, "%s%s%s", root,
372+ *root ? "/": "", leaf);
373+
374+ if (S_ISDIR(st.st_mode)) {
375+ if (dirstack_top == dirstack_size) {
376+ dirstack_size *= 2;
377+ dirstack = realloc(dirstack,
378+ dirstack_size * sizeof *dirstack);
379+ }
380+ dirstack[dirstack_top++] = strdup(name);
381+ }
382+ else {
383+ if (index_next == index_size) {
384+ index_size *= 2;
385+ db_index = realloc(db_index,
386+ index_size * sizeof *db_index);
387+ }
388+
389+ db_index[index_next++].id = strdup(name);
390+ }
391+ }
392+
393+ free(ents[--count]);
394+ }
395+
396+ if (count != -1) free(ents);
397+ free(top);
398+ } while (dirstack_top);
399+
400+ qsort(db_index, index_next, sizeof *db_index, sysdbcmp);
401+
402+ db->index = db_index;
403+ db->index_size = index_next;
404+
405+ free(dirstack);
406+}
407+
408+#define FAKE_HEADER "1234\0??\1??"
409+#define FAKE_UTC_POS (7 - 4)
410+
411+/* Create a fake data segment for database 'sysdb'. */
412+static void fake_data_segment(timelib_tzdb *sysdb,
413+ struct location_info **info)
414+{
415+ size_t n;
416+ char *data, *p;
417+
418+ data = malloc(3 * sysdb->index_size + 7);
419+
420+ p = mempcpy(data, FAKE_HEADER, sizeof(FAKE_HEADER) - 1);
421+
422+ for (n = 0; n < sysdb->index_size; n++) {
423+ const struct location_info *li;
424+ timelib_tzdb_index_entry *ent;
425+
426+ ent = (timelib_tzdb_index_entry *)&sysdb->index[n];
427+
428+ /* Lookup the timezone name in the hash table. */
429+ if (strcmp(ent->id, "UTC") == 0) {
430+ ent->pos = FAKE_UTC_POS;
431+ continue;
432+ }
433+
434+ li = find_zone_info(info, ent->id);
435+ if (li) {
436+ /* If found, append the BC byte and the
437+ * country code; set the position for this
438+ * section of timezone data. */
439+ ent->pos = (p - data) - 4;
440+ *p++ = '\1';
441+ *p++ = li->code[0];
442+ *p++ = li->code[1];
443+ }
444+ else {
445+ /* If not found, the timezone data can
446+ * point at the header. */
447+ ent->pos = 0;
448+ }
449+ }
450+
451+ sysdb->data = (unsigned char *)data;
452+}
453+
454+/* Returns true if the passed-in stat structure describes a
455+ * probably-valid timezone file. */
cacce04b 456+static int is_valid_tzfile(const struct stat *st, int fd)
c0240cb1 457+{
cacce04b
ER
458+ if (fd) {
459+ char buf[20];
460+ if (read(fd, buf, 20)!=20) {
461+ return 0;
462+ }
463+ lseek(fd, SEEK_SET, 0);
464+ if (memcmp(buf, "TZif", 4)) {
465+ return 0;
466+ }
467+ }
c0240cb1 468+ return S_ISREG(st->st_mode) && st->st_size > 20;
469+}
470+
a659fa18
ER
471+/* To allow timezone names to be used case-insensitively, find the
472+ * canonical name for this timezone, if possible. */
473+static const char *canonical_tzname(const char *timezone)
474+{
475+ if (timezonedb_system) {
476+ timelib_tzdb_index_entry *ent, lookup;
909e9211 477+
a659fa18 478+ lookup.id = (char *)timezone;
909e9211 479+
a659fa18
ER
480+ ent = bsearch(&lookup, timezonedb_system->index,
481+ timezonedb_system->index_size, sizeof lookup,
482+ sysdbcmp);
483+ if (ent) {
484+ return ent->id;
485+ }
486+ }
487+
488+ return timezone;
489+}
490+
c0240cb1 491+/* Return the mmap()ed tzfile if found, else NULL. On success, the
492+ * length of the mapped data is placed in *length. */
493+static char *map_tzfile(const char *timezone, size_t *length)
494+{
495+ char fname[PATH_MAX];
496+ struct stat st;
497+ char *p;
498+ int fd;
499+
500+ if (timezone[0] == '\0' || strstr(timezone, "..") != NULL) {
501+ return NULL;
502+ }
503+
a659fa18 504+ snprintf(fname, sizeof fname, ZONEINFO_PREFIX "/%s", canonical_tzname(timezone));
cacce04b 505+
c0240cb1 506+ fd = open(fname, O_RDONLY);
507+ if (fd == -1) {
508+ return NULL;
cacce04b 509+ } else if (fstat(fd, &st) != 0 || !is_valid_tzfile(&st, fd)) {
c0240cb1 510+ close(fd);
511+ return NULL;
512+ }
513+
514+ *length = st.st_size;
515+ p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
516+ close(fd);
517+
518+ return p != MAP_FAILED ? p : NULL;
519+}
520+
521+#endif
522+
060f741a 523+static int inmem_seek_to_tz_position(const unsigned char **tzf, const char *timezone, const timelib_tzdb *tzdb)
c0240cb1 524 {
525 int left = 0, right = tzdb->index_size - 1;
539ed3cb 526
5eb6bcd0 527@@ -603,9 +1043,48 @@ static int seek_to_tz_position(const uns
c0240cb1 528 return 0;
529 }
530
060f741a 531+static int seek_to_tz_position(const unsigned char **tzf, const char *timezone,
c0240cb1 532+ char **map, size_t *maplen,
533+ const timelib_tzdb *tzdb)
534+{
361fb152 535+#ifdef HAVE_SYSTEM_TZDATA
c0240cb1 536+ if (tzdb == timezonedb_system) {
537+ char *orig;
538+
539+ orig = map_tzfile(timezone, maplen);
540+ if (orig == NULL) {
541+ return 0;
542+ }
a659fa18 543+
909e9211 544+ (*tzf) = (unsigned char *)orig;
c0240cb1 545+ *map = orig;
909e9211 546+ return 1;
c0240cb1 547+ }
a659fa18 548+ else
361fb152 549+#endif
a659fa18 550+ {
c0240cb1 551+ return inmem_seek_to_tz_position(tzf, timezone, tzdb);
552+ }
553+}
554+
555 const timelib_tzdb *timelib_builtin_db(void)
556 {
557+#ifdef HAVE_SYSTEM_TZDATA
558+ if (timezonedb_system == NULL) {
559+ timelib_tzdb *tmp = malloc(sizeof *tmp);
560+
561+ tmp->version = "0.system";
562+ tmp->data = NULL;
563+ create_zone_index(tmp);
564+ system_location_table = create_location_table();
a659fa18 565+ fake_data_segment(tmp, system_location_table);
c0240cb1 566+ timezonedb_system = tmp;
567+ }
568+
c0240cb1 569+ return timezonedb_system;
570+#else
571 return &timezonedb_builtin;
572+#endif
573 }
574
539ed3cb 575 const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(const timelib_tzdb *tzdb, int *count)
5eb6bcd0 576@@ -617,7 +1096,30 @@ const timelib_tzdb_index_entry *timelib_
060f741a 577 int timelib_timezone_id_is_valid(const char *timezone, const timelib_tzdb *tzdb)
c0240cb1 578 {
579 const unsigned char *tzf;
580- return (seek_to_tz_position(&tzf, timezone, tzdb));
581+
582+#ifdef HAVE_SYSTEM_TZDATA
a659fa18
ER
583+ if (tzdb == timezonedb_system) {
584+ char fname[PATH_MAX];
585+ struct stat st;
586+
587+ if (timezone[0] == '\0' || strstr(timezone, "..") != NULL) {
588+ return 0;
589+ }
c0240cb1 590+
a659fa18
ER
591+ if (system_location_table) {
592+ if (find_zone_info(system_location_table, timezone) != NULL) {
593+ /* found in cache */
594+ return 1;
595+ }
596+ }
597+
598+ snprintf(fname, sizeof fname, ZONEINFO_PREFIX "/%s", canonical_tzname(timezone));
599+
cacce04b 600+ return stat(fname, &st) == 0 && is_valid_tzfile(&st, 0);
a659fa18
ER
601+ }
602+#endif
909e9211 603+
c0240cb1 604+ return (inmem_seek_to_tz_position(&tzf, timezone, tzdb));
605 }
606
cacce04b 607 static int skip_64bit_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
5eb6bcd0 608@@ -662,6 +1164,8 @@ static timelib_tzinfo* timelib_tzinfo_ct
060f741a 609 timelib_tzinfo *timelib_parse_tzfile(const char *timezone, const timelib_tzdb *tzdb, int *error_code)
c0240cb1 610 {
611 const unsigned char *tzf;
612+ char *memmap = NULL;
613+ size_t maplen;
614 timelib_tzinfo *tmp;
a659fa18 615 int version;
cacce04b 616 int transitions_result, types_result;
5eb6bcd0 617@@ -669,7 +1173,7 @@ timelib_tzinfo *timelib_parse_tzfile(con
072a47ef
ER
618
619 *error_code = TIMELIB_ERROR_NO_ERROR;
c0240cb1 620
621- if (seek_to_tz_position(&tzf, timezone, tzdb)) {
622+ if (seek_to_tz_position(&tzf, timezone, &memmap, &maplen, tzdb)) {
623 tmp = timelib_tzinfo_ctor(timezone);
624
cacce04b 625 version = read_preamble(&tzf, tmp, &type);
5eb6bcd0 626@@ -712,11 +1216,36 @@ timelib_tzinfo *timelib_parse_tzfile(con
da3ee842 627 return NULL;
cacce04b 628 }
539ed3cb 629
c0240cb1 630+#ifdef HAVE_SYSTEM_TZDATA
631+ if (memmap) {
632+ const struct location_info *li;
633+
634+ /* TZif-style - grok the location info from the system database,
635+ * if possible. */
636+
637+ if ((li = find_zone_info(system_location_table, timezone)) != NULL) {
909e9211
ER
638+ tmp->location.comments = timelib_strdup(li->comment);
639+ strncpy(tmp->location.country_code, li->code, 2);
c0240cb1 640+ tmp->location.longitude = li->longitude;
641+ tmp->location.latitude = li->latitude;
642+ tmp->bc = 1;
643+ }
644+ else {
cacce04b 645+ set_default_location_and_comments(&tzf, tmp);
c0240cb1 646+ }
647+
648+ /* Now done with the mmap segment - discard it. */
649+ munmap(memmap, maplen);
cacce04b
ER
650+ } else {
651+#endif
539ed3cb
AG
652 if (type == TIMELIB_TZINFO_PHP) {
653 read_location(&tzf, tmp);
cacce04b
ER
654 } else {
655 set_default_location_and_comments(&tzf, tmp);
656 }
657+#ifdef HAVE_SYSTEM_TZDATA
658+ }
c0240cb1 659+#endif
c0240cb1 660 } else {
cacce04b 661 *error_code = TIMELIB_ERROR_NO_SUCH_TIMEZONE;
c0240cb1 662 tmp = NULL;
This page took 0.436208 seconds and 4 git commands to generate.