static void *LZMA_openArchive(const char *name, int forWriting) { PHYSFS_uint64 len; LZMAarchive *archive = NULL; ISzAlloc allocImp; ISzAlloc allocTempImp; BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL); BAIL_IF_MACRO(!LZMA_isArchive(name,forWriting), ERR_UNSUPPORTED_ARCHIVE, 0); archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive)); BAIL_IF_MACRO(archive == NULL, ERR_OUT_OF_MEMORY, NULL); archive->firstEntry = NULL; archive->lastEntry = NULL; if ((archive->stream.File = __PHYSFS_platformOpenRead(name)) == NULL) { allocator.Free(archive); return NULL; } /* if */ /* Prepare structs for 7z */ archive->stream.InStream.Read = SzFileReadImp; archive->stream.InStream.Seek = SzFileSeekImp; allocImp.Alloc = SzAllocPhysicsFS; allocImp.Free = SzFreePhysicsFS; allocTempImp.Alloc = SzAllocPhysicsFS; allocTempImp.Free = SzFreePhysicsFS; InitCrcTable(); SzArDbExInit(&archive->db); if (lzma_err(SzArchiveOpen(&archive->stream.InStream, &archive->db, &allocImp, &allocTempImp)) != SZ_OK) { __PHYSFS_platformClose(archive->stream.File); allocator.Free(archive); return NULL; } /* if */ len = archive->db.Database.NumFolders * sizeof (LZMAfolder); archive->folder = (LZMAfolder *) allocator.Malloc(len); BAIL_IF_MACRO(archive->folder == NULL, ERR_OUT_OF_MEMORY, NULL); /* * Init with 0 so we know when a folder is already cached * Values will be set by LZMA_read() */ memset(archive->folder, 0, (size_t) len); return(archive); } /* LZMA_openArchive */
static PHYSFS_sint64 LZMA_read(PHYSFS_Io *io, void *outBuf, PHYSFS_uint64 len) { LZMAfile *file = (LZMAfile *) io->opaque; size_t wantedSize = (size_t) len; const size_t remainingSize = file->item->Size - file->position; size_t fileSize = 0; BAIL_IF_MACRO(wantedSize == 0, ERRPASS, 0); /* quick rejection. */ BAIL_IF_MACRO(remainingSize == 0, PHYSFS_ERR_PAST_EOF, 0); if (wantedSize > remainingSize) wantedSize = remainingSize; /* Only decompress the folder if it is not already cached */ if (file->folder->cache == NULL) { const int rc = lzma_err(SzExtract( &file->archive->stream.inStream, /* compressed data */ &file->archive->db, /* 7z's database, containing everything */ file->index, /* Index into database arrays */ /* Index of cached folder, will be changed by SzExtract */ &file->folder->index, /* Cache for decompressed folder, allocated/freed by SzExtract */ &file->folder->cache, /* Size of cache, will be changed by SzExtract */ &file->folder->size, /* Offset of this file inside the cache, set by SzExtract */ &file->offset, &fileSize, /* Size of this file */ &file->archive->stream.allocImp, &file->archive->stream.allocTempImp)); if (rc != SZ_OK) return -1; } /* if */ /* Copy wanted bytes over from cache to outBuf */ memcpy(outBuf, (file->folder->cache + file->offset + file->position), wantedSize); file->position += wantedSize; /* Increase virtual position */ return wantedSize; } /* LZMA_read */
static void *LZMA_openArchive(PHYSFS_Io *io, const char *name, int forWriting) { PHYSFS_uint8 sig[k7zSignatureSize]; size_t len = 0; LZMAarchive *archive = NULL; assert(io != NULL); /* shouldn't ever happen. */ BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL); if (io->read(io, sig, k7zSignatureSize) != k7zSignatureSize) return 0; BAIL_IF_MACRO(!TestSignatureCandidate(sig), PHYSFS_ERR_UNSUPPORTED, NULL); BAIL_IF_MACRO(!io->seek(io, 0), ERRPASS, NULL); archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive)); BAIL_IF_MACRO(archive == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL); lzma_archive_init(archive); archive->stream.io = io; CrcGenerateTable(); SzArDbExInit(&archive->db); if (lzma_err(SzArchiveOpen(&archive->stream.inStream, &archive->db, &archive->stream.allocImp, &archive->stream.allocTempImp)) != SZ_OK) { SzArDbExFree(&archive->db, SzFreePhysicsFS); lzma_archive_exit(archive); return NULL; /* Error is set by lzma_err! */ } /* if */ len = archive->db.Database.NumFiles * sizeof (LZMAfile); archive->files = (LZMAfile *) allocator.Malloc(len); if (archive->files == NULL) { SzArDbExFree(&archive->db, SzFreePhysicsFS); lzma_archive_exit(archive); BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL); } /* * Init with 0 so we know when a folder is already cached * Values will be set by LZMA_openRead() */ memset(archive->files, 0, len); len = archive->db.Database.NumFolders * sizeof (LZMAfolder); archive->folders = (LZMAfolder *) allocator.Malloc(len); if (archive->folders == NULL) { SzArDbExFree(&archive->db, SzFreePhysicsFS); lzma_archive_exit(archive); BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL); } /* * Init with 0 so we know when a folder is already cached * Values will be set by LZMA_read() */ memset(archive->folders, 0, len); if(!lzma_files_init(archive)) { SzArDbExFree(&archive->db, SzFreePhysicsFS); lzma_archive_exit(archive); BAIL_MACRO(PHYSFS_ERR_OTHER_ERROR, NULL); } return archive; } /* LZMA_openArchive */
static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuffer, PHYSFS_uint32 objSize, PHYSFS_uint32 objCount) { LZMAentry *entry = (LZMAentry *) opaque; PHYSFS_sint64 wantedSize = objSize*objCount; PHYSFS_sint64 remainingSize = entry->file->Size - entry->position; size_t fileSize; ISzAlloc allocImp; ISzAlloc allocTempImp; BAIL_IF_MACRO(wantedSize == 0, NULL, 0); /* quick rejection. */ BAIL_IF_MACRO(remainingSize == 0, ERR_PAST_EOF, 0); if (remainingSize < wantedSize) { wantedSize = remainingSize - (remainingSize % objSize); objCount = (PHYSFS_uint32) (remainingSize / objSize); BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0); /* quick rejection. */ __PHYSFS_setError(ERR_PAST_EOF); /* this is always true here. */ } /* if */ /* Prepare callbacks for 7z */ allocImp.Alloc = SzAllocPhysicsFS; allocImp.Free = SzFreePhysicsFS; allocTempImp.Alloc = SzAllocPhysicsFS; allocTempImp.Free = SzFreePhysicsFS; /* Only decompress the folder if it is not allready cached */ if (entry->archive->folder[entry->folderIndex].cache == NULL) { size_t tmpsize = entry->archive->folder[entry->folderIndex].size; int rc = lzma_err(SzExtract( &entry->archive->stream.InStream, /* compressed data */ &entry->archive->db, entry->fileIndex, /* Index of cached folder, will be changed by SzExtract */ &entry->archive->folder[entry->folderIndex].index, /* Cache for decompressed folder, allocated/freed by SzExtract */ &entry->archive->folder[entry->folderIndex].cache, /* Size of cache, will be changed by SzExtract */ &tmpsize, /* Offset of this file inside the cache, set by SzExtract */ &entry->offset, &fileSize, /* Size of this file */ &allocImp, &allocTempImp)); entry->archive->folder[entry->folderIndex].size = tmpsize; if (rc != SZ_OK) return -1; } /* if */ /* Copy wanted bytes over from cache to outBuffer */ /* !!! FIXME: strncpy for non-string data? */ strncpy(outBuffer, (void*) (entry->archive->folder[entry->folderIndex].cache + entry->offset + entry->position), (size_t) wantedSize); entry->position += wantedSize; return objCount; } /* LZMA_read */