1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * Chenthill Palanisamy <pchenthill@novell.com>
6 * Copyright 2007, Novell, Inc.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU Lesser General Public
10 * License as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
32 #if defined(sun) && defined(__SVR4)
33 #include <sys/types.h>
34 #include <sys/byteorder.h>
36 # ifdef HAVE_BYTESWAP_H
37 # include <byteswap.h>
42 # ifdef HAVE_SYS_ENDIAN_H
43 # include <sys/endian.h>
45 # define bswap_32 bswap32
47 # define bswap_32 swap32
54 #if !defined(HAVE_BYTESWAP_H) && !defined(HAVE_SYS_ENDIAN_H) && !defined(HAVE_ENDIAN_H)
55 #define bswap_16(x) (((x) << 8) & 0xff00) | (((x) >> 8 ) & 0xff)
56 #define bswap_32(x) (((x) << 24) & 0xff000000) \
57 | (((x) << 8) & 0xff0000) \
58 | (((x) >> 8) & 0xff00) \
59 | (((x) >> 24) & 0xff )
60 #define bswap_64(x) ((((x) & 0xff00000000000000ull) >> 56) \
61 | (((x) & 0x00ff000000000000ull) >> 40) \
62 | (((x) & 0x0000ff0000000000ull) >> 24) \
63 | (((x) & 0x000000ff00000000ull) >> 8) \
64 | (((x) & 0x00000000ff000000ull) << 8) \
65 | (((x) & 0x0000000000ff0000ull) << 24) \
66 | (((x) & 0x000000000000ff00ull) << 40) \
67 | (((x) & 0x00000000000000ffull) << 56))
72 #if defined(__APPLE__)
73 #define bswap_16(x) (((x) << 8) & 0xff00) | (((x) >> 8 ) & 0xff)
74 #define bswap_32 __builtin_bswap32
75 #define bswap_64 __builtin_bswap64
96 #include <libical/icalerror.h>
97 #include <icaltz-util.h>
109 static int r_pos [] = {1, 2, 3, -2, -1};
111 static char *search_paths [] = {"/usr/share/zoneinfo","/usr/lib/zoneinfo","/etc/zoneinfo","/usr/share/lib/zoneinfo"};
112 static char *zdir = NULL;
114 #define NUM_SEARCH_PATHS (sizeof (search_paths)/ sizeof (search_paths [0]))
115 #define EFREAD(buf,size,num,fs) \
116 if (fread (buf, size, num, fs) == 0 && ferror (fs)) {\
117 icalerror_set_errno (ICAL_FILE_ERROR); \
138 extern const char *ical_tzid_prefix;
141 decode (const void *ptr)
143 #if defined(sun) && defined(__SVR4)
144 if (sizeof (int) == 4)
146 return *(const int *) ptr;
148 return BSWAP_32 (*(const int *) ptr);
151 if ((BYTE_ORDER == BIG_ENDIAN) && sizeof (int) == 4)
152 return *(const int *) ptr;
153 else if (BYTE_ORDER == LITTLE_ENDIAN && sizeof (int) == 4)
154 return bswap_32 (*(const int *) ptr);
158 const unsigned char *p = ptr;
159 int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0;
161 result = (result << 8) | *p++;
162 result = (result << 8) | *p++;
163 result = (result << 8) | *p++;
164 result = (result << 8) | *p++;
171 zname_from_stridx (char *str, long int idx)
179 while (str [i] != '\0')
184 ret = (char *) malloc (size + 1);
185 ret = strncpy (ret, str, size);
194 char file_path[PATH_MAX];
195 const char *fname = ZONES_TAB_SYSTEM_FILENAME;
198 for (i = 0;i < NUM_SEARCH_PATHS; i++) {
199 sprintf (file_path, "%s/%s", search_paths [i], fname);
200 if (!access (file_path, F_OK|R_OK)) {
201 zdir = search_paths [i];
209 icaltzutil_get_zone_directory (void)
217 /* Calculate the relative position of the week in a month from a date */
219 calculate_pos (icaltimetype icaltime)
223 pos = (icaltime.day -1) / 7;
225 /* Check if pos 3 is the last occurence of the week day in the month */
226 if (pos == 3 && ((icaltime.day + 7) > icaltime_days_in_month (icaltime.month, icaltime.year)))
233 icaltzutil_fetch_timezone (const char *location)
238 unsigned int i, num_trans, num_types, num_chars, num_leaps, num_isstd, num_isgmt;
239 time_t *transitions = NULL;
240 time_t trans, start, end;
241 int *trans_idx = NULL, pos, sign, zidx, zp_idx, idx, prev_idx;
242 ttinfo *types = NULL;
243 char *znames = NULL, *full_path, *tzid, *r_trans, *temp;
245 icalcomponent *tz_comp = NULL, *comp = NULL;
246 icalproperty *icalprop;
247 icaltimetype dtstart, icaltime;
248 struct icalrecurrencetype ical_recur;
251 basedir = icaltzutil_get_zone_directory();
253 icalerror_set_errno (ICAL_FILE_ERROR);
257 full_path = (char *) malloc (strlen (basedir) + strlen (location) + 2);
258 sprintf (full_path,"%s/%s",basedir, location);
260 if ((f = fopen (full_path, "rb")) == 0) {
261 icalerror_set_errno (ICAL_FILE_ERROR);
266 if ((ret = fseek (f, 20, SEEK_SET)) != 0) {
267 icalerror_set_errno (ICAL_FILE_ERROR);
271 EFREAD(&type_cnts, 24, 1, f);
273 num_isgmt = decode (type_cnts.ttisgmtcnt);
274 num_leaps = decode (type_cnts.leapcnt);
275 num_chars = decode (type_cnts.charcnt);
276 num_trans = decode (type_cnts.timecnt);
277 num_isstd = decode (type_cnts.ttisstdcnt);
278 num_types = decode (type_cnts.typecnt);
280 transitions = calloc (num_trans, sizeof (time_t));
281 r_trans = calloc (num_trans, 4);
282 EFREAD(r_trans, 4, num_trans, f);
286 trans_idx = calloc (num_trans, sizeof (int));
287 for (i = 0; i < num_trans; i++) {
288 trans_idx [i] = fgetc (f);
289 transitions [i] = decode (r_trans);
296 types = calloc (num_types, sizeof (ttinfo));
297 for (i = 0; i < num_types; i++) {
304 if((c = fgetc (f)) < 0) {
309 types [i].gmtoff = decode (a);
312 znames = (char *) malloc (num_chars);
313 EFREAD(znames, num_chars, 1, f);
315 /* We got all the information which we need */
317 leaps = calloc (num_leaps, sizeof (leap));
318 for (i = 0; i < num_leaps; i++) {
322 leaps [i].transition = decode (c);
325 leaps [i].change = decode (c);
328 for (i = 0; i < num_isstd; ++i) {
330 types [i].isstd = c != 0;
333 while (i < num_types)
334 types [i++].isstd = 0;
336 for (i = 0; i < num_isgmt; ++i) {
338 types [i].isgmt = c != 0;
341 while (i < num_types)
342 types [i++].isgmt = 0;
344 /* Read all the contents now */
346 for (i = 0; i < num_types; i++)
347 types [i].zname = zname_from_stridx (znames, types [i].abbr);
349 tz_comp = icalcomponent_new (ICAL_VTIMEZONE_COMPONENT);
351 /* Add tzid property */
352 tzid = (char *) malloc (strlen (ical_tzid_prefix) + strlen (location) + 8);
353 sprintf (tzid, "%sTzfile/%s", ical_tzid_prefix, location);
354 icalprop = icalproperty_new_tzid (tzid);
355 icalcomponent_add_property (tz_comp, icalprop);
358 icalprop = icalproperty_new_x (location);
359 icalproperty_set_x_name (icalprop, "X-LIC-LOCATION");
360 icalcomponent_add_property (tz_comp, icalprop);
363 if (num_trans == 0) {
370 for (i = 1; i < num_trans; i++, start = end) {
373 end = transitions [i] + types [prev_idx].gmtoff;
374 /* don't bother starting until the epoch */
378 if (types [prev_idx].isdst)
379 comp = icalcomponent_new (ICAL_XDAYLIGHT_COMPONENT);
381 comp = icalcomponent_new (ICAL_XSTANDARD_COMPONENT);
382 icalprop = icalproperty_new_tzname (types [prev_idx].zname);
383 icalcomponent_add_property (comp, icalprop);
384 dtstart = icaltime_from_timet(start, 0);
385 icalprop = icalproperty_new_dtstart (dtstart);
386 icalcomponent_add_property (comp, icalprop);
387 icalprop = icalproperty_new_tzoffsetfrom (types [idx].gmtoff);
388 icalcomponent_add_property (comp, icalprop);
389 icalprop = icalproperty_new_tzoffsetto (types [prev_idx].gmtoff);
390 icalcomponent_add_property (comp, icalprop);
391 icalcomponent_add_component (tz_comp, comp);
393 /* finally, add a last zone with no end date */
394 if (types [idx].isdst)
395 comp = icalcomponent_new (ICAL_XDAYLIGHT_COMPONENT);
397 comp = icalcomponent_new (ICAL_XSTANDARD_COMPONENT);
398 icalprop = icalproperty_new_tzname (types [idx].zname);
399 icalcomponent_add_property (comp, icalprop);
400 dtstart = icaltime_from_timet(start, 0);
401 icalprop = icalproperty_new_dtstart (dtstart);
402 icalcomponent_add_property (comp, icalprop);
403 icalprop = icalproperty_new_tzoffsetfrom (types [prev_idx].gmtoff);
404 icalcomponent_add_property (comp, icalprop);
405 icalprop = icalproperty_new_tzoffsetto (types [idx].gmtoff);
406 icalcomponent_add_property (comp, icalprop);
407 icalcomponent_add_component (tz_comp, comp);
419 for (i = 0; i < num_types; i++)
421 free (types [i].zname);
435 main (int argc, char *argv [])
437 tzutil_fetch_timezone (argv [1]);