Merge to Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0...
[linux-2.6.git] / net / tux / times.c
1 /*
2  * TUX - Integrated Application Protocols Layer and Object Cache
3  *
4  * Copyright (C) 2000, 2001, Ingo Molnar <mingo@redhat.com>
5  *
6  * times.c: time conversion routines.
7  *
8  * Original time convserion code Copyright (C) 1999 by Arjan van de Ven
9  */
10
11 /****************************************************************
12  *      This program is free software; you can redistribute it and/or modify
13  *      it under the terms of the GNU General Public License as published by
14  *      the Free Software Foundation; either version 2, or (at your option)
15  *      any later version.
16  *
17  *      This program is distributed in the hope that it will be useful,
18  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *      GNU General Public License for more details.
21  *
22  *      You should have received a copy of the GNU General Public License
23  *      along with this program; if not, write to the Free Software
24  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  *
26  ****************************************************************/
27
28 #include <linux/time.h>
29 #include <linux/kernel.h>
30 #include <linux/slab.h>
31 #include <linux/ctype.h>
32
33
34 #include "times.h"
35
36 char *dayName[7] = {
37         "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
38 };
39
40 static char *monthName[12] = {
41         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
42         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
43 };
44
45 char itoa_h[60]={'0','0','0','0','0','0','0','0','0','0',
46                  '1','1','1','1','1','1','1','1','1','1',
47                  '2','2','2','2','2','2','2','2','2','2',
48                  '3','3','3','3','3','3','3','3','3','3',
49                  '4','4','4','4','4','4','4','4','4','4',
50                  '5','5','5','5','5','5','5','5','5','5'};
51
52 char itoa_l[60]={'0','1','2','3','4','5','6','7','8','9',
53                  '0','1','2','3','4','5','6','7','8','9',
54                  '0','1','2','3','4','5','6','7','8','9',
55                  '0','1','2','3','4','5','6','7','8','9',
56                  '0','1','2','3','4','5','6','7','8','9',
57                  '0','1','2','3','4','5','6','7','8','9'};
58
59 int time_unix2ls(time_t zulu, char *buf)
60 {
61         int Y=0,M=0,D=0;
62         int H=0,Min=0,S=0,WD=0;
63         int I,I2;
64         time_t rest, delta;
65
66         if (zulu > xtime.tv_sec)
67                 zulu = xtime.tv_sec;
68
69         I=0;
70         while (I<TUX_NUMYEARS) {
71                 if (TimeDays[I][0]>zulu)
72                    break;
73                 I++;
74         }
75
76         Y=--I;
77         if (I<0) {
78                 Y=0;
79                 goto BuildYear;
80         }
81         I2=0;
82         while (I2<=12) {
83                 if (TimeDays[I][I2]>zulu)
84                    break;
85                 I2++;
86         }
87
88         M=I2-1;
89
90         rest=zulu - TimeDays[Y][M];
91         WD=WeekDays[Y][M];
92         D=rest/86400;
93         rest=rest%86400;
94         WD+=D;
95         WD=WD%7;
96         H=rest/3600;
97         rest=rest%3600;
98         Min=rest/60;
99         rest=rest%60;
100         S=rest;
101
102 BuildYear:
103         Y+=TUX_YEAROFFSET;
104
105
106         /* Format:  Day, 01 Mon 1999 01:01:01 GMT */
107
108         delta = xtime.tv_sec - zulu;
109         if (delta > 6*30*24*60)
110                 //               "May 23   2000"
111                 return sprintf( buf, "%s %02i  %04i", monthName[M], D+1, Y);
112         else
113                 //                "May 23 10:14"
114                 return sprintf( buf, "%s %02i %02i:%02i",
115                         monthName[M], D+1, H, Min);
116 }
117
118 static int MonthHash[32] =
119         {0,0,7,0,0,0,0,0,0,0,0,3,0,0,0,2,6,0,5,0,9,8,4,0,0,11,1,10,0,0,0,0};
120
121 #define is_digit(c)     ((c) >= '0' && (c) <= '9')
122
123 static inline int skip_atoi(char **s)
124 {
125         int i=0;
126
127         while (is_digit(**s))
128                 i = i*10 + *((*s)++) - '0';
129         return i;
130 }
131
132 time_t mimetime_to_unixtime(char *Q)
133 {
134         int Y,M,D,H,Min,S;
135         unsigned int Hash;
136         time_t Temp;
137         char *s,**s2;
138
139         s=Q;
140         s2=&s;
141
142         if (strlen(s)<30) return 0;
143         if (s[3]!=',') return 0;
144         if (s[19]!=':') return 0;
145
146         s+=5; /* Skip day of week */
147         D = skip_atoi(s2);  /*  Day of month */
148         s++;
149         Hash = (char)s[0]+(char)s[2];
150         Hash = (Hash<<1) + (char)s[1];
151         Hash = (Hash&63)>>1;
152         M = MonthHash[Hash];
153         s+=4;
154         Y = skip_atoi(s2); /* Year */
155         s++;
156         H = skip_atoi(s2); /* Hour */
157         s++;
158         Min = skip_atoi(s2); /* Minutes */
159         s++;
160         S = skip_atoi(s2); /* Seconds */
161         s++;
162         if ((s[0]!='G')||(s[1]!='M')||(s[2]!='T'))
163         {
164                 return 0; /* No GMT */
165         }
166
167         if (Y<TUX_YEAROFFSET) Y = TUX_YEAROFFSET;
168         if (Y>TUX_YEAROFFSET+9) Y = TUX_YEAROFFSET+9;
169
170         Temp = TimeDays[Y-TUX_YEAROFFSET][M];
171         Temp += D*86400+H*3600+Min*60+S;
172
173         return Temp;
174 }
175
176 // writes the full http date, corresponding to time_t received
177
178 void last_mod_time(char * curr, const time_t t)
179 {
180         int day, tod, year, wday, mon, hour, min, sec;
181
182         tod = t % 86400;
183         day = t / 86400;
184         if (tod < 0) {
185                 tod += 86400;
186                 --day;
187         }
188
189         hour = tod / 3600;
190         tod %= 3600;
191         min = tod / 60;
192         sec = tod % 60;
193
194         wday = (day + 4) % 7;
195         if (wday < 0)
196                 wday += 7;
197
198         day -= 11017;
199         /* day 0 is march 1, 2000 */
200         year = 5 + day / 146097;
201         day = day % 146097;
202         if (day < 0) {
203                 day += 146097;
204                 --year;
205         }
206         /* from now on, day is nonnegative */
207         year *= 4;
208         if (day == 146096) {
209                 year += 3;
210                 day = 36524;
211         } else {
212                 year += day / 36524;
213                 day %= 36524;
214         }
215         year *= 25;
216         year += day / 1461;
217         day %= 1461;
218         year *= 4;
219         if (day == 1460) {
220                 year += 3;
221                 day = 365;
222         } else {
223                 year += day / 365;
224                 day %= 365;
225         }
226
227         day *= 10;
228         mon = (day + 5) / 306;
229         day = day + 5 - 306 * mon;
230         day /= 10;
231         if (mon >= 10) {
232                 ++year;
233                 mon -= 10;
234         } else
235                 mon += 2;
236
237         sprintf(curr, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", dayName[wday],
238                 day+1, monthName[mon], year, hour, min, sec);
239 }
240
241 // writes the full date in ISO8601 format,
242 // corresponding to time_t received
243 // example: 20011126224910
244
245 int mdtm_time(char * curr, const time_t t)
246 {
247         int day, tod, year, wday, mon, hour, min, sec;
248
249         tod = t % 86400;
250         day = t / 86400;
251         if (tod < 0) {
252                 tod += 86400;
253                 --day;
254         }
255
256         hour = tod / 3600;
257         tod %= 3600;
258         min = tod / 60;
259         sec = tod % 60;
260
261         wday = (day + 4) % 7;
262         if (wday < 0)
263                 wday += 7;
264
265         day -= 11017;
266         /* day 0 is march 1, 2000 */
267         year = 5 + day / 146097;
268         day = day % 146097;
269         if (day < 0) {
270                 day += 146097;
271                 --year;
272         }
273         /* from now on, day is nonnegative */
274         year *= 4;
275         if (day == 146096) {
276                 year += 3;
277                 day = 36524;
278         } else {
279                 year += day / 36524;
280                 day %= 36524;
281         }
282         year *= 25;
283         year += day / 1461;
284         day %= 1461;
285         year *= 4;
286         if (day == 1460) {
287                 year += 3;
288                 day = 365;
289         } else {
290                 year += day / 365;
291                 day %= 365;
292         }
293
294         day *= 10;
295         mon = (day + 5) / 306;
296         day = day + 5 - 306 * mon;
297         day /= 10;
298         if (mon >= 10) {
299                 ++year;
300                 mon -= 10;
301         } else
302                 mon += 2;
303
304         return sprintf(curr, "213 %.4d%.2d%.2d%.2d%.2d%.2d\r\n",
305                 year, mon+1, day+1, hour, min, sec);
306 }
307
308 static inline int make_num(const char *s)
309 {
310         if (*s >= '0' && *s <= '9')
311                 return 10 * (*s - '0') + *(s + 1) - '0';
312         else
313                 return *(s + 1) - '0';
314 }
315
316 static inline int make_month(const char *s)
317 {
318         int i;
319
320         for (i = 0; i < 12; i++)
321                 if (!strncmp(monthName[i], s, 3))
322                         return i+1;
323         return 0;
324 }
325
326 time_t parse_time(const char *str, const int str_len)
327 {
328         int hour;
329         int min;
330         int sec;
331         int mday;
332         int mon;
333         int year;
334
335         if (str[3] == ',') {
336                 /* Thu, 09 Jan 1993 01:29:59 GMT */
337
338                 if (str_len < 29)
339                         return -1;
340
341                 mday = make_num(str+5);
342                 mon = make_month(str + 8);
343                 year = 100 * make_num(str + 12) + make_num(str + 14);
344                 hour = make_num(str + 17);
345                 min = make_num(str + 20);
346                 sec = make_num(str + 23);
347         }
348         else {
349                 const char *s;
350                 s = strchr(str, ',');
351                 if (!s || (str_len - (s - str) < 24)) {
352                         /* Wed Jun  9 01:29:59 1993 */
353
354                         if (str_len < 24)
355                                 return -1;
356
357                         mon = make_month(str+4);
358                         mday = make_num(str+8);
359                         hour = make_num(str+11);
360                         min = make_num(str+14);
361                         sec = make_num(str+17);
362                         year = make_num(str+20)*100 + make_num(str+22);
363                 }
364                 else {
365                         /* Thursday, 10-Jun-93 01:29:59 GMT */
366
367                         mday = make_num(s + 2);
368                         mon = make_month(s + 5);
369                         year = make_num(s + 9) + 1900;
370                         if (year < 1970)
371                                 year += 100;
372                         hour = make_num(s + 12);
373                         min = make_num(s + 15);
374                         sec = make_num(s + 18);
375                 }
376         }
377
378         if (sec < 0 || sec > 59)
379                 return -1;
380         if (min < 0 || min > 59)
381                 return -1;
382         if (hour < 0 || hour > 23)
383                 return -1;
384         if (mday < 1 || mday > 31)
385                 return -1;
386         if (mon < 1 || mon > 12)
387                 return -1;
388         if (year < 1970 || year > 2020)
389                 return -1;
390
391         return mktime(year, mon, mday, hour, min, sec);
392 }