included commits to RCS files with non-trunk default branches.
--- /dev/null
+<h2> ZIP Obfuscation </h2> Using obfuscations like XOR.
+
+<!--border--> <date> 15. July 2002 </date>
+
+<h3> The EXT/IO calls </h3>
+
+<P>
+ You really should read the section about the
+ <a href="zzip-extio.html">EXT/IO feature</a> of the zziplib since the
+ obfuscation routines are built on top of it. In order to use obfuscation,
+ you will generally need to use all the three additional argument that
+ can be passsed to _open_ext_io functions. For the XOR-example, only one
+ IO-handler is modified being the read()-call that will simply xor each
+ data byte upon read with a specific value. It two advantages - doing an
+ xor twice does yield the same data, so as a developer you do not have
+ to wonder about the encryption/decryption pair, and it is a stateless
+ obfuscation that does not need to know about the current position
+ within the zip-datafile or zippedfile-datatream.
+</P><P>
+ The examples provided just use a simple routine for xoring data that
+ is defined in all the three of the example programs: <pre>
+ static int xor_value = 0x55;
+ static zzip_ssize_t xor_read (int f, void* p, zzip_size_t l)
+ {
+ zzip_size_t r = read(f, p, l);
+ zzip_size_t i; char* q = p;
+ for (x=0; x < r; x++) q[x] ^= xor_value;
+ return r;
+ }
+ </pre>
+ and place this routine into the io-handlers after initializing
+ the structure: <pre>
+ zzip_init_io (&xor_handlers, 0); xor_handlers.read = &xor_read;
+ </pre>
+</P>
+
+<h3> The examples </h3>
+
+<P>
+ There are three example programs. The first one is
+ <a href="zzxorcopy.c">zzxorcopy.c</a> which actually is not a zziplib
+ based program. It just opens a file via stdio, loops through all data bytes
+ it can read thereby xor'ing it, and writes it out to the output file. A
+ call like <code><nobr>"zzxorcopy file.zip file.dat"</nobr></code> will
+ create an obfuscated dat-file from a zip-file that has been possibly
+ create with the normal infozip tools or any other archive program to
+ generate a zip-file. The output dat-file is not recognized by normal
+ zip-enabled apps - the filemagic is obfuscated too. This output
+ dat-file however is subject to the other two example programs.
+</P><P>
+ The <a href="zzxordir.c">zzxordir.c</a> program will open such an obfuscated
+ zip file and decode the central directory of that zip. Everything is
+ still there in just the way it can be shown with the normal unzip
+ programs and routines. And the <a href="zzxorcat.c">zzxorcat.c</a> program
+ can extract data from this obfuscated zip - and print it un-obfuscated
+ to the screen. These example programs can help you jumpstart with
+ your own set of obfuscator routines, possibly more complex ones.
+</P><P>
+ By the way, just compare those with their non-xor counterparts that
+ you can find in <a href="zzdir.c">zzdir.c</a> and
+ <a href="zzxorcat.c">zzxorcat.c</a>. Notice that the difference is
+ in the setup part until the _open_ call after which one can just
+ use the normal zzip_ routines on that obfuscated file. This is
+ great for developing since you can start of with the magic-wrappers
+ working on real-files then slowly turning to pack-files that hold
+ most of the data and finally ending with a zip-only and obfuscated
+ dat-file for your project.
+</P>
+
+<h3> Some rationale </h3>
+
+<P>
+ Some people might ask why not adding standard zip-encryption. Well,
+ first of all the standard zip-encryption has not been strong enough
+ for modern computers, and there are hacker tools that even a
+ half-literate computer-user can use to crack the password of a
+ zip-archive. Furthermore, adding real encryption is a heavy weight
+ that many people do not need, see the last argument for seeing the
+ standard one is useless anyway, and adding a non-standard one
+ should not be the case of the standard zziplib either, ye know.
+</P><P>
+ On the other hand, obfuscation is a means to fear off half-literates
+ just as well - there are no premade tools for the obfuscation you
+ can invent from the xor examples. And a hacker that can de-obfuscate
+ such a dat-file is able to dissassemble your program as well thereby
+ going to see your decryption routine <em>and</em> the decryption key.
+ Although there is a difference, it just ranges on about times and
+ exprience, not magnitudes. Remember the old saying: you can irritate
+ some people for some time but not irritate all people for all the time.
+ As for encryption of artwork and AI scripts in games and applications,
+ just keep in mind that the final recipient has the decryption key on
+ his system anyway, just obfuscated. So each such encryption is nothing
+ more than just a clever form of obfuscation, nothing mathemetical strong.
+</P><P>
+ Some other people might ask why to obfuscate anyway. Well, the reason
+ is theft. Even people who write opensource free software generally
+ like to get some reward for what they do, some fame or atleast some
+ sweet dream to have helped the world go a bit easier in the future.
+ As for program text this is quite natural for the programmers who
+ pick up some code from somewhere else - it happens that most of them
+ have gone through some formation and they know how hard it is to get
+ even some lines of code out of your brain. This is not the case for
+ some artwork and AI parameters, people do not have much respect for
+ those - they just pick it up, put it under their umbrella, and
+ that's it - they even claim they could have done that themselves,
+ and in most cases it is that they never have been really trying to
+ do it and think of it as being comparable to that action-art they've
+ seen on TV.
+</P><P>
+ Just be sure that there is nothing wrong with obfuscating
+ things for a binary distribution of your program even for the
+ opensource case - the program text itself is an obfuscation in its
+ source form when being compiled into cpu instructions. Still, the
+ interested people can get hold of the source code since you provide
+ it somewhere and actually the original programmers like to hear
+ from literate people who could help with modifying the project. The
+ same is true for you artwork and AI scripts, the interested people
+ can still see them in the opensource project material, but only
+ those will look who dare to, not just the halfwit next door.
+</P><P>
+ Well, you do not need to that on the other hand - ID software has
+ shown that it can be very helpful since people will start to
+ write new maps and new bots, pack them and publish them. An open
+ data format is a form of attraction for people who can use a
+ graphics program and an editor but who do not know how to program.
+ And if you use obfuscation within an opensource program, it is
+ surely enought to just use the xor-format presented here, so that
+ it easy for third people to get involved if they want to, they
+ just have to rewrite their new datapacks with zzxorcopy, and
+ that's it.
+</P><P>
+ As for the non-opensource projects, be aware that there are
+ some ways to even staticlink the zziplib into your project, so
+ you can even hide that you used zip tools to create your dat files.
+ This is well enough for anyone to do - as soon as a hacker will
+ get to the point to notice you used a zip format, he would have
+ had found any other deobfusation or decryption routine as well.
+ If you are frightened, just encrypt the executable with tools
+ you bought from somewhere else. On the other hand, should there
+ be problems or bugs, you have an easier time to find them when
+ they could be caused by your dat entries, and it is again easy
+ to send a fixup file to your clients, since the command line
+ tools are just a breeze compared with some other anti-hacking
+ tools you'll find on the market.
+</P><P>
+ Well, hope this is enough rationale to tell you that I do not
+ see a need to implement anything more than obfuscation within
+ zziplib - if you need real encryption, use real encryption
+ software and its fileformat that supports it, not zip files.
+</P>
+
+<p align="right"><small><small>
+<a href="copying.html">staticlinking?</a>
+</small></small></p>
--- /dev/null
+#ifndef ZZIP_INTERNAL_DIRENT_H
+#define ZZIP_INTERNAL_DIRENT_H
+#include <zzip/conf.h>
+
+/*
+ * DO NOT USE THIS CODE.
+ *
+ * It is an internal header file for zziplib that carries some inline
+ * functions (or just static members) and a few defines, simply to be
+ * able to reuse these across - and have everything in a specific place.
+ *
+ * Copyright (c) 2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#ifdef ZZIP_HAVE_DIRENT_H
+#define USE_DIRENT 1
+
+#define _zzip_opendir opendir
+#define _zzip_readdir readdir
+#define _zzip_closedir closedir
+#define _zzip_rewinddir rewinddir
+#define _zzip_telldir telldir
+#define _zzip_seekdir seekdir
+#define _zzip_DIR DIR
+
+#include <dirent.h>
+
+#elif defined ZZIP_HAVE_WINBASE_H
+#define USE_DIRENT 2
+
+#define _zzip_opendir win32_opendir
+#define _zzip_readdir win32_readdir
+#define _zzip_closedir win32_closedir
+#define _zzip_rewinddir win32_rewinddir
+#define _zzip_telldir win32_telldir
+#define _zzip_seekdir win32_seekdir
+#define _zzip_DIR DIR
+
+/*
+ * DIRENT.H (formerly DIRLIB.H)
+ *
+ * by M. J. Weinstein Released to public domain 1-Jan-89
+ *
+ * Because I have heard that this feature (opendir, readdir, closedir)
+ * it so useful for programmers coming from UNIX or attempting to port
+ * UNIX code, and because it is reasonably light weight, I have included
+ * it in the Mingw32 package. I have also added an implementation of
+ * rewinddir, seekdir and telldir.
+ * - Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
+ *
+ * This code is distributed in the hope that is will be useful but
+ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ * DISCLAMED. This includeds but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include <io.h>
+
+struct dirent
+{
+ long d_ino; /* Always zero. */
+ unsigned short d_reclen; /* Always zero. */
+ unsigned short d_namlen; /* Length of name in d_name. */
+ char* d_name; /* File name. */
+ /* NOTE: The name in the dirent structure points to the name in the
+ * finddata_t structure in the DIR. */
+};
+
+/*
+ * This is an internal data structure. Good programmers will not use it
+ * except as an argument to one of the functions below.
+ */
+typedef struct
+{
+ /* disk transfer area for this dir */
+ struct _finddata_t dd_dta;
+
+ /* dirent struct to return from dir (NOTE: this makes this thread
+ * safe as long as only one thread uses a particular DIR struct at
+ * a time) */
+ struct dirent dd_dir;
+
+ /* _findnext handle */
+ long dd_handle;
+
+ /*
+ * Status of search:
+ * 0 = not started yet (next entry to read is first entry)
+ * -1 = off the end
+ * positive = 0 based index of next entry
+ */
+ short dd_stat;
+
+ /* given path for dir with search pattern (struct is extended) */
+ char dd_name[1];
+} DIR;
+
+/*
+ * dirent.c
+ *
+ * Derived from DIRLIB.C by Matt J. Weinstein
+ * This note appears in the DIRLIB.H
+ * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89
+ *
+ * Updated by Jeremy Bettis <jeremy@hksys.com>
+ * Significantly revised and rewinddir, seekdir and telldir added by Colin
+ * Peters <colin@fu.is.saga-u.ac.jp>
+ */
+
+#include <direct.h>
+#include <errno.h>
+#include <io.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#define win32_SUFFIX "*"
+#define win32_SLASH "\\"
+
+#ifndef S_ISDIR
+#define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR) /* is a directory */
+#endif S_ISDIR
+
+
+/*
+ opendir
+
+ Returns a pointer to a DIR structure appropriately filled in to begin
+ searching a directory.
+*/
+static DIR*
+win32_opendir (const char *szPath)
+{
+ DIR *nd;
+ struct _stat statDir;
+
+ errno = 0;
+
+ if (!szPath) {
+ errno = EFAULT;
+ return (DIR *) 0;
+ }
+
+ if (szPath[0] == '\0') {
+ errno = ENOTDIR;
+ return (DIR *) 0;
+ }
+
+ /* Attempt to determine if the given path really is a directory. */
+ if (_stat (szPath, &statDir)) {
+ /* Error, stat should have set an error value. */
+ return (DIR *) 0;
+ }
+
+ if (!S_ISDIR (statDir.st_mode)) {
+ /* Error, stat reports not a directory. */
+ errno = ENOTDIR;
+ return (DIR *) 0;
+ }
+
+ /* Allocate enough space to store DIR structure and the complete *
+ directory path given. */
+ nd = (DIR *) calloc (1, sizeof (DIR) + strlen (szPath)
+ + strlen (win32_SLASH) + strlen (win32_SUFFIX));
+
+ if (!nd) {
+ /* Error, out of memory. */
+ errno = ENOMEM;
+ return (DIR *) 0;
+ }
+
+ /* Create the search expression. */
+ strcpy (nd->dd_name, szPath);
+
+ /* Add on a slash if the path does not end with one. */
+ if (nd->dd_name[0] != '\0' &&
+ nd->dd_name[strlen (nd->dd_name) - 1] != '/' &&
+ nd->dd_name[strlen (nd->dd_name) - 1] != '\\') {
+ strcat (nd->dd_name, win32_SLASH);
+ }
+
+ /* Add on the search pattern */
+ strcat (nd->dd_name, win32_SUFFIX);
+
+ /* Initialize handle to -1 so that a premature closedir doesn't try * to
+ call _findclose on it. */
+ nd->dd_handle = -1;
+
+ /* Initialize the status. */
+ nd->dd_stat = 0;
+
+ /* Initialize the dirent structure. ino and reclen are invalid under *
+ Win32, and name simply points at the appropriate part of the *
+ findfirst_t structure. */
+ nd->dd_dir.d_ino = 0;
+ nd->dd_dir.d_reclen = 0;
+ nd->dd_dir.d_namlen = 0;
+ nd->dd_dir.d_name = nd->dd_dta.name;
+
+ return nd;
+}
+
+/*
+ readdir
+
+ Return a pointer to a dirent structure filled with the information on the
+ next entry in the directory.
+*/
+static struct dirent *
+win32_readdir (DIR * dirp)
+{
+ errno = 0;
+
+ /* Check for valid DIR struct. */
+ if (!dirp) {
+ errno = EFAULT;
+ return (struct dirent *) 0;
+ }
+
+ if (dirp->dd_dir.d_name != dirp->dd_dta.name) {
+ /* The structure does not seem to be set up correctly. */
+ errno = EINVAL;
+ return (struct dirent *) 0;
+ }
+
+ if (dirp->dd_stat < 0) {
+ /* We have already returned all files in the directory * (or the
+ structure has an invalid dd_stat). */
+ return (struct dirent *) 0;
+ } else if (dirp->dd_stat == 0) {
+ /* We haven't started the search yet. */
+ /* Start the search */
+ dirp->dd_handle = _findfirst (dirp->dd_name, &(dirp->dd_dta));
+
+ if (dirp->dd_handle == -1) {
+ /* Whoops! Seems there are no files in that * directory. */
+ dirp->dd_stat = -1;
+ } else {
+ dirp->dd_stat = 1;
+ }
+ } else {
+ /* Get the next search entry. */
+ if (_findnext (dirp->dd_handle, &(dirp->dd_dta))) {
+ /* We are off the end or otherwise error. */
+ _findclose (dirp->dd_handle);
+ dirp->dd_handle = -1;
+ dirp->dd_stat = -1;
+ } else {
+ /* Update the status to indicate the correct * number. */
+ dirp->dd_stat++;
+ }
+ }
+
+ if (dirp->dd_stat > 0) {
+ /* Successfully got an entry. Everything about the file is * already
+ appropriately filled in except the length of the * file name. */
+ dirp->dd_dir.d_namlen = (unsigned short) strlen (dirp->dd_dir.d_name);
+ return &dirp->dd_dir;
+ }
+
+ return (struct dirent *) 0;
+}
+
+/*
+ closedir
+
+ Frees up resources allocated by opendir.
+*/
+static int
+win32_closedir (DIR * dirp)
+{
+ int rc;
+
+ errno = 0;
+ rc = 0;
+
+ if (!dirp) {
+ errno = EFAULT;
+ return -1;
+ }
+
+ if (dirp->dd_handle != -1) {
+ rc = _findclose (dirp->dd_handle);
+ }
+
+ /* Delete the dir structure. */
+ free (dirp);
+
+ return rc;
+}
+
+/*
+ rewinddir
+
+ Return to the beginning of the directory "stream". We simply call findclose
+ and then reset things like an opendir.
+*/
+static void
+win32_rewinddir (DIR * dirp)
+{
+ errno = 0;
+
+ if (!dirp) {
+ errno = EFAULT;
+ return;
+ }
+
+ if (dirp->dd_handle != -1) {
+ _findclose (dirp->dd_handle);
+ }
+
+ dirp->dd_handle = -1;
+ dirp->dd_stat = 0;
+}
+
+/*
+ telldir
+
+ Returns the "position" in the "directory stream" which can be used with
+ seekdir to go back to an old entry. We simply return the value in stat.
+*/
+static long
+win32_telldir (DIR * dirp)
+{
+ errno = 0;
+
+ if (!dirp) {
+ errno = EFAULT;
+ return -1;
+ }
+ return dirp->dd_stat;
+}
+
+/*
+ seekdir
+
+ Seek to an entry previously returned by telldir. We rewind the directory
+ and call readdir repeatedly until either dd_stat is the position number
+ or -1 (off the end). This is not perfect, in that the directory may
+ have changed while we weren't looking. But that is probably the case with
+ any such system.
+*/
+static void
+win32_seekdir (DIR * dirp, long lPos)
+{
+ errno = 0;
+
+ if (!dirp) {
+ errno = EFAULT;
+ return;
+ }
+
+ if (lPos < -1) {
+ /* Seeking to an invalid position. */
+ errno = EINVAL;
+ return;
+ } else if (lPos == -1) {
+ /* Seek past end. */
+ if (dirp->dd_handle != -1) {
+ _findclose (dirp->dd_handle);
+ }
+ dirp->dd_handle = -1;
+ dirp->dd_stat = -1;
+ } else {
+ /* Rewind and read forward to the appropriate index. */
+ win32_rewinddir (dirp);
+
+ while ((dirp->dd_stat < lPos) && win32_readdir (dirp));
+ }
+}
+
+#else
+#define USE_DIRENT 0
+
+#define _zzip_opendir(_N_) 0
+#define _zzip_readdir(_D_) 0
+#define _zzip_closedir(_D_) /* omit return code */
+#define _zzip_rewinddir(_D_)
+#define _zzip_telldir(_D_) 0
+#define _zzip_seekdir(_D_,_V_) /* omit return code */
+#define _zzip_DIR void*
+
+/* end of DIRENT implementation */
+#endif
+
+/* once */
+#endif
--- /dev/null
+#ifndef __ZZIP_INTERNAL_MMAP_H
+#define __ZZIP_INTERNAL_MMAP_H
+#include <zzip/conf.h>
+
+/*
+ * DO NOT USE THIS CODE.
+ *
+ * It is an internal header file for zziplib that carries some inline
+ * functions (or just static members) and a few defines, simply to be
+ * able to reuse these across - and have everything in a specific place.
+ *
+ * Copyright (c) 2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#ifdef _USE_MMAP
+#if defined ZZIP_HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#define USE_POSIX_MMAP 1
+#elif defined ZZIP_HAVE_WINBASE_H || defined WIN32
+#include <windows.h>
+#define USE_WIN32_MMAP 1
+#else
+#undef _USE_MMAP
+#endif
+#endif
+
+/* -------------- specify MMAP function imports --------------------------- */
+
+#if defined USE_POSIX_MMAP
+#define USE_MMAP 1
+
+#define _zzip_mmap(user, fd, offs, len) \
+ mmap (0, len, PROT_READ, MAP_SHARED, fd, offs)
+#define _zzip_munmap(user, ptr, len) \
+ munmap (ptr, len)
+#define _zzip_getpagesize(user) getpagesize()
+
+#ifndef MAP_FAILED /* hpux10.20 does not have it */
+#define MAP_FAILED ((void*)(-1))
+#endif
+
+#elif defined USE_WIN32_MMAP
+#define USE_MMAP 1
+#ifndef MAP_FAILED
+#define MAP_FAILED 0
+#endif
+/* we (ab)use the "*user" variable to store the FileMapping handle */
+ /* which assumes (sizeof(long) == sizeof(HANDLE)) */
+
+static size_t win32_getpagesize ()
+{
+ SYSTEM_INFO si; GetSystemInfo (&si);
+ return si.dwAllocationGranularity;
+}
+static void* win32_mmap (long* user, int fd, zzip_off_t offs, size_t len)
+{
+ if (! user || *user != 1) /* || offs % getpagesize() */
+ return 0;
+ {
+ HANDLE hFile = (HANDLE)_get_osfhandle(fd);
+ if (hFile)
+ *user = (int) CreateFileMapping (hFile, 0, PAGE_READONLY, 0, 0, NULL);
+ if (*user)
+ {
+ char* p = 0;
+ p = MapViewOfFile(*(HANDLE*)user, FILE_MAP_READ, 0, offs, len);
+ if (p) return p + offs;
+ CloseHandle (*(HANDLE*)user); *user = 1;
+ }
+ return MAP_FAILED;
+ }
+}
+static void win32_munmap (long* user, char* fd_map, size_t len)
+{
+ UnmapViewOfFile (fd_map);
+ CloseHandle (*(HANDLE*)user); *user = 1;
+}
+
+#define _zzip_mmap(user, fd, offs, len) \
+ win32_mmap ((long*) &(user), fd, offs, len)
+#define _zzip_munmap(user, ptr, len) \
+ win32_munmap ((long*) &(user), ptr, len)
+#define _zzip_getpagesize(user) win32_getpagesize()
+
+#else /* disable */
+#define USE_MMAP 0
+/* USE_MAP is intentional: we expect the compiler to do some "code removal"
+ * on any source code enclosed in if (USE_MMAP) {...} i.e. the unreachable
+ * branch of an if (0) {....} is not emitted to the final object binary. */
+
+#ifndef MAP_FAILED
+#define MAP_FAILED 0
+#endif
+
+#define _zzip_mmap(user, fd, offs, len) (MAP_FAILED)
+#define _zzip_munmap(user, ptr, len) {}
+#define _zzip_getpagesize(user) 1
+
+#endif /* USE_MMAP defines */
+
+
+#endif
--- /dev/null
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 1999,2000,2001,2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#include <zzip/lib.h> /* exported... */
+#include <zzip/file.h>
+#include <stddef.h> /*offsetof*/
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef ZZIP_HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#else
+#include <stdio.h>
+#endif
+
+#include <zzip/__dirent.h>
+
+#ifndef offsetof
+#pragma warning had to DEFINE offsetof as it was not in stddef.h
+#define offsetof(T,M) ((unsigned)(& ((T*)0)->M))
+#endif
+
+#ifdef ZZIP_HAVE_SYS_STAT_H
+/* MSVC does have IFbitmask but not the corresponding IStests */
+# if !defined S_ISDIR && defined S_IFDIR
+# define S_ISDIR(_X_) ((_X_) & S_IFDIR)
+# endif
+# if !defined S_ISREG && defined S_IFREG
+# define S_ISREG(_X_) ((_X_) & S_IFREG)
+# endif
+#endif
+
+/**
+ * This function is the equivalent of a => rewinddir(2) for a realdir or
+ * the zipfile in place of a directory. The ZZIP_DIR handle returned from
+ * => zzip_opendir has a flag saying realdir or zipfile. As for a zipfile,
+ * the filenames will include the filesubpath, so take care.
+ */
+void
+zzip_rewinddir(ZZIP_DIR * dir)
+{
+ if (! dir) return;
+
+ if (USE_DIRENT && dir->realdir)
+ {
+ _zzip_rewinddir(dir->realdir);
+ return;
+ }
+
+ if (dir->hdr0)
+ dir->hdr = dir->hdr0;
+ else
+ dir->hdr = 0;
+}
+
+#if ! USE_DIRENT
+#define real_readdir(_X_) 1
+#else
+static int
+real_readdir(ZZIP_DIR* dir)
+{
+ struct stat st = { 0 };
+ char filename[PATH_MAX];
+ struct dirent* dirent = _zzip_readdir(dir->realdir);
+ if (! dirent) return 0;
+
+ dir->dirent.d_name = dirent->d_name;
+ strcpy(filename, dir->realname);
+ strcat(filename, "/");
+ strcat(filename, dirent->d_name);
+
+ if (stat(filename, &st) == -1)
+ return -1;
+
+ dir->dirent.d_csize = dir->dirent.st_size = st.st_size;
+
+ if (st.st_mode)
+ {
+ if (! S_ISREG(st.st_mode))
+ {
+ dir->dirent.d_compr = st.st_mode;
+ dir->dirent.d_compr |= 0x80000000;
+ /* makes it effectively negative,
+ * but can still be fed to S_ISXXX(x) */
+ }else
+ {
+ dir->dirent.d_compr = 0; /* stored */
+ }
+ }else
+ {
+ dir->dirent.d_compr = 0; /* stored */
+ }
+
+ return 1;
+}
+#endif
+
+/**
+ * This function is the equivalent of a => readdir(2) for a realdir
+ * or a zipfile referenced by the ZZIP_DIR returned from => zzip_opendir.
+ *
+ * The ZZIP_DIR handle (as returned by => zzip_opendir) contains a few more
+ * entries than being copied into the ZZIP_DIRENT. The only valid fields in
+ * a ZZIP_DIRENT are d_name (the file name), d_compr (compression), d_csize
+ * (compressed size), st_size (uncompressed size).
+ */
+ZZIP_DIRENT*
+zzip_readdir(ZZIP_DIR * dir)
+{
+ if (! dir) { errno=EBADF; return 0; }
+
+ if (USE_DIRENT && dir->realdir)
+ {
+ if (! real_readdir(dir))
+ return 0;
+ }else
+ {
+ if (! dir->hdr) return 0;
+
+ dir->dirent.d_name = dir->hdr->d_name;
+ dir->dirent.d_compr = dir->hdr->d_compr;
+
+ dir->dirent.d_csize = dir->hdr->d_csize;
+ dir->dirent.st_size = dir->hdr->d_usize;
+
+ if (! dir->hdr->d_reclen) dir->hdr = 0;
+ else dir->hdr = (struct zzip_dir_hdr *)
+ ((char *)dir->hdr + dir->hdr->d_reclen);
+ }
+ return &dir->dirent;
+}
+
+/** => zzip_rewinddir
+ * This function is the equivalent of => telldir(2) for a realdir or zipfile.
+ */
+zzip_off_t
+zzip_telldir(ZZIP_DIR* dir)
+{
+ if (! dir) { errno=EBADF; return -1; }
+
+ if (USE_DIRENT && dir->realdir)
+ {
+ return _zzip_telldir(dir->realdir);
+ }else
+ {
+ return ((zzip_off_t) ((char*) dir->hdr - (char*) dir->hdr0));
+ }
+}
+
+/** => zzip_rewinddir
+ * This function is the equivalent of => seekdir(2) for a realdir or zipfile.
+ */
+void
+zzip_seekdir(ZZIP_DIR* dir, zzip_off_t offset)
+{
+ if (! dir) return;
+
+ if (USE_DIRENT && dir->realdir)
+ {
+ _zzip_seekdir(dir->realdir, offset);
+ }else
+ {
+ dir->hdr = (struct zzip_dir_hdr*)
+ (dir->hdr0 ? (char*) dir->hdr0 + (size_t) offset : 0);
+ }
+}
+
+#if defined ZZIP_LARGEFILE_RENAME && defined EOVERFLOW && defined PIC
+#undef zzip_seekdir /* zzip_seekdir64 */
+#undef zzip_telldir /* zzip_telldir64 */
+
+long zzip_telldir(ZZIP_DIR* dir)
+{
+ off_t off = zzip_telldir64 (dir);
+ long offs = off;
+ if (offs != off) { errno = EOVERFLOW; return -1; }
+ return offs;
+}
+
+void zzip_seekdir(ZZIP_DIR* dir, long offset)
+{
+ zzip_seekdir64 (dir, offset);
+}
+#endif
+
+/**
+ * This function is the equivalent of => opendir(3) for a realdir or zipfile.
+ * <p>
+ * This function has some magic - if the given argument-path
+ * is a directory, it will wrap a real => opendir(3) into the ZZIP_DIR
+ * structure. Otherwise it will divert to => zzip_dir_open which
+ * can also attach a ".zip" extension if needed to find the archive.
+ * <p>
+ * the error-code is mapped to => errno(3).
+ */
+ZZIP_DIR*
+zzip_opendir(zzip_char_t* filename)
+{
+ return zzip_opendir_ext_io (filename, 0, 0, 0);
+}
+
+/** => zzip_opendir
+ * This function uses explicit ext and io instead of the internal
+ * defaults, setting them to zero is equivalent to => zzip_opendir
+ */
+ZZIP_DIR*
+zzip_opendir_ext_io(zzip_char_t* filename, int o_modes,
+ zzip_strings_t* ext, zzip_plugin_io_t io)
+{
+ zzip_error_t e;
+ ZZIP_DIR* dir;
+
+# ifdef ZZIP_HAVE_SYS_STAT_H
+ struct stat st;
+# endif
+
+ if (o_modes & (ZZIP_PREFERZIP|ZZIP_ONLYZIP)) goto try_zzip;
+ try_real:
+
+# ifdef ZZIP_HAVE_SYS_STAT_H
+ if (stat(filename, &st) >= 0 && S_ISDIR(st.st_mode)
+ ){
+ if (USE_DIRENT)
+ {
+ _zzip_DIR* realdir = _zzip_opendir(filename);
+ if (realdir)
+ {
+ if (! (dir = (ZZIP_DIR *)calloc(1, sizeof (*dir))))
+ {
+ _zzip_closedir(realdir);
+ return 0;
+ }else
+ {
+ dir->realdir = realdir;
+ dir->realname = strdup(filename);
+ return dir;
+ }
+ }
+ }
+ return 0;
+ }
+# endif /* HAVE_SYS_STAT_H */
+
+ try_zzip:
+ dir = zzip_dir_open_ext_io (filename, &e, ext, io);
+ if (! dir && (o_modes & ZZIP_PREFERZIP)) goto try_real;
+ if (e) errno = zzip_errno(e);
+ return dir;
+}
+
+/**
+ * This function is the equivalent of => closedir(3) for a realdir or zipfile.
+ * <p>
+ * This function is magic - if the given arg-ZZIP_DIR
+ * is a real directory, it will call the real => closedir(3) and then
+ * free the wrapping ZZIP_DIR structure. Otherwise it will divert
+ * to => zzip_dir_close which will free the ZZIP_DIR structure.
+ */
+int
+zzip_closedir(ZZIP_DIR* dir)
+{
+ if (! dir) { errno = EBADF; return -1; }
+
+ if (USE_DIRENT && dir->realdir)
+ {
+ _zzip_closedir(dir->realdir);
+ free(dir->realname);
+ free(dir);
+ return 0;
+ }else
+ {
+ zzip_dir_close(dir);
+ return 0;
+ }
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
--- /dev/null
+/*\r
+ * Author: \r
+ * Guido Draheim <guidod@gmx.de>\r
+ * Tomi Ollila <Tomi.Ollila@iki.fi>\r
+ *\r
+ * Copyright (c) 1999,2000,2001,2002,2003 Guido Draheim\r
+ * All rights reserved,\r
+ * use under the restrictions of the\r
+ * Lesser GNU General Public License\r
+ * or alternatively the restrictions \r
+ * of the Mozilla Public License 1.1\r
+ */\r
+\r
+#include <zzip/lib.h> /* exported... */\r
+#include <zlib.h>\r
+\r
+#include <string.h>\r
+#include <errno.h>\r
+\r
+#include <zzip/file.h>\r
+\r
+static struct errlistentry { int code; const char* mesg; } \r
+errlist[] = \r
+{\r
+ { ZZIP_NO_ERROR, "No error" },\r
+ { ZZIP_OUTOFMEM, "could not get temporary memory for internal structures" },\r
+ { ZZIP_DIR_OPEN, "Failed to open zip-file %s" },\r
+ { ZZIP_DIR_STAT, "Failed to fstat zip-file %s" },\r
+ { ZZIP_DIR_SEEK, "Failed to lseek zip-file %s" },\r
+ { ZZIP_DIR_READ, "Failed to read zip-file %s"}, \r
+ { ZZIP_DIR_TOO_SHORT, "zip-file %s too short" },\r
+ { ZZIP_DIR_EDH_MISSING, "zip-file central directory not found" },\r
+ { ZZIP_DIRSIZE, "Directory size too big..." },\r
+ { ZZIP_ENOENT, "No such file found in zip-file %s" },\r
+ { ZZIP_UNSUPP_COMPR, "Unsupported compression format" },\r
+ { ZZIP_CORRUPTED, "Zipfile corrupted" }, \r
+ { ZZIP_UNDEF, "Some undefined error occurred" },\r
+ { 0, 0 },\r
+};\r
+\r
+#define errlistSIZE (sizeof(errlist)/sizeof(*errlist))\r
+\r
+/**\r
+ * returns the static string for the given error code. The\r
+ * error code can be either a normal system error (a\r
+ * positive error code will flag this), it can be => libz\r
+ * error code (a small negative error code will flag this)\r
+ * or it can be an error code from => libzzip, which is an\r
+ * negative value lower than => ZZIP_ERROR\r
+ */\r
+zzip_char_t* \r
+zzip_strerror(int errcode)\r
+{\r
+ if (errcode < ZZIP_ERROR && errcode > ZZIP_ERROR-32)\r
+ {\r
+ struct errlistentry* err = errlist;\r
+ for (; err->mesg ; err++)\r
+ {\r
+ if (err->code == errcode) \r
+ return err->mesg; \r
+ }\r
+ errcode = EINVAL;\r
+ }\r
+\r
+ if (errcode < 0)\r
+ {\r
+ if (errcode == -1)\r
+ return strerror(errcode);\r
+ else\r
+ return zError(errcode);\r
+ }\r
+ \r
+ return strerror (errcode);\r
+}\r
+\r
+/** => zzip_strerror\r
+ * This function fetches the errorcode from the => DIR-handle and \r
+ * runs it through => zzip_strerror to obtain the static string\r
+ * describing the error.\r
+ */\r
+zzip_char_t* \r
+zzip_strerror_of(ZZIP_DIR* dir)\r
+{\r
+ if (! dir) return strerror (errno);\r
+ return zzip_strerror(dir->errcode);\r
+}\r
+\r
+static struct errnolistentry { int code; int e_no; } \r
+errnolist[] =\r
+{\r
+ { Z_STREAM_ERROR, EPIPE },\r
+ { Z_DATA_ERROR, ESPIPE },\r
+ { Z_MEM_ERROR, ENOMEM },\r
+ { Z_BUF_ERROR, EMFILE },\r
+ { Z_VERSION_ERROR, ENOEXEC },\r
+ \r
+ { ZZIP_DIR_OPEN, ENOTDIR },\r
+ { ZZIP_DIR_STAT, EREMOTE },\r
+ { ZZIP_DIR_SEEK, ESPIPE },\r
+# ifdef ESTRPIPE\r
+ { ZZIP_DIR_READ, ESTRPIPE}, \r
+# else\r
+ { ZZIP_DIR_READ, EPIPE}, \r
+# endif\r
+ { ZZIP_DIR_TOO_SHORT, ENOEXEC },\r
+# ifdef ENOMEDIUM\r
+ { ZZIP_DIR_EDH_MISSING, ENOMEDIUM },\r
+# else\r
+ { ZZIP_DIR_EDH_MISSING, EIO },\r
+# endif\r
+ { ZZIP_DIRSIZE, EFBIG },\r
+ { ZZIP_OUTOFMEM, ENOMEM },\r
+ { ZZIP_ENOENT, ENOENT },\r
+# ifdef EPFNOSUPPORT\r
+ { ZZIP_UNSUPP_COMPR, EPFNOSUPPORT },\r
+# else\r
+ { ZZIP_UNSUPP_COMPR, EACCES },\r
+# endif \r
+# ifdef EILSEQ\r
+ { ZZIP_CORRUPTED, EILSEQ }, \r
+# else\r
+ { ZZIP_CORRUPTED, ELOOP }, \r
+# endif\r
+ { ZZIP_UNDEF, EINVAL },\r
+ { 0, 0 },\r
+}; \r
+\r
+/**\r
+ * map the error code to a system error code. This is used\r
+ * for the drop-in replacement functions to return a value\r
+ * that can be interpreted correctly by code sections that\r
+ * are unaware of the fact they their => open(2) call had been\r
+ * diverted to a file inside a zip-archive.\r
+ */\r
+int\r
+zzip_errno(int errcode)\r
+{\r
+ if (errcode >= -1) return errno;\r
+ \r
+ { struct errnolistentry* err = errnolist;\r
+ for (; err->code ; err++)\r
+ {\r
+ if (err->code == errcode) \r
+ return err->e_no; \r
+ }\r
+ }\r
+ return EINVAL;\r
+}\r
+\r
+/* \r
+ * Local variables:\r
+ * c-file-style: "stroustrup"\r
+ * End:\r
+ */\r
--- /dev/null
+/*\r
+ * this is an internal header file - the structure contains two off_t\r
+ * atleast making it LARGEFILE_SENSITIVE on linux2 and solaris systems\r
+ * whereas about all functions just return a ZZIP_FILE* in zzip/zzip.h\r
+ *\r
+ * and so, this structure should be handled version-specific and\r
+ * subject to change - it had been kept binary-compatible for quite\r
+ * a while now so perhaps some program sources have errnously taken\r
+ * advantage of this file.\r
+ *\r
+ * Author: \r
+ * Guido Draheim <guidod@gmx.de>\r
+ * Tomi Ollila <Tomi.Ollila@tfi.net>\r
+ *\r
+ * Copyright (c) 1999,2000,2001,2002 Guido Draheim\r
+ * All rights reserved,\r
+ * use under the restrictions of the\r
+ * Lesser GNU General Public License\r
+ * or alternatively the restrictions \r
+ * of the Mozilla Public License 1.1\r
+ */\r
+\r
+#ifndef _ZZIP_FILE_H /* zzip-file.h */\r
+#define _ZZIP_FILE_H 1\r
+\r
+#ifndef ZZIP_32K\r
+#ifdef __GNUC__\r
+/* include zzip/lib.h beforehand in order to suppress the following warning */\r
+#warning zzip/file.h is an internal header, do not use it freely\r
+#endif\r
+#endif\r
+\r
+#include <zzip/lib.h>\r
+#include <zlib.h>\r
+\r
+#ifdef ZZIP_HAVE_UNISTD_H\r
+#include <unistd.h>\r
+#else\r
+#include <stdio.h>\r
+# ifdef ZZIP_HAVE_SYS_TYPES_H\r
+# include <sys/types.h>\r
+# endif\r
+#endif\r
+\r
+#ifdef ZZIP_HAVE_SYS_PARAM_H\r
+#include <sys/param.h> /* PATH_MAX */\r
+#endif\r
+\r
+#ifndef PATH_MAX\r
+# ifdef MAX_PATH /* windows */\r
+# define PATH_MAX MAX_PATH\r
+# else\r
+# define PATH_MAX 512\r
+# endif\r
+#endif\r
+/*\r
+ * ZZIP_FILE structure... currently no need to unionize, since structure needed\r
+ * for inflate is superset of structure needed for unstore.\r
+ *\r
+ * Don't make this public. Instead, create methods for needed operations.\r
+ */\r
+\r
+struct zzip_file\r
+{\r
+ struct zzip_dir* dir; \r
+ int fd;\r
+ int method;\r
+ zzip_size_t restlen;\r
+ zzip_size_t crestlen;\r
+ zzip_size_t usize;\r
+ zzip_size_t csize;\r
+ /* added dataoffset member - data offset from start of zipfile*/\r
+ zzip_off_t dataoffset;\r
+ char* buf32k;\r
+ zzip_off_t offset; /* offset from the start of zipfile... */\r
+ z_stream d_stream;\r
+ zzip_plugin_io_t io;\r
+};\r
+\r
+#endif /* _ZZIP_FILE_H */\r
+\r
--- /dev/null
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 2000,2001,2002,2003 Guido Draheim
+ * All rights reserved
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ *
+ * The information was taken from appnote-981119-iz.zip
+ * at http://www.freesoftware.com/pub/infozip/doc/
+ * which in turn is based on PKWARE's appnote.txt
+ */
+#ifndef _ZZIP_FORMAT_H /* zzipformat.h */
+#define _ZZIP_FORMAT_H
+
+#include <zzip/lib.h>
+/* we have ICO C 9X types defined */
+
+/*
+ * Overall zipfile format
+ * [local file header + file data + data descriptr] ... [central directory] [EOD record]
+ */
+
+# ifdef _MSC_VER
+# pragma pack(push, 1)
+# endif
+
+struct zzip_version
+{
+ char version[1];
+ char ostype[1];
+} __attribute__((packed));
+
+struct zzip_dostime
+{
+ char time[2];
+ char date[2];
+} __attribute__((packed));
+
+#define ZZIP_CHECKMAGIC(__p,__A,__B,__C,__D) \
+ ( (((char*)(__p))[0]==(__A)) && \
+ (((char*)(__p))[1]==(__B)) && \
+ (((char*)(__p))[2]==(__C)) && \
+ (((char*)(__p))[3]==(__D)) )
+
+/* A. Local file header */
+struct zzip_file_header
+{
+# define ZZIP_FILE_HEADER_MAGIC 0x04034b50
+# define ZZIP_FILE_HEADER_CHECKMAGIC(__p) ZZIP_CHECKMAGIC(__p,'P','K','\3','\4')
+ char z_magic[4]; /* local file header signature (0x04034b50) */
+ struct zzip_version z_extract; /* version needed to extract */
+ char z_flags[2]; /* general purpose bit flag */
+ char z_compr[2]; /* compression method */
+ struct zzip_dostime z_dostime; /* last mod file time (dos format) */
+ char z_crc32[4]; /* crc-32 */
+ char z_csize[4]; /* compressed size */
+ char z_usize[4]; /* uncompressed size */
+ char z_namlen[2]; /* filename length (null if stdin) */
+ char z_extras[2]; /* extra field length */
+ /* followed by filename (of variable size) */
+ /* followed by extra field (of variable size) */
+} __attribute__((packed));
+
+/* B. data descriptor
+ * the data descriptor exists only if bit 3 of z_flags is set. It is byte aligned
+ * and immediately follows the last byte of compressed data. It is only used if
+ * the output media of the compressor was not seekable, eg. standard output.
+ */
+struct zzip_file_trailer
+{
+# define ZZIP_FILE_TRAILER_MAGIC 0x08074B50
+# define ZZIP_FILE_TRAILER_CHECKMAGIC(__p) ZZIP_CHECKMAGIC(__p,'P','K','\7','\8')
+ uint32_t z_magic; /* data descriptor signature (0x08074b50) */
+ uint32_t z_crc32; /* crc-32 */
+ uint32_t z_csize; /* compressed size */
+ uint32_t z_usize; /* uncompressed size */
+} __attribute__((packed));
+
+/* C. central directory structure:
+ [file header] . . . end of central dir record
+*/
+
+/* directory file header
+ * - a single entry including filename, extras and comment may not exceed 64k.
+ */
+
+struct zzip_root_dirent
+{
+# define ZZIP_ROOT_DIRENT_MAGIC 0x02014b50
+# define ZZIP_ROOT_DIRENT_CHECKMAGIC(__p) ZZIP_CHECKMAGIC(__p,'P','K','\1','\2')
+ char z_magic[4]; /* central file header signature (0x02014b50) */
+ struct zzip_version z_encoder; /* version made by */
+ struct zzip_version z_extract; /* version need to extract */
+ char z_flags[2]; /* general purpose bit flag */
+ char z_compr[2]; /* compression method */
+ struct zzip_dostime z_dostime; /* last mod file time&date (dos format) */
+ char z_crc32[4]; /* crc-32 */
+ char z_csize[4]; /* compressed size */
+ char z_usize[4]; /* uncompressed size */
+ char z_namlen[2]; /* filename length (null if stdin) */
+ char z_extras[2]; /* extra field length */
+ char z_comment[2]; /* file comment length */
+ char z_diskstart[2]; /* disk number of start (if spanning zip over multiple disks) */
+ char z_filetype[2]; /* internal file attributes, bit0 = ascii */
+ char z_filemode[4]; /* extrnal file attributes, eg. msdos attrib byte */
+ char z_off[4]; /* relative offset of local file header, seekval if singledisk */
+ /* followed by filename (of variable size) */
+ /* followed by extra field (of variable size) */
+ /* followed by file comment (of variable size) */
+} __attribute__((packed));
+
+/* end of central dir record */
+struct zzip_disk_trailer
+{
+# define ZZIP_DISK_TRAILER_MAGIC 0x06054b50
+# define ZZIP_DISK_TRAILER_CHECKMAGIC(__p) ZZIP_CHECKMAGIC(__p,'P','K','\5','\6')
+ char z_magic[4]; /* end of central dir signature (0x06054b50) */
+ char z_disk[2]; /* number of this disk */
+ char z_finaldisk[2]; /* number of the disk with the start of the central dir */
+ char z_entries[2]; /* total number of entries in the central dir on this disk */
+ char z_finalentries[2]; /* total number of entries in the central dir */
+ char z_rootsize[4]; /* size of the central directory */
+ char z_rootseek[4]; /* offset of start of central directory with respect to *
+ * the starting disk number */
+ char z_comment[2]; /* zipfile comment length */
+ /* followed by zipfile comment (of variable size) */
+} __attribute__((packed));
+
+/* z_flags */
+#define ZZIP_IS_ENCRYPTED(p) ((*(unsigned char*)p)&1)
+#define ZZIP_IS_COMPRLEVEL(p) (((*(unsigned char*)p)>>1)&3)
+#define ZZIP_IS_STREAMED(p) (((*(unsigned char*)p)>>3)&1)
+
+/* z_compr */
+#define ZZIP_IS_STORED 0
+#define ZZIP_IS_SHRUNK 1
+#define ZZIP_IS_REDUCEDx1 2
+#define ZZIP_IS_REDUCEDx2 3
+#define ZZIP_IS_REDUCEDx3 4
+#define ZZIP_IS_REDUCEDx4 5
+#define ZZIP_IS_IMPLODED 6
+#define ZZIP_IS_TOKENIZED 7
+#define ZZIP_IS_DEFLATED 8
+#define ZZIP_IS_DEFLATED_BETTER 9
+#define ZZIP_IS_IMPLODED_BETTER 10
+
+# ifdef _MSC_VER
+# pragma pack(pop)
+# endif
+
+#endif /* _ZZIPFORMAT_H */
+
+
+
+
--- /dev/null
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ *
+ * Copyright (c) 2000,2001,2002,2003 Guido Draheim
+ * All rights reserved,
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ */
+
+#include <zzip/lib.h> /* exported... */
+#include <zzip/file.h>
+#include <zzip/format.h>
+
+#ifdef ZZIP_HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#endif
+
+/**
+ * just returns dir->errcode of the ZZIP_DIR handle
+ * see: => zzip_dir_open, => zzip_diropen, => zzip_readdir, => zzip_dir_read
+ */
+int
+zzip_error(ZZIP_DIR * dir)
+{
+ return dir->errcode;
+}
+
+/** => zzip_error
+ * This function just does dir->errcode = errcode
+ */
+void
+zzip_seterror(ZZIP_DIR * dir, int errcode)
+{ dir->errcode = errcode; }
+
+/**
+ * This function will just return fp->dir
+ *
+ * If a ZZIP_FILE is contained within a zip-file that one will be a valid
+ * pointer, otherwise a NULL is returned and the ZZIP_FILE wraps a real file.
+ */
+ZZIP_DIR *
+zzip_dirhandle(ZZIP_FILE * fp)
+{
+ return fp->dir;
+}
+
+/** => zzip_dirhandle
+ * This function will just return dir->fd
+ *
+ * If a ZZIP_DIR does point to a zipfile then the file-descriptor of that
+ * zipfile is returned, otherwise a NULL is returned and the ZZIP_DIR wraps
+ * a real directory DIR (if you have dirent on your system).
+ */
+int
+zzip_dirfd(ZZIP_DIR* dir)
+{
+ return dir->fd;
+}
+
+/**
+ * return static const string of the known compression methods,
+ * otherwise just "zipped" is returned
+ */
+zzip_char_t*
+zzip_compr_str(int compr)
+{
+ switch(compr)
+ {
+ case ZZIP_IS_STORED: return "stored";
+ case ZZIP_IS_SHRUNK: return "shrunk";
+ case ZZIP_IS_REDUCEDx1:
+ case ZZIP_IS_REDUCEDx2:
+ case ZZIP_IS_REDUCEDx3:
+ case ZZIP_IS_REDUCEDx4: return "reduced";
+ case ZZIP_IS_IMPLODED: return "imploded";
+ case ZZIP_IS_TOKENIZED: return "tokenized";
+ case ZZIP_IS_DEFLATED: return "deflated";
+ case ZZIP_IS_DEFLATED_BETTER: return "deflatedX";
+ case ZZIP_IS_IMPLODED_BETTER: return "implodedX";
+ default:
+ if (0 < compr && compr < 256) return "zipped";
+ else
+ {
+# ifdef S_ISDIR
+ if (S_ISDIR(compr)) return "directory";
+# endif
+# ifdef S_ISCHR
+ if (S_ISCHR(compr)) return "is/chr";
+# endif
+# ifdef S_ISBLK
+ if (S_ISBLK(compr)) return "is/blk";
+# endif
+# ifdef S_ISFIFO
+ if (S_ISFIFO(compr)) return "is/fifo";
+# endif
+# ifdef S_ISSOCK
+ if (S_ISSOCK(compr)) return "is/sock";
+# endif
+# ifdef S_ISLNK
+ if (S_ISLNK(compr)) return "is/lnk";
+# endif
+ return "special";
+ }
+ }/*switch*/
+}
+
+/** => zzip_file_real
+ * This function checks if the ZZIP_DIR-handle is wrapping
+ * a real directory or a zip-archive.
+ * Returns 1 for a stat'able directory, and 0 for a handle to zip-archive.
+ */
+int
+zzip_dir_real(ZZIP_DIR* dir)
+{
+ return dir->realdir != 0;
+}
+
+/**
+ * This function checks if the ZZIP_FILE-handle is wrapping
+ * a real file or a zip-contained file.
+ * Returns 1 for a stat'able file, and 0 for a file inside a zip-archive.
+ */
+int
+zzip_file_real(ZZIP_FILE* fp)
+{
+ return fp->dir == 0; /* ie. not dependent on a zip-arch-dir */
+}
+
+/** => zzip_file_real
+ * This function returns the posix DIR* handle (if one exists).
+ * Check before with => zzip_dir_real if the
+ * the ZZIP_DIR points to a real directory.
+ */
+void*
+zzip_realdir(ZZIP_DIR* dir)
+{
+ return dir->realdir;
+}
+
+/** => zzip_file_real
+ * This function returns the posix file descriptor (if one exists).
+ * Check before with => zzip_file_real if the
+ * the ZZIP_FILE points to a real file.
+ */
+int
+zzip_realfd(ZZIP_FILE* fp)
+{
+ return fp->fd;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */
--- /dev/null
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ * Tomi Ollila <Tomi.Ollila@iki.fi>
+ *
+ * Copyright (c) 1999,2000,2001,2002,2003 Guido Draheim
+ * All rights reserved
+ * use under the restrictions of the
+ * Lesser GNU General Public License
+ * or alternatively the restrictions
+ * of the Mozilla Public License 1.1
+ *
+ * This is the private header containing definitions that are not
+ * use by a libzzip user application. Writing an extension lib that
+ * uses libzzip will still want to include this. The extension
+ * write should make way to have the ISO C9X integer types defined.
+ */
+#ifndef _ZZIP_LIB_H /* zzip.h */
+#define _ZZIP_LIB_H
+
+#include <zzip/zzip.h>
+#include <zzip/plugin.h>
+#include <zzip/stdint.h>
+
+/*
+ * this structure cannot be wildly enlarged... (see zzip-zip.c)
+ */
+struct zzip_dir_hdr
+{
+ uint32_t d_usize; /* uncompressed size */
+ uint32_t d_csize; /* compressed size */
+ uint32_t d_crc32; /* the adler32-checksum */
+ uint32_t d_off; /* offset of file in zipfile */
+ uint16_t d_reclen; /* next dir_hdr structure offset */
+ uint16_t d_namlen; /* explicit namelen of d_name */
+ uint8_t d_compr; /* the compression type, 0 = store, 8 = inflate */
+ char d_name[1]; /* the actual name of the entry, may contain DIRSEPs */
+};
+#define _ZZIP_DIRENT_HAVE_D_NAMLEN
+#define _ZZIP_DIRENT_HAVE_D_OFF
+#define _ZZIP_DIRENT_HAVE_D_RECLEN
+
+/*
+ * you shall not use this struct anywhere else than in zziplib sources.
+ */
+struct zzip_dir
+{
+ int fd;
+ int errcode; /* zzip_error_t */
+ long refcount;
+ struct {
+ struct zzip_file * fp; /* reduce a lot of alloc/deallocations by */
+ char * buf32k; /* caching one entry of these data structures */
+ } cache;
+ struct zzip_dir_hdr * hdr0; /* zfi; */
+ struct zzip_dir_hdr * hdr; /* zdp; directory pointer, for dirent stuff */
+ struct zzip_file * currentfp; /* last fp used... */
+ struct zzip_dirent dirent;
+ void* realdir; /* e.g. DIR* from posix dirent.h */
+ char* realname;
+ zzip_strings_t* fileext; /* list of fileext to test for */
+ zzip_plugin_io_t io; /* vtable for io routines */
+};
+
+#define ZZIP_32K 32768
+
+/* try to open a zip-basename with default_fileext */
+int __zzip_try_open (zzip_char_t* filename, int filemode,
+ zzip_strings_t* ext, zzip_plugin_io_t io);
+
+ZZIP_DIR *
+zzip_dir_fdopen(int fd, zzip_error_t * errcode_p);
+
+ZZIP_DIR*
+zzip_dir_fdopen_ext_io(int fd, zzip_error_t * errorcode_p,
+ zzip_strings_t* ext, const zzip_plugin_io_t io);
+
+ZZIP_DIR* /*depracated*/
+zzip_dir_alloc_ext_io (zzip_strings_t* ext, const zzip_plugin_io_t io);
+
+/* get 16/32 bits from little-endian zip-file to host byteorder */
+uint32_t __zzip_get32(unsigned char * s);
+uint16_t __zzip_get16(unsigned char * s);
+
+#ifdef __i386__
+#define ZZIP_GET32(x) (*(uint32_t*)(x))
+#define ZZIP_GET16(x) (*(uint16_t*)(x))
+#else
+#define ZZIP_GET32(x) (__zzip_get32(x))
+#define ZZIP_GET16(x) (__zzip_get16(x))
+#endif
+
+#endif /* _ZZIP_H */
+
--- /dev/null
+/*
+ * Author:
+ * Guido Draheim <guidod@gmx.de>
+ * Tomi Ollila <Tomi.Ollila@iki.fi>
+ *
+ * Copyright (c) 1999,2000,2001,2002 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
+ *
+ * Description:
+ * although this file is defining a function called zzip_stat it
+ * will not need a real stat(2) exported by the Operating System.
+ * It will just try to fill the fields of the ZZIP_STAT structure
+ * of
+ */
+
+#include <zzip/lib.h> /* exported...*/
+#include <string.h>
+
+/**
+ * obtain information about a filename in an opened zip-archive without
+ * opening that file first. Mostly used to obtain the uncompressed
+ * size of a file inside a zip-archive. see => zzip_dir_open.
+ */
+int
+zzip_dir_stat(ZZIP_DIR * dir, zzip_char_t* name, ZZIP_STAT * zs, int flags)
+{
+ struct zzip_dir_hdr * hdr = dir->hdr0;
+ int (*cmp)(zzip_char_t*, zzip_char_t*);
+
+ cmp = (flags & ZZIP_CASEINSENSITIVE) ? strcasecmp : strcmp;
+
+ if (flags & ZZIP_IGNOREPATH)
+ {
+ char* n = strrchr(name, '/');
+ if (n) name = n + 1;
+ }
+
+ if (hdr)
+ while (1)
+ {
+ register char* hdr_name = hdr->d_name;
+ if (flags & ZZIP_IGNOREPATH)
+ {
+ register char* n = strrchr(hdr_name, '/');
+ if (n) hdr_name = n + 1;
+ }
+
+ if (! cmp(hdr_name, name))
+ break;
+
+ if (! hdr->d_reclen)
+ {
+ dir->errcode = ZZIP_ENOENT;
+ return -1;
+ }
+
+ hdr = (struct zzip_dir_hdr *) ((char *)hdr + hdr->d_reclen);
+ }
+
+ zs->d_compr = hdr->d_compr;
+ zs->d_csize = hdr->d_csize;
+ zs->st_size = hdr->d_usize;
+ zs->d_name = hdr->d_name;
+
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * End:
+ */