📄 7zin.c
字号:
/* 7zIn.c */#include "7zIn.h"#include "7zCrc.h"#include "7zDecode.h"#define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; }void SzArDbExInit(CArchiveDatabaseEx *db){ SzArchiveDatabaseInit(&db->Database); db->FolderStartPackStreamIndex = 0; db->PackStreamStartPositions = 0; db->FolderStartFileIndex = 0; db->FileIndexToFolderIndexMap = 0;}void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)){ freeFunc(db->FolderStartPackStreamIndex); freeFunc(db->PackStreamStartPositions); freeFunc(db->FolderStartFileIndex); freeFunc(db->FileIndexToFolderIndexMap); SzArchiveDatabaseFree(&db->Database, freeFunc); SzArDbExInit(db);}/*CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const { return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];}CFileSize GetFilePackSize(int fileIndex) const{ int folderIndex = FileIndexToFolderIndexMap[fileIndex]; if (folderIndex >= 0) { const CFolder &folderInfo = Folders[folderIndex]; if (FolderStartFileIndex[folderIndex] == fileIndex) return GetFolderFullPackSize(folderIndex); } return 0;}*/#define MY_ALLOC(T, p, size, allocFunc) { if ((size) == 0) p = 0; else \ if ((p = (T *)allocFunc((size) * sizeof(T))) == 0) return SZE_OUTOFMEMORY; }SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size)){ UInt32 startPos = 0; CFileSize startPosSize = 0; UInt32 i; UInt32 folderIndex = 0; UInt32 indexInFolder = 0; MY_ALLOC(UInt32, db->FolderStartPackStreamIndex, db->Database.NumFolders, allocFunc); for(i = 0; i < db->Database.NumFolders; i++) { db->FolderStartPackStreamIndex[i] = startPos; startPos += db->Database.Folders[i].NumPackStreams; } MY_ALLOC(CFileSize, db->PackStreamStartPositions, db->Database.NumPackStreams, allocFunc); for(i = 0; i < db->Database.NumPackStreams; i++) { db->PackStreamStartPositions[i] = startPosSize; startPosSize += db->Database.PackSizes[i]; } MY_ALLOC(UInt32, db->FolderStartFileIndex, db->Database.NumFolders, allocFunc); MY_ALLOC(UInt32, db->FileIndexToFolderIndexMap, db->Database.NumFiles, allocFunc); for (i = 0; i < db->Database.NumFiles; i++) { CFileItem *file = db->Database.Files + i; int emptyStream = !file->HasStream; if (emptyStream && indexInFolder == 0) { db->FileIndexToFolderIndexMap[i] = (UInt32)-1; continue; } if (indexInFolder == 0) { /* v3.13 incorrectly worked with empty folders v4.07: Loop for skipping empty folders */ while(1) { if (folderIndex >= db->Database.NumFolders) return SZE_ARCHIVE_ERROR; db->FolderStartFileIndex[folderIndex] = i; if (db->Database.Folders[folderIndex].NumUnPackStreams != 0) break; folderIndex++; } } db->FileIndexToFolderIndexMap[i] = folderIndex; if (emptyStream) continue; indexInFolder++; if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams) { folderIndex++; indexInFolder = 0; } } return SZ_OK;}CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder){ return db->ArchiveInfo.DataStartPosition + db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder];}CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex){ UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex]; CFolder *folder = db->Database.Folders + folderIndex; CFileSize size = 0; UInt32 i; for (i = 0; i < folder->NumPackStreams; i++) size += db->Database.PackSizes[packStreamIndex + i]; return size;}/*SZ_RESULT SzReadTime(const CObjectVector<CSzByteBuffer> &dataVector, CObjectVector<CFileItem> &files, UInt64 type){ CBoolVector boolVector; RINOK(ReadBoolVector2(files.Size(), boolVector)) CStreamSwitch streamSwitch; RINOK(streamSwitch.Set(this, &dataVector)); for(int i = 0; i < files.Size(); i++) { CFileItem &file = files[i]; CArchiveFileTime fileTime; bool defined = boolVector[i]; if (defined) { UInt32 low, high; RINOK(SzReadUInt32(low)); RINOK(SzReadUInt32(high)); fileTime.dwLowDateTime = low; fileTime.dwHighDateTime = high; } switch(type) { case k7zIdCreationTime: file.IsCreationTimeDefined = defined; if (defined) file.CreationTime = fileTime; break; case k7zIdLastWriteTime: file.IsLastWriteTimeDefined = defined; if (defined) file.LastWriteTime = fileTime; break; case k7zIdLastAccessTime: file.IsLastAccessTimeDefined = defined; if (defined) file.LastAccessTime = fileTime; break; } } return SZ_OK;}*/SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size){ #ifdef _LZMA_IN_CB while (size > 0) { Byte *inBuffer; size_t processedSize; RINOK(inStream->Read(inStream, (void **)&inBuffer, size, &processedSize)); if (processedSize == 0 || processedSize > size) return SZE_FAIL; size -= processedSize; do { *data++ = *inBuffer++; } while (--processedSize != 0); } #else size_t processedSize; RINOK(inStream->Read(inStream, data, size, &processedSize)); if (processedSize != size) return SZE_FAIL; #endif return SZ_OK;}SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data){ return SafeReadDirect(inStream, data, 1);}SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value){ int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt32)b << (8 * i)); } return SZ_OK;}SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value){ int i; *value = 0; for (i = 0; i < 8; i++) { Byte b; RINOK(SafeReadDirectByte(inStream, &b)); *value |= ((UInt32)b << (8 * i)); } return SZ_OK;}int TestSignatureCandidate(Byte *testBytes){ size_t i; for (i = 0; i < k7zSignatureSize; i++) if (testBytes[i] != k7zSignature[i]) return 0; return 1;}typedef struct _CSzState{ Byte *Data; size_t Size;}CSzData;SZ_RESULT SzReadByte(CSzData *sd, Byte *b){ if (sd->Size == 0) return SZE_ARCHIVE_ERROR; sd->Size--; *b = *sd->Data++; return SZ_OK;}SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size){ size_t i; for (i = 0; i < size; i++) { RINOK(SzReadByte(sd, data + i)); } return SZ_OK;}SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value){ int i; *value = 0; for (i = 0; i < 4; i++) { Byte b; RINOK(SzReadByte(sd, &b)); *value |= ((UInt32)(b) << (8 * i)); } return SZ_OK;}SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value){ Byte firstByte; Byte mask = 0x80; int i; RINOK(SzReadByte(sd, &firstByte)); *value = 0; for (i = 0; i < 8; i++) { Byte b; if ((firstByte & mask) == 0) { UInt64 highPart = firstByte & (mask - 1); *value += (highPart << (8 * i)); return SZ_OK; } RINOK(SzReadByte(sd, &b)); *value |= ((UInt64)b << (8 * i)); mask >>= 1; } return SZ_OK;}SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value){ UInt64 value64; RINOK(SzReadNumber(sd, &value64)); *value = (CFileSize)value64; return SZ_OK;}SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value){ UInt64 value64; RINOK(SzReadNumber(sd, &value64)); if (value64 >= 0x80000000) return SZE_NOTIMPL; if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) return SZE_NOTIMPL; *value = (UInt32)value64; return SZ_OK;}SZ_RESULT SzReadID(CSzData *sd, UInt64 *value) { return SzReadNumber(sd, value); }SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size){ if (size > sd->Size) return SZE_ARCHIVE_ERROR; sd->Size -= (size_t)size; sd->Data += (size_t)size; return SZ_OK;}SZ_RESULT SzSkeepData(CSzData *sd){ UInt64 size; RINOK(SzReadNumber(sd, &size)); return SzSkeepDataSize(sd, size);}SZ_RESULT SzReadArchiveProperties(CSzData *sd){ while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == k7zIdEnd) break; SzSkeepData(sd); } return SZ_OK;}SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute){ while(1) { UInt64 type; RINOK(SzReadID(sd, &type)); if (type == attribute) return SZ_OK; if (type == k7zIdEnd) return SZE_ARCHIVE_ERROR; RINOK(SzSkeepData(sd)); }}SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)){ Byte b = 0; Byte mask = 0; size_t i; MY_ALLOC(Byte, *v, numItems, allocFunc); for(i = 0; i < numItems; i++) { if (mask == 0) { RINOK(SzReadByte(sd, &b)); mask = 0x80; } (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); mask >>= 1; } return SZ_OK;}SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)){ Byte allAreDefined; size_t i; RINOK(SzReadByte(sd, &allAreDefined)); if (allAreDefined == 0) return SzReadBoolVector(sd, numItems, v, allocFunc); MY_ALLOC(Byte, *v, numItems, allocFunc); for(i = 0; i < numItems; i++) (*v)[i] = 1; return SZ_OK;}SZ_RESULT SzReadHashDigests( CSzData *sd, size_t numItems, Byte **digestsDefined, UInt32 **digests, void * (*allocFunc)(size_t size)){ size_t i; RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc)); MY_ALLOC(UInt32, *digests, numItems, allocFunc); for(i = 0; i < numItems; i++) if ((*digestsDefined)[i]) { RINOK(SzReadUInt32(sd, (*digests) + i)); } return SZ_OK;}SZ_RESULT SzReadPackInfo( CSzData *sd, CFileSize *dataOffset, UInt32 *numPackStreams, CFileSize **packSizes, Byte **packCRCsDefined,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -