zip-reader: New function zip_reader_get_member_name().
[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 const char *
376 zip_reader_get_member_name(const struct zip_reader *zr, size_t idx)
377 {
378   return idx < zr->n_entries ? zr->entries[idx].name : NULL;
379 }
380
381 /* Return the member called MEMBER from the reader ZR  */
382 struct zip_member *
383 zip_member_open (struct zip_reader *zr, const char *member)
384 {
385   struct zip_entry *ze = zip_entry_find (zr, member);
386   if ( ze == NULL)
387     {
388       ds_put_format (zr->errs, _("%s: unknown member"), member);
389       return NULL;
390     }
391
392   FILE *fp = fopen (zr->filename, "rb");
393   if (!fp)
394     {
395       ds_put_cstr (zr->errs, strerror (errno));
396       return NULL;
397     }
398
399   struct zip_member *zm = xmalloc (sizeof *zm);
400   zm->fp = fp;
401   zm->offset = ze->offset;
402   zm->comp_size = ze->comp_size;
403   zm->ucomp_size = ze->ucomp_size;
404   zm->decompressor = NULL;
405   zm->bytes_unread = ze->ucomp_size;
406   zm->errmsgs = zr->errs;
407   zm->aux = NULL;
408
409   if ( 0 != fseeko (zm->fp, zm->offset, SEEK_SET))
410     {
411       ds_put_format (zr->errs, _("Failed to seek to start of member `%s': %s"),
412                      ze->name, strerror (errno));
413       goto error;
414     }
415
416   if ( ! check_magic (zm->fp, MAGIC_LHDR, zr->errs))
417     goto error;
418
419   uint16_t v, nlen, extra_len;
420   uint16_t gp, comp_type, time, date;
421   uint32_t ucomp_size, comp_size;
422   uint32_t crc;
423   if (! get_u16 (zm->fp, &v)) goto error;
424   if (! get_u16 (zm->fp, &gp)) goto error;
425   if (! get_u16 (zm->fp, &comp_type)) goto error;
426   zm->decompressor = get_decompressor (comp_type);
427   if (! zm->decompressor) goto error;
428   if (! get_u16 (zm->fp, &time)) goto error;
429   if (! get_u16 (zm->fp, &date)) goto error;
430   if (! get_u32 (zm->fp, &crc)) goto error;
431   if (! get_u32 (zm->fp, &comp_size)) goto error;
432
433   if (! get_u32 (zm->fp, &ucomp_size)) goto error;
434   if (! get_u16 (zm->fp, &nlen)) goto error;
435   if (! get_u16 (zm->fp, &extra_len)) goto error;
436
437   char *name = xzalloc (nlen + 1);
438   if (! get_bytes (zm->fp, name, nlen))
439     {
440       free (name);
441       goto error;
442     }
443   if (strcmp (name, ze->name) != 0)
444     {
445       ds_put_format (zm->errmsgs,
446                      _("Name mismatch in zip archive. Central directory "
447                        "says `%s'; local file header says `%s'"),
448                      ze->name, name);
449       free (name);
450       goto error;
451     }
452   free (name);
453
454   skip_bytes (zm->fp, extra_len);
455
456   if (!zm->decompressor->init (zm) )
457     goto error;
458
459   return zm;
460
461 error:
462   fclose (zm->fp);
463   free (zm);
464   return NULL;
465 }
466
467 \f
468
469 static bool probe_magic (FILE *fp, uint32_t magic, off_t start, off_t stop, off_t *off);
470
471
472 /* Search for something that looks like the End Of Central Directory in FP.
473    If found, the offset of the record will be placed in OFF.
474    Returns true if found false otherwise.
475 */
476 static bool
477 find_eocd (FILE *fp, off_t *off)
478 {
479   off_t start, stop;
480   const uint32_t magic = MAGIC_EOCD;
481   bool found = false;
482
483   /* The magic cannot be more than 22 bytes from the end of the file,
484      because that is the minimum length of the EndOfCentralDirectory
485      record.
486    */
487   if ( 0 > fseeko (fp, -22, SEEK_END))
488     {
489       return false;
490     }
491   start = ftello (fp);
492   stop = start + sizeof (magic);
493   do
494     {
495       found = probe_magic (fp, magic, start, stop, off);
496       /* FIXME: For extra confidence lookup the directory start record here*/
497       if ( start == 0)
498         break;
499       stop = start + sizeof (magic);
500       start >>= 1;
501     }
502   while (!found );
503
504   return found;
505 }
506
507
508 /*
509   Search FP for MAGIC starting at START and reaching until STOP.
510   Returns true iff MAGIC is found.  False otherwise.
511   OFF receives the location of the magic.
512 */
513 static bool
514 probe_magic (FILE *fp, uint32_t magic, off_t start, off_t stop, off_t *off)
515 {
516   int i;
517   int state = 0;
518   unsigned char seq[4];
519   unsigned char byte;
520
521   if ( 0 > fseeko (fp, start, SEEK_SET))
522     {
523       return -1;
524     }
525
526   for (i = 0; i < 4 ; ++i)
527     {
528       seq[i] = (magic >> i * 8) & 0xFF;
529     }
530
531   do
532     {
533       if (1 != fread (&byte, 1, 1, fp))
534         break;
535
536       if ( byte == seq[state])
537         state++;
538       else
539         state = 0;
540
541       if ( state == 4)
542         {
543           *off = ftello (fp) - 4;
544           return true;
545         }
546       start++;
547       if ( start >= stop)
548         break;
549     }
550   while (!feof (fp));
551
552   return false;
553 }
554 \f
555 /* Null decompressor. */
556
557 static int
558 stored_read (struct zip_member *zm, void *buf, size_t n)
559 {
560   return fread (buf, 1, n, zm->fp);
561 }
562
563 static bool
564 stored_init (struct zip_member *zm UNUSED)
565 {
566   return true;
567 }
568
569 static void
570 stored_finish (struct zip_member *zm UNUSED)
571 {
572   /* Nothing required */
573 }
574
575 static const struct decompressor stored_decompressor =
576   {stored_init, stored_read, stored_finish};
577 \f
578 /* Inflate decompressor. */
579
580 #undef crc32
581 #include <zlib.h>
582
583 #define UCOMPSIZE 4096
584
585 struct inflator
586 {
587   z_stream zss;
588   int state;
589   unsigned char ucomp[UCOMPSIZE];
590   size_t bytes_uncomp;
591   size_t ucomp_bytes_read;
592
593   /* Two bitfields as defined by RFC1950 */
594   uint16_t cmf_flg ;
595 };
596
597 static void
598 inflate_finish (struct zip_member *zm)
599 {
600   struct inflator *inf = zm->aux;
601
602   inflateEnd (&inf->zss);
603
604   free (inf);
605 }
606
607 static bool
608 inflate_init (struct zip_member *zm)
609 {
610   int r;
611   struct inflator *inf = xzalloc (sizeof *inf);
612
613   uint16_t flg = 0 ;
614   uint16_t cmf = 0x8; /* Always 8 for inflate */
615
616   const uint16_t cinfo = 7;  /* log_2(Window size) - 8 */
617
618   cmf |= cinfo << 4;     /* Put cinfo into the high nibble */
619
620   /* make these into a 16 bit word */
621   inf->cmf_flg = (cmf << 8 ) | flg;
622
623   /* Set the check bits */
624   inf->cmf_flg += 31 - (inf->cmf_flg % 31);
625   assert (inf->cmf_flg % 31 == 0);
626
627   inf->zss.next_in = Z_NULL;
628   inf->zss.avail_in = 0;
629   inf->zss.zalloc = Z_NULL;
630   inf->zss.zfree  = Z_NULL;
631   inf->zss.opaque = Z_NULL;
632   r = inflateInit (&inf->zss);
633
634   if ( Z_OK != r)
635     {
636       ds_put_format (zm->errmsgs, _("Cannot initialize inflator: %s"), zError (r));
637       return false;
638     }
639
640   zm->aux = inf;
641
642   return true;
643 }
644
645 static int
646 inflate_read (struct zip_member *zm, void *buf, size_t n)
647 {
648   int r;
649   struct inflator *inf = zm->aux;
650
651   if (inf->zss.avail_in == 0)
652     {
653       int bytes_read;
654       int bytes_to_read;
655       int pad = 0;
656
657       if ( inf->state == 0)
658         {
659           inf->ucomp[1] = inf->cmf_flg ;
660           inf->ucomp[0] = inf->cmf_flg >> 8 ;
661
662           pad = 2;
663           inf->state++;
664         }
665
666       bytes_to_read = zm->comp_size - inf->ucomp_bytes_read;
667
668       if (bytes_to_read == 0)
669         return 0;
670
671       if (bytes_to_read > UCOMPSIZE)
672         bytes_to_read = UCOMPSIZE;
673
674       bytes_read = fread (inf->ucomp + pad, 1, bytes_to_read - pad, zm->fp);
675
676       inf->ucomp_bytes_read += bytes_read;
677
678       inf->zss.avail_in = bytes_read + pad;
679       inf->zss.next_in = inf->ucomp;
680     }
681   inf->zss.avail_out = n;
682   inf->zss.next_out = buf;
683
684   r = inflate (&inf->zss, Z_NO_FLUSH);
685   if ( Z_OK == r)
686     {
687       return n - inf->zss.avail_out;
688     }
689
690   ds_put_format (zm->errmsgs, _("Error inflating: %s"), zError (r));
691
692   return -1;
693 }
694
695 static const struct decompressor inflate_decompressor =
696   {inflate_init, inflate_read, inflate_finish};
697