Skip to content

Commit b8b0c17

Browse files
author
Зишан Мирза
committed
parse /etc/localtime implementation
1 parent 8cbd30f commit b8b0c17

File tree

3 files changed

+108
-2
lines changed

3 files changed

+108
-2
lines changed

libc/src/time/timezone.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include <fcntl.h>
10+
#include <unistd.h>
11+
#include <stdio.h> // TODO: Remove all printf functions
12+
#include <sys/types.h>
13+
914
#include "src/time/time_utils.h"
1015
#include "src/__support/common.h"
1116
#include "src/time/timezone.h"
@@ -15,8 +20,106 @@ namespace timezone {
1520

1621
using LIBC_NAMESPACE::time_utils::TimeConstants;
1722

23+
void rev_str(char *str) {
24+
int start = 0;
25+
int end = 0;
26+
27+
while (str[end] != '\0') {
28+
end++;
29+
}
30+
end--;
31+
32+
while (start < end) {
33+
str[start] = str[start] ^ str[end];
34+
str[end] = str[start] ^ str[end];
35+
str[start] = str[start] ^ str[end];
36+
37+
start++;
38+
end--;
39+
}
40+
}
41+
1842
int get_timezone_offset(char *timezone) {
1943
(void)timezone;
44+
45+
unsigned char hdr[TIMEZONE_HDR_SIZE];
46+
47+
int32_t magic;
48+
unsigned char version;
49+
__int128_t reserved;
50+
int32_t tzh_ttisutcnt;
51+
int32_t tzh_ttisstdcnt;
52+
int32_t tzh_leapcnt;
53+
int32_t tzh_timecnt;
54+
int32_t tzh_typecnt;
55+
int32_t tzh_charcnt;
56+
57+
int fd;
58+
size_t bytes;
59+
60+
fd = open("/etc/localtime", O_RDONLY);
61+
if (fd < 0) {
62+
return 0;
63+
}
64+
65+
bytes = read(fd, hdr, sizeof(hdr));
66+
if (bytes != sizeof(hdr)) {
67+
return 0;
68+
}
69+
70+
size_t i;
71+
__uint128_t tmp;
72+
73+
// these locations in timezone files are defined in `tzfile`
74+
magic = (hdr[0] << 24) | (hdr[1] << 16) | (hdr[2] << 8) | hdr[3];
75+
version = hdr[4];
76+
for (i = 5; i <= 20; i++) {
77+
tmp = (tmp << 8) | hdr[i];
78+
}
79+
reserved = tmp;
80+
tzh_ttisutcnt = (hdr[20] << 24) | (hdr[21] << 16) | (hdr[22] << 8) | hdr[23];
81+
tzh_ttisstdcnt = (hdr[24] << 24) | (hdr[25] << 16) | (hdr[26] << 8) | hdr[27];
82+
tzh_leapcnt = (hdr[28] << 24) | (hdr[29] << 16) | (hdr[30] << 8) | hdr[31];
83+
tzh_timecnt = (hdr[32] << 24) | (hdr[33] << 16) | (hdr[34] << 8) | hdr[35];
84+
tzh_typecnt = (hdr[36] << 24) | (hdr[37] << 16) | (hdr[38] << 8) | hdr[39];
85+
tzh_charcnt = (hdr[40] << 24) | (hdr[41] << 16) | (hdr[42] << 8) | hdr[43];
86+
(void)tzh_ttisutcnt;
87+
(void)tzh_ttisstdcnt;
88+
(void)tzh_leapcnt;
89+
(void)tzh_typecnt;
90+
(void)tzh_charcnt;
91+
92+
if (magic != 0x545A6966) {
93+
return 0;
94+
}
95+
96+
// currently only supporting tzfile v2
97+
if (version != 0x32) {
98+
return 0;
99+
}
100+
101+
// according to `tzfile`, 15 bytes should be 0
102+
if ((reserved ^ 0x00) != 0) {
103+
return 0;
104+
}
105+
106+
for (i = 0; i < (size_t)tzh_timecnt; i++) {
107+
uint8_t buf[4];
108+
bytes = read(fd, buf, 4);
109+
if (bytes != 4) {
110+
continue;
111+
}
112+
113+
int32_t transition = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
114+
transition = ((transition & 0xFF000000) >> 24) |
115+
((transition & 0x00FF0000) >> 8) |
116+
((transition & 0x0000FF00) << 8) |
117+
((transition & 0x000000FF) << 24);
118+
printf("transition %d: %d\n", i, transition);
119+
}
120+
121+
close(fd);
122+
20123
return 0;
21124
}
22125

libc/src/time/timezone.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
namespace LIBC_NAMESPACE_DECL {
1616
namespace timezone {
1717

18+
// accoring to `tzfile`, timezone header if always 44 bytes
19+
#define TIMEZONE_HDR_SIZE 44
20+
1821
int get_timezone_offset(char *timezone);
1922

2023
} // namespace timezone

libc/test/src/time/localtime_test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ void set_env_var(const char *env) {
2626
}
2727
}
2828

29-
/*TEST(LlvmLibcLocaltime, ValidUnixTimestamp0) {
29+
TEST(LlvmLibcLocaltime, ValidUnixTimestamp0) {
3030
set_env_var("TZ=Europe/Berlin");
3131

3232
const time_t t_ptr = 0;
@@ -42,7 +42,7 @@ void set_env_var(const char *env) {
4242
ASSERT_EQ(0, result->tm_isdst);
4343
}
4444

45-
TEST(LlvmLibcLocaltime, ValidUnixTimestamp32Int) {
45+
/*TEST(LlvmLibcLocaltime, ValidUnixTimestamp32Int) {
4646
set_env_var("TZ=Europe/Berlin");
4747
4848
time_t t_ptr = 2147483647;

0 commit comments

Comments
 (0)