~ubuntu-branches/ubuntu/raring/php5/raring

« back to all changes in this revision

Viewing changes to debian/patches/use_embedded_timezonedb.patch

  • Committer: Package Import Robot
  • Author(s): Clint Byrum
  • Date: 2012-06-18 16:10:26 UTC
  • mfrom: (1.1.24) (0.3.58 sid)
  • Revision ID: package-import@ubuntu.com-20120618161026-hg1fc5r9z1a4hlqz
Tags: 5.4.4-1ubuntu1
* Merge from Debian unstable. Remaining changes:
  - d/rules: Simplify apache config settings since we never build 
    interbase or firebird.
  - debian/rules: export DEB_HOST_MULTIARCH properly.
  - Add build-dependency on lemon, which we now need.
  - Dropped firebird2.1-dev, libc-client-dev, libmcrypt-dev as it is in universe.
  - Dropped libcurl-dev not in the archive.
  - debian/control: replace build-depends on mysql-server with
    mysql-server-core-5.5 and mysql-client-5.5 to avoid upstart and
    mysql-server-5.5 postinst confusion with starting up multiple
    mysqlds listening on the same port.
  - Dropped php5-imap, php5-interbase, php5-mcrypt since we have versions
    already in universe.
  - Dropped libonig-dev and libqgdbm since its in universe. (libonig MIR
    has been declined due to an inactive upstream. So this is probably
    a permanent change).
  - modulelist: Drop imap, interbase, sybase, and mcrypt.
  - debian/rules:
    * Dropped building of mcrypt, imap, and interbase.
    * Install apport hook for php5.
    * stop mysql instance on clean just in case we failed in tests
* Dropped Changes:
  * d/rules: enable Suhosin patch with PHP5_SUHOSIN=yes -- Upstream suhosin
    has been slow to adopt PHP 5.4, and is showing signs of disengagement.
    Therefore, we will follow Debian's lead and drop Suhosin for now.
  - d/control: build-depend on mysql 5.5 instead of 5.1 for running tests.
    -- Debian just deps on mysql-server
  - Suggest php5-suhosin rather than recommends. -- Dropping suhosin
  - d/setup-mysql.sh: modify to work with mysql 5.5 differences -- superseded
    in Debian.
  - Only build php5-sqlite for sqlite3, dropping the obsolete sqlite2. --
    superseded in Debian
  - d/maxlifetime: Improve maxlifetime script to scan for more SAPIs and 
    scan all *.ini in conf.d directory. -- Change came from Debian
  - d/libapache2-mod-php5.postinst,libapache2-mod-php5filter.postinst: 
    Restart apache on first install to ensure module is fully enabled.
    -- Change came from Debian
  - debian/patches/php5-CVE-2012-1823.patch: filter query strings that
    are prefixed with '-' -- Fixed upstream
  - debian/control: Recommend php5-dev for php-pear. -- This was a poorly
    conceived idea anyway.
  - Pre-Depend on a new enough version of dpkg for dpkg-maintscript-helper
    rather than checking whether it exists at run-time, leading to more
    predictable behaviour on upgrades. -- Applied in Debian
  - d/p/gd-multiarch-fix.patch: superseded
* d/NEWS: add note explaining that SUHOSIN is no longer enabled in the
  Ubuntu packages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
than embedding a copy.  Discussed upstream but was not desired.
4
4
 
5
5
History:
6
 
r7: per Sean Finney's review: simpler lat/long rounding,
7
 
    use stat() not access() to check existence of timezone,
8
 
    improve comments throughout.
 
6
r8: fix compile error without --with-system-tzdata configured
 
7
r7: improve check for valid timezone id to exclude directories
9
8
r6: fix fd leak in r5, fix country code/BC flag use in 
10
9
    timezone_identifiers_list() using system db,
11
10
    fix use of PECL timezonedb to override system db,
49
48
 
50
49
 #if (defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__))
51
50
 # if defined(__LITTLE_ENDIAN__)
52
 
@@ -55,6 +70,11 @@
 
51
@@ -55,9 +70,14 @@
53
52
 
54
53
 static void read_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
55
54
 {
56
 
+       if (memcmp(tzf, "TZif", 4) == 0) {
57
 
+               *tzf += 20;
58
 
+               return;
59
 
+       }
60
 
+    
61
 
        /* skip ID */
62
 
        *tzf += 4;
63
 
        
64
 
@@ -260,7 +280,435 @@ void timelib_dump_tzinfo(timelib_tzinfo
 
55
-       /* skip ID */
 
56
-       *tzf += 4;
 
57
-       
 
58
+        if (memcmp(tzf, "TZif", 4) == 0) {
 
59
+                *tzf += 20;
 
60
+                return;
 
61
+        }
 
62
+        
 
63
+        /* skip ID */
 
64
+        *tzf += 4;
 
65
+                
 
66
        /* read BC flag */
 
67
        tz->bc = (**tzf == '\1');
 
68
        *tzf += 1;
 
69
@@ -260,7 +280,397 @@ void timelib_dump_tzinfo(timelib_tzinfo
65
70
        }
66
71
 }
67
72
 
74
79
+#define ZONEINFO_PREFIX "/usr/share/zoneinfo"
75
80
+#endif
76
81
+
 
82
+/* System timezone database pointer. */
 
83
+static const timelib_tzdb *timezonedb_system = NULL;
 
84
+
77
85
+/* Hash table entry for the cache of the zone.tab mapping table. */
78
86
+struct location_info {
79
 
+       char code[2]; /* Country code. */
80
 
+       double latitude, longitude;
81
 
+       char name[64];
82
 
+       char *comment;
83
 
+       struct location_info *next;
 
87
+        char code[2];
 
88
+        double latitude, longitude;
 
89
+        char name[64];
 
90
+        char *comment;
 
91
+        struct location_info *next;
84
92
+};
85
93
+
86
 
+/* System timezone database pointer. */
87
 
+static const timelib_tzdb *timezonedb_system = NULL;
88
 
+
89
 
+/* Cache of zone.tab location data. */
 
94
+/* Cache of zone.tab. */
90
95
+static struct location_info **system_location_table;
91
96
+
92
97
+/* Size of the zone.tab hash table; a random-ish prime big enough to
93
98
+ * prevent too many collisions. */
94
99
+#define LOCINFO_HASH_SIZE (1021)
95
100
+
96
 
+/* Hash function for indexing the location_info hash table. */
97
101
+static uint32_t tz_hash(const char *str)
98
102
+{
99
 
+       const unsigned char *p = (const unsigned char *)str;
100
 
+       uint32_t hash = 5381;
101
 
+       int c;
102
 
+       
103
 
+       while ((c = *p++) != '\0') {
104
 
+               hash = (hash << 5) ^ hash ^ c;
105
 
+       }
106
 
+       
107
 
+       return hash % LOCINFO_HASH_SIZE;
 
103
+    const unsigned char *p = (const unsigned char *)str;
 
104
+    uint32_t hash = 5381;
 
105
+    int c;
 
106
+    
 
107
+    while ((c = *p++) != '\0') {
 
108
+        hash = (hash << 5) ^ hash ^ c;
 
109
+    }
 
110
+    
 
111
+    return hash % LOCINFO_HASH_SIZE;
108
112
+}
109
113
+
110
 
+/* Parse an ISO-6709 co-ordinate as used in zone.tab. Returns end of
111
 
+ * the parsed string on success, or NULL on parse error.  On success,
 
114
+/* Parse an ISO-6709 date as used in zone.tab. Returns end of the
 
115
+ * parsed string on success, or NULL on parse error.  On success,
112
116
+ * writes the parsed number to *result. */
113
117
+static char *parse_iso6709(char *p, double *result)
114
118
+{
115
 
+       double v, sign;
116
 
+       char *pend;
117
 
+       size_t len;
118
 
+
119
 
+       if (*p == '+')
120
 
+               sign = 1.0;
121
 
+       else if (*p == '-')
122
 
+               sign = -1.0;
123
 
+       else
124
 
+               return NULL;
125
 
+
126
 
+       p++;
127
 
+       for (pend = p; *pend >= '0' && *pend <= '9'; pend++)
128
 
+               ;;
129
 
+
130
 
+       /* Annoying encoding used by zone.tab has no decimal point, so use
131
 
+        * the length to determine the format:
132
 
+        * 
133
 
+        * 4 = DDMM
134
 
+        * 5 = DDDMM
135
 
+        * 6 = DDMMSS
136
 
+        * 7 = DDDMMSS
137
 
+        */
138
 
+       len = pend - p;
139
 
+       if (len < 4 || len > 7) {
140
 
+               return NULL;
141
 
+       }
142
 
+
143
 
+       /* p => [D]DD */
144
 
+       v = (p[0] - '0') * 10.0 + (p[1] - '0');
145
 
+       p += 2;
146
 
+       if (len == 5 || len == 7)
147
 
+               v = v * 10.0 + (*p++ - '0');
148
 
+       /* p => MM[SS] */
149
 
+       v += (10.0 * (p[0] - '0')
150
 
+                 + p[1] - '0') / 60.0;
151
 
+       p += 2;
152
 
+       /* p => [SS] */
153
 
+       if (len > 5) {
154
 
+               v += (10.0 * (p[0] - '0')
155
 
+                         + p[1] - '0') / 3600.0;
156
 
+               p += 2;
157
 
+       }
158
 
+
159
 
+       /* Round to five decimal place, not because it's a good idea,
160
 
+        * but, because the builtin data uses rounded data, so, match
161
 
+        * that. */
162
 
+       *result = sign * (int)(v * 100000.0 + 0.5) / 100000.0;
163
 
+
164
 
+       return p;
 
119
+    double v, sign;
 
120
+    char *pend;
 
121
+    size_t len;
 
122
+
 
123
+    if (*p == '+')
 
124
+        sign = 1.0;
 
125
+    else if (*p == '-')
 
126
+        sign = -1.0;
 
127
+    else
 
128
+        return NULL;
 
129
+
 
130
+    p++;
 
131
+    for (pend = p; *pend >= '0' && *pend <= '9'; pend++)
 
132
+        ;;
 
133
+
 
134
+    /* Annoying encoding used by zone.tab has no decimal point, so use
 
135
+     * the length to determine the format:
 
136
+     * 
 
137
+     * 4 = DDMM
 
138
+     * 5 = DDDMM
 
139
+     * 6 = DDMMSS
 
140
+     * 7 = DDDMMSS
 
141
+     */
 
142
+    len = pend - p;
 
143
+    if (len < 4 || len > 7) {
 
144
+        return NULL;
 
145
+    }
 
146
+
 
147
+    /* p => [D]DD */
 
148
+    v = (p[0] - '0') * 10.0 + (p[1] - '0');
 
149
+    p += 2;
 
150
+    if (len == 5 || len == 7)
 
151
+        v = v * 10.0 + (*p++ - '0');
 
152
+    /* p => MM[SS] */
 
153
+    v += (10.0 * (p[0] - '0')
 
154
+          + p[1] - '0') / 60.0;
 
155
+    p += 2;
 
156
+    /* p => [SS] */
 
157
+    if (len > 5) {
 
158
+        v += (10.0 * (p[0] - '0')
 
159
+              + p[1] - '0') / 3600.0;
 
160
+        p += 2;
 
161
+    }
 
162
+
 
163
+    /* Round to five decimal place, not because it's a good idea,
 
164
+     * but, because the builtin data uses rounded data, so, match
 
165
+     * that. */
 
166
+    *result = round(v * sign * 100000.0) / 100000.0;
 
167
+
 
168
+    return p;
165
169
+}
166
170
+
167
171
+/* This function parses the zone.tab file to build up the mapping of
168
172
+ * timezone to country code and geographic location, and returns a
169
 
+ * hash table. The hash table is indexed by the function:
 
173
+ * hash table.  The hash table is indexed by the function:
170
174
+ *
171
 
+ *      tz_hash(timezone-name)
 
175
+ *   tz_hash(timezone-name)
172
176
+ */
173
177
+static struct location_info **create_location_table(void)
174
178
+{
175
 
+       struct location_info **li, *i;
176
 
+       char zone_tab[PATH_MAX];
177
 
+       char line[512];
178
 
+       FILE *fp;
179
 
+
180
 
+       strncpy(zone_tab, ZONEINFO_PREFIX "/zone.tab", sizeof zone_tab);
181
 
+
182
 
+       fp = fopen(zone_tab, "r");
183
 
+       if (!fp) {
184
 
+               return NULL;
185
 
+       }
186
 
+
187
 
+       li = calloc(LOCINFO_HASH_SIZE, sizeof *li);
188
 
+
189
 
+       while (fgets(line, sizeof line, fp)) {
190
 
+               char *p = line, *code, *name, *comment;
191
 
+               uint32_t hash;
192
 
+               double latitude, longitude;
193
 
+
194
 
+               while (isspace(*p))
195
 
+                       p++;
196
 
+
197
 
+               if (*p == '#' || *p == '\0' || *p == '\n')
198
 
+                       continue;
199
 
+               
200
 
+               if (!isalpha(p[0]) || !isalpha(p[1]) || p[2] != '\t')
201
 
+                       continue;
202
 
+               
203
 
+               /* code => AA */
204
 
+               code = p;
205
 
+               p[2] = 0;
206
 
+               p += 3;
207
 
+
208
 
+               /* coords => [+-][D]DDMM[SS][+-][D]DDMM[SS] */
209
 
+               p = parse_iso6709(p, &latitude);
210
 
+               if (!p) {
211
 
+                       continue;
212
 
+               }
213
 
+               p = parse_iso6709(p, &longitude);
214
 
+               if (!p) {
215
 
+                       continue;
216
 
+               }
217
 
+
218
 
+               if (!p || *p != '\t') {
219
 
+                       continue;
220
 
+               }
221
 
+
222
 
+               /* name = string */
223
 
+               name = ++p;
224
 
+               while (*p != '\t' && *p && *p != '\n')
225
 
+                       p++;
226
 
+
227
 
+               *p++ = '\0';
228
 
+
229
 
+               /* comment = string */
230
 
+               comment = p;
231
 
+               while (*p != '\t' && *p && *p != '\n')
232
 
+                       p++;
233
 
+
234
 
+               if (*p == '\n' || *p == '\t')
235
 
+                       *p = '\0';
236
 
+               
237
 
+               hash = tz_hash(name);
238
 
+               i = malloc(sizeof *i);
239
 
+               memcpy(i->code, code, 2);
240
 
+               strncpy(i->name, name, sizeof i->name);
241
 
+               i->comment = strdup(comment);
242
 
+               i->longitude = longitude;
243
 
+               i->latitude = latitude;
244
 
+               i->next = li[hash];
245
 
+               li[hash] = i;
246
 
+               /* printf("%s [%u, %f, %f]\n", name, hash, latitude, longitude); */
247
 
+       }
248
 
+
249
 
+       fclose(fp);
250
 
+
251
 
+       return li;
 
179
+    struct location_info **li, *i;
 
180
+    char zone_tab[PATH_MAX];
 
181
+    char line[512];
 
182
+    FILE *fp;
 
183
+
 
184
+    strncpy(zone_tab, ZONEINFO_PREFIX "/zone.tab", sizeof zone_tab);
 
185
+
 
186
+    fp = fopen(zone_tab, "r");
 
187
+    if (!fp) {
 
188
+        return NULL;
 
189
+    }
 
190
+
 
191
+    li = calloc(LOCINFO_HASH_SIZE, sizeof *li);
 
192
+
 
193
+    while (fgets(line, sizeof line, fp)) {
 
194
+        char *p = line, *code, *name, *comment;
 
195
+        uint32_t hash;
 
196
+        double latitude, longitude;
 
197
+
 
198
+        while (isspace(*p))
 
199
+            p++;
 
200
+
 
201
+        if (*p == '#' || *p == '\0' || *p == '\n')
 
202
+            continue;
 
203
+        
 
204
+        if (!isalpha(p[0]) || !isalpha(p[1]) || p[2] != '\t')
 
205
+            continue;
 
206
+        
 
207
+        /* code => AA */
 
208
+        code = p;
 
209
+        p[2] = 0;
 
210
+        p += 3;
 
211
+
 
212
+        /* coords => [+-][D]DDMM[SS][+-][D]DDMM[SS] */
 
213
+        p = parse_iso6709(p, &latitude);
 
214
+        if (!p) {
 
215
+            continue;
 
216
+        }
 
217
+        p = parse_iso6709(p, &longitude);
 
218
+        if (!p) {
 
219
+            continue;
 
220
+        }
 
221
+
 
222
+        if (!p || *p != '\t') {
 
223
+            continue;
 
224
+        }
 
225
+
 
226
+        /* name = string */
 
227
+        name = ++p;
 
228
+        while (*p != '\t' && *p && *p != '\n')
 
229
+            p++;
 
230
+
 
231
+        *p++ = '\0';
 
232
+
 
233
+        /* comment = string */
 
234
+        comment = p;
 
235
+        while (*p != '\t' && *p && *p != '\n')
 
236
+            p++;
 
237
+
 
238
+        if (*p == '\n' || *p == '\t')
 
239
+            *p = '\0';
 
240
+        
 
241
+        hash = tz_hash(name);
 
242
+        i = malloc(sizeof *i);
 
243
+        memcpy(i->code, code, 2);
 
244
+        strncpy(i->name, name, sizeof i->name);
 
245
+        i->comment = strdup(comment);
 
246
+        i->longitude = longitude;
 
247
+        i->latitude = latitude;
 
248
+        i->next = li[hash];
 
249
+        li[hash] = i;
 
250
+        /* printf("%s [%u, %f, %f]\n", name, hash, latitude, longitude); */
 
251
+    }
 
252
+
 
253
+    fclose(fp);
 
254
+
 
255
+    return li;
252
256
+}
253
257
+
254
258
+/* Return location info from hash table, using given timezone name.
255
259
+ * Returns NULL if the name could not be found. */
256
260
+const struct location_info *find_zone_info(struct location_info **li, 
257
 
+                                                                                  const char *name)
 
261
+                                           const char *name)
258
262
+{
259
 
+       uint32_t hash = tz_hash(name);
260
 
+       const struct location_info *l;
261
 
+
262
 
+       if (!li) {
263
 
+               return NULL;
264
 
+       }
265
 
+
266
 
+       for (l = li[hash]; l; l = l->next) {
267
 
+               if (strcasecmp(l->name, name) == 0)
268
 
+                       return l;
269
 
+       }
270
 
+
271
 
+       return NULL;
272
 
+}       
 
263
+    uint32_t hash = tz_hash(name);
 
264
+    const struct location_info *l;
 
265
+
 
266
+    if (!li) {
 
267
+        return NULL;
 
268
+    }
 
269
+
 
270
+    for (l = li[hash]; l; l = l->next) {
 
271
+        if (strcasecmp(l->name, name) == 0)
 
272
+            return l;
 
273
+    }
 
274
+
 
275
+    return NULL;
 
276
+}    
273
277
+
274
278
+/* Filter out some non-tzdata files and the posix/right databases, if
275
279
+ * present. */
283
287
+               && strstr(ent->d_name, ".tab") == NULL;
284
288
+}
285
289
+
286
 
+/* Comparison callback for qsort(), used to alpha-sort the index
287
 
+ * array by timezone name. */
288
290
+static int sysdbcmp(const void *first, const void *second)
289
291
+{
290
 
+       const timelib_tzdb_index_entry *alpha = first, *beta = second;
291
 
+       
292
 
+       return strcmp(alpha->id, beta->id);
 
292
+        const timelib_tzdb_index_entry *alpha = first, *beta = second;
 
293
+
 
294
+        return strcmp(alpha->id, beta->id);
293
295
+}
294
296
+
295
297
+
344
346
+                                       if (dirstack_top == dirstack_size) {
345
347
+                                               dirstack_size *= 2;
346
348
+                                               dirstack = realloc(dirstack, 
347
 
+                                                                                  dirstack_size * sizeof *dirstack);
 
349
+                                                                  dirstack_size * sizeof *dirstack);
348
350
+                                       }
349
351
+                                       dirstack[dirstack_top++] = strdup(name);
350
352
+                               }
352
354
+                                       if (index_next == index_size) {
353
355
+                                               index_size *= 2;
354
356
+                                               db_index = realloc(db_index,
355
 
+                                                                                  index_size * sizeof *db_index);
 
357
+                                                                  index_size * sizeof *db_index);
356
358
+                                       }
357
359
+
358
360
+                                       db_index[index_next++].id = strdup(name);
366
368
+               free(top);
367
369
+       } while (dirstack_top);
368
370
+
369
 
+       /* Alpha-sort the index array; shouldn't be technically necessary
370
 
+        * but some of the test cases rely on this, and, it matches the
371
 
+        * builtin database. */
372
 
+       qsort(db_index, index_next, sizeof *db_index, sysdbcmp);
373
 
+       
 
371
+        qsort(db_index, index_next, sizeof *db_index, sysdbcmp);
 
372
+
374
373
+       db->index = db_index;
375
374
+       db->index_size = index_next;
376
375
+
378
377
+}
379
378
+
380
379
+#define FAKE_HEADER "1234\0??\1??"
381
 
+#define FAKE_BC_POS (0)
382
380
+#define FAKE_UTC_POS (7 - 4)
383
381
+
384
 
+/* Create a fake data segment for database 'sysdb'.   This mocks
385
 
+ * up a fake ->data segment for the given timezone database. 
386
 
+ * php_date.c::timezone_identifiers_list() looks at data[pos + 4]
387
 
+ * through data[pos + 6] to compare the country code and BC flag, 
388
 
+ * which are stored in the builtin data array like:
389
 
+ *
390
 
+ *    (pos + 4) => BC flag
391
 
+ *    (pos + 5, pos + 6) => Two chars of country code
392
 
+ *
393
 
+ * where pos is the index corresponding to the timezone name.
394
 
+ *
395
 
+ * Timezone names are classified here into three types:
396
 
+ *    1) UTC, which is special
397
 
+ *    2) "normal" zone names
398
 
+ *    3) "backwards-compat" zone names
399
 
+ *
400
 
+ * (boolean logic of the BC flag seems to be inverted, but hey)
401
 
+ *
402
 
+ * UTC is special since it has BC=\1, code = "??"
403
 
+ * "normal" zones exist in zone.tab and have the given c-code and BC=\1
404
 
+ * "backwards-compat" zones don't exist in zone.tab and have BC=\0
405
 
+ *
406
 
+ * Since UTC and the BC zones are constant, they are encoded in the
407
 
+ * FAKE_HEADER prefix, and pos pointers index into that.
408
 
+ *
409
 
+ * FAKE_HEADER is hence four random bytes, then the BC zone segment
410
 
+ * (three bytes), then the UTC zone segment (another three).
411
 
+ *
412
 
+ * For all "normal" zones, three bytes are appended to the data array;
413
 
+ * the BC flag, always 1, and the two bytes of country code.
414
 
+ */
 
382
+/* Create a fake data segment for database 'sysdb'. */
415
383
+static void fake_data_segment(timelib_tzdb *sysdb,
416
 
+                                                         struct location_info **info)
417
 
+{
418
 
+       size_t n;
419
 
+       char *data, *p;
420
 
+       
421
 
+       /* Worst case maximum is 3 bytes per zone, plus the header. */
422
 
+       data = malloc((3 * sysdb->index_size) + sizeof(FAKE_HEADER) - 1);
423
 
+       
424
 
+       /* Append the fake header, p then = next byte */
425
 
+       p = mempcpy(data, FAKE_HEADER, sizeof(FAKE_HEADER) - 1);
426
 
+       
427
 
+       for (n = 0; n < sysdb->index_size; n++) {
428
 
+               const struct location_info *li;
429
 
+               timelib_tzdb_index_entry *ent;
430
 
+               
431
 
+               /* Lost const'ness since we're modifying the pos pointer. */
432
 
+               ent = (timelib_tzdb_index_entry *)&sysdb->index[n];
433
 
+               
434
 
+               /* Lookup the timezone name in the hash table. */
435
 
+               if (strcmp(ent->id, "UTC") == 0) {
436
 
+                       ent->pos = FAKE_UTC_POS;
437
 
+                       continue;
438
 
+               }
439
 
+               
440
 
+               li = find_zone_info(info, ent->id);
441
 
+               if (li) {
442
 
+                       /* If found, append the BC byte and the country code; set
443
 
+                        * the position index for the timezone to point to
444
 
+                        * this.  */
445
 
+                       ent->pos = (p - data) - 4;
446
 
+                       *p++ = '\x01';
447
 
+                       *p++ = li->code[0];
448
 
+                       *p++ = li->code[1];
449
 
+               }
450
 
+               else {
451
 
+                       /* If not found, the timezone data can
452
 
+                        * point at the header. */
453
 
+                       ent->pos = 0;
454
 
+               }
455
 
+       }
456
 
+       
457
 
+       /* Store the fake data array */
458
 
+       sysdb->data = (unsigned char *)data;
459
 
+}
460
 
+
461
 
+/* Evaluates to true if given timezone name is valid. */
462
 
+#define is_valid_tz_name(tz_) (tz_[0] && strstr(tz_, "..") == NULL)
463
 
+
464
 
+/* Return the mmap()ed tzfile if found, else NULL.     On success, the
 
384
+                              struct location_info **info)
 
385
+{
 
386
+        size_t n;
 
387
+        char *data, *p;
 
388
+        
 
389
+        data = malloc(3 * sysdb->index_size + 7);
 
390
+
 
391
+        p = mempcpy(data, FAKE_HEADER, sizeof(FAKE_HEADER) - 1);
 
392
+
 
393
+        for (n = 0; n < sysdb->index_size; n++) {
 
394
+                const struct location_info *li;
 
395
+                timelib_tzdb_index_entry *ent;
 
396
+
 
397
+                ent = (timelib_tzdb_index_entry *)&sysdb->index[n];
 
398
+
 
399
+                /* Lookup the timezone name in the hash table. */
 
400
+                if (strcmp(ent->id, "UTC") == 0) {
 
401
+                        ent->pos = FAKE_UTC_POS;
 
402
+                        continue;
 
403
+                }
 
404
+
 
405
+                li = find_zone_info(info, ent->id);
 
406
+                if (li) {
 
407
+                        /* If found, append the BC byte and the
 
408
+                         * country code; set the position for this
 
409
+                         * section of timezone data.  */
 
410
+                        ent->pos = (p - data) - 4;
 
411
+                        *p++ = '\1';
 
412
+                        *p++ = li->code[0];
 
413
+                        *p++ = li->code[1];
 
414
+                }
 
415
+                else {
 
416
+                        /* If not found, the timezone data can
 
417
+                         * point at the header. */
 
418
+                        ent->pos = 0;
 
419
+                }
 
420
+        }
 
421
+        
 
422
+        sysdb->data = (unsigned char *)data;
 
423
+}
 
424
+
 
425
+/* Returns true if the passed-in stat structure describes a
 
426
+ * probably-valid timezone file. */
 
427
+static int is_valid_tzfile(const struct stat *st)
 
428
+{
 
429
+       return S_ISREG(st->st_mode) && st->st_size > 20;
 
430
+}
 
431
+
 
432
+/* Return the mmap()ed tzfile if found, else NULL.  On success, the
465
433
+ * length of the mapped data is placed in *length. */
466
434
+static char *map_tzfile(const char *timezone, size_t *length)
467
435
+{
470
438
+       char *p;
471
439
+       int fd;
472
440
+       
473
 
+       if (!is_valid_tz_name(timezone)) {
 
441
+       if (timezone[0] == '\0' || strstr(timezone, "..") != NULL) {
474
442
+               return NULL;
475
443
+       }
476
444
+
479
447
+       fd = open(fname, O_RDONLY);
480
448
+       if (fd == -1) {
481
449
+               return NULL;
482
 
+       } else if (fstat(fd, &st) != 0 || st.st_size < 21) {
 
450
+       } else if (fstat(fd, &st) != 0 || !is_valid_tzfile(&st)) {
483
451
+               close(fd);
484
452
+               return NULL;
485
453
+       }
490
458
+       
491
459
+       return p != MAP_FAILED ? p : NULL;
492
460
+}
 
461
+
493
462
+#endif
494
463
+
495
 
+/* seek_to_tz_position() for a builtin/external database. */
496
 
+static int inmem_seek_to_tz_position(const unsigned char **tzf, 
497
 
+                                                                        char *timezone, const timelib_tzdb *tzdb)
 
464
+static int inmem_seek_to_tz_position(const unsigned char **tzf, char *timezone, const timelib_tzdb *tzdb)
498
465
 {
499
466
        int left = 0, right = tzdb->index_size - 1;
500
467
 #ifdef HAVE_SETLOCALE
501
 
@@ -299,36 +747,131 @@ static int seek_to_tz_position(const uns
 
468
@@ -299,36 +709,125 @@ static int seek_to_tz_position(const uns
502
469
        return 0;
503
470
 }
504
471
 
505
 
+/* Modified seek_to_tz_position wrapper which handles the system
506
 
+ * database and the builtin/external databases in the same way.
507
 
+ * Returns zero on failure on non-zero on success.  On success, (*map,
508
 
+ * *maplen) is an mmap'ed region if *map is non-NULL, and must be
509
 
+ * munmaped after use.  */
510
472
+static int seek_to_tz_position(const unsigned char **tzf, char *timezone, 
511
 
+                                                          char **map, size_t *maplen,
512
 
+                                                          const timelib_tzdb *tzdb)
 
473
+                              char **map, size_t *maplen,
 
474
+                              const timelib_tzdb *tzdb)
513
475
+{
514
 
+#ifdef HAVE_SYSTEM_TZDATA
515
476
+       if (tzdb == timezonedb_system) {
516
477
+               char *orig;
517
478
+
522
483
+               
523
484
+               (*tzf) = (unsigned char *)orig ;
524
485
+               *map = orig;
525
 
+                               
526
 
+               return 1;
 
486
+                
 
487
+                return 1;
527
488
+       }
528
 
+       else 
529
 
+#endif
530
 
+       {
 
489
+       else {
531
490
+               return inmem_seek_to_tz_position(tzf, timezone, tzdb);
532
491
+       }
533
492
+}
542
501
+               tmp->data = NULL;
543
502
+               create_zone_index(tmp);
544
503
+               system_location_table = create_location_table();
545
 
+               fake_data_segment(tmp, system_location_table);
 
504
+                fake_data_segment(tmp, system_location_table);
546
505
+               timezonedb_system = tmp;
547
506
+       }
 
507
+
548
508
+                       
549
509
+       return timezonedb_system;
550
510
+#else
569
529
-       return (seek_to_tz_position(&tzf, timezone, tzdb));
570
530
+
571
531
+#ifdef HAVE_SYSTEM_TZDATA
572
 
+       if (tzdb == timezonedb_system) {
573
 
+               char fname[PATH_MAX];
574
 
+               struct stat st;
575
 
+               
576
 
+               if (!is_valid_tz_name(timezone)) {
577
 
+                       return 0;
578
 
+               }
579
 
+        
580
 
+               snprintf(fname, sizeof fname, ZONEINFO_PREFIX "/%s", timezone);
581
 
+        
582
 
+               return stat(fname, &st) == 0 && S_ISREG(st.st_mode);
583
 
+       }
 
532
+        if (tzdb == timezonedb_system) {
 
533
+            char fname[PATH_MAX];
 
534
+            struct stat st;
 
535
+
 
536
+            if (timezone[0] == '\0' || strstr(timezone, "..") != NULL) {
 
537
+               return 0;
 
538
+            }
 
539
+            
 
540
+            snprintf(fname, sizeof fname, ZONEINFO_PREFIX "/%s", timezone);
 
541
+            
 
542
+            return stat(fname, &st) == 0 && is_valid_tzfile(&st);
 
543
+        }
584
544
+#endif
585
545
+
586
546
+       return (inmem_seek_to_tz_position(&tzf, timezone, tzdb));
606
566
+#ifdef HAVE_SYSTEM_TZDATA
607
567
+               if (memmap) {
608
568
+                       const struct location_info *li;
609
 
+                       
 
569
+
610
570
+                       /* TZif-style - grok the location info from the system database,
611
571
+                        * if possible. */
 
572
+
612
573
+                       if ((li = find_zone_info(system_location_table, timezone)) != NULL) {
613
574
+                               tmp->location.comments = strdup(li->comment);
614
 
+                               strncpy(tmp->location.country_code, li->code, 2);
 
575
+                                strncpy(tmp->location.country_code, li->code, 2);
615
576
+                               tmp->location.longitude = li->longitude;
616
577
+                               tmp->location.latitude = li->latitude;
617
578
+                               tmp->bc = 1;