int extract_fastfile(char * infilename, char * outfilename) { FILE *fd, *fdo = NULL; uint32_t inlen, outlen; int i, files; char *file_input, *file_output, *file_offset; setbuf(stdout, NULL); setbuf(stderr, NULL); file_input = infilename; file_output = outfilename; file_offset = "0x15"; printf("Extracting fastfile: %s\n", file_input); fd = fopen(file_input, "rb"); if(!fd) std_err(); if(minzip > INSZ) minzip = INSZ; if(minzip < 1) minzip = 1; in = malloc(INSZ); out = malloc(OUTSZ); filebuff = malloc(FBUFFSZ); if(!in || !out || !filebuff) std_err(); offset = get_num(file_offset); // do not skip, needed for buffseek buffseek(fd, offset, SEEK_SET); z.zalloc = (alloc_func)0; z.zfree = (free_func)0; z.opaque = (voidpf)0; if(inflateInit2(&z, zipwbits) != Z_OK) zlib_err(Z_INIT_ERROR); fdo = save_file(file_output); unzip(fd, &fdo, &inlen, &outlen); FCLOSE(fdo) printf("\n" "%u bytes compressed\n" "%u bytes extracted\n", inlen, outlen); FCLOSE(fdo) FCLOSE(fd) inflateEnd(&z); free(in); free(out); free(filebuff); return(0); }
static int HHA_seek(fvoid *opaque, PHYSFS_uint64 offset) { HHAfileinfo *finfo = (HHAfileinfo *) opaque; HHAentry *entry = finfo->entry; void *in = finfo->handle; BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0); BAIL_IF_MACRO(offset >= entry->uncompressed_size, ERR_PAST_EOF, 0); if (entry->compress == HHA_COMPRESS_NONE) { PHYSFS_sint64 newpos = offset + entry->offset; BAIL_IF_MACRO(!__PHYSFS_platformSeek(in, newpos), NULL, 0); finfo->uncompressed_position = (PHYSFS_uint32) offset; } else if (entry->compress == HHA_COMPRESS_ZLIB) { /* * If seeking backwards, we need to redecode the file * from the start and throw away the compressed bits until we hit * the offset we need. If seeking forward, we still need to * decode, but we don't rewind first. */ if (offset < finfo->uncompressed_position) { /* we do a copy so state is sane if inflateInit2() fails. */ z_stream str; initializeZStream(&str); if (zlib_err(inflateInit2(&str, -MAX_WBITS)) != Z_OK) return(0); if (!__PHYSFS_platformSeek(in, entry->offset)) return(0); inflateEnd(&finfo->zlib_stream); memcpy(&finfo->zlib_stream, &str, sizeof (z_stream)); finfo->uncompressed_position = finfo->compressed_position = 0; } /* if */ while (finfo->uncompressed_position != offset) { PHYSFS_uint8 buf[512]; PHYSFS_uint32 maxread; maxread = (PHYSFS_uint32) (offset - finfo->uncompressed_position); if (maxread > sizeof (buf)) maxread = sizeof (buf); if (HHA_read(finfo, buf, maxread, 1) != 1) return(0); } /* while */ } /* else */ else printf("LZMA file: %s/%s\n", entry->dir, entry->name); return(1); } /* HHA_seek */
static int ZIP_seek(fvoid *opaque, PHYSFS_uint64 offset) { ZIPfileinfo *finfo = (ZIPfileinfo *) opaque; ZIPentry *entry = finfo->entry; void *in = finfo->handle; BAIL_IF_MACRO(offset > entry->uncompressed_size, ERR_PAST_EOF, 0); if (entry->compression_method == COMPMETH_NONE) { PHYSFS_sint64 newpos = offset + entry->offset; BAIL_IF_MACRO(!__PHYSFS_platformSeek(in, newpos), NULL, 0); finfo->uncompressed_position = (PHYSFS_uint32) offset; } /* if */ else { /* * If seeking backwards, we need to redecode the file * from the start and throw away the compressed bits until we hit * the offset we need. If seeking forward, we still need to * decode, but we don't rewind first. */ if (offset < finfo->uncompressed_position) { /* we do a copy so state is sane if inflateInit2() fails. */ z_stream str; initializeZStream(&str); if (zlib_err(inflateInit2(&str, -MAX_WBITS)) != Z_OK) return(0); if (!__PHYSFS_platformSeek(in, entry->offset)) return(0); inflateEnd(&finfo->stream); memcpy(&finfo->stream, &str, sizeof (z_stream)); finfo->uncompressed_position = finfo->compressed_position = 0; } /* if */ while (finfo->uncompressed_position != offset) { PHYSFS_uint8 buf[512]; PHYSFS_uint32 maxread; maxread = (PHYSFS_uint32) (offset - finfo->uncompressed_position); if (maxread > sizeof (buf)) maxread = sizeof (buf); if (ZIP_read(finfo, buf, maxread, 1) != 1) return(0); } /* while */ } /* else */ return(1); } /* ZIP_seek */
int unzip(FILE *fd, FILE **fdo, uint32_t *inlen, uint32_t *outlen) { uint32_t oldsz = 0, oldoff, len; int ret = -1, zerr = Z_OK; oldoff = offset; inflateReset(&z); for(; (len = buffread(fd, in, INSZ)); buffinc(len)) { z.next_in = in; z.avail_in = len; do { z.next_out = out; z.avail_out = OUTSZ; zerr = inflate(&z, Z_SYNC_FLUSH); myfw(out, z.total_out - oldsz, *fdo); oldsz = z.total_out; if(zerr != Z_OK) { // inflate() return value MUST be handled now if(zerr == Z_STREAM_END) { ret = 0; } else { zlib_err(zerr); } break; } ret = 0; // it's better to return 0 even if the z stream is incomplete... or not? } while(z.avail_in); if(zerr != Z_OK) break; // Z_STREAM_END included, for avoiding "goto" } *inlen = z.total_in; *outlen = z.total_out; if(!ret) { oldoff += z.total_in; } else { oldoff++; } buffseek(fd, oldoff, SEEK_SET); return(ret); }
static fvoid *HHA_openRead(dvoid *opaque, const char *fnm, int *fileExists) { HHAinfo *info = (HHAinfo *) opaque; HHAfileinfo *finfo; HHAentry *entry; entry = HHA_find_entry(info, fnm); *fileExists = (entry != NULL); BAIL_IF_MACRO(entry == NULL, NULL, NULL); finfo = (HHAfileinfo *) allocator.Malloc(sizeof (HHAfileinfo)); BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL); memset(finfo, '\0', sizeof (HHAfileinfo)); finfo->handle = __PHYSFS_platformOpenRead(info->filename); if ( (finfo->handle == NULL) || (!__PHYSFS_platformSeek(finfo->handle, entry->offset)) ) { allocator.Free(finfo); return(NULL); } /* if */ finfo->entry = entry; if (finfo->entry->compress == HHA_COMPRESS_ZLIB) { initializeZStream(&finfo->zlib_stream); if (zlib_err(inflateInit2(&finfo->zlib_stream, -MAX_WBITS)) != Z_OK) { HHA_fileClose(finfo); return(NULL); } /* if */ finfo->buffer = (PHYSFS_uint8 *) allocator.Malloc(ZIP_READBUFSIZE); if (finfo->buffer == NULL) { HHA_fileClose(finfo); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ } /* if */ return(finfo); } /* HHA_openRead */
static PHYSFS_sint64 HHA_read(fvoid *opaque, void *buffer, PHYSFS_uint32 objSize, PHYSFS_uint32 objCount) { HHAfileinfo *finfo = (HHAfileinfo *) opaque; HHAentry *entry = finfo->entry; PHYSFS_sint64 retval = 0; PHYSFS_sint64 maxread = ((PHYSFS_sint64) objSize) * objCount; PHYSFS_sint64 avail = entry->uncompressed_size - finfo->uncompressed_position; BAIL_IF_MACRO(maxread == 0, NULL, 0); /* quick rejection. */ if (avail < maxread) { maxread = avail - (avail % objSize); objCount = (PHYSFS_uint32) (maxread / objSize); BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0); /* quick rejection. */ __PHYSFS_setError(ERR_PAST_EOF); /* this is always true here. */ } /* if */ if (entry->compress == HHA_COMPRESS_NONE) { retval = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount); } else if (entry->compress == HHA_COMPRESS_ZLIB) { finfo->zlib_stream.next_out = buffer; finfo->zlib_stream.avail_out = objSize * objCount; while (retval < maxread) { PHYSFS_uint32 before = finfo->zlib_stream.total_out; int rc; if (finfo->zlib_stream.avail_in == 0) { PHYSFS_sint64 br; br = entry->compressed_size - finfo->compressed_position; if (br > 0) { if (br > ZIP_READBUFSIZE) br = ZIP_READBUFSIZE; br = __PHYSFS_platformRead(finfo->handle, finfo->buffer, 1, (PHYSFS_uint32) br); if (br <= 0) break; finfo->compressed_position += (PHYSFS_uint32) br; finfo->zlib_stream.next_in = finfo->buffer; finfo->zlib_stream.avail_in = (PHYSFS_uint32) br; } /* if */ } /* if */ rc = zlib_err(inflate(&finfo->zlib_stream, Z_SYNC_FLUSH)); retval += (finfo->zlib_stream.total_out - before); if (rc != Z_OK) break; } /* while */ retval /= objSize; } if (retval > 0) finfo->uncompressed_position += (PHYSFS_uint32) (retval * objSize); return(retval); } /* HHA_read */
static PHYSFS_sint64 ZIP_read(fvoid *opaque, void *buf, PHYSFS_uint32 objSize, PHYSFS_uint32 objCount) { int total, i = 0; ZIPfileinfo *finfo = (ZIPfileinfo *) opaque; ZIPentry *entry = finfo->entry; PHYSFS_sint64 retval = 0; PHYSFS_sint64 maxread = ((PHYSFS_sint64) objSize) * objCount; PHYSFS_sint64 avail = entry->uncompressed_size - finfo->uncompressed_position; BAIL_IF_MACRO(maxread == 0, NULL, 0); /* quick rejection. */ if (avail < maxread) { maxread = avail - (avail % objSize); objCount = (PHYSFS_uint32) (maxread / objSize); BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0); /* quick rejection. */ __PHYSFS_setError(ERR_PAST_EOF); /* this is always true here. */ } /* if */ if (entry->compression_method == COMPMETH_NONE) { if (entry->encrypted == AES_ENCRYPTED) { retval = __PHYSFS_platformRead(finfo->handle, buf, objSize, objCount); total = maxread; while (total > 16) { fcrypt_decrypt(((char*)buf) + i, 16, &finfo->zctx); i += 16; total -= 16; } if (total > 0) { fcrypt_decrypt(((char*)buf) + i, total, &finfo->zctx); } } else { retval = __PHYSFS_platformRead(finfo->handle, buf, objSize, objCount); } } /* if */ else { finfo->stream.next_out = buf; finfo->stream.avail_out = objSize * objCount; while (retval < maxread) { PHYSFS_uint32 before = finfo->stream.total_out; int rc; if (finfo->stream.avail_in == 0) { PHYSFS_sint64 br; br = entry->compressed_size - finfo->compressed_position; if (br > 0) { if (br > ZIP_READBUFSIZE) br = ZIP_READBUFSIZE; br = __PHYSFS_platformRead(finfo->handle, finfo->buffer, 1, (PHYSFS_uint32) br); if (br <= 0) { break; } if (entry->encrypted == AES_ENCRYPTED) { total = br; i = 0; while (total > 16) { fcrypt_decrypt(finfo->buffer + i, 16, &finfo->zctx); i += 16; total -= 16; } if (total > 0) { fcrypt_decrypt(finfo->buffer + i, total, &finfo->zctx); } } finfo->compressed_position += (PHYSFS_uint32) br; finfo->stream.next_in = finfo->buffer; finfo->stream.avail_in = (PHYSFS_uint32) br; } /* if */ } /* if */ rc = zlib_err(inflate(&finfo->stream, Z_SYNC_FLUSH)); retval += (finfo->stream.total_out - before); if (rc != Z_OK) break; } /* while */ retval /= objSize; } /* else */ if (retval > 0) finfo->uncompressed_position += (PHYSFS_uint32) (retval * objSize); return(retval); } /* ZIP_read */