Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial public release

  • Loading branch information...
commit e89d322cf3e201e4a49365734ce791dd087920a8 0 parents
@thp authored
Showing with 18,406 additions and 0 deletions.
  1. +28 −0 LICENSE.apkenv
  2. +112 −0 README
  3. +367 −0 apkenv.c
  4. +116 −0 apkenv.h
  5. +199 −0 apklib/apklib.c
  6. +54 −0 apklib/apklib.h
  7. +247 −0 apklib/ioapi.c
  8. +208 −0 apklib/ioapi.h
  9. +219 −0 apklib/ioapi_mem.c
  10. +7 −0 apklib/ioapi_mem.h
  11. +2,125 −0 apklib/unzip.c
  12. +437 −0 apklib/unzip.h
  13. +7 −0 compat/README
  14. +162 −0 compat/gles2_mapping.h
  15. +969 −0 compat/gles2_wrappers.c
  16. +327 −0 compat/gles2_wrappers.h
  17. +259 −0 compat/gles_mapping.h
  18. +1,551 −0 compat/gles_wrappers.c
  19. +521 −0 compat/gles_wrappers.h
  20. +78 −0 compat/hooks.c
  21. +42 −0 compat/hooks.h
  22. +216 −0 compat/libc_mapping.h
  23. +727 −0 compat/libc_wrappers.c
  24. +255 −0 compat/libc_wrappers.h
  25. +3 −0  compat/liblog_mapping.h
  26. +57 −0 compat/liblog_wrappers.c
  27. +42 −0 compat/liblog_wrappers.h
  28. +43 −0 compat/pthread_mapping.h
  29. +248 −0 compat/pthread_wrappers.c
  30. +99 −0 compat/pthread_wrappers.h
  31. +1,154 −0 jni/jni.h
  32. +2,152 −0 jni/jnienv.c
  33. +297 −0 jni/jnienv.h
  34. +116 −0 jni/shlib.c
  35. +41 −0 jni/shlib.h
  36. +5 −0 libs/README
  37. BIN  libs/libc.so
  38. BIN  libs/libm.so
  39. BIN  libs/libstdc++.so
  40. +190 −0 linker/NOTICE
  41. +144 −0 linker/README.TXT
  42. +141 −0 linker/bionic_tls.h
  43. +274 −0 linker/dlfcn.c
  44. +2,325 −0 linker/linker.c
  45. +221 −0 linker/linker.h
  46. +155 −0 linker/linker_debug.h
  47. +204 −0 linker/linker_environ.c
  48. +54 −0 linker/linker_environ.h
  49. +707 −0 linker/linker_format.c
  50. +41 −0 linker/linker_format.h
  51. +36 −0 linker/rt.c
  52. +50 −0 linker/strlcpy.c
  53. +10 −0 linker/strlcpy.h
  54. +73 −0 makefile
  55. +85 −0 modules/common.h
  56. +83 −0 modules/generic.c
  57. +123 −0 modules/trg2.c
28 LICENSE.apkenv
@@ -0,0 +1,28 @@
+/**
+ * apkenv
+ * Copyright (c) 2012, Thomas Perl <m@thp.io>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **/
112 README
@@ -0,0 +1,112 @@
+
+apkenv
+======
+
+A compatibility layer for applications packaged as .apk.
+
+Support website: http://thp.io/2012/apkenv/
+
+
+Example module and .apk
+=======================
+
+An example module is provided in modules/trg2.c - you can use this module as a
+basis to create your own modules. You can download the .apk that works with
+this example module from:
+
+ http://thp.io/2011/trg2/
+
+
+softfp vs. hardfp
+=================
+
+Android is softfp.
+Maemo 5 is softfp.
+MeeGo 1.2 Harmattan is hardfp.
+
+softfp and hardfp differ in the way functions with floating point arguments
+get called. Trying to call a hardfp function with the softfp calling
+convention will not work and likely result in a crash or worse. To avoid
+this, you can add an attribute to function declarations to make sure that
+the function accepts its parameters using the softfp calling convention,
+like this:
+
+ __attribute__((pcs("aapcs")))
+
+There's a convenience #define in apkenv.h called "SOFTFP" with which you can
+decorate all functions that are either in a native library (i.e. in
+modules/) or that will be called from the native library (i.e. in compat/).
+Please note that in theory this attribute is only required on functions that
+pass float values in the arguments, but do it always to save you some
+headaches.
+
+
+Debugging crashes
+=================
+
+First of all, enable debugging in the makefile (set DEBUG=1). Then rebuild
+to get a debug build with lots of debug output. You can then check which
+symbols get mapped from where at the linker phase (e.g. apkenv x.apk | grep
+'from libc') - in general, most libc functions must be mapped in order to
+avoid problems (e.g. stdio functions don't work in Bionic libc, so we have
+to hack around these issues - the same is true for memory (de-)allocation,
+etc..).
+
+When you have all relevant functions mapped, ltrace'ing apkenv can help you
+find the library function in which it crashes - this will not list functions
+from Bionic libs, but only from your system libraries (another reason why it
+is usually a good idea to map system-level functions).
+
+
+Documentation
+=============
+
+JNI Invocation API
+http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html
+
+JNI Functions
+http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html
+
+JNI Types and Data Structures
+http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html
+
+GCC Function Attributes
+http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
+
+ARM Hard Float Point: VFP Comparison
+http://wiki.debian.org/ArmHardFloatPort/VfpComparison
+
+Android MotionEvent
+http://developer.android.com/reference/android/view/MotionEvent.html
+
+
+Third Party Code
+================
+
+All code written by me (thp) for apkenv is licensed under a simplified BSD
+license (see LICENSE.apkenv). However, code from third parties might be
+licensed under a different license, and have different copyright holders:
+
+apklib/unzip.{c,h}, apklib/ioapi.{c,h}:
+ The MiniZip project - http://www.winimage.com/zLibDll/minizip.html
+ Copyright (C) 1998-2010 Gilles Vollant (minizip)
+ Copyright (C) 2007-2008 Even Rouault
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+apklib/ioapi_mem.c:
+ ioapi implementation for accessing .zip files in memory
+ Copyright (C) 1998-2003 Gilles Vollant
+ Copyright (C) 2003 Justin Fletcher
+
+linker/*:
+ The Android Bionic Linker + The Android Bionic C Library
+ Copyright (c) 2005-2008, The Android Open Source Project
+
+jni/jni.h:
+ libnativehelper: Support functions for Android's class libraries
+ Copyright (C) 2006 The Android Open Source Project
+
+compat/hooks.c, compat/pthread_wrapper.c:
+ pthread wrapper implementation based on code from libhybris
+ Copyright (C) 2012 Carsten Munk
+
367 apkenv.c
@@ -0,0 +1,367 @@
+
+/**
+ * apkenv
+ * Copyright (c) 2012, Thomas Perl <m@thp.io>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **/
+
+#include <dlfcn.h>
+#include <assert.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include <SDL/SDL.h>
+#ifdef FREMANTLE
+# include <SDL/SDL_gles.h>
+#endif
+
+#include <SDL/SDL_syswm.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include "jni/jnienv.h"
+#include "jni/shlib.h"
+#include "apklib/apklib.h"
+
+#include "apkenv.h"
+
+/* Global application state */
+struct GlobalState global;
+
+void *
+lookup_symbol_impl(const char *method)
+{
+ return jni_shlib_resolve(&global, method);
+}
+
+void
+foreach_file_impl(const char *prefix, apk_for_each_file_callback callback)
+{
+ apk_for_each_file(global.apklib_handle, prefix, callback);
+}
+
+int
+read_file_impl(const char *filename, char **buffer, size_t *size)
+{
+ return (apk_read_file(global.apklib_handle,
+ filename, buffer, size) == APK_OK);
+}
+
+void register_module(struct SupportModule *module)
+{
+ struct SupportModule **current = &(global.support_modules);
+
+ while ((*current) != NULL) {
+ if ((*current)->priority < module->priority) {
+ break;
+ }
+ current = &((*current)->next);
+ }
+
+ module->next = *current;
+ *current = module;
+}
+
+void load_module(const char *filename)
+{
+ void *dl = dlopen(filename, RTLD_LAZY);
+ if (dl == NULL) {
+ printf("Cannot load module: %s\n", filename);
+ return;
+ }
+
+ struct SupportModule *module = calloc(1, sizeof(struct SupportModule));
+ module->global = &global;
+ module->filename = strdup(filename);
+
+ apkenv_module_init_t module_init = (apkenv_module_init_t)dlsym(dl,
+ APKENV_MODULE_INIT);
+
+ if (module_init != NULL) {
+ int version = module_init(APKENV_MODULE_VERSION, module);
+ switch (version) {
+ case 0:
+ printf("Cannot init module: %s\n", filename);
+ break;
+ case APKENV_MODULE_VERSION:
+ printf("Loaded module: %s (%d)\n", filename, module->priority);
+ register_module(module);
+ return;
+ default:
+ printf("Wrong module ABI version: %x (need %x)\n",
+ version, APKENV_MODULE_VERSION);
+ break;
+ }
+ } else {
+ printf("Cannot find %s(): %s\n", APKENV_MODULE_INIT, filename);
+ }
+
+ free(module->filename);
+ free(module);
+ dlclose(dl);
+}
+
+void load_modules(const char *dirname)
+{
+ DIR *dir = opendir(dirname);
+ assert(dir != NULL);
+
+ char tmp[PATH_MAX];
+ strcpy(tmp, dirname);
+ strcat(tmp, "/");
+ char *filename = tmp + strlen(dirname) + 1;
+
+ struct dirent *ent;
+ while ((ent = readdir(dir)) != NULL) {
+ int len = strlen(ent->d_name) - strlen(APKENV_MODULE_SUFFIX);
+ if (len > 0) {
+ char *suffix = ent->d_name + len;
+ if (strcmp(suffix, APKENV_MODULE_SUFFIX) == 0) {
+ strcpy(filename, ent->d_name);
+ load_module(tmp);
+ }
+ }
+ }
+ closedir(dir);
+}
+
+void install_overrides(struct SupportModule *module)
+{
+ int i;
+ void **override, **fake;
+
+ /* Install overrides for JNIEnv */
+ override = (void**)(&(module->override_env));
+ fake = (void**)(&(global.fake_env));
+ for (i=0; i<sizeof(module->override_env)/sizeof(void*); i++) {
+ if (override[i]) {
+ fake[i] = override[i];
+ }
+ }
+
+ /* Install overrides for JavaVM */
+ override = (void**)(&(module->override_vm));
+ fake = (void**)(&(global.fake_vm));
+ for (i=0; i<sizeof(module->override_vm)/sizeof(void*); i++) {
+ if (override[i]) {
+ fake[i] = override[i];
+ }
+ }
+}
+
+#define MEEGOTOUCH_BORDER 16
+
+int main(int argc, char **argv)
+{
+ char **tmp;
+
+ global.apkenv_executable = argv[0];
+ global.apkenv_headline = APKENV_HEADLINE;
+ global.apkenv_copyright = APKENV_COPYRIGHT;
+
+ printf("%s\n%s\n\n", global.apkenv_headline, global.apkenv_copyright);
+
+ if (argc != 2) {
+ printf("Usage: %s <file.apk>\n", global.apkenv_executable);
+ return 1;
+ }
+
+ global.lookup_symbol = lookup_symbol_impl;
+ global.foreach_file = foreach_file_impl;
+ global.read_file = read_file_impl;
+ jnienv_init(&global);
+ javavm_init(&global);
+ global.apk_filename = strdup(argv[1]);
+ global.apklib_handle = apk_open(argv[1]);
+ global.support_modules = NULL;
+
+ const char *shlib = apk_get_shared_library(global.apklib_handle);
+ if (shlib == NULL) {
+ printf("Not a native APK.\n");
+ return 0;
+ }
+
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) {
+ printf("SDL Init failed.\n");
+ return 0;
+ }
+
+ SDL_Surface *screen;
+
+ /**
+ * The following block looks scary, but it just creates an SDL surface
+ * with the right OpenGL ES context version. The block looks so scary,
+ * because on Fremantle, javispedro's SDL_gles is used and on Harmattan
+ * (where the GLES features are integrated directly into libSDL), only
+ * SDL is used.
+ **/
+#ifdef FREMANTLE
+#ifdef APKENV_GLES2
+ SDL_GLES_Init(SDL_GLES_VERSION_2_0);
+#else /* APKENV_GLES2 */
+ SDL_GLES_Init(SDL_GLES_VERSION_1_1);
+#endif /* APKENV_GLES2 */
+ screen = SDL_SetVideoMode(0, 0, 0, SDL_FULLSCREEN);
+ SDL_GLES_MakeCurrent(SDL_GLES_CreateContext());
+#else /* FREMANTLE */
+#ifdef APKENV_GLES2
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+#else /* APKENV_GLES2 */
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
+#endif /* APKENV_GLES2 */
+ screen = SDL_SetVideoMode(0, 0, 0, SDL_OPENGLES | SDL_FULLSCREEN);
+#endif /* FREMANTLE */
+
+ SDL_ShowCursor(0);
+
+#ifndef FREMANTLE
+ /* Set up swipe lock (left and right) */
+ SDL_SysWMinfo wm;
+ SDL_VERSION(&wm.version);
+ SDL_GetWMInfo(&wm);
+ Display *dpy = wm.info.x11.display;
+ Atom atom = XInternAtom(dpy, "_MEEGOTOUCH_CUSTOM_REGION", False);
+ unsigned int region[] = {
+ 0,
+ MEEGOTOUCH_BORDER,
+ screen->w,
+ screen->h - 2*MEEGOTOUCH_BORDER,
+ };
+ XChangeProperty(dpy, wm.info.x11.wmwindow, atom, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)region, 4);
+#endif
+
+ global.method_table = jni_shlib_find_methods(shlib);
+ global.jni_library = android_dlopen(shlib, RTLD_LAZY);
+ unlink(shlib);
+ if (!(global.jni_library)) {
+ printf("Missing library dependencies.\n");
+ return 0;
+ }
+
+ load_modules(".");
+ if (global.support_modules == NULL) {
+ printf("No support modules found.\n");
+ }
+
+ /* Search for a suitable module to handle the library */
+ struct SupportModule *module = global.support_modules;
+ while (module != NULL) {
+ if (module->try_init(module)) {
+ break;
+ }
+ module = module->next;
+ }
+
+ if (module == NULL) {
+ printf("Not supported yet, but found JNI methods:\n");
+ tmp = global.method_table;
+ while (*tmp) {
+ printf(" %s\n", *tmp);
+ tmp++;
+ }
+ goto finish;
+ }
+
+ global.active_module = module;
+ printf("Using module: %s\n", module->filename);
+ install_overrides(module);
+
+ struct stat st;
+ if (stat(DATA_DIRECTORY_BASE, &st) != 0) {
+ mkdir(DATA_DIRECTORY_BASE, 0700);
+ }
+
+ char data_directory[PATH_MAX];
+ strcpy(data_directory, DATA_DIRECTORY_BASE);
+
+ char *fn = strdup(global.apk_filename);
+ char *start = strrchr(fn, '/');
+ if (start != NULL) {
+ start++;
+ } else {
+ start = fn;
+ }
+ strcat(data_directory, start);
+ strcat(data_directory, "/");
+ free(fn);
+
+ if (stat(data_directory, &st) != 0) {
+ mkdir(data_directory, 0700);
+ }
+
+ module->init(module, screen->w, screen->h, data_directory);
+
+ while (1) {
+ SDL_Event e;
+ while (SDL_PollEvent(&e)) {
+ if (e.type == SDL_MOUSEBUTTONDOWN) {
+ module->input(module, ACTION_DOWN, e.button.x, e.button.y, e.button.which);
+ } else if (e.type == SDL_MOUSEBUTTONUP) {
+ module->input(module, ACTION_UP, e.button.x, e.button.y, e.button.which);
+ } else if (e.type == SDL_MOUSEMOTION) {
+ module->input(module, ACTION_MOVE, e.motion.x, e.motion.y, e.motion.which);
+ } else if (e.type == SDL_QUIT) {
+ module->deinit(module);
+ goto finish;
+ } else if (e.type == SDL_ACTIVEEVENT) {
+ if (e.active.state == SDL_APPACTIVE && e.active.gain == 0) {
+ module->pause(module);
+ while (1) {
+ SDL_WaitEvent(&e);
+ if (e.type == SDL_ACTIVEEVENT) {
+ if (e.active.state == SDL_APPACTIVE &&
+ e.active.gain == 1) {
+ break;
+ }
+ } else if (e.type == SDL_QUIT) {
+ goto finish;
+ }
+ }
+ module->resume(module);
+ }
+ }
+ }
+ module->update(module);
+#ifdef FREMANTLE
+ SDL_GLES_SwapBuffers();
+#else
+ SDL_GL_SwapBuffers();
+#endif
+ }
+
+finish:
+ tmp = global.method_table;
+ while (*tmp) {
+ free(*tmp++);
+ }
+ free(global.method_table);
+ apk_close(global.apklib_handle);
+
+ return 0;
+}
+
116 apkenv.h
@@ -0,0 +1,116 @@
+#ifndef APKENV_H
+#define APKENV_H
+
+/**
+ * apkenv
+ * Copyright (c) 2012, Thomas Perl <m@thp.io>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **/
+
+#include "apklib/apklib.h"
+#include "jni/jni.h"
+
+#define APKENV_NAME "apkenv"
+#define APKENV_VERSION "42.1.0"
+#define APKENV_WEBSITE "http://thp.io/2012/apkenv/"
+#define APKENV_HEADLINE APKENV_NAME " " APKENV_VERSION " - " APKENV_WEBSITE
+#define APKENV_COPYRIGHT "Copyright (c) 2012 Thomas Perl <m@thp.io>"
+
+struct GlobalState;
+struct SupportModulePriv;
+
+struct SupportModule {
+ struct GlobalState *global;
+ struct SupportModulePriv *priv;
+ char *filename;
+ int priority;
+
+ struct JNINativeInterface override_env;
+ struct JNIInvokeInterface override_vm;
+
+ int (*try_init)(struct SupportModule *self);
+ void (*init)(struct SupportModule *self, int width, int height, const char *home);
+ void (*input)(struct SupportModule *self, int event, int x, int y, int finger);
+ void (*update)(struct SupportModule *self);
+ void (*deinit)(struct SupportModule *self);
+ void (*pause)(struct SupportModule *self);
+ void (*resume)(struct SupportModule *self);
+
+ struct SupportModule *next;
+};
+
+typedef void *(*lookup_symbol_t)(const char *method);
+typedef void (*foreach_file_t)(const char *prefix, apk_for_each_file_callback callback);
+typedef int (*read_file_t)(const char *filename, char **buffer, size_t *size);
+
+struct GlobalState {
+ const char *apkenv_executable;
+ const char *apkenv_headline;
+ const char *apkenv_copyright;
+
+ struct JNINativeInterface fake_env;
+ JNIEnv env;
+ struct JNIInvokeInterface fake_vm;
+ JavaVM vm;
+
+ const char *apk_filename;
+ AndroidApk *apklib_handle;
+
+ void *jni_library;
+ char **method_table;
+
+ struct SupportModule *support_modules;
+ struct SupportModule *active_module;
+
+ lookup_symbol_t lookup_symbol;
+ foreach_file_t foreach_file;
+ read_file_t read_file;
+};
+
+#define VM(global_ptr) (&((global_ptr)->vm))
+#define ENV(global_ptr) (&((global_ptr)->env))
+
+#define DATA_DIRECTORY_BASE "/home/user/.apkenv/"
+
+/* Android MotionEvent */
+#define ACTION_DOWN 0
+#define ACTION_UP 1
+#define ACTION_MOVE 2
+
+/* Attribute for softfp-calling-style functions */
+#define SOFTFP __attribute__((pcs("aapcs")))
+
+/* Forward-declarations for the Bionic linker */
+void *android_dlopen(const char *filename, int flag);
+void *android_dlsym(void *handle, const char *symbol);
+
+/* Module support */
+typedef int (*apkenv_module_init_t)(int version, struct SupportModule *module);
+#define APKENV_MODULE_INIT "apkenv_module_init"
+#define APKENV_MODULE_SUFFIX ".apkenv.so"
+#define APKENV_MODULE_VERSION 0x010000
+
+#endif /* APKENV_H */
199 apklib/apklib.c
@@ -0,0 +1,199 @@
+
+/**
+ * apkenv
+ * Copyright (c) 2012, Thomas Perl <m@thp.io>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **/
+
+#include <zlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <string.h>
+
+#include "unzip.h"
+#include "ioapi_mem.h"
+
+#include "apklib.h"
+
+AndroidApk *
+apk_open(const char *filename)
+{
+ AndroidApk *apk = calloc(1, sizeof(AndroidApk));
+ apk->zip = unzOpen(filename);
+ return apk;
+}
+
+char *
+apk_get_shared_library(AndroidApk *apk)
+{
+ assert(apk != NULL);
+
+ char filename[PATH_MAX];
+ FILE *result = NULL;
+ char buf[64*1024];
+ int read;
+
+ if (unzGoToFirstFile(apk->zip) != UNZ_OK) {
+ return NULL;
+ }
+
+ do {
+ if (unzGetCurrentFileInfo(apk->zip, NULL, filename, sizeof(filename),
+ NULL, 0, NULL, 0) == UNZ_OK) {
+ if (memcmp(filename, "lib/armeabi", 11) == 0) {
+ if (unzOpenCurrentFile(apk->zip) == UNZ_OK) {
+ strcpy(filename, "/home/user/.apkenv-XXXXXX");
+ int fd = mkstemp(filename);
+ result = fdopen(fd, "w+b");
+ while (!unzeof(apk->zip)) {
+ read = unzReadCurrentFile(apk->zip, buf, sizeof(buf));
+ if (read) {
+ assert(fwrite(buf, read, 1, result) == 1);
+ }
+ }
+ fclose(result);
+ unzCloseCurrentFile(apk->zip);
+ return strdup(filename);
+ }
+ break;
+ }
+ }
+ } while (unzGoToNextFile(apk->zip) == UNZ_OK);
+
+ return NULL;
+}
+
+enum ApkResult
+apk_uncompress_internal(AndroidApk *apk, char **buffer, size_t *size)
+{
+ zlib_filefunc_def filefunc;
+ fill_memory_filefunc(&filefunc);
+ char *old_buffer = *buffer;
+ char path[1024];
+ sprintf(path, "%x+%x", *buffer, *size);
+
+ /* Decompress a single file in a .zip from memory */
+ unz_file_info info;
+ unzFile *unz = unzOpen2(path, &filefunc);
+ unzGoToFirstFile(unz);
+ unzGetCurrentFileInfo(unz, &info, NULL, 0, NULL, 0, NULL, 0);
+ *size = info.uncompressed_size;
+ *buffer = malloc(*size);
+ unzOpenCurrentFile(unz);
+ unzReadCurrentFile(unz, *buffer, *size);
+ unzCloseCurrentFile(unz);
+ unzClose(unz);
+ free(old_buffer);
+
+ return APK_OK;
+}
+
+enum ApkResult
+apk_read_file(AndroidApk *apk, const char *filename, char **buffer, size_t *size)
+{
+ assert(apk != NULL);
+
+ unz_file_info info;
+ int read;
+ char *write_pos;
+ int remaining;
+ int is_zipfile = 0;
+
+ if (unzLocateFile(apk->zip, filename, 2) != UNZ_OK) {
+ char *filename2 = malloc(strlen(filename) + strlen(".zip") + 1);
+ sprintf(filename2, "%s.zip", filename);
+ if (unzLocateFile(apk->zip, filename2, 2) == UNZ_OK) {
+ is_zipfile = 1;
+ } else {
+ return APK_ERROR;
+ }
+ }
+
+ if (unzGetCurrentFileInfo(apk->zip, &info, NULL, 0,
+ NULL, 0, NULL, 0) == UNZ_OK) {
+ if (unzOpenCurrentFile(apk->zip) == UNZ_OK) {
+ *size = info.uncompressed_size;
+ *buffer = malloc(*size);
+
+ write_pos = *buffer;
+ remaining = *size;
+ while (!unzeof(apk->zip)) {
+ read = unzReadCurrentFile(apk->zip, write_pos, remaining);
+ write_pos += read;
+ remaining -= read;
+ }
+ unzCloseCurrentFile(apk->zip);
+
+ if (is_zipfile) {
+ return apk_uncompress_internal(apk, buffer, size);
+ }
+ return APK_OK;
+ }
+ }
+
+ return APK_ERROR;
+}
+
+void
+apk_for_each_file(AndroidApk *apk, const char *prefix,
+ apk_for_each_file_callback callback)
+{
+ assert(apk != NULL);
+
+ unz_file_info info;
+ char filename[PATH_MAX];
+ char *buf;
+ size_t size;
+
+ if (unzGoToFirstFile(apk->zip) != UNZ_OK) {
+ return;
+ }
+
+ do {
+ if (unzGetCurrentFileInfo(apk->zip, &info, filename, sizeof(filename),
+ NULL, 0, NULL, 0) == UNZ_OK) {
+ if (memcmp(filename, prefix, strlen(prefix)) == 0) {
+ if (unzOpenCurrentFile(apk->zip) == UNZ_OK) {
+ size = info.uncompressed_size;
+ buf = malloc(info.uncompressed_size);
+ size = unzReadCurrentFile(apk->zip, buf,
+ info.uncompressed_size);
+ callback(filename, buf, size);
+ free(buf);
+ unzCloseCurrentFile(apk->zip);
+ }
+ }
+ }
+ } while (unzGoToNextFile(apk->zip) == UNZ_OK);
+}
+
+void
+apk_close(AndroidApk *apk)
+{
+ assert(apk != NULL);
+ unzClose(apk->zip);
+}
+
54 apklib/apklib.h
@@ -0,0 +1,54 @@
+#ifndef APKLIB_H
+#define APKLIB_H
+
+/**
+ * apkenv
+ * Copyright (c) 2012, Thomas Perl <m@thp.io>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **/
+
+#include "unzip.h"
+
+struct AndroidApk {
+ unzFile *zip;
+};
+typedef struct AndroidApk AndroidApk;
+
+enum ApkResult {
+ APK_OK,
+ APK_ERROR,
+};
+
+typedef void (*apk_for_each_file_callback)(const char *filename, char *buffer, size_t size);
+
+/* apklib.c */
+AndroidApk *apk_open(const char *filename);
+char *apk_get_shared_library(AndroidApk *apk);
+enum ApkResult apk_read_file(AndroidApk *apk, const char *filename, char **buffer, size_t *size);
+void apk_for_each_file(AndroidApk *apk, const char *prefix, apk_for_each_file_callback callback);
+void apk_close(AndroidApk *apk);
+
+#endif /* APKLIB_H */
247 apklib/ioapi.c
@@ -0,0 +1,247 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications for Zip64 support
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+*/
+
+#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS)))
+ #define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#if defined(__APPLE__) || defined(IOAPI_NO_64)
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+
+
+#include "ioapi.h"
+
+voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
+{
+ if (pfilefunc->zfile_func64.zopen64_file != NULL)
+ return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode);
+ else
+ {
+ return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode);
+ }
+}
+
+long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)
+{
+ if (pfilefunc->zfile_func64.zseek64_file != NULL)
+ return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
+ else
+ {
+ uLong offsetTruncated = (uLong)offset;
+ if (offsetTruncated != offset)
+ return -1;
+ else
+ return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);
+ }
+}
+
+ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)
+{
+ if (pfilefunc->zfile_func64.zseek64_file != NULL)
+ return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
+ else
+ {
+ uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
+ if ((tell_uLong) == MAXU32)
+ return (ZPOS64_T)-1;
+ else
+ return tell_uLong;
+ }
+}
+
+void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)
+{
+ p_filefunc64_32->zfile_func64.zopen64_file = NULL;
+ p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
+ p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
+ p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
+ p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
+ p_filefunc64_32->zfile_func64.ztell64_file = NULL;
+ p_filefunc64_32->zfile_func64.zseek64_file = NULL;
+ p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
+ p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
+ p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
+ p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
+ p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
+}
+
+
+
+static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));
+static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size));
+static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream));
+static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
+static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream));
+static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream));
+
+static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode)
+{
+ FILE* file = NULL;
+ const char* mode_fopen = NULL;
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+ mode_fopen = "rb";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ mode_fopen = "r+b";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ mode_fopen = "wb";
+
+ if ((filename!=NULL) && (mode_fopen != NULL))
+ file = fopen(filename, mode_fopen);
+ return file;
+}
+
+static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode)
+{
+ FILE* file = NULL;
+ const char* mode_fopen = NULL;
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+ mode_fopen = "rb";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ mode_fopen = "r+b";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ mode_fopen = "wb";
+
+ if ((filename!=NULL) && (mode_fopen != NULL))
+ file = FOPEN_FUNC((const char*)filename, mode_fopen);
+ return file;
+}
+
+
+static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
+{
+ uLong ret;
+ ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)
+{
+ uLong ret;
+ ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
+{
+ long ret;
+ ret = ftell((FILE *)stream);
+ return ret;
+}
+
+
+static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
+{
+ ZPOS64_T ret;
+ ret = FTELLO_FUNC((FILE *)stream);
+ return ret;
+}
+
+static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin)
+{
+ int fseek_origin=0;
+ long ret;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ fseek_origin = SEEK_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ fseek_origin = SEEK_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ fseek_origin = SEEK_SET;
+ break;
+ default: return -1;
+ }
+ ret = 0;
+ if (fseek((FILE *)stream, offset, fseek_origin) != 0)
+ ret = -1;
+ return ret;
+}
+
+static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)
+{
+ int fseek_origin=0;
+ long ret;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ fseek_origin = SEEK_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ fseek_origin = SEEK_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ fseek_origin = SEEK_SET;
+ break;
+ default: return -1;
+ }
+ ret = 0;
+
+ if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0)
+ ret = -1;
+
+ return ret;
+}
+
+
+static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
+{
+ int ret;
+ ret = fclose((FILE *)stream);
+ return ret;
+}
+
+static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
+{
+ int ret;
+ ret = ferror((FILE *)stream);
+ return ret;
+}
+
+void fill_fopen_filefunc (pzlib_filefunc_def)
+ zlib_filefunc_def* pzlib_filefunc_def;
+{
+ pzlib_filefunc_def->zopen_file = fopen_file_func;
+ pzlib_filefunc_def->zread_file = fread_file_func;
+ pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+ pzlib_filefunc_def->ztell_file = ftell_file_func;
+ pzlib_filefunc_def->zseek_file = fseek_file_func;
+ pzlib_filefunc_def->zclose_file = fclose_file_func;
+ pzlib_filefunc_def->zerror_file = ferror_file_func;
+ pzlib_filefunc_def->opaque = NULL;
+}
+
+void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def)
+{
+ pzlib_filefunc_def->zopen64_file = fopen64_file_func;
+ pzlib_filefunc_def->zread_file = fread_file_func;
+ pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+ pzlib_filefunc_def->ztell64_file = ftell64_file_func;
+ pzlib_filefunc_def->zseek64_file = fseek64_file_func;
+ pzlib_filefunc_def->zclose_file = fclose_file_func;
+ pzlib_filefunc_def->zerror_file = ferror_file_func;
+ pzlib_filefunc_def->opaque = NULL;
+}
208 apklib/ioapi.h
@@ -0,0 +1,208 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications for Zip64 support
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+ Changes
+
+ Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
+ Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
+ More if/def section may be needed to support other platforms
+ Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
+ (but you should use iowin32.c for windows instead)
+
+*/
+
+#ifndef _ZLIBIOAPI64_H
+#define _ZLIBIOAPI64_H
+
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
+
+ // Linux needs this to support file operation on files larger then 4+GB
+ // But might need better if/def to select just the platforms that needs them.
+
+ #ifndef __USE_FILE_OFFSET64
+ #define __USE_FILE_OFFSET64
+ #endif
+ #ifndef __USE_LARGEFILE64
+ #define __USE_LARGEFILE64
+ #endif
+ #ifndef _LARGEFILE64_SOURCE
+ #define _LARGEFILE64_SOURCE
+ #endif
+ #ifndef _FILE_OFFSET_BIT
+ #define _FILE_OFFSET_BIT 64
+ #endif
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "zlib.h"
+
+#if defined(USE_FILE32API)
+#define fopen64 fopen
+#define ftello64 ftell
+#define fseeko64 fseek
+#else
+#ifdef __FreeBSD__
+#define fopen64 fopen
+#define ftello64 ftello
+#define fseeko64 fseeko
+#endif
+#ifdef _MSC_VER
+ #define fopen64 fopen
+ #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
+ #define ftello64 _ftelli64
+ #define fseeko64 _fseeki64
+ #else // old MSC
+ #define ftello64 ftell
+ #define fseeko64 fseek
+ #endif
+#endif
+#endif
+
+/*
+#ifndef ZPOS64_T
+ #ifdef _WIN32
+ #define ZPOS64_T fpos_t
+ #else
+ #include <stdint.h>
+ #define ZPOS64_T uint64_t
+ #endif
+#endif
+*/
+
+#ifdef HAVE_MINIZIP64_CONF_H
+#include "mz64conf.h"
+#endif
+
+/* a type choosen by DEFINE */
+#ifdef HAVE_64BIT_INT_CUSTOM
+typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
+#else
+#ifdef HAS_STDINT_H
+#include "stdint.h"
+typedef uint64_t ZPOS64_T;
+#else
+
+/* Maximum unsigned 32-bit value used as placeholder for zip64 */
+#define MAXU32 0xffffffff
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef unsigned __int64 ZPOS64_T;
+#else
+typedef unsigned long long int ZPOS64_T;
+#endif
+#endif
+#endif
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define ZLIB_FILEFUNC_SEEK_CUR (1)
+#define ZLIB_FILEFUNC_SEEK_END (2)
+#define ZLIB_FILEFUNC_SEEK_SET (0)
+
+#define ZLIB_FILEFUNC_MODE_READ (1)
+#define ZLIB_FILEFUNC_MODE_WRITE (2)
+#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
+
+#define ZLIB_FILEFUNC_MODE_EXISTING (4)
+#define ZLIB_FILEFUNC_MODE_CREATE (8)
+
+
+#ifndef ZCALLBACK
+ #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
+ #define ZCALLBACK CALLBACK
+ #else
+ #define ZCALLBACK
+ #endif
+#endif
+
+
+
+
+typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
+typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
+typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
+
+typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
+typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
+
+
+/* here is the "old" 32 bits structure structure */
+typedef struct zlib_filefunc_def_s
+{
+ open_file_func zopen_file;
+ read_file_func zread_file;
+ write_file_func zwrite_file;
+ tell_file_func ztell_file;
+ seek_file_func zseek_file;
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
+} zlib_filefunc_def;
+
+typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream));
+typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
+typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode));
+
+typedef struct zlib_filefunc64_def_s
+{
+ open64_file_func zopen64_file;
+ read_file_func zread_file;
+ write_file_func zwrite_file;
+ tell64_file_func ztell64_file;
+ seek64_file_func zseek64_file;
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
+} zlib_filefunc64_def;
+
+void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
+void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+
+/* now internal definition, only for zip.c and unzip.h */
+typedef struct zlib_filefunc64_32_def_s
+{
+ zlib_filefunc64_def zfile_func64;
+ open_file_func zopen32_file;
+ tell_file_func ztell32_file;
+ seek_file_func zseek32_file;
+} zlib_filefunc64_32_def;
+
+
+#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
+#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
+//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
+//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))
+#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream))
+#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
+
+voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode));
+long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin));
+ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream));
+
+void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
+
+#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode)))
+#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream)))
+#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
219 apklib/ioapi_mem.c
@@ -0,0 +1,219 @@
+/* ioapi_mem.c -- IO base function header for compress/uncompress .zip
+ files using zlib + zip or unzip API
+
+ This version of ioapi is designed to access memory rather than files.
+ We do use a region of memory to put data in to and take it out of. We do
+ not have auto-extending buffers and do not inform anyone else that the
+ data has been written. It is really intended for accessing a zip archive
+ embedded in an application such that I can write an installer with no
+ external files. Creation of archives has not been attempted, although
+ parts of the framework are present.
+
+ Based on Unzip ioapi.c version 0.22, May 19th, 2003
+
+ Copyright (C) 1998-2003 Gilles Vollant
+ (C) 2003 Justin Fletcher
+
+ This file is under the same license as the Unzip tool it is distributed
+ with.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "zlib.h"
+#include "ioapi.h"
+
+
+
+voidpf ZCALLBACK fopen_mem_func OF((
+ voidpf opaque,
+ const char* filename,
+ int mode));
+
+uLong ZCALLBACK fread_mem_func OF((
+ voidpf opaque,
+ voidpf stream,
+ void* buf,
+ uLong size));
+
+uLong ZCALLBACK fwrite_mem_func OF((
+ voidpf opaque,
+ voidpf stream,
+ const void* buf,
+ uLong size));
+
+long ZCALLBACK ftell_mem_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+long ZCALLBACK fseek_mem_func OF((
+ voidpf opaque,
+ voidpf stream,
+ uLong offset,
+ int origin));
+
+int ZCALLBACK fclose_mem_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+int ZCALLBACK ferror_mem_func OF((
+ voidpf opaque,
+ voidpf stream));
+
+
+typedef struct ourmemory_s {
+ char *base; /* Base of the region of memory we're using */
+ uLong size; /* Size of the region of memory we're using */
+ uLong limit; /* Furthest we've written */
+ uLong cur_offset; /* Current offset in the area */
+} ourmemory_t;
+
+voidpf ZCALLBACK fopen_mem_func (opaque, filename, mode)
+ voidpf opaque;
+ const char* filename;
+ int mode;
+{
+ ourmemory_t *mem = malloc(sizeof(*mem));
+ if (mem==NULL)
+ return NULL; /* Can't allocate space, so failed */
+
+ /* Filenames are specified in the form :
+ * <hex base of zip file>+<hex size of zip file>
+ * This may not work where memory addresses are longer than the
+ * size of an int and therefore may need addressing for 64bit
+ * architectures
+ */
+ if (sscanf(filename,"%x+%x",&mem->base,&mem->size)!=2)
+ return NULL;
+
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ mem->limit=0; /* When writing we start with 0 bytes written */
+ else
+ mem->limit=mem->size;
+
+ mem->cur_offset = 0;
+
+ return mem;
+}
+
+
+uLong ZCALLBACK fread_mem_func (opaque, stream, buf, size)
+ voidpf opaque;
+ voidpf stream;
+ void* buf;
+ uLong size;
+{
+ ourmemory_t *mem = (ourmemory_t *)stream;
+
+ if (size > mem->size - mem->cur_offset)
+ size = mem->size - mem->cur_offset;
+
+ memcpy(buf, mem->base + mem->cur_offset, size);
+ mem->cur_offset+=size;
+
+ return size;
+}
+
+
+uLong ZCALLBACK fwrite_mem_func (opaque, stream, buf, size)
+ voidpf opaque;
+ voidpf stream;
+ const void* buf;
+ uLong size;
+{
+ ourmemory_t *mem = (ourmemory_t *)stream;
+
+ if (size > mem->size - mem->cur_offset)
+ size = mem->size - mem->cur_offset;
+
+ memcpy(mem->base + mem->cur_offset, buf, size);
+ mem->cur_offset+=size;
+ if (mem->cur_offset > mem->limit)
+ mem->limit = mem->cur_offset;
+
+ return size;
+}
+
+long ZCALLBACK ftell_mem_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ ourmemory_t *mem = (ourmemory_t *)stream;
+
+ return mem->cur_offset;
+}
+
+long ZCALLBACK fseek_mem_func (opaque, stream, offset, origin)
+ voidpf opaque;
+ voidpf stream;
+ uLong offset;
+ int origin;
+{
+ ourmemory_t *mem = (ourmemory_t *)stream;
+ uLong new_pos;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ new_pos = mem->cur_offset + offset;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ new_pos = mem->limit + offset;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ new_pos = offset;
+ break;
+ default: return -1;
+ }
+
+ if (new_pos > mem->size)
+ return 1; /* Failed to seek that far */
+
+ if (new_pos > mem->limit)
+ memset(mem->base + mem->limit, 0, new_pos - mem->limit);
+
+ mem->cur_offset = new_pos;
+ return 0;
+}
+
+int ZCALLBACK fclose_mem_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ ourmemory_t *mem = (ourmemory_t *)stream;
+
+ /* Note that once we've written to the buffer we don't tell anyone
+ about it here. Probably the opaque handle could be used to inform
+ some other component of how much data was written.
+
+ This, and other aspects of writing through this interface, has
+ not been tested.
+ */
+
+ free (mem);
+ return 0;
+}
+
+int ZCALLBACK ferror_mem_func (opaque, stream)
+ voidpf opaque;
+ voidpf stream;
+{
+ //ourmemory_t *mem = (ourmemory_t *)stream;
+ /* We never return errors */
+ return 0;
+}
+
+void fill_memory_filefunc (pzlib_filefunc_def)
+ zlib_filefunc_def* pzlib_filefunc_def;
+{
+ pzlib_filefunc_def->zopen_file = fopen_mem_func;
+ pzlib_filefunc_def->zread_file = fread_mem_func;
+ pzlib_filefunc_def->zwrite_file = fwrite_mem_func;
+ pzlib_filefunc_def->ztell_file = ftell_mem_func;
+ pzlib_filefunc_def->zseek_file = fseek_mem_func;
+ pzlib_filefunc_def->zclose_file = fclose_mem_func;
+ pzlib_filefunc_def->zerror_file = ferror_mem_func;
+ pzlib_filefunc_def->opaque = NULL;
+}
7 apklib/ioapi_mem.h
@@ -0,0 +1,7 @@
+#ifndef IOAPI_MEM_H
+#define IOAPI_MEM_H
+
+/* ioapi_mem.c */
+void fill_memory_filefunc(zlib_filefunc_def *pzlib_filefunc_def);
+
+#endif /* IOAPI_MEM_H */
2,125 apklib/unzip.c
@@ -0,0 +1,2125 @@
+/* unzip.c -- IO for uncompress .zip files using zlib
+ Version 1.1, February 14h, 2010
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications of Unzip for Zip64
+ Copyright (C) 2007-2008 Even Rouault
+
+ Modifications for Zip64 support on both zip and unzip
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+
+ ------------------------------------------------------------------------------------
+ Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
+ compatibility with older software. The following is from the original crypt.c.
+ Code woven in by Terry Thorsen 1/2003.
+
+ Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2000-Apr-09 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, all these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+
+ crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h]
+
+ The encryption/decryption parts of this source code (as opposed to the
+ non-echoing password parts) were originally written in Europe. The
+ whole source package can be freely distributed, including from the USA.
+ (Prior to January 2000, re-export from the US was a violation of US law.)
+
+ This encryption code is a direct transcription of the algorithm from
+ Roger Schlafly, described by Phil Katz in the file appnote.txt. This
+ file (appnote.txt) is distributed with the PKZIP program (even in the
+ version without encryption capabilities).
+
+ ------------------------------------------------------------------------------------
+
+ Changes in unzip.c
+
+ 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos
+ 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz*
+ 2007-2008 - Even Rouault - Remove old C style function prototypes
+ 2007-2008 - Even Rouault - Add unzip support for ZIP64
+
+ Copyright (C) 2007-2008 Even Rouault
+
+
+ Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again).
+ Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G
+ should only read the compressed/uncompressed size from the Zip64 format if
+ the size from normal header was 0xFFFFFFFF
+ Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant
+ Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required)
+ Patch created by Daniel Borca
+
+ Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
+
+ Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson
+
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef NOUNCRYPT
+ #define NOUNCRYPT
+#endif
+
+#include "zlib.h"
+#include "unzip.h"
+
+#ifdef STDC
+# include <stddef.h>
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+ extern int errno;
+#else
+# include <errno.h>
+#endif
+
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+
+#ifndef CASESENSITIVITYDEFAULT_NO
+# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
+# define CASESENSITIVITYDEFAULT_NO
+# endif
+#endif
+
+
+#ifndef UNZ_BUFSIZE
+#define UNZ_BUFSIZE (16384)
+#endif
+
+#ifndef UNZ_MAXFILENAMEINZIP
+#define UNZ_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (malloc(size))
+#endif
+#ifndef TRYFREE
+# define TRYFREE(p) {if (p) free(p);}
+#endif
+
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+
+
+const char unz_copyright[] =
+ " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
+
+/* unz_file_info_interntal contain internal info about a file in zipfile*/
+typedef struct unz_file_info64_internal_s
+{
+ ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
+} unz_file_info64_internal;
+
+
+/* file_in_zip_read_info_s contain internal information about a file in zipfile,
+ when reading and decompress it */
+typedef struct
+{
+ char *read_buffer; /* internal buffer for compressed data */
+ z_stream stream; /* zLib stream structure for inflate */
+
+#ifdef HAVE_BZIP2
+ bz_stream bstream; /* bzLib stream structure for bziped */
+#endif
+
+ ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
+ uLong stream_initialised; /* flag set if stream structure is initialised*/
+
+ ZPOS64_T offset_local_extrafield;/* offset of the local extra field */
+ uInt size_local_extrafield;/* size of the local extra field */
+ ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/
+ ZPOS64_T total_out_64;
+
+ uLong crc32; /* crc32 of all data uncompressed */
+ uLong crc32_wait; /* crc32 we must obtain after decompress all */
+ ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */
+ ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/
+ zlib_filefunc64_32_def z_filefunc;
+ voidpf filestream; /* io structore of the zipfile */
+ uLong compression_method; /* compression method (0==store) */
+ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ int raw;
+} file_in_zip64_read_info_s;
+
+
+/* unz64_s contain internal information about the zipfile
+*/
+typedef struct
+{
+ zlib_filefunc64_32_def z_filefunc;
+ int is64bitOpenFunction;
+ voidpf filestream; /* io structore of the zipfile */
+ unz_global_info64 gi; /* public global information */
+ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ ZPOS64_T num_file; /* number of the current file in the zipfile*/
+ ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/
+ ZPOS64_T current_file_ok; /* flag about the usability of the current file*/
+ ZPOS64_T central_pos; /* position of the beginning of the central dir*/
+
+ ZPOS64_T size_central_dir; /* size of the central directory */
+ ZPOS64_T offset_central_dir; /* offset of start of central directory with
+ respect to the starting disk number */
+
+ unz_file_info64 cur_file_info; /* public info about the current file in zip*/
+ unz_file_info64_internal cur_file_info_internal; /* private info about it*/
+ file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current
+ file if we are decompressing it */
+ int encrypted;
+
+ int isZip64;
+
+# ifndef NOUNCRYPT
+ unsigned long keys[3]; /* keys defining the pseudo-random sequence */
+ const unsigned long* pcrc_32_tab;
+# endif
+} unz64_s;
+
+
+#ifndef NOUNCRYPT
+#include "crypt.h"
+#endif
+
+/* ===========================================================================
+ Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+ for end of file.
+ IN assertion: the stream s has been sucessfully opened for reading.
+*/
+
+
+local int unz64local_getByte OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ int *pi));
+
+local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)
+{
+ unsigned char c;
+ int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
+ if (err==1)
+ {
+ *pi = (int)c;
+ return UNZ_OK;
+ }
+ else
+ {
+ if (ZERROR64(*pzlib_filefunc_def,filestream))
+ return UNZ_ERRNO;
+ else
+ return UNZ_EOF;
+ }
+}
+
+
+/* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets
+*/
+local int unz64local_getShort OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX));
+
+local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX)
+{
+ uLong x ;
+ int i = 0;
+ int err;
+
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (uLong)i;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((uLong)i)<<8;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+local int unz64local_getLong OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX));
+
+local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX)
+{
+ uLong x ;
+ int i = 0;
+ int err;
+
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (uLong)i;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((uLong)i)<<8;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((uLong)i)<<16;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<24;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+local int unz64local_getLong64 OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ ZPOS64_T *pX));
+
+
+local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ ZPOS64_T *pX)
+{
+ ZPOS64_T x ;
+ int i = 0;
+ int err;
+
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (ZPOS64_T)i;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<8;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<16;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<24;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<32;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<40;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<48;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<56;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+/* My own strcmpi / strcasecmp */
+local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)
+{
+ for (;;)
+ {
+ char c1=*(fileName1++);
+ char c2=*(fileName2++);
+ if ((c1>='a') && (c1<='z'))
+ c1 -= 0x20;
+ if ((c2>='a') && (c2<='z'))
+ c2 -= 0x20;
+ if (c1=='\0')
+ return ((c2=='\0') ? 0 : -1);
+ if (c2=='\0')
+ return 1;
+ if (c1<c2)
+ return -1;
+ if (c1>c2)
+ return 1;
+ }
+}
+
+
+#ifdef CASESENSITIVITYDEFAULT_NO
+#define CASESENSITIVITYDEFAULTVALUE 2
+#else
+#define CASESENSITIVITYDEFAULTVALUE 1
+#endif
+
+#ifndef STRCMPCASENOSENTIVEFUNCTION
+#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
+#endif
+
+/*
+ Compare two filename (fileName1,fileName2).
+ If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+ If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+ or strcasecmp)
+ If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+ (like 1 on Unix, 2 on Windows)
+
+*/
+extern int ZEXPORT unzStringFileNameCompare (const char* fileName1,
+ const char* fileName2,
+ int iCaseSensitivity)
+
+{
+ if (iCaseSensitivity==0)
+ iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
+
+ if (iCaseSensitivity==1)
+ return strcmp(fileName1,fileName2);
+
+ return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
+}
+
+#ifndef BUFREADCOMMENT
+#define BUFREADCOMMENT (0x400)
+#endif
+
+/*
+ Locate the Central directory of a zipfile (at the end, just before
+ the global comment)
+*/
+local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));
+local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
+{
+ unsigned char* buf;
+ ZPOS64_T uSizeFile;
+ ZPOS64_T uBackRead;
+ ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+ ZPOS64_T uPosFound=0;
+
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return 0;
+
+
+ uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+ uMaxBack = uSizeFile;
+
+ buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+ if (buf==NULL)
+ return 0;
+
+ uBackRead = 4;
+ while (uBackRead<uMaxBack)
+ {
+ uLong uReadSize;
+ ZPOS64_T uReadPos ;
+ int i;
+ if (uBackRead+BUFREADCOMMENT>uMaxBack)
+ uBackRead = uMaxBack;
+ else
+ uBackRead+=BUFREADCOMMENT;
+ uReadPos = uSizeFile-uBackRead ;
+
+ uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+ (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ break;
+
+ if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+ break;
+
+ for (i=(int)uReadSize-3; (i--)>0;)
+ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+ ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+ {
+ uPosFound = uReadPos+i;
+ break;
+ }
+
+ if (uPosFound!=0)
+ break;
+ }
+ TRYFREE(buf);
+ return uPosFound;
+}
+
+
+/*
+ Locate the Central directory 64 of a zipfile (at the end, just before
+ the global comment)
+*/
+local ZPOS64_T unz64local_SearchCentralDir64 OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream));
+
+local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream)
+{
+ unsigned char* buf;
+ ZPOS64_T uSizeFile;
+ ZPOS64_T uBackRead;
+ ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+ ZPOS64_T uPosFound=0;
+ uLong uL;
+ ZPOS64_T relativeOffset;
+
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return 0;
+
+
+ uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+ uMaxBack = uSizeFile;
+
+ buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+ if (buf==NULL)
+ return 0;
+
+ uBackRead = 4;
+ while (uBackRead<uMaxBack)
+ {
+ uLong uReadSize;
+ ZPOS64_T uReadPos;
+ int i;
+ if (uBackRead+BUFREADCOMMENT>uMaxBack)
+ uBackRead = uMaxBack;
+ else
+ uBackRead+=BUFREADCOMMENT;
+ uReadPos = uSizeFile-uBackRead ;
+
+ uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+ (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ break;
+
+ if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+ break;
+
+ for (i=(int)uReadSize-3; (i--)>0;)
+ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+ ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
+ {
+ uPosFound = uReadPos+i;
+ break;
+ }
+
+ if (uPosFound!=0)
+ break;
+ }
+ TRYFREE(buf);
+ if (uPosFound == 0)
+ return 0;
+
+ /* Zip64 end of central directory locator */
+ if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return 0;
+
+ /* the signature, already checked */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return 0;
+
+ /* number of the disk with the start of the zip64 end of central directory */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return 0;
+ if (uL != 0)
+ return 0;
+
+ /* relative offset of the zip64 end of central directory record */
+ if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
+ return 0;
+
+ /* total number of disks */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return 0;
+ if (uL != 1)
+ return 0;
+
+ /* Goto end of central directory record */
+ if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return 0;
+
+ /* the signature */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return 0;
+
+ if (uL != 0x06064b50)
+ return 0;
+
+ return relativeOffset;
+}
+
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
+ "zlib/zlib114.zip".
+ If the zipfile cannot be opened (file doesn't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+*/
+local unzFile unzOpenInternal (const void *path,
+ zlib_filefunc64_32_def* pzlib_filefunc64_32_def,
+ int is64bitOpenFunction)
+{
+ unz64_s us;
+ unz64_s *s;
+ ZPOS64_T central_pos;
+ uLong uL;
+
+ uLong number_disk; /* number of the current dist, used for
+ spaning ZIP, unsupported, always 0*/
+ uLong number_disk_with_CD; /* number the the disk with central dir, used
+ for spaning ZIP, unsupported, always 0*/
+ ZPOS64_T number_entry_CD; /* total number of entries in
+ the central dir
+ (same than number_entry on nospan) */
+
+ int err=UNZ_OK;
+
+ if (unz_copyright[0]!=' ')
+ return NULL;
+
+ us.z_filefunc.zseek32_file = NULL;
+ us.z_filefunc.ztell32_file = NULL;
+ if (pzlib_filefunc64_32_def==NULL)
+ fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
+ else
+ us.z_filefunc = *pzlib_filefunc64_32_def;
+ us.is64bitOpenFunction = is64bitOpenFunction;
+
+
+
+ us.filestream = ZOPEN64(us.z_filefunc,
+ path,
+ ZLIB_FILEFUNC_MODE_READ |
+ ZLIB_FILEFUNC_MODE_EXISTING);
+ if (us.filestream==NULL)
+ return NULL;
+
+ central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
+ if (central_pos)
+ {
+ uLong uS;
+ ZPOS64_T uL64;
+
+ us.isZip64 = 1;
+
+ if (ZSEEK64(us.z_filefunc, us.filestream,
+ central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+ /* the signature, already checked */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* size of zip64 end of central directory record */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* version made by */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* version needed to extract */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of this disk */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of the disk with the start of the central directory */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central directory on this disk */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central directory */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if ((number_entry_CD!=us.gi.number_entry) ||
+ (number_disk_with_CD!=0) ||
+ (number_disk!=0))
+ err=UNZ_BADZIPFILE;
+
+ /* size of the central directory */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* offset of start of central directory with respect to the
+ starting disk number */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ us.gi.size_comment = 0;
+ }
+ else
+ {
+ central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
+ if (central_pos==0)
+ err=UNZ_ERRNO;
+
+ us.isZip64 = 0;
+
+ if (ZSEEK64(us.z_filefunc, us.filestream,
+ central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+ /* the signature, already checked */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of this disk */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of the disk with the start of the central directory */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central dir on this disk */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ us.gi.number_entry = uL;
+
+ /* total number of entries in the central dir */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ number_entry_CD = uL;
+
+ if ((number_entry_CD!=us.gi.number_entry) ||
+ (number_disk_with_CD!=0) ||
+ (number_disk!=0))
+ err=UNZ_BADZIPFILE;
+
+ /* size of the central directory */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ us.size_central_dir = uL;
+
+ /* offset of start of central directory with respect to the
+ starting disk number */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ us.offset_central_dir = uL;
+
+ /* zipfile comment length */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
+ (err==UNZ_OK))
+ err=UNZ_BADZIPFILE;
+
+ if (err!=UNZ_OK)
+ {
+ ZCLOSE64(us.z_filefunc, us.filestream);
+ return NULL;
+ }
+
+ us.byte_before_the_zipfile = central_pos -
+ (us.offset_central_dir+us.size_central_dir);
+ us.central_pos = central_pos;
+ us.pfile_in_zip_read = NULL;
+ us.encrypted = 0;
+
+
+ s=(unz64_s*)ALLOC(sizeof(unz64_s));
+ if( s != NULL)
+ {
+ *s=us;
+ unzGoToFirstFile((unzFile)s);
+ }
+ return (unzFile)s;
+}
+
+
+extern unzFile ZEXPORT unzOpen2 (const char *path,
+ zlib_filefunc_def* pzlib_filefunc32_def)
+{
+ if (pzlib_filefunc32_def != NULL)
+ {
+ zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
+ fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
+ return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0);
+ }
+ else
+ return unzOpenInternal(path, NULL, 0);
+}
+
+extern unzFile ZEXPORT unzOpen2_64 (const void *path,
+ zlib_filefunc64_def* pzlib_filefunc_def)
+{
+ if (pzlib_filefunc_def != NULL)
+ {
+ zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
+ zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
+ zlib_filefunc64_32_def_fill.ztell32_file = NULL;
+ zlib_filefunc64_32_def_fill.zseek32_file = NULL;
+ return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1);
+ }
+ else
+ return unzOpenInternal(path, NULL, 1);
+}
+
+extern unzFile ZEXPORT unzOpen (const char *path)
+{
+ return unzOpenInternal(path, NULL, 0);
+}
+
+extern unzFile ZEXPORT unzOpen64 (const void *path)
+{
+ return unzOpenInternal(path, NULL, 1);
+}
+
+/*
+ Close a ZipFile opened with unzipOpen.
+ If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
+ these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+ return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzClose (unzFile file)
+{
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+
+ if (s->pfile_in_zip_read!=NULL)
+ unzCloseCurrentFile(file);
+
+ ZCLOSE64(s->z_filefunc, s->filestream);
+ TRYFREE(s);
+ return UNZ_OK;
+}
+
+
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info)
+{
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ *pglobal_info=s->gi;
+ return UNZ_OK;
+}
+
+extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32)
+{
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ /* to do : check if number_entry is not truncated */
+ pglobal_info32->number_entry = (uLong)s->gi.number_entry;
+ pglobal_info32->size_comment = s->gi.size_comment;
+ return UNZ_OK;
+}
+/*
+ Translate date/time from Dos format to tm_unz (readable more easilty)
+*/
+local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm)
+{
+ ZPOS64_T uDate;
+ uDate = (ZPOS64_T)(ulDosDate>>16);
+ ptm->tm_mday = (uInt)(uDate&0x1f) ;
+ ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
+ ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
+
+ ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
+ ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
+ ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
+}
+
+/*
+ Get Info about the current file in the zipfile, with internal only info
+*/
+local int unz64local_GetCurrentFileInfoInternal OF((unzFile file,
+ unz_file_info64 *pfile_info,
+ unz_file_info64_internal
+ *pfile_info_internal,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+
+local int unz64local_GetCurrentFileInfoInternal (unzFile file,
+ unz_file_info64 *pfile_info,
+ unz_file_info64_internal
+ *pfile_info_internal,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize)
+{
+ unz64_s* s;
+ unz_file_info64 file_info;
+ unz_file_info64_internal file_info_internal;
+ int err=UNZ_OK;
+ uLong uMagic;
+ long lSeek=0;
+ uLong uL;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (ZSEEK64(s->z_filefunc, s->filestream,
+ s->pos_in_central_dir+s->byte_before_the_zipfile,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+
+ /* we check the magic */
+ if (err==UNZ_OK)
+ {
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if (uMagic!=0x02014b50)
+ err=UNZ_BADZIPFILE;
+ }
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)