Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
 
4
#define	TZSIZE	150
5
static	void	readtimezone(void);
6
static	int	rd_name(char**, char*);
7
static	int	rd_long(char**, long*);
8
static
9
struct
10
{
11
	char	stname[4];
12
	char	dlname[4];
13
	long	stdiff;
14
	long	dldiff;
15
	long	dlpairs[TZSIZE];
16
} timezone;
17
 
18
#define SEC2MIN 60L
19
#define SEC2HOUR (60L*SEC2MIN)
20
#define SEC2DAY (24L*SEC2HOUR)
21
 
22
/*
23
 *  days per month plus days/year
24
 */
25
static	int	dmsize[] =
26
{
27
	365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
28
};
29
static	int	ldmsize[] =
30
{
31
	366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
32
};
33
 
34
/*
35
 *  return the days/month for the given year
36
 */
37
static int *
38
yrsize(int y)
39
{
40
	if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
41
		return ldmsize;
42
	else
43
		return dmsize;
44
}
45
 
46
/*
47
 * compute seconds since Jan 1 1970 GMT
48
 * and convert to our timezone.
49
 */
50
long
51
tm2sec(Tm *tm)
52
{
53
	long secs;
54
	int i, yday, year, *d2m;
55
 
56
	if(strcmp(tm->zone, "GMT") != 0 && timezone.stname[0] == 0)
57
		readtimezone();
58
	secs = 0;
59
 
60
	/*
61
	 *  seconds per year
62
	 */
63
	year = tm->year + 1900;
64
	for(i = 1970; i < year; i++){
65
		d2m = yrsize(i);
66
		secs += d2m[0] * SEC2DAY;
67
	}
68
 
69
	/*
70
	 *  if mday is set, use mon and mday to compute yday
71
	 */
72
	if(tm->mday){
73
		yday = 0;
74
		d2m = yrsize(year);
75
		for(i=0; i<tm->mon; i++)
76
			yday += d2m[i+1];
77
		yday += tm->mday-1;
78
	}else{
79
		yday = tm->yday;
80
	}
81
	secs += yday * SEC2DAY;
82
 
83
	/*
84
	 * hours, minutes, seconds
85
	 */
86
	secs += tm->hour * SEC2HOUR;
87
	secs += tm->min * SEC2MIN;
88
	secs += tm->sec;
89
 
90
	/*
91
	 * Only handles zones mentioned in /env/timezone,
92
	 * but things get too ambiguous otherwise.
93
	 */
94
	if(strcmp(tm->zone, timezone.stname) == 0)
95
		secs -= timezone.stdiff;
96
	else if(strcmp(tm->zone, timezone.dlname) == 0)
97
		secs -= timezone.dldiff;
98
	if(secs < 0)
99
		secs = 0;
100
	return secs;
101
}
102
 
103
static
104
void
105
readtimezone(void)
106
{
107
	char buf[TZSIZE*11+30], *p;
108
	int i;
109
 
110
	memset(buf, 0, sizeof(buf));
111
	i = open("/env/timezone", 0);
112
	if(i < 0)
113
		goto error;
114
	if(read(i, buf, sizeof(buf)) >= sizeof(buf))
115
		goto error;
116
	close(i);
117
	p = buf;
118
	if(rd_name(&p, timezone.stname))
119
		goto error;
120
	if(rd_long(&p, &timezone.stdiff))
121
		goto error;
122
	if(rd_name(&p, timezone.dlname))
123
		goto error;
124
	if(rd_long(&p, &timezone.dldiff))
125
		goto error;
126
	for(i=0; i<TZSIZE; i++) {
127
		if(rd_long(&p, &timezone.dlpairs[i]))
128
			goto error;
129
		if(timezone.dlpairs[i] == 0)
130
			return;
131
	}
132
 
133
error:
134
	timezone.stdiff = 0;
135
	strcpy(timezone.stname, "GMT");
136
	timezone.dlpairs[0] = 0;
137
}
138
 
139
static int
140
rd_name(char **f, char *p)
141
{
142
	int c, i;
143
 
144
	for(;;) {
145
		c = *(*f)++;
146
		if(c != ' ' && c != '\n')
147
			break;
148
	}
149
	for(i=0; i<3; i++) {
150
		if(c == ' ' || c == '\n')
151
			return 1;
152
		*p++ = c;
153
		c = *(*f)++;
154
	}
155
	if(c != ' ' && c != '\n')
156
		return 1;
157
	*p = 0;
158
	return 0;
159
}
160
 
161
static int
162
rd_long(char **f, long *p)
163
{
164
	int c, s;
165
	long l;
166
 
167
	s = 0;
168
	for(;;) {
169
		c = *(*f)++;
170
		if(c == '-') {
171
			s++;
172
			continue;
173
		}
174
		if(c != ' ' && c != '\n')
175
			break;
176
	}
177
	if(c == 0) {
178
		*p = 0;
179
		return 0;
180
	}
181
	l = 0;
182
	for(;;) {
183
		if(c == ' ' || c == '\n')
184
			break;
185
		if(c < '0' || c > '9')
186
			return 1;
187
		l = l*10 + c-'0';
188
		c = *(*f)++;
189
	}
190
	if(s)
191
		l = -l;
192
	*p = l;
193
	return 0;
194
}