5 #include "Common/ComTry.h"
\r
6 #include "Common/StringConvert.h"
\r
8 #include "Windows/PropVariant.h"
\r
9 #include "Windows/Time.h"
\r
11 #include "TarHandler.h"
\r
12 #include "TarUpdate.h"
\r
14 using namespace NWindows;
\r
16 namespace NArchive {
\r
19 STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
\r
21 *type = NFileTimeType::kUnix;
\r
25 static HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res)
\r
27 NCOM::CPropVariant prop;
\r
28 RINOK(callback->GetProperty(index, propId, &prop));
\r
29 if (prop.vt == VT_BSTR)
\r
30 res = UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP);
\r
31 else if (prop.vt != VT_EMPTY)
\r
32 return E_INVALIDARG;
\r
36 STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
\r
37 IArchiveUpdateCallback *callback)
\r
40 if ((_stream && !_errorMessage.IsEmpty()) || _seqStream)
\r
42 CObjectVector<CUpdateItem> updateItems;
\r
43 for (UInt32 i = 0; i < numItems; i++)
\r
48 UInt32 indexInArchive;
\r
51 RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
\r
52 ui.NewProps = IntToBool(newProps);
\r
53 ui.NewData = IntToBool(newData);
\r
54 ui.IndexInArchive = indexInArchive;
\r
55 ui.IndexInClient = i;
\r
57 if (IntToBool(newProps))
\r
60 NCOM::CPropVariant prop;
\r
61 RINOK(callback->GetProperty(i, kpidIsDir, &prop));
\r
62 if (prop.vt == VT_EMPTY)
\r
64 else if (prop.vt != VT_BOOL)
\r
65 return E_INVALIDARG;
\r
67 ui.IsDir = (prop.boolVal != VARIANT_FALSE);
\r
71 NCOM::CPropVariant prop;
\r
72 RINOK(callback->GetProperty(i, kpidPosixAttrib, &prop));
\r
73 if (prop.vt == VT_EMPTY)
\r
74 ui.Mode = 0777 | (ui.IsDir ? 0040000 : 0100000);
\r
75 else if (prop.vt != VT_UI4)
\r
76 return E_INVALIDARG;
\r
78 ui.Mode = prop.ulVal;
\r
81 NCOM::CPropVariant prop;
\r
82 RINOK(callback->GetProperty(i, kpidMTime, &prop));
\r
83 if (prop.vt == VT_EMPTY)
\r
85 else if (prop.vt != VT_FILETIME)
\r
86 return E_INVALIDARG;
\r
87 else if (!NTime::FileTimeToUnixTime(prop.filetime, ui.Time))
\r
91 NCOM::CPropVariant prop;
\r
92 RINOK(callback->GetProperty(i, kpidPath, &prop));
\r
93 if (prop.vt == VT_BSTR)
\r
94 ui.Name = UnicodeStringToMultiByte(NItemName::MakeLegalName(prop.bstrVal), CP_OEMCP);
\r
95 else if (prop.vt != VT_EMPTY)
\r
96 return E_INVALIDARG;
\r
100 RINOK(GetPropString(callback, i, kpidUser, ui.User));
\r
101 RINOK(GetPropString(callback, i, kpidGroup, ui.Group));
\r
103 if (IntToBool(newData))
\r
105 NCOM::CPropVariant prop;
\r
106 RINOK(callback->GetProperty(i, kpidSize, &prop));
\r
107 if (prop.vt != VT_UI8)
\r
108 return E_INVALIDARG;
\r
109 ui.Size = prop.uhVal.QuadPart;
\r
111 // now we support GNU extension for big files
\r
112 if (ui.Size >= ((UInt64)1 << 33))
\r
113 return E_INVALIDARG;
\r
116 updateItems.Add(ui);
\r
118 return UpdateArchive(_stream, outStream, _items, updateItems, callback);
\r