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