summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/unix/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/7zip/unix/CPP/7zip/Archive/Tar/TarHandlerOut.cpp')
-rw-r--r--src/libs/7zip/unix/CPP/7zip/Archive/Tar/TarHandlerOut.cpp122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
new file mode 100644
index 000000000..ffdf2b136
--- /dev/null
+++ b/src/libs/7zip/unix/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
@@ -0,0 +1,122 @@
+// TarHandlerOut.cpp
+
+#include "StdAfx.h"
+
+#include "Common/ComTry.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "TarHandler.h"
+#include "TarUpdate.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NTar {
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
+{
+ *type = NFileTimeType::kUnix;
+ return S_OK;
+}
+
+static HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res)
+{
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(index, propId, &prop));
+ if (prop.vt == VT_BSTR)
+ res = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP);
+ else if (prop.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *callback)
+{
+ COM_TRY_BEGIN
+ if ((_stream && !_errorMessage.IsEmpty()) || _seqStream)
+ return E_NOTIMPL;
+ CObjectVector<CUpdateItem> updateItems;
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ CUpdateItem ui;
+ Int32 newData;
+ Int32 newProps;
+ UInt32 indexInArchive;
+ if (!callback)
+ return E_FAIL;
+ RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
+ ui.NewProps = IntToBool(newProps);
+ ui.NewData = IntToBool(newData);
+ ui.IndexInArchive = indexInArchive;
+ ui.IndexInClient = i;
+
+ if (IntToBool(newProps))
+ {
+ {
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidIsDir, &prop));
+ if (prop.vt == VT_EMPTY)
+ ui.IsDir = false;
+ else if (prop.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ ui.IsDir = (prop.boolVal != VARIANT_FALSE);
+ }
+
+ {
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidPosixAttrib, &prop));
+ if (prop.vt == VT_EMPTY)
+ ui.Mode = 0777 | (ui.IsDir ? 0040000 : 0100000);
+ else if (prop.vt != VT_UI4)
+ return E_INVALIDARG;
+ else
+ ui.Mode = prop.ulVal;
+ }
+ {
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidMTime, &prop));
+ if (prop.vt == VT_EMPTY)
+ ui.Time = 0;
+ else if (prop.vt != VT_FILETIME)
+ return E_INVALIDARG;
+ else if (!NTime::FileTimeToUnixTime(prop.filetime, ui.Time))
+ ui.Time = 0;
+ }
+ {
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidPath, &prop));
+ if (prop.vt == VT_BSTR)
+ ui.Name = UnicodeStringToMultiByte(NItemName::MakeLegalName(prop.bstrVal), CP_OEMCP);
+ else if (prop.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ if (ui.IsDir)
+ ui.Name += '/';
+ }
+ RINOK(GetPropString(callback, i, kpidUser, ui.User));
+ RINOK(GetPropString(callback, i, kpidGroup, ui.Group));
+ }
+ if (IntToBool(newData))
+ {
+ NCOM::CPropVariant prop;
+ RINOK(callback->GetProperty(i, kpidSize, &prop));
+ if (prop.vt != VT_UI8)
+ return E_INVALIDARG;
+ ui.Size = prop.uhVal.QuadPart;
+ /*
+ // now we support GNU extension for big files
+ if (ui.Size >= ((UInt64)1 << 33))
+ return E_INVALIDARG;
+ */
+ }
+ updateItems.Add(ui);
+ }
+ return UpdateArchive(_stream, outStream, _items, updateItems, callback);
+ COM_TRY_END
+}
+
+}}