From d9666cf046a8453b33b3e2fbf4d82295a9f87df3 Mon Sep 17 00:00:00 2001 From: Igor Pavlov Date: Sat, 20 Jan 2007 00:00:00 +0000 Subject: 4.44 beta --- CPP/7zip/Archive/Tar/DllExports.cpp | 86 ++++++++++ CPP/7zip/Archive/Tar/StdAfx.cpp | 3 + CPP/7zip/Archive/Tar/StdAfx.h | 9 + CPP/7zip/Archive/Tar/Tar.dsp | 297 +++++++++++++++++++++++++++++++++ CPP/7zip/Archive/Tar/Tar.dsw | 29 ++++ CPP/7zip/Archive/Tar/TarHandler.cpp | 282 +++++++++++++++++++++++++++++++ CPP/7zip/Archive/Tar/TarHandler.h | 56 +++++++ CPP/7zip/Archive/Tar/TarHandlerOut.cpp | 126 ++++++++++++++ CPP/7zip/Archive/Tar/TarHeader.cpp | 25 +++ CPP/7zip/Archive/Tar/TarHeader.h | 99 +++++++++++ CPP/7zip/Archive/Tar/TarIn.cpp | 248 +++++++++++++++++++++++++++ CPP/7zip/Archive/Tar/TarIn.h | 30 ++++ CPP/7zip/Archive/Tar/TarItem.h | 69 ++++++++ CPP/7zip/Archive/Tar/TarOut.cpp | 191 +++++++++++++++++++++ CPP/7zip/Archive/Tar/TarOut.h | 28 ++++ CPP/7zip/Archive/Tar/TarUpdate.cpp | 162 ++++++++++++++++++ CPP/7zip/Archive/Tar/TarUpdate.h | 36 ++++ CPP/7zip/Archive/Tar/makefile | 59 +++++++ CPP/7zip/Archive/Tar/resource.rc | 5 + CPP/7zip/Archive/Tar/tar.ico | Bin 0 -> 3638 bytes 20 files changed, 1840 insertions(+) create mode 100755 CPP/7zip/Archive/Tar/DllExports.cpp create mode 100755 CPP/7zip/Archive/Tar/StdAfx.cpp create mode 100755 CPP/7zip/Archive/Tar/StdAfx.h create mode 100755 CPP/7zip/Archive/Tar/Tar.dsp create mode 100755 CPP/7zip/Archive/Tar/Tar.dsw create mode 100755 CPP/7zip/Archive/Tar/TarHandler.cpp create mode 100755 CPP/7zip/Archive/Tar/TarHandler.h create mode 100755 CPP/7zip/Archive/Tar/TarHandlerOut.cpp create mode 100755 CPP/7zip/Archive/Tar/TarHeader.cpp create mode 100755 CPP/7zip/Archive/Tar/TarHeader.h create mode 100755 CPP/7zip/Archive/Tar/TarIn.cpp create mode 100755 CPP/7zip/Archive/Tar/TarIn.h create mode 100755 CPP/7zip/Archive/Tar/TarItem.h create mode 100755 CPP/7zip/Archive/Tar/TarOut.cpp create mode 100755 CPP/7zip/Archive/Tar/TarOut.h create mode 100755 CPP/7zip/Archive/Tar/TarUpdate.cpp create mode 100755 CPP/7zip/Archive/Tar/TarUpdate.h create mode 100755 CPP/7zip/Archive/Tar/makefile create mode 100755 CPP/7zip/Archive/Tar/resource.rc create mode 100755 CPP/7zip/Archive/Tar/tar.ico (limited to 'CPP/7zip/Archive/Tar') diff --git a/CPP/7zip/Archive/Tar/DllExports.cpp b/CPP/7zip/Archive/Tar/DllExports.cpp new file mode 100755 index 00000000..afa2fd24 --- /dev/null +++ b/CPP/7zip/Archive/Tar/DllExports.cpp @@ -0,0 +1,86 @@ +// DLLExports.cpp + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" +#include "Common/ComTry.h" +#include "Windows/PropVariant.h" +#include "../../ICoder.h" +#include "TarHandler.h" + +// {23170F69-40C1-278A-1000-000110EE0000} +DEFINE_GUID(CLSID_CTarHandler, + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEE, 0x00, 0x00); + +extern "C" +BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /* lpReserved */) +{ + return TRUE; +} + +STDAPI CreateObject( + const GUID *classID, + const GUID *interfaceID, + void **outObject) +{ + COM_TRY_BEGIN + *outObject = 0; + if (*classID != CLSID_CTarHandler) + return CLASS_E_CLASSNOTAVAILABLE; + int needIn = *interfaceID == IID_IInArchive; + int needOut = *interfaceID == IID_IOutArchive; + if (needIn || needOut) + { + NArchive::NTar::CHandler *temp = new NArchive::NTar::CHandler; + if (needIn) + { + CMyComPtr inArchive = (IInArchive *)temp; + *outObject = inArchive.Detach(); + } + else + { + CMyComPtr outArchive = (IOutArchive *)temp; + *outObject = outArchive.Detach(); + } + } + else + return E_NOINTERFACE; + COM_TRY_END + return S_OK; +} + +STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant propVariant; + switch(propID) + { + case NArchive::kName: + propVariant = L"Tar"; + break; + case NArchive::kClassID: + { + if ((value->bstrVal = ::SysAllocStringByteLen( + (const char *)&CLSID_CTarHandler, sizeof(GUID))) != 0) + value->vt = VT_BSTR; + return S_OK; + } + case NArchive::kExtension: + propVariant = L"tar"; + break; + case NArchive::kUpdate: + propVariant = true; + break; + case NArchive::kKeepName: + propVariant = false; + break; + case NArchive::kStartSignature: + { + const unsigned char sig[] = { 'u', 's', 't', 'a', 'r' }; + if ((value->bstrVal = ::SysAllocStringByteLen((const char *)sig, 5)) != 0) + value->vt = VT_BSTR; + return S_OK; + } + } + propVariant.Detach(value); + return S_OK; +} diff --git a/CPP/7zip/Archive/Tar/StdAfx.cpp b/CPP/7zip/Archive/Tar/StdAfx.cpp new file mode 100755 index 00000000..d0feea85 --- /dev/null +++ b/CPP/7zip/Archive/Tar/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Archive/Tar/StdAfx.h b/CPP/7zip/Archive/Tar/StdAfx.h new file mode 100755 index 00000000..2e4be10b --- /dev/null +++ b/CPP/7zip/Archive/Tar/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" +#include "../../../Common/NewHandler.h" + +#endif diff --git a/CPP/7zip/Archive/Tar/Tar.dsp b/CPP/7zip/Archive/Tar/Tar.dsp new file mode 100755 index 00000000..c01e7383 --- /dev/null +++ b/CPP/7zip/Archive/Tar/Tar.dsp @@ -0,0 +1,297 @@ +# Microsoft Developer Studio Project File - Name="Tar" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=Tar - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Tar.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Tar.mak" CFG="Tar - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Tar - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Tar - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Tar - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /YX /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-Zip\Formats\tar.dll" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "Tar - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-Zip\Formats\tar.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "Tar - Win32 Release" +# Name "Tar - Win32 Debug" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Archive.def +# End Source File +# Begin Source File + +SOURCE=.\DllExports.cpp +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=.\Tar.ico +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\Alloc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\String.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\String.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Vector.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Vector.h +# End Source File +# End Group +# Begin Group "Windows" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.h +# End Source File +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Copy\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Copy\CopyCoder.h +# End Source File +# End Group +# Begin Group "Engine" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\TarHandler.cpp +# End Source File +# Begin Source File + +SOURCE=.\TarHandler.h +# End Source File +# Begin Source File + +SOURCE=.\TarHandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=.\TarHeader.cpp +# End Source File +# Begin Source File + +SOURCE=.\TarHeader.h +# End Source File +# Begin Source File + +SOURCE=.\TarIn.cpp +# End Source File +# Begin Source File + +SOURCE=.\TarIn.h +# End Source File +# Begin Source File + +SOURCE=.\TarItem.h +# End Source File +# Begin Source File + +SOURCE=.\TarOut.cpp +# End Source File +# Begin Source File + +SOURCE=.\TarOut.h +# End Source File +# Begin Source File + +SOURCE=.\TarUpdate.cpp +# End Source File +# Begin Source File + +SOURCE=.\TarUpdate.h +# End Source File +# End Group +# Begin Group "Archive Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Common\ItemNameUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ItemNameUtils.h +# End Source File +# End Group +# Begin Group "7zip Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# End Group +# End Target +# End Project diff --git a/CPP/7zip/Archive/Tar/Tar.dsw b/CPP/7zip/Archive/Tar/Tar.dsw new file mode 100755 index 00000000..318cce1c --- /dev/null +++ b/CPP/7zip/Archive/Tar/Tar.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Tar"=.\Tar.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp new file mode 100755 index 00000000..9c2cd006 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp @@ -0,0 +1,282 @@ +// Tar/Handler.cpp + +#include "StdAfx.h" + +#include "TarHandler.h" +#include "TarIn.h" + +#include "Common/Defs.h" +#include "Common/StringConvert.h" +#include "Common/NewHandler.h" +#include "Common/ComTry.h" + +#include "Windows/Time.h" +#include "Windows/PropVariant.h" + +#include "../../Common/ProgressUtils.h" +#include "../../Common/LimitedStreams.h" +#include "../../Compress/Copy/CopyCoder.h" + +#include "../Common/ItemNameUtils.h" + +using namespace NWindows; +using namespace NTime; + +namespace NArchive { +namespace NTar { + +STATPROPSTG kProperties[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsFolder, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackedSize, VT_UI8}, + { NULL, kpidLastWriteTime, VT_FILETIME}, + { NULL, kpidUser, VT_BSTR}, + { NULL, kpidGroup, VT_BSTR}, +}; + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value) +{ + value->vt = VT_EMPTY; + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) +{ + *numProperties = sizeof(kProperties) / sizeof(kProperties[0]); + return S_OK; +} + +STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType) +{ + if(index >= sizeof(kProperties) / sizeof(kProperties[0])) + return E_INVALIDARG; + const STATPROPSTG &srcItem = kProperties[index]; + *propID = srcItem.propid; + *varType = srcItem.vt; + *name = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) +{ + *numProperties = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */, + BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) +{ + return E_INVALIDARG; +} + +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) + return S_FALSE; + + _inStream = stream; + } + /* + catch(...) + { + return S_FALSE; + } + */ + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Close() +{ + _items.Clear(); + _inStream.Release(); + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = _items.Size(); + return S_OK; +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant propVariant; + const NArchive::NTar::CItemEx &item = _items[index]; + + switch(propID) + { + case kpidPath: + propVariant = (const wchar_t *)NItemName::GetOSName2( + MultiByteToUnicodeString(item.Name, CP_OEMCP)); + break; + case kpidIsFolder: + propVariant = item.IsDirectory(); + break; + case kpidSize: + case kpidPackedSize: + propVariant = (UInt64)item.Size; + break; + case kpidLastWriteTime: + { + FILETIME utcFileTime; + if (item.ModificationTime != 0) + NTime::UnixTimeToFileTime((UInt32)item.ModificationTime, utcFileTime); + else + { + utcFileTime.dwLowDateTime = 0; + utcFileTime.dwHighDateTime = 0; + } + propVariant = utcFileTime; + break; + } + case kpidUser: + propVariant = (const wchar_t *) + MultiByteToUnicodeString(item.UserName, CP_OEMCP); + break; + case kpidGroup: + propVariant = (const wchar_t *) + MultiByteToUnicodeString(item.GroupName, CP_OEMCP); + break; + } + propVariant.Detach(value); + return S_OK; + COM_TRY_END +} + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool testMode = (_aTestMode != 0); + bool allFilesMode = (numItems == UInt32(-1)); + if (allFilesMode) + numItems = _items.Size(); + UInt64 totalSize = 0; + if(numItems == 0) + return S_OK; + UInt32 i; + for(i = 0; i < numItems; i++) + totalSize += _items[allFilesMode ? i : indices[i]].Size; + extractCallback->SetTotal(totalSize); + + UInt64 currentTotalSize = 0; + UInt64 currentItemSize; + + CMyComPtr copyCoder; + + for(i = 0; i < numItems; i++, currentTotalSize += currentItemSize) + { + RINOK(extractCallback->SetCompleted(¤tTotalSize)); + CMyComPtr realOutStream; + Int32 askMode; + 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()) + { + RINOK(extractCallback->PrepareOperation(askMode)); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; + } + if(!testMode && (!realOutStream)) + { + continue; + } + RINOK(extractCallback->PrepareOperation(askMode)); + { + if (testMode) + { + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + continue; + } + + RINOK(_inStream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL)); + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStream(streamSpec); + streamSpec->SetStream(_inStream); + streamSpec->Init(item.Size); + + CLocalProgress *localProgressSpec = new CLocalProgress; + CMyComPtr progress = localProgressSpec; + localProgressSpec->Init(extractCallback, false); + + + CLocalCompressProgressInfo *localCompressProgressSpec = + new CLocalCompressProgressInfo; + CMyComPtr compressProgress = localCompressProgressSpec; + localCompressProgressSpec->Init(progress, + ¤tTotalSize, ¤tTotalSize); + + if(!copyCoder) + { + copyCoder = new NCompress::CCopyCoder; + } + try + { + RINOK(copyCoder->Code(inStream, realOutStream, + NULL, NULL, compressProgress)); + } + catch(...) + { + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError)); + continue; + } + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + } + } + return S_OK; + COM_TRY_END +} + +}} diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h new file mode 100755 index 00000000..7b6e3a40 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarHandler.h @@ -0,0 +1,56 @@ +// Tar/Handler.h + +#ifndef __TAR_HANDLER_H +#define __TAR_HANDLER_H + +#include "Common/MyCom.h" +#include "../IArchive.h" + +#include "TarItem.h" + +namespace NArchive { +namespace NTar { + +class CHandler: + public IInArchive, + public IOutArchive, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP2( + IInArchive, + IOutArchive + ) + + STDMETHOD(Open)(IInStream *stream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openArchiveCallback); + STDMETHOD(Close)(); + STDMETHOD(GetNumberOfItems)(UInt32 *numItems); + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback); + + STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value); + + STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties); + STDMETHOD(GetPropertyInfo)(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType); + + STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties); + STDMETHOD(GetArchivePropertyInfo)(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType); + + // IOutArchive + STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback); + STDMETHOD(GetFileTimeType)(UInt32 *type); + +private: + CObjectVector _items; + CMyComPtr _inStream; +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp new file mode 100755 index 00000000..110833fb --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp @@ -0,0 +1,126 @@ +// Tar/HandlerOut.cpp + +#include "StdAfx.h" + +#include "Common/StringConvert.h" +#include "Common/ComTry.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../Common/ItemNameUtils.h" + +#include "TarHandler.h" +#include "TarUpdate.h" + +using namespace NWindows; +using namespace NCOM; +using namespace NTime; + +namespace NArchive { +namespace NTar { + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type) +{ + *type = NFileTimeType::kUnix; + return S_OK; +} + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback) +{ + COM_TRY_BEGIN + CObjectVector updateItems; + for(UInt32 i = 0; i < numItems; i++) + { + CUpdateItemInfo updateItem; + Int32 newData; + Int32 newProperties; + UInt32 indexInArchive; + if (!updateCallback) + return E_FAIL; + RINOK(updateCallback->GetUpdateItemInfo(i, + &newData, &newProperties, &indexInArchive)); + updateItem.NewProperties = IntToBool(newProperties); + updateItem.NewData = IntToBool(newData); + updateItem.IndexInArchive = indexInArchive; + updateItem.IndexInClient = i; + + if (IntToBool(newProperties)) + { + FILETIME utcTime; + UString name; + bool isDirectoryStatusDefined; + UInt32 attributes; + { + NCOM::CPropVariant propVariant; + RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant)); + if (propVariant.vt == VT_EMPTY) + attributes = 0; + else if (propVariant.vt != VT_UI4) + return E_INVALIDARG; + else + attributes = propVariant.ulVal; + } + { + NCOM::CPropVariant propVariant; + RINOK(updateCallback->GetProperty(i, kpidLastWriteTime, &propVariant)); + if (propVariant.vt != VT_FILETIME) + return E_INVALIDARG; + utcTime = propVariant.filetime; + } + { + NCOM::CPropVariant propVariant; + RINOK(updateCallback->GetProperty(i, kpidPath, &propVariant)); + if (propVariant.vt == VT_EMPTY) + name.Empty(); + else if (propVariant.vt != VT_BSTR) + return E_INVALIDARG; + else + name = propVariant.bstrVal; + } + { + NCOM::CPropVariant propVariant; + RINOK(updateCallback->GetProperty(i, kpidIsFolder, &propVariant)); + if (propVariant.vt == VT_EMPTY) + isDirectoryStatusDefined = false; + else if (propVariant.vt != VT_BOOL) + return E_INVALIDARG; + else + { + updateItem.IsDirectory = (propVariant.boolVal != VARIANT_FALSE); + isDirectoryStatusDefined = true; + } + } + updateItem.Name = UnicodeStringToMultiByte( + NItemName::MakeLegalName(name), CP_OEMCP); + if (!isDirectoryStatusDefined) + updateItem.IsDirectory = ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); + if (updateItem.IsDirectory) + updateItem.Name += '/'; + + if(!FileTimeToUnixTime(utcTime, updateItem.Time)) + { + updateItem.Time = 0; + // return E_INVALIDARG; + } + } + if (IntToBool(newData)) + { + UInt64 size; + { + NCOM::CPropVariant propVariant; + RINOK(updateCallback->GetProperty(i, kpidSize, &propVariant)); + if (propVariant.vt != VT_UI8) + return E_INVALIDARG; + size = propVariant.uhVal.QuadPart; + } + updateItem.Size = size; + } + updateItems.Add(updateItem); + } + return UpdateArchive(_inStream, outStream, _items, updateItems, updateCallback); + COM_TRY_END +} + +}} diff --git a/CPP/7zip/Archive/Tar/TarHeader.cpp b/CPP/7zip/Archive/Tar/TarHeader.cpp new file mode 100755 index 00000000..35f0d0cf --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarHeader.cpp @@ -0,0 +1,25 @@ +// Archive/Tar/Header.h + +#include "StdAfx.h" + +#include "TarHeader.h" + +namespace NArchive { +namespace NTar { +namespace NFileHeader { + + // The checksum field is filled with this while the checksum is computed. + const char *kCheckSumBlanks = " "; // 8 blanks, no null + + const char *kLongLink = "././@LongLink"; + const char *kLongLink2 = "@LongLink"; + + // The magic field is filled with this if uname and gname are valid. + namespace NMagic + { + const char *kUsTar = "ustar"; // 5 chars + const char *kGNUTar = "GNUtar "; // 7 chars and a null + const char *kEmpty = "\0\0\0\0\0\0\0\0"; // 7 chars and a null + } + +}}} diff --git a/CPP/7zip/Archive/Tar/TarHeader.h b/CPP/7zip/Archive/Tar/TarHeader.h new file mode 100755 index 00000000..0ab31e52 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarHeader.h @@ -0,0 +1,99 @@ +// Archive/Tar/Header.h + +#ifndef __ARCHIVE_TAR_HEADER_H +#define __ARCHIVE_TAR_HEADER_H + +#include "Common/Types.h" + +namespace NArchive { +namespace NTar { + +namespace NFileHeader +{ + const int kRecordSize = 512; + const int kNameSize = 100; + const int kUserNameSize = 32; + const int kGroupNameSize = 32; + const int kPrefixSize = 155; + + /* + struct CHeader + { + char Name[kNameSize]; + char Mode[8]; + char UID[8]; + char GID[8]; + char Size[12]; + char ModificationTime[12]; + char CheckSum[8]; + char LinkFlag; + char LinkName[kNameSize]; + char Magic[8]; + char UserName[kUserNameSize]; + char GroupName[kGroupNameSize]; + char DeviceMajor[8]; + char DeviceMinor[8]; + char Prefix[155]; + }; + union CRecord + { + CHeader Header; + Byte Padding[kRecordSize]; + }; + */ + + namespace NMode + { + const int kSetUID = 04000; // Set UID on execution + const int kSetGID = 02000; // Set GID on execution + const int kSaveText = 01000; // Save text (sticky bit) + } + + namespace NFilePermissions + { + const int kUserRead = 00400; // read by owner + const int kUserWrite = 00200; // write by owner + const int kUserExecute = 00100; // execute/search by owner + const int kGroupRead = 00040; // read by group + const int kGroupWrite = 00020; // write by group + const int kGroupExecute = 00010; // execute/search by group + const int kOtherRead = 00004; // read by other + const int kOtherWrite = 00002; // write by other + const int kOtherExecute = 00001; // execute/search by other + } + + + // The linkflag defines the type of file + namespace NLinkFlag + { + const char kOldNormal = '\0'; // Normal disk file, Unix compatible + 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 + const char kBlock = '4'; // Block special file + const char kDirectory = '5'; // Directory + const char kFIFO = '6'; // FIFO special file + const char kContiguous = '7'; // Contiguous file + } + // Further link types may be defined later. + + // The checksum field is filled with this while the checksum is computed. + extern const char *kCheckSumBlanks;// = " "; // 8 blanks, no null + + extern const char *kLongLink; // = "././@LongLink"; + extern const char *kLongLink2; // = "@LongLink"; + + // The magic field is filled with this if uname and gname are valid. + namespace NMagic + { + extern const char *kUsTar; // = "ustar"; // 5 chars + extern const char *kGNUTar; // = "GNUtar "; // 7 chars and a null + extern const char *kEmpty; // = "GNUtar "; // 7 chars and a null + } + +} + +}} + +#endif diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp new file mode 100755 index 00000000..86afc482 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarIn.cpp @@ -0,0 +1,248 @@ +// Archive/TarIn.cpp + +#include "StdAfx.h" + +#include "TarIn.h" +#include "TarHeader.h" + +#include "Common/StringToInt.h" +#include "Windows/Defs.h" + +#include "../../Common/StreamUtils.h" + +namespace NArchive { +namespace NTar { + +HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize) +{ + RINOK(ReadStream(m_Stream, data, size, &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++) + { + char c = src[i]; + dest[i] = c; + if (c == 0) + break; + } +} + +static bool OctalToNumber(const char *srcString, int size, UInt64 &res) +{ + char sz[32]; + MyStrNCpy(sz, srcString, size); + sz[size] = 0; + const char *end; + int i; + for (i = 0; sz[i] == ' '; i++); + res = ConvertOctStringToUInt64(sz + i, &end); + return (*end == ' ' || *end == 0); +} + +static bool OctalToNumber32(const char *srcString, int size, UInt32 &res) +{ + UInt64 res64; + if (!OctalToNumber(srcString, size, res64)) + return false; + res = (UInt32)res64; + return (res64 <= 0xFFFFFFFF); +} + +#define RIF(x) { if (!(x)) return S_FALSE; } + +static bool IsRecordLast(const char *record) +{ + for (int i = 0; i < NFileHeader::kRecordSize; i++) + if (record[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; +} + +static char GetHex(Byte value) +{ + return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10))); +} + +HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item) +{ + item.LongLinkSize = 0; + // NFileHeader::CRecord record; + char record[NFileHeader::kRecordSize]; + char *cur = record; + + filled = false; + + UInt32 processedSize; + item.HeaderPosition = m_Position; + RINOK(ReadBytes(record, NFileHeader::kRecordSize, processedSize)); + if (processedSize == 0 || + (processedSize == NFileHeader::kRecordSize && IsRecordLast(record))) + 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; + + 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(cur, 8, item.Mode)); + cur += 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; + + UInt32 checkSum; + RIF(OctalToNumber32(cur, 8, checkSum)); + memmove(cur, NFileHeader::kCheckSumBlanks, 8); + cur += 8; + + item.LinkFlag = *cur++; + + ReadString(cur, NFileHeader::kNameSize, item.LinkName); + cur += NFileHeader::kNameSize; + + memmove(item.Magic, cur, 8); + cur += 8; + + ReadString(cur, NFileHeader::kUserNameSize, item.UserName); + cur += NFileHeader::kUserNameSize; + ReadString(cur, NFileHeader::kUserNameSize, item.GroupName); + cur += 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; + + AString prefix; + ReadString(cur, NFileHeader::kPrefixSize, prefix); + cur += NFileHeader::kPrefixSize; + if (!prefix.IsEmpty() && item.IsMagic()) + 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]); + + if (checkSumReal != checkSum) + return S_FALSE; + + filled = true; + return S_OK; +} + +HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) +{ + RINOK(GetNextItemReal(filled, item)); + if (!filled) + return S_OK; + // GNUtar extension + if (item.LinkFlag == 'L') + { + if (item.Name.Compare(NFileHeader::kLongLink) != 0) + if (item.Name.Compare(NFileHeader::kLongLink2) != 0) + return S_FALSE; + UInt64 headerPosition = item.HeaderPosition; + + UInt32 processedSize; + AString fullName; + char *buffer = fullName.GetBuffer((UInt32)item.Size + 1); + RINOK(ReadBytes(buffer, (UInt32)item.Size, processedSize)); + buffer[item.Size] = '\0'; + fullName.ReleaseBuffer(); + if (processedSize != item.Size) + return S_FALSE; + RINOK(Skeep((0 - item.Size) & 0x1FF)); + RINOK(GetNextItemReal(filled, item)); + item.Name = fullName; + item.LongLinkSize = item.HeaderPosition - headerPosition; + item.HeaderPosition = headerPosition; + } + else if (item.LinkFlag == 'g' || item.LinkFlag == 'x') + { + // pax Extended Header + return S_OK; + } + else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0)) + return S_FALSE; + 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))); +} + +}} diff --git a/CPP/7zip/Archive/Tar/TarIn.h b/CPP/7zip/Archive/Tar/TarIn.h new file mode 100755 index 00000000..28781375 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarIn.h @@ -0,0 +1,30 @@ +// Archive/TarIn.h + +#ifndef __ARCHIVE_TAR_IN_H +#define __ARCHIVE_TAR_IN_H + +#include "Common/MyCom.h" +#include "../../IStream.h" + +#include "TarItem.h" + +namespace NArchive { +namespace NTar { + +class CInArchive +{ + CMyComPtr m_Stream; + UInt64 m_Position; + + HRESULT ReadBytes(void *data, UInt32 size, UInt32 &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); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h new file mode 100755 index 00000000..71fff7ba --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarItem.h @@ -0,0 +1,69 @@ +// Archive/Tar/Item.h + +#ifndef __ARCHIVE_TAR_ITEM_H +#define __ARCHIVE_TAR_ITEM_H + +#include + +#include "Common/Types.h" +#include "Common/String.h" + +#include "../Common/ItemNameUtils.h" +#include "TarHeader.h" + +namespace NArchive { +namespace NTar { + +class CItem +{ +public: + AString Name; + UInt32 Mode; + UInt32 UID; + UInt32 GID; + UInt64 Size; + UInt32 ModificationTime; + char LinkFlag; + AString LinkName; + char Magic[8]; + AString UserName; + AString GroupName; + + bool DeviceMajorDefined; + UInt32 DeviceMajor; + bool DeviceMinorDefined; + UInt32 DeviceMinor; + + bool IsDirectory() const + { + if (LinkFlag == NFileHeader::NLinkFlag::kDirectory) + return true; + if (LinkFlag == NFileHeader::NLinkFlag::kOldNormal || + LinkFlag == NFileHeader::NLinkFlag::kNormal) + { + return NItemName::HasTailSlash(Name, CP_OEMCP); + } + return false; + } + + bool IsMagic() const + { + for (int i = 0; i < 5; i++) + if (Magic[i] != NFileHeader::NMagic::kUsTar[i]) + return false; + return true; + } +}; + +class CItemEx: public CItem +{ +public: + UInt64 HeaderPosition; + UInt64 LongLinkSize; + UInt64 GetDataPosition() const { return HeaderPosition + LongLinkSize + NFileHeader::kRecordSize; }; + UInt64 GetFullSize() const { return LongLinkSize + NFileHeader::kRecordSize + Size; }; +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp new file mode 100755 index 00000000..e278edda --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarOut.cpp @@ -0,0 +1,191 @@ +// Archive/TarOut.cpp + +#include "StdAfx.h" + +#include "TarOut.h" +#include "TarHeader.h" + +#include "Common/IntToString.h" +#include "Windows/Defs.h" +#include "../../Common/StreamUtils.h" + +namespace NArchive { +namespace NTar { + +HRESULT COutArchive::WriteBytes(const void *buffer, UInt32 size) +{ + UInt32 processedSize; + RINOK(WriteStream(m_Stream, buffer, size, &processedSize)); + if(processedSize != size) + return E_FAIL; + return S_OK; +} + +void COutArchive::Create(ISequentialOutStream *outStream) +{ + m_Stream = outStream; +} + +static AString MakeOctalString(UInt64 value) +{ + char s[32]; + ConvertUInt64ToString(value, s, 8); + return AString(s) + ' '; +} + +static void MyStrNCpy(char *dest, const char *src, int size) +{ + for (int i = 0; i < size; i++) + { + char c = src[i]; + dest[i] = c; + if (c == 0) + break; + } +} + +static bool MakeOctalString8(char *s, UInt32 value) +{ + AString tempString = MakeOctalString(value); + + const int kMaxSize = 8; + if (tempString.Length() >= kMaxSize) + return false; + int numSpaces = kMaxSize - (tempString.Length() + 1); + for(int i = 0; i < numSpaces; i++) + s[i] = ' '; + MyStringCopy(s + numSpaces, (const char *)tempString); + return true; +} + +static bool MakeOctalString12(char *s, UInt64 value) +{ + AString tempString = MakeOctalString(value); + const int kMaxSize = 12; + if (tempString.Length() > kMaxSize) + return false; + int numSpaces = kMaxSize - tempString.Length(); + for(int i = 0; i < numSpaces; i++) + s[i] = ' '; + memmove(s + numSpaces, (const char *)tempString, tempString.Length()); + return true; +} + +static bool CopyString(char *dest, const AString &src, int maxSize) +{ + if (src.Length() >= maxSize) + return false; + MyStringCopy(dest, (const char *)src); + return true; +} + +#define RETURN_IF_NOT_TRUE(x) { if (!(x)) return E_FAIL; } + +HRESULT COutArchive::WriteHeaderReal(const CItem &item) +{ + char record[NFileHeader::kRecordSize]; + char *cur = record; + int i; + for (i = 0; i < NFileHeader::kRecordSize; i++) + record[i] = 0; + + // RETURN_IF_NOT_TRUE(CopyString(header.Name, item.Name, NFileHeader::kNameSize)); + if (item.Name.Length() > NFileHeader::kNameSize) + return E_FAIL; + MyStrNCpy(cur, item.Name, NFileHeader::kNameSize); + cur += NFileHeader::kNameSize; + + RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode)); + cur += 8; + RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID)); + cur += 8; + RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID)); + cur += 8; + + RETURN_IF_NOT_TRUE(MakeOctalString12(cur, item.Size)); + cur += 12; + RETURN_IF_NOT_TRUE(MakeOctalString12(cur, item.ModificationTime)); + cur += 12; + + memmove(cur, NFileHeader::kCheckSumBlanks, 8); + cur += 8; + + *cur++ = item.LinkFlag; + + RETURN_IF_NOT_TRUE(CopyString(cur, item.LinkName, NFileHeader::kNameSize)); + cur += NFileHeader::kNameSize; + + memmove(cur, item.Magic, 8); + cur += 8; + + RETURN_IF_NOT_TRUE(CopyString(cur, item.UserName, NFileHeader::kUserNameSize)); + cur += NFileHeader::kUserNameSize; + RETURN_IF_NOT_TRUE(CopyString(cur, item.GroupName, NFileHeader::kGroupNameSize)); + cur += NFileHeader::kUserNameSize; + + + if (item.DeviceMajorDefined) + RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMajor)); + cur += 8; + + if (item.DeviceMinorDefined) + RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMinor)); + cur += 8; + + + UInt32 checkSumReal = 0; + for(i = 0; i < NFileHeader::kRecordSize; i++) + checkSumReal += Byte(record[i]); + + RETURN_IF_NOT_TRUE(MakeOctalString8(record + 148, checkSumReal)); + + return WriteBytes(record, NFileHeader::kRecordSize); +} + +HRESULT COutArchive::WriteHeader(const CItem &item) +{ + int nameSize = item.Name.Length(); + if (nameSize < NFileHeader::kNameSize) + return WriteHeaderReal(item); + + CItem modifiedItem = item; + int nameStreamSize = nameSize + 1; + modifiedItem.Size = nameStreamSize; + modifiedItem.LinkFlag = 'L'; + modifiedItem.Name = NFileHeader::kLongLink; + modifiedItem.LinkName.Empty(); + RINOK(WriteHeaderReal(modifiedItem)); + RINOK(WriteBytes(item.Name, nameStreamSize)); + RINOK(FillDataResidual(nameStreamSize)); + + modifiedItem = item; + modifiedItem.Name = item.Name.Left(NFileHeader::kNameSize - 1); + return WriteHeaderReal(modifiedItem); +} + +HRESULT COutArchive::FillDataResidual(UInt64 dataSize) +{ + UInt32 lastRecordSize = UInt32(dataSize & (NFileHeader::kRecordSize - 1)); + if (lastRecordSize == 0) + return S_OK; + UInt32 residualSize = NFileHeader::kRecordSize - lastRecordSize; + Byte residualBytes[NFileHeader::kRecordSize]; + for (UInt32 i = 0; i < residualSize; i++) + residualBytes[i] = 0; + return WriteBytes(residualBytes, residualSize); +} + +HRESULT COutArchive::WriteFinishHeader() +{ + Byte record[NFileHeader::kRecordSize]; + int i; + for (i = 0; i < NFileHeader::kRecordSize; i++) + record[i] = 0; + for (i = 0; i < 2; i++) + { + RINOK(WriteBytes(record, NFileHeader::kRecordSize)); + } + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Tar/TarOut.h b/CPP/7zip/Archive/Tar/TarOut.h new file mode 100755 index 00000000..ef837869 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarOut.h @@ -0,0 +1,28 @@ +// Archive/TarOut.h + +#ifndef __ARCHIVE_TAR_OUT_H +#define __ARCHIVE_TAR_OUT_H + +#include "TarItem.h" + +#include "Common/MyCom.h" +#include "../../IStream.h" + +namespace NArchive { +namespace NTar { + +class COutArchive +{ + CMyComPtr m_Stream; + HRESULT WriteBytes(const void *buffer, UInt32 size); +public: + void Create(ISequentialOutStream *outStream); + HRESULT WriteHeaderReal(const CItem &item); + HRESULT WriteHeader(const CItem &item); + HRESULT FillDataResidual(UInt64 dataSize); + HRESULT WriteFinishHeader(); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp new file mode 100755 index 00000000..9a6f64e2 --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp @@ -0,0 +1,162 @@ +// TarUpdate.cpp + +#include "StdAfx.h" + +#include "Common/Defs.h" +#include "Common/StringConvert.h" +#include "Windows/Defs.h" + +#include "../../Common/ProgressUtils.h" +#include "../../Common/LimitedStreams.h" +#include "../../Compress/Copy/CopyCoder.h" + +#include "TarOut.h" +#include "TarUpdate.h" + +static const UInt64 kOneItemComplexity = 512; + +namespace NArchive { +namespace NTar { + +static HRESULT CopyBlock(ISequentialInStream *inStream, + ISequentialOutStream *outStream, ICompressProgressInfo *progress, + UInt64 *totalSize = NULL) +{ + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; + CMyComPtr copyCoder = copyCoderSpec; + HRESULT result = copyCoder->Code(inStream, outStream, NULL, NULL, progress); + if (totalSize != NULL) + *totalSize = copyCoderSpec->TotalSize; + return result; +} + +HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, + const CObjectVector &inputItems, + const CObjectVector &updateItems, + IArchiveUpdateCallback *updateCallback) +{ + COutArchive outArchive; + outArchive.Create(outStream); + + UInt64 complexity = 0; + + int i; + for(i = 0; i < updateItems.Size(); i++) + { + const CUpdateItemInfo &updateItem = updateItems[i]; + if (updateItem.NewData) + complexity += updateItem.Size; + else + complexity += inputItems[updateItem.IndexInArchive].GetFullSize(); + complexity += kOneItemComplexity; + } + + RINOK(updateCallback->SetTotal(complexity)); + + complexity = 0; + + for(i = 0; i < updateItems.Size(); i++) + { + RINOK(updateCallback->SetCompleted(&complexity)); + + CLocalProgress *localProgressSpec = new CLocalProgress; + CMyComPtr localProgress = localProgressSpec; + localProgressSpec->Init(updateCallback, true); + + CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo; + CMyComPtr compressProgress = localCompressProgressSpec; + + localCompressProgressSpec->Init(localProgress, &complexity, NULL); + + const CUpdateItemInfo &updateItem = updateItems[i]; + CItem item; + if (updateItem.NewProperties) + { + item.Mode = 0777; + item.Name = (updateItem.Name); + if (updateItem.IsDirectory) + { + item.LinkFlag = NFileHeader::NLinkFlag::kDirectory; + item.Size = 0; + } + else + { + item.LinkFlag = NFileHeader::NLinkFlag::kNormal; + item.Size = updateItem.Size; + } + item.ModificationTime = updateItem.Time; + item.DeviceMajorDefined = false; + item.DeviceMinorDefined = false; + item.UID = 0; + item.GID = 0; + memmove(item.Magic, NFileHeader::NMagic::kEmpty, 8); + } + else + { + const CItemEx &existItemInfo = inputItems[updateItem.IndexInArchive]; + item = existItemInfo; + } + if (updateItem.NewData) + { + item.Size = updateItem.Size; + if (item.Size == UInt64(Int64(-1))) + return E_INVALIDARG; + } + else + { + const CItemEx &existItemInfo = inputItems[updateItem.IndexInArchive]; + item.Size = existItemInfo.Size; + } + + if (updateItem.NewData) + { + CMyComPtr fileInStream; + HRESULT res = updateCallback->GetStream(updateItem.IndexInClient, &fileInStream); + if (res != S_FALSE) + { + RINOK(res); + RINOK(outArchive.WriteHeader(item)); + if (!updateItem.IsDirectory) + { + UInt64 totalSize; + RINOK(CopyBlock(fileInStream, outStream, compressProgress, &totalSize)); + if (totalSize != item.Size) + return E_FAIL; + RINOK(outArchive.FillDataResidual(item.Size)); + } + } + complexity += updateItem.Size; + RINOK(updateCallback->SetOperationResult( + NArchive::NUpdate::NOperationResult::kOK)); + } + else + { + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr inStreamLimited(streamSpec); + const CItemEx &existItemInfo = inputItems[updateItem.IndexInArchive]; + if (updateItem.NewProperties) + { + RINOK(outArchive.WriteHeader(item)); + RINOK(inStream->Seek(existItemInfo.GetDataPosition(), + STREAM_SEEK_SET, NULL)); + streamSpec->SetStream(inStream); + streamSpec->Init(existItemInfo.Size); + } + else + { + RINOK(inStream->Seek(existItemInfo.HeaderPosition, + STREAM_SEEK_SET, NULL)); + streamSpec->SetStream(inStream); + streamSpec->Init(existItemInfo.GetFullSize()); + } + RINOK(CopyBlock(inStreamLimited, outStream, compressProgress)); + RINOK(outArchive.FillDataResidual(existItemInfo.Size)); + complexity += existItemInfo.GetFullSize(); + } + complexity += kOneItemComplexity; + } + return outArchive.WriteFinishHeader(); +} + +}} + diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h new file mode 100755 index 00000000..92f5cebb --- /dev/null +++ b/CPP/7zip/Archive/Tar/TarUpdate.h @@ -0,0 +1,36 @@ +// Tar/Update.h + +#ifndef __TAR_UPDATE_H +#define __TAR_UPDATE_H + +#include "Common/Vector.h" +#include "Common/Types.h" +#include "Common/String.h" + +#include "../IArchive.h" +#include "TarItem.h" + +namespace NArchive { +namespace NTar { + +struct CUpdateItemInfo +{ + bool NewData; + bool NewProperties; + int IndexInArchive; + int IndexInClient; + + UInt32 Time; + UInt64 Size; + AString Name; + bool IsDirectory; +}; + +HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream, + const CObjectVector &inputItems, + const CObjectVector &updateItems, + IArchiveUpdateCallback *updateCallback); + +}} + +#endif diff --git a/CPP/7zip/Archive/Tar/makefile b/CPP/7zip/Archive/Tar/makefile new file mode 100755 index 00000000..f892c303 --- /dev/null +++ b/CPP/7zip/Archive/Tar/makefile @@ -0,0 +1,59 @@ +PROG = tar.dll +DEF_FILE = ../Archive.def +CFLAGS = $(CFLAGS) -I ../../../ +LIBS = $(LIBS) oleaut32.lib user32.lib + +TAR_OBJS = \ + $O\DllExports.obj \ + $O\TarHandler.obj \ + $O\TarHandlerOut.obj \ + $O\TarHeader.obj \ + $O\TarIn.obj \ + $O\TarOut.obj \ + $O\TarUpdate.obj \ + +COMMON_OBJS = \ + $O\Alloc.obj \ + $O\IntToString.obj \ + $O\NewHandler.obj \ + $O\String.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\Vector.obj \ + +WIN_OBJS = \ + $O\PropVariant.obj \ + +7ZIP_COMMON_OBJS = \ + $O\LimitedStreams.obj \ + $O\ProgressUtils.obj \ + $O\StreamUtils.obj \ + +AR_COMMON_OBJS = \ + $O\ItemNameUtils.obj \ + +OBJS = \ + $O\StdAfx.obj \ + $(TAR_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ + $(COMPRESS_TAR_OBJS) \ + $O\CopyCoder.obj \ + $O\resource.res + +!include "../../../Build.mak" + +$(TAR_OBJS): $(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../Common/$(*B).cpp + $(COMPL) +$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp + $(COMPL) diff --git a/CPP/7zip/Archive/Tar/resource.rc b/CPP/7zip/Archive/Tar/resource.rc new file mode 100755 index 00000000..3d37f440 --- /dev/null +++ b/CPP/7zip/Archive/Tar/resource.rc @@ -0,0 +1,5 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_DLL("Tar Plugin", "tar") + +101 ICON "tar.ico" diff --git a/CPP/7zip/Archive/Tar/tar.ico b/CPP/7zip/Archive/Tar/tar.ico new file mode 100755 index 00000000..6835885b Binary files /dev/null and b/CPP/7zip/Archive/Tar/tar.ico differ -- cgit v1.2.3