Fixed timezone detection on linux.

Fix originally proposed via IRC by myth0s
Original changeset at https://paste.debian.net/hidden/0a03314a/
This commit is contained in:
Armin Novak 2021-09-20 08:18:42 +02:00 committed by akallabeth
parent b3ae8cec8d
commit 1d9e886a7f

View File

@ -95,13 +95,16 @@ static char* winpr_read_unix_timezone_identifier_from_file(FILE* fp)
return tzid;
}
static char* winpr_get_timezone_from_link(void)
static char* winpr_get_timezone_from_link(const char* links[], size_t count)
{
const char* links[] = { "/etc/localtime", "/etc/TZ" };
const char* _links[] = { "/etc/localtime", "/etc/TZ" };
size_t x;
ssize_t len;
char buf[1024];
char* tzid = NULL;
if (links == NULL)
{
links = _links;
count = ARRAYSIZE(_links);
}
/*
* On linux distros such as Redhat or Archlinux, a symlink at /etc/localtime
@ -110,42 +113,53 @@ static char* winpr_get_timezone_from_link(void)
* Some distributions do have to symlink at /etc/TZ.
*/
for (x = 0; x < sizeof(links) / sizeof(links[0]); x++)
for (x = 0; x < count; x++)
{
char* tzid = NULL;
const char* link = links[x];
char* buf = realpath(link, NULL);
if ((len = readlink(link, buf, sizeof(buf) - 1)) != -1)
if (buf)
{
int num = 0;
size_t alloc;
SSIZE_T pos = len;
buf[len] = '\0';
size_t i;
size_t sep = 0;
size_t alloc = 0;
size_t pos = 0;
size_t len = pos = strlen(buf);
/* find the position of the 2nd to last "/" */
while (num < 2)
for (i = 1; i <= len; i++)
{
if (pos == 0)
const size_t curpos = len - i;
const char cur = buf[curpos];
if (cur == '/')
sep++;
if (sep >= 2)
{
alloc = i;
pos = len - i + 1;
break;
pos -= 1;
if (buf[pos] == '/')
num++;
}
}
if ((len < 0) || (pos < 0) || (pos > len))
return NULL;
if ((len == 0) || (sep != 2))
goto end;
alloc = (size_t)len - (size_t)pos;
tzid = (char*)malloc(alloc + 1);
tzid = (char*)calloc(alloc + 1, sizeof(char));
if (!tzid)
return NULL;
goto end;
strncpy(tzid, buf + pos + 1, alloc);
return tzid;
strncpy(tzid, &buf[pos], alloc);
WLog_INFO(TAG, "winpr_get_timezone_from_link: tzid: %s", tzid);
goto end;
}
end:
free(buf);
if (tzid)
return tzid;
}
return NULL;
@ -249,6 +263,8 @@ static char* winpr_get_unix_timezone_identifier_from_file(void)
tzid = winpr_read_unix_timezone_identifier_from_file(fp);
fclose(fp);
if (tzid != NULL)
WLog_INFO(TAG, "winpr_get_unix_timezone_identifier_from_file: tzid: %s", tzid);
return tzid;
#endif
}
@ -284,7 +300,7 @@ static BOOL winpr_match_unix_timezone_identifier_with_list(const char* tzid, con
static TIME_ZONE_ENTRY* winpr_detect_windows_time_zone(void)
{
size_t i, j;
char* tzid = NULL;
char *tzid = NULL, *ntzid = NULL;
LPCSTR tz = "TZ";
DWORD nSize = GetEnvironmentVariableA(tz, NULL, 0);
@ -302,11 +318,29 @@ static TIME_ZONE_ENTRY* winpr_detect_windows_time_zone(void)
tzid = winpr_get_unix_timezone_identifier_from_file();
if (tzid == NULL)
tzid = winpr_get_timezone_from_link();
{
tzid = winpr_get_timezone_from_link(NULL, 0);
}
else
{
const char* zipath = "/usr/share/zoneinfo/";
char buf[1024] = { 0 };
const char* links[] = { buf };
snprintf(buf, ARRAYSIZE(buf), "%s%s", zipath, tzid);
ntzid = winpr_get_timezone_from_link(links, 1);
if (ntzid != NULL)
{
free(tzid);
tzid = ntzid;
}
}
if (tzid == NULL)
return NULL;
WLog_INFO(TAG, "tzid: %s", tzid);
for (i = 0; i < TimeZoneTableNrElements; i++)
{
const TIME_ZONE_ENTRY* tze = &TimeZoneTable[i];