📄 7zin.c
字号:
return SZ_OK;
}
static SRes SzReadSwitch(CSzData *sd)
{
Byte external;
RINOK(SzReadByte(sd, &external));
return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;
}
static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc)
{
UInt32 numCoders, numBindPairs, numPackStreams, i;
UInt32 numInStreams = 0, numOutStreams = 0;
RINOK(SzReadNumber32(sd, &numCoders));
if (numCoders > NUM_FOLDER_CODERS_MAX)
return SZ_ERROR_UNSUPPORTED;
folder->NumCoders = numCoders;
MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc);
for (i = 0; i < numCoders; i++)
SzCoderInfo_Init(folder->Coders + i);
for (i = 0; i < numCoders; i++)
{
Byte mainByte;
CSzCoderInfo *coder = folder->Coders + i;
{
unsigned idSize, j;
Byte longID[15];
RINOK(SzReadByte(sd, &mainByte));
idSize = (unsigned)(mainByte & 0xF);
RINOK(SzReadBytes(sd, longID, idSize));
if (idSize > sizeof(coder->MethodID))
return SZ_ERROR_UNSUPPORTED;
coder->MethodID = 0;
for (j = 0; j < idSize; j++)
coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j);
if ((mainByte & 0x10) != 0)
{
RINOK(SzReadNumber32(sd, &coder->NumInStreams));
RINOK(SzReadNumber32(sd, &coder->NumOutStreams));
if (coder->NumInStreams > NUM_CODER_STREAMS_MAX ||
coder->NumOutStreams > NUM_CODER_STREAMS_MAX)
return SZ_ERROR_UNSUPPORTED;
}
else
{
coder->NumInStreams = 1;
coder->NumOutStreams = 1;
}
if ((mainByte & 0x20) != 0)
{
UInt64 propertiesSize = 0;
RINOK(SzReadNumber(sd, &propertiesSize));
if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc))
return SZ_ERROR_MEM;
RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize));
}
}
while ((mainByte & 0x80) != 0)
{
RINOK(SzReadByte(sd, &mainByte));
RINOK(SzSkeepDataSize(sd, (mainByte & 0xF)));
if ((mainByte & 0x10) != 0)
{
UInt32 n;
RINOK(SzReadNumber32(sd, &n));
RINOK(SzReadNumber32(sd, &n));
}
if ((mainByte & 0x20) != 0)
{
UInt64 propertiesSize = 0;
RINOK(SzReadNumber(sd, &propertiesSize));
RINOK(SzSkeepDataSize(sd, propertiesSize));
}
}
numInStreams += coder->NumInStreams;
numOutStreams += coder->NumOutStreams;
}
if (numOutStreams == 0)
return SZ_ERROR_UNSUPPORTED;
folder->NumBindPairs = numBindPairs = numOutStreams - 1;
MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, alloc);
for (i = 0; i < numBindPairs; i++)
{
CBindPair *bp = folder->BindPairs + i;
RINOK(SzReadNumber32(sd, &bp->InIndex));
RINOK(SzReadNumber32(sd, &bp->OutIndex));
}
if (numInStreams < numBindPairs)
return SZ_ERROR_UNSUPPORTED;
folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs;
MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc);
if (numPackStreams == 1)
{
for (i = 0; i < numInStreams ; i++)
if (SzFolder_FindBindPairForInStream(folder, i) < 0)
break;
if (i == numInStreams)
return SZ_ERROR_UNSUPPORTED;
folder->PackStreams[0] = i;
}
else
for (i = 0; i < numPackStreams; i++)
{
RINOK(SzReadNumber32(sd, folder->PackStreams + i));
}
return SZ_OK;
}
static SRes SzReadUnpackInfo(
CSzData *sd,
UInt32 *numFolders,
CSzFolder **folders, /* for alloc */
ISzAlloc *alloc,
ISzAlloc *allocTemp)
{
UInt32 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 j;
CSzFolder *folder = (*folders) + i;
UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder);
MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc);
for (j = 0; j < numOutStreams; j++)
{
RINOK(SzReadNumber(sd, folder->UnpackSizes + j));
}
}
for (;;)
{
UInt64 type;
RINOK(SzReadID(sd, &type));
if (type == k7zIdEnd)
return SZ_OK;
if (type == k7zIdCRC)
{
SRes res;
Byte *crcsDefined = 0;
UInt32 *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));
}
}
static SRes SzReadSubStreamsInfo(
CSzData *sd,
UInt32 numFolders,
CSzFolder *folders,
UInt32 *numUnpackStreams,
UInt64 **unpackSizes,
Byte **digestsDefined,
UInt32 **digests,
ISzAlloc *allocTemp)
{
UInt64 type = 0;
UInt32 i;
UInt32 si = 0;
UInt32 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 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 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64));
RINOM(*unpackSizes);
*digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte));
RINOM(*digestsDefined);
*digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32));
RINOM(*digests);
}
for (i = 0; i < numFolders; i++)
{
/*
v3.13 incorrectly worked with empty folders
v4.07: we check that folder is empty
*/
UInt64 sum = 0;
UInt32 j;
UInt32 numSubstreams = folders[i].NumUnpackStreams;
if (numSubstreams == 0)
continue;
if (type == k7zIdSize)
for (j = 1; j < numSubstreams; j++)
{
UInt64 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 numSubstreams = folders[i].NumUnpackStreams;
if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)
numDigests += numSubstreams;
}
si = 0;
for (;;)
{
if (type == k7zIdCRC)
{
int digestIndex = 0;
Byte *digestsDefined2 = 0;
UInt32 *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 numSubstreams = folder->NumUnpackStreams;
if (numSubstreams == 1 && folder->UnpackCRCDefined)
{
(*digestsDefined)[si] = 1;
(*digests)[si] = folder->UnpackCRC;
si++;
}
else
{
UInt32 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 SzReadStreamsInfo(
CSzData *sd,
UInt64 *dataOffset,
CSzAr *p,
UInt32 *numUnpackStreams,
UInt64 **unpackSizes, /* allocTemp */
Byte **digestsDefined, /* allocTemp */
UInt32 **digests, /* allocTemp */
ISzAlloc *alloc,
ISzAlloc *allocTemp)
{
for (;;)
{
UInt64 type;
RINOK(SzReadID(sd, &type));
if ((UInt64)(int)type != type)
return SZ_ERROR_UNSUPPORTED;
switch((int)type)
{
case k7zIdEnd:
return SZ_OK;
case k7zIdPackInfo:
{
RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams,
&p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc));
break;
}
case k7zIdUnpackInfo:
{
RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp));
break;
}
case k7zIdSubStreamsInfo:
{
RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders,
numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp));
break;
}
default:
return SZ_ERROR_UNSUPPORTED;
}
}
}
Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static SRes SzReadFileNames(CSzData *sd, UInt32 numFiles, CSzFileItem *files, ISzAlloc *alloc)
{
UInt32 i;
for (i = 0; i < numFiles; i++)
{
UInt32 len = 0;
UInt32 pos = 0;
CSzFileItem *file = files + i;
while (pos + 2 <= sd->Size)
{
int numAdds;
UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
pos += 2;
len++;
if (value == 0)
break;
if (value < 0x80)
continue;
if (value >= 0xD800 && value < 0xE000)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -