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