diff options
Diffstat (limited to 'Build/source/libs/zziplib/zziplib-0.13.62/zzip/zip.c')
-rw-r--r-- | Build/source/libs/zziplib/zziplib-0.13.62/zzip/zip.c | 870 |
1 files changed, 0 insertions, 870 deletions
diff --git a/Build/source/libs/zziplib/zziplib-0.13.62/zzip/zip.c b/Build/source/libs/zziplib/zziplib-0.13.62/zzip/zip.c deleted file mode 100644 index a4b06b47189..00000000000 --- a/Build/source/libs/zziplib/zziplib-0.13.62/zzip/zip.c +++ /dev/null @@ -1,870 +0,0 @@ - -/* - * Author: - * Guido Draheim <guidod@gmx.de> - * Tomi Ollila <too@iki.fi> - * - * Copyright (c) 1999,2000,2001,2002,2003 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 - */ - -#include <zzip/lib.h> /* archive handling */ -#include <zzip/file.h> -#include <zzip/format.h> -#include <zzip/fetch.h> - -#include <ctype.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#ifdef ZZIP_HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#include <zzip/__mmap.h> -#include <zzip/__debug.h> - -#define __sizeof(X) ((zzip_ssize_t)(sizeof(X))) - -#ifndef ZZIP_EASY -/* per default, we use a little hack to correct bad z_rootseek parts */ -#define ZZIP_CORRECT_ROOTSEEK 1 -#endif - -#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || (__GNUC__ >= 4) -# ifdef DEBUG -# warning suppress a warning where the compiler should have optimized instead. -# endif -#define _255 254 -#else -#define _255 255 -#endif - -#define ZZIP_DISK64_TRAILER 1 - -#ifdef ZZIP_DISK64_TRAILER -struct _disk_trailer -{ - void *zz_tail; - void *zz_for_correct_rootseek; // ZZIP_CORRECT_ROOTSEEK - zzip_off64_t zz_entries; - zzip_off64_t zz_finalentries; - zzip_off64_t zz_rootseek; - zzip_off64_t zz_rootsize; -}; -#define _disk_trailer_entries(__p) ((__p)->zz_entries) -#define _disk_trailer_localentries(__p) ((__p)->zz_entries) -#define _disk_trailer_finalentries(__p) ((__p)->zz_entries) -#define _disk_trailer_rootseek(__p) ((__p)->zz_rootseek) -#define _disk_trailer_rootsize(__p) ((__p)->zz_rootsize) -#define _disk_trailer_set_rootseek(__p,__v) ((__p)->rootseek = (__v)) - -#else -#define _disk_trailer zzip_disk_trailer -#define _disk_trailer_entries zzip_disk_trailer_entries -#define _disk_trailer_localentries zzip_disk_trailer_localentries -#define _disk_trailer_finalentries zzip_disk_trailer_finalentries -#define _disk_trailer_rootseek zzip_disk_trailer_rootseek -#define _disk_trailer_rootsize zzip_disk_trailer_rootsize -#define _disk_trailer_set_rootseek zzip_disk_trailer_set_rootseek -#define __zzip_fetch_disk_trailer __zzip_find_disk_trailer -#endif - -/* --------------------------- internals -------------------------------- */ - -/* internal functions of zziplib, avoid at all cost, changes w/o warning. - * we do export them for debugging purpose and special external tools - * which know what they do and which can adapt from version to version - */ - -int __zzip_fetch_disk_trailer(int fd, zzip_off_t filesize, - struct _disk_trailer *_zzip_restrict trailer, - zzip_plugin_io_t io); -int __zzip_parse_root_directory(int fd, - struct _disk_trailer *trailer, - struct zzip_dir_hdr **hdr_return, - zzip_plugin_io_t io); - -_zzip_inline static char *__zzip_aligned4(char *p); - -/* ------------------------ harden routines ------------------------------ */ - -#ifdef ZZIP_HARDEN - -/* - * check for inconsistent values in trailer and prefer lower seek value - * - we fix values assuming the root directory was written at the end - * and it is just before the zip trailer. Therefore, ... - */ -_zzip_inline static void -__fixup_rootseek(zzip_off_t offset_of_trailer, struct _disk_trailer *trailer) -{ - if (_disk_trailer_rootseek(trailer) > - offset_of_trailer - _disk_trailer_rootsize(trailer) && - offset_of_trailer > _disk_trailer_rootsize(trailer)) - { - register zzip_off_t offset; - offset = offset_of_trailer - _disk_trailer_rootsize(trailer); - _disk_trailer_set_rootseek(trailer, offset); - HINT2("new rootseek=%li", (long) _disk_trailer_rootseek(trailer)); - } -} - -#define __correct_rootseek(A,B,C) - -#elif defined ZZIP_CORRECT_ROOTSEEK - -/* store the seekvalue of the trailer into the "z_magic" field and with - * a 64bit off_t we overwrite z_disk/z_finaldisk as well. If you change - * anything in zziplib or dump the trailer structure then watch out that - * these are still unused, so that this code may still (ab)use those. */ -#define __fixup_rootseek(_offset_of_trailer, _trailer) \ - *(zzip_off_t*)_trailer = _offset_of_trailer; -#define __correct_rootseek( _u_rootseek, _u_rootsize, _trailer) \ - if (_u_rootseek > *(zzip_off_t*)_trailer - _u_rootsize) \ - _u_rootseek = *(zzip_off_t*)_trailer - _u_rootsize; -#else -#define __fixup_rootseek(A,B) -#define __correct_rootseek(A,B,C) -#endif - - -#ifdef DEBUG -_zzip_inline static void -__debug_dir_hdr(struct zzip_dir_hdr *hdr) -{ - if (sizeof(struct zzip_dir_hdr) > sizeof(struct zzip_disk_entry)) - { WARN1("internal sizeof-mismatch may break wreakage"); } - /* the internal directory structure is never bigger than the - * external zip central directory space had been beforehand - * (as long as the following assertion holds...) - */ - - if (((zzip_off_t) hdr) & 3) - { - NOTE1("this machine's malloc(3) returns sth. not u32-aligned"); - } - /* we assume that if this machine's malloc has returned a non-aligned - * memory block, then it is actually safe to access misaligned data, and - * since it does only affect the first hdr it should not even bring about - * too much of that cpu's speed penalty - */ -} -#else -#define __debug_dir_hdr(X) -#endif - -/* -------------------------- low-level interface -------------------------- */ - -#if defined BUFSIZ -#if BUFSIZ == 1024 || BUFSIZ == 512 || BUFSIZ == 256 -#define ZZIP_BUFSIZ BUFSIZ -#endif -#endif - -#ifndef ZZIP_BUFSIZ -#define ZZIP_BUFSIZ 512 - -/* #define ZZIP_BUFSIZ 64 / * for testing */ -#endif - -/** - * This function is used by => zzip_file_open. It tries to find - * the zip's central directory info that is usually a few - * bytes off the end of the file. - */ -int -__zzip_fetch_disk_trailer(int fd, zzip_off_t filesize, - struct _disk_trailer *_zzip_restrict trailer, - zzip_plugin_io_t io) -{ -#ifdef DEBUG -#define return(val) { e=val; HINT2("%s", zzip_strerror(e)); goto cleanup; } -#else -#define return(val) { e=val; goto cleanup; } -#endif - register int e; - -#ifndef _LOWSTK - auto char buffer[2 * ZZIP_BUFSIZ]; - char *buf = buffer; -#else - char *buf = malloc(2 * ZZIP_BUFSIZ); -#endif - zzip_off_t offset = 0; - zzip_ssize_t maplen = 0; /* mmap(),read(),getpagesize() use size_t !! */ - char *fd_map = 0; - - if (! trailer) - { return(EINVAL); } - - if (filesize < __sizeof(struct zzip_disk_trailer)) - { return(ZZIP_DIR_TOO_SHORT); } - - if (! buf) - { return(ZZIP_OUTOFMEM); } - - offset = filesize; /* a.k.a. old offset */ - while (1) /* outer loop */ - { - register unsigned char *mapped; - - if (offset <= 0) - { return(ZZIP_DIR_EDH_MISSING); } - - /* trailer cannot be farther away than 64K from fileend */ - if (filesize - offset > 64 * 1024) - { return(ZZIP_DIR_EDH_MISSING); } - - /* the new offset shall overlap with the area after the old offset! */ - if (USE_MMAP && io->fd.sys) - { - zzip_off_t mapoff = offset; - { - zzip_ssize_t pagesize = _zzip_getpagesize(io->fd.sys); - if (pagesize < ZZIP_BUFSIZ) - goto non_mmap; /* an error? */ - if (mapoff == filesize && filesize > pagesize) - mapoff -= pagesize; - if (mapoff < pagesize) - { - maplen = (zzip_ssize_t) mapoff + pagesize; - mapoff = 0; - } else - { - mapoff -= pagesize; - maplen = 2 * pagesize; - if ((zzip_ssize_t) mapoff & (pagesize - 1)) - { /*only 1. run */ - pagesize -= (zzip_ssize_t) mapoff & (pagesize - 1); - mapoff += pagesize; - maplen -= pagesize; - } - } - if (mapoff + maplen > filesize) - maplen = filesize - mapoff; - } - - fd_map = _zzip_mmap(io->fd.sys, fd, mapoff, (zzip_size_t) maplen); - if (fd_map == MAP_FAILED) - goto non_mmap; - mapped = (unsigned char *) fd_map; - offset = mapoff; /* success */ - HINT3("mapped *%p len=%li", fd_map, (long) maplen); - } else - { - non_mmap: - fd_map = 0; /* have no mmap */ - { - zzip_off_t pagesize = ZZIP_BUFSIZ; - if (offset == filesize && filesize > pagesize) - offset -= pagesize; - if (offset < pagesize) - { - maplen = (zzip_ssize_t) offset + pagesize; - offset = 0; - } else - { - offset -= pagesize; - maplen = 2 * pagesize; - if ((zzip_ssize_t) offset & (pagesize - 1)) - { /*on 1st run */ - pagesize -= (zzip_ssize_t) offset & (pagesize - 1); - offset += pagesize; - maplen -= pagesize; - } - } - if (offset + maplen > filesize) - maplen = filesize - offset; - } - - if (io->fd.seeks(fd, offset, SEEK_SET) < 0) - { return(ZZIP_DIR_SEEK); } - if (io->fd.read(fd, buf, (zzip_size_t) maplen) < maplen) - { return(ZZIP_DIR_READ); } - mapped = (unsigned char *) buf; /* success */ - HINT5("offs=$%lx len=%li filesize=%li pagesize=%i", - (long) offset, (long) maplen, (long) filesize, ZZIP_BUFSIZ); - } - - { /* now, check for the trailer-magic, hopefully near the end of file */ - register unsigned char *end = mapped + maplen; - register unsigned char *tail; - for (tail = end - 1; (tail >= mapped); tail--) - { - if ((*tail == 'P') && /* quick pre-check for trailer magic */ - end - tail >= __sizeof(struct zzip_disk_trailer) - 2 && - zzip_disk_trailer_check_magic(tail)) - { -# ifndef ZZIP_DISK64_TRAILER - /* if the file-comment is not present, it happens - that the z_comment field often isn't either */ - if (end - tail >= __sizeof(*trailer)) - { - memcpy(trailer, tail, sizeof(*trailer)); - } else - { - memcpy(trailer, tail, sizeof(*trailer) - 2); - trailer->z_comment[0] = 0; - trailer->z_comment[1] = 0; - } -# else - struct zzip_disk_trailer *orig = - (struct zzip_disk_trailer *) tail; - trailer->zz_tail = tail; - trailer->zz_entries = zzip_disk_trailer_localentries(orig); - trailer->zz_finalentries = - zzip_disk_trailer_finalentries(orig); - trailer->zz_rootseek = zzip_disk_trailer_rootseek(orig); - trailer->zz_rootsize = zzip_disk_trailer_rootsize(orig); -# endif - - __fixup_rootseek(offset + tail - mapped, trailer); - { return(0); } - } else if ((*tail == 'P') && - end - tail >= - __sizeof(struct zzip_disk64_trailer) - 2 - && zzip_disk64_trailer_check_magic(tail)) - { -# ifndef ZZIP_DISK64_TRAILER - return (ZZIP_DIR_LARGEFILE); -# else - struct zzip_disk64_trailer *orig = - (struct zzip_disk64_trailer *) tail; - trailer->zz_tail = tail; - trailer->zz_entries = - zzip_disk64_trailer_localentries(orig); - trailer->zz_finalentries = - zzip_disk64_trailer_finalentries(orig); - trailer->zz_rootseek = zzip_disk64_trailer_rootseek(orig); - trailer->zz_rootsize = zzip_disk64_trailer_rootsize(orig); - { return(0); } -# endif - } - } - } - - if (USE_MMAP && fd_map) - { - HINT3("unmap *%p len=%li", fd_map, (long) maplen); - _zzip_munmap(io->fd.sys, fd_map, (zzip_size_t) maplen); - fd_map = 0; - } - } /*outer loop */ - - cleanup: - if (USE_MMAP && fd_map) - { - HINT3("unmap *%p len=%li", fd_map, (long) maplen); - _zzip_munmap(io->fd.sys, fd_map, (zzip_size_t) maplen); - } -# ifdef _LOWSTK - free(buf); -# endif -# undef return - return e; -} - -/* - * making pointer alignments to values that can be handled as structures - * is tricky. We assume here that an align(4) is sufficient even for - * 64 bit machines. Note that binary operations are not usually allowed - * to pointer types but we can cast the value to a suitably sized integer. - */ -_zzip_inline static char * -__zzip_aligned4(char *p) -{ -#define aligned4 __zzip_aligned4 -#ifdef _WIN64 - p += ((__int64) p) & 1; - p += ((__int64) p) & 2; -#else - p += ((long) p) & 1; - p += ((long) p) & 2; -#endif - return p; -} - -/** - * This function is used by => zzip_file_open, it is usually called after - * => __zzip_find_disk_trailer. It will parse the zip's central directory - * information and create a zziplib private directory table in - * memory. - */ -int -__zzip_parse_root_directory(int fd, - struct _disk_trailer *trailer, - struct zzip_dir_hdr **hdr_return, - zzip_plugin_io_t io) -{ - auto struct zzip_disk_entry dirent; - struct zzip_dir_hdr *hdr; - struct zzip_dir_hdr *hdr0; - uint16_t *p_reclen = 0; - zzip_off64_t entries; - zzip_off64_t zz_offset; /* offset from start of root directory */ - char *fd_map = 0; - zzip_off64_t zz_fd_gap = 0; - zzip_off64_t zz_entries = _disk_trailer_localentries(trailer); - zzip_off64_t zz_rootsize = _disk_trailer_rootsize(trailer); - zzip_off64_t zz_rootseek = _disk_trailer_rootseek(trailer); - __correct_rootseek(zz_rootseek, zz_rootsize, trailer); - - hdr0 = (struct zzip_dir_hdr *) malloc(zz_rootsize); - if (! hdr0) - return ZZIP_DIRSIZE; - hdr = hdr0; - __debug_dir_hdr(hdr); - - if (USE_MMAP && io->fd.sys) - { - zz_fd_gap = zz_rootseek & (_zzip_getpagesize(io->fd.sys) - 1); - HINT4(" fd_gap=%ld, mapseek=0x%lx, maplen=%ld", (long) (zz_fd_gap), - (long) (zz_rootseek - zz_fd_gap), - (long) (zz_rootsize + zz_fd_gap)); - fd_map = - _zzip_mmap(io->fd.sys, fd, zz_rootseek - zz_fd_gap, - zz_rootsize + zz_fd_gap); - /* if mmap failed we will fallback to seek/read mode */ - if (fd_map == MAP_FAILED) - { - NOTE2("map failed: %s", strerror(errno)); - fd_map = 0; - } else - { - HINT3("mapped *%p len=%li", fd_map, - (long) (zz_rootsize + zz_fd_gap)); - } - } - - for (entries=0, zz_offset=0; ; entries++) - { - register struct zzip_disk_entry *d; - uint16_t u_extras, u_comment, u_namlen; - -# ifndef ZZIP_ALLOW_MODULO_ENTRIES - if (entries >= zz_entries) { - if (zz_offset + 256 < zz_rootsize) { - FAIL4("%li's entry is long before the end of directory - enable modulo_entries? (O:%li R:%li)", - (long) entries, (long) (zz_offset), (long) zz_rootsize); - } - break; - } -# endif - - if (fd_map) - { d = (void*)(fd_map+zz_fd_gap+zz_offset); } /* fd_map+fd_gap==u_rootseek */ - else - { - if (io->fd.seeks(fd, zz_rootseek + zz_offset, SEEK_SET) < 0) - return ZZIP_DIR_SEEK; - if (io->fd.read(fd, &dirent, sizeof(dirent)) < __sizeof(dirent)) - return ZZIP_DIR_READ; - d = &dirent; - } - - if ((zzip_off64_t) (zz_offset + sizeof(*d)) > zz_rootsize || - (zzip_off64_t) (zz_offset + sizeof(*d)) < 0) - { - FAIL4("%li's entry stretches beyond root directory (O:%li R:%li)", - (long) entries, (long) (zz_offset), (long) zz_rootsize); - break; - } - - if (! zzip_disk_entry_check_magic(d)) { -# ifndef ZZIP_ALLOW_MODULO_ENTRIES - FAIL4("%li's entry has no disk_entry magic indicator (O:%li R:%li)", - (long) entries, (long) (zz_offset), (long) zz_rootsize); -# endif - break; - } - -# if 0 && defined DEBUG - zzip_debug_xbuf((unsigned char *) d, sizeof(*d) + 8); -# endif - - u_extras = zzip_disk_entry_get_extras(d); - u_comment = zzip_disk_entry_get_comment(d); - u_namlen = zzip_disk_entry_get_namlen(d); - HINT5("offset=0x%lx, size %ld, dirent *%p, hdr %p\n", - (long) (zz_offset + zz_rootseek), (long) zz_rootsize, d, hdr); - - /* writes over the read buffer, Since the structure where data is - copied is smaller than the data in buffer this can be done. - It is important that the order of setting the fields is considered - when filling the structure, so that some data is not trashed in - first structure read. - at the end the whole copied list of structures is copied into - newly allocated buffer */ - hdr->d_crc32 = zzip_disk_entry_get_crc32(d); - hdr->d_csize = zzip_disk_entry_get_csize(d); - hdr->d_usize = zzip_disk_entry_get_usize(d); - hdr->d_off = zzip_disk_entry_get_offset(d); - hdr->d_compr = zzip_disk_entry_get_compr(d); - if (hdr->d_compr > _255) - hdr->d_compr = 255; - - if ((zzip_off64_t) (zz_offset + sizeof(*d) + u_namlen) > zz_rootsize || - (zzip_off64_t) (zz_offset + sizeof(*d) + u_namlen) < 0) - { - FAIL4("%li's name stretches beyond root directory (O:%li N:%li)", - (long) entries, (long) (zz_offset), (long) (u_namlen)); - break; - } - - if (fd_map) - { memcpy(hdr->d_name, fd_map+zz_fd_gap + zz_offset+sizeof(*d), u_namlen); } - else - { io->fd.read(fd, hdr->d_name, u_namlen); } - hdr->d_name[u_namlen] = '\0'; - hdr->d_namlen = u_namlen; - - /* update offset by the total length of this entry -> next entry */ - zz_offset += sizeof(*d) + u_namlen + u_extras + u_comment; - - if (zz_offset > zz_rootsize) - { - FAIL3("%li's entry stretches beyond root directory (O:%li)", - (long) entries, (long) (zz_offset)); - entries ++; - break; - } - - HINT5("file %ld { compr=%d crc32=$%x offset=%d", - (long) entries, hdr->d_compr, hdr->d_crc32, hdr->d_off); - HINT5("csize=%d usize=%d namlen=%d extras=%d", - hdr->d_csize, hdr->d_usize, u_namlen, u_extras); - HINT5("comment=%d name='%s' %s <sizeof %d> } ", - u_comment, hdr->d_name, "", (int) sizeof(*d)); - - p_reclen = &hdr->d_reclen; - - { - register char *p = (char *) hdr; - register char *q = aligned4(p + sizeof(*hdr) + u_namlen + 1); - *p_reclen = (uint16_t) (q - p); - hdr = (struct zzip_dir_hdr *) q; - } - } /*for */ - - if (USE_MMAP && fd_map) - { - HINT3("unmap *%p len=%li", fd_map, (long) (zz_rootsize + zz_fd_gap)); - _zzip_munmap(io->fd.sys, fd_map, zz_rootsize + zz_fd_gap); - } - - if (p_reclen) - { - *p_reclen = 0; /* mark end of list */ - - if (hdr_return) - *hdr_return = hdr0; - } /* else zero (sane) entries */ -# ifndef ZZIP_ALLOW_MODULO_ENTRIES - return (entries != zz_entries ? ZZIP_CORRUPTED : 0); -# else - return ((entries & (unsigned)0xFFFF) != zz_entries ? ZZIP_CORRUPTED : 0); -# endif -} - -/* ------------------------- high-level interface ------------------------- */ - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -static zzip_strings_t * -zzip_get_default_ext(void) -{ - static zzip_strings_t ext[] = { - /* *INDENT-OFF* */ - ".zip", ".ZIP", /* common extension */ -# ifdef ZZIP_USE_ZIPLIKES - ".pk3", ".PK3", /* ID Software's Quake3 zipfiles */ - ".jar", ".JAR", /* Java zipfiles */ -# endif - /* *INDENT-ON* */ - 0 - }; - - return ext; -} - -/** - * allocate a new ZZIP_DIR handle and do basic - * initializations before usage by => zzip_dir_fdopen - * => zzip_dir_open => zzip_file_open or through - * => zzip_open - * (ext==null flags uses { ".zip" , ".ZIP" } ) - * (io ==null flags use of posix io defaults) - */ -ZZIP_DIR * -zzip_dir_alloc_ext_io(zzip_strings_t * ext, const zzip_plugin_io_t io) -{ - ZZIP_DIR *dir; - if ((dir = (ZZIP_DIR *) calloc(1, sizeof(*dir))) == NULL) - return 0; - - /* dir->fileext is currently unused - so what, still initialize it */ - dir->fileext = ext ? ext : zzip_get_default_ext(); - dir->io = io ? io : zzip_get_default_io(); - return dir; -} - -/** => zzip_dir_alloc_ext_io - * this function is obsolete - it was generally used for implementation - * and exported to let other code build on it. It is now advised to - * use => zzip_dir_alloc_ext_io now on explicitly, just set that second - * argument to zero to achieve the same functionality as the old style. - */ -ZZIP_DIR * -zzip_dir_alloc(zzip_strings_t * fileext) -{ - return zzip_dir_alloc_ext_io(fileext, 0); -} - -/** - * will free the zzip_dir handle unless there are still - * zzip_files attached (that may use its cache buffer). - * This is the inverse of => zzip_dir_alloc , and both - * are helper functions used implicitly in other zzipcalls - * e.g. => zzip_dir_close = zzip_close - * - * returns zero on sucess - * returns the refcount when files are attached. - */ -int -zzip_dir_free(ZZIP_DIR * dir) -{ - if (dir->refcount) - return (dir->refcount); /* still open files attached */ - - if (dir->fd >= 0) - dir->io->fd.close(dir->fd); - if (dir->hdr0) - free(dir->hdr0); - if (dir->cache.fp) - free(dir->cache.fp); - if (dir->cache.buf32k) - free(dir->cache.buf32k); - if (dir->realname) - free(dir->realname); - free(dir); - return 0; -} - -/** => zzip_dir_free - * It will also => free(2) the => ZZIP_DIR-handle given. - * the counterpart for => zzip_dir_open - * see also => zzip_dir_free - */ -int -zzip_dir_close(ZZIP_DIR * dir) -{ - dir->refcount &= ~0x10000000; /* explicit dir close */ - return zzip_dir_free(dir); -} - -/** - * used by the => zzip_dir_open and zzip_opendir(2) call. Opens the - * zip-archive as specified with the fd which points to an - * already openend file. This function then search and parse - * the zip's central directory. - * - * NOTE: refcount is zero, so an _open/_close pair will also delete - * this _dirhandle - */ -ZZIP_DIR * -zzip_dir_fdopen(int fd, zzip_error_t * errcode_p) -{ - return zzip_dir_fdopen_ext_io(fd, errcode_p, 0, 0); -} - -static zzip_error_t __zzip_dir_parse(ZZIP_DIR * dir); /* forward */ - -/** => zzip_dir_fdopen - * this function uses explicit ext and io instead of the internal - * defaults, setting these to zero is equivalent to => zzip_dir_fdopen - */ -ZZIP_DIR * -zzip_dir_fdopen_ext_io(int fd, zzip_error_t * errcode_p, - zzip_strings_t * ext, const zzip_plugin_io_t io) -{ - zzip_error_t rv; - ZZIP_DIR *dir; - - if ((dir = zzip_dir_alloc_ext_io(ext, io)) == NULL) - { rv = ZZIP_OUTOFMEM; goto error; } - - dir->fd = fd; - if ((rv = __zzip_dir_parse(dir))) - goto error; - - dir->hdr = dir->hdr0; - dir->refcount |= 0x10000000; - - if (errcode_p) - *errcode_p = rv; - return dir; - error: - if (dir) - zzip_dir_free(dir); - if (errcode_p) - *errcode_p = rv; - return NULL; -} - -static zzip_error_t -__zzip_dir_parse(ZZIP_DIR * dir) -{ - zzip_error_t rv; - zzip_off_t filesize; - struct _disk_trailer trailer; - /* if (! dir || dir->fd < 0) - * { rv = EINVAL; goto error; } - */ - - HINT2("------------------ fd=%i", (int) dir->fd); - if ((filesize = dir->io->fd.filesize(dir->fd)) < 0) - { rv = ZZIP_DIR_STAT; goto error; } - - HINT2("------------------ filesize=%ld", (long) filesize); - if ((rv = __zzip_fetch_disk_trailer(dir->fd, filesize, &trailer, - dir->io)) != 0) - { goto error; } - - HINT5("directory = { entries= %ld/%ld, size= %ld, seek= %ld } ", - (long) _disk_trailer_localentries(&trailer), - (long) _disk_trailer_finalentries(&trailer), - (long) _disk_trailer_rootsize(&trailer), - (long) _disk_trailer_rootseek(&trailer)); - - if ((rv = __zzip_parse_root_directory(dir->fd, &trailer, &dir->hdr0, - dir->io)) != 0) - { goto error; } - error: - return rv; -} - -/** - * This function will attach any of the .zip extensions then - * trying to open it the with => open(2). This is a helper - * function for => zzip_dir_open, => zzip_opendir and => zzip_open. - * - * This function returns a new system file handle or -1 on error. - * On error this function leaves the errno(3) of the underlying - * open(2) call on the last file. - */ -int -__zzip_try_open(zzip_char_t * filename, int filemode, - zzip_strings_t * ext, zzip_plugin_io_t io) -{ - auto char file[PATH_MAX]; - int fd; - zzip_size_t len = strlen(filename); - - if (len + 4 >= PATH_MAX) - { errno = ENAMETOOLONG; return -1; } - memcpy(file, filename, len + 1); - - if (! io) - io = zzip_get_default_io(); - if (! ext) - ext = zzip_get_default_ext(); - - for (; *ext; ++ext) - { - strcpy(file + len, *ext); - fd = (io->fd.open)(file, filemode); - if (fd != -1) - return fd; - } - return -1; -} - -/** - * Opens the zip-archive (if available). - * the two ext_io arguments will default to use posix io and - * a set of default fileext that can atleast add .zip ext itself. - */ -ZZIP_DIR * -zzip_dir_open(zzip_char_t * filename, zzip_error_t * e) -{ - return zzip_dir_open_ext_io(filename, e, 0, 0); -} - -/** => zzip_dir_open - * this function uses explicit ext and io instead of the internal - * defaults. Setting these to zero is equivalent to => zzip_dir_open - * Note that the referenced ext_io plugin handlers structure must be - * static as it is not copied to the returned ZZIP_DIR structure. - */ -ZZIP_DIR * -zzip_dir_open_ext_io(zzip_char_t * filename, zzip_error_t * e, - zzip_strings_t * ext, zzip_plugin_io_t io) -{ - int fd; - - if (! io) - io = zzip_get_default_io(); - if (! ext) - ext = zzip_get_default_ext(); - - fd = (io->fd.open)(filename, O_RDONLY | O_BINARY); - if (fd != -1) - { - return zzip_dir_fdopen_ext_io(fd, e, ext, io); - } else - { - fd = __zzip_try_open(filename, O_RDONLY | O_BINARY, ext, io); - if (fd != -1) - { - return zzip_dir_fdopen_ext_io(fd, e, ext, io); - } else - { - if (e) - { *e = ZZIP_DIR_OPEN; } - return 0; - } - } -} - -/** => zzip_dir_open - * fills the dirent-argument with the values and - * increments the read-pointer of the dir-argument. - * - * returns 0 if there no entry (anymore). - */ -int -zzip_dir_read(ZZIP_DIR * dir, ZZIP_DIRENT * d) -{ - if (! dir || ! dir->hdr || ! d) - return 0; - - d->d_compr = dir->hdr->d_compr; - d->d_csize = dir->hdr->d_csize; - d->st_size = dir->hdr->d_usize; - d->d_name = dir->hdr->d_name; - - if (! dir->hdr->d_reclen) - { - dir->hdr = 0; - } else - { - dir->hdr = (struct zzip_dir_hdr *) - ((char *) dir->hdr + dir->hdr->d_reclen); - } - - return 1; -} - -/* - * Local variables: - * c-file-style: "stroustrup" - * End: - */ |