/* PSPP - a program for statistical analysis.
- Copyright (C) 2011 Free Software Foundation, Inc.
+ Copyright (C) 2011, 2013, 2014 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <errno.h>
#include <xalloc.h>
#include <libpspp/assertion.h>
+#include <libpspp/compiler.h>
#include <byteswap.h>
#include <crc.h>
}
-static struct decompressor decompressors[n_COMPRESSION] =
+static struct decompressor decompressors[n_COMPRESSION] =
{
{stored_init, stored_read, stored_finish},
-#if HAVE_ZLIB_H
{inflate_init, inflate_read, inflate_finish}
-#endif
};
static enum compression
comp_code (struct zip_member *zm, uint16_t c)
{
enum compression which;
+ assert (zm->errmsgs);
switch (c)
{
case 0:
which = COMPRESSION_STORED;
break;
-#if HAVE_ZLIB_H
case 8:
which = COMPRESSION_INFLATE;
break;
-#endif
default:
- ds_put_format (zm->errs, _("Unsupported compression type (%d)"), c);
+ ds_put_format (zm->errmsgs, _("Unsupported compression type (%d)"), c);
which = n_COMPRESSION;
break;
}
void
zip_member_finish (struct zip_member *zm)
{
- ds_clear (zm->errs);
+ ds_clear (zm->errmsgs);
/* Probably not useful, because we would have to read right to the end of the member
if (zm->expected_crc != zm->crc)
{
zip_reader_destroy (struct zip_reader *zr)
{
int i;
- if (zr == NULL)
+ if (zr == NULL)
return;
- if (zr->fr != NULL)
- fclose (zr->fr);
-
+ fclose (zr->fr);
free (zr->filename);
for (i = 0; i < zr->n_members; ++i)
fseeko (f, n, SEEK_CUR);
}
+static bool get_bytes (FILE *f, void *x, size_t n) WARN_UNUSED_RESULT;
+
+
/* Read N bytes from F, storing the result in X */
-static void
+static bool
get_bytes (FILE *f, void *x, size_t n)
{
- fread (x, 1, n, f);
+ return (n == fread (x, 1, n, f));
}
+static bool get_u32 (FILE *f, uint32_t *v) WARN_UNUSED_RESULT;
+
+
/* Read a 32 bit value from F */
-static void
+static bool
get_u32 (FILE *f, uint32_t *v)
{
uint32_t x;
- get_bytes (f, &x, sizeof x);
+ if (!get_bytes (f, &x, sizeof x))
+ return false;
#ifdef WORDS_BIGENDIAN
*v = bswap_32 (x);
#else
*v = x;
#endif
+ return true;
}
+static bool get_u16 (FILE *f, uint16_t *v) WARN_UNUSED_RESULT;
+
+
/* Read a 16 bit value from F */
-static void
+static bool
get_u16 (FILE *f, uint16_t *v)
{
uint16_t x;
- get_bytes (f, &x, sizeof x);
+ if (!get_bytes (f, &x, sizeof x))
+ return false;
#ifdef WORDS_BIGENDIAN
*v = bswap_16 (x);
#else
*v = x;
#endif
+ return true;
}
{
uint32_t magic;
- get_u32 (f, &magic);
+ if (! get_u32 (f, &magic)) return false;
if ((expected != magic))
{
ds_put_format (err,
- _("Corrupt file at 0x%llx: Expected %"PRIx32"; got %"PRIx32),
+ _("Corrupt file at 0x%llx: Expected %"PRIx32"; got %"PRIx32),
(long long int) ftello (f) - sizeof (uint32_t), expected, magic);
return false;
{
int bytes_read = 0;
- ds_clear (zm->errs);
+ ds_clear (zm->errmsgs);
if ( bytes > zm->bytes_unread)
bytes = zm->bytes_unread;
/*
Read a local file header from ZR and add it to ZR's internal array.
Returns a pointer to the member read. This pointer belongs to ZR.
- If the caller wishes to control it, she should ref it with
+ If the caller wishes to control it, she should ref it with
zip_member_ref.
*/
static struct zip_member *
uint16_t v, nlen, extralen;
uint16_t gp, time, date;
-
+
uint16_t clen, diskstart, iattr;
uint32_t eattr;
uint16_t comp_type;
ds_clear (zr->errs);
+ zm->errmsgs = zr->errs;
if ( ! check_magic (zr->fr, MAGIC_SOCD, zr->errs))
return NULL;
- get_u16 (zr->fr, &v);
+ if (! get_u16 (zr->fr, &v)) return NULL;
- get_u16 (zr->fr, &v);
- get_u16 (zr->fr, &gp);
- get_u16 (zr->fr, &comp_type);
+ if (! get_u16 (zr->fr, &v)) return NULL;
+ if (! get_u16 (zr->fr, &gp)) return NULL;
+ if (! get_u16 (zr->fr, &comp_type)) return NULL;
zm->compression = comp_code (zm, comp_type);
- get_u16 (zr->fr, &time);
- get_u16 (zr->fr, &date);
- get_u32 (zr->fr, &zm->expected_crc);
- get_u32 (zr->fr, &zm->comp_size);
- get_u32 (zr->fr, &zm->ucomp_size);
- get_u16 (zr->fr, &nlen);
- get_u16 (zr->fr, &extralen);
- get_u16 (zr->fr, &clen);
- get_u16 (zr->fr, &diskstart);
- get_u16 (zr->fr, &iattr);
- get_u32 (zr->fr, &eattr);
- get_u32 (zr->fr, &zm->offset);
+ if (! get_u16 (zr->fr, &time)) return NULL;
+ if (! get_u16 (zr->fr, &date)) return NULL;
+ if (! get_u32 (zr->fr, &zm->expected_crc)) return NULL;
+ if (! get_u32 (zr->fr, &zm->comp_size)) return NULL;
+ if (! get_u32 (zr->fr, &zm->ucomp_size)) return NULL;
+ if (! get_u16 (zr->fr, &nlen)) return NULL;
+ if (! get_u16 (zr->fr, &extralen)) return NULL;
+ if (! get_u16 (zr->fr, &clen)) return NULL;
+ if (! get_u16 (zr->fr, &diskstart)) return NULL;
+ if (! get_u16 (zr->fr, &iattr)) return NULL;
+ if (! get_u32 (zr->fr, &eattr)) return NULL;
+ if (! get_u32 (zr->fr, &zm->offset)) return NULL;
zm->name = xzalloc (nlen + 1);
- get_bytes (zr->fr, zm->name, nlen);
+ if (! get_bytes (zr->fr, zm->name, nlen)) return NULL;
skip_bytes (zr->fr, extralen);
-
+
zr->members[zr->nm++] = zm;
- zm->fp = fopen (zr->filename, "r");
+ zm->fp = fopen (zr->filename, "rb");
zm->ref_cnt = 1;
- zm->errs = zr->errs;
+
return zm;
}
zr->nm = 0;
- zr->fr = fopen (filename, "r");
+ zr->fr = fopen (filename, "rb");
if (NULL == zr->fr)
{
ds_put_cstr (zr->errs, strerror (errno));
free (zr);
return NULL;
}
-
- get_u16 (zr->fr, &disknum);
- get_u16 (zr->fr, &disknum);
- get_u16 (zr->fr, &zr->n_members);
- get_u16 (zr->fr, &total_members);
+ if (! get_u16 (zr->fr, &disknum)) return NULL;
+ if (! get_u16 (zr->fr, &disknum)) return NULL;
+
+ if (! get_u16 (zr->fr, &zr->n_members)) return NULL;
+ if (! get_u16 (zr->fr, &total_members)) return NULL;
- get_u32 (zr->fr, ¢ral_dir_length);
- get_u32 (zr->fr, ¢ral_dir_start);
+ if (! get_u32 (zr->fr, ¢ral_dir_length)) return NULL;
+ if (! get_u32 (zr->fr, ¢ral_dir_start)) return NULL;
if ( 0 != fseeko (zr->fr, central_dir_start, SEEK_SET))
{
zr->members = xcalloc (zr->n_members, sizeof (*zr->members));
memset (zr->members, 0, zr->n_members * sizeof (*zr->members));
- zr->filename = strdup (filename);
+ zr->filename = xstrdup (filename);
return zr;
}
uint16_t v, nlen, extra_len;
uint16_t gp, comp_type, time, date;
uint32_t ucomp_size, comp_size;
-
+
uint32_t crc;
bool new_member = false;
char *name = NULL;
else
zm = NULL;
}
-
+
if ( zm == NULL)
return NULL;
if ( 0 != fseeko (zm->fp, zm->offset, SEEK_SET))
{
const char *mm = strerror (errno);
- ds_put_format (zm->errs, _("Failed to seek to start of member `%s': %s"), zm->name, mm);
+ ds_put_format (zm->errmsgs, _("Failed to seek to start of member `%s': %s"), zm->name, mm);
return NULL;
}
return NULL;
}
- get_u16 (zm->fp, &v);
- get_u16 (zm->fp, &gp);
- get_u16 (zm->fp, &comp_type);
+ if (! get_u16 (zm->fp, &v)) return NULL;
+ if (! get_u16 (zm->fp, &gp)) return NULL;
+ if (! get_u16 (zm->fp, &comp_type)) return NULL;
zm->compression = comp_code (zm, comp_type);
- get_u16 (zm->fp, &time);
- get_u16 (zm->fp, &date);
- get_u32 (zm->fp, &crc);
- get_u32 (zm->fp, &comp_size);
+ if (! get_u16 (zm->fp, &time)) return NULL;
+ if (! get_u16 (zm->fp, &date)) return NULL;
+ if (! get_u32 (zm->fp, &crc)) return NULL;
+ if (! get_u32 (zm->fp, &comp_size)) return NULL;
- get_u32 (zm->fp, &ucomp_size);
- get_u16 (zm->fp, &nlen);
- get_u16 (zm->fp, &extra_len);
+ if (! get_u32 (zm->fp, &ucomp_size)) return NULL;
+ if (! get_u16 (zm->fp, &nlen)) return NULL;
+ if (! get_u16 (zm->fp, &extra_len)) return NULL;
name = xzalloc (nlen + 1);
- get_bytes (zm->fp, name, nlen);
+ if (! get_bytes (zm->fp, name, nlen)) return NULL;
skip_bytes (zm->fp, extra_len);
if (strcmp (name, zm->name) != 0)
{
- ds_put_format (zm->errs,
+ ds_put_format (zm->errmsgs,
_("Name mismatch in zip archive. Central directory says `%s'; local file header says `%s'"),
zm->name, name);
free (name);
free (name);
zm->bytes_unread = zm->ucomp_size;
-
+
if ( !new_member)
decompressors[zm->compression].finish (zm);
const uint32_t magic = MAGIC_EOCD;
bool found = false;
- /* The magic cannot be more than 22 bytes from the end of the file,
+ /* The magic cannot be more than 22 bytes from the end of the file,
because that is the minimum length of the EndOfCentralDirectory
record.
*/
}
start = ftello (fp);
stop = start + sizeof (magic);
- do
+ do
{
found = probe_magic (fp, magic, start, stop, off);
/* FIXME: For extra confidence lookup the directory start record here*/
do
{
- fread (&byte, 1, 1, fp);
+ if (1 != fread (&byte, 1, 1, fp))
+ break;
if ( byte == seq[state])
state++;
else
state = 0;
-
+
if ( state == 4)
{
*off = ftello (fp) - 4;