Blame


1 f35a0486 2008-07-09 devnull #include <u.h>
2 f35a0486 2008-07-09 devnull #include <libc.h>
3 f35a0486 2008-07-09 devnull
4 f35a0486 2008-07-09 devnull /*
5 f35a0486 2008-07-09 devnull * Access local time entries of zoneinfo files.
6 f35a0486 2008-07-09 devnull * Formats 0 and 2 are supported, and 4-byte timestamps
7 fa325e9b 2020-01-10 cross *
8 f35a0486 2008-07-09 devnull * Copyright © 2008 M. Teichgräber
9 88a87fad 2021-03-24 rsc * Contributed under the MIT license used in the rest of the distribution.
10 f35a0486 2008-07-09 devnull */
11 f35a0486 2008-07-09 devnull #include "zoneinfo.h"
12 f35a0486 2008-07-09 devnull
13 f35a0486 2008-07-09 devnull static
14 f35a0486 2008-07-09 devnull struct Zoneinfo
15 f35a0486 2008-07-09 devnull {
16 f35a0486 2008-07-09 devnull int timecnt; /* # of transition times */
17 f35a0486 2008-07-09 devnull int typecnt; /* # of local time types */
18 f35a0486 2008-07-09 devnull int charcnt; /* # of characters of time zone abbreviation strings */
19 f35a0486 2008-07-09 devnull
20 f35a0486 2008-07-09 devnull uchar *ptime;
21 f35a0486 2008-07-09 devnull uchar *ptype;
22 f35a0486 2008-07-09 devnull uchar *ptt;
23 f35a0486 2008-07-09 devnull uchar *pzone;
24 f35a0486 2008-07-09 devnull } z;
25 f35a0486 2008-07-09 devnull
26 f35a0486 2008-07-09 devnull static uchar *tzdata;
27 f35a0486 2008-07-09 devnull
28 f35a0486 2008-07-09 devnull static
29 f35a0486 2008-07-09 devnull uchar*
30 f35a0486 2008-07-09 devnull readtzfile(char *file)
31 f35a0486 2008-07-09 devnull {
32 f35a0486 2008-07-09 devnull uchar *p;
33 f35a0486 2008-07-09 devnull int fd;
34 f35a0486 2008-07-09 devnull Dir *d;
35 f35a0486 2008-07-09 devnull
36 f35a0486 2008-07-09 devnull fd = open(file, OREAD);
37 f35a0486 2008-07-09 devnull if (fd<0)
38 f35a0486 2008-07-09 devnull return nil;
39 0cfb3760 2012-10-21 rsc d = dirfstat(fd);
40 f35a0486 2008-07-09 devnull if (d==nil)
41 f35a0486 2008-07-09 devnull return nil;
42 f35a0486 2008-07-09 devnull p = malloc(d->length);
43 f35a0486 2008-07-09 devnull if (p!=nil)
44 f35a0486 2008-07-09 devnull readn(fd, p, d->length);
45 f35a0486 2008-07-09 devnull free(d);
46 f35a0486 2008-07-09 devnull close(fd);
47 f35a0486 2008-07-09 devnull return p;
48 f35a0486 2008-07-09 devnull }
49 f35a0486 2008-07-09 devnull static char *zonefile;
50 f35a0486 2008-07-09 devnull void
51 f35a0486 2008-07-09 devnull tzfile(char *f)
52 f35a0486 2008-07-09 devnull {
53 f35a0486 2008-07-09 devnull if (tzdata!=nil) {
54 f35a0486 2008-07-09 devnull free(tzdata);
55 f35a0486 2008-07-09 devnull tzdata = nil;
56 f35a0486 2008-07-09 devnull }
57 f35a0486 2008-07-09 devnull z.timecnt = 0;
58 f35a0486 2008-07-09 devnull zonefile = f;
59 f35a0486 2008-07-09 devnull }
60 f35a0486 2008-07-09 devnull
61 f35a0486 2008-07-09 devnull static
62 f35a0486 2008-07-09 devnull long
63 f35a0486 2008-07-09 devnull get4(uchar *p)
64 f35a0486 2008-07-09 devnull {
65 f35a0486 2008-07-09 devnull return (p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
66 f35a0486 2008-07-09 devnull }
67 f35a0486 2008-07-09 devnull
68 f35a0486 2008-07-09 devnull enum {
69 f35a0486 2008-07-09 devnull TTinfosz = 4+1+1,
70 f35a0486 2008-07-09 devnull };
71 f35a0486 2008-07-09 devnull
72 f35a0486 2008-07-09 devnull static
73 f35a0486 2008-07-09 devnull int
74 f35a0486 2008-07-09 devnull parsehead(void)
75 f35a0486 2008-07-09 devnull {
76 f35a0486 2008-07-09 devnull uchar *p;
77 f35a0486 2008-07-09 devnull int ver;
78 f35a0486 2008-07-09 devnull
79 f35a0486 2008-07-09 devnull ver = tzdata[4];
80 f35a0486 2008-07-09 devnull if (ver!=0)
81 f35a0486 2008-07-09 devnull if (ver!='2')
82 f35a0486 2008-07-09 devnull return -1;
83 f35a0486 2008-07-09 devnull
84 f35a0486 2008-07-09 devnull p = tzdata + 4 + 1 + 15;
85 f35a0486 2008-07-09 devnull
86 f35a0486 2008-07-09 devnull z.timecnt = get4(p+3*4);
87 f35a0486 2008-07-09 devnull z.typecnt = get4(p+4*4);
88 f35a0486 2008-07-09 devnull if (z.typecnt==0)
89 f35a0486 2008-07-09 devnull return -1;
90 f35a0486 2008-07-09 devnull z.charcnt = get4(p+5*4);
91 f35a0486 2008-07-09 devnull z.ptime = p+6*4;
92 f35a0486 2008-07-09 devnull z.ptype = z.ptime + z.timecnt*4;
93 f35a0486 2008-07-09 devnull z.ptt = z.ptype + z.timecnt;
94 f35a0486 2008-07-09 devnull z.pzone = z.ptt + z.typecnt*TTinfosz;
95 f35a0486 2008-07-09 devnull return 0;
96 f35a0486 2008-07-09 devnull }
97 f35a0486 2008-07-09 devnull
98 f35a0486 2008-07-09 devnull static
99 f35a0486 2008-07-09 devnull void
100 f35a0486 2008-07-09 devnull ttinfo(Tinfo *ti, int tti)
101 f35a0486 2008-07-09 devnull {
102 f35a0486 2008-07-09 devnull uchar *p;
103 f35a0486 2008-07-09 devnull int i;
104 f35a0486 2008-07-09 devnull
105 f35a0486 2008-07-09 devnull i = z.ptype[tti];
106 f35a0486 2008-07-09 devnull assert(i<z.typecnt);
107 f35a0486 2008-07-09 devnull p = z.ptt + i*TTinfosz;
108 f35a0486 2008-07-09 devnull ti->tzoff = get4(p);
109 f35a0486 2008-07-09 devnull ti->dlflag = p[4];
110 f35a0486 2008-07-09 devnull assert(p[5]<z.charcnt);
111 f35a0486 2008-07-09 devnull ti->zone = (char*)z.pzone + p[5];
112 f35a0486 2008-07-09 devnull }
113 f35a0486 2008-07-09 devnull
114 f35a0486 2008-07-09 devnull static
115 f35a0486 2008-07-09 devnull void
116 f35a0486 2008-07-09 devnull readtimezone(void)
117 f35a0486 2008-07-09 devnull {
118 f35a0486 2008-07-09 devnull char *tmp;
119 f35a0486 2008-07-09 devnull
120 f35a0486 2008-07-09 devnull z.timecnt = 0;
121 0cfb3760 2012-10-21 rsc if(zonefile==nil) {
122 f35a0486 2008-07-09 devnull if ((tmp=getenv("timezone"))!=nil) {
123 f35a0486 2008-07-09 devnull tzdata = readtzfile(tmp);
124 f35a0486 2008-07-09 devnull free(tmp);
125 0cfb3760 2012-10-21 rsc goto havedata;
126 f35a0486 2008-07-09 devnull }
127 f35a0486 2008-07-09 devnull zonefile = "/etc/localtime";
128 f35a0486 2008-07-09 devnull }
129 0cfb3760 2012-10-21 rsc tzdata = readtzfile(zonefile);
130 f35a0486 2008-07-09 devnull if (tzdata==nil)
131 f35a0486 2008-07-09 devnull return;
132 f35a0486 2008-07-09 devnull
133 0cfb3760 2012-10-21 rsc havedata:
134 f35a0486 2008-07-09 devnull if (strncmp("TZif", (char*)tzdata, 4)!=0)
135 f35a0486 2008-07-09 devnull goto errfree;
136 f35a0486 2008-07-09 devnull
137 f35a0486 2008-07-09 devnull if (parsehead()==-1) {
138 f35a0486 2008-07-09 devnull errfree:
139 f35a0486 2008-07-09 devnull free(tzdata);
140 f35a0486 2008-07-09 devnull tzdata = nil;
141 f35a0486 2008-07-09 devnull z.timecnt = 0;
142 f35a0486 2008-07-09 devnull return;
143 f35a0486 2008-07-09 devnull }
144 f35a0486 2008-07-09 devnull }
145 f35a0486 2008-07-09 devnull
146 f35a0486 2008-07-09 devnull static
147 f35a0486 2008-07-09 devnull tlong
148 f35a0486 2008-07-09 devnull gett4(uchar *p)
149 f35a0486 2008-07-09 devnull {
150 f35a0486 2008-07-09 devnull long l;
151 f35a0486 2008-07-09 devnull
152 f35a0486 2008-07-09 devnull l = get4(p);
153 f35a0486 2008-07-09 devnull if (l<0)
154 f35a0486 2008-07-09 devnull return 0;
155 f35a0486 2008-07-09 devnull return l;
156 f35a0486 2008-07-09 devnull }
157 f35a0486 2008-07-09 devnull int
158 f35a0486 2008-07-09 devnull zonetinfo(Tinfo *ti, int i)
159 f35a0486 2008-07-09 devnull {
160 f35a0486 2008-07-09 devnull if (tzdata==nil)
161 f35a0486 2008-07-09 devnull readtimezone();
162 f35a0486 2008-07-09 devnull if (i<0 || i>=z.timecnt)
163 f35a0486 2008-07-09 devnull return -1;
164 f35a0486 2008-07-09 devnull ti->t = gett4(z.ptime + 4*i);
165 f35a0486 2008-07-09 devnull ttinfo(ti, i);
166 f35a0486 2008-07-09 devnull return i;
167 f35a0486 2008-07-09 devnull }
168 f35a0486 2008-07-09 devnull
169 f35a0486 2008-07-09 devnull int
170 f35a0486 2008-07-09 devnull zonelookuptinfo(Tinfo *ti, tlong t)
171 f35a0486 2008-07-09 devnull {
172 f35a0486 2008-07-09 devnull uchar *p;
173 f35a0486 2008-07-09 devnull int i;
174 f35a0486 2008-07-09 devnull tlong oldtt, tt;
175 f35a0486 2008-07-09 devnull
176 f35a0486 2008-07-09 devnull if (tzdata==nil)
177 f35a0486 2008-07-09 devnull readtimezone();
178 f35a0486 2008-07-09 devnull oldtt = 0;
179 f35a0486 2008-07-09 devnull p = z.ptime;
180 f35a0486 2008-07-09 devnull for (i=0; i<z.timecnt; i++) {
181 f35a0486 2008-07-09 devnull tt = gett4(p);
182 f35a0486 2008-07-09 devnull if (t<tt)
183 f35a0486 2008-07-09 devnull break;
184 f35a0486 2008-07-09 devnull oldtt = tt;
185 f35a0486 2008-07-09 devnull p += 4;
186 f35a0486 2008-07-09 devnull }
187 f35a0486 2008-07-09 devnull if (i>0) {
188 f35a0486 2008-07-09 devnull ttinfo(ti, i-1);
189 f35a0486 2008-07-09 devnull ti->t = oldtt;
190 f35a0486 2008-07-09 devnull // fprint(2, "t:%ld off:%d dflag:%d %s\n", (long)ti->t, ti->tzoff, ti->dlflag, ti->zone);
191 f35a0486 2008-07-09 devnull return i-1;
192 f35a0486 2008-07-09 devnull }
193 f35a0486 2008-07-09 devnull return -1;
194 f35a0486 2008-07-09 devnull }
195 f35a0486 2008-07-09 devnull
196 f35a0486 2008-07-09 devnull void
197 f35a0486 2008-07-09 devnull zonedump(int fd)
198 f35a0486 2008-07-09 devnull {
199 f35a0486 2008-07-09 devnull int i;
200 f35a0486 2008-07-09 devnull uchar *p;
201 f35a0486 2008-07-09 devnull tlong t;
202 f35a0486 2008-07-09 devnull Tinfo ti;
203 f35a0486 2008-07-09 devnull
204 f35a0486 2008-07-09 devnull if (tzdata==nil)
205 f35a0486 2008-07-09 devnull readtimezone();
206 f35a0486 2008-07-09 devnull p = z.ptime;
207 f35a0486 2008-07-09 devnull for (i=0; i<z.timecnt; i++) {
208 f35a0486 2008-07-09 devnull t = gett4(p);
209 f35a0486 2008-07-09 devnull ttinfo(&ti, i);
210 f35a0486 2008-07-09 devnull fprint(fd, "%ld\t%d\t%d\t%s\n", (long)t, ti.tzoff, ti.dlflag, ti.zone);
211 f35a0486 2008-07-09 devnull p += 4;
212 f35a0486 2008-07-09 devnull }
213 f35a0486 2008-07-09 devnull }