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