On March 23, 2021, Nokia transferred the copyrights in the Plan 9 software to the Plan 9 Foundation, which relicensed them under the MIT license. This commit updates the Plan 9 from User Space license to reflect the new base license. The vast majority of the contributions beyond the base Plan 9 set were by me, many of them explicitly under an MIT license. Those are all under the new MIT license now as well. The port of mk to Unix was taken from Inferno via Vita Nuova and had been made available under GPL, but Vita Nuova has relicensed Inferno under the MIT license as well, to match the new Plan 9 license. Michael Teichgraber contributed src/lib9/zoneinfo.c explicitly under the Lucent Public License but has agreed to change the contribution to the MIT license now used in the rest of the distribution. There remain a few exceptions, most notably fonts. See the root LICENSE file for full details. The only mention of the Lucent Public License in the whole tree now is in the LICENSE file, explaining the history.
213 lines
3 KiB
C
213 lines
3 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
|
|
/*
|
|
* Access local time entries of zoneinfo files.
|
|
* Formats 0 and 2 are supported, and 4-byte timestamps
|
|
*
|
|
* Copyright © 2008 M. Teichgräber
|
|
* Contributed under the MIT license used in the rest of the distribution.
|
|
*/
|
|
#include "zoneinfo.h"
|
|
|
|
static
|
|
struct Zoneinfo
|
|
{
|
|
int timecnt; /* # of transition times */
|
|
int typecnt; /* # of local time types */
|
|
int charcnt; /* # of characters of time zone abbreviation strings */
|
|
|
|
uchar *ptime;
|
|
uchar *ptype;
|
|
uchar *ptt;
|
|
uchar *pzone;
|
|
} z;
|
|
|
|
static uchar *tzdata;
|
|
|
|
static
|
|
uchar*
|
|
readtzfile(char *file)
|
|
{
|
|
uchar *p;
|
|
int fd;
|
|
Dir *d;
|
|
|
|
fd = open(file, OREAD);
|
|
if (fd<0)
|
|
return nil;
|
|
d = dirfstat(fd);
|
|
if (d==nil)
|
|
return nil;
|
|
p = malloc(d->length);
|
|
if (p!=nil)
|
|
readn(fd, p, d->length);
|
|
free(d);
|
|
close(fd);
|
|
return p;
|
|
}
|
|
static char *zonefile;
|
|
void
|
|
tzfile(char *f)
|
|
{
|
|
if (tzdata!=nil) {
|
|
free(tzdata);
|
|
tzdata = nil;
|
|
}
|
|
z.timecnt = 0;
|
|
zonefile = f;
|
|
}
|
|
|
|
static
|
|
long
|
|
get4(uchar *p)
|
|
{
|
|
return (p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
|
|
}
|
|
|
|
enum {
|
|
TTinfosz = 4+1+1,
|
|
};
|
|
|
|
static
|
|
int
|
|
parsehead(void)
|
|
{
|
|
uchar *p;
|
|
int ver;
|
|
|
|
ver = tzdata[4];
|
|
if (ver!=0)
|
|
if (ver!='2')
|
|
return -1;
|
|
|
|
p = tzdata + 4 + 1 + 15;
|
|
|
|
z.timecnt = get4(p+3*4);
|
|
z.typecnt = get4(p+4*4);
|
|
if (z.typecnt==0)
|
|
return -1;
|
|
z.charcnt = get4(p+5*4);
|
|
z.ptime = p+6*4;
|
|
z.ptype = z.ptime + z.timecnt*4;
|
|
z.ptt = z.ptype + z.timecnt;
|
|
z.pzone = z.ptt + z.typecnt*TTinfosz;
|
|
return 0;
|
|
}
|
|
|
|
static
|
|
void
|
|
ttinfo(Tinfo *ti, int tti)
|
|
{
|
|
uchar *p;
|
|
int i;
|
|
|
|
i = z.ptype[tti];
|
|
assert(i<z.typecnt);
|
|
p = z.ptt + i*TTinfosz;
|
|
ti->tzoff = get4(p);
|
|
ti->dlflag = p[4];
|
|
assert(p[5]<z.charcnt);
|
|
ti->zone = (char*)z.pzone + p[5];
|
|
}
|
|
|
|
static
|
|
void
|
|
readtimezone(void)
|
|
{
|
|
char *tmp;
|
|
|
|
z.timecnt = 0;
|
|
if(zonefile==nil) {
|
|
if ((tmp=getenv("timezone"))!=nil) {
|
|
tzdata = readtzfile(tmp);
|
|
free(tmp);
|
|
goto havedata;
|
|
}
|
|
zonefile = "/etc/localtime";
|
|
}
|
|
tzdata = readtzfile(zonefile);
|
|
if (tzdata==nil)
|
|
return;
|
|
|
|
havedata:
|
|
if (strncmp("TZif", (char*)tzdata, 4)!=0)
|
|
goto errfree;
|
|
|
|
if (parsehead()==-1) {
|
|
errfree:
|
|
free(tzdata);
|
|
tzdata = nil;
|
|
z.timecnt = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
static
|
|
tlong
|
|
gett4(uchar *p)
|
|
{
|
|
long l;
|
|
|
|
l = get4(p);
|
|
if (l<0)
|
|
return 0;
|
|
return l;
|
|
}
|
|
int
|
|
zonetinfo(Tinfo *ti, int i)
|
|
{
|
|
if (tzdata==nil)
|
|
readtimezone();
|
|
if (i<0 || i>=z.timecnt)
|
|
return -1;
|
|
ti->t = gett4(z.ptime + 4*i);
|
|
ttinfo(ti, i);
|
|
return i;
|
|
}
|
|
|
|
int
|
|
zonelookuptinfo(Tinfo *ti, tlong t)
|
|
{
|
|
uchar *p;
|
|
int i;
|
|
tlong oldtt, tt;
|
|
|
|
if (tzdata==nil)
|
|
readtimezone();
|
|
oldtt = 0;
|
|
p = z.ptime;
|
|
for (i=0; i<z.timecnt; i++) {
|
|
tt = gett4(p);
|
|
if (t<tt)
|
|
break;
|
|
oldtt = tt;
|
|
p += 4;
|
|
}
|
|
if (i>0) {
|
|
ttinfo(ti, i-1);
|
|
ti->t = oldtt;
|
|
// fprint(2, "t:%ld off:%d dflag:%d %s\n", (long)ti->t, ti->tzoff, ti->dlflag, ti->zone);
|
|
return i-1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void
|
|
zonedump(int fd)
|
|
{
|
|
int i;
|
|
uchar *p;
|
|
tlong t;
|
|
Tinfo ti;
|
|
|
|
if (tzdata==nil)
|
|
readtimezone();
|
|
p = z.ptime;
|
|
for (i=0; i<z.timecnt; i++) {
|
|
t = gett4(p);
|
|
ttinfo(&ti, i);
|
|
fprint(fd, "%ld\t%d\t%d\t%s\n", (long)t, ti.tzoff, ti.dlflag, ti.zone);
|
|
p += 4;
|
|
}
|
|
}
|