Blame


1 64f7506b 2006-02-24 devnull #include <u.h>
2 64f7506b 2006-02-24 devnull #include <libc.h>
3 64f7506b 2006-02-24 devnull #include <bio.h>
4 64f7506b 2006-02-24 devnull #include <flate.h>
5 64f7506b 2006-02-24 devnull #include <auth.h>
6 64f7506b 2006-02-24 devnull #include <fcall.h>
7 64f7506b 2006-02-24 devnull #include <ctype.h>
8 64f7506b 2006-02-24 devnull #include "tapefs.h"
9 64f7506b 2006-02-24 devnull #include "zip.h"
10 64f7506b 2006-02-24 devnull
11 64f7506b 2006-02-24 devnull #define FORCE_LOWER 1 /* force filenames to lower case */
12 64f7506b 2006-02-24 devnull #define MUNGE_CR 1 /* replace '\r\n' with ' \n' */
13 64f7506b 2006-02-24 devnull #define High64 (1LL<<63)
14 64f7506b 2006-02-24 devnull
15 64f7506b 2006-02-24 devnull /*
16 64f7506b 2006-02-24 devnull * File system for zip archives (read-only)
17 64f7506b 2006-02-24 devnull */
18 64f7506b 2006-02-24 devnull
19 64f7506b 2006-02-24 devnull enum {
20 64f7506b 2006-02-24 devnull IS_MSDOS = 0, /* creator OS (interpretation of external flags) */
21 64f7506b 2006-02-24 devnull IS_RDONLY = 1, /* file was readonly (external flags) */
22 cbeb0b26 2006-04-01 devnull IS_TEXT = 1 /* file was text (internal flags) */
23 64f7506b 2006-02-24 devnull };
24 64f7506b 2006-02-24 devnull
25 64f7506b 2006-02-24 devnull typedef struct Block Block;
26 64f7506b 2006-02-24 devnull struct Block{
27 64f7506b 2006-02-24 devnull uchar *pos;
28 64f7506b 2006-02-24 devnull uchar *limit;
29 64f7506b 2006-02-24 devnull };
30 64f7506b 2006-02-24 devnull
31 64f7506b 2006-02-24 devnull static Biobuf *bin;
32 8425b514 2010-02-23 rsc static u32int *crctab;
33 64f7506b 2006-02-24 devnull static ulong crc;
34 64f7506b 2006-02-24 devnull
35 64f7506b 2006-02-24 devnull static int findCDir(Biobuf *);
36 64f7506b 2006-02-24 devnull static int header(Biobuf *, ZipHead *);
37 64f7506b 2006-02-24 devnull static int cheader(Biobuf *, ZipHead *);
38 64f7506b 2006-02-24 devnull /* static void trailer(Biobuf *, ZipHead *); */
39 64f7506b 2006-02-24 devnull static char *getname(Biobuf *, int);
40 64f7506b 2006-02-24 devnull static int blwrite(void *, void *, int);
41 64f7506b 2006-02-24 devnull static ulong get4(Biobuf *);
42 64f7506b 2006-02-24 devnull static int get2(Biobuf *);
43 64f7506b 2006-02-24 devnull static int get1(Biobuf *);
44 64f7506b 2006-02-24 devnull static long msdos2time(int, int);
45 64f7506b 2006-02-24 devnull
46 64f7506b 2006-02-24 devnull void
47 64f7506b 2006-02-24 devnull populate(char *name)
48 64f7506b 2006-02-24 devnull {
49 64f7506b 2006-02-24 devnull char *p;
50 64f7506b 2006-02-24 devnull Fileinf f;
51 64f7506b 2006-02-24 devnull ZipHead zh;
52 64f7506b 2006-02-24 devnull int ok, entries;
53 64f7506b 2006-02-24 devnull
54 64f7506b 2006-02-24 devnull crctab = mkcrctab(ZCrcPoly);
55 64f7506b 2006-02-24 devnull ok = inflateinit();
56 64f7506b 2006-02-24 devnull if(ok != FlateOk)
57 64f7506b 2006-02-24 devnull sysfatal("inflateinit failed: %s", flateerr(ok));
58 64f7506b 2006-02-24 devnull
59 64f7506b 2006-02-24 devnull bin = Bopen(name, OREAD);
60 64f7506b 2006-02-24 devnull if (bin == nil)
61 64f7506b 2006-02-24 devnull error("Can't open argument file");
62 64f7506b 2006-02-24 devnull
63 64f7506b 2006-02-24 devnull entries = findCDir(bin);
64 64f7506b 2006-02-24 devnull if(entries < 0)
65 64f7506b 2006-02-24 devnull sysfatal("empty file");
66 64f7506b 2006-02-24 devnull
67 64f7506b 2006-02-24 devnull while(entries-- > 0){
68 64f7506b 2006-02-24 devnull memset(&zh, 0, sizeof(zh));
69 64f7506b 2006-02-24 devnull if(!cheader(bin, &zh))
70 64f7506b 2006-02-24 devnull break;
71 64f7506b 2006-02-24 devnull f.addr = zh.off;
72 64f7506b 2006-02-24 devnull if(zh.iattr & IS_TEXT)
73 64f7506b 2006-02-24 devnull f.addr |= High64;
74 64f7506b 2006-02-24 devnull f.mode = (zh.madevers == IS_MSDOS && zh.eattr & IS_RDONLY)? 0444: 0644;
75 64f7506b 2006-02-24 devnull if (zh.meth == 0 && zh.uncsize == 0){
76 64f7506b 2006-02-24 devnull p = strchr(zh.file, '\0');
77 64f7506b 2006-02-24 devnull if(p > zh.file && p[-1] == '/')
78 64f7506b 2006-02-24 devnull f.mode |= (DMDIR | 0111);
79 64f7506b 2006-02-24 devnull }
80 64f7506b 2006-02-24 devnull f.uid = 0;
81 64f7506b 2006-02-24 devnull f.gid = 0;
82 64f7506b 2006-02-24 devnull f.size = zh.uncsize;
83 64f7506b 2006-02-24 devnull f.mdate = msdos2time(zh.modtime, zh.moddate);
84 64f7506b 2006-02-24 devnull f.name = zh.file + ((zh.file[0] == '/')? 1: 0);
85 64f7506b 2006-02-24 devnull poppath(f, 1);
86 64f7506b 2006-02-24 devnull free(zh.file);
87 64f7506b 2006-02-24 devnull }
88 64f7506b 2006-02-24 devnull return ;
89 64f7506b 2006-02-24 devnull }
90 64f7506b 2006-02-24 devnull
91 64f7506b 2006-02-24 devnull void
92 64f7506b 2006-02-24 devnull dotrunc(Ram *r)
93 64f7506b 2006-02-24 devnull {
94 64f7506b 2006-02-24 devnull USED(r);
95 64f7506b 2006-02-24 devnull }
96 64f7506b 2006-02-24 devnull
97 64f7506b 2006-02-24 devnull void
98 64f7506b 2006-02-24 devnull docreate(Ram *r)
99 64f7506b 2006-02-24 devnull {
100 64f7506b 2006-02-24 devnull USED(r);
101 64f7506b 2006-02-24 devnull }
102 64f7506b 2006-02-24 devnull
103 64f7506b 2006-02-24 devnull char *
104 64f7506b 2006-02-24 devnull doread(Ram *r, vlong off, long cnt)
105 64f7506b 2006-02-24 devnull {
106 64f7506b 2006-02-24 devnull int i, err;
107 64f7506b 2006-02-24 devnull Block bs;
108 64f7506b 2006-02-24 devnull ZipHead zh;
109 64f7506b 2006-02-24 devnull static Qid oqid;
110 64f7506b 2006-02-24 devnull static char buf[Maxbuf];
111 64f7506b 2006-02-24 devnull static uchar *cache = nil;
112 64f7506b 2006-02-24 devnull
113 64f7506b 2006-02-24 devnull if (cnt > Maxbuf)
114 64f7506b 2006-02-24 devnull sysfatal("file too big (>%d)", Maxbuf);
115 64f7506b 2006-02-24 devnull
116 64f7506b 2006-02-24 devnull if (Bseek(bin, r->addr & 0x7FFFFFFFFFFFFFFFLL, 0) < 0)
117 64f7506b 2006-02-24 devnull sysfatal("seek failed");
118 64f7506b 2006-02-24 devnull
119 64f7506b 2006-02-24 devnull memset(&zh, 0, sizeof(zh));
120 64f7506b 2006-02-24 devnull if (!header(bin, &zh))
121 64f7506b 2006-02-24 devnull sysfatal("cannot get local header");
122 64f7506b 2006-02-24 devnull
123 64f7506b 2006-02-24 devnull switch(zh.meth){
124 64f7506b 2006-02-24 devnull case 0:
125 64f7506b 2006-02-24 devnull if (Bseek(bin, off, 1) < 0)
126 64f7506b 2006-02-24 devnull sysfatal("seek failed");
127 64f7506b 2006-02-24 devnull if (Bread(bin, buf, cnt) != cnt)
128 64f7506b 2006-02-24 devnull sysfatal("read failed");
129 64f7506b 2006-02-24 devnull break;
130 64f7506b 2006-02-24 devnull case 8:
131 64f7506b 2006-02-24 devnull if (r->qid.path != oqid.path){
132 64f7506b 2006-02-24 devnull oqid = r->qid;
133 64f7506b 2006-02-24 devnull if (cache)
134 64f7506b 2006-02-24 devnull free(cache);
135 64f7506b 2006-02-24 devnull cache = emalloc(r->ndata);
136 64f7506b 2006-02-24 devnull
137 64f7506b 2006-02-24 devnull bs.pos = cache;
138 64f7506b 2006-02-24 devnull bs.limit = cache+r->ndata;
139 64f7506b 2006-02-24 devnull if ((err = inflate(&bs, blwrite, bin, (int(*)(void*))Bgetc)) != FlateOk)
140 64f7506b 2006-02-24 devnull sysfatal("inflate failed - %s", flateerr(err));
141 64f7506b 2006-02-24 devnull
142 64f7506b 2006-02-24 devnull if (blockcrc(crctab, crc, cache, r->ndata) != zh.crc)
143 64f7506b 2006-02-24 devnull fprint(2, "%s - crc failed", r->name);
144 64f7506b 2006-02-24 devnull
145 64f7506b 2006-02-24 devnull if ((r->addr & High64) && MUNGE_CR){
146 64f7506b 2006-02-24 devnull for (i = 0; i < r->ndata -1; i++)
147 64f7506b 2006-02-24 devnull if (cache[i] == '\r' && cache[i +1] == '\n')
148 64f7506b 2006-02-24 devnull cache[i] = ' ';
149 64f7506b 2006-02-24 devnull }
150 64f7506b 2006-02-24 devnull }
151 64f7506b 2006-02-24 devnull memcpy(buf, cache+off, cnt);
152 64f7506b 2006-02-24 devnull break;
153 64f7506b 2006-02-24 devnull default:
154 64f7506b 2006-02-24 devnull sysfatal("%d - unsupported compression method", zh.meth);
155 64f7506b 2006-02-24 devnull break;
156 64f7506b 2006-02-24 devnull }
157 fa325e9b 2020-01-10 cross
158 64f7506b 2006-02-24 devnull return buf;
159 64f7506b 2006-02-24 devnull }
160 64f7506b 2006-02-24 devnull
161 64f7506b 2006-02-24 devnull void
162 64f7506b 2006-02-24 devnull popdir(Ram *r)
163 64f7506b 2006-02-24 devnull {
164 64f7506b 2006-02-24 devnull USED(r);
165 64f7506b 2006-02-24 devnull }
166 64f7506b 2006-02-24 devnull
167 64f7506b 2006-02-24 devnull void
168 64f7506b 2006-02-24 devnull dowrite(Ram *r, char *buf, long off, long cnt)
169 64f7506b 2006-02-24 devnull {
170 64f7506b 2006-02-24 devnull USED(r); USED(buf); USED(off); USED(cnt);
171 64f7506b 2006-02-24 devnull }
172 64f7506b 2006-02-24 devnull
173 64f7506b 2006-02-24 devnull int
174 64f7506b 2006-02-24 devnull dopermw(Ram *r)
175 64f7506b 2006-02-24 devnull {
176 64f7506b 2006-02-24 devnull USED(r);
177 64f7506b 2006-02-24 devnull return 0;
178 64f7506b 2006-02-24 devnull }
179 64f7506b 2006-02-24 devnull
180 64f7506b 2006-02-24 devnull /*************************************************/
181 64f7506b 2006-02-24 devnull
182 64f7506b 2006-02-24 devnull static int
183 64f7506b 2006-02-24 devnull findCDir(Biobuf *bin)
184 64f7506b 2006-02-24 devnull {
185 64f7506b 2006-02-24 devnull vlong ecoff;
186 64f7506b 2006-02-24 devnull long off;
187 64f7506b 2006-02-24 devnull int entries, zclen;
188 64f7506b 2006-02-24 devnull
189 64f7506b 2006-02-24 devnull ecoff = Bseek(bin, -ZECHeadSize, 2);
190 64f7506b 2006-02-24 devnull if(ecoff < 0)
191 64f7506b 2006-02-24 devnull sysfatal("can't seek to header");
192 64f7506b 2006-02-24 devnull
193 64f7506b 2006-02-24 devnull if(get4(bin) != ZECHeader)
194 64f7506b 2006-02-24 devnull sysfatal("bad magic number on directory");
195 64f7506b 2006-02-24 devnull
196 64f7506b 2006-02-24 devnull get2(bin);
197 64f7506b 2006-02-24 devnull get2(bin);
198 64f7506b 2006-02-24 devnull get2(bin);
199 64f7506b 2006-02-24 devnull entries = get2(bin);
200 64f7506b 2006-02-24 devnull get4(bin);
201 64f7506b 2006-02-24 devnull off = get4(bin);
202 64f7506b 2006-02-24 devnull zclen = get2(bin);
203 64f7506b 2006-02-24 devnull while(zclen-- > 0)
204 64f7506b 2006-02-24 devnull get1(bin);
205 64f7506b 2006-02-24 devnull
206 64f7506b 2006-02-24 devnull if(Bseek(bin, off, 0) != off)
207 64f7506b 2006-02-24 devnull sysfatal("can't seek to contents");
208 64f7506b 2006-02-24 devnull
209 64f7506b 2006-02-24 devnull return entries;
210 64f7506b 2006-02-24 devnull }
211 64f7506b 2006-02-24 devnull
212 64f7506b 2006-02-24 devnull
213 64f7506b 2006-02-24 devnull static int
214 64f7506b 2006-02-24 devnull header(Biobuf *bin, ZipHead *zh)
215 64f7506b 2006-02-24 devnull {
216 64f7506b 2006-02-24 devnull ulong v;
217 64f7506b 2006-02-24 devnull int flen, xlen;
218 64f7506b 2006-02-24 devnull
219 64f7506b 2006-02-24 devnull v = get4(bin);
220 64f7506b 2006-02-24 devnull if(v != ZHeader){
221 64f7506b 2006-02-24 devnull if(v == ZCHeader)
222 64f7506b 2006-02-24 devnull return 0;
223 64f7506b 2006-02-24 devnull sysfatal("bad magic on local header");
224 64f7506b 2006-02-24 devnull }
225 64f7506b 2006-02-24 devnull zh->extvers = get1(bin);
226 64f7506b 2006-02-24 devnull zh->extos = get1(bin);
227 64f7506b 2006-02-24 devnull zh->flags = get2(bin);
228 64f7506b 2006-02-24 devnull zh->meth = get2(bin);
229 64f7506b 2006-02-24 devnull zh->modtime = get2(bin);
230 64f7506b 2006-02-24 devnull zh->moddate = get2(bin);
231 64f7506b 2006-02-24 devnull zh->crc = get4(bin);
232 64f7506b 2006-02-24 devnull zh->csize = get4(bin);
233 64f7506b 2006-02-24 devnull zh->uncsize = get4(bin);
234 64f7506b 2006-02-24 devnull flen = get2(bin);
235 64f7506b 2006-02-24 devnull xlen = get2(bin);
236 64f7506b 2006-02-24 devnull
237 64f7506b 2006-02-24 devnull zh->file = getname(bin, flen);
238 64f7506b 2006-02-24 devnull
239 64f7506b 2006-02-24 devnull while(xlen-- > 0)
240 64f7506b 2006-02-24 devnull get1(bin);
241 64f7506b 2006-02-24 devnull return 1;
242 64f7506b 2006-02-24 devnull }
243 64f7506b 2006-02-24 devnull
244 64f7506b 2006-02-24 devnull static int
245 64f7506b 2006-02-24 devnull cheader(Biobuf *bin, ZipHead *zh)
246 64f7506b 2006-02-24 devnull {
247 64f7506b 2006-02-24 devnull ulong v;
248 64f7506b 2006-02-24 devnull int flen, xlen, fclen;
249 64f7506b 2006-02-24 devnull
250 64f7506b 2006-02-24 devnull v = get4(bin);
251 64f7506b 2006-02-24 devnull if(v != ZCHeader){
252 64f7506b 2006-02-24 devnull if(v == ZECHeader)
253 64f7506b 2006-02-24 devnull return 0;
254 64f7506b 2006-02-24 devnull sysfatal("bad magic number in file");
255 64f7506b 2006-02-24 devnull }
256 64f7506b 2006-02-24 devnull zh->madevers = get1(bin);
257 64f7506b 2006-02-24 devnull zh->madeos = get1(bin);
258 64f7506b 2006-02-24 devnull zh->extvers = get1(bin);
259 64f7506b 2006-02-24 devnull zh->extos = get1(bin);
260 64f7506b 2006-02-24 devnull zh->flags = get2(bin);
261 64f7506b 2006-02-24 devnull zh->meth = get2(bin);
262 64f7506b 2006-02-24 devnull zh->modtime = get2(bin);
263 64f7506b 2006-02-24 devnull zh->moddate = get2(bin);
264 64f7506b 2006-02-24 devnull zh->crc = get4(bin);
265 64f7506b 2006-02-24 devnull zh->csize = get4(bin);
266 64f7506b 2006-02-24 devnull zh->uncsize = get4(bin);
267 64f7506b 2006-02-24 devnull flen = get2(bin);
268 64f7506b 2006-02-24 devnull xlen = get2(bin);
269 64f7506b 2006-02-24 devnull fclen = get2(bin);
270 64f7506b 2006-02-24 devnull get2(bin); /* disk number start */
271 64f7506b 2006-02-24 devnull zh->iattr = get2(bin); /* 1 == is-text-file */
272 64f7506b 2006-02-24 devnull zh->eattr = get4(bin); /* 1 == readonly-file */
273 64f7506b 2006-02-24 devnull zh->off = get4(bin);
274 64f7506b 2006-02-24 devnull
275 64f7506b 2006-02-24 devnull zh->file = getname(bin, flen);
276 64f7506b 2006-02-24 devnull
277 64f7506b 2006-02-24 devnull while(xlen-- > 0)
278 64f7506b 2006-02-24 devnull get1(bin);
279 64f7506b 2006-02-24 devnull
280 64f7506b 2006-02-24 devnull while(fclen-- > 0)
281 64f7506b 2006-02-24 devnull get1(bin);
282 64f7506b 2006-02-24 devnull
283 64f7506b 2006-02-24 devnull return 1;
284 64f7506b 2006-02-24 devnull }
285 64f7506b 2006-02-24 devnull
286 64f7506b 2006-02-24 devnull static int
287 64f7506b 2006-02-24 devnull blwrite(void *vb, void *buf, int n)
288 64f7506b 2006-02-24 devnull {
289 64f7506b 2006-02-24 devnull Block *b = vb;
290 64f7506b 2006-02-24 devnull if(n > b->limit - b->pos)
291 64f7506b 2006-02-24 devnull n = b->limit - b->pos;
292 64f7506b 2006-02-24 devnull memmove(b->pos, buf, n);
293 64f7506b 2006-02-24 devnull b->pos += n;
294 64f7506b 2006-02-24 devnull return n;
295 64f7506b 2006-02-24 devnull }
296 64f7506b 2006-02-24 devnull
297 64f7506b 2006-02-24 devnull /*
298 64f7506b 2006-02-24 devnull static void
299 64f7506b 2006-02-24 devnull trailer(Biobuf *bin, ZipHead *zh)
300 64f7506b 2006-02-24 devnull {
301 64f7506b 2006-02-24 devnull if(zh->flags & ZTrailInfo){
302 64f7506b 2006-02-24 devnull zh->crc = get4(bin);
303 64f7506b 2006-02-24 devnull zh->csize = get4(bin);
304 64f7506b 2006-02-24 devnull zh->uncsize = get4(bin);
305 64f7506b 2006-02-24 devnull }
306 64f7506b 2006-02-24 devnull }
307 64f7506b 2006-02-24 devnull */
308 64f7506b 2006-02-24 devnull
309 64f7506b 2006-02-24 devnull static char*
310 64f7506b 2006-02-24 devnull getname(Biobuf *bin, int len)
311 64f7506b 2006-02-24 devnull {
312 64f7506b 2006-02-24 devnull char *s;
313 64f7506b 2006-02-24 devnull int i, c;
314 64f7506b 2006-02-24 devnull
315 64f7506b 2006-02-24 devnull s = emalloc(len + 1);
316 64f7506b 2006-02-24 devnull for(i = 0; i < len; i++){
317 64f7506b 2006-02-24 devnull c = get1(bin);
318 64f7506b 2006-02-24 devnull if(FORCE_LOWER)
319 64f7506b 2006-02-24 devnull c = tolower(c);
320 64f7506b 2006-02-24 devnull s[i] = c;
321 64f7506b 2006-02-24 devnull }
322 64f7506b 2006-02-24 devnull s[i] = '\0';
323 64f7506b 2006-02-24 devnull return s;
324 64f7506b 2006-02-24 devnull }
325 64f7506b 2006-02-24 devnull
326 64f7506b 2006-02-24 devnull
327 64f7506b 2006-02-24 devnull static ulong
328 64f7506b 2006-02-24 devnull get4(Biobuf *b)
329 64f7506b 2006-02-24 devnull {
330 64f7506b 2006-02-24 devnull ulong v;
331 64f7506b 2006-02-24 devnull int i, c;
332 64f7506b 2006-02-24 devnull
333 64f7506b 2006-02-24 devnull v = 0;
334 64f7506b 2006-02-24 devnull for(i = 0; i < 4; i++){
335 64f7506b 2006-02-24 devnull c = Bgetc(b);
336 64f7506b 2006-02-24 devnull if(c < 0)
337 64f7506b 2006-02-24 devnull sysfatal("unexpected eof");
338 64f7506b 2006-02-24 devnull v |= c << (i * 8);
339 64f7506b 2006-02-24 devnull }
340 64f7506b 2006-02-24 devnull return v;
341 64f7506b 2006-02-24 devnull }
342 64f7506b 2006-02-24 devnull
343 64f7506b 2006-02-24 devnull static int
344 64f7506b 2006-02-24 devnull get2(Biobuf *b)
345 64f7506b 2006-02-24 devnull {
346 64f7506b 2006-02-24 devnull int i, c, v;
347 64f7506b 2006-02-24 devnull
348 64f7506b 2006-02-24 devnull v = 0;
349 64f7506b 2006-02-24 devnull for(i = 0; i < 2; i++){
350 64f7506b 2006-02-24 devnull c = Bgetc(b);
351 64f7506b 2006-02-24 devnull if(c < 0)
352 64f7506b 2006-02-24 devnull sysfatal("unexpected eof");
353 64f7506b 2006-02-24 devnull v |= c << (i * 8);
354 64f7506b 2006-02-24 devnull }
355 64f7506b 2006-02-24 devnull return v;
356 64f7506b 2006-02-24 devnull }
357 64f7506b 2006-02-24 devnull
358 64f7506b 2006-02-24 devnull static int
359 64f7506b 2006-02-24 devnull get1(Biobuf *b)
360 64f7506b 2006-02-24 devnull {
361 64f7506b 2006-02-24 devnull int c;
362 64f7506b 2006-02-24 devnull
363 64f7506b 2006-02-24 devnull c = Bgetc(b);
364 64f7506b 2006-02-24 devnull if(c < 0)
365 64f7506b 2006-02-24 devnull sysfatal("unexpected eof");
366 64f7506b 2006-02-24 devnull return c;
367 64f7506b 2006-02-24 devnull }
368 64f7506b 2006-02-24 devnull
369 64f7506b 2006-02-24 devnull static long
370 64f7506b 2006-02-24 devnull msdos2time(int time, int date)
371 64f7506b 2006-02-24 devnull {
372 64f7506b 2006-02-24 devnull Tm tm;
373 64f7506b 2006-02-24 devnull
374 64f7506b 2006-02-24 devnull tm.hour = time >> 11;
375 64f7506b 2006-02-24 devnull tm.min = (time >> 5) & 63;
376 64f7506b 2006-02-24 devnull tm.sec = (time & 31) << 1;
377 64f7506b 2006-02-24 devnull tm.year = 80 + (date >> 9);
378 64f7506b 2006-02-24 devnull tm.mon = ((date >> 5) & 15) - 1;
379 64f7506b 2006-02-24 devnull tm.mday = date & 31;
380 64f7506b 2006-02-24 devnull tm.zone[0] = '\0';
381 64f7506b 2006-02-24 devnull tm.yday = 0;
382 64f7506b 2006-02-24 devnull
383 64f7506b 2006-02-24 devnull return tm2sec(&tm);
384 64f7506b 2006-02-24 devnull }