/*! * \brief * Decompresses a single file entry from a 7zip archive, into memory. * * \param archive_stream * The stream to read the compressed data from. * * \param archive_desc * The archives description struct. * * \param look_stream * The stream associated with the archive stream. * * \param file_index * Index of the file to extract. * * \param uncompressed_data * The pointer reference to set when allocating memory for the uncompressed data. * * \param uncompressed_data_size * Reference to set the uncompressed datas size to. * * \returns * Returns SZ_OK if decompression was successfully, otherwise returns a non-zero value. * * Decompresses a single file entry from a 7zip archive, into memory. */ static SRes Decompress(CFileInStream& archive_stream, CSzArEx& archive_desc, CLookToRead& look_stream, uint32 file_index, byte*& uncompressed_data, size_t& uncompressed_data_size) { ISzAlloc alloc_imp; SRes result = SZ_OK; // set functions 7zip will use to allocated and free memory alloc_imp.Alloc = AllocFunc; alloc_imp.Free = FreeFunc; UInt32 block_index = 0xFFFFFFFF; size_t offset = 0; size_t out_size_processed = 0; // decompress the requested file, saving the uncompressed data into memory result = SzArEx_Extract(&archive_desc, &look_stream.s, file_index, &block_index, &uncompressed_data, &uncompressed_data_size, &offset, &out_size_processed, &alloc_imp, &alloc_imp); if (result != SZ_OK) { // the decompression failed, so delete the allocated data IAlloc_Free(&alloc_imp, uncompressed_data); uncompressed_data = NULL; uncompressed_data_size = 0; } return result; }
void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) { uint32_t i; if (p->Coders) for (i = 0; i < p->NumCoders; i++) SzCoderInfo_Free(&p->Coders[i], alloc); IAlloc_Free(alloc, p->Coders); IAlloc_Free(alloc, p->BindPairs); IAlloc_Free(alloc, p->PackStreams); IAlloc_Free(alloc, p->UnpackSizes); SzFolder_Init(p); }
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->FolderStartPackStreamIndex); IAlloc_Free(alloc, p->PackStreamStartPositions); IAlloc_Free(alloc, p->FolderStartFileIndex); IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); IAlloc_Free(alloc, p->FileNameOffsets); Buf_Free(&p->FileNames, alloc); SzAr_Free(&p->db, alloc); SzArEx_Init(p); }
void SzAr_Free(CSzAr *p, ISzAlloc *alloc) { uint32_t i; if (p->Folders) for (i = 0; i < p->NumFolders; i++) SzFolder_Free(&p->Folders[i], alloc); IAlloc_Free(alloc, p->PackSizes); IAlloc_Free(alloc, p->PackCRCsDefined); IAlloc_Free(alloc, p->PackCRCs); IAlloc_Free(alloc, p->Folders); IAlloc_Free(alloc, p->Files); SzAr_Init(p); }
~Qt7zPackagePrivate() { if (m_outBuffer) { IAlloc_Free(&m_allocImp, m_outBuffer); m_outBuffer = 0; } }
static void _7z_close(ar_archive *ar) { ar_archive_7z *_7z = (ar_archive_7z *)ar; free(_7z->entry_name); SzArEx_Free(&_7z->data, &gSzAlloc); IAlloc_Free(&gSzAlloc, _7z->uncomp.buffer); }
~C7zArchive() { if (OutBuffer != NULL) { IAlloc_Free(&g_Alloc, OutBuffer); } SzArEx_Free(&DB, &g_Alloc); }
static void CMtThread_Destruct(CMtThread *p) { CMtThread_CloseEvents(p); if (Thread_WasCreated(&p->thread.thread)) { LoopThread_StopAndWait(&p->thread); LoopThread_Close(&p->thread); } if (p->mtCoder->alloc) IAlloc_Free(p->mtCoder->alloc, p->outBuf); p->outBuf = 0; if (p->mtCoder->alloc) IAlloc_Free(p->mtCoder->alloc, p->inBuf); p->inBuf = 0; }
CArchive7Zip::~CArchive7Zip() { if (outBuffer) { IAlloc_Free(&allocImp, outBuffer); } if (isOpen) { File_Close(&archiveStream.file); } SzArEx_Free(&db, &allocImp); }
static SRes SzReadAndDecodePackedStreams( ILookInStream *inStream, CSzData *sd, CBuf *outBuffer, uint64_t baseOffset, ISzAlloc *allocTemp) { CSzAr p; uint64_t *unpackSizes = 0; uint8_t *digestsDefined = 0; uint32_t *digests = 0; SRes res; SzAr_Init(&p); res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, &p, &unpackSizes, &digestsDefined, &digests, allocTemp); SzAr_Free(&p, allocTemp); IAlloc_Free(allocTemp, unpackSizes); IAlloc_Free(allocTemp, digestsDefined); IAlloc_Free(allocTemp, digests); return res; }
static SRes SzReadAndDecodePackedStreams( ISeekInStream *inStream, CSzData *sd, ISeqOutStream *outStream, UInt64 baseOffset, ISzAlloc *allocTemp) { CSzAr p; UInt64 *unpackSizes = 0; Byte *digestsDefined = 0; UInt32 *digests = 0; SRes res; SzAr_Init(&p); res = SzReadAndDecodePackedStreams2(inStream, sd, outStream, baseOffset, &p, &unpackSizes, &digestsDefined, &digests, allocTemp); SzAr_Free(&p, allocTemp); IAlloc_Free(allocTemp, unpackSizes); IAlloc_Free(allocTemp, digestsDefined); IAlloc_Free(allocTemp, digests); return res; }
void Qt7zPackagePrivate::reset() { m_packagePath.clear(); m_isOpen = false; m_fileNameList.clear(); m_fileInfoList.clear(); m_blockIndex = 0xFFFFFFFF; if (m_outBuffer) { IAlloc_Free(&m_allocImp, m_outBuffer); m_outBufferSize = 0; } }
void SzArEx_DictCache_free(SzArEx_DictCache *dictCache) { if (dictCache->mapFile) { // unmap memory SzArEx_DictCache_munmap(dictCache); // close file handle (it will be set to NULL in init method) // FIXME: can we close the FILE* and just hold on to the mmap pointer? I think // that will keep the fd open until the mapping is closed. fclose(dictCache->mapFile); } else if (dictCache->outBuffer != 0) { // free memory that was allocated on the heap IAlloc_Free(dictCache->allocMain, dictCache->outBuffer); } SzArEx_DictCache_init(dictCache, dictCache->allocMain); }
static void sevenzip_stream_free(void *data) { struct sevenzip_context_t *sevenzip_context = (struct sevenzip_context_t*)data; if (!sevenzip_context) return; if (sevenzip_context->output) { IAlloc_Free(&sevenzip_context->allocImp, sevenzip_context->output); sevenzip_context->output = NULL; sevenzip_context->handle->data = NULL; } SzArEx_Free(&sevenzip_context->db, &sevenzip_context->allocImp); File_Close(&sevenzip_context->archiveStream.file); }
static void SzAr_Free(CSzAr *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->PackPositions); SzBitUi32s_Free(&p->FolderCRCs, alloc); IAlloc_Free(alloc, p->FoCodersOffsets); IAlloc_Free(alloc, p->FoStartPackStreamIndex); IAlloc_Free(alloc, p->FoToCoderUnpackSizes); IAlloc_Free(alloc, p->FoToMainUnpackSizeIndex); IAlloc_Free(alloc, p->CoderUnpackSizes); IAlloc_Free(alloc, p->CodersData); SzAr_Init(p); }
static void free__7z_file(_7z_file *_7z) { if (_7z != NULL) { if (_7z->archiveStream.file._7z_osdfile != NULL) osd_close(_7z->archiveStream.file._7z_osdfile); if (_7z->filename != NULL) free((void *)_7z->filename); if (_7z->outBuffer) IAlloc_Free(&_7z->allocImp, _7z->outBuffer); if (_7z->inited) SzArEx_Free(&_7z->db, &_7z->allocImp); free(_7z); } }
CBuf* SZFilePack::openFile(const char* fileName) { char szFileName[MAX_PATH+1] = ""; strncpy(szFileName, fileName, MAX_PATH); NormalFileName(szFileName); _strlwr(szFileName); FileIndexMap::iterator itFind = mIndexMap.find(szFileName); if (itFind == mIndexMap.end()) return NULL; //if you need cache, use these 3 variables. //if you use external function, you can make these variable as static. UInt32 blockIndex = 0xFFFFFFFF; // it can have any value before first call (if outBuffer = 0) Byte *outBuffer = 0; // it must be 0 before first call for each new archive. size_t outBufferSize = 0; // it can have any value before first call (if outBuffer = 0) size_t offset = 0; size_t outSizeProcessed = 0; SRes res; size_t index = itFind->second; res = SzArEx_Extract(&mDb, &mLookStream.s, index, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &mAllocImp, &mAllocTempImp); if (res != SZ_OK) return NULL; closeFile(); mFileBuffer = new CBuf; mFileBuffer->data = new byte[outSizeProcessed]; memcpy(mFileBuffer->data, outBuffer+offset, outSizeProcessed); mFileBuffer->size = outSizeProcessed; IAlloc_Free(&mAllocImp, outBuffer); return mFileBuffer; }
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->UnpackPositions); IAlloc_Free(alloc, p->IsDirs); IAlloc_Free(alloc, p->FolderToFile); IAlloc_Free(alloc, p->FileToFolder); IAlloc_Free(alloc, p->FileNameOffsets); IAlloc_Free(alloc, p->FileNames); SzBitUi32s_Free(&p->CRCs, alloc); SzBitUi32s_Free(&p->Attribs, alloc); // SzBitUi32s_Free(&p->Parents, alloc); SzBitUi64s_Free(&p->MTime, alloc); SzBitUi64s_Free(&p->CTime, alloc); SzAr_Free(&p->db, alloc); SzArEx_Init(p); }
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) { // IAlloc_Free(alloc, p->FolderStartPackStreamIndex); // IAlloc_Free(alloc, p->PackStreamStartPositions); IAlloc_Free(alloc, p->FolderStartFileIndex); IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); IAlloc_Free(alloc, p->FileNameOffsets); IAlloc_Free(alloc, p->FileNames); SzBitUi64s_Free(&p->CTime, alloc); SzBitUi64s_Free(&p->MTime, alloc); SzBitUi32s_Free(&p->CRCs, alloc); // SzBitUi32s_Free(&p->Parents, alloc); SzBitUi32s_Free(&p->Attribs, alloc); IAlloc_Free(alloc, p->IsDirs); // IAlloc_Free(alloc, p->IsEmptyFiles); IAlloc_Free(alloc, p->UnpackPositions); // IAlloc_Free(alloc, p->Files); SzAr_Free(&p->db, alloc); SzArEx_Init(p); }
static SRes SzReadHeader( CSzArEx *p, CSzData *sd, ISzAlloc *allocMain, ISzAlloc *allocTemp) { uint64_t *unpackSizes = 0; uint8_t *digestsDefined = 0; uint32_t *digests = 0; uint8_t *emptyStreamVector = 0; uint8_t *emptyFileVector = 0; uint8_t *lwtVector = 0; SRes res = SzReadHeader2(p, sd, &unpackSizes, &digestsDefined, &digests, &emptyStreamVector, &emptyFileVector, &lwtVector, allocMain, allocTemp); IAlloc_Free(allocTemp, unpackSizes); IAlloc_Free(allocTemp, digestsDefined); IAlloc_Free(allocTemp, digests); IAlloc_Free(allocTemp, emptyStreamVector); IAlloc_Free(allocTemp, emptyFileVector); IAlloc_Free(allocTemp, lwtVector); return res; }
int MY_CDECL main(int numargs, char *args[]) { CFileInStream archiveStream; CLookToRead lookStream; CSzArEx db; SRes res; ISzAlloc allocImp; ISzAlloc allocTempImp; UInt16 *temp = NULL; size_t tempSize = 0; // UInt32 parents[NUM_PARENTS_MAX]; printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n"); if (numargs == 1) { printf( "Usage: 7zDec <command> <archive_name>\n\n" "<Commands>\n" " e: Extract files from archive (without using directory names)\n" " l: List contents of archive\n" " t: Test integrity of archive\n" " x: eXtract files with full paths\n"); return 0; } if (numargs < 3) { PrintError("incorrect command"); return 1; } #if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE) g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; #endif allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; #ifdef UNDER_CE if (InFile_OpenW(&archiveStream.file, L"\test.7z")) #else if (InFile_Open(&archiveStream.file, args[2])) #endif { PrintError("can not open input file"); return 1; } FileInStream_CreateVTable(&archiveStream); LookToRead_CreateVTable(&lookStream, False); lookStream.realStream = &archiveStream.s; LookToRead_Init(&lookStream); CrcGenerateTable(); SzArEx_Init(&db); res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); if (res == SZ_OK) { char *command = args[1]; int listCommand = 0, testCommand = 0, fullPaths = 0; if (strcmp(command, "l") == 0) listCommand = 1; else if (strcmp(command, "t") == 0) testCommand = 1; else if (strcmp(command, "e") == 0) { } else if (strcmp(command, "x") == 0) { fullPaths = 1; } else { PrintError("incorrect command"); res = SZ_ERROR_FAIL; } if (res == SZ_OK) { UInt32 i; /* if you need cache, use these 3 variables. if you use external function, you can make these variable as static. */ UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ for (i = 0; i < db.NumFiles; i++) { size_t offset = 0; size_t outSizeProcessed = 0; // const CSzFileItem *f = db.Files + i; size_t len; unsigned isDir = SzArEx_IsDir(&db, i); if (listCommand == 0 && isDir && !fullPaths) continue; len = SzArEx_GetFileNameUtf16(&db, i, NULL); // len = SzArEx_GetFullNameLen(&db, i); if (len > tempSize) { SzFree(NULL, temp); tempSize = len; temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0])); if (!temp) { res = SZ_ERROR_MEM; break; } } SzArEx_GetFileNameUtf16(&db, i, temp); /* if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp) { res = SZ_ERROR_FAIL; break; } */ if (listCommand) { char attr[8], s[32], t[32]; UInt64 fileSize; GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr); fileSize = SzArEx_GetFileSize(&db, i); UInt64ToStr(fileSize, s); if (SzBitWithVals_Check(&db.MTime, i)) ConvertFileTimeToString(&db.MTime.Vals[i], t); else { size_t j; for (j = 0; j < 19; j++) t[j] = ' '; t[j] = '\0'; } printf("%s %s %10s ", t, attr, s); res = PrintString(temp); if (res != SZ_OK) break; if (isDir) printf("/"); printf("\n"); continue; } fputs(testCommand ? "Testing ": "Extracting ", stdout); res = PrintString(temp); if (res != SZ_OK) break; if (isDir) printf("/"); else { res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; } if (!testCommand) { CSzFile outFile; size_t processedSize; size_t j; UInt16 *name = (UInt16 *)temp; const UInt16 *destPath = (const UInt16 *)name; for (j = 0; name[j] != 0; j++) if (name[j] == '/') { if (fullPaths) { name[j] = 0; MyCreateDir(name); name[j] = CHAR_PATH_SEPARATOR; } else destPath = name + j + 1; } if (isDir) { MyCreateDir(destPath); printf("\n"); continue; } else if (OutFile_OpenUtf16(&outFile, destPath)) { PrintError("can not open output file"); res = SZ_ERROR_FAIL; break; } processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { PrintError("can not write output file"); res = SZ_ERROR_FAIL; break; } if (File_Close(&outFile)) { PrintError("can not close output file"); res = SZ_ERROR_FAIL; break; } #ifdef USE_WINDOWS_FILE if (SzBitWithVals_Check(&db.Attribs, i)) SetFileAttributesW(destPath, db.Attribs.Vals[i]); #endif } printf("\n"); } IAlloc_Free(&allocImp, outBuffer); } } SzArEx_Free(&db, &allocImp); SzFree(NULL, temp); File_Close(&archiveStream.file); if (res == SZ_OK) { printf("\nEverything is Ok\n"); return 0; } if (res == SZ_ERROR_UNSUPPORTED) PrintError("decoder doesn't support this archive"); else if (res == SZ_ERROR_MEM) PrintError("can not allocate memory"); else if (res == SZ_ERROR_CRC) PrintError("CRC error"); else printf("\nERROR #%d\n", res); return 1; }
static SRes SzReadHeader2( CSzArEx *p, /* allocMain */ CSzData *sd, uint64_t **unpackSizes, /* allocTemp */ uint8_t **digestsDefined, /* allocTemp */ uint32_t **digests, /* allocTemp */ uint8_t **emptyStreamVector, /* allocTemp */ uint8_t **emptyFileVector, /* allocTemp */ uint8_t **lwtVector, /* allocTemp */ ISzAlloc *allocMain, ISzAlloc *allocTemp) { uint64_t type; uint32_t numUnpackStreams = 0; uint32_t numFiles = 0; CSzFileItem *files = 0; uint32_t numEmptyStreams = 0; uint32_t i; RINOK(SzReadID(sd, &type)); if (type == k7zIdArchiveProperties) { RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadID(sd, &type)); } if (type == k7zIdMainStreamsInfo) { RINOK(SzReadStreamsInfo(sd, &p->dataPos, &p->db, &numUnpackStreams, unpackSizes, digestsDefined, digests, allocMain, allocTemp)); p->dataPos += p->startPosAfterHeader; RINOK(SzReadID(sd, &type)); } if (type == k7zIdEnd) return SZ_OK; if (type != k7zIdFilesInfo) return SZ_ERROR_ARCHIVE; RINOK(SzReadNumber32(sd, &numFiles)); p->db.NumFiles = numFiles; MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain); p->db.Files = files; for (i = 0; i < numFiles; i++) SzFile_Init(files + i); for (;;) { uint64_t size; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; RINOK(SzReadNumber(sd, &size)); if (size > sd->Size) return SZ_ERROR_ARCHIVE; if ((uint64_t)(int)type != type) { RINOK(SzSkeepDataSize(sd, size)); } else switch((int)type) { case k7zIdName: { size_t namesSize; RINOK(SzReadSwitch(sd)); namesSize = (size_t)size - 1; if ((namesSize & 1) != 0) return SZ_ERROR_ARCHIVE; if (!Buf_Create(&p->FileNames, namesSize, allocMain)) return SZ_ERROR_MEM; MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); memcpy(p->FileNames.data, sd->Data, namesSize); RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets)) RINOK(SzSkeepDataSize(sd, namesSize)); break; } case k7zIdEmptyStream: { RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp)); numEmptyStreams = 0; for (i = 0; i < numFiles; i++) if ((*emptyStreamVector)[i]) numEmptyStreams++; break; } case k7zIdEmptyFile: { RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); break; } case k7zIdWinAttributes: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); RINOK(SzReadSwitch(sd)); for (i = 0; i < numFiles; i++) { CSzFileItem *f = &files[i]; uint8_t defined = (*lwtVector)[i]; f->AttribDefined = defined; f->Attrib = 0; if (defined) { RINOK(SzReaduint32_t(sd, &f->Attrib)); } } IAlloc_Free(allocTemp, *lwtVector); *lwtVector = NULL; break; } case k7zIdMTime: { RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); RINOK(SzReadSwitch(sd)); for (i = 0; i < numFiles; i++) { CSzFileItem *f = &files[i]; uint8_t defined = (*lwtVector)[i]; f->MTimeDefined = defined; f->MTime.Low = f->MTime.High = 0; if (defined) { RINOK(SzReaduint32_t(sd, &f->MTime.Low)); RINOK(SzReaduint32_t(sd, &f->MTime.High)); } } IAlloc_Free(allocTemp, *lwtVector); *lwtVector = NULL; break; } default: { RINOK(SzSkeepDataSize(sd, size)); } } } { uint32_t emptyFileIndex = 0; uint32_t sizeIndex = 0; for (i = 0; i < numFiles; i++) { CSzFileItem *file = files + i; file->IsAnti = 0; if (*emptyStreamVector == 0) file->HasStream = 1; else file->HasStream = (uint8_t)((*emptyStreamVector)[i] ? 0 : 1); if (file->HasStream) { file->IsDir = 0; file->Size = (*unpackSizes)[sizeIndex]; file->Crc = (*digests)[sizeIndex]; file->CrcDefined = (uint8_t)(*digestsDefined)[sizeIndex]; sizeIndex++; } else { if (*emptyFileVector == 0) file->IsDir = 1; else file->IsDir = (uint8_t)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); emptyFileIndex++; file->Size = 0; file->Crc = 0; file->CrcDefined = 0; } } } return SzArEx_Fill(p, allocMain); }
static SRes SzReadSubStreamsInfo( CSzData *sd, uint32_t numFolders, CSzFolder *folders, uint32_t *numUnpackStreams, uint64_t **unpackSizes, uint8_t **digestsDefined, uint32_t **digests, ISzAlloc *allocTemp) { uint64_t type = 0; uint32_t i; uint32_t si = 0; uint32_t numDigests = 0; for (i = 0; i < numFolders; i++) folders[i].NumUnpackStreams = 1; *numUnpackStreams = numFolders; for (;;) { RINOK(SzReadID(sd, &type)); if (type == k7zIdNumUnpackStream) { *numUnpackStreams = 0; for (i = 0; i < numFolders; i++) { uint32_t numStreams; RINOK(SzReadNumber32(sd, &numStreams)); folders[i].NumUnpackStreams = numStreams; *numUnpackStreams += numStreams; } continue; } if (type == k7zIdCRC || type == k7zIdSize) break; if (type == k7zIdEnd) break; RINOK(SzSkeepData(sd)); } if (*numUnpackStreams == 0) { *unpackSizes = 0; *digestsDefined = 0; *digests = 0; } else { *unpackSizes = (uint64_t *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(uint64_t)); RINOM(*unpackSizes); *digestsDefined = (uint8_t *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(uint8_t)); RINOM(*digestsDefined); *digests = (uint32_t *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(uint32_t)); RINOM(*digests); } for (i = 0; i < numFolders; i++) { /* v3.13 incorrectly worked with empty folders v4.07: we check that folder is empty */ uint64_t sum = 0; uint32_t j; uint32_t numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams == 0) continue; if (type == k7zIdSize) for (j = 1; j < numSubstreams; j++) { uint64_t size; RINOK(SzReadNumber(sd, &size)); (*unpackSizes)[si++] = size; sum += size; } (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum; } if (type == k7zIdSize) { RINOK(SzReadID(sd, &type)); } for (i = 0; i < *numUnpackStreams; i++) { (*digestsDefined)[i] = 0; (*digests)[i] = 0; } for (i = 0; i < numFolders; i++) { uint32_t numSubstreams = folders[i].NumUnpackStreams; if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) numDigests += numSubstreams; } si = 0; for (;;) { if (type == k7zIdCRC) { int digestIndex = 0; uint8_t *digestsDefined2 = 0; uint32_t *digests2 = 0; SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp); if (res == SZ_OK) { for (i = 0; i < numFolders; i++) { CSzFolder *folder = folders + i; uint32_t numSubstreams = folder->NumUnpackStreams; if (numSubstreams == 1 && folder->UnpackCRCDefined) { (*digestsDefined)[si] = 1; (*digests)[si] = folder->UnpackCRC; si++; } else { uint32_t j; for (j = 0; j < numSubstreams; j++, digestIndex++) { (*digestsDefined)[si] = digestsDefined2[digestIndex]; (*digests)[si] = digests2[digestIndex]; si++; } } } } IAlloc_Free(allocTemp, digestsDefined2); IAlloc_Free(allocTemp, digests2); RINOK(res); } else if (type == k7zIdEnd) return SZ_OK; else { RINOK(SzSkeepData(sd)); } RINOK(SzReadID(sd, &type)); } }
static SRes SzReadUnpackInfo( CSzData *sd, uint32_t *numFolders, CSzFolder **folders, /* for alloc */ ISzAlloc *alloc, ISzAlloc *allocTemp) { uint32_t i; RINOK(SzWaitAttribute(sd, k7zIdFolder)); RINOK(SzReadNumber32(sd, numFolders)); { RINOK(SzReadSwitch(sd)); MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc); for (i = 0; i < *numFolders; i++) SzFolder_Init((*folders) + i); for (i = 0; i < *numFolders; i++) { RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc)); } } RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize)); for (i = 0; i < *numFolders; i++) { uint32_t j; CSzFolder *folder = (*folders) + i; uint32_t numOutStreams = SzFolder_GetNumOutStreams(folder); MY_ALLOC(uint64_t, folder->UnpackSizes, (size_t)numOutStreams, alloc); for (j = 0; j < numOutStreams; j++) { RINOK(SzReadNumber(sd, folder->UnpackSizes + j)); } } for (;;) { uint64_t type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) return SZ_OK; if (type == k7zIdCRC) { SRes res; uint8_t *crcsDefined = 0; uint32_t *crcs = 0; res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp); if (res == SZ_OK) { for (i = 0; i < *numFolders; i++) { CSzFolder *folder = (*folders) + i; folder->UnpackCRCDefined = crcsDefined[i]; folder->UnpackCRC = crcs[i]; } } IAlloc_Free(allocTemp, crcs); IAlloc_Free(allocTemp, crcsDefined); RINOK(res); continue; } RINOK(SzSkeepData(sd)); } }
int cli_7unz (cli_ctx *ctx, size_t offset) { CFileInStream archiveStream; CLookToRead lookStream; CSzArEx db; SRes res; UInt16 utf16buf[UTFBUFSZ], *utf16name = utf16buf; int namelen = UTFBUFSZ, found = CL_CLEAN; Int64 begin_of_archive = offset; UInt32 viruses_found = 0; /* Replacement for FileInStream_CreateVTable(&archiveStream); */ archiveStream.s.Read = FileInStream_fmap_Read; archiveStream.s.Seek = FileInStream_fmap_Seek; archiveStream.s.curpos = 0; archiveStream.file.fmap = *ctx->fmap; LookToRead_CreateVTable(&lookStream, False); if(archiveStream.s.Seek(&archiveStream.s, &begin_of_archive, SZ_SEEK_SET) != 0) return CL_CLEAN; lookStream.realStream = &archiveStream.s; LookToRead_Init(&lookStream); SzArEx_Init(&db); res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); if(res == SZ_OK) { UInt32 i, blockIndex = 0xFFFFFFFF; Byte *outBuffer = 0; size_t outBufferSize = 0; unsigned int encrypted = 0; for (i = 0; i < db.db.NumFiles; i++) { size_t offset = 0; size_t outSizeProcessed = 0; const CSzFileItem *f = db.db.Files + i; char *name; size_t j; int newnamelen, fd; if((found = cli_checklimits("7unz", ctx, 0, 0, 0))) break; if (f->IsDir) continue; if(cli_checklimits("7unz", ctx, f->Size, 0, 0)) continue; if (!db.FileNameOffsets) newnamelen = 0; /* no filename */ else { newnamelen = SzArEx_GetFileNameUtf16(&db, i, NULL); if (newnamelen > namelen) { if(namelen > UTFBUFSZ) free(utf16name); utf16name = cli_malloc(newnamelen*2); if(!utf16name) { found = CL_EMEM; break; } namelen = newnamelen; } SzArEx_GetFileNameUtf16(&db, i, utf16name); } name = (char *)utf16name; for(j=0; j<(size_t)newnamelen; j++) /* FIXME */ name[j] = utf16name[j]; name[j] = 0; cli_dbgmsg("cli_7unz: extracting %s\n", name); res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if(res == SZ_ERROR_ENCRYPTED) { encrypted = 1; if(DETECT_ENCRYPTED) { cli_dbgmsg("cli_7unz: Encrypted files found in archive.\n"); cli_append_virus(ctx, "Heuristics.Encrypted.7Zip"); viruses_found++; if(!SCAN_ALL) { found = CL_VIRUS; break; } } } if(cli_matchmeta(ctx, name, 0, f->Size, encrypted, i, f->CrcDefined ? f->Crc : 0, NULL)) { found = CL_VIRUS; viruses_found++; if (!SCAN_ALL) break; } if (res != SZ_OK) cli_dbgmsg("cli_unz: extraction failed with %d\n", res); else { if((found = cli_gentempfd(ctx->engine->tmpdir, &name, &fd))) break; cli_dbgmsg("cli_7unz: Saving to %s\n", name); if((size_t)cli_writen(fd, outBuffer + offset, outSizeProcessed) != outSizeProcessed) found = CL_EWRITE; else if ((found = cli_magic_scandesc(fd, ctx)) == CL_VIRUS) viruses_found++; close(fd); if(!ctx->engine->keeptmp && cli_unlink(name)) found = CL_EUNLINK; free(name); if(found != CL_CLEAN) if (!(SCAN_ALL && found == CL_VIRUS)) break; } } IAlloc_Free(&allocImp, outBuffer); } SzArEx_Free(&db, &allocImp); if(namelen > UTFBUFSZ) free(utf16name); if (res == SZ_OK) cli_dbgmsg("cli_7unz: completed successfully\n"); else if (res == SZ_ERROR_UNSUPPORTED) cli_dbgmsg("cli_7unz: unsupported\n"); else if (res == SZ_ERROR_MEM) cli_dbgmsg("cli_7unz: oom\n"); else if (res == SZ_ERROR_CRC) cli_dbgmsg("cli_7unz: crc mismatch\n"); else cli_dbgmsg("cli_7unz: error %d\n", res); if (SCAN_ALL && viruses_found) return CL_VIRUS; return found; }
SRes SzArEx_Extract( const CSzArEx *p, ILookInStream *inStream, uint32_t fileIndex, uint32_t *blockIndex, uint8_t **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { uint32_t folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; SRes res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (uint32_t)-1) { IAlloc_Free(allocMain, *outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CSzFolder *folder = p->db.Folders + folderIndex; uint64_t unpackSizeSpec = SzFolder_GetUnpackSize(folder); size_t unpackSize = (size_t)unpackSizeSpec; uint64_t startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); if (unpackSize != unpackSizeSpec) return SZ_ERROR_MEM; *blockIndex = folderIndex; IAlloc_Free(allocMain, *outBuffer); *outBuffer = 0; RINOK(LookInStream_SeekTo(inStream, startOffset)); if (res == SZ_OK) { *outBufferSize = unpackSize; if (unpackSize != 0) { *outBuffer = (uint8_t *)IAlloc_Alloc(allocMain, unpackSize); if (*outBuffer == 0) res = SZ_ERROR_MEM; } if (res == SZ_OK) { res = SzFolder_Decode(folder, p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], inStream, startOffset, *outBuffer, unpackSize, allocTemp); if (res == SZ_OK) { if (folder->UnpackCRCDefined) { if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) res = SZ_ERROR_CRC; } } } } } if (res == SZ_OK) { uint32_t i; CSzFileItem *fileItem = p->db.Files + fileIndex; *offset = 0; for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (uint32_t)p->db.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZ_ERROR_FAIL; if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc) res = SZ_ERROR_CRC; } return res; }
void SzBitUi64s_Free(CSzBitUi64s *p, ISzAlloc *alloc) { IAlloc_Free(alloc, p->Defs); p->Defs = NULL; IAlloc_Free(alloc, p->Vals); p->Vals = NULL; }
SRes SzAr_Extract( const CSzArEx *p, ISzInStream *inStream, UInt32 fileIndex, UInt32 *blockIndex, Byte **outBuffer, size_t *outBufferSize, size_t *offset, size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; SRes res = SZ_OK; *offset = 0; *outSizeProcessed = 0; if (folderIndex == (UInt32)-1) { IAlloc_Free(allocMain, *outBuffer); *blockIndex = folderIndex; *outBuffer = 0; *outBufferSize = 0; return SZ_OK; } if (*outBuffer == 0 || *blockIndex != folderIndex) { CSzFolder *folder = p->db.Folders + folderIndex; CFileSize unPackSizeSpec = SzFolder_GetUnPackSize(folder); size_t unPackSize = (size_t)unPackSizeSpec; CFileSize startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); if (unPackSize != unPackSizeSpec) return SZ_ERROR_MEM; *blockIndex = folderIndex; IAlloc_Free(allocMain, *outBuffer); *outBuffer = 0; RINOK(inStream->Seek(inStream, startOffset, SZ_SEEK_SET)); if (res == SZ_OK) { *outBufferSize = unPackSize; if (unPackSize != 0) { *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unPackSize); if (*outBuffer == 0) res = SZ_ERROR_MEM; } if (res == SZ_OK) { res = SzDecode(p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex], folder, inStream, startOffset, *outBuffer, unPackSize, allocTemp); if (res == SZ_OK) { if (folder->UnPackCRCDefined) { if (CrcCalc(*outBuffer, unPackSize) != folder->UnPackCRC) res = SZ_ERROR_CRC; } } } } } if (res == SZ_OK) { UInt32 i; CSzFileItem *fileItem = p->db.Files + fileIndex; *offset = 0; for(i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)p->db.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size; if (*offset + *outSizeProcessed > *outBufferSize) return SZ_ERROR_FAIL; { if (fileItem->IsFileCRCDefined) { if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) res = SZ_ERROR_CRC; } } } return res; }
/* Extract the relative path (needle) from a 7z archive * (path) and allocate a buf for it to write it in. * If optional_outfile is set, extract to that instead * and don't allocate buffer. */ static int content_7zip_file_read( const char *path, const char *needle, void **buf, const char *optional_outfile) { CFileInStream archiveStream; CLookToRead lookStream; CSzArEx db; ISzAlloc allocImp; ISzAlloc allocTempImp; uint8_t *output = 0; long outsize = -1; /*These are the allocation routines. * Currently using the non-standard 7zip choices. */ allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; if (InFile_Open(&archiveStream.file, path)) { RARCH_ERR("Could not open %s as 7z archive\n.", path); return -1; } FileInStream_CreateVTable(&archiveStream); LookToRead_CreateVTable(&lookStream, False); lookStream.realStream = &archiveStream.s; LookToRead_Init(&lookStream); CrcGenerateTable(); SzArEx_Init(&db); if (SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp) == SZ_OK) { uint32_t i; bool file_found = false; uint16_t *temp = NULL; size_t temp_size = 0; uint32_t block_index = 0xFFFFFFFF; SRes res = SZ_OK; for (i = 0; i < db.db.NumFiles; i++) { size_t len; char infile[PATH_MAX_LENGTH]; size_t offset = 0; size_t outSizeProcessed = 0; const CSzFileItem *f = db.db.Files + i; /* We skip over everything which is not a directory. * FIXME: Why continue then if f->IsDir is true?*/ if (f->IsDir) continue; len = SzArEx_GetFileNameUtf16(&db, i, NULL); if (len > temp_size) { free(temp); temp_size = len; temp = (uint16_t *)malloc(temp_size * sizeof(temp[0])); if (temp == 0) { res = SZ_ERROR_MEM; break; } } SzArEx_GetFileNameUtf16(&db, i, temp); res = utf16_to_char_string(temp, infile, sizeof(infile)) ? SZ_OK : SZ_ERROR_FAIL; if (string_is_equal(infile, needle)) { size_t output_size = 0; RARCH_LOG_OUTPUT("Opened archive %s. Now trying to extract %s\n", path, needle); /* C LZMA SDK does not support chunked extraction - see here: * sourceforge.net/p/sevenzip/discussion/45798/thread/6fb59aaf/ * */ file_found = true; res = SzArEx_Extract(&db, &lookStream.s, i, &block_index, &output, &output_size, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; /* This goes to the error section. */ outsize = outSizeProcessed; if (optional_outfile != NULL) { const void *ptr = (const void*)(output + offset); if (!retro_write_file(optional_outfile, ptr, outsize)) { RARCH_ERR("Could not open outfilepath %s.\n", optional_outfile); res = SZ_OK; file_found = true; outsize = -1; } } else { /*We could either use the 7Zip allocated buffer, * or create our own and use it. * We would however need to realloc anyways, because RetroArch * expects a \0 at the end, therefore we allocate new, * copy and free the old one. */ *buf = malloc(outsize + 1); ((char*)(*buf))[outsize] = '\0'; memcpy(*buf,output + offset,outsize); } break; } } free(temp); IAlloc_Free(&allocImp, output); if (!(file_found && res == SZ_OK)) { /* Error handling */ if (!file_found) RARCH_ERR("File %s not found in %s\n", needle, path); RARCH_ERR("Failed to open compressed file inside 7zip archive.\n"); outsize = -1; } } SzArEx_Free(&db, &allocImp); File_Close(&archiveStream.file); return outsize; }
void ExtractPayload(const void* payload, size_t payloadSize, const WCHAR* prefix) { CMemInStream memStream; MemInStream_Init(&memStream, payload, payloadSize); CrcGenerateTable(); ISzAlloc alloc = { SzAlloc, SzFree }; CSzArEx db; SzArEx_Init(&db); SRes res = SzArEx_Open(&db, &memStream.s, &alloc, &alloc); if (res != SZ_OK) { SzArEx_Free(&db, &alloc); return; } WCHAR buffer[MAX_PATH]; UInt32 blockIndex = 0xFFFFFFFF; Byte* outBuffer = 0; size_t outBufferSize = 0; for (UInt32 i = 0; i < db.db.NumFiles; i++) { size_t offset = 0; size_t outSizeProcessed = 0; const CSzFileItem* f = db.db.Files + i; SzArEx_GetFileNameUtf16(&db, i, (UInt16*)buffer); WCHAR* destPath = buffer; if (wcsncmp(destPath, prefix, 3) == 0 || wcsncmp(destPath, L"ALL", 3) == 0) { // Skip the prefix (X64/X32/ALL) and the path separater. destPath += 4; } else { // This file isn't for this arch. continue; } if (!f->IsDir) { res = SzArEx_Extract( &db, &memStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &alloc, &alloc); if (res != SZ_OK) { break; } } for (size_t j = 0; destPath[j] != L'\0'; ++j) { if (destPath[j] == L'/') { destPath[j] = L'\0'; CreateDirectory(destPath, NULL); destPath[j] = CHAR_PATH_SEPARATOR; } } if (f->IsDir) { CreateDirectory(destPath, NULL); continue; } CSzFile outFile; if (OutFile_OpenW(&outFile, destPath)) { res = SZ_ERROR_FAIL; break; } size_t processedSize = outSizeProcessed; if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) { res = SZ_ERROR_FAIL; break; } if (File_Close(&outFile)) { res = SZ_ERROR_FAIL; break; } if (f->AttribDefined) SetFileAttributesW(destPath, f->Attrib); } IAlloc_Free(&alloc, outBuffer); SzArEx_Free(&db, &alloc); if (res == SZ_OK) { // Success. } }