Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: fusl/src/time/__tz.c

Issue 1714623002: [fusl] clang-format fusl (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: headers too Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #include "time_impl.h" 1 #include "time_impl.h"
2 #include <stdint.h> 2 #include <stdint.h>
3 #include <limits.h> 3 #include <limits.h>
4 #include <stdlib.h> 4 #include <stdlib.h>
5 #include <string.h> 5 #include <string.h>
6 #include "libc.h" 6 #include "libc.h"
7 7
8 long __timezone = 0; 8 long __timezone = 0;
9 int __daylight = 0; 9 int __daylight = 0;
10 char *__tzname[2] = { 0, 0 }; 10 char* __tzname[2] = {0, 0};
11 11
12 weak_alias(__timezone, timezone); 12 weak_alias(__timezone, timezone);
13 weak_alias(__daylight, daylight); 13 weak_alias(__daylight, daylight);
14 weak_alias(__tzname, tzname); 14 weak_alias(__tzname, tzname);
15 15
16 static char std_name[TZNAME_MAX+1]; 16 static char std_name[TZNAME_MAX + 1];
17 static char dst_name[TZNAME_MAX+1]; 17 static char dst_name[TZNAME_MAX + 1];
18 const char __gmt[] = "GMT"; 18 const char __gmt[] = "GMT";
19 19
20 static int dst_off; 20 static int dst_off;
21 static int r0[5], r1[5]; 21 static int r0[5], r1[5];
22 22
23 static const unsigned char *zi, *trans, *index, *types, *abbrevs, *abbrevs_end; 23 static const unsigned char *zi, *trans, *index, *types, *abbrevs, *abbrevs_end;
24 static size_t map_size; 24 static size_t map_size;
25 25
26 static char old_tz_buf[32]; 26 static char old_tz_buf[32];
27 static char *old_tz = old_tz_buf; 27 static char* old_tz = old_tz_buf;
28 static size_t old_tz_size = sizeof old_tz_buf; 28 static size_t old_tz_size = sizeof old_tz_buf;
29 29
30 static volatile int lock[2]; 30 static volatile int lock[2];
31 31
32 static int getint(const char **p) 32 static int getint(const char** p) {
33 { 33 unsigned x;
34 » unsigned x; 34 for (x = 0; **p - '0' < 10U; (*p)++)
35 » for (x=0; **p-'0'<10U; (*p)++) x = **p-'0' + 10*x; 35 x = **p - '0' + 10 * x;
36 » return x; 36 return x;
37 } 37 }
38 38
39 static int getoff(const char **p) 39 static int getoff(const char** p) {
40 { 40 int neg = 0;
41 » int neg = 0; 41 if (**p == '-') {
42 » if (**p == '-') { 42 ++*p;
43 » » ++*p; 43 neg = 1;
44 » » neg = 1; 44 } else if (**p == '+') {
45 » } else if (**p == '+') { 45 ++*p;
46 » » ++*p; 46 }
47 » } 47 int off = 3600 * getint(p);
48 » int off = 3600*getint(p); 48 if (**p == ':') {
49 » if (**p == ':') { 49 ++*p;
50 » » ++*p; 50 off += 60 * getint(p);
51 » » off += 60*getint(p); 51 if (**p == ':') {
52 » » if (**p == ':') { 52 ++*p;
53 » » » ++*p; 53 off += getint(p);
54 » » » off += getint(p); 54 }
55 » » } 55 }
56 » } 56 return neg ? -off : off;
57 » return neg ? -off : off; 57 }
58 } 58
59 59 static void getrule(const char** p, int rule[5]) {
60 static void getrule(const char **p, int rule[5]) 60 int r = rule[0] = **p;
61 { 61
62 » int r = rule[0] = **p; 62 if (r != 'M') {
63 63 if (r == 'J')
64 » if (r!='M') { 64 ++*p;
65 » » if (r=='J') ++*p; 65 else
66 » » else rule[0] = 0; 66 rule[0] = 0;
67 » » rule[1] = getint(p); 67 rule[1] = getint(p);
68 » } else { 68 } else {
69 » » ++*p; rule[1] = getint(p); 69 ++*p;
70 » » ++*p; rule[2] = getint(p); 70 rule[1] = getint(p);
71 » » ++*p; rule[3] = getint(p); 71 ++*p;
72 » } 72 rule[2] = getint(p);
73 73 ++*p;
74 » if (**p=='/') { 74 rule[3] = getint(p);
75 » » ++*p; 75 }
76 » » rule[4] = getoff(p); 76
77 » } else { 77 if (**p == '/') {
78 » » rule[4] = 7200; 78 ++*p;
79 » } 79 rule[4] = getoff(p);
80 } 80 } else {
81 81 rule[4] = 7200;
82 static void getname(char *d, const char **p) 82 }
83 { 83 }
84 » int i; 84
85 » if (**p == '<') { 85 static void getname(char* d, const char** p) {
86 » » ++*p; 86 int i;
87 » » for (i=0; **p!='>' && i<TZNAME_MAX; i++) 87 if (**p == '<') {
88 » » » d[i] = (*p)[i]; 88 ++*p;
89 » » ++*p; 89 for (i = 0; **p != '>' && i < TZNAME_MAX; i++)
90 » } else { 90 d[i] = (*p)[i];
91 » » for (i=0; ((*p)[i]|32)-'a'<26U && i<TZNAME_MAX; i++) 91 ++*p;
92 » » » d[i] = (*p)[i]; 92 } else {
93 » } 93 for (i = 0; ((*p)[i] | 32) - 'a' < 26U && i < TZNAME_MAX; i++)
94 » *p += i; 94 d[i] = (*p)[i];
95 » d[i] = 0; 95 }
96 *p += i;
97 d[i] = 0;
96 } 98 }
97 99
98 #define VEC(...) ((const unsigned char[]){__VA_ARGS__}) 100 #define VEC(...) ((const unsigned char[]){__VA_ARGS__})
99 101
100 static uint32_t zi_read32(const unsigned char *z) 102 static uint32_t zi_read32(const unsigned char* z) {
101 { 103 return (unsigned)z[0] << 24 | z[1] << 16 | z[2] << 8 | z[3];
102 » return (unsigned)z[0]<<24 | z[1]<<16 | z[2]<<8 | z[3]; 104 }
103 } 105
104 106 static size_t zi_dotprod(const unsigned char* z,
105 static size_t zi_dotprod(const unsigned char *z, const unsigned char *v, size_t n) 107 const unsigned char* v,
106 { 108 size_t n) {
107 » size_t y; 109 size_t y;
108 » uint32_t x; 110 uint32_t x;
109 » for (y=0; n; n--, z+=4, v++) { 111 for (y = 0; n; n--, z += 4, v++) {
110 » » x = zi_read32(z); 112 x = zi_read32(z);
111 » » y += x * *v; 113 y += x * *v;
112 » } 114 }
113 » return y; 115 return y;
114 } 116 }
115 117
116 int __munmap(void *, size_t); 118 int __munmap(void*, size_t);
117 119
118 static void do_tzset() 120 static void do_tzset() {
119 { 121 char buf[NAME_MAX + 25], *pathname = buf + 24;
120 » char buf[NAME_MAX+25], *pathname=buf+24; 122 const char* try
121 » const char *try, *s, *p; 123 , *s, *p;
122 » const unsigned char *map = 0; 124 const unsigned char* map = 0;
123 » size_t i; 125 size_t i;
124 » static const char search[] = 126 static const char search[] =
125 » » "/usr/share/zoneinfo/\0/share/zoneinfo/\0/etc/zoneinfo/\0"; 127 "/usr/share/zoneinfo/\0/share/zoneinfo/\0/etc/zoneinfo/\0";
126 128
127 » s = getenv("TZ"); 129 s = getenv("TZ");
128 » if (!s) s = "/etc/localtime"; 130 if (!s)
129 » if (!*s) s = __gmt; 131 s = "/etc/localtime";
130 132 if (!*s)
131 » if (old_tz && !strcmp(s, old_tz)) return; 133 s = __gmt;
132 134
133 » if (zi) __munmap((void *)zi, map_size); 135 if (old_tz && !strcmp(s, old_tz))
134 136 return;
135 » /* Cache the old value of TZ to check if it has changed. Avoid 137
136 » * free so as not to pull it into static programs. Growth 138 if (zi)
137 » * strategy makes it so free would have minimal benefit anyway. */ 139 __munmap((void*)zi, map_size);
138 » i = strlen(s); 140
139 » if (i > PATH_MAX+1) s = __gmt, i = 3; 141 /* Cache the old value of TZ to check if it has changed. Avoid
140 » if (i >= old_tz_size) { 142 * free so as not to pull it into static programs. Growth
141 » » old_tz_size *= 2; 143 * strategy makes it so free would have minimal benefit anyway. */
142 » » if (i >= old_tz_size) old_tz_size = i+1; 144 i = strlen(s);
143 » » if (old_tz_size > PATH_MAX+2) old_tz_size = PATH_MAX+2; 145 if (i > PATH_MAX + 1)
144 » » old_tz = malloc(old_tz_size); 146 s = __gmt, i = 3;
145 » } 147 if (i >= old_tz_size) {
146 » if (old_tz) memcpy(old_tz, s, i+1); 148 old_tz_size *= 2;
147 149 if (i >= old_tz_size)
148 » /* Non-suid can use an absolute tzfile pathname or a relative 150 old_tz_size = i + 1;
149 » * pathame beginning with "."; in secure mode, only the 151 if (old_tz_size > PATH_MAX + 2)
150 » * standard path will be searched. */ 152 old_tz_size = PATH_MAX + 2;
151 » if (*s == ':' || ((p=strchr(s, '/')) && !memchr(s, ',', p-s))) { 153 old_tz = malloc(old_tz_size);
152 » » if (*s == ':') s++; 154 }
153 » » if (*s == '/' || *s == '.') { 155 if (old_tz)
154 » » » if (!libc.secure || !strcmp(s, "/etc/localtime")) 156 memcpy(old_tz, s, i + 1);
155 » » » » map = __map_file(s, &map_size); 157
156 » » } else { 158 /* Non-suid can use an absolute tzfile pathname or a relative
157 » » » size_t l = strlen(s); 159 * pathame beginning with "."; in secure mode, only the
158 » » » if (l <= NAME_MAX && !strchr(s, '.')) { 160 * standard path will be searched. */
159 » » » » memcpy(pathname, s, l+1); 161 if (*s == ':' || ((p = strchr(s, '/')) && !memchr(s, ',', p - s))) {
160 » » » » pathname[l] = 0; 162 if (*s == ':')
161 » » » » for (try=search; !map && *try; try+=l+1) { 163 s++;
162 » » » » » l = strlen(try); 164 if (*s == '/' || *s == '.') {
163 » » » » » memcpy(pathname-l, try, l); 165 if (!libc.secure || !strcmp(s, "/etc/localtime"))
164 » » » » » map = __map_file(pathname-l, &map_size); 166 map = __map_file(s, &map_size);
165 » » » » } 167 } else {
166 » » » } 168 size_t l = strlen(s);
167 » » } 169 if (l <= NAME_MAX && !strchr(s, '.')) {
168 » » if (!map) s = __gmt; 170 memcpy(pathname, s, l + 1);
169 » } 171 pathname[l] = 0;
170 » if (map && (map_size < 44 || memcmp(map, "TZif", 4))) { 172 for (try = search; !map && *try; try += l + 1) {
171 » » __munmap((void *)map, map_size); 173 l = strlen(try);
172 » » map = 0; 174 memcpy(pathname - l, try, l);
173 » » s = __gmt; 175 map = __map_file(pathname - l, &map_size);
174 » } 176 }
175 177 }
176 » zi = map; 178 }
177 » if (map) { 179 if (!map)
178 » » int scale = 2; 180 s = __gmt;
179 » » if (sizeof(time_t) > 4 && map[4]=='2') { 181 }
180 » » » size_t skip = zi_dotprod(zi+20, VEC(1,1,8,5,6,1), 6); 182 if (map && (map_size < 44 || memcmp(map, "TZif", 4))) {
181 » » » trans = zi+skip+44+44; 183 __munmap((void*)map, map_size);
182 » » » scale++; 184 map = 0;
183 » » } else { 185 s = __gmt;
184 » » » trans = zi+44; 186 }
185 » » } 187
186 » » index = trans + (zi_read32(trans-12) << scale); 188 zi = map;
187 » » types = index + zi_read32(trans-12); 189 if (map) {
188 » » abbrevs = types + 6*zi_read32(trans-8); 190 int scale = 2;
189 » » abbrevs_end = abbrevs + zi_read32(trans-4); 191 if (sizeof(time_t) > 4 && map[4] == '2') {
190 » » if (zi[map_size-1] == '\n') { 192 size_t skip = zi_dotprod(zi + 20, VEC(1, 1, 8, 5, 6, 1), 6);
191 » » » for (s = (const char *)zi+map_size-2; *s!='\n'; s--); 193 trans = zi + skip + 44 + 44;
192 » » » s++; 194 scale++;
193 » » } else { 195 } else {
194 » » » const unsigned char *p; 196 trans = zi + 44;
195 » » » __tzname[0] = __tzname[1] = 0; 197 }
196 » » » __daylight = __timezone = dst_off = 0; 198 index = trans + (zi_read32(trans - 12) << scale);
197 » » » for (i=0; i<5; i++) r0[i] = r1[i] = 0; 199 types = index + zi_read32(trans - 12);
198 » » » for (p=types; p<abbrevs; p+=6) { 200 abbrevs = types + 6 * zi_read32(trans - 8);
199 » » » » if (!p[4] && !__tzname[0]) { 201 abbrevs_end = abbrevs + zi_read32(trans - 4);
200 » » » » » __tzname[0] = (char *)abbrevs + p[5]; 202 if (zi[map_size - 1] == '\n') {
201 » » » » » __timezone = -zi_read32(p); 203 for (s = (const char*)zi + map_size - 2; *s != '\n'; s--)
202 » » » » } 204 ;
203 » » » » if (p[4] && !__tzname[1]) { 205 s++;
204 » » » » » __tzname[1] = (char *)abbrevs + p[5]; 206 } else {
205 » » » » » dst_off = -zi_read32(p); 207 const unsigned char* p;
206 » » » » » __daylight = 1; 208 __tzname[0] = __tzname[1] = 0;
207 » » » » } 209 __daylight = __timezone = dst_off = 0;
208 » » » } 210 for (i = 0; i < 5; i++)
209 » » » if (!__tzname[0]) __tzname[0] = __tzname[1]; 211 r0[i] = r1[i] = 0;
210 » » » if (!__tzname[0]) __tzname[0] = (char *)__gmt; 212 for (p = types; p < abbrevs; p += 6) {
211 » » » if (!__daylight) { 213 if (!p[4] && !__tzname[0]) {
212 » » » » __tzname[1] = __tzname[0]; 214 __tzname[0] = (char*)abbrevs + p[5];
213 » » » » dst_off = __timezone; 215 __timezone = -zi_read32(p);
214 » » » } 216 }
215 » » » return; 217 if (p[4] && !__tzname[1]) {
216 » » } 218 __tzname[1] = (char*)abbrevs + p[5];
217 » } 219 dst_off = -zi_read32(p);
218 220 __daylight = 1;
219 » if (!s) s = __gmt; 221 }
220 » getname(std_name, &s); 222 }
221 » __tzname[0] = std_name; 223 if (!__tzname[0])
222 » __timezone = getoff(&s); 224 __tzname[0] = __tzname[1];
223 » getname(dst_name, &s); 225 if (!__tzname[0])
224 » __tzname[1] = dst_name; 226 __tzname[0] = (char*)__gmt;
225 » if (dst_name[0]) { 227 if (!__daylight) {
226 » » __daylight = 1; 228 __tzname[1] = __tzname[0];
227 » » if (*s == '+' || *s=='-' || *s-'0'<10U) 229 dst_off = __timezone;
228 » » » dst_off = getoff(&s); 230 }
229 » » else 231 return;
230 » » » dst_off = __timezone - 3600; 232 }
231 » } else { 233 }
232 » » __daylight = 0; 234
233 » » dst_off = 0; 235 if (!s)
234 » } 236 s = __gmt;
235 237 getname(std_name, &s);
236 » if (*s == ',') s++, getrule(&s, r0); 238 __tzname[0] = std_name;
237 » if (*s == ',') s++, getrule(&s, r1); 239 __timezone = getoff(&s);
240 getname(dst_name, &s);
241 __tzname[1] = dst_name;
242 if (dst_name[0]) {
243 __daylight = 1;
244 if (*s == '+' || *s == '-' || *s - '0' < 10U)
245 dst_off = getoff(&s);
246 else
247 dst_off = __timezone - 3600;
248 } else {
249 __daylight = 0;
250 dst_off = 0;
251 }
252
253 if (*s == ',')
254 s++, getrule(&s, r0);
255 if (*s == ',')
256 s++, getrule(&s, r1);
238 } 257 }
239 258
240 /* Search zoneinfo rules to find the one that applies to the given time, 259 /* Search zoneinfo rules to find the one that applies to the given time,
241 * and determine alternate opposite-DST-status rule that may be needed. */ 260 * and determine alternate opposite-DST-status rule that may be needed. */
242 261
243 static size_t scan_trans(long long t, int local, size_t *alt) 262 static size_t scan_trans(long long t, int local, size_t* alt) {
244 { 263 int scale = 3 - (trans == zi + 44);
245 » int scale = 3 - (trans == zi+44); 264 uint64_t x;
246 » uint64_t x; 265 int off = 0;
247 » int off = 0; 266
248 267 size_t a = 0, n = (index - trans) >> scale, m;
249 » size_t a = 0, n = (index-trans)>>scale, m; 268
250 269 if (!n) {
251 » if (!n) { 270 if (alt)
252 » » if (alt) *alt = 0; 271 *alt = 0;
253 » » return 0; 272 return 0;
254 » } 273 }
255 274
256 » /* Binary search for 'most-recent rule before t'. */ 275 /* Binary search for 'most-recent rule before t'. */
257 » while (n > 1) { 276 while (n > 1) {
258 » » m = a + n/2; 277 m = a + n / 2;
259 » » x = zi_read32(trans + (m<<scale)); 278 x = zi_read32(trans + (m << scale));
260 » » if (scale == 3) x = x<<32 | zi_read32(trans + (m<<scale) + 4); 279 if (scale == 3)
261 » » else x = (int32_t)x; 280 x = x << 32 | zi_read32(trans + (m << scale) + 4);
262 » » if (local) off = (int32_t)zi_read32(types + 6 * index[m-1]); 281 else
263 » » if (t - off < (int64_t)x) { 282 x = (int32_t)x;
264 » » » n /= 2; 283 if (local)
265 » » } else { 284 off = (int32_t)zi_read32(types + 6 * index[m - 1]);
266 » » » a = m; 285 if (t - off < (int64_t)x) {
267 » » » n -= n/2; 286 n /= 2;
268 » » } 287 } else {
269 » } 288 a = m;
270 289 n -= n / 2;
271 » /* First and last entry are special. First means to use lowest-index 290 }
272 » * non-DST type. Last means to apply POSIX-style rule if available. */ 291 }
273 » n = (index-trans)>>scale; 292
274 » if (a == n-1) return -1; 293 /* First and last entry are special. First means to use lowest-index
275 » if (a == 0) { 294 * non-DST type. Last means to apply POSIX-style rule if available. */
276 » » x = zi_read32(trans + (a<<scale)); 295 n = (index - trans) >> scale;
277 » » if (scale == 3) x = x<<32 | zi_read32(trans + (a<<scale) + 4); 296 if (a == n - 1)
278 » » else x = (int32_t)x; 297 return -1;
279 » » if (local) off = (int32_t)zi_read32(types + 6 * index[a-1]); 298 if (a == 0) {
280 » » if (t - off < (int64_t)x) { 299 x = zi_read32(trans + (a << scale));
281 » » » for (a=0; a<(abbrevs-types)/6; a++) { 300 if (scale == 3)
282 » » » » if (types[6*a+4] != types[4]) break; 301 x = x << 32 | zi_read32(trans + (a << scale) + 4);
283 » » » } 302 else
284 » » » if (a == (abbrevs-types)/6) a = 0; 303 x = (int32_t)x;
285 » » » if (types[6*a+4]) { 304 if (local)
286 » » » » *alt = a; 305 off = (int32_t)zi_read32(types + 6 * index[a - 1]);
287 » » » » return 0; 306 if (t - off < (int64_t)x) {
288 » » » } else { 307 for (a = 0; a < (abbrevs - types) / 6; a++) {
289 » » » » *alt = 0; 308 if (types[6 * a + 4] != types[4])
290 » » » » return a; 309 break;
291 » » » } 310 }
292 » » } 311 if (a == (abbrevs - types) / 6)
293 » } 312 a = 0;
294 313 if (types[6 * a + 4]) {
295 » /* Try to find a neighboring opposite-DST-status rule. */ 314 *alt = a;
296 » if (alt) { 315 return 0;
297 » » if (a && types[6*index[a-1]+4] != types[6*index[a]+4]) 316 } else {
298 » » » *alt = index[a-1]; 317 *alt = 0;
299 » » else if (a+1<n && types[6*index[a+1]+4] != types[6*index[a]+4]) 318 return a;
300 » » » *alt = index[a+1]; 319 }
301 » » else 320 }
302 » » » *alt = index[a]; 321 }
303 » } 322
304 323 /* Try to find a neighboring opposite-DST-status rule. */
305 » return index[a]; 324 if (alt) {
306 } 325 if (a && types[6 * index[a - 1] + 4] != types[6 * index[a] + 4])
307 326 *alt = index[a - 1];
308 static int days_in_month(int m, int is_leap) 327 else if (a + 1 < n &&
309 { 328 types[6 * index[a + 1] + 4] != types[6 * index[a] + 4])
310 » if (m==2) return 28+is_leap; 329 *alt = index[a + 1];
311 » else return 30+((0xad5>>(m-1))&1); 330 else
331 *alt = index[a];
332 }
333
334 return index[a];
335 }
336
337 static int days_in_month(int m, int is_leap) {
338 if (m == 2)
339 return 28 + is_leap;
340 else
341 return 30 + ((0xad5 >> (m - 1)) & 1);
312 } 342 }
313 343
314 /* Convert a POSIX DST rule plus year to seconds since epoch. */ 344 /* Convert a POSIX DST rule plus year to seconds since epoch. */
315 345
316 static long long rule_to_secs(const int *rule, int year) 346 static long long rule_to_secs(const int* rule, int year) {
317 { 347 int is_leap;
318 » int is_leap; 348 long long t = __year_to_secs(year, &is_leap);
319 » long long t = __year_to_secs(year, &is_leap); 349 int x, m, n, d;
320 » int x, m, n, d; 350 if (rule[0] != 'M') {
321 » if (rule[0]!='M') { 351 x = rule[1];
322 » » x = rule[1]; 352 if (rule[0] == 'J' && (x < 60 || !is_leap))
323 » » if (rule[0]=='J' && (x < 60 || !is_leap)) x--; 353 x--;
324 » » t += 86400 * x; 354 t += 86400 * x;
325 » } else { 355 } else {
326 » » m = rule[1]; 356 m = rule[1];
327 » » n = rule[2]; 357 n = rule[2];
328 » » d = rule[3]; 358 d = rule[3];
329 » » t += __month_to_secs(m-1, is_leap); 359 t += __month_to_secs(m - 1, is_leap);
330 » » int wday = (int)((t + 4*86400) % (7*86400)) / 86400; 360 int wday = (int)((t + 4 * 86400) % (7 * 86400)) / 86400;
331 » » int days = d - wday; 361 int days = d - wday;
332 » » if (days < 0) days += 7; 362 if (days < 0)
333 » » if (n == 5 && days+28 >= days_in_month(m, is_leap)) n = 4; 363 days += 7;
334 » » t += 86400 * (days + 7*(n-1)); 364 if (n == 5 && days + 28 >= days_in_month(m, is_leap))
335 » } 365 n = 4;
336 » t += rule[4]; 366 t += 86400 * (days + 7 * (n - 1));
337 » return t; 367 }
368 t += rule[4];
369 return t;
338 } 370 }
339 371
340 /* Determine the time zone in effect for a given time in seconds since the 372 /* Determine the time zone in effect for a given time in seconds since the
341 * epoch. It can be given in local or universal time. The results will 373 * epoch. It can be given in local or universal time. The results will
342 * indicate whether DST is in effect at the queried time, and will give both 374 * indicate whether DST is in effect at the queried time, and will give both
343 * the GMT offset for the active zone/DST rule and the opposite DST. This 375 * the GMT offset for the active zone/DST rule and the opposite DST. This
344 * enables a caller to efficiently adjust for the case where an explicit 376 * enables a caller to efficiently adjust for the case where an explicit
345 * DST specification mismatches what would be in effect at the time. */ 377 * DST specification mismatches what would be in effect at the time. */
346 378
347 void __secs_to_zone(long long t, int local, int *isdst, long *offset, long *oppo ff, const char **zonename) 379 void __secs_to_zone(long long t,
348 { 380 int local,
349 » LOCK(lock); 381 int* isdst,
382 long* offset,
383 long* oppoff,
384 const char** zonename) {
385 LOCK(lock);
350 386
351 » do_tzset(); 387 do_tzset();
352 388
353 » if (zi) { 389 if (zi) {
354 » » size_t alt, i = scan_trans(t, local, &alt); 390 size_t alt, i = scan_trans(t, local, &alt);
355 » » if (i != -1) { 391 if (i != -1) {
356 » » » *isdst = types[6*i+4]; 392 *isdst = types[6 * i + 4];
357 » » » *offset = (int32_t)zi_read32(types+6*i); 393 *offset = (int32_t)zi_read32(types + 6 * i);
358 » » » *zonename = (const char *)abbrevs + types[6*i+5]; 394 *zonename = (const char*)abbrevs + types[6 * i + 5];
359 » » » if (oppoff) *oppoff = (int32_t)zi_read32(types+6*alt); 395 if (oppoff)
360 » » » UNLOCK(lock); 396 *oppoff = (int32_t)zi_read32(types + 6 * alt);
361 » » » return; 397 UNLOCK(lock);
362 » » } 398 return;
363 » } 399 }
400 }
364 401
365 » if (!__daylight) goto std; 402 if (!__daylight)
403 goto std;
366 404
367 » /* FIXME: may be broken if DST changes right at year boundary? 405 /* FIXME: may be broken if DST changes right at year boundary?
368 » * Also, this could be more efficient.*/ 406 * Also, this could be more efficient.*/
369 » long long y = t / 31556952 + 70; 407 long long y = t / 31556952 + 70;
370 » while (__year_to_secs(y, 0) > t) y--; 408 while (__year_to_secs(y, 0) > t)
371 » while (__year_to_secs(y+1, 0) < t) y++; 409 y--;
410 while (__year_to_secs(y + 1, 0) < t)
411 y++;
372 412
373 » long long t0 = rule_to_secs(r0, y); 413 long long t0 = rule_to_secs(r0, y);
374 » long long t1 = rule_to_secs(r1, y); 414 long long t1 = rule_to_secs(r1, y);
375 415
376 » if (t0 < t1) { 416 if (t0 < t1) {
377 » » if (!local) { 417 if (!local) {
378 » » » t0 += __timezone; 418 t0 += __timezone;
379 » » » t1 += dst_off; 419 t1 += dst_off;
380 » » } 420 }
381 » » if (t >= t0 && t < t1) goto dst; 421 if (t >= t0 && t < t1)
382 » » goto std; 422 goto dst;
383 » } else { 423 goto std;
384 » » if (!local) { 424 } else {
385 » » » t1 += __timezone; 425 if (!local) {
386 » » » t0 += dst_off; 426 t1 += __timezone;
387 » » } 427 t0 += dst_off;
388 » » if (t >= t1 && t < t0) goto std; 428 }
389 » » goto dst; 429 if (t >= t1 && t < t0)
390 » } 430 goto std;
431 goto dst;
432 }
391 std: 433 std:
392 » *isdst = 0; 434 *isdst = 0;
393 » *offset = -__timezone; 435 *offset = -__timezone;
394 » if (oppoff) *oppoff = -dst_off; 436 if (oppoff)
395 » *zonename = __tzname[0]; 437 *oppoff = -dst_off;
396 » UNLOCK(lock); 438 *zonename = __tzname[0];
397 » return; 439 UNLOCK(lock);
440 return;
398 dst: 441 dst:
399 » *isdst = 1; 442 *isdst = 1;
400 » *offset = -dst_off; 443 *offset = -dst_off;
401 » if (oppoff) *oppoff = -__timezone; 444 if (oppoff)
402 » *zonename = __tzname[1]; 445 *oppoff = -__timezone;
403 » UNLOCK(lock); 446 *zonename = __tzname[1];
447 UNLOCK(lock);
404 } 448 }
405 449
406 void __tzset() 450 void __tzset() {
407 { 451 LOCK(lock);
408 » LOCK(lock); 452 do_tzset();
409 » do_tzset(); 453 UNLOCK(lock);
410 » UNLOCK(lock);
411 } 454 }
412 455
413 weak_alias(__tzset, tzset); 456 weak_alias(__tzset, tzset);
414 457
415 const char *__tm_to_tzname(const struct tm *tm) 458 const char* __tm_to_tzname(const struct tm* tm) {
416 { 459 const void* p = tm->__tm_zone;
417 » const void *p = tm->__tm_zone; 460 LOCK(lock);
418 » LOCK(lock); 461 do_tzset();
419 » do_tzset(); 462 if (p != __gmt && p != __tzname[0] && p != __tzname[1] &&
420 » if (p != __gmt && p != __tzname[0] && p != __tzname[1] && 463 (!zi || (uintptr_t)p - (uintptr_t)abbrevs >= abbrevs_end - abbrevs))
421 » (!zi || (uintptr_t)p-(uintptr_t)abbrevs >= abbrevs_end - abbrevs)) 464 p = "";
422 » » p = ""; 465 UNLOCK(lock);
423 » UNLOCK(lock); 466 return p;
424 » return p;
425 } 467 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698