diff --git a/source/lib/res/file.cpp b/source/lib/res/file.cpp index 3c514d50eb..2f4e1a0a4a 100755 --- a/source/lib/res/file.cpp +++ b/source/lib/res/file.cpp @@ -188,12 +188,13 @@ struct DirEnt { const std::string name; const uint flags; - const ssize_t size; + const off_t size; - DirEnt(const char* const _name, const uint _flags, const ssize_t _size) + DirEnt(const char* const _name, const uint _flags, const off_t _size) : name(_name), flags(_flags), size(_size) {} }; +// pointer to DirEnt: faster sorting, but more allocs. typedef std::vector DirEnts; typedef DirEnts::const_iterator DirEntIt; @@ -253,7 +254,7 @@ int file_enum(const char* const dir, const FileCB cb, const uintptr_t user) } uint flags = 0; - ssize_t size = s.st_size; + off_t size = s.st_size; // dir if(s.st_mode & S_IFDIR) @@ -399,7 +400,7 @@ int file_open(const char* p_fn, uint flags, File* f) { // don't stat if opening for writing - the file may not exist yet - size_t size = 0; + off_t size = 0; int mode = O_RDONLY; if(flags & FILE_WRITE) @@ -466,7 +467,7 @@ struct ll_cb }; -int ll_start_io(File* f, size_t ofs, size_t size, void* p, ll_cb* lcb) +int ll_start_io(File* f, off_t ofs, size_t size, void* p, ll_cb* lcb) { CHECK_FILE(f) @@ -481,12 +482,14 @@ int ll_start_io(File* f, size_t ofs, size_t size, void* p, ll_cb* lcb) return -1; } - size_t bytes_left = f->size - ofs; // > 0 + off_t bytes_left = f->size - ofs; // > 0 int op = (f->flags & FILE_WRITE)? LIO_WRITE : LIO_READ; - // don't read beyond EOF - if(size > bytes_left) // avoid min() - it wants int - size = bytes_left; + // cut off at EOF. + // avoid min() due to type conversion warnings. + if((off_t)size > bytes_left) + size = (size_t)bytes_left; + // guaranteed to fit, since size was > bytes_left aiocb* cb = &lcb->cb; @@ -495,7 +498,7 @@ int ll_start_io(File* f, size_t ofs, size_t size, void* p, ll_cb* lcb) cb->aio_buf = p; cb->aio_fildes = f->fd; cb->aio_offset = (off_t)ofs; - cb->aio_nbytes = size; + cb->aio_nbytes = (size_t)size; return lio_listio(LIO_NOWAIT, &cb, 1, (struct sigevent*)0); // this just issues the I/O - doesn't wait until complete. } @@ -536,7 +539,7 @@ static Cache c; // create an id for use with the Cache that uniquely identifies // the block from the file containing . -static u64 block_make_id(const u32 fn_hash, const size_t ofs) +static u64 block_make_id(const u32 fn_hash, const off_t ofs) { // id format: filename hash | block number // 63 32 31 0 @@ -684,7 +687,7 @@ struct IO // so we don't allocate a new cb every file_start_io. void* user_p; - size_t user_ofs; + off_t user_ofs; size_t user_size; int cached : 1; @@ -700,8 +703,8 @@ H_TYPE_DEFINE(IO) static void IO_init(IO* io, va_list args) { - size_t size = round_up(sizeof(struct ll_cb), 16); - io->cb = (ll_cb*)mem_alloc(size, 16, MEM_ZERO); + const size_t cb_size = round_up(sizeof(struct ll_cb), 16); + io->cb = (ll_cb*)mem_alloc(cb_size, 16, MEM_ZERO); } static void IO_dtor(IO* io) @@ -867,7 +870,7 @@ static Handle io_find(u64 block_id) // pads the request up to BLOCK_SIZE, and stores the original parameters in IO. // transfers of more than 1 block (including padding) are allowed, but do not // go through the cache. don't see any case where that's necessary, though. -Handle file_start_io(File* f, size_t user_ofs, size_t user_size, void* user_p) +Handle file_start_io(File* f, off_t user_ofs, size_t user_size, void* user_p) { int err; @@ -884,12 +887,13 @@ Handle file_start_io(File* f, size_t user_ofs, size_t user_size, void* user_p) return -1; } - const size_t bytes_left = f->size - user_ofs; // > 0 + const off_t bytes_left = f->size - user_ofs; // > 0 int op = (f->flags & FILE_WRITE)? LIO_WRITE : LIO_READ; // don't read beyond EOF - if(user_size > bytes_left) // avoid min() - it wants int - user_size = bytes_left; + if((off_t)user_size > bytes_left) // avoid min() - it wants int + user_size = (size_t)bytes_left; + // guaranteed to fit in user_size, since user_size > bytes_left u64 block_id = block_make_id(f->fn_hash, user_ofs); @@ -919,9 +923,9 @@ debug_out("file_start_io hio=%I64x ofs=%d size=%d\n", hio, user_ofs, user_size); // a zip archive may contain one last file in the block. // if not, no loss - the buffer will be LRU, and reused. - size_t ofs = user_ofs; + off_t ofs = user_ofs; size_t padding = ofs % BLOCK_SIZE; - ofs -= padding; + ofs -= (off_t)padding; size_t size = round_up(padding + user_size, BLOCK_SIZE); @@ -1060,7 +1064,7 @@ int file_discard_io(Handle& hio) // // return (positive) number of raw bytes transferred if successful; // otherwise, an error code. -ssize_t file_io(File* const f, const size_t raw_ofs, size_t raw_size, void** const p, +ssize_t file_io(File* const f, const off_t raw_ofs, size_t raw_size, void** const p, const FILE_IO_CB cb, const uintptr_t ctx) // optional { #ifdef PARANOIA @@ -1078,9 +1082,14 @@ debug_out("file_io fd=%d size=%d ofs=%d\n", f->fd, raw_size, raw_ofs); // reading: make sure we don't go beyond EOF if(!is_write) { - if(raw_ofs >= f->size) + // cut off at EOF. + // avoid min() due to type conversion warnings. + off_t bytes_left = f->size - raw_ofs; + if(bytes_left < 0) return ERR_EOF; - raw_size = MIN(f->size - raw_ofs, raw_size); + if((off_t)raw_size > bytes_left) + raw_size = (size_t)bytes_left; + // guaranteed to fit, since size was > bytes_left } // writing: make sure buffer is valid else @@ -1098,7 +1107,7 @@ debug_out("file_io fd=%d size=%d ofs=%d\n", f->fd, raw_size, raw_ofs); // actual transfer start offset // not aligned! aio takes care of initial unalignment; // next read will be aligned, because we read up to the next block. - const size_t start_ofs = raw_ofs; + const off_t start_ofs = raw_ofs; void* buf = 0; // I/O source or sink; assume temp buffer @@ -1187,7 +1196,7 @@ debug_out("file_io fd=%d size=%d ofs=%d\n", f->fd, raw_size, raw_ofs); { // calculate issue_size: // at most, transfer up to the next block boundary. - size_t issue_ofs = start_ofs + issue_cnt; + off_t issue_ofs = (off_t)(start_ofs + issue_cnt); const size_t left_in_block = BLOCK_SIZE - (issue_ofs % BLOCK_SIZE); const size_t total_left = raw_size - issue_cnt; size_t issue_size = MIN(left_in_block, total_left); diff --git a/source/lib/res/file.h b/source/lib/res/file.h index ceed212078..ff3ffe9964 100755 --- a/source/lib/res/file.h +++ b/source/lib/res/file.h @@ -34,7 +34,7 @@ struct File // it is accessed by VFS and must be the same for both (union). // dirty, but necessary because VFile is pushing the HDATA size limit. int flags; - size_t size; + off_t size; u32 fn_hash; @@ -91,7 +91,7 @@ extern int file_close(File* f); extern int file_map(File* f, void*& p, size_t& size); extern int file_unmap(File* f); -extern Handle file_start_io(File* f, size_t ofs, size_t size, void* buf); +extern Handle file_start_io(File* f, off_t ofs, size_t size, void* buf); extern int file_wait_io(const Handle hio, void*& p, size_t& size); extern int file_discard_io(Handle& hio); @@ -103,7 +103,7 @@ extern int file_discard_io(Handle& hio); // > 0: bytes output (not used ATM; useful for statistics) - continue. typedef ssize_t(*FILE_IO_CB)(uintptr_t ctx, void* p, size_t size); -extern ssize_t file_io(File* f, size_t ofs, size_t size, void** p, +extern ssize_t file_io(File* f, off_t ofs, size_t size, void** p, FILE_IO_CB cb = 0, uintptr_t ctx = 0); diff --git a/source/lib/res/h_mgr.h b/source/lib/res/h_mgr.h index 16f1885567..5a41e01c73 100755 --- a/source/lib/res/h_mgr.h +++ b/source/lib/res/h_mgr.h @@ -94,31 +94,37 @@ struct H_VTbl typedef H_VTbl* H_Type; -#define H_TYPE_DEFINE(t)\ +#define H_TYPE_DEFINE(type)\ /* forward decls */\ - static void t##_init(t*, va_list);\ - static int t##_reload(t*, const char*);\ - static void t##_dtor(t*);\ - static H_VTbl V_##t =\ + static void type##_init(type*, va_list);\ + static int type##_reload(type*, const char*);\ + static void type##_dtor(type*);\ + static H_VTbl V_##type =\ {\ - (void(*)(void*, va_list))t##_init,\ - (int(*)(void*, const char*))t##_reload,\ - (void(*)(void*))t##_dtor,\ - sizeof(t), /* control block size */\ - #t /* name */\ + (void(*)(void*, va_list))type##_init,\ + (int(*)(void*, const char*))type##_reload,\ + (void(*)(void*))type##_dtor,\ + sizeof(type), /* control block size */\ + #type /* name */\ };\ - static H_Type H_##t = &V_##t; + static H_Type H_##type = &V_##type; // note: we cast to void* pointers so the functions can be declared to // take the control block pointers, instead of requiring a cast in each. // the forward decls ensure the function signatures are correct. -// * = H_USER_DATA(, ) -#define H_USER_DATA(h, type) (type*)h_user_data(h, H_##type); +// convenience macro for h_user_data: +// casts its return value to the control block type. +// use if H_DEREF's returning a negative error code isn't acceptable. +#define H_USER_DATA(h, type) (type*)h_user_data(h, H_##type) +// even more convenient wrapper for h_user_data: +// declares a pointer (), assigns it H_USER_DATA, and has +// the user's function return a negative error code on failure. #define H_DEREF(h, type, var)\ - type* const var = (type*)h_user_data(h, H_##type);\ + /* don't use STMT - var decl must be visible to "caller" */\ + type* const var = H_USER_DATA(h, type);\ if(!var)\ return ERR_INVALID_HANDLE; @@ -173,7 +179,9 @@ extern int h_free(Handle& h, H_Type type); // currently O(n). extern Handle h_find(H_Type type, uintptr_t key); -// return a pointer to handle data, or 0 on error +// returns a void* pointer to the control block of the resource , +// or 0 on error (i.e. h is invalid or of the wrong type). +// prefer using H_DEREF or H_USER_DATA. extern void* h_user_data(Handle h, H_Type type); extern const char* h_filename(Handle h); diff --git a/source/lib/res/vfs.cpp b/source/lib/res/vfs.cpp index ce40a27a41..e6a908f4f9 100755 --- a/source/lib/res/vfs.cpp +++ b/source/lib/res/vfs.cpp @@ -955,7 +955,7 @@ H_TYPE_DEFINE(VFile) // use the functions below to insulate against change a bit. -static size_t& vf_size(VFile* vf) +static off_t& vf_size(VFile* vf) { assert(offsetof(struct File, size) == offsetof(struct ZFile, ucsize)); return vf->f.size; @@ -1061,7 +1061,7 @@ debug_out("vfs_close %I64x\n", h); } -ssize_t vfs_io(Handle hf, size_t ofs, size_t size, void*& p) +ssize_t vfs_io(Handle hf, off_t ofs, size_t size, void*& p) { #ifdef PARANOIA debug_out("vfs_io ofs=%d size=%d\n", ofs, size); @@ -1146,20 +1146,24 @@ int vfs_store(const char* fn, void* p, size_t size) -Handle vfs_map(const char* fn, uint flags, void*& p, size_t& size) +int vfs_map(const Handle hf, uint flags, void*& p, size_t& size) { - Handle hf = vfs_open(fn, flags); H_DEREF(hf, VFile, vf); - CHECK_ERR(file_map(&vf->f, p, size)); -MEM_DTOR dtor = 0; -uintptr_t ctx = 0; - return mem_assign(p, size, 0, dtor, ctx); + + if(vf_flags(vf) & VF_ZIP) + CHECK_ERR(zip_map(&vf->zf, p, size)); + else + CHECK_ERR(file_map(&vf->f, p, size)); + return 0; } -int vfs_unmap(Handle& hm) +int vfs_unmap(Handle hf) { - return -1; -// return h_free(hm, H_MMap); + H_DEREF(hf, VFile, vf); + if(vf_flags(vf) & VF_ZIP) + CHECK_ERR(zip_unmap(&vf->zf)); + else + CHECK_ERR(file_unmap(&vf->f)); + return 0; } - diff --git a/source/lib/res/vfs.h b/source/lib/res/vfs.h index 4dd19f89c7..ec56dd0a8b 100755 --- a/source/lib/res/vfs.h +++ b/source/lib/res/vfs.h @@ -41,7 +41,8 @@ extern Handle vfs_load(const char* fn, void*& p, size_t& size); extern Handle vfs_open(const char* fn, uint flags = 0); extern int vfs_close(Handle& h); -extern Handle vfs_map(Handle hf, uint flags, void*& p, size_t& size); +extern int vfs_map(Handle hf, uint flags, void*& p, size_t& size); +extern int vfs_unmap(Handle hf); struct vfsDirEnt @@ -70,11 +71,11 @@ extern int vfs_rebuild(); // async read interface // -extern Handle vfs_start_read(const Handle hf, size_t ofs, size_t& advance, void* buf); +extern Handle vfs_start_read(const Handle hf, off_t ofs, size_t& advance, void* buf); extern int vfs_wait_read(Handle hr, void*& p, size_t& size); extern int vfs_discard_read(Handle& hr); -extern ssize_t vfs_io(Handle hf, size_t ofs, size_t size, void*& p); +extern ssize_t vfs_io(Handle hf, off_t ofs, size_t size, void*& p); // keep in sync with File flags! diff --git a/source/lib/res/zip.cpp b/source/lib/res/zip.cpp index a7814486d5..186e65ee96 100755 --- a/source/lib/res/zip.cpp +++ b/source/lib/res/zip.cpp @@ -46,9 +46,9 @@ // convenience container for location / size of file in archive. struct ZFileLoc { - size_t ofs; - size_t csize; // = 0 if not compressed - size_t ucsize; + off_t ofs; + off_t csize; // = 0 if not compressed + off_t ucsize; // why csize? // file I/O may be N-buffered, so it's good to know when the raw data @@ -108,7 +108,7 @@ static int zip_find_ecdr(const void* const file, const size_t size, const u8*& e if(*(u32*)ecdr == *(u32*)&ecdr_id) goto found_ecdr; - // check next 4 bytes (non aligned!!) + // check next 4 bytes (unaligned!!) ecdr++; bytes_left--; } @@ -127,7 +127,7 @@ found_ecdr: // make sure the LFH fields match those passed (from the CDFH). // only used in PARANOIA builds - costs time when opening archives. -static int zip_verify_lfh(const void* const file, const size_t lfh_ofs, const size_t file_ofs) +static int zip_verify_lfh(const void* const file, const off_t lfh_ofs, const off_t file_ofs) { const char lfh_id[] = "PK\3\4"; // signature const size_t LFH_SIZE = 30; @@ -145,7 +145,7 @@ static int zip_verify_lfh(const void* const file, const size_t lfh_ofs, const si const u16 lfh_fn_len = read_le16(lfh+26); const u16 lfh_e_len = read_le16(lfh+28); - const size_t lfh_file_ofs = lfh_ofs + LFH_SIZE + lfh_fn_len + lfh_e_len; + const off_t lfh_file_ofs = lfh_ofs + LFH_SIZE + lfh_fn_len + lfh_e_len; if(file_ofs != lfh_file_ofs) { @@ -196,9 +196,9 @@ static int zip_read_cdfh(const u8*& cdfh, const char*& fn, size_t& fn_len, ZFile fn = fn_; fn_len = fn_len_; - loc->ofs = lfh_ofs + LFH_SIZE + fn_len_ + e_len; - loc->csize = csize_; - loc->ucsize = ucsize_; + loc->ofs = (off_t)(lfh_ofs + LFH_SIZE + fn_len_ + e_len); + loc->csize = (off_t)csize_; + loc->ucsize = (off_t)ucsize_; // performance issue: want to avoid seeking between LFHs and central dir. // would be safer to calculate file offset from the LFH, since its @@ -856,7 +856,7 @@ int zip_stat(Handle ha, const char* fn, struct stat* s) lookup_get_file_info(li, idx, fn2, &loc); // can't fail - returned valid index above - s->st_size = (off_t)loc.ucsize; + s->st_size = loc.ucsize; return 0; } @@ -874,7 +874,7 @@ static inline bool is_compressed(ZFile* zf) // note: we go to a bit of trouble to make sure the buffer we allocated // (if p == 0) is freed when the read fails. -ssize_t zip_read(ZFile* zf, size_t raw_ofs, size_t size, void*& p) +ssize_t zip_read(ZFile* zf, off_t raw_ofs, size_t size, void*& p) { CHECK_ZFILE(zf) @@ -885,7 +885,7 @@ ssize_t zip_read(ZFile* zf, size_t raw_ofs, size_t size, void*& p) if(!za) return ERR_INVALID_HANDLE; - const size_t ofs = zf->ofs + raw_ofs; + const off_t ofs = zf->ofs + raw_ofs; // not compressed - just pass it on to file_io // (avoid the Zip inflate start/finish stuff below) @@ -946,7 +946,7 @@ fail: } -int zip_map(ZFile* zf, void*& p, size_t& size) +int zip_map(ZFile* const zf, void*& p, size_t& size) { CHECK_ZFILE(zf) @@ -958,5 +958,17 @@ int zip_map(ZFile* zf, void*& p, size_t& size) } H_DEREF(zf->ha, ZArchive, za) + // increase refs + return file_map(&za->f, p, size); } + + +int zip_unmap(ZFile* const zf) +{ + CHECK_ZFILE(zf) + H_DEREF(zf->ha, ZArchive, za) + // decrement refs + // unmap archive if 0 + return 0; +} diff --git a/source/lib/res/zip.h b/source/lib/res/zip.h index 2c5f641735..b394200d86 100755 --- a/source/lib/res/zip.h +++ b/source/lib/res/zip.h @@ -77,9 +77,9 @@ struct ZFile size_t ucsize; // size of logical file - size_t ofs; - size_t csize; - size_t last_raw_ofs; + off_t ofs; + off_t csize; + off_t last_raw_ofs; Handle ha; uintptr_t read_ctx; @@ -96,30 +96,10 @@ extern int zip_close(ZFile* zf); extern int zip_map(ZFile* zf, void*& p, size_t& size); +extern int zip_unmap(ZFile* zf); -extern ssize_t zip_read(ZFile* zf, size_t ofs, size_t size, void*& p); - - -//-------- - -// read from file , starting at offset in the compressed data -// (typically only used if the file is known to be stored). -// p == 0: allocate, read into, and return the output buffer -// p != 0: read into given output buffer, return handle to it -// if file is compressed, size must be >= uncompressed file size -// size: no input value, unless specifying an output buffer (p != 0) -// out: - - - - -//extern void* zip_mmap( - - - - - - +// read from file , starting at offset in the compressed data +extern ssize_t zip_read(ZFile* zf, off_t ofs, size_t size, void*& p); #endif // #ifndef __ZIP_H__