21 #include "TimeZoneIanaAbbrevMap.h"
29 #include <winpr/string.h>
35 } TimeZoneInanaAbbrevMapEntry;
37 const static char* zonepath =
"/usr/share/zoneinfo";
39 static TimeZoneInanaAbbrevMapEntry* TimeZoneIanaAbbrevMap = NULL;
40 static size_t TimeZoneIanaAbbrevMapSize = 0;
42 static void append(
const char* iana,
const char* sname)
44 const size_t size = TimeZoneIanaAbbrevMapSize + 1;
46 TimeZoneInanaAbbrevMapEntry* tmp =
47 realloc(TimeZoneIanaAbbrevMap, size *
sizeof(TimeZoneInanaAbbrevMapEntry));
50 TimeZoneIanaAbbrevMap = tmp;
51 TimeZoneIanaAbbrevMapSize = size;
53 TimeZoneInanaAbbrevMapEntry* cur = &TimeZoneIanaAbbrevMap[size - 1];
54 cur->Abbrev = _strdup(sname);
55 cur->Iana = _strdup(iana);
58 static void append_timezone(
const char* dir,
const char* name)
66 winpr_asprintf(&tz, &len,
"%s", name);
71 winpr_asprintf(&tz, &len,
"%s/%s", dir, name);
76 const char* otz = getenv(
"TZ");
82 const time_t t = time(NULL);
84 (void)localtime_r(&t, <);
85 append(tz, lt.tm_zone);
88 setenv(
"TZ", oldtz, 1);
97 static void handle_link(
const char* base,
const char* dir,
const char* name);
99 static char* topath(
const char* base,
const char* bname,
const char* name)
104 if (!base && !bname && !name)
108 return _strdup(bname);
111 return _strdup(base);
114 return _strdup(name);
117 winpr_asprintf(&path, &plen,
"%s/%s", bname, name);
119 winpr_asprintf(&path, &plen,
"%s/%s", base, name);
121 winpr_asprintf(&path, &plen,
"%s/%s", base, bname);
123 winpr_asprintf(&path, &plen,
"%s/%s/%s", base, bname, name);
127 static void iterate_subdir_recursive(
const char* base,
const char* bname,
const char* name)
129 char* path = topath(base, bname, name);
133 DIR* d = opendir(path);
136 struct dirent* dp = NULL;
137 while ((dp = readdir(d)) != NULL)
143 if (strcmp(dp->d_name,
".") == 0)
145 if (strcmp(dp->d_name,
"..") == 0)
147 iterate_subdir_recursive(path, dp->d_name, NULL);
151 handle_link(base, bname, dp->d_name);
154 append_timezone(bname, dp->d_name);
165 static char* get_link_target(
const char* base,
const char* dir,
const char* name)
168 char* path = topath(base, dir, name);
178 char* tmp = realloc(target, size + 1);
184 memset(target, 0, size + 1);
185 rc = readlink(path, target, size);
188 }
while ((
size_t)rc >= size);
190 apath = topath(base, dir, target);
197 void handle_link(
const char* base,
const char* dir,
const char* name)
201 char* target = get_link_target(base, dir, name);
204 struct stat s = { 0 };
205 const int rc3 = stat(target, &s);
207 isDir = S_ISDIR(s.st_mode);
215 iterate_subdir_recursive(base, dir, name);
218 append_timezone(dir, name);
225 static void TimeZoneIanaAbbrevCleanup(
void)
227 if (!TimeZoneIanaAbbrevMap)
230 for (
size_t x = 0; x < TimeZoneIanaAbbrevMapSize; x++)
232 TimeZoneInanaAbbrevMapEntry* entry = &TimeZoneIanaAbbrevMap[x];
236 free(TimeZoneIanaAbbrevMap);
237 TimeZoneIanaAbbrevMap = NULL;
238 TimeZoneIanaAbbrevMapSize = 0;
241 static void TimeZoneIanaAbbrevInitialize(
void)
243 static BOOL initialized = FALSE;
247 iterate_subdir_recursive(zonepath, NULL, NULL);
248 (void)atexit(TimeZoneIanaAbbrevCleanup);
252 size_t TimeZoneIanaAbbrevGet(
const char* abbrev,
const char** list,
size_t listsize)
254 TimeZoneIanaAbbrevInitialize();
257 for (
size_t x = 0; x < TimeZoneIanaAbbrevMapSize; x++)
259 const TimeZoneInanaAbbrevMapEntry* entry = &TimeZoneIanaAbbrevMap[x];
260 if (strcmp(abbrev, entry->Abbrev) == 0)
263 list[rc] = entry->Iana;