1 /*
2 zip_dirent.c -- read directory entry (local or central), clean dirent
3 Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
4
5 This file is part of libzip, a library to manipulate ZIP archives.
6 The authors can be contacted at <libzip@nih.at>
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in
15 the documentation and/or other materials provided with the
16 distribution.
17 3. The names of the authors may not be used to endorse or promote
18 products derived from this software without specific prior
19 written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <errno.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42
43 #include "zipint.h"
44
45 static time_t _zip_d2u_time(int, int);
46 static char *_zip_readfpstr(FILE *, unsigned int, int, struct zip_error *);
47 static char *_zip_readstr(unsigned char **, int, int, struct zip_error *);
48 static void _zip_write2(unsigned short, FILE *);
49 static void _zip_write4(unsigned int, FILE *);
50
51
52
53 void
_zip_cdir_free(struct zip_cdir * cd)54 _zip_cdir_free(struct zip_cdir *cd)
55 {
56 int i;
57
58 if (!cd)
59 return;
60
61 for (i=0; i<cd->nentry; i++)
62 _zip_dirent_finalize(cd->entry+i);
63 free(cd->comment);
64 free(cd->entry);
65 free(cd);
66 }
67
68
69
70 int
_zip_cdir_grow(struct zip_cdir * cd,int nentry,struct zip_error * error)71 _zip_cdir_grow(struct zip_cdir *cd, int nentry, struct zip_error *error)
72 {
73 struct zip_dirent *entry;
74
75 if (nentry < cd->nentry) {
76 _zip_error_set(error, ZIP_ER_INTERNAL, 0);
77 return -1;
78 }
79
80 if ((entry=((struct zip_dirent *)
81 realloc(cd->entry, sizeof(*(cd->entry))*nentry))) == NULL) {
82 _zip_error_set(error, ZIP_ER_MEMORY, 0);
83 return -1;
84 }
85
86 cd->nentry = nentry;
87 cd->entry = entry;
88
89 return 0;
90 }
91
92
93
94 struct zip_cdir *
_zip_cdir_new(int nentry,struct zip_error * error)95 _zip_cdir_new(int nentry, struct zip_error *error)
96 {
97 struct zip_cdir *cd;
98
99 if ((cd=(struct zip_cdir *)malloc(sizeof(*cd))) == NULL) {
100 _zip_error_set(error, ZIP_ER_MEMORY, 0);
101 return NULL;
102 }
103
104 if ( nentry > ((size_t)-1)/sizeof(*(cd->entry)) || (cd->entry=(struct zip_dirent *)malloc(sizeof(*(cd->entry))*(size_t)nentry))
105 == NULL) {
106 _zip_error_set(error, ZIP_ER_MEMORY, 0);
107 free(cd);
108 return NULL;
109 }
110
111 /* entries must be initialized by caller */
112
113 cd->nentry = nentry;
114 cd->size = cd->offset = 0;
115 cd->comment = NULL;
116 cd->comment_len = 0;
117
118 return cd;
119 }
120
121
122
123 int
_zip_cdir_write(struct zip_cdir * cd,FILE * fp,struct zip_error * error)124 _zip_cdir_write(struct zip_cdir *cd, FILE *fp, struct zip_error *error)
125 {
126 int i;
127
128 cd->offset = ftello(fp);
129
130 for (i=0; i<cd->nentry; i++) {
131 if (_zip_dirent_write(cd->entry+i, fp, 0, error) != 0)
132 return -1;
133 }
134
135 cd->size = ftello(fp) - cd->offset;
136
137 /* clearerr(fp); */
138 fwrite(EOCD_MAGIC, 1, 4, fp);
139 _zip_write4(0, fp);
140 _zip_write2((unsigned short)cd->nentry, fp);
141 _zip_write2((unsigned short)cd->nentry, fp);
142 _zip_write4(cd->size, fp);
143 _zip_write4(cd->offset, fp);
144 _zip_write2(cd->comment_len, fp);
145 fwrite(cd->comment, 1, cd->comment_len, fp);
146
147 if (ferror(fp)) {
148 _zip_error_set(error, ZIP_ER_WRITE, errno);
149 return -1;
150 }
151
152 return 0;
153 }
154
155
156
157 void
_zip_dirent_finalize(struct zip_dirent * zde)158 _zip_dirent_finalize(struct zip_dirent *zde)
159 {
160 if (zde->filename_len > 0) {
161 free(zde->filename);
162 }
163 zde->filename = NULL;
164 if (zde->extrafield_len > 0) {
165 free(zde->extrafield);
166 }
167 zde->extrafield = NULL;
168 if (zde->comment_len > 0) {
169 free(zde->comment);
170 }
171 zde->comment = NULL;
172 }
173
174
175
176 void
_zip_dirent_init(struct zip_dirent * de)177 _zip_dirent_init(struct zip_dirent *de)
178 {
179 de->version_madeby = 0;
180 de->version_needed = 20; /* 2.0 */
181 de->bitflags = 0;
182 de->comp_method = 0;
183 de->last_mod = 0;
184 de->crc = 0;
185 de->comp_size = 0;
186 de->uncomp_size = 0;
187 de->filename = NULL;
188 de->filename_len = 0;
189 de->extrafield = NULL;
190 de->extrafield_len = 0;
191 de->comment = NULL;
192 de->comment_len = 0;
193 de->disk_number = 0;
194 de->int_attrib = 0;
195 de->ext_attrib = 0;
196 de->offset = 0;
197 }
198
199
200
201 /* _zip_dirent_read(zde, fp, bufp, left, localp, error):
202 Fills the zip directory entry zde.
203
204 If bufp is non-NULL, data is taken from there and bufp is advanced
205 by the amount of data used; otherwise data is read from fp as needed.
206
207 if leftp is non-NULL, no more bytes than specified by it are used,
208 and *leftp is reduced by the number of bytes used.
209
210 If local != 0, it reads a local header instead of a central
211 directory entry.
212
213 Returns 0 if successful. On error, error is filled in and -1 is
214 returned.
215
216 XXX: leftp and file position undefined on error.
217 */
218
219 int
_zip_dirent_read(struct zip_dirent * zde,FILE * fp,unsigned char ** bufp,zip_uint32_t * leftp,int local,struct zip_error * error)220 _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
221 unsigned char **bufp, zip_uint32_t *leftp, int local,
222 struct zip_error *error)
223 {
224 unsigned char buf[CDENTRYSIZE];
225 unsigned char *cur;
226 unsigned short dostime, dosdate;
227 zip_uint32_t size;
228
229 if (local)
230 size = LENTRYSIZE;
231 else
232 size = CDENTRYSIZE;
233
234 if (leftp && (*leftp < size)) {
235 _zip_error_set(error, ZIP_ER_NOZIP, 0);
236 return -1;
237 }
238
239 if (bufp) {
240 /* use data from buffer */
241 cur = *bufp;
242 }
243 else {
244 /* read entry from disk */
245 if ((fread(buf, 1, size, fp)<size)) {
246 _zip_error_set(error, ZIP_ER_READ, errno);
247 return -1;
248 }
249 cur = buf;
250 }
251
252 if (memcmp(cur, (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
253 _zip_error_set(error, ZIP_ER_NOZIP, 0);
254 return -1;
255 }
256 cur += 4;
257
258
259 /* convert buffercontents to zip_dirent */
260
261 if (!local)
262 zde->version_madeby = _zip_read2(&cur);
263 else
264 zde->version_madeby = 0;
265 zde->version_needed = _zip_read2(&cur);
266 zde->bitflags = _zip_read2(&cur);
267 zde->comp_method = _zip_read2(&cur);
268
269 /* convert to time_t */
270 dostime = _zip_read2(&cur);
271 dosdate = _zip_read2(&cur);
272 zde->last_mod = _zip_d2u_time(dostime, dosdate);
273
274 zde->crc = _zip_read4(&cur);
275 zde->comp_size = _zip_read4(&cur);
276 zde->uncomp_size = _zip_read4(&cur);
277
278 zde->filename_len = _zip_read2(&cur);
279 zde->extrafield_len = _zip_read2(&cur);
280
281 if (local) {
282 zde->comment_len = 0;
283 zde->disk_number = 0;
284 zde->int_attrib = 0;
285 zde->ext_attrib = 0;
286 zde->offset = 0;
287 } else {
288 zde->comment_len = _zip_read2(&cur);
289 zde->disk_number = _zip_read2(&cur);
290 zde->int_attrib = _zip_read2(&cur);
291 zde->ext_attrib = _zip_read4(&cur);
292 zde->offset = _zip_read4(&cur);
293 }
294
295 zde->filename = NULL;
296 zde->extrafield = NULL;
297 zde->comment = NULL;
298
299 size += zde->filename_len+zde->extrafield_len+zde->comment_len;
300
301 if (leftp && (*leftp < size)) {
302 _zip_error_set(error, ZIP_ER_NOZIP, 0);
303 return -1;
304 }
305
306 if (bufp) {
307 if (zde->filename_len) {
308 zde->filename = _zip_readstr(&cur, zde->filename_len, 1, error);
309 if (!zde->filename)
310 return -1;
311 }
312
313 if (zde->extrafield_len) {
314 zde->extrafield = _zip_readstr(&cur, zde->extrafield_len, 0,
315 error);
316 if (!zde->extrafield)
317 return -1;
318 }
319
320 if (zde->comment_len) {
321 zde->comment = _zip_readstr(&cur, zde->comment_len, 0, error);
322 if (!zde->comment)
323 return -1;
324 }
325 }
326 else {
327 if (zde->filename_len) {
328 zde->filename = _zip_readfpstr(fp, zde->filename_len, 1, error);
329 if (!zde->filename)
330 return -1;
331 }
332
333 if (zde->extrafield_len) {
334 zde->extrafield = _zip_readfpstr(fp, zde->extrafield_len, 0,
335 error);
336 if (!zde->extrafield)
337 return -1;
338 }
339
340 if (zde->comment_len) {
341 zde->comment = _zip_readfpstr(fp, zde->comment_len, 0, error);
342 if (!zde->comment)
343 return -1;
344 }
345 }
346
347 if (bufp)
348 *bufp = cur;
349 if (leftp)
350 *leftp -= size;
351
352 return 0;
353 }
354
355
356
357 /* _zip_dirent_torrent_normalize(de);
358 Set values suitable for torrentzip.
359 */
360
361 void
_zip_dirent_torrent_normalize(struct zip_dirent * de)362 _zip_dirent_torrent_normalize(struct zip_dirent *de)
363 {
364 static struct tm torrenttime;
365 static time_t last_mod = 0;
366
367 if (last_mod == 0) {
368 #ifdef HAVE_STRUCT_TM_TM_ZONE
369 time_t now;
370 struct tm *l;
371 #endif
372
373 torrenttime.tm_sec = 0;
374 torrenttime.tm_min = 32;
375 torrenttime.tm_hour = 23;
376 torrenttime.tm_mday = 24;
377 torrenttime.tm_mon = 11;
378 torrenttime.tm_year = 96;
379 torrenttime.tm_wday = 0;
380 torrenttime.tm_yday = 0;
381 torrenttime.tm_isdst = 0;
382
383 #ifdef HAVE_STRUCT_TM_TM_ZONE
384 time(&now);
385 l = localtime(&now);
386 torrenttime.tm_gmtoff = l->tm_gmtoff;
387 torrenttime.tm_zone = l->tm_zone;
388 #endif
389
390 last_mod = mktime(&torrenttime);
391 }
392
393 de->version_madeby = 0;
394 de->version_needed = 20; /* 2.0 */
395 de->bitflags = 2; /* maximum compression */
396 de->comp_method = ZIP_CM_DEFLATE;
397 de->last_mod = last_mod;
398
399 de->disk_number = 0;
400 de->int_attrib = 0;
401 de->ext_attrib = 0;
402 de->offset = 0;
403
404 free(de->extrafield);
405 de->extrafield = NULL;
406 de->extrafield_len = 0;
407 free(de->comment);
408 de->comment = NULL;
409 de->comment_len = 0;
410 }
411
412
413
414 /* _zip_dirent_write(zde, fp, localp, error):
415 Writes zip directory entry zde to file fp.
416
417 If localp != 0, it writes a local header instead of a central
418 directory entry.
419
420 Returns 0 if successful. On error, error is filled in and -1 is
421 returned.
422 */
423
424 int
_zip_dirent_write(struct zip_dirent * zde,FILE * fp,int localp,struct zip_error * error)425 _zip_dirent_write(struct zip_dirent *zde, FILE *fp, int localp,
426 struct zip_error *error)
427 {
428 unsigned short dostime, dosdate;
429
430 fwrite(localp ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp);
431
432 if (!localp)
433 _zip_write2(zde->version_madeby, fp);
434 _zip_write2(zde->version_needed, fp);
435 _zip_write2(zde->bitflags, fp);
436 _zip_write2(zde->comp_method, fp);
437
438 _zip_u2d_time(zde->last_mod, &dostime, &dosdate);
439 _zip_write2(dostime, fp);
440 _zip_write2(dosdate, fp);
441
442 _zip_write4(zde->crc, fp);
443 _zip_write4(zde->comp_size, fp);
444 _zip_write4(zde->uncomp_size, fp);
445
446 _zip_write2(zde->filename_len, fp);
447 _zip_write2(zde->extrafield_len, fp);
448
449 if (!localp) {
450 _zip_write2(zde->comment_len, fp);
451 _zip_write2(zde->disk_number, fp);
452 _zip_write2(zde->int_attrib, fp);
453 _zip_write4(zde->ext_attrib, fp);
454 _zip_write4(zde->offset, fp);
455 }
456
457 if (zde->filename_len)
458 fwrite(zde->filename, 1, zde->filename_len, fp);
459
460 if (zde->extrafield_len)
461 fwrite(zde->extrafield, 1, zde->extrafield_len, fp);
462
463 if (!localp) {
464 if (zde->comment_len)
465 fwrite(zde->comment, 1, zde->comment_len, fp);
466 }
467
468 if (ferror(fp)) {
469 _zip_error_set(error, ZIP_ER_WRITE, errno);
470 return -1;
471 }
472
473 return 0;
474 }
475
476
477
478 static time_t
_zip_d2u_time(int dtime,int ddate)479 _zip_d2u_time(int dtime, int ddate)
480 {
481 struct tm tm;
482
483 memset(&tm, 0, sizeof(tm));
484
485 /* let mktime decide if DST is in effect */
486 tm.tm_isdst = -1;
487
488 tm.tm_year = ((ddate>>9)&127) + 1980 - 1900;
489 tm.tm_mon = ((ddate>>5)&15) - 1;
490 tm.tm_mday = ddate&31;
491
492 tm.tm_hour = (dtime>>11)&31;
493 tm.tm_min = (dtime>>5)&63;
494 tm.tm_sec = (dtime<<1)&62;
495
496 return mktime(&tm);
497 }
498
499
500
501 unsigned short
_zip_read2(unsigned char ** a)502 _zip_read2(unsigned char **a)
503 {
504 unsigned short ret;
505
506 ret = (*a)[0]+((*a)[1]<<8);
507 *a += 2;
508
509 return ret;
510 }
511
512
513
514 unsigned int
_zip_read4(unsigned char ** a)515 _zip_read4(unsigned char **a)
516 {
517 unsigned int ret;
518
519 ret = ((((((*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0];
520 *a += 4;
521
522 return ret;
523 }
524
525
526
527 static char *
_zip_readfpstr(FILE * fp,unsigned int len,int nulp,struct zip_error * error)528 _zip_readfpstr(FILE *fp, unsigned int len, int nulp, struct zip_error *error)
529 {
530 char *r, *o;
531
532 r = (char *)malloc(nulp ? len+1 : len);
533 if (!r) {
534 _zip_error_set(error, ZIP_ER_MEMORY, 0);
535 return NULL;
536 }
537
538 if (fread(r, 1, len, fp)<len) {
539 free(r);
540 _zip_error_set(error, ZIP_ER_READ, errno);
541 return NULL;
542 }
543
544 if (nulp) {
545 /* replace any in-string NUL characters with spaces */
546 r[len] = 0;
547 for (o=r; o<r+len; o++)
548 if (*o == '\0')
549 *o = ' ';
550 }
551
552 return r;
553 }
554
555
556
557 static char *
_zip_readstr(unsigned char ** buf,int len,int nulp,struct zip_error * error)558 _zip_readstr(unsigned char **buf, int len, int nulp, struct zip_error *error)
559 {
560 char *r, *o;
561
562 r = (char *)malloc(nulp ? len+1 : len);
563 if (!r) {
564 _zip_error_set(error, ZIP_ER_MEMORY, 0);
565 return NULL;
566 }
567
568 memcpy(r, *buf, len);
569 *buf += len;
570
571 if (nulp) {
572 /* replace any in-string NUL characters with spaces */
573 r[len] = 0;
574 for (o=r; o<r+len; o++)
575 if (*o == '\0')
576 *o = ' ';
577 }
578
579 return r;
580 }
581
582
583
584 static void
_zip_write2(unsigned short i,FILE * fp)585 _zip_write2(unsigned short i, FILE *fp)
586 {
587 putc(i&0xff, fp);
588 putc((i>>8)&0xff, fp);
589
590 return;
591 }
592
593
594
595 static void
_zip_write4(unsigned int i,FILE * fp)596 _zip_write4(unsigned int i, FILE *fp)
597 {
598 putc(i&0xff, fp);
599 putc((i>>8)&0xff, fp);
600 putc((i>>16)&0xff, fp);
601 putc((i>>24)&0xff, fp);
602
603 return;
604 }
605
606
607
608 void
_zip_u2d_time(time_t time,unsigned short * dtime,unsigned short * ddate)609 _zip_u2d_time(time_t time, unsigned short *dtime, unsigned short *ddate)
610 {
611 struct tm *tm;
612
613 tm = localtime(&time);
614 *ddate = ((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5)
615 + tm->tm_mday;
616 *dtime = ((tm->tm_hour)<<11) + ((tm->tm_min)<<5)
617 + ((tm->tm_sec)>>1);
618
619 return;
620 }
621