This commit is contained in:
Igor Pavlov
2023-12-22 17:17:05 +00:00
committed by Kornel
parent ec44a8a070
commit a36c48cece
954 changed files with 42199 additions and 25482 deletions

View File

@@ -134,15 +134,15 @@ bool CHeader::Parse(const Byte *p)
}
{
{
UInt32 val32 = Get16(p + 11);
int s = GetLog(val32);
const UInt32 val32 = Get16(p + 11);
const int s = GetLog(val32);
if (s < 9 || s > 12)
return false;
SectorSizeLog = (Byte)s;
}
{
UInt32 val32 = p[13];
int s = GetLog(val32);
const UInt32 val32 = p[13];
const int s = GetLog(val32);
if (s < 0)
return false;
SectorsPerClusterLog = (Byte)s;
@@ -161,10 +161,10 @@ bool CHeader::Parse(const Byte *p)
return false;
// we also support images that contain 0 in offset field.
bool isOkOffset = (codeOffset == 0)
const bool isOkOffset = (codeOffset == 0)
|| (codeOffset == (p[0] == 0xEB ? 2 : 3));
UInt16 numRootDirEntries = Get16(p + 17);
const UInt16 numRootDirEntries = Get16(p + 17);
if (numRootDirEntries == 0)
{
if (codeOffset < 90 && !isOkOffset)
@@ -178,7 +178,7 @@ bool CHeader::Parse(const Byte *p)
if (codeOffset < 62 - 24 && !isOkOffset)
return false;
NumFatBits = 0;
UInt32 mask = (1 << (SectorSizeLog - 5)) - 1;
const UInt32 mask = (1 << (SectorSizeLog - 5)) - 1;
if ((numRootDirEntries & mask) != 0)
return false;
NumRootDirSectors = (numRootDirEntries + mask) >> (SectorSizeLog - 5);
@@ -187,8 +187,12 @@ bool CHeader::Parse(const Byte *p)
NumSectors = Get16(p + 19);
if (NumSectors == 0)
NumSectors = Get32(p + 32);
/*
// mkfs.fat could create fat32 image with 16-bit number of sectors.
// v23: we allow 16-bit value for number of sectors in fat32.
else if (IsFat32())
return false;
*/
MediaType = p[21];
NumFatSectors = Get16(p + 22);
@@ -241,19 +245,18 @@ bool CHeader::Parse(const Byte *p)
DataSector = RootDirSector + NumRootDirSectors;
if (NumSectors < DataSector)
return false;
UInt32 numDataSectors = NumSectors - DataSector;
UInt32 numClusters = numDataSectors >> SectorsPerClusterLog;
const UInt32 numDataSectors = NumSectors - DataSector;
const UInt32 numClusters = numDataSectors >> SectorsPerClusterLog;
BadCluster = 0x0FFFFFF7;
if (numClusters < 0xFFF5)
// v23: we support unusual (< 0xFFF5) numClusters values in fat32 systems
if (NumFatBits != 32)
{
if (NumFatBits == 32)
if (numClusters >= 0xFFF5)
return false;
NumFatBits = (Byte)(numClusters < 0xFF5 ? 12 : 16);
BadCluster &= ((1 << NumFatBits) - 1);
}
else if (NumFatBits != 32)
return false;
FatSize = numClusters + 2;
if (FatSize > BadCluster || CalcFatSizeInSectors() > NumFatSectors)
@@ -358,7 +361,7 @@ struct CDatabase
UInt64 PhySize;
CDatabase(): Fat(0) {}
CDatabase(): Fat(NULL) {}
~CDatabase() { ClearAndClose(); }
void Clear();
@@ -366,7 +369,7 @@ struct CDatabase
HRESULT OpenProgressFat(bool changeTotal = true);
HRESULT OpenProgress();
UString GetItemPath(Int32 index) const;
UString GetItemPath(UInt32 index) const;
HRESULT Open();
HRESULT ReadDir(Int32 parent, UInt32 cluster, unsigned level);
@@ -380,7 +383,7 @@ struct CDatabase
HRESULT CDatabase::SeekToSector(UInt32 sector)
{
return InStream->Seek((UInt64)sector << Header.SectorSizeLog, STREAM_SEEK_SET, NULL);
return InStream_SeekSet(InStream, (UInt64)sector << Header.SectorSizeLog);
}
void CDatabase::Clear()
@@ -392,7 +395,7 @@ void CDatabase::Clear()
Items.Clear();
delete []Fat;
Fat = 0;
Fat = NULL;
}
void CDatabase::ClearAndClose()
@@ -409,7 +412,7 @@ HRESULT CDatabase::OpenProgressFat(bool changeTotal)
{
UInt64 numTotalBytes = (Header.CalcFatSizeInSectors() << Header.SectorSizeLog) +
((UInt64)(Header.FatSize - NumFreeClusters) << Header.ClusterSizeLog);
RINOK(OpenCallback->SetTotal(NULL, &numTotalBytes));
RINOK(OpenCallback->SetTotal(NULL, &numTotalBytes))
}
return OpenCallback->SetCompleted(NULL, &NumCurUsedBytes);
}
@@ -422,14 +425,14 @@ HRESULT CDatabase::OpenProgress()
return OpenCallback->SetCompleted(&numItems, &NumCurUsedBytes);
}
UString CDatabase::GetItemPath(Int32 index) const
UString CDatabase::GetItemPath(UInt32 index) const
{
const CItem *item = &Items[index];
UString name = item->GetName();
for (;;)
{
index = item->Parent;
if (index < 0)
index = (UInt32)item->Parent;
if (item->Parent < 0)
return name;
item = &Items[index];
name.InsertAtFront(WCHAR_PATH_SEPARATOR);
@@ -464,7 +467,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level)
if (!clusterMode)
{
blockSize = Header.SectorSize();
RINOK(SeekToSector(Header.RootDirSector));
RINOK(SeekToSector(Header.RootDirSector))
}
ByteBuf.Alloc(blockSize);
@@ -480,7 +483,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level)
if ((NumDirClusters & 0xFF) == 0)
{
RINOK(OpenProgress());
RINOK(OpenProgress())
}
if (clusterMode)
@@ -490,7 +493,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level)
if (!Header.IsValidCluster(cluster))
return S_FALSE;
PRF(printf("\nCluster = %4X", cluster));
RINOK(SeekToCluster(cluster));
RINOK(SeekToCluster(cluster))
UInt32 newCluster = Fat[cluster];
if ((newCluster & kFatItemUsedByDirMask) != 0)
return S_FALSE;
@@ -502,7 +505,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level)
else if (sectorIndex++ >= Header.NumRootDirSectors)
break;
RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize));
RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize))
}
const Byte *p = ByteBuf + pos;
@@ -621,7 +624,7 @@ HRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level)
if (item.IsDir())
{
PRF(printf("\n%S", GetItemPath(i)));
RINOK(CDatabase::ReadDir(i, item.Cluster, level + 1));
RINOK(CDatabase::ReadDir((int)i, item.Cluster, level + 1))
}
}
return S_OK;
@@ -633,11 +636,11 @@ HRESULT CDatabase::Open()
bool numFreeClustersDefined = false;
{
Byte buf[kHeaderSize];
RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize));
RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize))
if (!Header.Parse(buf))
return S_FALSE;
UInt64 fileSize;
RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize));
RINOK(InStream_GetSize_SeekToEnd(InStream, fileSize))
/* we comment that check to support truncated images */
/*
@@ -648,7 +651,7 @@ HRESULT CDatabase::Open()
if (Header.IsFat32())
{
SeekToSector(Header.FsInfoSector);
RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize));
RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize))
if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
return S_FALSE;
if (Get32(buf) == 0x41615252 && Get32(buf + 484) == 0x61417272)
@@ -666,8 +669,8 @@ HRESULT CDatabase::Open()
CByteBuffer byteBuf;
Fat = new UInt32[Header.FatSize];
RINOK(OpenProgressFat());
RINOK(SeekToSector(Header.GetFatSector()));
RINOK(OpenProgressFat())
RINOK(SeekToSector(Header.GetFatSector()))
if (Header.NumFatBits == 32)
{
const UInt32 kBufSize = (1 << 15);
@@ -679,7 +682,7 @@ HRESULT CDatabase::Open()
if (size > kBufSize32)
size = kBufSize32;
UInt32 readSize = Header.SizeToSectors(size * 4) << Header.SectorSizeLog;
RINOK(ReadStream_FALSE(InStream, byteBuf, readSize));
RINOK(ReadStream_FALSE(InStream, byteBuf, readSize))
NumCurUsedBytes += readSize;
const UInt32 *src = (const UInt32 *)(const void *)(const Byte *)byteBuf;
@@ -701,7 +704,7 @@ HRESULT CDatabase::Open()
i += size;
if ((i & 0xFFFFF) == 0)
{
RINOK(OpenProgressFat(!numFreeClustersDefined));
RINOK(OpenProgressFat(!numFreeClustersDefined))
}
}
}
@@ -711,7 +714,7 @@ HRESULT CDatabase::Open()
NumCurUsedBytes += kBufSize;
byteBuf.Alloc(kBufSize);
Byte *p = byteBuf;
RINOK(ReadStream_FALSE(InStream, p, kBufSize));
RINOK(ReadStream_FALSE(InStream, p, kBufSize))
UInt32 fatSize = Header.FatSize;
UInt32 *fat = &Fat[0];
if (Header.NumFatBits == 16)
@@ -730,7 +733,7 @@ HRESULT CDatabase::Open()
}
}
RINOK(OpenProgressFat());
RINOK(OpenProgressFat())
if ((Fat[0] & 0xFF) != Header.MediaType)
{
@@ -741,28 +744,27 @@ HRESULT CDatabase::Open()
return S_FALSE;
}
RINOK(ReadDir(-1, Header.RootCluster, 0));
RINOK(ReadDir(-1, Header.RootCluster, 0))
PhySize = Header.GetPhySize();
return S_OK;
}
class CHandler:
Z7_class_CHandler_final:
public IInArchive,
public IInArchiveGetStream,
public CMyUnknownImp,
CDatabase
{
public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
Z7_IFACES_IMP_UNK_2(IInArchive, IInArchiveGetStream)
};
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
{
COM_TRY_BEGIN
*stream = 0;
*stream = NULL;
const CItem &item = Items[index];
CClusterInStream *streamSpec = new CClusterInStream;
CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
@@ -796,7 +798,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
if (!Header.IsEocAndUnused(cluster))
return S_FALSE;
}
RINOK(streamSpec->InitAndSeek());
RINOK(streamSpec->InitAndSeek())
*stream = streamTemp.Detach();
return S_OK;
COM_TRY_END
@@ -873,7 +875,7 @@ static void StringToProp(const Byte *src, unsigned size, NWindows::NCOM::CPropVa
#define STRING_TO_PROP(s, p) StringToProp(s, sizeof(s), prop)
*/
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
@@ -911,7 +913,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
COM_TRY_END
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
@@ -933,7 +935,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END
}
STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)
Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))
{
COM_TRY_BEGIN
{
@@ -957,17 +959,17 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
COM_TRY_END
}
STDMETHODIMP CHandler::Close()
Z7_COM7F_IMF(CHandler::Close())
{
ClearAndClose();
return S_OK;
}
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback))
{
COM_TRY_BEGIN
bool allFilesMode = (numItems == (UInt32)(Int32)-1);
const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode)
numItems = Items.Size();
if (numItems == 0)
@@ -980,7 +982,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (!item.IsDir())
totalSize += item.Size;
}
RINOK(extractCallback->SetTotal(totalSize));
RINOK(extractCallback->SetTotal(totalSize))
UInt64 totalPackSize;
totalSize = totalPackSize = 0;
@@ -995,23 +997,25 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CDummyOutStream *outStreamSpec = new CDummyOutStream;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
for (i = 0; i < numItems; i++)
for (i = 0;; i++)
{
lps->InSize = totalPackSize;
lps->OutSize = totalSize;
RINOK(lps->SetCur());
RINOK(lps->SetCur())
if (i == numItems)
break;
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
const Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
Int32 index = allFilesMode ? i : indices[i];
const UInt32 index = allFilesMode ? i : indices[i];
const CItem &item = Items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
if (item.IsDir())
{
RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
RINOK(extractCallback->PrepareOperation(askMode))
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
continue;
}
@@ -1020,7 +1024,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->PrepareOperation(askMode))
outStreamSpec->SetStream(realOutStream);
realOutStream.Release();
@@ -1031,22 +1035,22 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
HRESULT hres = GetStream(index, &inStream);
if (hres != S_FALSE)
{
RINOK(hres);
RINOK(hres)
if (inStream)
{
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress))
if (copyCoderSpec->TotalSize == item.Size)
res = NExtract::NOperationResult::kOK;
}
}
outStreamSpec->ReleaseStream();
RINOK(extractCallback->SetOperationResult(res));
RINOK(extractCallback->SetOperationResult(res))
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
{
*numItems = Items.Size();
return S_OK;
@@ -1055,7 +1059,7 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
static const Byte k_Signature[] = { 0x55, 0xAA };
REGISTER_ARC_I(
"FAT", "fat img", 0, 0xDA,
"FAT", "fat img", NULL, 0xDA,
k_Signature,
0x1FE,
0,