This commit is contained in:
Igor Pavlov
2022-06-23 11:43:16 +01:00
committed by Kornel
parent c3529a41f5
commit ec44a8a070
1248 changed files with 15242 additions and 2443 deletions

209
CPP/7zip/Archive/Tar/TarHandlerOut.cpp Normal file → Executable file
View File

@@ -2,15 +2,16 @@
#include "StdAfx.h"
// #include <stdio.h>
#include "../../../Common/ComTry.h"
#include "../../../Common/Defs.h"
#include "../../../Common/MyLinux.h"
#include "../../../Common/StringConvert.h"
#include "../../../Common/UTFConvert.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Windows/TimeUtils.h"
#include "../Common/ItemNameUtils.h"
#include "TarHandler.h"
#include "TarUpdate.h"
@@ -21,10 +22,35 @@ namespace NTar {
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
{
*type = NFileTimeType::kUnix;
UInt32 t = NFileTimeType::kUnix;
const UInt32 prec = _handlerTimeOptions.Prec;
if (prec != (UInt32)(Int32)-1)
{
t = NFileTimeType::kWindows;
if (prec == k_PropVar_TimePrec_0 ||
prec == k_PropVar_TimePrec_100ns)
t = NFileTimeType::kWindows;
else if (prec == k_PropVar_TimePrec_HighPrec)
t = k_PropVar_TimePrec_1ns;
else if (prec >= k_PropVar_TimePrec_Base)
t = prec;
}
// 7-Zip before 22.00 fails, if unknown typeType.
*type = t;
return S_OK;
}
void Get_AString_From_UString(const UString &s, AString &res,
UINT codePage, unsigned utfFlags)
{
if (codePage == CP_UTF8)
ConvertUnicodeToUTF8_Flags(s, res, utfFlags);
else
UnicodeStringToMultiByte2(res, s, codePage);
}
HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res,
UINT codePage, unsigned utfFlags, bool convertSlash)
{
@@ -36,14 +62,7 @@ HRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID pro
UString s = prop.bstrVal;
if (convertSlash)
NItemName::ReplaceSlashes_OsToUnix(s);
if (codePage == CP_UTF8)
{
ConvertUnicodeToUTF8_Flags(s, res, utfFlags);
// if (!ConvertUnicodeToUTF8(s, res)) // return E_INVALIDARG;
}
else
UnicodeStringToMultiByte2(res, s, codePage);
Get_AString_From_UString(s, res, codePage, utfFlags);
}
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
@@ -70,12 +89,106 @@ static int CompareUpdateItems(void *const *p1, void *const *p2, void *)
}
static HRESULT GetTime(UInt32 i, UInt32 pid, IArchiveUpdateCallback *callback,
CPaxTime &pt)
{
pt.Clear();
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, pid, &prop));
return Prop_To_PaxTime(prop, pt);
}
/*
static HRESULT GetDevice(IArchiveUpdateCallback *callback, UInt32 i,
UInt32 &majo, UInt32 &mino, bool &majo_defined, bool &mino_defined)
{
NWindows::NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidDevice, &prop));
if (prop.vt == VT_EMPTY)
return S_OK;
if (prop.vt != VT_UI8)
return E_INVALIDARG;
{
const UInt64 v = prop.uhVal.QuadPart;
majo = MY_dev_major(v);
mino = MY_dev_minor(v);
majo_defined = true;
mino_defined = true;
}
return S_OK;
}
*/
static HRESULT GetDevice(IArchiveUpdateCallback *callback, UInt32 i,
UInt32 pid, UInt32 &id, bool &defined)
{
defined = false;
NWindows::NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, pid, &prop));
if (prop.vt == VT_EMPTY)
return S_OK;
if (prop.vt == VT_UI4)
{
id = prop.ulVal;
defined = true;
return S_OK;
}
return E_INVALIDARG;
}
static HRESULT GetUser(IArchiveUpdateCallback *callback, UInt32 i,
UInt32 pidName, UInt32 pidId, AString &name, UInt32 &id,
UINT codePage, unsigned utfFlags)
{
// printf("\ncallback->GetProperty(i, pidId, &prop))\n");
bool isSet = false;
{
NWindows::NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, pidId, &prop));
if (prop.vt == VT_UI4)
{
isSet = true;
id = prop.ulVal;
// printf("\ncallback->GetProperty(i, pidId, &prop)); = %d \n", (unsigned)id);
name.Empty();
}
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
}
{
NWindows::NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, pidName, &prop));
if (prop.vt == VT_BSTR)
{
const UString s = prop.bstrVal;
Get_AString_From_UString(s, name, codePage, utfFlags);
if (!isSet)
id = 0;
}
else if (prop.vt == VT_UI4)
{
id = prop.ulVal;
name.Empty();
}
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 && (_error != k_ErrorType_OK || _warning /* || _isSparse */)) || _seqStream)
if ((_stream && (_arc._error != k_ErrorType_OK || _arc._is_Warning
/* || _isSparse */
)) || _seqStream)
return E_NOTIMPL;
CObjectVector<CUpdateItem> updateItems;
const UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage);
@@ -131,25 +244,30 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
else
ui.Mode = prop.ulVal;
// 21.07 : we clear high file type bits as GNU TAR.
ui.Mode &= ~(UInt32)MY_LIN_S_IFMT;
// we will clear it later
// ui.Mode &= ~(UInt32)MY_LIN_S_IFMT;
}
{
NCOM::CPropVariant prop;
RINOK(callback->GetProperty(i, kpidMTime, &prop));
if (prop.vt == VT_EMPTY)
ui.MTime = 0;
else if (prop.vt != VT_FILETIME)
return E_INVALIDARG;
else
ui.MTime = NTime::FileTimeToUnixTime64(prop.filetime);
}
if (_handlerTimeOptions.Write_MTime.Val)
RINOK(GetTime(i, kpidMTime, callback, ui.PaxTimes.MTime))
if (_handlerTimeOptions.Write_ATime.Val)
RINOK(GetTime(i, kpidATime, callback, ui.PaxTimes.ATime))
if (_handlerTimeOptions.Write_CTime.Val)
RINOK(GetTime(i, kpidCTime, callback, ui.PaxTimes.CTime))
RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, utfFlags, true));
if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/')
ui.Name += '/';
RINOK(GetPropString(callback, i, kpidUser, ui.User, codePage, utfFlags, false));
RINOK(GetPropString(callback, i, kpidGroup, ui.Group, codePage, utfFlags, false));
// ui.Name += '/'; // for debug
if (_posixMode)
{
RINOK(GetDevice(callback, i, kpidDeviceMajor, ui.DeviceMajor, ui.DeviceMajor_Defined));
RINOK(GetDevice(callback, i, kpidDeviceMinor, ui.DeviceMinor, ui.DeviceMinor_Defined));
}
RINOK(GetUser(callback, i, kpidUser, kpidUserId, ui.User, ui.UID, codePage, utfFlags));
RINOK(GetUser(callback, i, kpidGroup, kpidGroupId, ui.Group, ui.GID, codePage, utfFlags));
}
if (IntToBool(newData))
@@ -169,13 +287,44 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
updateItems.Add(ui);
}
if (_thereIsPaxExtendedHeader)
if (_arc._are_Pax_Items)
{
// we restore original order of files, if there is pax header block
// we restore original order of files, if there are pax items
updateItems.Sort(CompareUpdateItems, NULL);
}
CUpdateOptions options;
options.CodePage = codePage;
options.UtfFlags = utfFlags;
options.PosixMode = _posixMode;
return UpdateArchive(_stream, outStream, _items, updateItems, codePage, utfFlags, callback);
options.Write_MTime = _handlerTimeOptions.Write_MTime;
options.Write_ATime = _handlerTimeOptions.Write_ATime;
options.Write_CTime = _handlerTimeOptions.Write_CTime;
// options.TimeOptions = TimeOptions;
const UInt32 prec = _handlerTimeOptions.Prec;
if (prec != (UInt32)(Int32)-1)
{
unsigned numDigits = 0;
if (prec == 0)
numDigits = 7;
else if (prec == k_PropVar_TimePrec_HighPrec
|| prec >= k_PropVar_TimePrec_1ns)
numDigits = 9;
else if (prec >= k_PropVar_TimePrec_Base)
numDigits = prec - k_PropVar_TimePrec_Base;
options.TimeOptions.NumDigitsMax = numDigits;
// options.TimeOptions.RemoveZeroMode =
// k_PaxTimeMode_DontRemoveZero; // pure for debug
// k_PaxTimeMode_RemoveZero_if_PureSecondOnly; // optimized code
// k_PaxTimeMode_RemoveZero_Always; // original pax code
}
return UpdateArchive(_stream, outStream, _items, updateItems,
options, callback);
COM_TRY_END
}