diff options
Diffstat (limited to 'Build/source/libs/zziplib/zziplib-0.13.62/zzip/mmapped.c')
-rw-r--r-- | Build/source/libs/zziplib/zziplib-0.13.62/zzip/mmapped.c | 646 |
1 files changed, 0 insertions, 646 deletions
diff --git a/Build/source/libs/zziplib/zziplib-0.13.62/zzip/mmapped.c b/Build/source/libs/zziplib/zziplib-0.13.62/zzip/mmapped.c deleted file mode 100644 index 6fafc1163a6..00000000000 --- a/Build/source/libs/zziplib/zziplib-0.13.62/zzip/mmapped.c +++ /dev/null @@ -1,646 +0,0 @@ - -/* - * NOTE: this is part of libzzipmmapped (i.e. it is not libzzip). - * ================== - * - * These routines are fully independent from the traditional zzip - * implementation. They assume a readonly mmapped sharedmem block - * representing a complete zip file. The functions show how to - * parse the structure, find files and return a decoded bytestream. - * - * These routines are a bit simple and really here for documenting - * the way to access a zip file. The complexity of zip access comes - * from staggered reading of bytes and reposition of a filepointer in - * a big archive with lots of files and long compressed datastreams. - * Plus varaints of drop-in stdio replacements, obfuscation routines, - * auto fileextensions, drop-in dirent replacements, and so on... - * - * Author: - * Guido Draheim <guidod@gmx.de> - * - * Copyright (c) 2003,2004,2006 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 - */ - -#define _ZZIP_DISK_FILE_STRUCT 1 - -#ifdef __linux__ -#define _GNU_SOURCE _glibc_developers_are_idiots_to_call_strndup_gnu_specific_ -#endif - -#include <zzip/mmapped.h> -#include <zzip/format.h> -#include <zzip/fetch.h> -#include <zzip/__mmap.h> -#include <zzip/__fnmatch.h> - -#include <stdlib.h> -#include <sys/stat.h> - -#if defined ZZIP_HAVE_UNISTD_H -#include <unistd.h> -#elif defined ZZIP_HAVE_IO_H -#include <io.h> -#endif - -#if defined ZZIP_HAVE_STRING_H -#include <string.h> -#elif defined ZZIP_HAVE_STRINGS_H -#include <strings.h> -#endif - - -#if __STDC_VERSION__+0 > 199900L -#define ___ -#define ____ -#else -#define ___ { -#define ____ } -#endif - -/** => zzip_disk_mmap - * This function does primary initialization of a disk-buffer struct. - */ -int -zzip_disk_init(ZZIP_DISK * disk, void *buffer, zzip_size_t buflen) -{ - disk->buffer = (zzip_byte_t *) buffer; - disk->endbuf = (zzip_byte_t *) buffer + buflen; - disk->reserved = 0; - disk->flags = 0; - disk->mapped = 0; - /* do not touch disk->user */ - /* do not touch disk->code */ - return 0; -} - -/** => zzip_disk_mmap - * This function allocates a new disk-buffer with => malloc(3) - */ -zzip__new__ ZZIP_DISK * -zzip_disk_new(void) -{ - ZZIP_DISK *disk = malloc(sizeof(ZZIP_DISK)); - if (! disk) - return disk; - zzip_disk_init(disk, 0, 0); - return disk; -} - -/** turn a filehandle into a mmapped zip disk archive handle - * - * This function uses the given file-descriptor to detect the length of the - * file and calls the system => mmap(2) to put it in main memory. If it is - * successful then a newly allocated ZZIP_DISK* is returned with - * disk->buffer pointing to the mapview of the zipdisk content. - */ -zzip__new__ ZZIP_DISK * -zzip_disk_mmap(int fd) -{ - struct stat st; - if (fstat(fd, &st) || ! st.st_size) - return 0; - ___ ZZIP_DISK *disk = zzip_disk_new(); - if (! disk) - return 0; - disk->buffer = _zzip_mmap(disk->mapped, fd, 0, st.st_size); - if (disk->buffer == MAP_FAILED) - { free (disk); return 0; } - disk->endbuf = disk->buffer + st.st_size; - return disk; - ____; -} - -/** => zzip_disk_mmap - * This function is the inverse of => zzip_disk_mmap and using the system - * munmap(2) on the buffer area and => free(3) on the ZZIP_DISK structure. - */ -int -zzip_disk_munmap(ZZIP_DISK * disk) -{ - if (! disk) - return 0; - _zzip_munmap(disk->mapped, disk->buffer, disk->endbuf - disk->buffer); - free(disk); - return 0; -} - -/** => zzip_disk_mmap - * - * This function opens the given archive by name and turn the filehandle - * to => zzip_disk_mmap for bringing it to main memory. If it can not - * be => mmap(2)'ed then we slurp the whole file into a newly => malloc(2)'ed - * memory block. Only if that fails too then we return null. Since handling - * of disk->buffer is ambigous it should not be snatched away please. - */ -zzip__new__ ZZIP_DISK * -zzip_disk_open(char *filename) -{ -# ifndef O_BINARY -# define O_BINARY 0 -# endif - struct stat st; - if (stat(filename, &st) || ! st.st_size) - return 0; - ___ int fd = open(filename, O_RDONLY | O_BINARY); - if (fd <= 0) - return 0; - ___ ZZIP_DISK *disk = zzip_disk_mmap(fd); - if (disk) - return disk; - ___ zzip_byte_t *buffer = malloc(st.st_size); - if (! buffer) - return 0; - if ((st.st_size == read(fd, buffer, st.st_size)) && - (disk = zzip_disk_new())) - { - disk->buffer = buffer; - disk->endbuf = buffer + st.st_size; - disk->mapped = -1; - disk->flags |= ZZIP_DISK_FLAGS_OWNED_BUFFER; - } else { - free(buffer); - } - return disk; - ____; - ____; - ____; -} - -/** => zzip_disk_mmap - * This function will attach a buffer with a zip image - * that was acquired from another source than a file. - * Note that if zzip_disk_mmap fails then zzip_disk_open - * will fall back and try to read the full file to memory - * wrapping a ZZIP_DISK around the memory buffer just as - * this function will do. Note that this function will not - * own the buffer, it will neither be written nor free()d. - */ -zzip__new__ ZZIP_DISK * -zzip_disk_buffer(void *buffer, size_t buflen) { - ZZIP_DISK *disk = zzip_disk_new(); - if (disk) - { - disk->buffer = (zzip_byte_t *) buffer; - disk->endbuf = (zzip_byte_t *) buffer + buflen; - disk->mapped = -1; - } - return disk; -} - -/** => zzip_disk_mmap - * - * This function will release all data needed to access a (mmapped) - * zip archive, including any malloc()ed blocks, sharedmem mappings - * and it dumps the handle struct as well. - */ -int -zzip_disk_close(ZZIP_DISK * disk) -{ - if (! disk) - return 0; - if (disk->mapped != -1) - return zzip_disk_munmap(disk); - if (disk->flags & ZZIP_DISK_FLAGS_OWNED_BUFFER) - free(disk->buffer); - free(disk); - return 0; -} - -/* ====================================================================== */ - -/* helper functions */ - -#ifdef ZZIP_HAVE_STRNDUP -#define _zzip_strndup strndup -#else - -/* if your system does not have strndup: */ -zzip__new__ static char * -_zzip_strndup(char *p, size_t maxlen) -{ - if (! p) - return 0; - ___ zzip_byte_t *r = malloc(maxlen + 1); - if (! r) - return r; - strncpy(r, p, maxlen); - r[maxlen] = '\0'; - return r; - ____; -} -#endif - -#if defined ZZIP_HAVE_STRCASECMP || defined strcasecmp -#define _zzip_strcasecmp strcasecmp -#else - -/* if your system does not have strcasecmp: */ -static int -_zzip_strcasecmp(char *__zzip_restrict a, char *_zzip_restrict b) -{ - if (! a) - return (b) ? 1 : 0; - if (! b) - return -1; - while (1) - { - int v = tolower(*a) - tolower(*b); - if (v) - return v; - if (! *a) - return 1; - if (! *b) - return -1; - a++; - b++; - } -} -#endif - -/** helper functions for (mmapped) zip access api - * - * This function augments the other zzip_disk_entry_* helpers: here we move - * a disk_entry pointer (as returned by _find* functions) into a pointer to - * the data block right after the file_header. Only disk->buffer would be - * needed to perform the seek but we check the mmapped range end as well. - */ -zzip_byte_t * -zzip_disk_entry_to_data(ZZIP_DISK * disk, struct zzip_disk_entry * entry) -{ - struct zzip_file_header *file = zzip_disk_entry_to_file_header(disk, entry); - if (file) - return zzip_file_header_to_data(file); - return 0; -} - -/** => zzip_disk_entry_to_data - * This function does half the job of => zzip_disk_entry_to_data where it - * can augment with => zzip_file_header_to_data helper from format/fetch.h - */ -struct zzip_file_header * -zzip_disk_entry_to_file_header(ZZIP_DISK * disk, struct zzip_disk_entry *entry) -{ - zzip_byte_t *file_header = /* (struct zzip_file_header*) */ - (disk->buffer + zzip_disk_entry_fileoffset(entry)); - if (disk->buffer > file_header || file_header >= disk->endbuf) - return 0; - return (struct zzip_file_header *) file_header; -} - -/** => zzip_disk_entry_to_data - * This function is a big helper despite its little name: in a zip file the - * encoded filenames are usually NOT zero-terminated but for common usage - * 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. - */ -zzip__new__ char * -zzip_disk_entry_strdup_name(ZZIP_DISK * disk, struct zzip_disk_entry *entry) -{ - if (! disk || ! entry) - return 0; - - ___ char *name; - zzip_size_t len; - struct zzip_file_header *file; - if ((len = zzip_disk_entry_namlen(entry))) - name = zzip_disk_entry_to_filename(entry); - else if ((file = zzip_disk_entry_to_file_header(disk, entry)) && - (len = zzip_file_header_namlen(file))) - name = zzip_file_header_to_filename(file); - else - return 0; - - if ((zzip_byte_t *) name < disk->buffer || - (zzip_byte_t *) name + len > disk->endbuf) - return 0; - - return _zzip_strndup(name, len); - ____; -} - -/** => zzip_disk_entry_to_data - * This function is similar creating a reference to a zero terminated - * string but it can only exist in the zip central directory entry. - */ -zzip__new__ char * -zzip_disk_entry_strdup_comment(ZZIP_DISK * disk, struct zzip_disk_entry *entry) -{ - if (! disk || ! entry) - return 0; - - ___ char *text; - zzip_size_t len; - if ((len = zzip_disk_entry_comment(entry))) - text = zzip_disk_entry_to_comment(entry); - else - return 0; - - if ((zzip_byte_t *) text < disk->buffer || - (zzip_byte_t *) text + len > disk->endbuf) - return 0; - - return _zzip_strndup(text, len); - ____; -} - -/* ====================================================================== */ - -/** => zzip_disk_findfile - * - * This function is the first call of all the zip access functions here. - * It contains the code to find the first entry of the zip central directory. - * Here we require the mmapped block to represent a real zip file where the - * disk_trailer is _last_ in the file area, so that its position would be at - * a fixed offset from the end of the file area if not for the comment field - * allowed to be of variable length (which needs us to do a little search - * for the disk_tailer). However, in this simple implementation we disregard - * any disk_trailer info telling about multidisk archives, so we just return - * a pointer to the zip central directory. - * - * For an actual means, we are going to search backwards from the end - * of the mmaped block looking for the PK-magic signature of a - * disk_trailer. If we see one then we check the rootseek value to - * find the first disk_entry of the root central directory. If we find - * the correct PK-magic signature of a disk_entry over there then we - * assume we are done and we are going to return a pointer to that label. - * - * The return value is a pointer to the first zzip_disk_entry being checked - * to be within the bounds of the file area specified by the arguments. If - * no disk_trailer was found then null is returned, and likewise we only - * accept a disk_trailer with a seekvalue that points to a disk_entry and - * 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. - */ -struct zzip_disk_entry * -zzip_disk_findfirst(ZZIP_DISK * disk) -{ - if (disk->buffer > disk->endbuf - sizeof(struct zzip_disk_trailer)) - return 0; - ___ zzip_byte_t *p = disk->endbuf - sizeof(struct zzip_disk_trailer); - for (; p >= disk->buffer; p--) - { - zzip_byte_t *root; /* (struct zzip_disk_entry*) */ - if (zzip_disk_trailer_check_magic(p)) - { - struct zzip_disk_trailer *trailer = (struct zzip_disk_trailer *) p; - root = disk->buffer + zzip_disk_trailer_get_rootseek(trailer); - if (root > p) - { - /* the first disk_entry is after the disk_trailer? can't be! */ - zzip_size_t rootsize = zzip_disk_trailer_get_rootsize(trailer); - if (disk->buffer + rootsize > p) - continue; - /* a common brokeness that can be fixed: we just assume the - * central directory was written directly before the trailer:*/ - root = p - rootsize; - } - } else if (zzip_disk64_trailer_check_magic(p)) - { - struct zzip_disk64_trailer *trailer = - (struct zzip_disk64_trailer *) p; - if (sizeof(void *) < 8) - return 0; /* EOVERFLOW */ - root = disk->buffer + zzip_disk64_trailer_get_rootseek(trailer); - if (root > p) - continue; - } else - { - continue; - } - - if (root < disk->buffer) - continue; - if (zzip_disk_entry_check_magic(root)) - return (struct zzip_disk_entry *) root; - } ____; - return 0; -} - -/** => zzip_disk_findfile - * - * This function takes an existing disk_entry in the central root directory - * (e.g. from zzip_disk_findfirst) and returns the next entry within in - * the given bounds of the mmapped file area. - */ -struct zzip_disk_entry * -zzip_disk_findnext(ZZIP_DISK * disk, struct zzip_disk_entry *entry) -{ - if ((zzip_byte_t *) entry < disk->buffer || - (zzip_byte_t *) entry > disk->endbuf - sizeof(entry) || - ! zzip_disk_entry_check_magic(entry) || - zzip_disk_entry_sizeto_end(entry) > 64 * 1024) - return 0; - entry = zzip_disk_entry_to_next_entry(entry); - if ((zzip_byte_t *) entry > disk->endbuf - sizeof(entry) || - ! zzip_disk_entry_check_magic(entry) || - zzip_disk_entry_sizeto_end(entry) > 64 * 1024 || - zzip_disk_entry_skipto_end(entry) + sizeof(entry) > disk->endbuf) - return 0; - else - return entry; -} - -/** search for files in the (mmapped) zip central directory - * - * This function is given a filename as an additional argument, to find the - * disk_entry matching a given filename. The compare-function is usually - * strcmp or strcasecmp or perhaps strcoll, if null then strcmp is used. - * - use null as argument for "after"-entry when searching the first - * matching entry, otherwise the last returned value if you look for other - * entries with a special "compare" function (if null then a doubled search - * is rather useless with this variant of _findfile). - */ -struct zzip_disk_entry * -zzip_disk_findfile(ZZIP_DISK * disk, char *filename, - struct zzip_disk_entry *after, zzip_strcmp_fn_t compare) -{ - struct zzip_disk_entry *entry = (! after ? zzip_disk_findfirst(disk) - : zzip_disk_findnext(disk, after)); - if (! compare) - compare = (zzip_strcmp_fn_t) ((disk->flags & ZZIP_DISK_FLAGS_MATCH_NOCASE) ? - (_zzip_strcasecmp) : (strcmp)); - for (; entry; entry = zzip_disk_findnext(disk, entry)) - { - /* filenames within zip files are often not null-terminated! */ - char *realname = zzip_disk_entry_strdup_name(disk, entry); - if (realname && ! compare(filename, realname)) - { - free(realname); - return entry; - } - free(realname); - } - return 0; -} - -/** => zzip_disk_findfile - * - * This function uses a compare-function with an additional argument - * and it is called just like fnmatch(3) from POSIX.2 AD:1993), i.e. - * the argument filespec first and the ziplocal filename second with - * the integer-flags put in as third to the indirect call. If the - * platform has fnmatch available then null-compare will use that one - * and otherwise we fall back to mere strcmp, so if you need fnmatch - * searching then please provide an implementation somewhere else. - * - use null as argument for "after"-entry when searching the first - * matching entry, or the last disk_entry return-value to find the - * next entry matching the given filespec. - */ -struct zzip_disk_entry * -zzip_disk_findmatch(ZZIP_DISK * disk, char *filespec, - struct zzip_disk_entry *after, - zzip_fnmatch_fn_t compare, int flags) -{ - struct zzip_disk_entry *entry = (! after ? zzip_disk_findfirst(disk) - : zzip_disk_findnext(disk, after)); - if (! compare) - { - compare = (zzip_fnmatch_fn_t) _zzip_fnmatch; - if (disk->flags & ZZIP_DISK_FLAGS_MATCH_NOCASE) - flags |= _zzip_fnmatch_CASEFOLD; - } - for (; entry; entry = zzip_disk_findnext(disk, entry)) - { - /* filenames within zip files are often not null-terminated! */ - char *realname = zzip_disk_entry_strdup_name(disk, entry); - if (realname && ! compare(filespec, realname, flags)) - { - free(realname); - return entry; - } - free(realname); - } - return 0; -} - -/* ====================================================================== */ - -/** => zzip_disk_fopen - * - * the ZZIP_DISK_FILE* is rather simple in just encapsulating the - * arguments given to this function plus a zlib deflate buffer. - * Note that the ZZIP_DISK pointer does already contain the full - * mmapped file area of a zip disk, so open()ing a file part within - * that area happens to be a lookup of its bounds and encoding. That - * information is memorized on the ZZIP_DISK_FILE so that subsequent - * _read() operations will be able to get the next data portion or - * return an eof condition for that file part wrapped in the zip archive. - */ -zzip__new__ ZZIP_DISK_FILE * -zzip_disk_entry_fopen(ZZIP_DISK * disk, ZZIP_DISK_ENTRY * entry) -{ - /* keep this in sync with zzip_mem_entry_fopen */ - struct zzip_file_header *header = - zzip_disk_entry_to_file_header(disk, entry); - if (! header) - return 0; - ___ ZZIP_DISK_FILE *file = malloc(sizeof(ZZIP_DISK_FILE)); - if (! file) - return file; - file->buffer = disk->buffer; - file->endbuf = disk->endbuf; - file->avail = zzip_file_header_usize(header); - - if (! file->avail || zzip_file_header_data_stored(header)) - { file->stored = zzip_file_header_to_data (header); return file; } - - file->stored = 0; - file->zlib.opaque = 0; - file->zlib.zalloc = Z_NULL; - file->zlib.zfree = Z_NULL; - file->zlib.avail_in = zzip_file_header_csize(header); - file->zlib.next_in = zzip_file_header_to_data(header); - - if (! zzip_file_header_data_deflated(header) || - inflateInit2(&file->zlib, -MAX_WBITS) != Z_OK) - { free (file); return 0; } - - return file; - ____; -} - -/** openening a file part wrapped within a (mmapped) zip archive - * - * This function opens a file found by name, so it does a search into - * the zip central directory with => zzip_disk_findfile and whatever - * is found first is given to => zzip_disk_entry_fopen - */ -zzip__new__ ZZIP_DISK_FILE * -zzip_disk_fopen(ZZIP_DISK * disk, char *filename) -{ - ZZIP_DISK_ENTRY *entry = zzip_disk_findfile(disk, filename, 0, 0); - if (! entry) - return 0; - else - return zzip_disk_entry_fopen(disk, entry); -} - - -/** => zzip_disk_fopen - * - * This function reads more bytes into the output buffer specified as - * arguments. The return value is null on eof or error, the stdio-like - * interface can not distinguish between these so you need to check - * with => zzip_disk_feof for the difference. - */ -zzip_size_t -zzip_disk_fread(void *ptr, zzip_size_t sized, zzip_size_t nmemb, - ZZIP_DISK_FILE * file) -{ - zzip_size_t size = sized * nmemb; - if (size > file->avail) - size = file->avail; - if (file->stored) - { - memcpy(ptr, file->stored, size); - file->stored += size; - file->avail -= size; - return size; - } - - file->zlib.avail_out = sized * nmemb; - file->zlib.next_out = ptr; - ___ zzip_size_t total_old = file->zlib.total_out; - ___ int err = inflate(&file->zlib, Z_NO_FLUSH); - if (err == Z_STREAM_END) - file->avail = 0; - else if (err == Z_OK) - file->avail -= file->zlib.total_out - total_old; - else - return 0; - return file->zlib.total_out - total_old; - ____; - ____; -} - -/** => zzip_disk_fopen - * This function releases any zlib decoder info needed for decompression - * and dumps the ZZIP_DISK_FILE* then. - */ -int -zzip_disk_fclose(ZZIP_DISK_FILE * file) -{ - if (! file->stored) - inflateEnd(&file->zlib); - free(file); - return 0; -} - -/** => zzip_disk_fopen - * - * This function allows to distinguish an error from an eof condition. - * Actually, if we found an error but we did already reach eof then we - * just keep on saying that it was an eof, so the app can just continue. - */ -int -zzip_disk_feof(ZZIP_DISK_FILE * file) -{ - return ! file || ! file->avail; -} |