summaryrefslogtreecommitdiff
path: root/src/libical/icaltz-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libical/icaltz-util.c')
-rw-r--r--src/libical/icaltz-util.c119
1 files changed, 68 insertions, 51 deletions
diff --git a/src/libical/icaltz-util.c b/src/libical/icaltz-util.c
index 3a942e4e..2e6bfce0 100644
--- a/src/libical/icaltz-util.c
+++ b/src/libical/icaltz-util.c
@@ -2,18 +2,9 @@
* Authors :
* Chenthill Palanisamy <pchenthill@novell.com>
*
- * Copyright 2007, Novell, Inc.
+ * SPDX-FileCopyrightText: 2007, Novell, Inc.
*
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of either:
- *
- * The LGPL as published by the Free Software Foundation, version
- * 2.1, available at: https://www.gnu.org/licenses/lgpl-2.1.html
- *
- * Or:
- *
- * The Mozilla Public License Version 2.0. You may obtain a copy of
- * the License at https://www.mozilla.org/MPL/
+ * SPDX-License-Identifier: LGPL-2.1-only OR MPL-2.0
*/
//krazy:excludeall=cpp
@@ -24,6 +15,7 @@
#include "icaltz-util.h"
#include "icalerror.h"
#include "icaltimezone.h"
+#include "icalmemory.h"
#include <stdlib.h>
#include <limits.h>
@@ -82,6 +74,7 @@
#define bswap_64 __builtin_bswap64
#endif
+//@cond PRIVATE
typedef struct
{
char magic[4];
@@ -95,9 +88,11 @@ typedef struct
char charcnt[4];
} tzinfo;
-static const char *zdir = NULL;
+/* fullpath to the system zoneinfo directory (where zone.tab lives) */
+static ICAL_GLOBAL_VAR char s_zoneinfopath[MAXPATHLEN] = {0};
-static const char *search_paths[] = {
+/* A few well-known locations for system zoneinfo; can be overridden with TZDIR environment */
+static const char *s_zoneinfo_search_paths[] = {
"/usr/share/zoneinfo",
"/usr/lib/zoneinfo",
"/etc/zoneinfo",
@@ -123,9 +118,10 @@ typedef struct
typedef struct
{
- time_t transition;
+ icaltime_t transition;
long int change;
} leap;
+//@endcond
static int decode(const void *ptr)
{
@@ -186,35 +182,56 @@ static char *zname_from_stridx(char *str, size_t idx)
size = i - idx;
str += idx;
- ret = (char *)malloc(size + 1);
+ ret = (char *)icalmemory_new_buffer(size + 1);
ret = strncpy(ret, str, size);
ret[size] = '\0';
return ret;
}
-static void set_zonedir(void)
+static void set_zoneinfopath(void)
{
char file_path[MAXPATHLEN];
const char *fname = ZONES_TAB_SYSTEM_FILENAME;
- size_t i, num_search_paths;
+ size_t i, num_zi_search_paths;
+
+ /* Search for the zone.tab file in the dir specified by the TZDIR environment */
+ const char *env_tzdir = getenv("TZDIR");
+ if (env_tzdir != NULL) {
+ snprintf(file_path, MAXPATHLEN, "%s/%s", env_tzdir, fname);
+ if (!access (file_path, F_OK|R_OK)) {
+ strncpy(s_zoneinfopath, env_tzdir, MAXPATHLEN-1);
+ return;
+ }
+ }
- num_search_paths = sizeof(search_paths) / sizeof(search_paths[0]);
- for (i = 0; i < num_search_paths; i++) {
- snprintf(file_path, MAXPATHLEN, "%s/%s", search_paths[i], fname);
+ /* Else, search for zone.tab in a list of well-known locations */
+ num_zi_search_paths = sizeof(s_zoneinfo_search_paths) / sizeof(s_zoneinfo_search_paths[0]);
+ for (i = 0; i < num_zi_search_paths; i++) {
+ snprintf(file_path, MAXPATHLEN, "%s/%s", s_zoneinfo_search_paths[i], fname);
if (!access(file_path, F_OK | R_OK)) {
- zdir = search_paths[i];
+ strncpy(s_zoneinfopath, s_zoneinfo_search_paths[i], MAXPATHLEN-1);
break;
}
}
}
+void icaltzutil_set_zone_directory(const char *zonepath)
+{
+ if ((zonepath == NULL) || (zonepath[0] == '\0')) {
+ memset(s_zoneinfopath, 0, MAXPATHLEN);
+ } else {
+ strncpy(s_zoneinfopath, zonepath, MAXPATHLEN-1);
+ }
+}
+
const char *icaltzutil_get_zone_directory(void)
{
- if (!zdir)
- set_zonedir();
+ if (s_zoneinfopath[0] == '\0') {
+ set_zoneinfopath();
+ }
- return zdir;
+ return s_zoneinfopath;
}
static int calculate_pos(icaltimetype icaltime)
@@ -245,7 +262,7 @@ static char *parse_posix_zone(char *p, ttinfo *type)
size = strcspn(p, "-+0123456789,\n");
}
- type->zname = (char *) malloc(size + 1);
+ type->zname = (char *) icalmemory_new_buffer(size + 1);
strncpy(type->zname, p, size);
type->zname[size] = '\0';
p += size;
@@ -269,7 +286,7 @@ static char *parse_posix_zone(char *p, ttinfo *type)
return p;
}
-#define nth_weekday(week, day) ((day + (8 * abs(week))) * ((week < 0) ? -1 : 1))
+#define nth_weekday(week, day) (icalrecurrencetype_encode_day(day, week))
static char *parse_posix_rule(char *p,
struct icalrecurrencetype *recur, icaltimetype *t)
@@ -419,7 +436,7 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
const char *zonedir;
FILE *f = NULL;
char *full_path = NULL;
- time_t *transitions = NULL;
+ icaltime_t *transitions = NULL;
char *r_trans = NULL, *temp;
int *trans_idx = NULL;
ttinfo *types = NULL;
@@ -459,7 +476,7 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
}
size = strlen(zonedir) + strlen(location) + 2;
- full_path = (char *)malloc(size);
+ full_path = (char *)icalmemory_new_buffer(size);
if (full_path == NULL) {
icalerror_set_errno(ICAL_NEWFAILED_ERROR);
goto error;
@@ -481,7 +498,7 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
break;
case '2':
case '3':
- if (sizeof(time_t) == 8) {
+ if (sizeof(icaltime_t) == 8) {
trans_size = 8;
}
break;
@@ -523,24 +540,24 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
}
/* read data block */
- transitions = calloc(num_trans+1, sizeof(time_t)); // +1 for TZ string
+ transitions = icalmemory_new_buffer((num_trans+1) * sizeof(icaltime_t)); // +1 for TZ string
if (transitions == NULL) {
icalerror_set_errno(ICAL_NEWFAILED_ERROR);
goto error;
}
- r_trans = calloc(num_trans, (size_t)trans_size);
+ r_trans = icalmemory_new_buffer(num_trans * (size_t)trans_size);
if (r_trans == NULL) {
icalerror_set_errno(ICAL_NEWFAILED_ERROR);
goto error;
}
- trans_idx = calloc(num_trans+1, sizeof(int)); // +1 for TZ string
+ trans_idx = icalmemory_new_buffer((num_trans+1) * sizeof(int)); // +1 for TZ string
if (trans_idx == NULL) {
icalerror_set_errno(ICAL_NEWFAILED_ERROR);
goto error;
}
if (num_trans == 0) {
// Add one transition using time type 0 at 19011213T204552Z
- transitions[0] = (time_t)INT_MIN;
+ transitions[0] = (icaltime_t)INT_MIN;
trans_idx[0] = 0;
num_trans = 1;
} else {
@@ -549,16 +566,16 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
for (i = 0; i < num_trans; i++) {
trans_idx[i] = fgetc(f);
if (trans_size == 8) {
- transitions[i] = (time_t) decode64(r_trans);
+ transitions[i] = (icaltime_t) decode64(r_trans);
} else {
- transitions[i] = (time_t) decode(r_trans);
+ transitions[i] = (icaltime_t) decode(r_trans);
}
r_trans += trans_size;
}
r_trans = temp;
}
- types = calloc(num_types+2, sizeof(ttinfo)); // +2 for TZ string
+ types = icalmemory_new_buffer((num_types+2) * sizeof(ttinfo)); // +2 for TZ string
if (types == NULL) {
icalerror_set_errno(ICAL_NEWFAILED_ERROR);
goto error;
@@ -577,7 +594,7 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
types[i].gmtoff = decode(a);
}
- znames = (char *)malloc(num_chars);
+ znames = (char *)icalmemory_new_buffer(num_chars);
if (znames == NULL) {
icalerror_set_errno(ICAL_NEWFAILED_ERROR);
goto error;
@@ -586,7 +603,7 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
/* We got all the information which we need */
- leaps = calloc(num_leaps, sizeof(leap));
+ leaps = icalmemory_new_buffer(num_leaps * sizeof(leap));
if (leaps == NULL) {
icalerror_set_errno(ICAL_NEWFAILED_ERROR);
goto error;
@@ -596,9 +613,9 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
EFREAD(c, (size_t)trans_size, 1, f);
if (trans_size == 8) {
- leaps[i].transition = (time_t)decode64(c);
+ leaps[i].transition = (icaltime_t)decode64(c);
} else {
- leaps[i].transition = (time_t)decode(c);
+ leaps[i].transition = (icaltime_t)decode(c);
}
EFREAD(c, 4, 1, f);
@@ -714,7 +731,7 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
/* Add tzid property */
size = strlen(icaltimezone_tzid_prefix()) + strlen(location) + 1;
- tzid = (char *)malloc(size);
+ tzid = (char *)icalmemory_new_buffer(size);
if (tzid == NULL) {
icalerror_set_errno(ICAL_NEWFAILED_ERROR);
goto error;
@@ -731,7 +748,7 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
for (i = 0; i < num_trans; i++) {
int by_day = 0;
- time_t start;
+ icaltime_t start;
enum icalrecurrencetype_weekday dow = ICAL_NO_WEEKDAY;
prev_idx = idx;
@@ -890,34 +907,34 @@ icalcomponent *icaltzutil_fetch_timezone(const char *location)
fclose(f);
if (full_path)
- free(full_path);
+ icalmemory_free_buffer(full_path);
if (transitions)
- free(transitions);
+ icalmemory_free_buffer(transitions);
if (r_trans)
- free(r_trans);
+ icalmemory_free_buffer(r_trans);
if (trans_idx)
- free(trans_idx);
+ icalmemory_free_buffer(trans_idx);
if (types) {
for (i = 0; i < num_types; i++) {
if (types[i].zname) {
- free(types[i].zname);
+ icalmemory_free_buffer(types[i].zname);
}
}
- free(types);
+ icalmemory_free_buffer(types);
}
if (znames)
- free(znames);
+ icalmemory_free_buffer(znames);
if (leaps)
- free(leaps);
+ icalmemory_free_buffer(leaps);
if (tzid)
- free(tzid);
+ icalmemory_free_buffer(tzid);
return tz_comp;
}