summaryrefslogtreecommitdiff
path: root/Build/source/libs/zziplib/zziplib-src/zzip/fseeko.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/zziplib/zziplib-src/zzip/fseeko.c')
-rw-r--r--Build/source/libs/zziplib/zziplib-src/zzip/fseeko.c323
1 files changed, 253 insertions, 70 deletions
diff --git a/Build/source/libs/zziplib/zziplib-src/zzip/fseeko.c b/Build/source/libs/zziplib/zziplib-src/zzip/fseeko.c
index d99067a0b4f..ba19b436fb0 100644
--- a/Build/source/libs/zziplib/zziplib-src/zzip/fseeko.c
+++ b/Build/source/libs/zziplib/zziplib-src/zzip/fseeko.c
@@ -24,12 +24,7 @@
* Author:
* Guido Draheim <guidod@gmx.de>
*
- * Copyright (c) 2003,2004 Guido Draheim
- * All rights reserved,
- * use under the restrictions of the
- * Lesser GNU General Public License
- * or alternatively the restrictions
- * of the Mozilla Public License 1.1
+ * Copyright (c) Guido Draheim, use under copyleft (LGPL,MPL)
*/
#define _LARGEFILE_SOURCE 1
@@ -41,7 +36,6 @@
#include <zzip/__mmap.h>
#include <zzip/__fnmatch.h>
-#include <assert.h>
#include <stdlib.h>
#include <sys/stat.h>
@@ -83,6 +77,18 @@
* the sys/mmap interface we have to guess a good value here: */
#define PAGESIZE 8192
+#ifdef DEBUG
+#define debug1(msg) do { fprintf(stderr, "%s : " msg "\n", __func__); } while(0)
+#define debug2(msg, arg1) do { fprintf(stderr, "%s : " msg "\n", __func__, arg1); } while(0)
+#define debug3(msg, arg1, arg2) do { fprintf(stderr, "%s : " msg "\n", __func__, arg1, arg2); } while(0)
+#define debug4(msg, arg1, arg2, arg3) do { fprintf(stderr, "%s : " msg "\n", __func__, arg1, arg2, arg3); } while(0)
+#else
+#define debug1(msg)
+#define debug2(msg, arg1)
+#define debug3(msg, arg1, arg2)
+#define debug4(msg, arg1, arg2, arg3)
+#endif
+
/* ====================================================================== */
/* helper functions */
@@ -92,21 +98,42 @@
* the zip disk of the given "entry". The returned off_t points to the
* end of the file_header where the current fseek pointer has stopped.
* This is used to immediatly parse out any filename/extras block following
- * the file_header. The return value is null on error.
+ * the file_header.
+ *
+ * Returns zero on error. (errno = EINVAL|EBADMSG|EBADF|EIO)
*/
static zzip_off_t
zzip_entry_fread_file_header(ZZIP_ENTRY * entry,
struct zzip_file_header *file_header)
{
if (! entry || ! file_header)
+ {
+ errno = EINVAL;
return 0;
+ }
___ zzip_off_t offset = zzip_disk_entry_fileoffset(disk_(entry));
if (0 > offset || offset >= entry->disksize)
+ {
+ errno = EBADMSG;
return 0;
+ }
- if (fseeko(entry->diskfile, offset, SEEK_SET) == -1) return 0;
- return (fread(file_header, sizeof(*file_header), 1, entry->diskfile)
- ? offset + sizeof(*file_header) : 0);
+ if (fseeko(entry->diskfile, offset, SEEK_SET) == -1)
+ {
+ debug2("fseeko failed: %s", strerror(errno));
+ return 0; /* EBADF */
+ }
+
+ ___ zzip_size_t n = fread(file_header, 1, sizeof(*file_header), entry->diskfile);
+ if (n < sizeof(*file_header))
+ {
+ debug4("fread failed: at offset %llu got %i instead of %i",
+ (long long) offset, n, sizeof(*file_header));
+ errno = ferror(entry->diskfile) ? EBADF : EIO;
+ return 0;
+ }
+ ____;
+ return offset + sizeof(*file_header);
____;
}
@@ -116,20 +143,29 @@ zzip_entry_fread_file_header(ZZIP_ENTRY * entry,
* file referenced by the given zzip_entry. It requires an intermediate
* check of the file_header structure (i.e. it reads it from disk). After
* this call, the contained diskfile readposition is already set to the
- * data_offset returned here. On error -1 is returned.
+ * data_offset returned here.
+ *
+ * Returns -1 on error. (errno = EINVAL|EBADMSG)
*/
zzip_off_t
zzip_entry_data_offset(ZZIP_ENTRY * entry)
{
struct zzip_file_header file_header;
if (! entry)
+ {
+ errno = EINVAL;
return -1;
+ }
___ zzip_off_t offset = zzip_entry_fread_file_header(entry, &file_header);
if (! offset)
- return -1;
+ {
+ return -1; /* EBADMSG */
+ }
offset += zzip_file_header_sizeof_tails(&file_header);
if (fseeko(entry->diskfile, offset, SEEK_SET) == -1)
- return -1;
+ {
+ return -1; /* EBADF */
+ }
return offset;
____;
}
@@ -140,19 +176,26 @@ zzip_entry_data_offset(ZZIP_ENTRY * entry)
* with libc we need it that way. Secondly, the filename SHOULD be present
* in the zip central directory but if not then we fallback to the filename
* given in the file_header of each compressed data portion.
+ *
+ * returns: new string buffer, null on error (errno = EINVAL|ENOMEM|EBADMSG)
*/
zzip__new__ char *
zzip_entry_strdup_name(ZZIP_ENTRY * entry)
{
if (! entry)
+ {
+ errno = EINVAL;
return 0;
+ }
___ zzip_size_t len;
if ((len = zzip_disk_entry_namlen(disk_(entry))))
{
char *name = malloc(len + 1);
if (! name)
- return 0;
+ {
+ return 0; /* ENOMEM */
+ }
memcpy(name, entry->tail, len);
name[len] = '\0';
return name;
@@ -163,17 +206,20 @@ zzip_entry_strdup_name(ZZIP_ENTRY * entry)
{
char *name = malloc(len + 1);
if (! name) {
+ return 0; /* ENOMEM */
+ }
+ ___ zzip_size_t n = fread(name, 1, len, entry->diskfile);
+ if (n < len)
+ {
+ errno = ferror(entry->diskfile) ? EBADF : EIO;
+ free (name);
return 0;
- } else {
- zzip_size_t n = fread(name, 1, len, entry->diskfile);
- if (n != len) {
- free (name);
- return 0;
- }
- name[n] = '\0';
- return name;
}
+ name[n] = '\0';
+ return name;
+ ____;
}
+ errno = EBADMSG;
return 0;
____;
____;
@@ -182,7 +228,8 @@ zzip_entry_strdup_name(ZZIP_ENTRY * entry)
static int
prescan_entry(ZZIP_ENTRY * entry)
{
- assert(entry);
+ if (! entry)
+ return EINVAL;
___ zzip_off_t tailsize = zzip_disk_entry_sizeof_tails(disk_(entry));
if (tailsize + 1 > entry->tailalloc)
{
@@ -193,11 +240,16 @@ prescan_entry(ZZIP_ENTRY * entry)
entry->tailalloc = tailsize + 1;
}
# ifdef SIZE_MAX /* from stdint.h */
- if (tailsize > (zzip_off_t)(SIZE_MAX)) { return EFBIG; }
+ if ((unsigned long long)(tailsize) > (unsigned long long)(SIZE_MAX))
+ {
+ debug3("tailsize %llu bigger than sizemax %llu", (long long)(tailsize), (long long)(SIZE_MAX));
+ return EFBIG;
+ }
# endif
___ zzip_size_t readsize = fread(entry->tail, 1, tailsize, entry->diskfile);
/* name + comment + extras */
if ((zzip_off_t)readsize != tailsize) {
+ debug1("read to data");
return errno;
} else {
return 0;
@@ -207,7 +259,8 @@ prescan_entry(ZZIP_ENTRY * entry)
static void
prescan_clear(ZZIP_ENTRY * entry)
{
- assert(entry);
+ if (! entry)
+ return;
if (entry->tail)
free(entry->tail);
entry->tail = 0;
@@ -242,27 +295,42 @@ prescan_clear(ZZIP_ENTRY * entry)
* both parts have valid PK-magic parts. Beyond some sanity check we try to
* catch a common brokeness with zip archives that still allows us to find
* the start of the zip central directory.
+ *
+ * Returns null on error (errno = EINVAL|ENOMEM|EBADMSG|EBADF|ENOENT)
*/
zzip__new__ ZZIP_ENTRY *
zzip_entry_findfirst(FILE * disk)
{
if (! disk)
+ {
+ errno = EINVAL;
return 0;
+ }
if (fseeko(disk, 0, SEEK_END) == -1)
- return 0;
+ {
+ printf("fseeko failed: %s", strerror(errno));
+ return 0; /* EBADF */
+ }
___ zzip_off_t disksize = ftello(disk);
if (disksize < (zzip_off_t) sizeof(struct zzip_disk_trailer))
+ {
+ errno = EBADMSG;
return 0;
+ }
/* we read out chunks of 8 KiB in the hope to match disk granularity */
___ zzip_off_t pagesize = PAGESIZE; /* getpagesize() */
___ ZZIP_ENTRY *entry = malloc(sizeof(*entry));
if (! entry)
- return 0;
+ goto error0; /* ENOMEM */
___ unsigned char *buffer = malloc(pagesize);
if (! buffer)
- goto nomem;
+ goto error1; /* ENOMEM */
- assert(pagesize / 2 > (zzip_off_t) sizeof(struct zzip_disk_trailer));
+ if (pagesize / 2 <= (zzip_off_t) sizeof(struct zzip_disk_trailer))
+ {
+ errno = EBADMSG;
+ goto error2;
+ }
/* at each step, we will fread a pagesize block which overlaps with the
* previous read by means of pagesize/2 step at the end of the while(1) */
___ zzip_off_t mapoffs = disksize & ~(pagesize - 1);
@@ -272,13 +340,21 @@ zzip_entry_findfirst(FILE * disk)
mapoffs -= pagesize / 2;
mapsize += pagesize / 2;
}
- assert(mapsize < 3*8192);
+ if (mapsize >= 3*8192)
+ {
+ errno = EBADMSG;
+ goto error2;
+ }
while (1)
{
if (fseeko(disk, mapoffs, SEEK_SET) == -1)
- goto error;
- if (fread(buffer, 1, mapsize, disk) != (zzip_size_t)mapsize)
- goto error;
+ goto error2; /* EBADF */
+ if (fread(buffer, 1, mapsize, disk) < (zzip_size_t)mapsize)
+ {
+ errno = ferror(disk) ? EBADF : EIO;
+ debug1("in fread");
+ goto error2;
+ }
___ unsigned char *p =
buffer + mapsize - sizeof(struct zzip_disk_trailer);
for (; p >= buffer; p--)
@@ -305,39 +381,74 @@ zzip_entry_findfirst(FILE * disk)
struct zzip_disk64_trailer *trailer =
(struct zzip_disk64_trailer *) p;
if (sizeof(zzip_off_t) < 8)
- return 0;
+ {
+ debug1("disk64 trailer on non-large compile");
+ errno = EFBIG;
+ goto error2;
+ }
+ if ((void*)(trailer + 1) > (buffer + mapsize))
+ {
+ debug1("disk64 trailer is not complete");
+ errno = EBADMSG;
+ goto error2;
+ }
root = zzip_disk64_trailer_rootseek(trailer);
} else
continue;
- assert(0 <= root && root < mapsize);
+ if (!(0 <= root && root < disksize))
+ {
+ debug3("bogus rootseek value %lli (disksize %lli)", (long long)root, (long long)disksize);
+ errno = EBADMSG;
+ goto error2;
+ }
if (fseeko(disk, root, SEEK_SET) == -1)
- goto error;
+ {
+ debug2("next seeko %s", strerror(errno));
+ goto error2; /* EBADF */
+ }
if (fread(disk_(entry), 1, sizeof(*disk_(entry)), disk)
- != sizeof(*disk_(entry))) goto error;
+ != sizeof(*disk_(entry)))
+ {
+ debug2("next freed %s", strerror(errno));
+ errno = ferror(disk) ? EBADF : EIO;
+ goto error2;
+ }
if (zzip_disk_entry_check_magic(entry))
{
free(buffer);
entry->headseek = root;
entry->diskfile = disk;
entry->disksize = disksize;
- if (prescan_entry(entry))
- goto nomem;
+ ___ int err = prescan_entry(entry);
+ if (err)
+ {
+ debug2("prescan %s", strerror(err));
+ errno = err;
+ goto error2;
+ }
return entry;
+ ____;
}
}
____;
if (! mapoffs)
break;
- assert(mapsize >= pagesize / 2);
+ if (mapsize < pagesize / 2)
+ {
+ debug1("bad mapsize should not be possible");
+ errno = EBADMSG;
+ goto error2;
+ }
mapoffs -= pagesize / 2; /* mapsize += pagesize/2; */
mapsize = pagesize; /* if (mapsize > pagesize) ... */
if (disksize - mapoffs > 64 * 1024)
break;
}
- error:
+ errno = ENOENT; /* not found */
+ error2:
free(buffer);
- nomem:
+ error1:
free(entry);
____;
____;
@@ -345,6 +456,8 @@ zzip_entry_findfirst(FILE * disk)
____;
____;
____;
+ error0:
+ debug1("error..");
return 0;
}
@@ -361,25 +474,39 @@ zzip__new__ ZZIP_ENTRY *
zzip_entry_findnext(ZZIP_ENTRY * _zzip_restrict entry)
{
if (! entry)
+ {
+ errno = EINVAL;
return entry;
+ }
if (! zzip_disk_entry_check_magic(entry))
- goto err;
+ goto error_EBADMSG;
___ zzip_off_t seek =
entry->headseek + zzip_disk_entry_sizeto_end(disk_(entry));
if (seek + (zzip_off_t) sizeof(*disk_(entry)) > entry->disksize)
- goto err;
+ goto error_EBADMSG;
if (fseeko(entry->diskfile, seek, SEEK_SET) == -1)
- goto err;
+ goto error; /* EBADF */
if (fread(disk_(entry), 1, sizeof(*disk_(entry)), entry->diskfile)
- != sizeof(*disk_(entry))) goto err;
+ < sizeof(*disk_(entry)))
+ {
+ errno = ferror(entry->diskfile) ? EBADF : EIO;
+ goto error;
+ }
entry->headseek = seek;
if (! zzip_disk_entry_check_magic(entry))
- goto err;
- if (prescan_entry(entry))
- goto err;
+ goto error_EBADMSG;
+ ___ int err = prescan_entry(entry);
+ if (err)
+ {
+ errno = err;
+ goto error;
+ }
return entry;
- err:
+ ____;
+ error_EBADMSG:
+ errno = EBADMSG;
+ error:
zzip_entry_free(entry);
return 0;
____;
@@ -394,7 +521,10 @@ int
zzip_entry_free(ZZIP_ENTRY * entry)
{
if (! entry)
+ {
+ errno = EINVAL;
return 0;
+ }
prescan_clear(entry);
free(entry);
return 1;
@@ -416,7 +546,10 @@ zzip_entry_findfile(FILE * disk, char *filename,
ZZIP_ENTRY * _zzip_restrict entry, zzip_strcmp_fn_t compare)
{
if (! filename || ! disk)
+ {
+ errno = EINVAL;
return 0;
+ }
if (! entry)
entry = zzip_entry_findfirst(disk);
else
@@ -430,7 +563,9 @@ zzip_entry_findfile(FILE * disk, char *filename,
/* filenames within zip files are often not null-terminated! */
char *realname = zzip_entry_strdup_name(entry);
if (! realname)
- continue;
+ {
+ return 0; /* ENOMEM|EBADMSG */
+ }
if (! compare(filename, realname))
{
free(realname);
@@ -441,6 +576,7 @@ zzip_entry_findfile(FILE * disk, char *filename,
continue;
}
}
+ errno = ENOENT;
return 0;
}
@@ -464,7 +600,10 @@ zzip_entry_findmatch(FILE * disk, char *filespec,
zzip_fnmatch_fn_t compare, int flags)
{
if (! filespec || ! disk)
+ {
+ errno = EINVAL;
return 0;
+ }
if (! entry)
entry = zzip_entry_findfirst(disk);
else
@@ -478,17 +617,22 @@ zzip_entry_findmatch(FILE * disk, char *filespec,
/* filenames within zip files are often not null-terminated! */
char *realname = zzip_entry_strdup_name(entry);
if (! realname)
- continue;
+ {
+ return 0; /* ENOMEM|EBADMSG */
+ }
if (! compare(filespec, realname, flags))
{
+ debug3("compare '%s' equal with zip '%s'", filespec, realname);
free(realname);
return entry;
} else
{
+ debug3("compare '%s' not like zip '%s'", filespec, realname);
free(realname);
continue;
}
}
+ errno = ENOENT;
return 0;
}
@@ -525,25 +669,36 @@ zzip__new__ ZZIP_ENTRY_FILE *
zzip_entry_fopen(ZZIP_ENTRY * entry, int takeover)
{
if (! entry)
+ {
+ errno = EINVAL;
return 0;
+ }
if (! takeover)
{
ZZIP_ENTRY *found = malloc(sizeof(*entry));
if (! found)
- return 0;
+ {
+ return 0; /* ENOMEM */
+ }
memcpy(found, entry, sizeof(*entry)); /* prescan_copy */
found->tail = malloc(found->tailalloc);
- if (! found->tail)
- { free (found); return 0; }
+ if (! found->tail)
+ {
+ free (found);
+ return 0; /* ENOMEM */
+ }
memcpy(found->tail, entry->tail, entry->tailalloc);
entry = found;
}
___ ZZIP_ENTRY_FILE *file = malloc(sizeof(*file));
if (! file)
- goto fail1;
+ goto error1; /* ENOMEM */
file->entry = entry;
if (! zzip_entry_fread_file_header(entry, &file->header))
- goto fail2;
+ {
+ debug2("file header: %s", strerror(errno));
+ goto error2; /* EIO|EBADMSG */
+ }
file->avail = zzip_file_header_usize(&file->header);
file->data = zzip_entry_data_offset(entry);
file->dataoff = 0;
@@ -556,26 +711,32 @@ zzip_entry_fopen(ZZIP_ENTRY * entry, int takeover)
file->zlib.zalloc = Z_NULL;
file->zlib.zfree = Z_NULL;
- ___ zzip_off_t seek = file->data;
- seek += sizeof(file->buffer);
- seek -= seek & (sizeof(file->buffer) - 1);
- assert(file->data < seek); /* pre-read to next PAGESIZE boundary... */
+ ___ zzip_off_t size = file->avail;
+ if (size > sizeof(file->buffer))
+ size = sizeof(file->buffer);
if (fseeko(file->entry->diskfile, file->data + file->dataoff, SEEK_SET) == -1)
- goto fail2;
+ {
+ debug2("file seek failed: %s", strerror(errno));
+ goto error2; /* EBADF */
+ }
file->zlib.next_in = file->buffer;
- file->zlib.avail_in = fread(file->buffer, 1, seek - file->data,
+ file->zlib.avail_in = fread(file->buffer, 1, size,
file->entry->diskfile);
file->dataoff += file->zlib.avail_in;
____;
if (! zzip_file_header_data_deflated(&file->header)
|| inflateInit2(&file->zlib, -MAX_WBITS) != Z_OK)
- goto fail2;
+ {
+ debug1("decompress failed");
+ errno = EBADMSG;
+ goto error2;
+ }
return file;
- fail2:
+ error2:
free(file);
- fail1:
+ error1:
zzip_entry_free(entry);
return 0;
____;
@@ -592,7 +753,9 @@ zzip_entry_ffile(FILE * disk, char *filename)
{
ZZIP_ENTRY *entry = zzip_entry_findfile(disk, filename, 0, 0);
if (! entry)
- return 0;
+ {
+ return 0; /* EBADMSG */
+ }
return zzip_entry_fopen(entry, 1);
}
@@ -609,13 +772,21 @@ zzip_entry_fread(void *ptr, zzip_size_t sized, zzip_size_t nmemb,
ZZIP_ENTRY_FILE * file)
{
if (! file)
+ {
+ errno = EINVAL;
return 0;
+ }
___ zzip_size_t size = sized * nmemb;
if (! file->compressed)
{
if (size > file->avail)
size = file->avail;
- if (fread(ptr, 1, size, file->entry->diskfile) != size) return 0;
+ if (fread(ptr, 1, size, file->entry->diskfile) != size)
+ {
+ errno = ferror(file->entry->diskfile) ? EBADF : EIO;
+ debug2("uncompressed fread incomplete: %s", strerror(errno));
+ return 0;
+ }
file->dataoff += size;
file->avail -= size;
return size;
@@ -629,6 +800,7 @@ zzip_entry_fread(void *ptr, zzip_size_t sized, zzip_size_t nmemb,
if (! file->zlib.avail_in)
{
size = file->compressed - file->dataoff;
+ debug2("remaining compressed bytes: %lli", (long long)size);
if (size > sizeof(file->buffer))
size = sizeof(file->buffer);
/* fseek (file->data + file->dataoff, file->entry->diskfile); */
@@ -636,9 +808,13 @@ zzip_entry_fread(void *ptr, zzip_size_t sized, zzip_size_t nmemb,
file->entry->diskfile);
file->zlib.next_in = file->buffer;
file->dataoff += file->zlib.avail_in;
+ debug2("remaing compressed fread %lli", (long long) file->zlib.avail_in);
}
if (! file->zlib.avail_in)
+ {
+ errno = EIO;
return 0;
+ }
___ int err = inflate(&file->zlib, Z_NO_FLUSH);
if (err == Z_STREAM_END)
@@ -646,7 +822,11 @@ zzip_entry_fread(void *ptr, zzip_size_t sized, zzip_size_t nmemb,
else if (err == Z_OK)
file->avail -= file->zlib.total_out - total_old;
else
+ {
+ debug1("zlib decode incomplete");
+ errno = EBADMSG;
return 0;
+ }
____;
if (file->zlib.avail_out && ! file->zlib.avail_in)
continue;
@@ -664,7 +844,10 @@ int
zzip_entry_fclose(ZZIP_ENTRY_FILE * file)
{
if (! file)
- return 0;
+ {
+ errno = EINVAL;
+ return EOF;
+ }
if (file->compressed)
inflateEnd(&file->zlib);
zzip_entry_free(file->entry);