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