This commit is contained in:
Igor Pavlov
2005-05-30 00:00:00 +00:00
committed by Kornel Lesiński
parent 8c1b5c7b7e
commit 3c510ba80b
926 changed files with 40559 additions and 23519 deletions
+120 -54
View File
@@ -11,38 +11,38 @@
namespace NArchive{
namespace NCab{
static HRESULT ReadBytes(IInStream *inStream, void *data, UINT32 size)
static HRESULT ReadBytes(IInStream *inStream, void *data, UInt32 size)
{
UINT32 realProcessedSize;
UInt32 realProcessedSize;
RINOK(inStream->Read(data, size, &realProcessedSize));
if(realProcessedSize != size)
return S_FALSE;
return S_OK;
}
static HRESULT SafeRead(IInStream *inStream, void *data, UINT32 size)
static HRESULT SafeRead(IInStream *inStream, void *data, UInt32 size)
{
UINT32 realProcessedSize;
UInt32 realProcessedSize;
RINOK(inStream->Read(data, size, &realProcessedSize));
if(realProcessedSize != size)
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
return S_OK;
}
static void SafeInByteRead(CInBuffer &inBuffer, void *data, UINT32 size)
static void SafeInByteRead(::CInBuffer &inBuffer, void *data, UInt32 size)
{
UINT32 realProcessedSize;
UInt32 realProcessedSize;
inBuffer.ReadBytes(data, size, realProcessedSize);
if(realProcessedSize != size)
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
}
static void SafeReadName(CInBuffer &inBuffer, AString &name)
static void SafeReadName(::CInBuffer &inBuffer, AString &name)
{
name.Empty();
while(true)
{
BYTE b;
Byte b;
if (!inBuffer.ReadByte(b))
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
if (b == 0)
@@ -51,31 +51,63 @@ static void SafeReadName(CInBuffer &inBuffer, AString &name)
}
}
Byte CInArchive::ReadByte()
{
if (_blockPos >= _blockSize)
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
return _block[_blockPos++];
}
UInt16 CInArchive::ReadUInt16()
{
UInt16 value = 0;
for (int i = 0; i < 2; i++)
{
Byte b = ReadByte();
value |= (UInt16(b) << (8 * i));
}
return value;
}
UInt32 CInArchive::ReadUInt32()
{
UInt32 value = 0;
for (int i = 0; i < 4; i++)
{
Byte b = ReadByte();
value |= (UInt32(b) << (8 * i));
}
return value;
}
HRESULT CInArchive::Open(IInStream *inStream,
const UINT64 *searchHeaderSizeLimit,
const UInt64 *searchHeaderSizeLimit,
CInArchiveInfo &inArchiveInfo,
CObjectVector<NHeader::CFolder> &folders,
CObjectVector<CItem> &files,
CProgressVirt *progressVirt)
{
UINT64 startPosition;
UInt64 startPosition;
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &startPosition));
NHeader::NArchive::CBlock archiveHeader;
// NHeader::NArchive::CBlock archiveHeader;
{
CInBuffer inBuffer;
inBuffer.Init(inStream);
UINT64 value = 0;
const int kSignatureSize = sizeof(value);
UINT64 kSignature64 = NHeader::NArchive::kSignature;
::CInBuffer inBuffer;
if (!inBuffer.Create(1 << 17))
return E_OUTOFMEMORY;
inBuffer.SetStream(inStream);
inBuffer.Init();
UInt64 value = 0;
const int kSignatureSize = 8;
UInt64 kSignature64 = NHeader::NArchive::kSignature;
while(true)
{
BYTE b;
Byte b;
if (!inBuffer.ReadByte(b))
return S_FALSE;
value >>= 8;
value |= ((UINT64)b) << ((kSignatureSize - 1) * 8);
value |= ((UInt64)b) << ((kSignatureSize - 1) * 8);
if (inBuffer.GetProcessedSize() >= kSignatureSize)
{
if (value == kSignature64)
@@ -88,40 +120,59 @@ HRESULT CInArchive::Open(IInStream *inStream,
startPosition += inBuffer.GetProcessedSize() - kSignatureSize;
}
RINOK(inStream->Seek(startPosition, STREAM_SEEK_SET, NULL));
RINOK(ReadBytes(inStream, &archiveHeader, sizeof(archiveHeader)));
RINOK(ReadBytes(inStream, _block, NHeader::NArchive::kArchiveHeaderSize));
_blockSize = NHeader::NArchive::kArchiveHeaderSize;
_blockPos = 0;
ReadUInt32(); // Signature; // cabinet file signature
// if (archiveHeader.Signature != NHeader::NArchive::kSignature)
// return S_FALSE;
if (archiveHeader.Reserved1 != 0 ||
archiveHeader.Reserved2 != 0 ||
archiveHeader.Reserved3 != 0)
throw CInArchiveException(CInArchiveException::kUnsupported);
inArchiveInfo.VersionMinor = archiveHeader.VersionMinor;
inArchiveInfo.VersionMajor = archiveHeader.VersionMajor;
inArchiveInfo.NumFolders = archiveHeader.NumFolders;
inArchiveInfo.NumFiles = archiveHeader.NumFiles;
inArchiveInfo.Flags = archiveHeader.Flags;
UInt32 reserved1 = ReadUInt32();
UInt32 size = ReadUInt32(); // size of this cabinet file in bytes
UInt32 reserved2 = ReadUInt32();
UInt32 fileOffset = ReadUInt32(); // offset of the first CFFILE entry
UInt32 reserved3 = ReadUInt32();
inArchiveInfo.VersionMinor = ReadByte(); // cabinet file format version, minor
inArchiveInfo.VersionMajor = ReadByte(); // cabinet file format version, major
inArchiveInfo.NumFolders = ReadUInt16(); // number of CFFOLDER entries in this cabinet
inArchiveInfo.NumFiles = ReadUInt16(); // number of CFFILE entries in this cabinet
inArchiveInfo.Flags = ReadUInt16(); // number of CFFILE entries in this cabinet
UInt16 setID = ReadUInt16(); // must be the same for all cabinets in a set
UInt16 cabinetNumber = ReadUInt16(); // number of this cabinet file in a set
if (reserved1 != 0 || reserved2 != 0 || reserved3 != 0)
throw CInArchiveException(CInArchiveException::kUnsupported);
if (inArchiveInfo.ReserveBlockPresent())
{
RINOK(SafeRead(inStream, &inArchiveInfo.PerDataSizes,
sizeof(inArchiveInfo.PerDataSizes)));
RINOK(SafeRead(inStream, _block, NHeader::NArchive::kPerDataSizesHeaderSize));
_blockSize = NHeader::NArchive::kPerDataSizesHeaderSize;
_blockPos = 0;
inArchiveInfo.PerDataSizes.PerCabinetAreaSize = ReadUInt16(); // (optional) size of per-cabinet reserved area
inArchiveInfo.PerDataSizes.PerFolderAreaSize = ReadByte(); // (optional) size of per-folder reserved area
inArchiveInfo.PerDataSizes.PerDatablockAreaSize = ReadByte(); // (optional) size of per-datablock reserved area
RINOK(inStream->Seek(inArchiveInfo.PerDataSizes.PerCabinetAreaSize,
STREAM_SEEK_CUR, NULL));
}
{
UINT64 foldersStartPosition;
UInt64 foldersStartPosition;
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &foldersStartPosition));
CInBuffer inBuffer;
inBuffer.Init(inStream);
if ((archiveHeader.Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0)
::CInBuffer inBuffer;
if (!inBuffer.Create(1 << 17))
return E_OUTOFMEMORY;
inBuffer.SetStream(inStream);
inBuffer.Init();
if ((inArchiveInfo.Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0)
{
SafeReadName(inBuffer, inArchiveInfo.PreviousCabinetName);
SafeReadName(inBuffer, inArchiveInfo.PreviousDiskName);
}
if ((archiveHeader.Flags & NHeader::NArchive::NFlags::kNextCabinet) != 0)
if ((inArchiveInfo.Flags & NHeader::NArchive::NFlags::kNextCabinet) != 0)
{
SafeReadName(inBuffer, inArchiveInfo.NextCabinetName);
SafeReadName(inBuffer, inArchiveInfo.NextDiskName);
@@ -132,54 +183,69 @@ HRESULT CInArchive::Open(IInStream *inStream,
if (progressVirt != NULL)
{
UINT64 numFiles = archiveHeader.NumFiles;
UInt64 numFiles = inArchiveInfo.NumFiles;
RINOK(progressVirt->SetTotal(&numFiles));
}
folders.Clear();
for(int i = 0; i < archiveHeader.NumFolders; i++)
int i;
for(i = 0; i < inArchiveInfo.NumFolders; i++)
{
if (progressVirt != NULL)
{
UINT64 numFiles = 0;
UInt64 numFiles = 0;
RINOK(progressVirt->SetCompleted(&numFiles));
}
NHeader::CFolder folder;
RINOK(SafeRead(inStream, &folder, sizeof(folder)));
RINOK(SafeRead(inStream, _block, NHeader::kFolderHeaderSize));
_blockSize = NHeader::kFolderHeaderSize;
_blockPos = 0;
folder.DataStart = ReadUInt32();
folder.NumDataBlocks = ReadUInt16();
folder.CompressionTypeMajor = ReadByte();
folder.CompressionTypeMinor = ReadByte();
if (inArchiveInfo.ReserveBlockPresent())
{
RINOK(inStream->Seek(
inArchiveInfo.PerDataSizes.PerFolderAreaSize, STREAM_SEEK_CUR, NULL));
}
folder.DataStart += (UINT32)startPosition;
folder.DataStart += (UInt32)startPosition;
folders.Add(folder);
}
RINOK(inStream->Seek(startPosition + archiveHeader.FileOffset,
RINOK(inStream->Seek(startPosition + fileOffset,
STREAM_SEEK_SET, NULL));
CInBuffer inBuffer;
inBuffer.Init(inStream);
::CInBuffer inBuffer;
if (!inBuffer.Create(1 << 17))
return E_OUTOFMEMORY;
inBuffer.SetStream(inStream);
inBuffer.Init();
files.Clear();
if (progressVirt != NULL)
{
UINT64 numFiles = files.Size();
UInt64 numFiles = files.Size();
RINOK(progressVirt->SetCompleted(&numFiles));
}
for(i = 0; i < archiveHeader.NumFiles; i++)
for(i = 0; i < inArchiveInfo.NumFiles; i++)
{
NHeader::CFile fileHeader;
SafeInByteRead(inBuffer, &fileHeader, sizeof(fileHeader));
SafeInByteRead(inBuffer, _block, NHeader::kFileHeaderSize);
_blockSize = NHeader::kFileHeaderSize;
_blockPos = 0;
CItem item;
item.UnPackSize = fileHeader.UnPackSize;
item.UnPackOffset = fileHeader.UnPackOffset;
item.FolderIndex = fileHeader.FolderIndex;
item.Time = ((UINT32(fileHeader.PureDate) << 16)) | fileHeader.PureTime;
item.Attributes = fileHeader.Attributes;
item.UnPackSize = ReadUInt32();
item.UnPackOffset = ReadUInt32();
item.FolderIndex = ReadUInt16();
UInt16 pureDate = ReadUInt16();
UInt16 pureTime = ReadUInt16();
item.Time = ((UInt32(pureDate) << 16)) | pureTime;
item.Attributes = ReadUInt16();
SafeReadName(inBuffer, item.Name);
files.Add(item);
if (progressVirt != NULL)
{
UINT64 numFiles = files.Size();
UInt64 numFiles = files.Size();
RINOK(progressVirt->SetCompleted(&numFiles));
}
}