ZZIPlib
0.13.26


Library
-ZIP Access
-Transparently
-SDLrwops Example
-ext/io Customization
-xor/io Obfuscation
-Library API
-Parsing ZIPs
-64on32 extras
-Next To Come
-Config Helpers
-Making a zip/exe
-Hints And Links
-Referentials
-Functions List #
    (# autogenerated)
 

Download Area *
Sourceforge CVS
Sourceforge Project
zziplib.sf.net Home
LGPL/MPL license
 

generated 2003-12-23
(C) Guido Draheim
guidod@gmx.de

ZZIP Programmers Interface


The complete API description.

Basics

The naming schem of functions in this library follow a simple rule: if you see a function with a zzip_ prefix followed by compact name representing otherwise a C library or posix function then it is a magic wrapper that can automagically handle both real files/directories or zip-contained files. This includes:

zzip_opendir opendir
zzip_readdir readdir
zzip_closedir closedir
zzip_rewinddir rewinddir
zzip_telldir telldir
zzip_seekdir seekdir

The ZZIP_DIR handle can wrap both a real directory or a zip-file. Note that you can not open a virtual directory within a zip-file, the ZZIP_DIR is either a real DIR-handle of a real directory or the reference of ZIP-file but never a DIR-handle within a ZIP-file - there is no such schema of a SUB-DIR handle implemented in this library. A ZZIP_DIR does actually represent the central directory of a ZIP-file, so that each file entry in this ZZIP-DIR can possibly have a subpath prepended.

This form of magic has historic reasons as originally the magic wrappers of this library were not meant to wrap a complete subtree of a real file tree but only a single directory being wrapped with into a zip-file and placed instead. Later proposals and patches were coming in to support subtree wrapping by not only making a split between the dir-part and file-part but going recursivly up through all "/"-dirseparators of a filepath given to zzip_open and looking for zip-file there.

To open a zip-file unconditionally one should be using their respective methods that would return a ZZIP_DIR handle being the representant memory instance of a ZIP-DIR, the central directory of a zip-file. From that ZZIP-DIR one can open a compressed file entry which will be returned as a ZZIP_FILE pointer.

zzip_dir_open open a zip-file and parse the central directory to a memory shadow
zzip_dir_close close a zip-file and free the memory shadow
zzip_dir_fdopen aquire the given posix-file and try to parse it as a zip-file.
zzip_dir_read return the next info entry of a zip-file's central directory - this would include a possible subpath

To unconditionally access a zipped-file (as the counter-part of a zip-file's directory) you should be using the functions having a zzip_file_ prefix which are the methods working on ZZIP_FILE pointers directly and assuming those are references of a zipped file with a ZZIP_DIR.

zzip_file_open open a file within a zip and prepare a zlib compressor for it - note the ZZIP_DIR argument, multiple ZZIP_FILE's may share the same central directory shadow.
zzip_file_close close the handle of zippedfile and free zlib compressor of it
zzip_file_read decompress the next part of a compressed file within a zip-file

From here it is only a short step to the magic wrappers for file-access - when being given a filepath to zzip_open then the filepath is checked first for being possibly a real file (we can often do that by a stat call) and if there is a real file under that name then the returned ZZIP_FILE is nothing more than a wrapper around a file-descriptor of the underlying operating system. Any other calls like zzip_read will see the realfd-flag in the ZZIP_FILE and forward the execution to the read() function of the underlying operating system.

However if that fails then the filepath is cut at last directory separator, i.e. a filepath of "this/test/README" is cut into the dir-part "this/test" and a file-part "README". Then the possible zip-extensions are attached (".zip" and ".ZIP") and we check if there is a real file under that name. If a file "this/test.zip" does exist then it is given to zzip_dir_open which will create a ZZIP_DIR instance of it, and when that was successul (so it was in zip-format) then we call zzip_file_open which will see two arguments - the just opened ZZIP_DIR and the file-part. The resulting ZZIP_FILE has its own copy of a ZZIP_DIR, so if you open multiple files from the same zip-file than you will also have multiple in-memory copies of the zip's central directory whereas otherwise multiple ZZIP_FILE's may share a common ZZIP_DIR when being opened with zzip_file_open directly - the zzip_file_open's first argument is the ZZIP_DIR and the second one the file-part to be looked up within that zip-directory.

zzip_open try the file-path as a real-file, and if not there, look for the existance of ZZIP_DIR by applying extensions, and open the file contained within that one.
zzip_close if the ZZIP_FILE wraps a real-file, then call read(), otherwise call zzip_file_read()
zzip_close if the ZZIP_FILE wraps a real-file, then call close(), otherwise call zzip_file_close()

Up to here we have the original functionality of the zziplib when I (Guido Draheim) created the magic functions around the work from Tomi Ollila who wrote the routines to read and decompress files from a zip archive - unlike other libraries it was quite readable and intelligible source code (after many changes there is not much left of the original zip08x source code but that's another story). Later however some request and proposals and patches were coming in.

Among the first extensions was the recursive zzip_open magic. In the first instance, the library did just do as described above: a file-path of "this/test/README" might be a zip-file known as "this/test.zip" containing a compressed file "README". But if there is neither a real file "this/test/README" and no real zip-file "this/test.zip" then the call would have failed but know the zzip_open call will recursivly check the parent directories - so it can now find a zip-file "this.zip" which contains a file-part "test/README".

This dissolves the original meaning of a ZZIP_DIR and it has lead to some confusion later on - you can not create a DIRENT-like handle for "this/test/" being within a "test.zip" file. And actually, I did never see a reason to implement it so far (open "this.zip" and set an initial subpath of "test" and let zzip_readdir skip all entries that do not start with "test/"). This is left for excercie ;-)

Extras

The next requests circulated around other file-extensions to automagically look inside filetypes that have zip-format too but carry other fileextensions - most famous might be the ".PK3" files of ID's Quake game. There have been a number of these requests and in a lot of cases it dawned to me that those guys may have overlooked the zzip_dir_open functions to travel through documents of zipformat under any name - that is that the "magic" was not actually needed but they just wanted to read files in zipformat with the zziplib.

Other requests circulated around encryption but I did reject those bluntly, always. Instead there have been always examples for doing some obfuscation around the zip-format so that the stock zip/unzip tools do not recognize them but a game software developer can pack/unpack his AI scripts and bitmaps into such a zipformat-like file.

After some dead-end patches (being shipped along with the zziplib as configure-time compile-options - greetings to Lutz Sammer and Andreas Schiffler), the general approach of _ext_io came up, and finally implemented (greetings go to Mike Nordell). The _open()-calls do now each have a cousin of _open_ext_io() with two/three additional arguments being a set of extensions to loop through our magic testing, a callback-handler plugin-table for obfuscation-means, and (often) a bit-mask for extra-options - this bitmask even has "PREFERZIP" and "ONLYZIP" options to skip the real-file test magic in those zzip_*open functions.

zzip_open(name,flags) zzip_open_ext_io(name,flags,mode,ext,io)
zzip_opendir(name) zzip_opendir_ext_io(name,mode,ext,io)
zzip_dir_open(name,errp) zzip_dir_open_ext_io(name,errp,ext,io)
zzip_dir_fdopen(fd,errp) zzip_dir_fdopen_ext_io(fd,errp,ext,io)
zzip_file_open(dir,name,mode) zzip_file_open_ext_io(dir,name,mode,ext,io)

Oh, and note that the mode,ext,io extras are memorized in the respecitive ZZIP_DIR handle attached, so each of the other calls like zzip_file_open() and zzip_read() will be using them. There are a few helper routines to help setup a new io-plugin where the init_io will currently just memcopy the default_io entries into the user-supplied plugin-struct.

zzip_init_io the recommended way to do things
zzip_get_default_io used internally whenever you supply a null for the io-argument of a _ext_io()-call
zzip_get_default_ext used internally but not exported

And last some stdio-like replacements were build but these happen to be actually just small wrappers around the other posix-like magic-calls. It just offers some convenience since wrappers like "SDL_rwops" tend to use a stringised open-mode - and I took the occasion to fold the zzip-bits for the _ext_io-calls right in there recognized via special extensions to the openmode-string of zzip_fopen().

zzip_fopen convert stringmode and call zzip_open_ext_io
zzip_fread slower way to say zzip_read
zzip_fclose a synonym of zzip_close

For some reason, people did need the full set of function-calls() to be working on zzip-wrappers too, so here they are - if the ZZIP_FILE instance did wrap a real file, then the real posix-call will be used, otherwise it is simulated on the compressed stream with a zip-contained file - especially seek() can be a slow operation: if the new point is later then just read out more bytes till we hit that position but if it is an earlier point then rewind to the beginning of the compressed data and start reading/decompression until the position is met.

zzip_rewind magic for rewind()
zzip_tell magic for tell()
zzip_seek magic for seek()

And last not least, there are few informative functions to use function-calls to read parts of the opaque structures of zzip-objects and their zzip-factory.

zzip_dir_stat a stat()-like thing on a file within a ZZIP_DIR
zzip_dir_real check if ZZIP_DIR wraps a stat'able posix-dirent
zzip_file_real check if ZZIP_FILE wraps a stat'able posix-file
zzip_realdir if zzip_dir_real then return the posix-dirent
zzip_realfd if zzip_file_real then return the posix-file
zzip_dirhandle the attached ZZIP_DIR of compressed ZZIP_FILE
zzip_dirfd the attached posix-file of ZZIP_DIR zip-file
zzip_set_error set the last ZZIP_DIR error-code
zzip_error get the last ZZIP_DIR error-code
zzip_strerror convert a zzip_error into a readable string
zzip_strerror_of combine both above zzip_strerror of zzip_error
zzip_errno helper to wrap a zzip-error to a posix-errno
zzip_compr_str helper to wrap a compr-number to a readable string
zzip_dir_free internally called by zzip_dir_close if the ref-count of the ZZIP_DIR has gone zero
zzip_freopen to reuse the ZZIP_DIR from another ZZIP_FILE so it does not need to be parsed again
zzip_open_shared_io the ext/io cousin but it does not close the old ZZIP_FILE and instead just shares the ZZIP_DIR if possible

guidod@gmx.de 20. July 2002