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);
96 static void handle_link(
const char* base,
const char* dir,
const char* name);
98 static char* topath(
const char* base,
const char* bname,
const char* name)
103 if (!base && !bname && !name)
107 return _strdup(bname);
110 return _strdup(base);
113 return _strdup(name);
116 winpr_asprintf(&path, &plen,
"%s/%s", bname, name);
118 winpr_asprintf(&path, &plen,
"%s/%s", base, name);
120 winpr_asprintf(&path, &plen,
"%s/%s", base, bname);
122 winpr_asprintf(&path, &plen,
"%s/%s/%s", base, bname, name);
126 static void iterate_subdir_recursive(
const char* base,
const char* bname,
const char* name)
128 char* path = topath(base, bname, name);
132 DIR* d = opendir(path);
135 struct dirent* dp = NULL;
136 while ((dp = readdir(d)) != NULL)
142 if (strcmp(dp->d_name,
".") == 0)
144 if (strcmp(dp->d_name,
"..") == 0)
146 iterate_subdir_recursive(path, dp->d_name, NULL);
150 handle_link(base, bname, dp->d_name);
153 append_timezone(bname, dp->d_name);
164 static char* get_link_target(
const char* base,
const char* dir,
const char* name)
167 char* path = topath(base, dir, name);
177 char* tmp = realloc(target, size + 1);
183 memset(target, 0, size + 1);
184 rc = readlink(path, target, size);
187 }
while ((
size_t)rc >= size);
189 apath = topath(base, dir, target);
196 void handle_link(
const char* base,
const char* dir,
const char* name)
200 char* target = get_link_target(base, dir, name);
203 struct stat s = { 0 };
204 const int rc3 = stat(target, &s);
206 isDir = S_ISDIR(s.st_mode);
214 iterate_subdir_recursive(base, dir, name);
217 append_timezone(dir, name);
224 static void TimeZoneIanaAbbrevCleanup(
void)
226 if (!TimeZoneIanaAbbrevMap)
229 for (
size_t x = 0; x < TimeZoneIanaAbbrevMapSize; x++)
231 TimeZoneInanaAbbrevMapEntry* entry = &TimeZoneIanaAbbrevMap[x];
235 free(TimeZoneIanaAbbrevMap);
236 TimeZoneIanaAbbrevMap = NULL;
237 TimeZoneIanaAbbrevMapSize = 0;
240 static void TimeZoneIanaAbbrevInitialize(
void)
242 static BOOL initialized = FALSE;
246 iterate_subdir_recursive(zonepath, NULL, NULL);
247 (void)atexit(TimeZoneIanaAbbrevCleanup);
251 size_t TimeZoneIanaAbbrevGet(
const char* abbrev,
const char** list,
size_t listsize)
253 TimeZoneIanaAbbrevInitialize();
256 for (
size_t x = 0; x < TimeZoneIanaAbbrevMapSize; x++)
258 const TimeZoneInanaAbbrevMapEntry* entry = &TimeZoneIanaAbbrevMap[x];
259 if (strcmp(abbrev, entry->Abbrev) == 0)
262 list[rc] = entry->Iana;