21#include "TimeZoneIanaAbbrevMap.h"
29#include <winpr/string.h>
36} TimeZoneInanaAbbrevMapEntry;
38const static char* zonepath =
"/usr/share/zoneinfo";
40static TimeZoneInanaAbbrevMapEntry* TimeZoneIanaAbbrevMap = NULL;
41static size_t TimeZoneIanaAbbrevMapSize = 0;
43static void append(
const char* iana,
const char* sname)
45 const size_t size = TimeZoneIanaAbbrevMapSize + 1;
47 TimeZoneInanaAbbrevMapEntry* tmp =
48 realloc(TimeZoneIanaAbbrevMap, size *
sizeof(TimeZoneInanaAbbrevMapEntry));
51 TimeZoneIanaAbbrevMap = tmp;
52 TimeZoneIanaAbbrevMapSize = size;
54 TimeZoneInanaAbbrevMapEntry* cur = &TimeZoneIanaAbbrevMap[size - 1];
55 cur->Abbrev = _strdup(sname);
56 cur->Iana = _strdup(iana);
59static void append_timezone(
const char* dir,
const char* name)
67 winpr_asprintf(&tz, &len,
"%s", name);
72 winpr_asprintf(&tz, &len,
"%s/%s", dir, name);
77 char* oldtz = setNewAndSaveOldTZ(tz);
79 const time_t t = time(NULL);
81 (void)localtime_r(&t, <);
82 append(tz, lt.tm_zone);
83 restoreSavedTZ(oldtz);
87static void handle_link(
const char* base,
const char* dir,
const char* name);
89static char* topath(
const char* base,
const char* bname,
const char* name)
94 if (!base && !bname && !name)
98 return _strdup(bname);
101 return _strdup(base);
104 return _strdup(name);
107 winpr_asprintf(&path, &plen,
"%s/%s", bname, name);
109 winpr_asprintf(&path, &plen,
"%s/%s", base, name);
111 winpr_asprintf(&path, &plen,
"%s/%s", base, bname);
113 winpr_asprintf(&path, &plen,
"%s/%s/%s", base, bname, name);
117static void iterate_subdir_recursive(
const char* base,
const char* bname,
const char* name)
119 char* path = topath(base, bname, name);
123 DIR* d = opendir(path);
126 struct dirent* dp = NULL;
128 while ((dp = readdir(d)) != NULL)
134 if (strcmp(dp->d_name,
".") == 0)
136 if (strcmp(dp->d_name,
"..") == 0)
138 iterate_subdir_recursive(path, dp->d_name, NULL);
142 handle_link(base, bname, dp->d_name);
145 append_timezone(bname, dp->d_name);
156static char* get_link_target(
const char* base,
const char* dir,
const char* name)
159 char* path = topath(base, dir, name);
169 char* tmp = realloc(target, size + 1);
175 memset(target, 0, size + 1);
176 rc = readlink(path, target, size);
179 }
while ((
size_t)rc >= size);
181 apath = topath(base, dir, target);
188void handle_link(
const char* base,
const char* dir,
const char* name)
192 char* target = get_link_target(base, dir, name);
195 struct stat s = { 0 };
196 const int rc3 = stat(target, &s);
198 isDir = S_ISDIR(s.st_mode);
206 iterate_subdir_recursive(base, dir, name);
209 append_timezone(dir, name);
216static void TimeZoneIanaAbbrevCleanup(
void)
218 if (!TimeZoneIanaAbbrevMap)
221 for (
size_t x = 0; x < TimeZoneIanaAbbrevMapSize; x++)
223 TimeZoneInanaAbbrevMapEntry* entry = &TimeZoneIanaAbbrevMap[x];
227 free(TimeZoneIanaAbbrevMap);
228 TimeZoneIanaAbbrevMap = NULL;
229 TimeZoneIanaAbbrevMapSize = 0;
232static void TimeZoneIanaAbbrevInitialize(
void)
234 static BOOL initialized = FALSE;
238 iterate_subdir_recursive(zonepath, NULL, NULL);
239 (void)atexit(TimeZoneIanaAbbrevCleanup);
243size_t TimeZoneIanaAbbrevGet(
const char* abbrev,
const char** list,
size_t listsize)
245 TimeZoneIanaAbbrevInitialize();
248 for (
size_t x = 0; x < TimeZoneIanaAbbrevMapSize; x++)
250 const TimeZoneInanaAbbrevMapEntry* entry = &TimeZoneIanaAbbrevMap[x];
251 if (strcmp(abbrev, entry->Abbrev) == 0)
254 list[rc] = entry->Iana;