This commit is contained in:
Igor Pavlov
2018-01-11 22:16:32 +01:00
committed by Kornel
parent b5dc853b24
commit da28077952
44 changed files with 853 additions and 366 deletions

View File

@@ -124,6 +124,7 @@ enum Enum
kTechMode,
kShareForWrite,
kStopAfterOpenError,
kCaseSensitive,
kArcNameMode,
@@ -245,6 +246,7 @@ static const CSwitchForm kSwitchForms[] =
{ "slt" },
{ "ssw" },
{ "sse" },
{ "ssc", NSwitchType::kMinus },
{ "sa", NSwitchType::kChar, false, 1, k_ArcNameMode_PostCharSet },
@@ -1299,6 +1301,8 @@ void CArcCmdLineParser::Parse2(CArcCmdLineOptions &options)
if (parser[NKey::kShareForWrite].ThereIs)
updateOptions.OpenShareForWrite = true;
if (parser[NKey::kStopAfterOpenError].ThereIs)
updateOptions.StopAfterOpenError = true;
updateOptions.PathMode = censorPathMode;

View File

@@ -182,6 +182,7 @@ HRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *r
#endif
CArchiveExtractCallback::CArchiveExtractCallback():
_arc(NULL),
WriteCTime(true),
WriteATime(true),
WriteMTime(true),
@@ -205,8 +206,8 @@ void CArchiveExtractCallback::Init(
const UStringVector &removePathParts, bool removePartsForAltStreams,
UInt64 packSize)
{
_extractedFolderPaths.Clear();
_extractedFolderIndices.Clear();
ClearExtractedDirsInfo();
_outFileStream.Release();
#ifdef SUPPORT_LINKS
_hardLinks.Clear();
@@ -368,7 +369,7 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat
}
}
HRESULT CArchiveExtractCallback::GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
HRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
{
filetimeIsDefined = false;
NCOM::CPropVariant prop;
@@ -734,7 +735,8 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre
return E_FAIL;
UString s;
CReparseAttr reparse;
isOkReparse = reparse.Parse((const Byte *)data, dataSize);
DWORD errorCode = 0;
isOkReparse = reparse.Parse((const Byte *)data, dataSize, errorCode);
if (isOkReparse)
{
isHardLink = false;
@@ -1270,7 +1272,8 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)
if (FillLinkData(data, fs2us(existPath), !isJunction))
{
CReparseAttr attr;
if (!attr.Parse(data, data.Size()))
DWORD errorCode = 0;
if (!attr.Parse(data, data.Size(), errorCode))
{
RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path)));
// return E_FAIL;
@@ -1447,6 +1450,33 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
}
HRESULT CArchiveExtractCallback::CloseFile()
{
if (!_outFileStream)
return S_OK;
HRESULT hres = S_OK;
_outFileStreamSpec->SetTime(
(WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
(WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
(WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
const UInt64 processedSize = _outFileStreamSpec->ProcessedSize;
if (_fileLengthWasSet && _curSize > processedSize)
{
bool res = _outFileStreamSpec->File.SetLength(processedSize);
_fileLengthWasSet = res;
if (!res)
hres = SendMessageError_with_LastError(kCantSetFileLen, us2fs(_item.Path));
}
_curSize = processedSize;
_curSizeDefined = true;
RINOK(_outFileStreamSpec->Close());
_outFileStream.Release();
return hres;
}
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
{
COM_TRY_BEGIN
@@ -1475,27 +1505,7 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes)
#endif
if (_outFileStream)
{
HRESULT hres = S_OK;
_outFileStreamSpec->SetTime(
(WriteCTime && _fi.CTimeDefined) ? &_fi.CTime : NULL,
(WriteATime && _fi.ATimeDefined) ? &_fi.ATime : NULL,
(WriteMTime && _fi.MTimeDefined) ? &_fi.MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
const UInt64 processedSize = _outFileStreamSpec->ProcessedSize;
if (_fileLengthWasSet && _curSize > processedSize)
{
bool res = _outFileStreamSpec->File.SetLength(processedSize);
_fileLengthWasSet = res;
if (!res)
hres = SendMessageError_with_LastError(kCantSetFileLen, us2fs(_item.Path));
}
_curSize = processedSize;
_curSizeDefined = true;
RINOK(_outFileStreamSpec->Close());
_outFileStream.Release();
RINOK(hres);
}
RINOK(CloseFile());
#ifdef _USE_SECURITY_CODE
if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps)
@@ -1620,8 +1630,12 @@ static unsigned GetNumSlashes(const FChar *s)
}
}
HRESULT CArchiveExtractCallback::SetDirsTimes()
{
if (!_arc)
return S_OK;
CRecordVector<CExtrRefSortPair> pairs;
pairs.ClearAndSetSize(_extractedFolderPaths.Size());
unsigned i;
@@ -1637,8 +1651,8 @@ HRESULT CArchiveExtractCallback::SetDirsTimes()
for (i = 0; i < pairs.Size(); i++)
{
int pairIndex = pairs[i].Index;
int index = _extractedFolderIndices[pairIndex];
unsigned pairIndex = pairs[i].Index;
UInt32 index = _extractedFolderIndices[pairIndex];
FILETIME CTime;
FILETIME ATime;
@@ -1658,5 +1672,18 @@ HRESULT CArchiveExtractCallback::SetDirsTimes()
(WriteATime && ATimeDefined) ? &ATime : NULL,
(WriteMTime && MTimeDefined) ? &MTime : (_arc->MTimeDefined ? &_arc->MTime : NULL));
}
ClearExtractedDirsInfo();
return S_OK;
}
HRESULT CArchiveExtractCallback::CloseArc()
{
HRESULT res = CloseFile();
HRESULT res2 = SetDirsTimes();
if (res == S_OK)
res = res2;
_arc = NULL;
return res;
}

View File

@@ -249,7 +249,7 @@ class CArchiveExtractCallback:
#endif
void CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath);
HRESULT GetTime(int index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
HRESULT GetTime(UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined);
HRESULT GetUnpackSize();
HRESULT SendMessageError(const char *message, const FString &path);
@@ -343,9 +343,44 @@ public:
}
#endif
HRESULT CloseArc();
private:
void ClearExtractedDirsInfo()
{
_extractedFolderPaths.Clear();
_extractedFolderIndices.Clear();
}
HRESULT CloseFile();
HRESULT SetDirsTimes();
};
struct CArchiveExtractCallback_Closer
{
CArchiveExtractCallback *_ref;
CArchiveExtractCallback_Closer(CArchiveExtractCallback *ref): _ref(ref) {}
HRESULT Close()
{
HRESULT res = S_OK;
if (_ref)
{
res = _ref->CloseArc();
_ref = NULL;
}
return res;
}
~CArchiveExtractCallback_Closer()
{
Close();
}
};
bool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);
#endif

View File

@@ -386,15 +386,27 @@ HRESULT CDirItems::SetLinkInfo(CDirItem &dirItem, const NFind::CFileInfo &fi,
return S_OK;
const FString path = phyPrefix + fi.Name;
CByteBuffer &buf = dirItem.ReparseData;
DWORD res = 0;
if (NIO::GetReparseData(path, buf))
{
CReparseAttr attr;
if (attr.Parse(buf, buf.Size()))
if (attr.Parse(buf, buf.Size(), res))
return S_OK;
// we ignore unknown reparse points
if (res != ERROR_INVALID_REPARSE_DATA)
res = 0;
}
DWORD res = ::GetLastError();
else
{
res = ::GetLastError();
if (res == 0)
res = ERROR_INVALID_FUNCTION;
}
buf.Free();
return AddError(path , res);
if (res == 0)
return S_OK;
return AddError(path, res);
}
#endif
@@ -865,7 +877,8 @@ void CDirItems::FillFixedReparse()
continue;
CReparseAttr attr;
if (!attr.Parse(item.ReparseData, item.ReparseData.Size()))
DWORD errorCode = 0;
if (!attr.Parse(item.ReparseData, item.ReparseData.Size(), errorCode))
continue;
if (attr.IsRelative())
continue;

View File

@@ -197,6 +197,9 @@ static HRESULT DecompressArchive(
HRESULT result;
Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0;
CArchiveExtractCallback_Closer ecsCloser(ecs);
if (options.StdInMode)
{
result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs);
@@ -206,8 +209,11 @@ static HRESULT DecompressArchive(
}
else
result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, ecs);
if (result == S_OK && !options.StdInMode)
result = ecs->SetDirsTimes();
HRESULT res2 = ecsCloser.Close();
if (result == S_OK)
result = res2;
return callback->ExtractResult(result);
}

View File

@@ -224,7 +224,6 @@ static inline void AddHexToString(AString &res, unsigned v)
{
res += (char)GetHex(v >> 4);
res += (char)GetHex(v & 0xF);
res += ' ';
}
/*
@@ -269,6 +268,14 @@ struct CSecID2Name
const char *sz;
};
static int FindPairIndex(const CSecID2Name * pairs, unsigned num, UInt32 id)
{
for (unsigned i = 0; i < num; i++)
if (pairs[i].n == id)
return i;
return -1;
}
static const CSecID2Name sid_32_Names[] =
{
{ 544, "Administrators" },
@@ -359,22 +366,22 @@ static void ParseSid(AString &s, const Byte *p, UInt32 lim, UInt32 &sidSize)
if (v0 == 32 && num == 2)
{
UInt32 v1 = Get32(p + 12);
for (unsigned i = 0; i < ARRAY_SIZE(sid_32_Names); i++)
if (sid_32_Names[i].n == v1)
{
s += sid_32_Names[i].sz;
return;
}
int index = FindPairIndex(sid_32_Names, ARRAY_SIZE(sid_32_Names), v1);
if (index >= 0)
{
s += sid_32_Names[index].sz;
return;
}
}
if (v0 == 21 && num == 5)
{
UInt32 v4 = Get32(p + 8 + 4 * 4);
for (unsigned i = 0; i < ARRAY_SIZE(sid_21_Names); i++)
if (sid_21_Names[i].n == v4)
{
s += sid_21_Names[i].sz;
return;
}
int index = FindPairIndex(sid_21_Names, ARRAY_SIZE(sid_21_Names), v4);
if (index >= 0)
{
s += sid_21_Names[index].sz;
return;
}
}
if (v0 == 80 && num == 6)
{
@@ -419,20 +426,13 @@ static void ParseOwner(AString &s, const Byte *p, UInt32 size, UInt32 pos)
ParseSid(s, p + pos, size - pos, sidSize);
}
static void AddUInt32ToString(AString &s, UInt32 val)
{
char sz[16];
ConvertUInt32ToString(val, sz);
s += sz;
}
static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName, UInt32 flags, UInt32 offset)
{
UInt32 control = Get16(p + 2);
if ((flags & control) == 0)
return;
UInt32 pos = Get32(p + offset);
s += ' ';
s.Add_Space();
s += strName;
if (pos >= size)
return;
@@ -443,7 +443,7 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName
if (Get16(p) != 2) // revision
return;
UInt32 num = Get32(p + 4);
AddUInt32ToString(s, num);
s.Add_UInt32(num);
/*
UInt32 aclSize = Get16(p + 2);
@@ -466,7 +466,7 @@ static void ParseAcl(AString &s, const Byte *p, UInt32 size, const char *strName
size -= 8;
UInt32 sidSize = 0;
s += ' ';
s.Add_Space();
ParseSid(s, p, size, sidSize);
if (sidSize == 0)
return;
@@ -508,12 +508,12 @@ void ConvertNtSecureToString(const Byte *data, UInt32 size, AString &s)
return;
}
ParseOwner(s, data, size, Get32(data + 4));
s += ' ';
s.Add_Space();
ParseOwner(s, data, size, Get32(data + 8));
ParseAcl(s, data, size, "s:", MY_SE_SACL_PRESENT, 12);
ParseAcl(s, data, size, "d:", MY_SE_DACL_PRESENT, 16);
s += ' ';
AddUInt32ToString(s, size);
s.Add_Space();
s.Add_UInt32(size);
// s += '\n';
// s += Data_To_Hex(data, size);
}
@@ -567,11 +567,38 @@ bool CheckNtSecure(const Byte *data, UInt32 size) throw()
#endif
// IO_REPARSE_TAG_*
static const CSecID2Name k_ReparseTags[] =
{
{ 0xA0000003, "MOUNT_POINT" },
{ 0xC0000004, "HSM" },
{ 0x80000005, "DRIVE_EXTENDER" },
{ 0x80000006, "HSM2" },
{ 0x80000007, "SIS" },
{ 0x80000008, "WIM" },
{ 0x80000009, "CSV" },
{ 0x8000000A, "DFS" },
{ 0x8000000B, "FILTER_MANAGER" },
{ 0xA000000C, "SYMLINK" },
{ 0xA0000010, "IIS_CACHE" },
{ 0x80000012, "DFSR" },
{ 0x80000013, "DEDUP" },
{ 0xC0000014, "APPXSTRM" },
{ 0x80000014, "NFS" },
{ 0x80000015, "FILE_PLACEHOLDER" },
{ 0x80000016, "DFM" },
{ 0x80000017, "WOF" }
};
bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
{
s.Empty();
NFile::CReparseAttr attr;
if (attr.Parse(data, size))
DWORD errorCode = 0;
if (attr.Parse(data, size, errorCode))
{
if (!attr.IsSymLink())
s += "Junction: ";
@@ -593,19 +620,48 @@ bool ConvertNtReparseToString(const Byte *data, UInt32 size, UString &s)
if (Get16(data + 6) != 0) // padding
return false;
char hex[16];
ConvertUInt32ToHex8Digits(tag, hex);
s += hex;
s.Add_Space();
data += 8;
for (UInt32 i = 0; i < len; i++)
/*
#define _my_IO_REPARSE_TAG_DEDUP (0x80000013L)
if (tag == _my_IO_REPARSE_TAG_DEDUP)
{
unsigned b = ((const Byte *)data)[i];
s += (char)GetHex((b >> 4) & 0xF);
s += (char)GetHex(b & 0xF);
}
*/
{
int index = FindPairIndex(k_ReparseTags, ARRAY_SIZE(k_ReparseTags), tag);
if (index >= 0)
s += k_ReparseTags[index].sz;
else
{
s += "REPARSE:";
char hex[16];
ConvertUInt32ToHex8Digits(tag, hex);
s += hex;
}
}
s += ":";
s.Add_UInt32(len);
if (len != 0)
{
s.Add_Space();
data += 8;
for (UInt32 i = 0; i < len; i++)
{
if (i >= 8)
{
s += "...";
break;
}
unsigned b = data[i];
s += (char)GetHex((b >> 4) & 0xF);
s += (char)GetHex(b & 0xF);
}
}
return true;
}

View File

@@ -735,6 +735,7 @@ static HRESULT Compress(
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
updateCallbackSpec->ShareForWrite = options.OpenShareForWrite;
updateCallbackSpec->StopAfterOpenError = options.StopAfterOpenError;
updateCallbackSpec->StdInMode = options.StdInMode;
updateCallbackSpec->Callback = callback;

View File

@@ -92,6 +92,7 @@ struct CUpdateOptions
FString SfxModule;
bool OpenShareForWrite;
bool StopAfterOpenError;
bool StdInMode;
UString StdInFileName;
@@ -127,6 +128,7 @@ struct CUpdateOptions
EMailMode(false),
EMailRemoveAfter(false),
OpenShareForWrite(false),
StopAfterOpenError(false),
ArcNameMode(k_ArcNameMode_Smart),
PathMode(NWildcard::k_RelatPath),

View File

@@ -55,6 +55,7 @@ CArchiveUpdateCallback::CArchiveUpdateCallback():
Comment(NULL),
ShareForWrite(false),
StopAfterOpenError(false),
StdInMode(false),
KeepOriginalItemNames(false),
@@ -346,7 +347,8 @@ STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PR
// if (di.IsDir())
{
CReparseAttr attr;
if (attr.Parse(di.ReparseData, di.ReparseData.Size()))
DWORD errorCode = 0;
if (attr.Parse(di.ReparseData, di.ReparseData.Size(), errorCode))
{
UString simpleName = attr.GetPath();
if (attr.IsRelative())
@@ -512,7 +514,12 @@ STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStrea
#endif
if (!inStreamSpec->OpenShared(path, ShareForWrite))
{
return Callback->OpenFileError(path, ::GetLastError());
DWORD error = ::GetLastError();
HRESULT hres = Callback->OpenFileError(path, error);
if (StopAfterOpenError)
if (hres == S_OK || hres == S_FALSE)
return HRESULT_FROM_WIN32(error);
return hres;
}
if (StoreHardLinks)

View File

@@ -136,6 +136,7 @@ public:
const UString *Comment;
bool ShareForWrite;
bool StopAfterOpenError;
bool StdInMode;
bool KeepOriginalItemNames;