4.59 beta

This commit is contained in:
Igor Pavlov
2008-08-13 00:00:00 +00:00
committed by Kornel Lesiński
parent 3901bf0ab8
commit 173c07e166
781 changed files with 22124 additions and 13650 deletions

View File

@@ -1,3 +0,0 @@
// StdAfx.cpp
#include "StdAfx.h"

View File

@@ -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));
}

View File

@@ -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;

View File

@@ -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
}

View File

@@ -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

View File

@@ -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

View File

@@ -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)));
}
}}

View File

@@ -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

View File

@@ -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; }
};
}}

View File

@@ -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);

View File

@@ -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));

View File

@@ -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);
}}

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB