1 /*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2015-2019 Derick Rethans
5 * Copyright (c) 2018 MongoDB, Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26 #include "timelib.h"
27 #include "timelib_private.h"
28
29 #define TIMELIB_SUPPORTS_V2DATA
30 #include "timezonedb.h"
31
32 #if (defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__))
33 # if defined(__LITTLE_ENDIAN__)
34 # undef WORDS_BIGENDIAN
35 # else
36 # if defined(__BIG_ENDIAN__)
37 # define WORDS_BIGENDIAN
38 # endif
39 # endif
40 #endif
41
42 #if defined(__s390__)
43 # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
44 # define WORDS_BIGENDIAN
45 # else
46 # undef WORDS_BIGENDIAN
47 # endif
48 #endif
49
50 #ifdef WORDS_BIGENDIAN
timelib_conv_int_unsigned(uint32_t value)51 static inline uint32_t timelib_conv_int_unsigned(uint32_t value)
52 {
53 return value;
54 }
55
timelib_conv_int64_unsigned(uint64_t value)56 static inline uint64_t timelib_conv_int64_unsigned(uint64_t value)
57 {
58 return value;
59 }
60 #else
timelib_conv_int_unsigned(uint32_t value)61 static inline uint32_t timelib_conv_int_unsigned(uint32_t value)
62 {
63 return
64 ((value & 0x000000ff) << 24) +
65 ((value & 0x0000ff00) << 8) +
66 ((value & 0x00ff0000) >> 8) +
67 ((value & 0xff000000) >> 24);
68 }
69
timelib_conv_int64_unsigned(uint64_t value)70 static inline uint64_t timelib_conv_int64_unsigned(uint64_t value)
71 {
72 return
73 ((value & 0x00000000000000ff) << 56) +
74 ((value & 0x000000000000ff00) << 40) +
75 ((value & 0x0000000000ff0000) << 24) +
76 ((value & 0x00000000ff000000) << 8) +
77 ((value & 0x000000ff00000000) >> 8) +
78 ((value & 0x0000ff0000000000) >> 24) +
79 ((value & 0x00ff000000000000) >> 40) +
80 ((value & 0xff00000000000000) >> 56);
81 }
82 #endif
83
84 #define timelib_conv_int_signed(value) ((int32_t) timelib_conv_int_unsigned((int32_t) value))
85 #define timelib_conv_int64_signed(value) ((int64_t) timelib_conv_int64_unsigned((int64_t) value))
86
read_php_preamble(const unsigned char ** tzf,timelib_tzinfo * tz)87 static int read_php_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
88 {
89 uint32_t version;
90
91 /* read ID */
92 version = (*tzf)[3] - '0';
93 *tzf += 4;
94
95 /* read BC flag */
96 tz->bc = (**tzf == '\1');
97 *tzf += 1;
98
99 /* read country code */
100 memcpy(tz->location.country_code, *tzf, 2);
101 tz->location.country_code[2] = '\0';
102 *tzf += 2;
103
104 /* skip rest of preamble */
105 *tzf += 13;
106
107 return version;
108 }
109
read_tzif_preamble(const unsigned char ** tzf,timelib_tzinfo * tz)110 static int read_tzif_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
111 {
112 uint32_t version;
113
114 /* read ID */
115 switch ((*tzf)[4]) {
116 case '\0':
117 version = 0;
118 break;
119 case '2':
120 version = 2;
121 break;
122 case '3':
123 version = 3;
124 break;
125 default:
126 return -1;
127 }
128 *tzf += 5;
129
130 /* set BC flag and country code to default */
131 tz->bc = 0;
132 tz->location.country_code[0] = '?';
133 tz->location.country_code[1] = '?';
134 tz->location.country_code[2] = '\0';
135
136 /* skip rest of preamble */
137 *tzf += 15;
138
139 return version;
140 }
141
read_preamble(const unsigned char ** tzf,timelib_tzinfo * tz,unsigned int * type)142 static int read_preamble(const unsigned char **tzf, timelib_tzinfo *tz, unsigned int *type)
143 {
144 /* read marker (TZif) or (PHP) */
145 if (memcmp(*tzf, "PHP", 3) == 0) {
146 *type = TIMELIB_TZINFO_PHP;
147 return read_php_preamble(tzf, tz);
148 } else if (memcmp(*tzf, "TZif", 4) == 0) {
149 *type = TIMELIB_TZINFO_ZONEINFO;
150 return read_tzif_preamble(tzf, tz);
151 } else {
152 return -1;
153 }
154 }
155
read_32bit_header(const unsigned char ** tzf,timelib_tzinfo * tz)156 static void read_32bit_header(const unsigned char **tzf, timelib_tzinfo *tz)
157 {
158 uint32_t buffer[6];
159
160 memcpy(&buffer, *tzf, sizeof(buffer));
161 tz->_bit32.ttisgmtcnt = timelib_conv_int_unsigned(buffer[0]);
162 tz->_bit32.ttisstdcnt = timelib_conv_int_unsigned(buffer[1]);
163 tz->_bit32.leapcnt = timelib_conv_int_unsigned(buffer[2]);
164 tz->_bit32.timecnt = timelib_conv_int_unsigned(buffer[3]);
165 tz->_bit32.typecnt = timelib_conv_int_unsigned(buffer[4]);
166 tz->_bit32.charcnt = timelib_conv_int_unsigned(buffer[5]);
167
168 *tzf += sizeof(buffer);
169 }
170
read_64bit_transitions(const unsigned char ** tzf,timelib_tzinfo * tz)171 static int read_64bit_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
172 {
173 int64_t *buffer = NULL;
174 uint32_t i;
175 unsigned char *cbuffer = NULL;
176
177 if (tz->bit64.timecnt) {
178 buffer = (int64_t*) timelib_malloc(tz->bit64.timecnt * sizeof(int64_t));
179 if (!buffer) {
180 return TIMELIB_ERROR_CANNOT_ALLOCATE;
181 }
182 memcpy(buffer, *tzf, sizeof(int64_t) * tz->bit64.timecnt);
183 *tzf += (sizeof(int64_t) * tz->bit64.timecnt);
184 for (i = 0; i < tz->bit64.timecnt; i++) {
185 buffer[i] = timelib_conv_int64_signed(buffer[i]);
186 /* Sanity check to see whether TS is just increasing */
187 if (i > 0 && !(buffer[i] > buffer[i - 1])) {
188 return TIMELIB_ERROR_CORRUPT_TRANSITIONS_DONT_INCREASE;
189 }
190 }
191
192 cbuffer = (unsigned char*) timelib_malloc(tz->bit64.timecnt * sizeof(unsigned char));
193 if (!cbuffer) {
194 timelib_free(buffer);
195 return TIMELIB_ERROR_CANNOT_ALLOCATE;
196 }
197 memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->bit64.timecnt);
198 *tzf += sizeof(unsigned char) * tz->bit64.timecnt;
199 }
200
201 tz->trans = buffer;
202 tz->trans_idx = cbuffer;
203
204 return 0;
205 }
206
skip_32bit_transitions(const unsigned char ** tzf,timelib_tzinfo * tz)207 static void skip_32bit_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
208 {
209 if (tz->_bit32.timecnt) {
210 *tzf += (sizeof(int32_t) * tz->_bit32.timecnt);
211 *tzf += sizeof(unsigned char) * tz->_bit32.timecnt;
212 }
213 }
214
read_64bit_types(const unsigned char ** tzf,timelib_tzinfo * tz)215 static int read_64bit_types(const unsigned char **tzf, timelib_tzinfo *tz)
216 {
217 unsigned char *buffer;
218 int32_t *leap_buffer;
219 unsigned int i, j;
220
221 /* Offset Types */
222 buffer = (unsigned char*) timelib_malloc(tz->bit64.typecnt * sizeof(unsigned char) * 6);
223 if (!buffer) {
224 return TIMELIB_ERROR_CANNOT_ALLOCATE;
225 }
226 memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->bit64.typecnt);
227 *tzf += sizeof(unsigned char) * 6 * tz->bit64.typecnt;
228
229 tz->type = (ttinfo*) timelib_malloc(tz->bit64.typecnt * sizeof(ttinfo));
230 if (!tz->type) {
231 timelib_free(buffer);
232 return TIMELIB_ERROR_CANNOT_ALLOCATE;
233 }
234
235 for (i = 0; i < tz->bit64.typecnt; i++) {
236 j = i * 6;
237 tz->type[i].offset = 0;
238 tz->type[i].offset += (int32_t) (((uint32_t) buffer[j]) << 24) + (buffer[j + 1] << 16) + (buffer[j + 2] << 8) + tz->type[i].offset + buffer[j + 3];
239 tz->type[i].isdst = buffer[j + 4];
240 tz->type[i].abbr_idx = buffer[j + 5];
241 }
242 timelib_free(buffer);
243
244 /* Abbreviations */
245 tz->timezone_abbr = (char*) timelib_malloc(tz->bit64.charcnt);
246 if (!tz->timezone_abbr) {
247 return TIMELIB_ERROR_CORRUPT_NO_ABBREVIATION;
248 }
249 memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->bit64.charcnt);
250 *tzf += sizeof(char) * tz->bit64.charcnt;
251
252 /* Leap seconds (only use in 'right/') format */
253 if (tz->bit64.leapcnt) {
254 leap_buffer = (int32_t *) timelib_malloc(tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t)));
255 if (!leap_buffer) {
256 return TIMELIB_ERROR_CANNOT_ALLOCATE;
257 }
258 memcpy(leap_buffer, *tzf, tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t)));
259 *tzf += tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t));
260
261 tz->leap_times = (tlinfo*) timelib_malloc(tz->bit64.leapcnt * sizeof(tlinfo));
262 if (!tz->leap_times) {
263 timelib_free(leap_buffer);
264 return TIMELIB_ERROR_CANNOT_ALLOCATE;
265 }
266 for (i = 0; i < tz->bit64.leapcnt; i++) {
267 tz->leap_times[i].trans = timelib_conv_int64_signed(leap_buffer[i * 3 + 1] * 4294967296 + leap_buffer[i * 3]);
268 tz->leap_times[i].offset = timelib_conv_int_signed(leap_buffer[i * 3 + 2]);
269 }
270 timelib_free(leap_buffer);
271 }
272
273 /* Standard/Wall Indicators (unused) */
274 if (tz->bit64.ttisstdcnt) {
275 buffer = (unsigned char*) timelib_malloc(tz->bit64.ttisstdcnt * sizeof(unsigned char));
276 if (!buffer) {
277 return TIMELIB_ERROR_CANNOT_ALLOCATE;
278 }
279 memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit64.ttisstdcnt);
280 *tzf += sizeof(unsigned char) * tz->bit64.ttisstdcnt;
281
282 for (i = 0; i < tz->bit64.ttisstdcnt; i++) {
283 tz->type[i].isstdcnt = buffer[i];
284 }
285 timelib_free(buffer);
286 }
287
288 /* UT/Local Time Indicators (unused) */
289 if (tz->bit64.ttisgmtcnt) {
290 buffer = (unsigned char*) timelib_malloc(tz->bit64.ttisgmtcnt * sizeof(unsigned char));
291 if (!buffer) {
292 return TIMELIB_ERROR_CANNOT_ALLOCATE;
293 }
294 memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit64.ttisgmtcnt);
295 *tzf += sizeof(unsigned char) * tz->bit64.ttisgmtcnt;
296
297 for (i = 0; i < tz->bit64.ttisgmtcnt; i++) {
298 tz->type[i].isgmtcnt = buffer[i];
299 }
300 timelib_free(buffer);
301 }
302
303 return 0;
304 }
305
skip_32bit_types(const unsigned char ** tzf,timelib_tzinfo * tz)306 static void skip_32bit_types(const unsigned char **tzf, timelib_tzinfo *tz)
307 {
308 /* Offset Types */
309 *tzf += sizeof(unsigned char) * 6 * tz->_bit32.typecnt;
310
311 /* Abbreviations */
312 *tzf += sizeof(char) * tz->_bit32.charcnt;
313
314 /* Leap seconds (only use in 'right/') format */
315 if (tz->_bit32.leapcnt) {
316 *tzf += sizeof(int32_t) * tz->_bit32.leapcnt * 2;
317 }
318
319 /* Standard/Wall Indicators (unused) */
320 if (tz->_bit32.ttisstdcnt) {
321 *tzf += sizeof(unsigned char) * tz->_bit32.ttisstdcnt;
322 }
323
324 /* UT/Local Time Indicators (unused) */
325 if (tz->_bit32.ttisgmtcnt) {
326 *tzf += sizeof(unsigned char) * tz->_bit32.ttisgmtcnt;
327 }
328 }
329
skip_posix_string(const unsigned char ** tzf,timelib_tzinfo * tz)330 static void skip_posix_string(const unsigned char **tzf, timelib_tzinfo *tz)
331 {
332 int n_count = 0;
333
334 do {
335 if (*tzf[0] == '\n') {
336 n_count++;
337 }
338 (*tzf)++;
339 } while (n_count < 2);
340 }
341
read_location(const unsigned char ** tzf,timelib_tzinfo * tz)342 static void read_location(const unsigned char **tzf, timelib_tzinfo *tz)
343 {
344 uint32_t buffer[3];
345 uint32_t comments_len;
346
347 memcpy(&buffer, *tzf, sizeof(buffer));
348 tz->location.latitude = timelib_conv_int_unsigned(buffer[0]);
349 tz->location.latitude = (tz->location.latitude / 100000) - 90;
350 tz->location.longitude = timelib_conv_int_unsigned(buffer[1]);
351 tz->location.longitude = (tz->location.longitude / 100000) - 180;
352 comments_len = timelib_conv_int_unsigned(buffer[2]);
353 *tzf += sizeof(buffer);
354
355 tz->location.comments = timelib_malloc(comments_len + 1);
356 memcpy(tz->location.comments, *tzf, comments_len);
357 tz->location.comments[comments_len] = '\0';
358 *tzf += comments_len;
359 }
360
set_default_location_and_comments(const unsigned char ** tzf,timelib_tzinfo * tz)361 static void set_default_location_and_comments(const unsigned char **tzf, timelib_tzinfo *tz)
362 {
363 tz->location.latitude = 0;
364 tz->location.longitude = 0;
365 tz->location.comments = timelib_malloc(2);
366 tz->location.comments[0] = '?';
367 tz->location.comments[1] = '\0';
368 }
369
timelib_dump_tzinfo(timelib_tzinfo * tz)370 void timelib_dump_tzinfo(timelib_tzinfo *tz)
371 {
372 uint32_t i;
373
374 printf("Country Code: %s\n", tz->location.country_code);
375 printf("Geo Location: %f,%f\n", tz->location.latitude, tz->location.longitude);
376 printf("Comments:\n%s\n", tz->location.comments);
377 printf("BC: %s\n", tz->bc ? "" : "yes");
378
379 printf("\n64-bit:\n");
380 printf("UTC/Local count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.ttisgmtcnt);
381 printf("Std/Wall count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.ttisstdcnt);
382 printf("Leap.sec. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.leapcnt);
383 printf("Trans. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.timecnt);
384 printf("Local types count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.typecnt);
385 printf("Zone Abbr. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.charcnt);
386
387 printf ("%16s (%20s) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
388 "", "", 0,
389 (long int) tz->type[0].offset,
390 tz->type[0].isdst,
391 tz->type[0].abbr_idx,
392 &tz->timezone_abbr[tz->type[0].abbr_idx],
393 tz->type[0].isstdcnt,
394 tz->type[0].isgmtcnt
395 );
396 for (i = 0; i < tz->bit64.timecnt; i++) {
397 printf ("%016" PRIX64 " (%20" PRId64 ") = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
398 tz->trans[i], tz->trans[i], tz->trans_idx[i],
399 (long int) tz->type[tz->trans_idx[i]].offset,
400 tz->type[tz->trans_idx[i]].isdst,
401 tz->type[tz->trans_idx[i]].abbr_idx,
402 &tz->timezone_abbr[tz->type[tz->trans_idx[i]].abbr_idx],
403 tz->type[tz->trans_idx[i]].isstdcnt,
404 tz->type[tz->trans_idx[i]].isgmtcnt
405 );
406 }
407 for (i = 0; i < tz->bit64.leapcnt; i++) {
408 printf ("%016" PRIX64 " (%20ld) = %d\n",
409 tz->leap_times[i].trans,
410 (long) tz->leap_times[i].trans,
411 tz->leap_times[i].offset);
412 }
413 }
414
seek_to_tz_position(const unsigned char ** tzf,char * timezone,const timelib_tzdb * tzdb)415 static int seek_to_tz_position(const unsigned char **tzf, char *timezone, const timelib_tzdb *tzdb)
416 {
417 int left = 0, right = tzdb->index_size - 1;
418
419 if (tzdb->index_size == 0) {
420 return 0;
421 }
422
423 do {
424 int mid = ((unsigned)left + right) >> 1;
425 int cmp = timelib_strcasecmp(timezone, tzdb->index[mid].id);
426
427 if (cmp < 0) {
428 right = mid - 1;
429 } else if (cmp > 0) {
430 left = mid + 1;
431 } else { /* (cmp == 0) */
432 (*tzf) = &(tzdb->data[tzdb->index[mid].pos]);
433 return 1;
434 }
435
436 } while (left <= right);
437
438 return 0;
439 }
440
timelib_builtin_db(void)441 const timelib_tzdb *timelib_builtin_db(void)
442 {
443 return &timezonedb_builtin;
444 }
445
timelib_timezone_identifiers_list(const timelib_tzdb * tzdb,int * count)446 const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(const timelib_tzdb *tzdb, int *count)
447 {
448 *count = tzdb->index_size;
449 return tzdb->index;
450 }
451
timelib_timezone_id_is_valid(char * timezone,const timelib_tzdb * tzdb)452 int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb)
453 {
454 const unsigned char *tzf;
455 return (seek_to_tz_position(&tzf, timezone, tzdb));
456 }
457
skip_64bit_preamble(const unsigned char ** tzf,timelib_tzinfo * tz)458 static int skip_64bit_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
459 {
460 if (memcmp(*tzf, "TZif2", 5) == 0) {
461 *tzf += 20;
462 return 1;
463 } else if (memcmp(*tzf, "TZif3", 5) == 0) {
464 *tzf += 20;
465 return 1;
466 } else {
467 return 0;
468 }
469 }
470
read_64bit_header(const unsigned char ** tzf,timelib_tzinfo * tz)471 static void read_64bit_header(const unsigned char **tzf, timelib_tzinfo *tz)
472 {
473 uint32_t buffer[6];
474
475 memcpy(&buffer, *tzf, sizeof(buffer));
476 tz->bit64.ttisgmtcnt = timelib_conv_int_unsigned(buffer[0]);
477 tz->bit64.ttisstdcnt = timelib_conv_int_unsigned(buffer[1]);
478 tz->bit64.leapcnt = timelib_conv_int_unsigned(buffer[2]);
479 tz->bit64.timecnt = timelib_conv_int_unsigned(buffer[3]);
480 tz->bit64.typecnt = timelib_conv_int_unsigned(buffer[4]);
481 tz->bit64.charcnt = timelib_conv_int_unsigned(buffer[5]);
482 *tzf += sizeof(buffer);
483 }
484
timelib_tzinfo_ctor(char * name)485 static timelib_tzinfo* timelib_tzinfo_ctor(char *name)
486 {
487 timelib_tzinfo *t;
488 t = timelib_calloc(1, sizeof(timelib_tzinfo));
489 t->name = timelib_strdup(name);
490
491 return t;
492 }
493
timelib_parse_tzfile(char * timezone,const timelib_tzdb * tzdb,int * error_code)494 timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb, int *error_code)
495 {
496 const unsigned char *tzf;
497 timelib_tzinfo *tmp;
498 int version;
499 int transitions_result, types_result;
500 unsigned int type; /* TIMELIB_TZINFO_PHP or TIMELIB_TZINFO_ZONEINFO */
501
502 if (seek_to_tz_position(&tzf, timezone, tzdb)) {
503 tmp = timelib_tzinfo_ctor(timezone);
504
505 version = read_preamble(&tzf, tmp, &type);
506 if (version < 2 || version > 3) {
507 *error_code = TIMELIB_ERROR_UNSUPPORTED_VERSION;
508 timelib_tzinfo_dtor(tmp);
509 return NULL;
510 }
511 //printf("- timezone: %s, version: %0d\n", timezone, version);
512
513 read_32bit_header(&tzf, tmp);
514 skip_32bit_transitions(&tzf, tmp);
515 skip_32bit_types(&tzf, tmp);
516
517 if (!skip_64bit_preamble(&tzf, tmp)) {
518 /* 64 bit preamble is not in place */
519 *error_code = TIMELIB_ERROR_CORRUPT_NO_64BIT_PREAMBLE;
520 timelib_tzinfo_dtor(tmp);
521 return NULL;
522 }
523 read_64bit_header(&tzf, tmp);
524 if ((transitions_result = read_64bit_transitions(&tzf, tmp)) != 0) {
525 /* Corrupt file as transitions do not increase */
526 *error_code = transitions_result;
527 timelib_tzinfo_dtor(tmp);
528 return NULL;
529 }
530 if ((types_result = read_64bit_types(&tzf, tmp)) != 0) {
531 *error_code = types_result;
532 timelib_tzinfo_dtor(tmp);
533 return NULL;
534 }
535 skip_posix_string(&tzf, tmp);
536
537 if (type == TIMELIB_TZINFO_PHP) {
538 read_location(&tzf, tmp);
539 } else {
540 set_default_location_and_comments(&tzf, tmp);
541 }
542 } else {
543 *error_code = TIMELIB_ERROR_NO_SUCH_TIMEZONE;
544 tmp = NULL;
545 }
546
547 return tmp;
548 }
549
timelib_tzinfo_dtor(timelib_tzinfo * tz)550 void timelib_tzinfo_dtor(timelib_tzinfo *tz)
551 {
552 TIMELIB_TIME_FREE(tz->name);
553 TIMELIB_TIME_FREE(tz->trans);
554 TIMELIB_TIME_FREE(tz->trans_idx);
555 TIMELIB_TIME_FREE(tz->type);
556 TIMELIB_TIME_FREE(tz->timezone_abbr);
557 TIMELIB_TIME_FREE(tz->leap_times);
558 TIMELIB_TIME_FREE(tz->location.comments);
559 TIMELIB_TIME_FREE(tz);
560 tz = NULL;
561 }
562
timelib_tzinfo_clone(timelib_tzinfo * tz)563 timelib_tzinfo *timelib_tzinfo_clone(timelib_tzinfo *tz)
564 {
565 timelib_tzinfo *tmp = timelib_tzinfo_ctor(tz->name);
566 tmp->_bit32.ttisgmtcnt = tz->_bit32.ttisgmtcnt;
567 tmp->_bit32.ttisstdcnt = tz->_bit32.ttisstdcnt;
568 tmp->_bit32.leapcnt = tz->_bit32.leapcnt;
569 tmp->_bit32.timecnt = tz->_bit32.timecnt;
570 tmp->_bit32.typecnt = tz->_bit32.typecnt;
571 tmp->_bit32.charcnt = tz->_bit32.charcnt;
572 tmp->bit64.ttisgmtcnt = tz->bit64.ttisgmtcnt;
573 tmp->bit64.ttisstdcnt = tz->bit64.ttisstdcnt;
574 tmp->bit64.leapcnt = tz->bit64.leapcnt;
575 tmp->bit64.timecnt = tz->bit64.timecnt;
576 tmp->bit64.typecnt = tz->bit64.typecnt;
577 tmp->bit64.charcnt = tz->bit64.charcnt;
578
579 if (tz->bit64.timecnt) {
580 tmp->trans = (int64_t *) timelib_malloc(tz->bit64.timecnt * sizeof(int64_t));
581 tmp->trans_idx = (unsigned char*) timelib_malloc(tz->bit64.timecnt * sizeof(unsigned char));
582 memcpy(tmp->trans, tz->trans, tz->bit64.timecnt * sizeof(int64_t));
583 memcpy(tmp->trans_idx, tz->trans_idx, tz->bit64.timecnt * sizeof(unsigned char));
584 }
585
586 tmp->type = (ttinfo*) timelib_malloc(tz->bit64.typecnt * sizeof(ttinfo));
587 memcpy(tmp->type, tz->type, tz->bit64.typecnt * sizeof(ttinfo));
588
589 tmp->timezone_abbr = (char*) timelib_malloc(tz->bit64.charcnt);
590 memcpy(tmp->timezone_abbr, tz->timezone_abbr, tz->bit64.charcnt);
591
592 if (tz->bit64.leapcnt) {
593 tmp->leap_times = (tlinfo*) timelib_malloc(tz->bit64.leapcnt * sizeof(tlinfo));
594 memcpy(tmp->leap_times, tz->leap_times, tz->bit64.leapcnt * sizeof(tlinfo));
595 }
596
597 return tmp;
598 }
599
fetch_timezone_offset(timelib_tzinfo * tz,timelib_sll ts,timelib_sll * transition_time)600 static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib_sll *transition_time)
601 {
602 uint32_t i;
603
604 /* If there is no transition time, we pick the first one, if that doesn't
605 * exist we return NULL */
606 if (!tz->bit64.timecnt || !tz->trans) {
607 if (tz->bit64.typecnt == 1) {
608 *transition_time = INT64_MIN;
609 return &(tz->type[0]);
610 }
611 return NULL;
612 }
613
614 /* If the TS is lower than the first transition time, then we scan over
615 * all the transition times to find the first non-DST one, or the first
616 * one in case there are only DST entries. Not sure which smartass came up
617 * with this idea in the first though :) */
618 if (ts < tz->trans[0]) {
619 *transition_time = INT64_MIN;
620 return &(tz->type[0]);
621 }
622
623 /* In all other cases we loop through the available transition times to find
624 * the correct entry */
625 for (i = 0; i < tz->bit64.timecnt; i++) {
626 if (ts < tz->trans[i]) {
627 *transition_time = tz->trans[i - 1];
628 return &(tz->type[tz->trans_idx[i - 1]]);
629 }
630 }
631 *transition_time = tz->trans[tz->bit64.timecnt - 1];
632 return &(tz->type[tz->trans_idx[tz->bit64.timecnt - 1]]);
633 }
634
fetch_leaptime_offset(timelib_tzinfo * tz,timelib_sll ts)635 static tlinfo* fetch_leaptime_offset(timelib_tzinfo *tz, timelib_sll ts)
636 {
637 int i;
638
639 if (!tz->bit64.leapcnt || !tz->leap_times) {
640 return NULL;
641 }
642
643 for (i = tz->bit64.leapcnt - 1; i > 0; i--) {
644 if (ts > tz->leap_times[i].trans) {
645 return &(tz->leap_times[i]);
646 }
647 }
648 return NULL;
649 }
650
timelib_timestamp_is_in_dst(timelib_sll ts,timelib_tzinfo * tz)651 int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz)
652 {
653 ttinfo *to;
654 timelib_sll dummy;
655
656 if ((to = fetch_timezone_offset(tz, ts, &dummy))) {
657 return to->isdst;
658 }
659 return -1;
660 }
661
timelib_get_time_zone_info(timelib_sll ts,timelib_tzinfo * tz)662 timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz)
663 {
664 ttinfo *to;
665 tlinfo *tl;
666 int32_t offset = 0, leap_secs = 0;
667 char *abbr;
668 timelib_time_offset *tmp = timelib_time_offset_ctor();
669 timelib_sll transition_time;
670
671 if ((to = fetch_timezone_offset(tz, ts, &transition_time))) {
672 offset = to->offset;
673 abbr = &(tz->timezone_abbr[to->abbr_idx]);
674 tmp->is_dst = to->isdst;
675 tmp->transition_time = transition_time;
676 } else {
677 offset = 0;
678 abbr = tz->timezone_abbr;
679 tmp->is_dst = 0;
680 tmp->transition_time = 0;
681 }
682
683 if ((tl = fetch_leaptime_offset(tz, ts))) {
684 leap_secs = -tl->offset;
685 }
686
687 tmp->offset = offset;
688 tmp->leap_secs = leap_secs;
689 tmp->abbr = abbr ? timelib_strdup(abbr) : timelib_strdup("GMT");
690
691 return tmp;
692 }
693
timelib_get_current_offset(timelib_time * t)694 timelib_sll timelib_get_current_offset(timelib_time *t)
695 {
696 timelib_time_offset *gmt_offset;
697 timelib_sll retval;
698
699 switch (t->zone_type) {
700 case TIMELIB_ZONETYPE_ABBR:
701 case TIMELIB_ZONETYPE_OFFSET:
702 return t->z + (t->dst * 3600);
703
704 case TIMELIB_ZONETYPE_ID:
705 gmt_offset = timelib_get_time_zone_info(t->sse, t->tz_info);
706 retval = gmt_offset->offset;
707 timelib_time_offset_dtor(gmt_offset);
708 return retval;
709
710 default:
711 return 0;
712 }
713 }
714