zip-reader: Don't keep .zip file open for lifetime of zip_reader.
[pspp] / src / libpspp / zip-reader.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2011, 2013, 2014 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include <inttypes.h>
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include <errno.h>
26 #include <xalloc.h>
27 #include <libpspp/assertion.h>
28 #include <libpspp/compiler.h>
29
30 #include <byteswap.h>
31
32 #include "str.h"
33
34 #include "zip-reader.h"
35 #include "zip-private.h"
36
37 #include "gettext.h"
38 #define _(msgid) gettext (msgid)
39 #define N_(msgid) (msgid)
40
41 struct zip_member
42 {
43   FILE *fp;                   /* The stream from which the data is read */
44   uint32_t offset;            /* Starting offset in file. */
45   uint32_t comp_size;         /* Length of member file data, in bytes. */
46   uint32_t ucomp_size;        /* Uncompressed length of member file data, in bytes. */
47   const struct decompressor *decompressor;
48
49   size_t bytes_unread;       /* Number of bytes left in the member available for reading */
50   struct string *errmsgs;    /* A string to hold error messages.
51                                 This string is NOT owned by this object. */
52   void *aux;
53 };
54
55 struct decompressor
56 {
57   bool (*init) (struct zip_member *);
58   int  (*read) (struct zip_member *, void *, size_t);
59   void (*finish) (struct zip_member *);
60 };
61 static const struct decompressor stored_decompressor;
62 static const struct decompressor inflate_decompressor;
63
64 static bool find_eocd (FILE *fp, off_t *off);
65
66 static const struct decompressor *
67 get_decompressor (uint16_t c)
68 {
69   switch (c)
70     {
71     case 0:
72       return &stored_decompressor;
73
74     case 8:
75       return &inflate_decompressor;
76
77     default:
78       return NULL;
79     }
80 }
81
82 struct zip_reader
83 {
84   char *filename;                  /* The name of the file from which the data is read */
85   uint16_t n_entries;              /* Number of directory entries. */
86   struct zip_entry *entries;       /* Directory entries. */
87   struct string *errs;
88 };
89
90 struct zip_entry
91 {
92   uint32_t offset;            /* Starting offset in file. */
93   uint32_t comp_size;         /* Length of member file data, in bytes. */
94   uint32_t ucomp_size;        /* Uncompressed length of member file data, in bytes. */
95   char *name;                 /* Name of member file. */
96 };
97
98 void
99 zip_member_finish (struct zip_member *zm)
100 {
101   if (zm)
102     {
103       ds_clear (zm->errmsgs);
104       zm->decompressor->finish (zm);
105       fclose (zm->fp);
106       free (zm);
107     }
108 }
109
110 /* Destroy the zip reader */
111 void
112 zip_reader_destroy (struct zip_reader *zr)
113 {
114   int i;
115   if (zr == NULL)
116     return;
117
118   free (zr->filename);
119
120   for (i = 0; i < zr->n_entries; ++i)
121     {
122       struct zip_entry *ze = &zr->entries[i];
123       free (ze->name);
124     }
125   free (zr->entries);
126   free (zr);
127 }
128
129
130 /* Skip N bytes in F */
131 static void
132 skip_bytes (FILE *f, size_t n)
133 {
134   fseeko (f, n, SEEK_CUR);
135 }
136
137 static bool get_bytes (FILE *f, void *x, size_t n) WARN_UNUSED_RESULT;
138
139
140 /* Read N bytes from F, storing the result in X */
141 static bool
142 get_bytes (FILE *f, void *x, size_t n)
143 {
144   return (n == fread (x, 1, n, f));
145 }
146
147 static bool get_u32 (FILE *f, uint32_t *v) WARN_UNUSED_RESULT;
148
149
150 /* Read a 32 bit value from F */
151 static bool
152 get_u32 (FILE *f, uint32_t *v)
153 {
154   uint32_t x;
155   if (!get_bytes (f, &x, sizeof x))
156     return false;
157 #ifdef WORDS_BIGENDIAN
158   *v = bswap_32 (x);
159 #else
160   *v = x;
161 #endif
162   return true;
163 }
164
165 static bool get_u16 (FILE *f, uint16_t *v) WARN_UNUSED_RESULT;
166
167
168 /* Read a 16 bit value from F */
169 static bool
170 get_u16 (FILE *f, uint16_t *v)
171 {
172   uint16_t x;
173   if (!get_bytes (f, &x, sizeof x))
174     return false;
175 #ifdef WORDS_BIGENDIAN
176   *v = bswap_16 (x);
177 #else
178   *v = x;
179 #endif
180   return true;
181 }
182
183
184 /* Read 32 bit integer and compare it with EXPECTED.
185    place an error string in ERR if necessary. */
186 static bool
187 check_magic (FILE *f, uint32_t expected, struct string *err)
188 {
189   uint32_t magic;
190
191   if (! get_u32 (f, &magic)) return false;
192
193   if ((expected != magic))
194     {
195       ds_put_format (err,
196                      _("Corrupt file at 0x%llx: Expected %"PRIx32"; got %"PRIx32),
197                      (long long int) ftello (f) - sizeof (uint32_t), expected, magic);
198
199       return false;
200     }
201   return true;
202 }
203
204
205 /* Reads upto BYTES bytes from ZM and puts them in BUF.
206    Returns the number of bytes read, or -1 on error */
207 int
208 zip_member_read (struct zip_member *zm, void *buf, size_t bytes)
209 {
210   int bytes_read = 0;
211
212   ds_clear (zm->errmsgs);
213
214   if ( bytes > zm->bytes_unread)
215     bytes = zm->bytes_unread;
216
217   bytes_read  = zm->decompressor->read (zm, buf, bytes);
218   if ( bytes_read < 0)
219     return bytes_read;
220
221   zm->bytes_unread -= bytes_read;
222
223   return bytes_read;
224 }
225
226
227 /* Read a central directory header from FILE and initializes ZE with it.
228    Returns true if successful, false otherwise.  On error, appends error
229    messages to ERRS. */
230 static bool
231 zip_header_read_next (FILE *file, struct zip_entry *ze, struct string *errs)
232 {
233   uint16_t v, nlen, extralen;
234   uint16_t gp, time, date;
235   uint32_t expected_crc;
236
237   uint16_t clen, diskstart, iattr;
238   uint32_t eattr;
239   uint16_t comp_type;
240
241   if ( ! check_magic (file, MAGIC_SOCD, errs))
242     return false;
243
244   if (! get_u16 (file, &v)) return false;
245   if (! get_u16 (file, &v)) return false;
246   if (! get_u16 (file, &gp)) return false;
247   if (! get_u16 (file, &comp_type)) return false;
248   if (! get_u16 (file, &time)) return false;
249   if (! get_u16 (file, &date)) return false;
250   if (! get_u32 (file, &expected_crc)) return false;
251   if (! get_u32 (file, &ze->comp_size)) return false;
252   if (! get_u32 (file, &ze->ucomp_size)) return false;
253   if (! get_u16 (file, &nlen)) return false;
254   if (! get_u16 (file, &extralen)) return false;
255   if (! get_u16 (file, &clen)) return false;
256   if (! get_u16 (file, &diskstart)) return false;
257   if (! get_u16 (file, &iattr)) return false;
258   if (! get_u32 (file, &eattr)) return false;
259   if (! get_u32 (file, &ze->offset)) return false;
260
261   ze->name = xzalloc (nlen + 1);
262   if (! get_bytes (file, ze->name, nlen)) return false;
263
264   skip_bytes (file, extralen);
265
266   return true;
267 }
268
269
270 /* Create a reader from the zip called FILENAME */
271 struct zip_reader *
272 zip_reader_create (const char *filename, struct string *errs)
273 {
274   uint16_t disknum, n_members, total_members;
275   off_t offset = 0;
276   uint32_t central_dir_start, central_dir_length;
277
278   struct zip_reader *zr = xzalloc (sizeof *zr);
279   zr->errs = errs;
280   if ( zr->errs)
281     ds_init_empty (zr->errs);
282
283   FILE *file = fopen (filename, "rb");
284   if (!file)
285     {
286       ds_put_cstr (zr->errs, strerror (errno));
287       free (zr);
288       return NULL;
289     }
290
291   if ( ! check_magic (file, MAGIC_LHDR, zr->errs))
292     {
293       fclose (file);
294       free (zr);
295       return NULL;
296     }
297
298   if ( ! find_eocd (file, &offset))
299     {
300       ds_put_format (zr->errs, _("Cannot find central directory"));
301       fclose (file);
302       free (zr);
303       return NULL;
304     }
305
306   if ( 0 != fseeko (file, offset, SEEK_SET))
307     {
308       const char *mm = strerror (errno);
309       ds_put_format (zr->errs, _("Failed to seek to end of central directory record: %s"), mm);
310       fclose (file);
311       free (zr);
312       return NULL;
313     }
314
315
316   if ( ! check_magic (file, MAGIC_EOCD, zr->errs))
317     {
318       fclose (file);
319       free (zr);
320       return NULL;
321     }
322
323   if (! get_u16 (file, &disknum)
324       || ! get_u16 (file, &disknum)
325
326       || ! get_u16 (file, &n_members)
327       || ! get_u16 (file, &total_members)
328
329       || ! get_u32 (file, &central_dir_length)
330       || ! get_u32 (file, &central_dir_start))
331     {
332       fclose (file);
333       free (zr);
334       return NULL;
335     }
336
337   if ( 0 != fseeko (file, central_dir_start, SEEK_SET))
338     {
339       const char *mm = strerror (errno);
340       ds_put_format (zr->errs, _("Failed to seek to central directory: %s"), mm);
341       fclose (file);
342       free (zr);
343       return NULL;
344     }
345
346   zr->filename = xstrdup (filename);
347
348   zr->entries = xcalloc (n_members, sizeof *zr->entries);
349   for (int i = 0; i < n_members; i++)
350     {
351       if (!zip_header_read_next (file, &zr->entries[zr->n_entries], errs))
352         {
353           fclose (file);
354           zip_reader_destroy (zr);
355           return NULL;
356         }
357       zr->n_entries++;
358     }
359
360   return zr;
361 }
362
363 static struct zip_entry *
364 zip_entry_find (struct zip_reader *zr, const char *member)
365 {
366   for (int i = 0; i < zr->n_entries; ++i)
367     {
368       struct zip_entry *ze = &zr->entries[i];
369       if (0 == strcmp (ze->name, member))
370         return ze;
371     }
372   return NULL;
373 }
374
375 /* Return the member called MEMBER from the reader ZR  */
376 struct zip_member *
377 zip_member_open (struct zip_reader *zr, const char *member)
378 {
379   struct zip_entry *ze = zip_entry_find (zr, member);
380   if ( ze == NULL)
381     {
382       ds_put_format (zr->errs, _("%s: unknown member"), member);
383       return NULL;
384     }
385
386   FILE *fp = fopen (zr->filename, "rb");
387   if (!fp)
388     {
389       ds_put_cstr (zr->errs, strerror (errno));
390       return NULL;
391     }
392
393   struct zip_member *zm = xmalloc (sizeof *zm);
394   zm->fp = fp;
395   zm->offset = ze->offset;
396   zm->comp_size = ze->comp_size;
397   zm->ucomp_size = ze->ucomp_size;
398   zm->decompressor = NULL;
399   zm->bytes_unread = ze->ucomp_size;
400   zm->errmsgs = zr->errs;
401   zm->aux = NULL;
402
403   if ( 0 != fseeko (zm->fp, zm->offset, SEEK_SET))
404     {
405       ds_put_format (zr->errs, _("Failed to seek to start of member `%s': %s"),
406                      ze->name, strerror (errno));
407       goto error;
408     }
409
410   if ( ! check_magic (zm->fp, MAGIC_LHDR, zr->errs))
411     goto error;
412
413   uint16_t v, nlen, extra_len;
414   uint16_t gp, comp_type, time, date;
415   uint32_t ucomp_size, comp_size;
416   uint32_t crc;
417   if (! get_u16 (zm->fp, &v)) goto error;
418   if (! get_u16 (zm->fp, &gp)) goto error;
419   if (! get_u16 (zm->fp, &comp_type)) goto error;
420   zm->decompressor = get_decompressor (comp_type);
421   if (! zm->decompressor) goto error;
422   if (! get_u16 (zm->fp, &time)) goto error;
423   if (! get_u16 (zm->fp, &date)) goto error;
424   if (! get_u32 (zm->fp, &crc)) goto error;
425   if (! get_u32 (zm->fp, &comp_size)) goto error;
426
427   if (! get_u32 (zm->fp, &ucomp_size)) goto error;
428   if (! get_u16 (zm->fp, &nlen)) goto error;
429   if (! get_u16 (zm->fp, &extra_len)) goto error;
430
431   char *name = xzalloc (nlen + 1);
432   if (! get_bytes (zm->fp, name, nlen))
433     {
434       free (name);
435       goto error;
436     }
437   if (strcmp (name, ze->name) != 0)
438     {
439       ds_put_format (zm->errmsgs,
440                      _("Name mismatch in zip archive. Central directory "
441                        "says `%s'; local file header says `%s'"),
442                      ze->name, name);
443       free (name);
444       goto error;
445     }
446   free (name);
447
448   skip_bytes (zm->fp, extra_len);
449
450   if (!zm->decompressor->init (zm) )
451     goto error;
452
453   return zm;
454
455 error:
456   fclose (zm->fp);
457   free (zm);
458   return NULL;
459 }
460
461 \f
462
463 static bool probe_magic (FILE *fp, uint32_t magic, off_t start, off_t stop, off_t *off);
464
465
466 /* Search for something that looks like the End Of Central Directory in FP.
467    If found, the offset of the record will be placed in OFF.
468    Returns true if found false otherwise.
469 */
470 static bool
471 find_eocd (FILE *fp, off_t *off)
472 {
473   off_t start, stop;
474   const uint32_t magic = MAGIC_EOCD;
475   bool found = false;
476
477   /* The magic cannot be more than 22 bytes from the end of the file,
478      because that is the minimum length of the EndOfCentralDirectory
479      record.
480    */
481   if ( 0 > fseeko (fp, -22, SEEK_END))
482     {
483       return false;
484     }
485   start = ftello (fp);
486   stop = start + sizeof (magic);
487   do
488     {
489       found = probe_magic (fp, magic, start, stop, off);
490       /* FIXME: For extra confidence lookup the directory start record here*/
491       if ( start == 0)
492         break;
493       stop = start + sizeof (magic);
494       start >>= 1;
495     }
496   while (!found );
497
498   return found;
499 }
500
501
502 /*
503   Search FP for MAGIC starting at START and reaching until STOP.
504   Returns true iff MAGIC is found.  False otherwise.
505   OFF receives the location of the magic.
506 */
507 static bool
508 probe_magic (FILE *fp, uint32_t magic, off_t start, off_t stop, off_t *off)
509 {
510   int i;
511   int state = 0;
512   unsigned char seq[4];
513   unsigned char byte;
514
515   if ( 0 > fseeko (fp, start, SEEK_SET))
516     {
517       return -1;
518     }
519
520   for (i = 0; i < 4 ; ++i)
521     {
522       seq[i] = (magic >> i * 8) & 0xFF;
523     }
524
525   do
526     {
527       if (1 != fread (&byte, 1, 1, fp))
528         break;
529
530       if ( byte == seq[state])
531         state++;
532       else
533         state = 0;
534
535       if ( state == 4)
536         {
537           *off = ftello (fp) - 4;
538           return true;
539         }
540       start++;
541       if ( start >= stop)
542         break;
543     }
544   while (!feof (fp));
545
546   return false;
547 }
548 \f
549 /* Null decompressor. */
550
551 static int
552 stored_read (struct zip_member *zm, void *buf, size_t n)
553 {
554   return fread (buf, 1, n, zm->fp);
555 }
556
557 static bool
558 stored_init (struct zip_member *zm UNUSED)
559 {
560   return true;
561 }
562
563 static void
564 stored_finish (struct zip_member *zm UNUSED)
565 {
566   /* Nothing required */
567 }
568
569 static const struct decompressor stored_decompressor =
570   {stored_init, stored_read, stored_finish};
571 \f
572 /* Inflate decompressor. */
573
574 #undef crc32
575 #include <zlib.h>
576
577 #define UCOMPSIZE 4096
578
579 struct inflator
580 {
581   z_stream zss;
582   int state;
583   unsigned char ucomp[UCOMPSIZE];
584   size_t bytes_uncomp;
585   size_t ucomp_bytes_read;
586
587   /* Two bitfields as defined by RFC1950 */
588   uint16_t cmf_flg ;
589 };
590
591 static void
592 inflate_finish (struct zip_member *zm)
593 {
594   struct inflator *inf = zm->aux;
595
596   inflateEnd (&inf->zss);
597
598   free (inf);
599 }
600
601 static bool
602 inflate_init (struct zip_member *zm)
603 {
604   int r;
605   struct inflator *inf = xzalloc (sizeof *inf);
606
607   uint16_t flg = 0 ;
608   uint16_t cmf = 0x8; /* Always 8 for inflate */
609
610   const uint16_t cinfo = 7;  /* log_2(Window size) - 8 */
611
612   cmf |= cinfo << 4;     /* Put cinfo into the high nibble */
613
614   /* make these into a 16 bit word */
615   inf->cmf_flg = (cmf << 8 ) | flg;
616
617   /* Set the check bits */
618   inf->cmf_flg += 31 - (inf->cmf_flg % 31);
619   assert (inf->cmf_flg % 31 == 0);
620
621   inf->zss.next_in = Z_NULL;
622   inf->zss.avail_in = 0;
623   inf->zss.zalloc = Z_NULL;
624   inf->zss.zfree  = Z_NULL;
625   inf->zss.opaque = Z_NULL;
626   r = inflateInit (&inf->zss);
627
628   if ( Z_OK != r)
629     {
630       ds_put_format (zm->errmsgs, _("Cannot initialize inflator: %s"), zError (r));
631       return false;
632     }
633
634   zm->aux = inf;
635
636   return true;
637 }
638
639 static int
640 inflate_read (struct zip_member *zm, void *buf, size_t n)
641 {
642   int r;
643   struct inflator *inf = zm->aux;
644
645   if (inf->zss.avail_in == 0)
646     {
647       int bytes_read;
648       int bytes_to_read;
649       int pad = 0;
650
651       if ( inf->state == 0)
652         {
653           inf->ucomp[1] = inf->cmf_flg ;
654           inf->ucomp[0] = inf->cmf_flg >> 8 ;
655
656           pad = 2;
657           inf->state++;
658         }
659
660       bytes_to_read = zm->comp_size - inf->ucomp_bytes_read;
661
662       if (bytes_to_read == 0)
663         return 0;
664
665       if (bytes_to_read > UCOMPSIZE)
666         bytes_to_read = UCOMPSIZE;
667
668       bytes_read = fread (inf->ucomp + pad, 1, bytes_to_read - pad, zm->fp);
669
670       inf->ucomp_bytes_read += bytes_read;
671
672       inf->zss.avail_in = bytes_read + pad;
673       inf->zss.next_in = inf->ucomp;
674     }
675   inf->zss.avail_out = n;
676   inf->zss.next_out = buf;
677
678   r = inflate (&inf->zss, Z_NO_FLUSH);
679   if ( Z_OK == r)
680     {
681       return n - inf->zss.avail_out;
682     }
683
684   ds_put_format (zm->errmsgs, _("Error inflating: %s"), zError (r));
685
686   return -1;
687 }
688
689 static const struct decompressor inflate_decompressor =
690   {inflate_init, inflate_read, inflate_finish};
691