mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-09 06:07:05 -06:00
4.59 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
3901bf0ab8
commit
173c07e166
@@ -1,3 +0,0 @@
|
||||
// StdAfx.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
@@ -15,104 +15,99 @@
|
||||
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "../Common/DummyOutStream.h"
|
||||
|
||||
#include "../../Compress/Copy/CopyCoder.h"
|
||||
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NTime;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NTar {
|
||||
|
||||
STATPROPSTG kProps[] =
|
||||
STATPROPSTG kProps[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidIsFolder, VT_BOOL},
|
||||
{ NULL, kpidIsDir, VT_BOOL},
|
||||
{ NULL, kpidSize, VT_UI8},
|
||||
{ NULL, kpidPackedSize, VT_UI8},
|
||||
{ NULL, kpidLastWriteTime, VT_FILETIME},
|
||||
{ NULL, kpidPackSize, VT_UI8},
|
||||
{ NULL, kpidMTime, VT_FILETIME},
|
||||
{ NULL, kpidUser, VT_BSTR},
|
||||
{ NULL, kpidGroup, VT_BSTR},
|
||||
{ NULL, kpidGroup, VT_BSTR}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
IMP_IInArchive_Props
|
||||
IMP_IInArchive_ArcProps_NO
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||
{
|
||||
UInt64 endPos = 0;
|
||||
if (callback != NULL)
|
||||
{
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
|
||||
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
|
||||
UInt64 pos = 0;
|
||||
for (;;)
|
||||
{
|
||||
CItemEx item;
|
||||
bool filled;
|
||||
item.HeaderPosition = pos;
|
||||
RINOK(ReadItem(stream, filled, item));
|
||||
if (!filled)
|
||||
break;
|
||||
_items.Add(item);
|
||||
|
||||
RINOK(stream->Seek(item.GetPackSize(), STREAM_SEEK_CUR, &pos));
|
||||
if (pos >= endPos)
|
||||
return S_FALSE;
|
||||
if (callback != NULL)
|
||||
{
|
||||
if (_items.Size() == 1)
|
||||
{
|
||||
RINOK(callback->SetTotal(NULL, &endPos));
|
||||
}
|
||||
if (_items.Size() % 100 == 0)
|
||||
{
|
||||
UInt64 numFiles = _items.Size();
|
||||
RINOK(callback->SetCompleted(&numFiles, &pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_items.Size() == 0)
|
||||
{
|
||||
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
|
||||
if (!callback)
|
||||
return S_FALSE;
|
||||
callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
|
||||
if (!openVolumeCallback)
|
||||
return S_FALSE;
|
||||
NCOM::CPropVariant prop;
|
||||
if (openVolumeCallback->GetProperty(kpidName, &prop) != S_OK)
|
||||
return S_FALSE;
|
||||
if (prop.vt != VT_BSTR)
|
||||
return S_FALSE;
|
||||
UString baseName = prop.bstrVal;
|
||||
baseName = baseName.Right(4);
|
||||
if (baseName.CompareNoCase(L".tar") != 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const UInt64 * /* maxCheckStartPosition */,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
// try
|
||||
{
|
||||
CInArchive archive;
|
||||
|
||||
if (archive.Open(stream) != S_OK)
|
||||
return S_FALSE;
|
||||
|
||||
_items.Clear();
|
||||
|
||||
if (openArchiveCallback != NULL)
|
||||
{
|
||||
RINOK(openArchiveCallback->SetTotal(NULL, NULL));
|
||||
UInt64 numFiles = _items.Size();
|
||||
RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
CItemEx item;
|
||||
bool filled;
|
||||
HRESULT result = archive.GetNextItem(filled, item);
|
||||
if (result == S_FALSE)
|
||||
return S_FALSE;
|
||||
if (result != S_OK)
|
||||
return S_FALSE;
|
||||
if (!filled)
|
||||
break;
|
||||
_items.Add(item);
|
||||
archive.SkeepDataRecords(item.Size);
|
||||
if (openArchiveCallback != NULL)
|
||||
{
|
||||
UInt64 numFiles = _items.Size();
|
||||
RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
|
||||
}
|
||||
}
|
||||
if (_items.Size() == 0)
|
||||
{
|
||||
CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
|
||||
if (!openArchiveCallback)
|
||||
return S_FALSE;
|
||||
openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
|
||||
if (!openVolumeCallback)
|
||||
return S_FALSE;
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
|
||||
if (prop.vt != VT_BSTR)
|
||||
return S_FALSE;
|
||||
UString baseName = prop.bstrVal;
|
||||
baseName = baseName.Right(4);
|
||||
if (baseName.CompareNoCase(L".tar") != 0)
|
||||
return S_FALSE;
|
||||
}
|
||||
Close();
|
||||
RINOK(Open2(stream, openArchiveCallback));
|
||||
_inStream = stream;
|
||||
}
|
||||
/*
|
||||
catch(...)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
*/
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
@@ -138,38 +133,20 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPath:
|
||||
prop = (const wchar_t *)NItemName::GetOSName2(
|
||||
MultiByteToUnicodeString(item.Name, CP_OEMCP));
|
||||
break;
|
||||
case kpidIsFolder:
|
||||
prop = item.IsDirectory();
|
||||
break;
|
||||
case kpidSize:
|
||||
case kpidPackedSize:
|
||||
prop = (UInt64)item.Size;
|
||||
break;
|
||||
case kpidLastWriteTime:
|
||||
{
|
||||
FILETIME utcFileTime;
|
||||
if (item.ModificationTime != 0)
|
||||
NTime::UnixTimeToFileTime(item.ModificationTime, utcFileTime);
|
||||
else
|
||||
case kpidPath: prop = NItemName::GetOSName2(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break;
|
||||
case kpidIsDir: prop = item.IsDir(); break;
|
||||
case kpidSize: prop = item.Size; break;
|
||||
case kpidPackSize: prop = item.GetPackSize(); break;
|
||||
case kpidMTime:
|
||||
if (item.MTime != 0)
|
||||
{
|
||||
utcFileTime.dwLowDateTime = 0;
|
||||
utcFileTime.dwHighDateTime = 0;
|
||||
FILETIME ft;
|
||||
NTime::UnixTimeToFileTime(item.MTime, ft);
|
||||
prop = ft;
|
||||
}
|
||||
prop = utcFileTime;
|
||||
break;
|
||||
}
|
||||
case kpidUser:
|
||||
prop = (const wchar_t *)
|
||||
MultiByteToUnicodeString(item.UserName, CP_OEMCP);
|
||||
break;
|
||||
case kpidGroup:
|
||||
prop = (const wchar_t *)
|
||||
MultiByteToUnicodeString(item.GroupName, CP_OEMCP);
|
||||
break;
|
||||
case kpidUser: prop = MultiByteToUnicodeString(item.UserName, CP_OEMCP); break;
|
||||
case kpidGroup: prop = MultiByteToUnicodeString(item.GroupName, CP_OEMCP); break;
|
||||
}
|
||||
prop.Detach(value);
|
||||
return S_OK;
|
||||
@@ -192,8 +169,8 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
totalSize += _items[allFilesMode ? i : indices[i]].Size;
|
||||
extractCallback->SetTotal(totalSize);
|
||||
|
||||
UInt64 currentTotalSize = 0;
|
||||
UInt64 currentItemSize;
|
||||
UInt64 totalPackSize, curPackSize, curSize;
|
||||
totalSize = totalPackSize = 0;
|
||||
|
||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
|
||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
||||
@@ -206,19 +183,24 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
||||
streamSpec->SetStream(_inStream);
|
||||
|
||||
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
|
||||
CDummyOutStream *outStreamSpec = new CDummyOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||
|
||||
for (i = 0; i < numItems; i++, totalSize += curSize, totalPackSize += curPackSize)
|
||||
{
|
||||
lps->InSize = lps->OutSize = currentTotalSize;
|
||||
lps->InSize = totalPackSize;
|
||||
lps->OutSize = totalSize;
|
||||
RINOK(lps->SetCur());
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
Int32 askMode = testMode ?
|
||||
Int32 askMode = testMode ?
|
||||
NArchive::NExtract::NAskMode::kTest :
|
||||
NArchive::NExtract::NAskMode::kExtract;
|
||||
Int32 index = allFilesMode ? i : indices[i];
|
||||
const CItemEx &item = _items[index];
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
||||
currentItemSize = item.Size;
|
||||
if (item.IsDirectory())
|
||||
curSize = item.Size;
|
||||
curPackSize = item.GetPackSize();
|
||||
if (item.IsDir())
|
||||
{
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
||||
@@ -227,16 +209,16 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
if (!testMode && (!realOutStream))
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
if (testMode)
|
||||
{
|
||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
||||
continue;
|
||||
}
|
||||
|
||||
outStreamSpec->SetStream(realOutStream);
|
||||
realOutStream.Release();
|
||||
outStreamSpec->Init();
|
||||
|
||||
RINOK(_inStream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(item.Size);
|
||||
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
|
||||
realOutStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
|
||||
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
|
||||
outStreamSpec->ReleaseStream();
|
||||
RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == item.Size ?
|
||||
NArchive::NExtract::NOperationResult::kOK:
|
||||
NArchive::NExtract::NOperationResult::kDataError));
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace NArchive {
|
||||
namespace NTar {
|
||||
|
||||
class CHandler:
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public IOutArchive,
|
||||
public CMyUnknownImp
|
||||
@@ -25,6 +25,8 @@ public:
|
||||
INTERFACE_IInArchive(;)
|
||||
INTERFACE_IOutArchive(;)
|
||||
|
||||
HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
|
||||
|
||||
private:
|
||||
CObjectVector<CItemEx> _items;
|
||||
CMyComPtr<IInStream> _inStream;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NCOM;
|
||||
using namespace NTime;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NTar {
|
||||
@@ -27,34 +26,33 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
IArchiveUpdateCallback *callback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
CObjectVector<CUpdateItemInfo> updateItems;
|
||||
for(UInt32 i = 0; i < numItems; i++)
|
||||
CObjectVector<CUpdateItem> updateItems;
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
CUpdateItemInfo updateItem;
|
||||
CUpdateItem ui;
|
||||
Int32 newData;
|
||||
Int32 newProperties;
|
||||
UInt32 indexInArchive;
|
||||
if (!updateCallback)
|
||||
if (!callback)
|
||||
return E_FAIL;
|
||||
RINOK(updateCallback->GetUpdateItemInfo(i,
|
||||
&newData, &newProperties, &indexInArchive));
|
||||
updateItem.NewProperties = IntToBool(newProperties);
|
||||
updateItem.NewData = IntToBool(newData);
|
||||
updateItem.IndexInArchive = indexInArchive;
|
||||
updateItem.IndexInClient = i;
|
||||
RINOK(callback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive));
|
||||
ui.NewProperties = IntToBool(newProperties);
|
||||
ui.NewData = IntToBool(newData);
|
||||
ui.IndexInArchive = indexInArchive;
|
||||
ui.IndexInClient = i;
|
||||
|
||||
if (IntToBool(newProperties))
|
||||
{
|
||||
FILETIME utcTime;
|
||||
UString name;
|
||||
bool isDirectoryStatusDefined;
|
||||
/*
|
||||
UInt32 attributes;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidAttributes, &prop));
|
||||
RINOK(callback->GetProperty(i, kpidAttrib, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
attributes = 0;
|
||||
else if (prop.vt != VT_UI4)
|
||||
@@ -62,16 +60,17 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
else
|
||||
attributes = prop.ulVal;
|
||||
}
|
||||
*/
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidLastWriteTime, &prop));
|
||||
RINOK(callback->GetProperty(i, kpidMTime, &prop));
|
||||
if (prop.vt != VT_FILETIME)
|
||||
return E_INVALIDARG;
|
||||
utcTime = prop.filetime;
|
||||
}
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidPath, &prop));
|
||||
RINOK(callback->GetProperty(i, kpidPath, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
name.Empty();
|
||||
else if (prop.vt != VT_BSTR)
|
||||
@@ -81,27 +80,21 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
}
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidIsFolder, &prop));
|
||||
RINOK(callback->GetProperty(i, kpidIsDir, &prop));
|
||||
if (prop.vt == VT_EMPTY)
|
||||
isDirectoryStatusDefined = false;
|
||||
ui.IsDir = false;
|
||||
else if (prop.vt != VT_BOOL)
|
||||
return E_INVALIDARG;
|
||||
else
|
||||
{
|
||||
updateItem.IsDirectory = (prop.boolVal != VARIANT_FALSE);
|
||||
isDirectoryStatusDefined = true;
|
||||
}
|
||||
ui.IsDir = (prop.boolVal != VARIANT_FALSE);
|
||||
}
|
||||
updateItem.Name = UnicodeStringToMultiByte(
|
||||
NItemName::MakeLegalName(name), CP_OEMCP);
|
||||
if (!isDirectoryStatusDefined)
|
||||
updateItem.IsDirectory = ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
|
||||
if (updateItem.IsDirectory)
|
||||
updateItem.Name += '/';
|
||||
ui.Name = UnicodeStringToMultiByte(NItemName::MakeLegalName(name), CP_OEMCP);
|
||||
if (ui.IsDir)
|
||||
ui.Name += '/';
|
||||
|
||||
if(!FileTimeToUnixTime(utcTime, updateItem.Time))
|
||||
if (!NTime::FileTimeToUnixTime(utcTime, ui.Time))
|
||||
{
|
||||
updateItem.Time = 0;
|
||||
ui.Time = 0;
|
||||
// return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
@@ -110,16 +103,16 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
||||
UInt64 size;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(i, kpidSize, &prop));
|
||||
RINOK(callback->GetProperty(i, kpidSize, &prop));
|
||||
if (prop.vt != VT_UI8)
|
||||
return E_INVALIDARG;
|
||||
size = prop.uhVal.QuadPart;
|
||||
}
|
||||
updateItem.Size = size;
|
||||
ui.Size = size;
|
||||
}
|
||||
updateItems.Add(updateItem);
|
||||
updateItems.Add(ui);
|
||||
}
|
||||
return UpdateArchive(_inStream, outStream, _items, updateItems, updateCallback);
|
||||
return UpdateArchive(_inStream, outStream, _items, updateItems, callback);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace NFileHeader {
|
||||
const char *kLongLink2 = "@LongLink";
|
||||
|
||||
// The magic field is filled with this if uname and gname are valid.
|
||||
namespace NMagic
|
||||
namespace NMagic
|
||||
{
|
||||
const char *kUsTar = "ustar"; // 5 chars
|
||||
const char *kGNUTar = "GNUtar "; // 7 chars and a null
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace NFileHeader
|
||||
namespace NMode
|
||||
{
|
||||
const int kSetUID = 04000; // Set UID on execution
|
||||
const int kSetGID = 02000; // Set GID on execution
|
||||
const int kSetGID = 02000; // Set GID on execution
|
||||
const int kSaveText = 01000; // Save text (sticky bit)
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace NFileHeader
|
||||
namespace NLinkFlag
|
||||
{
|
||||
const char kOldNormal = '\0'; // Normal disk file, Unix compatible
|
||||
const char kNormal = '0'; // Normal disk file
|
||||
const char kNormal = '0'; // Normal disk file
|
||||
const char kLink = '1'; // Link to previously dumped file
|
||||
const char kSymbolicLink = '2'; // Symbolic link
|
||||
const char kCharacter = '3'; // Character special file
|
||||
@@ -76,12 +76,12 @@ namespace NFileHeader
|
||||
const char kFIFO = '6'; // FIFO special file
|
||||
const char kContiguous = '7'; // Contiguous file
|
||||
|
||||
const char kDumpDir = 'D'; /* GNUTYPE_DUMPDIR.
|
||||
const char kDumpDir = 'D'; /* GNUTYPE_DUMPDIR.
|
||||
data: list of files created by the --incremental (-G) option
|
||||
Each file name is preceded by either
|
||||
- 'Y' (file should be in this archive)
|
||||
- 'N' (file is a directory, or is not stored in the archive.)
|
||||
Each file name is terminated by a null + an additional null after
|
||||
Each file name is preceded by either
|
||||
- 'Y' (file should be in this archive)
|
||||
- 'N' (file is a directory, or is not stored in the archive.)
|
||||
Each file name is terminated by a null + an additional null after
|
||||
the last file name. */
|
||||
|
||||
}
|
||||
@@ -94,7 +94,7 @@ namespace NFileHeader
|
||||
extern const char *kLongLink2; // = "@LongLink";
|
||||
|
||||
// The magic field is filled with this if uname and gname are valid.
|
||||
namespace NMagic
|
||||
namespace NMagic
|
||||
{
|
||||
extern const char *kUsTar; // = "ustar"; // 5 chars
|
||||
extern const char *kGNUTar; // = "GNUtar "; // 7 chars and a null
|
||||
|
||||
@@ -13,21 +13,6 @@
|
||||
namespace NArchive {
|
||||
namespace NTar {
|
||||
|
||||
HRESULT CInArchive::ReadBytes(void *data, size_t size, size_t &processedSize)
|
||||
{
|
||||
processedSize = size;
|
||||
RINOK(ReadStream(m_Stream, data, &processedSize));
|
||||
m_Position += processedSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Open(IInStream *inStream)
|
||||
{
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
|
||||
m_Stream = inStream;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void MyStrNCpy(char *dest, const char *src, int size)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
@@ -62,130 +47,76 @@ static bool OctalToNumber32(const char *srcString, int size, UInt32 &res)
|
||||
|
||||
#define RIF(x) { if (!(x)) return S_FALSE; }
|
||||
|
||||
static bool IsRecordLast(const char *record)
|
||||
static bool IsRecordLast(const char *buf)
|
||||
{
|
||||
for (int i = 0; i < NFileHeader::kRecordSize; i++)
|
||||
if (record[i] != 0)
|
||||
if (buf[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ReadString(const char *s, int size, AString &result)
|
||||
{
|
||||
if (size > NFileHeader::kRecordSize)
|
||||
size = NFileHeader::kNameSize;
|
||||
char tempString[NFileHeader::kRecordSize + 1];
|
||||
MyStrNCpy(tempString, s, size);
|
||||
tempString[size] = '\0';
|
||||
result = tempString;
|
||||
char temp[NFileHeader::kRecordSize + 1];
|
||||
MyStrNCpy(temp, s, size);
|
||||
temp[size] = '\0';
|
||||
result = temp;
|
||||
}
|
||||
|
||||
static char GetHex(Byte value)
|
||||
{
|
||||
return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
|
||||
}
|
||||
|
||||
HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item)
|
||||
static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, size_t &processedSize)
|
||||
{
|
||||
item.LongLinkSize = 0;
|
||||
// NFileHeader::CRecord record;
|
||||
char record[NFileHeader::kRecordSize];
|
||||
char *cur = record;
|
||||
char buf[NFileHeader::kRecordSize];
|
||||
char *p = buf;
|
||||
|
||||
filled = false;
|
||||
|
||||
size_t processedSize;
|
||||
item.HeaderPosition = m_Position;
|
||||
RINOK(ReadBytes(record, NFileHeader::kRecordSize, processedSize));
|
||||
if (processedSize == 0 ||
|
||||
(processedSize == NFileHeader::kRecordSize && IsRecordLast(record)))
|
||||
processedSize = NFileHeader::kRecordSize;
|
||||
RINOK(ReadStream(stream, buf, &processedSize));
|
||||
if (processedSize == 0 || (processedSize == NFileHeader::kRecordSize && IsRecordLast(buf)))
|
||||
return S_OK;
|
||||
if (processedSize < NFileHeader::kRecordSize)
|
||||
return S_FALSE;
|
||||
|
||||
// NFileHeader::CHeader &header = record.Header;
|
||||
|
||||
AString name;
|
||||
ReadString(cur, NFileHeader::kNameSize, name);
|
||||
cur += NFileHeader::kNameSize;
|
||||
ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize;
|
||||
|
||||
item.Name.Empty();
|
||||
int i;
|
||||
for (i = 0; i < name.Length(); i++)
|
||||
{
|
||||
char c = name[i];
|
||||
if (((Byte)c) < 0x08)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
if (((Byte)c) < 0x20)
|
||||
{
|
||||
item.Name += '[';
|
||||
item.Name += GetHex((Byte)(((Byte)c) >> 4));
|
||||
item.Name += GetHex((Byte)(((Byte)c) & 0xF));
|
||||
item.Name += ']';
|
||||
}
|
||||
else
|
||||
item.Name += c;
|
||||
}
|
||||
RIF(OctalToNumber32(p, 8, item.Mode)); p += 8;
|
||||
|
||||
RIF(OctalToNumber32(cur, 8, item.Mode));
|
||||
cur += 8;
|
||||
if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8;
|
||||
if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8;
|
||||
|
||||
if (!OctalToNumber32(cur, 8, item.UID))
|
||||
item.UID = 0;
|
||||
cur += 8;
|
||||
|
||||
if (!OctalToNumber32(cur, 8, item.GID))
|
||||
item.GID = 0;
|
||||
cur += 8;
|
||||
|
||||
RIF(OctalToNumber(cur, 12, item.Size));
|
||||
cur += 12;
|
||||
|
||||
RIF(OctalToNumber32(cur, 12, item.ModificationTime));
|
||||
cur += 12;
|
||||
RIF(OctalToNumber(p, 12, item.Size)); p += 12;
|
||||
RIF(OctalToNumber32(p, 12, item.MTime)); p += 12;
|
||||
|
||||
UInt32 checkSum;
|
||||
RIF(OctalToNumber32(cur, 8, checkSum));
|
||||
memmove(cur, NFileHeader::kCheckSumBlanks, 8);
|
||||
cur += 8;
|
||||
RIF(OctalToNumber32(p, 8, checkSum));
|
||||
memcpy(p, NFileHeader::kCheckSumBlanks, 8); p += 8;
|
||||
|
||||
item.LinkFlag = *cur++;
|
||||
item.LinkFlag = *p++;
|
||||
|
||||
ReadString(cur, NFileHeader::kNameSize, item.LinkName);
|
||||
cur += NFileHeader::kNameSize;
|
||||
ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize;
|
||||
|
||||
memmove(item.Magic, cur, 8);
|
||||
cur += 8;
|
||||
memcpy(item.Magic, p, 8); p += 8;
|
||||
|
||||
ReadString(cur, NFileHeader::kUserNameSize, item.UserName);
|
||||
cur += NFileHeader::kUserNameSize;
|
||||
ReadString(cur, NFileHeader::kUserNameSize, item.GroupName);
|
||||
cur += NFileHeader::kUserNameSize;
|
||||
ReadString(p, NFileHeader::kUserNameSize, item.UserName); p += NFileHeader::kUserNameSize;
|
||||
ReadString(p, NFileHeader::kUserNameSize, item.GroupName); p += NFileHeader::kUserNameSize;
|
||||
|
||||
item.DeviceMajorDefined = (cur[0] != 0);
|
||||
RIF(OctalToNumber32(cur, 8, item.DeviceMajor));
|
||||
cur += 8;
|
||||
|
||||
item.DeviceMinorDefined = (cur[0] != 0);
|
||||
RIF(OctalToNumber32(cur, 8, item.DeviceMinor));
|
||||
cur += 8;
|
||||
item.DeviceMajorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMajor)); p += 8;
|
||||
item.DeviceMinorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMinor)); p += 8;
|
||||
|
||||
AString prefix;
|
||||
ReadString(cur, NFileHeader::kPrefixSize, prefix);
|
||||
cur += NFileHeader::kPrefixSize;
|
||||
if (!prefix.IsEmpty() && item.IsMagic() &&
|
||||
ReadString(p, NFileHeader::kPrefixSize, prefix);
|
||||
p += NFileHeader::kPrefixSize;
|
||||
if (!prefix.IsEmpty() && item.IsMagic() &&
|
||||
(item.LinkFlag != 'L' /* || prefix != "00000000000" */ ))
|
||||
item.Name = prefix + AString('/') + item.Name;
|
||||
|
||||
if (item.LinkFlag == NFileHeader::NLinkFlag::kLink)
|
||||
item.Size = 0;
|
||||
|
||||
|
||||
UInt32 checkSumReal = 0;
|
||||
for(i = 0; i < NFileHeader::kRecordSize; i++)
|
||||
checkSumReal += Byte(record[i]);
|
||||
for (int i = 0; i < NFileHeader::kRecordSize; i++)
|
||||
checkSumReal += (Byte)buf[i];
|
||||
|
||||
if (checkSumReal != checkSum)
|
||||
return S_FALSE;
|
||||
@@ -194,9 +125,10 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
|
||||
HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item)
|
||||
{
|
||||
RINOK(GetNextItemReal(filled, item));
|
||||
size_t processedSize;
|
||||
RINOK(GetNextItemReal(stream, filled, item, processedSize));
|
||||
if (!filled)
|
||||
return S_OK;
|
||||
// GNUtar extension
|
||||
@@ -205,22 +137,25 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
|
||||
if (item.Name.Compare(NFileHeader::kLongLink) != 0)
|
||||
if (item.Name.Compare(NFileHeader::kLongLink2) != 0)
|
||||
return S_FALSE;
|
||||
UInt64 headerPosition = item.HeaderPosition;
|
||||
|
||||
size_t processedSize;
|
||||
AString fullName;
|
||||
if (item.Size > (1 << 15))
|
||||
return S_FALSE;
|
||||
char *buffer = fullName.GetBuffer((int)item.Size + 1);
|
||||
RINOK(ReadBytes(buffer, (size_t)item.Size, processedSize));
|
||||
int packSize = (int)item.GetPackSize();
|
||||
char *buffer = fullName.GetBuffer(packSize + 1);
|
||||
|
||||
RINOK(ReadStream_FALSE(stream, buffer, packSize));
|
||||
processedSize += packSize;
|
||||
buffer[item.Size] = '\0';
|
||||
fullName.ReleaseBuffer();
|
||||
if (processedSize != item.Size)
|
||||
return S_FALSE;
|
||||
RINOK(Skeep((0 - item.Size) & 0x1FF));
|
||||
RINOK(GetNextItemReal(filled, item));
|
||||
|
||||
UInt64 headerPosition = item.HeaderPosition;
|
||||
{
|
||||
size_t processedSize2;
|
||||
RINOK(GetNextItemReal(stream, filled, item, processedSize2));
|
||||
}
|
||||
item.LongLinkSize = (unsigned)processedSize;
|
||||
item.Name = fullName;
|
||||
item.LongLinkSize = item.HeaderPosition - headerPosition;
|
||||
item.HeaderPosition = headerPosition;
|
||||
}
|
||||
else if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X')
|
||||
@@ -238,20 +173,4 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Skeep(UInt64 numBytes)
|
||||
{
|
||||
UInt64 newPostion;
|
||||
RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion));
|
||||
m_Position += numBytes;
|
||||
if (m_Position != newPostion)
|
||||
return E_FAIL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CInArchive::SkeepDataRecords(UInt64 dataSize)
|
||||
{
|
||||
return Skeep((dataSize + 0x1FF) & (~((UInt64)0x1FF)));
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -11,20 +11,8 @@
|
||||
namespace NArchive {
|
||||
namespace NTar {
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
CMyComPtr<IInStream> m_Stream;
|
||||
UInt64 m_Position;
|
||||
|
||||
HRESULT ReadBytes(void *data, size_t size, size_t &processedSize);
|
||||
public:
|
||||
HRESULT Open(IInStream *inStream);
|
||||
HRESULT GetNextItemReal(bool &filled, CItemEx &itemInfo);
|
||||
HRESULT GetNextItem(bool &filled, CItemEx &itemInfo);
|
||||
HRESULT Skeep(UInt64 numBytes);
|
||||
HRESULT SkeepDataRecords(UInt64 dataSize);
|
||||
};
|
||||
|
||||
HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &itemInfo);
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
#ifndef __ARCHIVE_TAR_ITEM_H
|
||||
#define __ARCHIVE_TAR_ITEM_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "Common/Types.h"
|
||||
#include "Common/MyString.h"
|
||||
|
||||
@@ -14,28 +12,29 @@
|
||||
namespace NArchive {
|
||||
namespace NTar {
|
||||
|
||||
class CItem
|
||||
struct CItem
|
||||
{
|
||||
public:
|
||||
AString Name;
|
||||
UInt64 Size;
|
||||
|
||||
UInt32 Mode;
|
||||
UInt32 UID;
|
||||
UInt32 GID;
|
||||
UInt64 Size;
|
||||
UInt32 ModificationTime;
|
||||
char LinkFlag;
|
||||
UInt32 MTime;
|
||||
UInt32 DeviceMajor;
|
||||
UInt32 DeviceMinor;
|
||||
|
||||
AString LinkName;
|
||||
char Magic[8];
|
||||
AString UserName;
|
||||
AString GroupName;
|
||||
|
||||
char Magic[8];
|
||||
char LinkFlag;
|
||||
bool DeviceMajorDefined;
|
||||
UInt32 DeviceMajor;
|
||||
bool DeviceMinorDefined;
|
||||
UInt32 DeviceMinor;
|
||||
|
||||
bool IsDirectory() const
|
||||
{
|
||||
bool IsDir() const
|
||||
{
|
||||
switch(LinkFlag)
|
||||
{
|
||||
case NFileHeader::NLinkFlag::kDirectory:
|
||||
@@ -48,22 +47,23 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsMagic() const
|
||||
{
|
||||
bool IsMagic() const
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
if (Magic[i] != NFileHeader::NMagic::kUsTar[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
UInt64 GetPackSize() const { return (Size + 0x1FF) & (~((UInt64)0x1FF)); }
|
||||
};
|
||||
|
||||
class CItemEx: public CItem
|
||||
struct CItemEx: public CItem
|
||||
{
|
||||
public:
|
||||
UInt64 HeaderPosition;
|
||||
UInt64 LongLinkSize;
|
||||
UInt64 GetDataPosition() const { return HeaderPosition + LongLinkSize + NFileHeader::kRecordSize; };
|
||||
UInt64 GetFullSize() const { return LongLinkSize + NFileHeader::kRecordSize + Size; };
|
||||
unsigned LongLinkSize;
|
||||
UInt64 GetDataPosition() const { return HeaderPosition + LongLinkSize + NFileHeader::kRecordSize; }
|
||||
UInt64 GetFullSize() const { return LongLinkSize + NFileHeader::kRecordSize + Size; }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -100,7 +100,7 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item)
|
||||
|
||||
RETURN_IF_NOT_TRUE(MakeOctalString12(cur, item.Size));
|
||||
cur += 12;
|
||||
RETURN_IF_NOT_TRUE(MakeOctalString12(cur, item.ModificationTime));
|
||||
RETURN_IF_NOT_TRUE(MakeOctalString12(cur, item.MTime));
|
||||
cur += 12;
|
||||
|
||||
memmove(cur, NFileHeader::kCheckSumBlanks, 8);
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace NTar {
|
||||
|
||||
HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
const CObjectVector<NArchive::NTar::CItemEx> &inputItems,
|
||||
const CObjectVector<CUpdateItemInfo> &updateItems,
|
||||
const CObjectVector<CUpdateItem> &updateItems,
|
||||
IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
COutArchive outArchive;
|
||||
@@ -29,11 +29,11 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
int i;
|
||||
for(i = 0; i < updateItems.Size(); i++)
|
||||
{
|
||||
const CUpdateItemInfo &updateItem = updateItems[i];
|
||||
if (updateItem.NewData)
|
||||
complexity += updateItem.Size;
|
||||
const CUpdateItem &ui = updateItems[i];
|
||||
if (ui.NewData)
|
||||
complexity += ui.Size;
|
||||
else
|
||||
complexity += inputItems[updateItem.IndexInArchive].GetFullSize();
|
||||
complexity += inputItems[ui.IndexInArchive].GetFullSize();
|
||||
}
|
||||
|
||||
RINOK(updateCallback->SetTotal(complexity));
|
||||
@@ -56,13 +56,13 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
lps->InSize = lps->OutSize = complexity;
|
||||
RINOK(lps->SetCur());
|
||||
|
||||
const CUpdateItemInfo &updateItem = updateItems[i];
|
||||
const CUpdateItem &ui = updateItems[i];
|
||||
CItem item;
|
||||
if (updateItem.NewProperties)
|
||||
if (ui.NewProperties)
|
||||
{
|
||||
item.Mode = 0777;
|
||||
item.Name = (updateItem.Name);
|
||||
if (updateItem.IsDirectory)
|
||||
item.Name = (ui.Name);
|
||||
if (ui.IsDir)
|
||||
{
|
||||
item.LinkFlag = NFileHeader::NLinkFlag::kDirectory;
|
||||
item.Size = 0;
|
||||
@@ -70,9 +70,9 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
else
|
||||
{
|
||||
item.LinkFlag = NFileHeader::NLinkFlag::kNormal;
|
||||
item.Size = updateItem.Size;
|
||||
item.Size = ui.Size;
|
||||
}
|
||||
item.ModificationTime = updateItem.Time;
|
||||
item.MTime = ui.Time;
|
||||
item.DeviceMajorDefined = false;
|
||||
item.DeviceMinorDefined = false;
|
||||
item.UID = 0;
|
||||
@@ -81,30 +81,30 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
}
|
||||
else
|
||||
{
|
||||
const CItemEx &existItemInfo = inputItems[updateItem.IndexInArchive];
|
||||
const CItemEx &existItemInfo = inputItems[ui.IndexInArchive];
|
||||
item = existItemInfo;
|
||||
}
|
||||
if (updateItem.NewData)
|
||||
if (ui.NewData)
|
||||
{
|
||||
item.Size = updateItem.Size;
|
||||
item.Size = ui.Size;
|
||||
if (item.Size == UInt64(Int64(-1)))
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
const CItemEx &existItemInfo = inputItems[updateItem.IndexInArchive];
|
||||
const CItemEx &existItemInfo = inputItems[ui.IndexInArchive];
|
||||
item.Size = existItemInfo.Size;
|
||||
}
|
||||
|
||||
if (updateItem.NewData)
|
||||
if (ui.NewData)
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> fileInStream;
|
||||
HRESULT res = updateCallback->GetStream(updateItem.IndexInClient, &fileInStream);
|
||||
HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);
|
||||
if (res != S_FALSE)
|
||||
{
|
||||
RINOK(res);
|
||||
RINOK(outArchive.WriteHeader(item));
|
||||
if (!updateItem.IsDirectory)
|
||||
if (!ui.IsDir)
|
||||
{
|
||||
RINOK(copyCoder->Code(fileInStream, outStream, NULL, NULL, progress));
|
||||
if (copyCoderSpec->TotalSize != item.Size)
|
||||
@@ -112,14 +112,14 @@ HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
RINOK(outArchive.FillDataResidual(item.Size));
|
||||
}
|
||||
}
|
||||
complexity += updateItem.Size;
|
||||
complexity += ui.Size;
|
||||
RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
|
||||
}
|
||||
else
|
||||
{
|
||||
const CItemEx &existItemInfo = inputItems[updateItem.IndexInArchive];
|
||||
const CItemEx &existItemInfo = inputItems[ui.IndexInArchive];
|
||||
UInt64 size;
|
||||
if (updateItem.NewProperties)
|
||||
if (ui.NewProperties)
|
||||
{
|
||||
RINOK(outArchive.WriteHeader(item));
|
||||
RINOK(inStream->Seek(existItemInfo.GetDataPosition(), STREAM_SEEK_SET, NULL));
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace NArchive {
|
||||
namespace NTar {
|
||||
|
||||
struct CUpdateItemInfo
|
||||
struct CUpdateItem
|
||||
{
|
||||
bool NewData;
|
||||
bool NewProperties;
|
||||
@@ -19,12 +19,12 @@ struct CUpdateItemInfo
|
||||
UInt32 Time;
|
||||
UInt64 Size;
|
||||
AString Name;
|
||||
bool IsDirectory;
|
||||
bool IsDir;
|
||||
};
|
||||
|
||||
HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
|
||||
const CObjectVector<CItemEx> &inputItems,
|
||||
const CObjectVector<CUpdateItemInfo> &updateItems,
|
||||
const CObjectVector<CUpdateItem> &updateItems,
|
||||
IArchiveUpdateCallback *updateCallback);
|
||||
|
||||
}}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.6 KiB |
Reference in New Issue
Block a user