add higher-level dox, fix some bugs, made case-insensitive
This was SVN commit r973.
This commit is contained in:
parent
e67ed4acc0
commit
c5701c8299
@ -16,6 +16,22 @@
|
|||||||
// Jan.Wassenberg@stud.uni-karlsruhe.de
|
// Jan.Wassenberg@stud.uni-karlsruhe.de
|
||||||
// http://www.stud.uni-karlsruhe.de/~urkt/
|
// http://www.stud.uni-karlsruhe.de/~urkt/
|
||||||
|
|
||||||
|
// components:
|
||||||
|
// - z_*: Zip-specific code
|
||||||
|
// passes the list of files in an archive to lookup.
|
||||||
|
// - lookup_*: file lookup
|
||||||
|
// per archive: return file info (e.g. offset, size), given filename.
|
||||||
|
// - ZArchive_*: Handle-based container for archive info
|
||||||
|
// owns archive file and its lookup mechanism.
|
||||||
|
// - inf_*: in-memory inflate routines (zlib wrapper)
|
||||||
|
// decompresses blocks from file_io callback.
|
||||||
|
// - zip_*: file from Zip archive
|
||||||
|
// uses lookup to get file information; holds inflate state.
|
||||||
|
// - sync and async I/O
|
||||||
|
// uses file_* and inf_*.
|
||||||
|
// - file mapping
|
||||||
|
|
||||||
|
|
||||||
#include "precompiled.h"
|
#include "precompiled.h"
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
@ -89,8 +105,8 @@ static inline int z_validate(const void* const file, const size_t size)
|
|||||||
if(size < 22)
|
if(size < 22)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// check "header" (first CDFH) signature
|
// check "header" (first LFH) signature
|
||||||
return (*(u32*)file == *(u32*)&cdfh_id)? 0 : -1;
|
return (*(u32*)file == *(u32*)&lfh_id)? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -199,7 +215,7 @@ static int z_read_cdfh(const u8*& cdfh, const char*& fn, size_t& fn_len, ZLoc* c
|
|||||||
debug_warn("warning: unknown compression method");
|
debug_warn("warning: unknown compression method");
|
||||||
goto skip_file;
|
goto skip_file;
|
||||||
}
|
}
|
||||||
// tell is_compressed that the file is uncompressed,
|
// tell zfile_compressed that the file is uncompressed,
|
||||||
// by setting csize_ to 0.
|
// by setting csize_ to 0.
|
||||||
if(method == 0)
|
if(method == 0)
|
||||||
csize_ = 0;
|
csize_ = 0;
|
||||||
@ -301,7 +317,7 @@ static int z_enum_files(const void* const file, const size_t size, const CDFH_CB
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// lookup_*: file lookup
|
// lookup_*: file lookup
|
||||||
// per archive: retrieve file information (e.g. offset, size), given filename.
|
// per archive: return file info (e.g. offset, size), given filename.
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -359,6 +375,22 @@ struct LookupInfo
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// support for case-insensitive filenames: the FNV hash of each
|
||||||
|
// filename string is saved in lookup_add_file_cb and searched for by
|
||||||
|
// lookup_get_file_info. in both cases, we convert a temporary to
|
||||||
|
// lowercase before hashing it.
|
||||||
|
static void strcpy_lower(char* dst, const char* src)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c = *src++;
|
||||||
|
*dst++ = tolower(c);
|
||||||
|
}
|
||||||
|
while(c != '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// add file <fn> to the lookup data structure.
|
// add file <fn> to the lookup data structure.
|
||||||
// called from z_enum_files in order (0 <= idx < num_files).
|
// called from z_enum_files in order (0 <= idx < num_files).
|
||||||
// the first call notifies us of # files, so we can allocate memory.
|
// the first call notifies us of # files, so we can allocate memory.
|
||||||
@ -392,7 +424,9 @@ static int lookup_add_file_cb(const uintptr_t user, const i32 idx, const char* c
|
|||||||
|
|
||||||
ZEnt* ent = li->ents + idx;
|
ZEnt* ent = li->ents + idx;
|
||||||
|
|
||||||
FnHash fn_hash = fnv_hash(fn, fn_len);
|
char lc_fn[PATH_MAX];
|
||||||
|
strcpy_lower(lc_fn, fn);
|
||||||
|
FnHash fn_hash = fnv_hash(lc_fn, fn_len);
|
||||||
|
|
||||||
(*li->idx)[fn_hash] = idx;
|
(*li->idx)[fn_hash] = idx;
|
||||||
li->fn_hashes[idx] = fn_hash;
|
li->fn_hashes[idx] = fn_hash;
|
||||||
@ -400,6 +434,7 @@ static int lookup_add_file_cb(const uintptr_t user, const i32 idx, const char* c
|
|||||||
// valid file - write out its info.
|
// valid file - write out its info.
|
||||||
if(loc)
|
if(loc)
|
||||||
{
|
{
|
||||||
|
// copy filename, so we can 0-terminate it
|
||||||
ent->fn = (const char*)malloc(fn_len+1);
|
ent->fn = (const char*)malloc(fn_len+1);
|
||||||
if(!ent->fn)
|
if(!ent->fn)
|
||||||
return ERR_NO_MEM;
|
return ERR_NO_MEM;
|
||||||
@ -473,9 +508,11 @@ static int lookup_free(LookupInfo* const li)
|
|||||||
// return file information of file <fn>.
|
// return file information of file <fn>.
|
||||||
static int lookup_get_file_info(LookupInfo* const li, const char* fn, ZLoc* const loc)
|
static int lookup_get_file_info(LookupInfo* const li, const char* fn, ZLoc* const loc)
|
||||||
{
|
{
|
||||||
const FnHash fn_hash = fnv_hash(fn);
|
char lc_fn[PATH_MAX];
|
||||||
const FnHash* fn_hashes = li->fn_hashes;
|
strcpy_lower(lc_fn, fn);
|
||||||
|
const FnHash fn_hash = fnv_hash(lc_fn);
|
||||||
|
|
||||||
|
const FnHash* fn_hashes = li->fn_hashes;
|
||||||
const i32 num_files = li->num_files;
|
const i32 num_files = li->num_files;
|
||||||
i32 i = li->next_file;
|
i32 i = li->next_file;
|
||||||
|
|
||||||
@ -501,19 +538,17 @@ static int lookup_get_file_info(LookupInfo* const li, const char* fn, ZLoc* cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef ZipFileCB LookupFileCB;
|
static int lookup_enum_files(LookupInfo* const li, FileCB cb, uintptr_t user)
|
||||||
|
|
||||||
static int lookup_enum_files(LookupInfo* const li, LookupFileCB cb, uintptr_t user)
|
|
||||||
{
|
{
|
||||||
const ZEnt* ent = li->ents;
|
const ZEnt* ent = li->ents;
|
||||||
for(i32 i = 0; i < li->num_files; i++, ent++)
|
for(i32 i = 0; i < li->num_files; i++, ent++)
|
||||||
{
|
{
|
||||||
// is this entry a directory?
|
ssize_t size = (ssize_t)ent->loc.ucsize;
|
||||||
int flags = 0;
|
if(size == 0) // it's a directory
|
||||||
if(ent->loc.csize == 0 && ent->loc.ucsize == 0)
|
size = -1;
|
||||||
flags |= LOC_DIR;
|
|
||||||
|
|
||||||
CHECK_ERR(cb(ent->fn, flags, (ssize_t)ent->loc.ucsize, user));
|
CHECK_ERR(cb(ent->fn, size, user));
|
||||||
|
// pass in complete path (see file_enum rationale).
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -522,7 +557,7 @@ static int lookup_enum_files(LookupInfo* const li, LookupFileCB cb, uintptr_t us
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// container with handle for archive info
|
// ZArchive_*: Handle-based container for archive info
|
||||||
// owns archive file and its lookup mechanism.
|
// owns archive file and its lookup mechanism.
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -534,9 +569,17 @@ struct ZArchive
|
|||||||
|
|
||||||
LookupInfo li;
|
LookupInfo li;
|
||||||
|
|
||||||
// hack: on first open, file is invalid (fn_hash isn't set),
|
// problem:
|
||||||
// and file validate in file_close fails.
|
// if ZArchive_reload aborts due to file_open failing, ZArchive_dtor
|
||||||
// workaround: only close if open.
|
// is called by h_alloc, and file_close complains the File is
|
||||||
|
// invalid (wasn't open). this happens if e.g. vfs_mount blindly
|
||||||
|
// tries to open a directory as an archive.
|
||||||
|
// workaround:
|
||||||
|
// only free the above if ZArchive_reload succeeds, i.e. is_open.
|
||||||
|
// note:
|
||||||
|
// if lookup_init fails after file_open opened the file,
|
||||||
|
// we wouldn't file_close in the dtor,
|
||||||
|
// but it's taken care of by ZArchive_reload.
|
||||||
bool is_open;
|
bool is_open;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -569,7 +612,9 @@ static int ZArchive_reload(ZArchive* za, const char* fn, Handle h)
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = file_open(fn, 0, &za->f);
|
err = file_open(fn, 0, &za->f);
|
||||||
if(err < 0) // don't CHECK_ERR; this happens often.
|
if(err < 0)
|
||||||
|
// don't complain - this happens when vfs_mount blindly
|
||||||
|
// zip_archive_opens a dir.
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
// map
|
// map
|
||||||
@ -594,26 +639,29 @@ exit_unmap_close:
|
|||||||
file_unmap(&za->f);
|
file_unmap(&za->f);
|
||||||
exit_close:
|
exit_close:
|
||||||
file_close(&za->f);
|
file_close(&za->f);
|
||||||
|
|
||||||
|
// don't complain here either; this happens when vfs_mount
|
||||||
|
// zip_archive_opens an invalid file that's in a mount point dir.
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// open and return a handle to the zip archive indicated by <fn>
|
// open and return a handle to the zip archive indicated by <fn>
|
||||||
Handle zip_archive_open(const char* const fn)
|
inline Handle zip_archive_open(const char* const fn)
|
||||||
{
|
{
|
||||||
return h_alloc(H_ZArchive, fn);
|
return h_alloc(H_ZArchive, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// close the archive <ha> and set ha to 0
|
// close the archive <ha> and set ha to 0
|
||||||
int zip_archive_close(Handle& ha)
|
inline int zip_archive_close(Handle& ha)
|
||||||
{
|
{
|
||||||
return h_free(ha, H_ZArchive);
|
return h_free(ha, H_ZArchive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// see lookup rationale for not passing along a key.
|
// call <cb>, passing <user>, for all files in archive <ha>
|
||||||
int zip_enum(const Handle ha, const ZipFileCB cb, const uintptr_t user)
|
int zip_enum(const Handle ha, const FileCB cb, const uintptr_t user)
|
||||||
{
|
{
|
||||||
H_DEREF(ha, ZArchive, za);
|
H_DEREF(ha, ZArchive, za);
|
||||||
|
|
||||||
@ -623,7 +671,8 @@ int zip_enum(const Handle ha, const ZipFileCB cb, const uintptr_t user)
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// in-memory inflate routines (zlib wrapper)
|
// inf_*: in-memory inflate routines (zlib wrapper)
|
||||||
|
// decompresses blocks from file_io callback.
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -749,8 +798,8 @@ int inf_free_ctx(uintptr_t ctx)
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// file from Zip archive
|
// zip_*: file from Zip archive
|
||||||
// on top of inflate and lookup
|
// uses lookup to get file information; holds inflate state.
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -758,7 +807,8 @@ int inf_free_ctx(uintptr_t ctx)
|
|||||||
enum ZFileFlags
|
enum ZFileFlags
|
||||||
{
|
{
|
||||||
// the ZFile has been successfully zip_map-ped.
|
// the ZFile has been successfully zip_map-ped.
|
||||||
// we store this so that the archive mapping refcount remains balanced.
|
// used to make sure the archive's mmap refcount remains balanced,
|
||||||
|
// i.e. no one double-frees the mapping.
|
||||||
ZF_HAS_MAPPING = 0x4000
|
ZF_HAS_MAPPING = 0x4000
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -788,7 +838,7 @@ static int zfile_validate(uint line, ZFile* zf)
|
|||||||
#endif
|
#endif
|
||||||
else if(!zf->ucsize)
|
else if(!zf->ucsize)
|
||||||
msg = "ucsize = 0";
|
msg = "ucsize = 0";
|
||||||
else if(!zf->read_ctx)
|
else if(!zf->inf_ctx)
|
||||||
msg = "read context invalid";
|
msg = "read context invalid";
|
||||||
// everything is OK
|
// everything is OK
|
||||||
else
|
else
|
||||||
@ -811,6 +861,35 @@ do\
|
|||||||
while(0);
|
while(0);
|
||||||
|
|
||||||
|
|
||||||
|
// convenience function, allows implementation change in ZFile.
|
||||||
|
// note that size == ucsize isn't foolproof, and adding a flag to
|
||||||
|
// ofs or size is ugly and error-prone.
|
||||||
|
// no error checking - always called from functions that check zf.
|
||||||
|
static inline bool zfile_compressed(ZFile* zf)
|
||||||
|
{
|
||||||
|
return zf->csize != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// return file information for <fn> in archive <ha>
|
||||||
|
int zip_stat(Handle ha, const char* fn, struct stat* s)
|
||||||
|
{
|
||||||
|
// zero output param in case we fail below.
|
||||||
|
memset(s, 0, sizeof(struct stat));
|
||||||
|
|
||||||
|
H_DEREF(ha, ZArchive, za);
|
||||||
|
LookupInfo* li = &za->li;
|
||||||
|
|
||||||
|
ZLoc loc;
|
||||||
|
CHECK_ERR(lookup_get_file_info(li, fn, &loc));
|
||||||
|
|
||||||
|
s->st_size = loc.ucsize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int zip_open(const Handle ha, const char* fn, ZFile* zf)
|
int zip_open(const Handle ha, const char* fn, ZFile* zf)
|
||||||
{
|
{
|
||||||
H_DEREF(ha, ZArchive, za);
|
H_DEREF(ha, ZArchive, za);
|
||||||
@ -842,7 +921,7 @@ int zip_open(const Handle ha, const char* fn, ZFile* zf)
|
|||||||
zf->csize = loc.csize;
|
zf->csize = loc.csize;
|
||||||
|
|
||||||
zf->ha = ha;
|
zf->ha = ha;
|
||||||
zf->read_ctx = inf_init_ctx();
|
zf->inf_ctx = inf_init_ctx();
|
||||||
}
|
}
|
||||||
|
|
||||||
invalid_zf:
|
invalid_zf:
|
||||||
@ -857,41 +936,14 @@ int zip_close(ZFile* zf)
|
|||||||
CHECK_ZFILE(zf);
|
CHECK_ZFILE(zf);
|
||||||
|
|
||||||
// remaining ZFile fields don't need to be freed/cleared
|
// remaining ZFile fields don't need to be freed/cleared
|
||||||
return inf_free_ctx(zf->read_ctx);
|
return inf_free_ctx(zf->inf_ctx);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// return file information for <fn> in archive <ha>
|
|
||||||
int zip_stat(Handle ha, const char* fn, struct stat* s)
|
|
||||||
{
|
|
||||||
// zero output param in case we fail below.
|
|
||||||
memset(s, 0, sizeof(struct stat));
|
|
||||||
|
|
||||||
H_DEREF(ha, ZArchive, za);
|
|
||||||
LookupInfo* li = &za->li;
|
|
||||||
|
|
||||||
ZLoc loc;
|
|
||||||
CHECK_ERR(lookup_get_file_info(li, fn, &loc));
|
|
||||||
|
|
||||||
s->st_size = loc.ucsize;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// convenience function, allows implementation change in ZFile.
|
|
||||||
// note that size == ucsize isn't foolproof, and adding a flag to
|
|
||||||
// ofs or size is ugly and error-prone.
|
|
||||||
// no error checking - always called from functions that check zf.
|
|
||||||
static inline bool is_compressed(ZFile* zf)
|
|
||||||
{
|
|
||||||
return zf->csize != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// synchronous I/O
|
// sync and async I/O
|
||||||
|
// uses file_* and inf_*.
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -913,7 +965,7 @@ ssize_t zip_read(ZFile* zf, off_t raw_ofs, size_t size, void** p)
|
|||||||
|
|
||||||
// not compressed - just pass it on to file_io
|
// not compressed - just pass it on to file_io
|
||||||
// (avoid the Zip inflate start/finish stuff below)
|
// (avoid the Zip inflate start/finish stuff below)
|
||||||
if(!is_compressed(zf))
|
if(!zfile_compressed(zf))
|
||||||
return file_io(&za->f, ofs, size, p);
|
return file_io(&za->f, ofs, size, p);
|
||||||
// no need to set last_raw_ofs - only checked if compressed.
|
// no need to set last_raw_ofs - only checked if compressed.
|
||||||
|
|
||||||
@ -947,7 +999,7 @@ ssize_t zip_read(ZFile* zf, off_t raw_ofs, size_t size, void** p)
|
|||||||
*p = buf;
|
*p = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = (ssize_t)inf_start_read(zf->read_ctx, buf, size);
|
err = (ssize_t)inf_start_read(zf->inf_ctx, buf, size);
|
||||||
if(err < 0)
|
if(err < 0)
|
||||||
{
|
{
|
||||||
fail:
|
fail:
|
||||||
@ -964,11 +1016,11 @@ fail:
|
|||||||
// zip_inflate, until all compressed data has been read, or it indicates
|
// zip_inflate, until all compressed data has been read, or it indicates
|
||||||
// the desired output amount has been reached.
|
// the desired output amount has been reached.
|
||||||
const size_t raw_size = zf->csize;
|
const size_t raw_size = zf->csize;
|
||||||
raw_bytes_read = file_io(&za->f, ofs, raw_size, (void**)0, inf_inflate, zf->read_ctx);
|
raw_bytes_read = file_io(&za->f, ofs, raw_size, (void**)0, inf_inflate, zf->inf_ctx);
|
||||||
|
|
||||||
zf->last_raw_ofs = raw_ofs + (off_t)raw_bytes_read;
|
zf->last_raw_ofs = raw_ofs + (off_t)raw_bytes_read;
|
||||||
|
|
||||||
err = inf_finish_read(zf->read_ctx);
|
err = inf_finish_read(zf->inf_ctx);
|
||||||
if(err < 0)
|
if(err < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -982,6 +1034,47 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
// rationale for not supporting aio for compressed files:
|
||||||
|
// would complicate things considerably (could no longer just
|
||||||
|
// return the file I/O handle, since we have to decompress in wait_io),
|
||||||
|
// yet it isn't really useful - aio is used to stream music,
|
||||||
|
// which is already compressed.
|
||||||
|
|
||||||
|
|
||||||
|
// begin transferring <size> bytes, starting at <ofs>. get result
|
||||||
|
// with zip_wait_io; when no longer needed, free via zip_discard_io.
|
||||||
|
Handle zip_start_io(ZFile* const zf, off_t ofs, size_t size, void* buf)
|
||||||
|
{
|
||||||
|
CHECK_ZFILE(zf);
|
||||||
|
if(zfile_compressed(zf))
|
||||||
|
{
|
||||||
|
debug_warn("Zip aio doesn't currently support compressed files (see rationale above)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
H_DEREF(zf->ha, ZArchive, za);
|
||||||
|
return file_start_io(&za->f, zf->ofs+ofs, size, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// wait until the transfer <hio> completes, and return its buffer.
|
||||||
|
// output parameters are zeroed on error.
|
||||||
|
inline int zip_wait_io(Handle hio, void*& p, size_t& size)
|
||||||
|
{
|
||||||
|
return file_wait_io(hio, p, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// finished with transfer <hio> - free its buffer (returned by vfs_wait_io)
|
||||||
|
inline int zip_discard_io(Handle& hio)
|
||||||
|
{
|
||||||
|
return file_discard_io(hio);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// file mapping
|
// file mapping
|
||||||
@ -1005,14 +1098,22 @@ int zip_map(ZFile* const zf, void*& p, size_t& size)
|
|||||||
|
|
||||||
// mapping compressed files doesn't make sense because the
|
// mapping compressed files doesn't make sense because the
|
||||||
// compression algorithm is unspecified - disallow it.
|
// compression algorithm is unspecified - disallow it.
|
||||||
if(is_compressed(zf))
|
if(zfile_compressed(zf))
|
||||||
{
|
{
|
||||||
debug_warn("zip_map: file is compressed");
|
debug_warn("zip_map: file is compressed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
H_DEREF(zf->ha, ZArchive, za)
|
// note: we mapped the archive in zip_archive_open, but unmapped it
|
||||||
CHECK_ERR(file_map(&za->f, p, size));
|
// in the meantime to save memory in case it wasn't going to be mapped.
|
||||||
|
// now we do so again; it's unmapped in zip_unmap (refcounted).
|
||||||
|
H_DEREF(zf->ha, ZArchive, za);
|
||||||
|
void* archive_p;
|
||||||
|
size_t archive_size;
|
||||||
|
CHECK_ERR(file_map(&za->f, archive_p, archive_size));
|
||||||
|
|
||||||
|
p = (char*)archive_p + zf->ofs;
|
||||||
|
size = zf->ucsize;
|
||||||
|
|
||||||
zf->flags |= ZF_HAS_MAPPING;
|
zf->flags |= ZF_HAS_MAPPING;
|
||||||
return 0;
|
return 0;
|
||||||
@ -1034,51 +1135,6 @@ int zip_unmap(ZFile* const zf)
|
|||||||
return -1;
|
return -1;
|
||||||
zf->flags &= ~ZF_HAS_MAPPING;
|
zf->flags &= ~ZF_HAS_MAPPING;
|
||||||
|
|
||||||
H_DEREF(zf->ha, ZArchive, za)
|
H_DEREF(zf->ha, ZArchive, za);
|
||||||
return file_unmap(&za->f);
|
return file_unmap(&za->f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// asynchronous I/O
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
// rationale for not supporting aio for compressed files:
|
|
||||||
// would complicate things considerably (could no longer just
|
|
||||||
// return the file I/O handle, since we have to decompress in wait_io),
|
|
||||||
// yet it isn't really useful - aio is used to stream music,
|
|
||||||
// which is already compressed.
|
|
||||||
|
|
||||||
|
|
||||||
// begin transferring <size> bytes, starting at <ofs>. get result
|
|
||||||
// with zip_wait_io; when no longer needed, free via zip_discard_io.
|
|
||||||
Handle zip_start_io(ZFile* const zf, off_t ofs, size_t size, void* buf)
|
|
||||||
{
|
|
||||||
CHECK_ZFILE(zf);
|
|
||||||
if(is_compressed(zf))
|
|
||||||
{
|
|
||||||
debug_warn("Zip aio doesn't currently support compressed files (see rationale above)");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
H_DEREF(zf->ha, ZArchive, za);
|
|
||||||
return file_start_io(&za->f, zf->ofs+ofs, size, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// wait until the transfer <hio> completes, and return its buffer.
|
|
||||||
// output parameters are zeroed on error.
|
|
||||||
inline int zip_wait_io(Handle hio, void*& p, size_t& size)
|
|
||||||
{
|
|
||||||
return file_wait_io(hio, p, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// finished with transfer <hio> - free its buffer (returned by vfs_wait_io)
|
|
||||||
inline int zip_discard_io(Handle& hio)
|
|
||||||
{
|
|
||||||
return file_discard_io(hio);
|
|
||||||
}
|
|
||||||
|
@ -20,23 +20,10 @@
|
|||||||
#define ZIP_H__
|
#define ZIP_H__
|
||||||
|
|
||||||
#include "h_mgr.h"
|
#include "h_mgr.h"
|
||||||
#include "lib.h"
|
#include "file.h" // FileCB for zip_enum
|
||||||
#include "file.h"
|
|
||||||
|
|
||||||
|
|
||||||
//
|
// note: filenames are case-insensitive.
|
||||||
// in-memory inflate routines (zlib wrapper)
|
|
||||||
//
|
|
||||||
|
|
||||||
extern uintptr_t inf_init_ctx();
|
|
||||||
|
|
||||||
extern int inf_start_read(uintptr_t ctx, void* out, size_t out_size);
|
|
||||||
|
|
||||||
extern ssize_t inf_inflate(uintptr_t ctx, void* in, size_t in_size);
|
|
||||||
|
|
||||||
extern int inf_finish_read(uintptr_t ctx);
|
|
||||||
|
|
||||||
extern int inf_free_ctx(uintptr_t ctx);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -49,10 +36,10 @@ extern Handle zip_archive_open(const char* fn);
|
|||||||
// close the archive <ha> and set ha to 0
|
// close the archive <ha> and set ha to 0
|
||||||
extern int zip_archive_close(Handle& ha);
|
extern int zip_archive_close(Handle& ha);
|
||||||
|
|
||||||
|
// for all files in archive <ha>: call <cb>, passing <user>
|
||||||
|
// and the entries's complete path.
|
||||||
|
extern int zip_enum(const Handle ha, const FileCB cb, const uintptr_t user);
|
||||||
|
|
||||||
// all files in archive!
|
|
||||||
typedef int(*ZipFileCB)(const char* const fn, const uint flags, const ssize_t size, const uintptr_t user);
|
|
||||||
extern int zip_enum(const Handle ha, const ZipFileCB cb, const uintptr_t user);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// file
|
// file
|
||||||
@ -64,7 +51,7 @@ struct ZFile
|
|||||||
u32 magic;
|
u32 magic;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// keep offset of flags and size members in sync with struct ZFile!
|
// keep offset of flags and size members in sync with struct File!
|
||||||
// it is accessed by VFS and must be the same for both (union).
|
// it is accessed by VFS and must be the same for both (union).
|
||||||
// dirty, but necessary because VFile is pushing the HDATA size limit.
|
// dirty, but necessary because VFile is pushing the HDATA size limit.
|
||||||
uint flags;
|
uint flags;
|
||||||
@ -76,10 +63,10 @@ struct ZFile
|
|||||||
off_t last_raw_ofs;
|
off_t last_raw_ofs;
|
||||||
|
|
||||||
Handle ha;
|
Handle ha;
|
||||||
uintptr_t read_ctx;
|
uintptr_t inf_ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
// return file information for <fn> (may include path) in archive <ha>
|
// return file information for <fn> in archive <ha>
|
||||||
extern int zip_stat(Handle ha, const char* fn, struct stat* s);
|
extern int zip_stat(Handle ha, const char* fn, struct stat* s);
|
||||||
|
|
||||||
// open the file <fn> in archive <ha>, and fill *zf with information about it.
|
// open the file <fn> in archive <ha>, and fill *zf with information about it.
|
||||||
@ -125,7 +112,6 @@ extern Handle zip_start_io(ZFile* const zf, off_t ofs, size_t size, void* buf);
|
|||||||
// output parameters are zeroed on error.
|
// output parameters are zeroed on error.
|
||||||
extern int zip_wait_io(Handle hio, void*& p, size_t& size);
|
extern int zip_wait_io(Handle hio, void*& p, size_t& size);
|
||||||
|
|
||||||
|
|
||||||
// finished with transfer <hio> - free its buffer (returned by vfs_wait_io)
|
// finished with transfer <hio> - free its buffer (returned by vfs_wait_io)
|
||||||
extern int zip_discard_io(Handle& hio);
|
extern int zip_discard_io(Handle& hio);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user