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