Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2007-01-20 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:15:49 +0300
commitd9666cf046a8453b33b3e2fbf4d82295a9f87df3 (patch)
treec722ed19b844b53042aec0c1d7d2f8381140a5ed /CPP/7zip/Archive/Tar
parent804edc5756fede54dbb1aefda6d39d306111938d (diff)
4.44 beta
Diffstat (limited to 'CPP/7zip/Archive/Tar')
-rwxr-xr-xCPP/7zip/Archive/Tar/DllExports.cpp86
-rwxr-xr-xCPP/7zip/Archive/Tar/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Tar/StdAfx.h9
-rwxr-xr-xCPP/7zip/Archive/Tar/Tar.dsp297
-rwxr-xr-xCPP/7zip/Archive/Tar/Tar.dsw29
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHandler.cpp282
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHandler.h56
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHandlerOut.cpp126
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHeader.cpp25
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHeader.h99
-rwxr-xr-xCPP/7zip/Archive/Tar/TarIn.cpp248
-rwxr-xr-xCPP/7zip/Archive/Tar/TarIn.h30
-rwxr-xr-xCPP/7zip/Archive/Tar/TarItem.h69
-rwxr-xr-xCPP/7zip/Archive/Tar/TarOut.cpp191
-rwxr-xr-xCPP/7zip/Archive/Tar/TarOut.h28
-rwxr-xr-xCPP/7zip/Archive/Tar/TarUpdate.cpp162
-rwxr-xr-xCPP/7zip/Archive/Tar/TarUpdate.h36
-rwxr-xr-xCPP/7zip/Archive/Tar/makefile59
-rwxr-xr-xCPP/7zip/Archive/Tar/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/Tar/tar.icobin0 -> 3638 bytes
20 files changed, 1840 insertions, 0 deletions
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<IInArchive> inArchive = (IInArchive *)temp;
+ *outObject = inArchive.Detach();
+ }
+ else
+ {
+ CMyComPtr<IOutArchive> 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<ICompressCoder> copyCoder;
+
+ for(i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+ {
+ RINOK(extractCallback->SetCompleted(&currentTotalSize));
+ CMyComPtr<ISequentialOutStream> 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<ISequentialInStream> inStream(streamSpec);
+ streamSpec->SetStream(_inStream);
+ streamSpec->Init(item.Size);
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, false);
+
+
+ CLocalCompressProgressInfo *localCompressProgressSpec =
+ new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+ localCompressProgressSpec->Init(progress,
+ &currentTotalSize, &currentTotalSize);
+
+ 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<CItemEx> _items;
+ CMyComPtr<IInStream> _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<CUpdateItemInfo> 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<IInStream> 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 <time.h>
+
+#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<ISequentialOutStream> 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<ICompressCoder> 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<NArchive::NTar::CItemEx> &inputItems,
+ const CObjectVector<CUpdateItemInfo> &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<ICompressProgressInfo> localProgress = localProgressSpec;
+ localProgressSpec->Init(updateCallback, true);
+
+ CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> 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<ISequentialInStream> 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<CLimitedSequentialInStream> 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<CItemEx> &inputItems,
+ const CObjectVector<CUpdateItemInfo> &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
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/tar.ico
Binary files differ