Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/Cab/CabHandler.cpp')
-rw-r--r--CPP/7zip/Archive/Cab/CabHandler.cpp99
1 files changed, 65 insertions, 34 deletions
diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp
index 22bc93a0..4235ec34 100644
--- a/CPP/7zip/Archive/Cab/CabHandler.cpp
+++ b/CPP/7zip/Archive/Cab/CabHandler.cpp
@@ -71,7 +71,7 @@ static const Byte kArcProps[] =
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
-static const char *kMethods[] =
+static const char * const kMethods[] =
{
"None"
, "MSZip"
@@ -124,17 +124,19 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
}
}
+
AString s;
+
for (unsigned i = 0; i < kNumMethodsMax; i++)
{
if ((mask & (1 << i)) == 0)
continue;
- if (!s.IsEmpty())
- s += ' ';
+ s.Add_Space_if_NotEmpty();
char temp[kMethodNameBufSize];
SetMethodName(temp, i, params[i == NHeader::NMethod::kQuantum ? 0 : 1]);
s += temp;
}
+
prop = s;
break;
}
@@ -466,8 +468,8 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
return result;
if (!_errorMessage.IsEmpty())
- _errorMessage += L"\n";
- _errorMessage += L"Can't open volume: ";
+ _errorMessage.Add_LF();
+ _errorMessage.AddAscii("Can't open volume: ");
_errorMessage += fullName;
if (prevChecked)
@@ -528,7 +530,7 @@ private:
Byte *TempBuf;
UInt32 TempBufSize;
- int NumIdenticalFiles;
+ unsigned NumIdenticalFiles;
bool TempBufMode;
UInt32 m_BufStartFolderOffset;
@@ -619,8 +621,9 @@ HRESULT CFolderOutStream::OpenFile()
{
const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
- int numExtractItems = 0;
+ unsigned numExtractItems = 0;
unsigned curIndex;
+
for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++)
{
const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex];
@@ -632,10 +635,12 @@ HRESULT CFolderOutStream::OpenFile()
if (!m_TestMode && (*m_ExtractStatuses)[curIndex])
numExtractItems++;
}
+
NumIdenticalFiles = (curIndex - m_CurrentIndex);
if (NumIdenticalFiles == 0)
NumIdenticalFiles = 1;
TempBufMode = false;
+
if (numExtractItems > 1)
{
if (!TempBuf || item.Size > TempBufSize)
@@ -699,7 +704,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
{
COM_TRY_BEGIN
UInt32 realProcessed = 0;
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = 0;
while (size != 0)
{
@@ -707,7 +712,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
{
UInt32 numBytesToWrite = MyMin(m_RemainFileSize, size);
HRESULT res = S_OK;
- if (numBytesToWrite > 0)
+ if (numBytesToWrite != 0)
{
if (!isOK)
m_IsOk = false;
@@ -721,7 +726,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
memcpy(TempBuf + (m_PosInFolder - m_BufStartFolderOffset), data, numBytesToWrite);
}
realProcessed += numBytesToWrite;
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = realProcessed;
data = (const void *)((const Byte *)data + numBytesToWrite);
size -= numBytesToWrite;
@@ -773,7 +778,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe
{
UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size);
realProcessed += numBytesToWrite;
- if (processedSize != NULL)
+ if (processedSize)
*processedSize = realProcessed;
data = (const void *)((const Byte *)data + numBytesToWrite);
size -= numBytesToWrite;
@@ -799,24 +804,24 @@ STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *proc
HRESULT CFolderOutStream::FlushCorrupted()
{
- const UInt32 kBufferSize = (1 << 10);
- Byte buffer[kBufferSize];
- for (int i = 0; i < kBufferSize; i++)
- buffer[i] = 0;
+ const unsigned kBufSize = (1 << 10);
+ Byte buf[kBufSize];
+ for (unsigned i = 0; i < kBufSize; i++)
+ buf[i] = 0;
for (;;)
{
UInt64 remain = GetRemain();
if (remain == 0)
return S_OK;
- UInt32 size = (UInt32)MyMin(remain, (UInt64)kBufferSize);
+ UInt32 size = (remain < kBufSize ? (UInt32)remain : (UInt32)kBufSize);
UInt32 processedSizeLocal = 0;
- RINOK(Write2(buffer, size, &processedSizeLocal, false));
+ RINOK(Write2(buf, size, &processedSizeLocal, false));
}
}
HRESULT CFolderOutStream::Unsupported()
{
- while(m_CurrentIndex < m_ExtractStatuses->Size())
+ while (m_CurrentIndex < m_ExtractStatuses->Size())
{
HRESULT result = OpenFile();
if (result != S_FALSE && result != S_OK)
@@ -844,9 +849,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt32 i;
int lastFolder = -2;
UInt64 lastFolderSize = 0;
- for(i = 0; i < numItems; i++)
+
+ for (i = 0; i < numItems; i++)
{
- int index = allFilesMode ? i : indices[i];
+ unsigned index = allFilesMode ? i : indices[i];
const CMvItem &mvItem = m_Database.Items[index];
const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
if (item.IsDir())
@@ -857,6 +863,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
lastFolder = folderIndex;
lastFolderSize = item.GetEndOffset();
}
+
totalUnPacked += lastFolderSize;
extractCallback->SetTotal(totalUnPacked);
@@ -887,9 +894,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
return E_OUTOFMEMORY;
CRecordVector<bool> extractStatuses;
- for(i = 0; i < numItems;)
+
+ for (i = 0; i < numItems;)
{
- int index = allFilesMode ? i : indices[i];
+ unsigned index = allFilesMode ? i : indices[i];
const CMvItem &mvItem = m_Database.Items[index];
const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];
@@ -909,7 +917,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
continue;
}
+
int folderIndex = m_Database.GetFolderIndex(&mvItem);
+
if (folderIndex < 0)
{
// If we need previous archive
@@ -923,17 +933,19 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError));
continue;
}
- int startIndex2 = m_Database.FolderStartFileIndex[folderIndex];
- int startIndex = startIndex2;
+
+ unsigned startIndex2 = m_Database.FolderStartFileIndex[folderIndex];
+ unsigned startIndex = startIndex2;
extractStatuses.Clear();
for (; startIndex < index; startIndex++)
extractStatuses.Add(false);
extractStatuses.Add(true);
startIndex++;
UInt64 curUnpack = item.GetEndOffset();
+
for (; i < numItems; i++)
{
- int indexNext = allFilesMode ? i : indices[i];
+ unsigned indexNext = allFilesMode ? i : indices[i];
const CMvItem &mvItem = m_Database.Items[indexNext];
const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
if (item.IsDir())
@@ -963,6 +975,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
cabBlockInStreamSpec->MsZip = false;
HRESULT res = S_OK;
+
switch (folder.GetMethod())
{
case NHeader::NMethod::kNone:
@@ -1009,7 +1022,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
int locFolderIndex = item.GetFolderIndex(db.Folders.Size());
bool keepHistory = false;
bool keepInputBuffer = false;
- for (UInt32 f = 0; cabFolderOutStream->GetRemain() != 0;)
+
+ for (UInt32 bl = 0; cabFolderOutStream->GetRemain() != 0;)
{
if (volIndex >= m_Database.Volumes.Size())
{
@@ -1019,19 +1033,32 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
const CDatabaseEx &db = m_Database.Volumes[volIndex];
const CFolder &folder = db.Folders[locFolderIndex];
- if (f == 0)
+
+ if (bl == 0)
{
cabBlockInStreamSpec->ReservedSize = db.ArcInfo.GetDataBlockReserveSize();
RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL));
}
- if (f == folder.NumDataBlocks)
+
+ if (bl == folder.NumDataBlocks)
{
- volIndex++;
- locFolderIndex = 0;
- f = 0;
- continue;
+ /*
+ CFolder::NumDataBlocks (CFFOLDER::cCFData in CAB specification) is 16-bit.
+ But there are some big CAB archives from MS that contain more
+ than (0xFFFF) CFDATA blocks in folder.
+ Old cab extracting software can show error (or ask next volume)
+ but cab extracting library in new Windows ignores this error.
+ 15.00 : We also try to ignore such error, if archive is not multi-volume.
+ */
+ if (m_Database.Volumes.Size() > 1)
+ {
+ volIndex++;
+ locFolderIndex = 0;
+ bl = 0;
+ continue;
+ }
}
- f++;
+ bl++;
if (!keepInputBuffer)
cabBlockInStreamSpec->InitForNewBlock();
@@ -1059,7 +1086,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
unpackRemain = kBlockSizeMax;
if (unpackRemain > unpackSize)
unpackRemain = unpackSize;
-
+
switch (folder.GetMethod())
{
case NHeader::NMethod::kNone:
@@ -1092,14 +1119,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
res = quantumDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
break;
}
+
if (res != S_OK)
{
if (res != S_FALSE)
RINOK(res);
break;
}
+
keepHistory = true;
}
+
if (res == S_OK)
{
RINOK(cabFolderOutStream->WriteEmptyFiles());
@@ -1111,6 +1141,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
totalUnPacked += curUnpack;
}
+
return S_OK;
COM_TRY_END
}