HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { RINOK(ReadStream_FALSE(stream, _header, kHeaderSize)); if (TestSignatureCandidate(_header)) return S_OK; CByteBuffer byteBuffer; const UInt32 kBufferSize = (1 << 16); byteBuffer.SetCapacity(kBufferSize); Byte *buffer = byteBuffer; UInt32 numPrevBytes = kHeaderSize - 1; memcpy(buffer, _header + 1, numPrevBytes); UInt64 curTestPos = _arhiveBeginStreamPosition + 1; for (;;) { if (searchHeaderSizeLimit != NULL) if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit) break; do { UInt32 numReadBytes = kBufferSize - numPrevBytes; UInt32 processedSize; RINOK(stream->Read(buffer + numPrevBytes, numReadBytes, &processedSize)); numPrevBytes += processedSize; if (processedSize == 0) return S_FALSE; } while (numPrevBytes < kHeaderSize); UInt32 numTests = numPrevBytes - kHeaderSize + 1; for (UInt32 pos = 0; pos < numTests; pos++) { for (; buffer[pos] != '7' && pos < numTests; pos++); if (pos == numTests) break; if (TestSignatureCandidate(buffer + pos)) { memcpy(_header, buffer + pos, kHeaderSize); curTestPos += pos; _arhiveBeginStreamPosition = curTestPos; return stream->Seek(curTestPos + kHeaderSize, STREAM_SEEK_SET, NULL); } } curTestPos += numTests; numPrevBytes -= numTests; memmove(buffer, buffer + numTests, numPrevBytes); } return S_FALSE; }
static int LZMA_isArchive(const char *filename, int forWriting) { PHYSFS_uint8 sig[k7zSignatureSize]; PHYSFS_uint8 res; void *in; BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0); in = __PHYSFS_platformOpenRead(filename); BAIL_IF_MACRO(in == NULL, NULL, 0); if (__PHYSFS_platformRead(in, sig, k7zSignatureSize, 1) != 1) BAIL_MACRO(NULL, 0); /* Test whether sig is the 7z signature */ res = TestSignatureCandidate(sig); __PHYSFS_platformClose(in); return res; } /* LZMA_isArchive */
static SRes SzArEx_Open2( CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { uint8_t header[k7zStartHeaderSize]; int64_t startArcPos; uint64_t nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; uint32_t nextHeaderCRC; CBuf buffer; SRes res; startArcPos = 0; RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR)); RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); if (!TestSignatureCandidate(header)) return SZ_ERROR_NO_ARCHIVE; if (header[6] != k7zMajorVersion) return SZ_ERROR_UNSUPPORTED; nextHeaderOffset = GetUi64(header + 12); nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; if (nextHeaderSizeT == 0) return SZ_OK; if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) return SZ_ERROR_NO_ARCHIVE; { int64_t pos = 0; RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); if ((uint64_t)pos < startArcPos + nextHeaderOffset || (uint64_t)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || (uint64_t)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT); if (res == SZ_OK) { res = SZ_ERROR_ARCHIVE; if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) { CSzData sd; uint64_t type; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); if (res == SZ_OK) { if (type == k7zIdEncodedHeader) { CBuf outBuffer; Buf_Init(&outBuffer); res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp); if (res != SZ_OK) Buf_Free(&outBuffer, allocTemp); else { Buf_Free(&buffer, allocTemp); buffer.data = outBuffer.data; buffer.size = outBuffer.size; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); } } } if (res == SZ_OK) { if (type == k7zIdHeader) res = SzReadHeader(p, &sd, allocMain, allocTemp); else res = SZ_ERROR_UNSUPPORTED; } } } Buf_Free(&buffer, allocTemp); return res; }
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 SRes SzArEx_Open2( CSzArEx *p, ISeekInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { Byte header[k7zStartHeaderSize]; Int64 startArcPos; UInt64 nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; UInt32 nextHeaderCRC; CBuf buffer; SRes res; size_t readSize; startArcPos = 0; RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR)); readSize = k7zStartHeaderSize; res = inStream->Read(inStream, header, &readSize); if(res != SZ_OK) return SZ_ERROR_NO_ARCHIVE; if (!TestSignatureCandidate(header)) return SZ_ERROR_NO_ARCHIVE; if (header[6] != k7zMajorVersion) return SZ_ERROR_UNSUPPORTED; nextHeaderOffset = GetUi64(header + 12); nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; if (nextHeaderSizeT == 0) return SZ_OK; if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) return SZ_ERROR_NO_ARCHIVE; { Int64 pos = 0; RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); if ((UInt64)pos < startArcPos + nextHeaderOffset || (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; pos = startArcPos + k7zStartHeaderSize + nextHeaderOffset; RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_SET)); } if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; readSize = nextHeaderSizeT; res = inStream->Read(inStream, buffer.data, &readSize); if (res == SZ_OK) { res = SZ_ERROR_ARCHIVE; if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) { CSzData sd; UInt64 type; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); if (res == SZ_OK) { if (type == k7zIdEncodedHeader) { CMemOutStream outStream; MemOutStream_Init(&outStream); res = SzReadAndDecodePackedStreams(inStream, &sd, &outStream.s, p->startPosAfterHeader, allocTemp); if (res != SZ_OK) Buf_Free((CBuf*)&outStream.data, allocTemp); else { Buf_Free(&buffer, allocTemp); buffer.data = outStream.data; buffer.size = outStream.size; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); } } } if (res == SZ_OK) { if (type == k7zIdHeader) res = SzReadHeader(p, &sd, allocMain, allocTemp); else res = SZ_ERROR_UNSUPPORTED; } } } Buf_Free(&buffer, allocTemp); return res; }