static int unzip_seek_helper (FILE *file, int offset) { char buffer[MAXBUFSIZE]; int n, tmp, pos = unztell (file); // returns ftell() of the "current file" if (pos == offset) return 0; else if (pos > offset) { unzCloseCurrentFile (file); unzip_goto_file (file, unzip_current_file_nr); unzOpenCurrentFile (file); pos = 0; } n = offset - pos; while (n > 0 && !unzeof (file)) { tmp = unzReadCurrentFile (file, buffer, n > MAXBUFSIZE ? MAXBUFSIZE : n); if (tmp < 0) return -1; n -= tmp; } return n > 0 ? -1 : 0; }
long ftell2 (FILE *file) { #undef ftell fmode2_t fmode = get_fmode (file); if (fmode == FM_NORMAL) return ftell (file); else if (fmode == FM_GZIP) return gztell (file); else if (fmode == FM_ZIP) return unztell (file); // returns ftell() of the "current file" else return -1; #define ftell ftell2 }
/* * Returns -1 if an error occurs. */ int FS_Tell(fileHandle_t f) { fsHandle_t *handle; handle = FS_GetFileByHandle(f); if (handle->file) { return ftell(handle->file); } #ifdef ZIP else if (handle->zip) { return unztell(handle->zip); } #endif return -1; }
/* ================= idFile_InZip::Tell ================= */ int idFile_InZip::Tell( void ) { return unztell( z ); }
static int Tell(ngeVF *f) { ngeVFZip* zip = (ngeVFZip*)f; return unztell(zip->file); }
size_t FileAccessZip::get_pos() const { ERR_FAIL_COND_V(!zfile, 0); return unztell(zfile); };
void FS_Seek(fileHandle_t f, int offset, fsOrigin_t origin) { #ifdef ZIP byte dummy[0x8000]; /* Dummy buffer to skip bytes. */ int len; /* Length of byte chunk to skip. */ int r; /* Number of bytes read. */ int remaining = 0; /* Remaining bytes to skip. */ unz_file_info info; /* ZIP information. */ #endif fsHandle_t *handle; /* File handle. */ handle = FS_GetFileByHandle(f); if (handle->file) { switch (origin) { case FS_SEEK_SET: fseek(handle->file, offset, SEEK_SET); break; case FS_SEEK_CUR: fseek(handle->file, offset, SEEK_CUR); break; case FS_SEEK_END: fseek(handle->file, offset, SEEK_END); break; default: Com_Error(ERR_FATAL, "FS_Seek: bad origin (%i)", origin); break; } } #ifdef ZIP else if (handle->zip) { switch (origin) { case FS_SEEK_SET: remaining = offset; break; case FS_SEEK_CUR: remaining = offset + unztell(handle->zip); break; case FS_SEEK_END: unzGetCurrentFileInfo(handle->zip, &info, NULL, 0, NULL, 0, NULL, 0); remaining = offset + info.uncompressed_size; break; default: Com_Error(ERR_FATAL, "FS_Seek: bad origin (%i)", origin); break; } /* Reopen the file. */ unzCloseCurrentFile(handle->zip); unzOpenCurrentFile(handle->zip); /* Skip until the desired offset is reached. */ while (remaining) { len = remaining; if (len > sizeof(dummy)) { len = sizeof(dummy); } r = unzReadCurrentFile(handle->zip, dummy, len); if (r <= 0) { break; } remaining -= r; } } #endif }
size_t unzStream::pos (void) { return (unztell(file)); }
int fseek2 (FILE *file, long offset, int mode) { #undef fseek st_finfo_t *finfo = get_finfo (file); /* // if (fmode != FM_NORMAL) printf ("fmode = %s\n", finfo->fmode == FM_NORMAL ? "FM_NORMAL" : (finfo->fmode == FM_GZIP ? "FM_GZIP" : (finfo->fmode == FM_ZIP ? "FM_ZIP" : "FM_UNDEF"))); */ if (finfo->fmode == FM_NORMAL) return fseek (file, offset, mode); else if (finfo->fmode == FM_GZIP) { if (mode == SEEK_END) // zlib doesn't support SEEK_END { // Note that this is _slow_... while (!gzeof (file)) { gzgetc (file); // necessary for _uncompressed_ files in order to set EOF gzseek (file, 1024 * 1024, SEEK_CUR); } offset += gztell (file); mode = SEEK_SET; } /* F*****G zlib documentation! It took me around 4 hours of debugging time to find out that the doc is wrong! From the doc: gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) That is not true for uncompressed files. gzrewind() doesn't change the file pointer for uncompressed files in the ports I tested (zlib 1.1.3, DJGPP, Cygwin & GNU/Linux). It clears the EOF indicator. */ if (!finfo->compressed) gzrewind (file); return gzseek (file, offset, mode) == -1 ? -1 : 0; } else if (finfo->fmode == FM_ZIP) { int base; if (mode != SEEK_SET && mode != SEEK_CUR && mode != SEEK_END) { errno = EINVAL; return -1; } if (mode == SEEK_SET) base = 0; else if (mode == SEEK_CUR) base = unztell (file); else // mode == SEEK_END { unz_file_info info; unzip_goto_file (file, unzip_current_file_nr); unzGetCurrentFileInfo (file, &info, NULL, 0, NULL, 0, NULL, 0); base = info.uncompressed_size; } return unzip_seek_helper (file, base + offset); } return -1; #define fseek fseek2 }
nglFileOffset nglZipFS::GetPos(void* pUnzip) const { unzSetCurrentFile(mpPrivate->mZip, pUnzip); return unztell(mpPrivate->mZip); }