📄 update.cpp
字号:
// Update.cpp
#include "StdAfx.h"
#include <mapi.h>
#include <vector>
#include "Update.h"
#include "Common/IntToString.h"
#include "Common/StringToInt.h"
#include "Common/StringConvert.h"
#include "Common/CommandLineParser.h"
#ifdef _WIN32
#include "Windows/DLL.h"
#endif
#include "Windows/Defs.h"
#include "Windows/FileDir.h"
#include "Windows/FileFind.h"
#include "Windows/FileName.h"
#include "Windows/PropVariant.h"
#include "Windows/PropVariantConversions.h"
#include "../../Common/FileStreams.h"
#include "../../Compress/Copy/CopyCoder.h"
#include "../Common/DirItem.h"
#include "../Common/EnumDirItems.h"
#include "../Common/UpdateProduce.h"
#include "../Common/OpenArchive.h"
#include "TempFiles.h"
#include "UpdateCallback.h"
#include "EnumDirItems.h"
#ifdef FORMAT_7Z
#include "../../Archive/7z/7zHandler.h"
#endif
#ifdef FORMAT_BZIP2
#include "../../Archive/BZip2/BZip2Handler.h"
#endif
#ifdef FORMAT_GZIP
#include "../../Archive/GZip/GZipHandler.h"
#endif
#ifdef FORMAT_TAR
#include "../../Archive/Tar/TarHandler.h"
#endif
#ifdef FORMAT_ZIP
#include "../../Archive/Zip/ZipHandler.h"
#endif
#ifndef EXCLUDE_COM
#include "../Common/HandlerLoader.h"
#endif
static const char *kUpdateIsNotSupoorted =
"update operations are not supported for this archive";
using namespace NCommandLineParser;
using namespace NWindows;
using namespace NCOM;
using namespace NFile;
using namespace NName;
static const wchar_t *kTempArchiveFilePrefixString = L"7zi";
static const wchar_t *kTempFolderPrefix = L"7zE";
static const char *kIllegalFileNameMessage = "Illegal file name for temp archive";
using namespace NUpdateArchive;
static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)
{
const wchar_t *endPtr;
UInt64 result = ConvertStringToUInt64(s, &endPtr);
if (endPtr - (const wchar_t *)s != s.Length())
prop = s;
else if (result <= 0xFFFFFFFF)
prop = (UInt32)result;
else
prop = result;
}
static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream)
{
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
}
static HRESULT Compress(
const CActionSet &actionSet,
IInArchive *archive,
const CCompressionMethodMode &compressionMethod,
CArchivePath &archivePath,
const CObjectVector<CArchiveItem> &archiveItems,
bool stdInMode,
const UString &stdInFileName,
bool stdOutMode,
const CObjectVector<CDirItem> &dirItems,
bool sfxMode,
const UString &sfxModule,
const CRecordVector<UInt64> &volumesSizes,
CTempFiles &tempFiles,
CUpdateErrorInfo &errorInfo,
IUpdateCallbackUI *callback)
{
#ifndef EXCLUDE_COM
CHandlerLoader loader;
#endif
CMyComPtr<IOutArchive> outArchive;
if(archive != NULL)
{
CMyComPtr<IInArchive> archive2 = archive;
HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);
if(result != S_OK)
throw kUpdateIsNotSupoorted;
}
else
{
#ifndef EXCLUDE_COM
if (loader.CreateHandler(compressionMethod.FilePath,
compressionMethod.ClassID, (void **)&outArchive, true) != S_OK)
throw kUpdateIsNotSupoorted;
#endif
#ifdef FORMAT_7Z
if (compressionMethod.Name.CompareNoCase(L"7z") == 0)
outArchive = new NArchive::N7z::CHandler;
#endif
#ifdef FORMAT_BZIP2
if (compressionMethod.Name.CompareNoCase(L"BZip2") == 0)
outArchive = new NArchive::NBZip2::CHandler;
#endif
#ifdef FORMAT_GZIP
if (compressionMethod.Name.CompareNoCase(L"GZip") == 0)
outArchive = new NArchive::NGZip::CHandler;
#endif
#ifdef FORMAT_TAR
if (compressionMethod.Name.CompareNoCase(L"Tar") == 0)
outArchive = new NArchive::NTar::CHandler;
#endif
#ifdef FORMAT_ZIP
if (compressionMethod.Name.CompareNoCase(L"Zip") == 0)
outArchive = new NArchive::NZip::CHandler;
#endif
}
if (outArchive == 0)
throw kUpdateIsNotSupoorted;
NFileTimeType::EEnum fileTimeType;
UInt32 value;
RINOK(outArchive->GetFileTimeType(&value));
switch(value)
{
case NFileTimeType::kWindows:
case NFileTimeType::kDOS:
case NFileTimeType::kUnix:
fileTimeType = NFileTimeType::EEnum(value);
break;
default:
return E_FAIL;
}
CObjectVector<CUpdatePair> updatePairs;
GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs); // must be done only once!!!
CObjectVector<CUpdatePair2> updatePairs2;
UpdateProduce(dirItems, archiveItems, updatePairs, actionSet, updatePairs2);
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec );
updateCallbackSpec->StdInMode = stdInMode;
updateCallbackSpec->Callback = callback;
updateCallbackSpec->DirItems = &dirItems;
updateCallbackSpec->ArchiveItems = &archiveItems;
updateCallbackSpec->UpdatePairs = &updatePairs2;
CMyComPtr<ISequentialOutStream> outStream;
const UString &archiveName = archivePath.GetFinalPath();
if (!stdOutMode)
{
UString resultPath;
int pos;
if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))
throw 1417161;
NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
}
if (volumesSizes.Size() == 0)
{
if (stdOutMode)
outStream = new CStdOutFileStream;
else
{
COutFileStream *outStreamSpec = new COutFileStream;
outStream = outStreamSpec;
bool isOK = false;
UString realPath;
for (int i = 0; i < (1 << 16); i++)
{
if (archivePath.Temp)
{
if (i > 0)
{
wchar_t s[32];
ConvertUInt64ToString(i, s);
archivePath.TempPostfix = s;
}
realPath = archivePath.GetTempPath();
}
else
realPath = archivePath.GetFinalPath();
if (outStreamSpec->Create(realPath, false))
{
tempFiles.Paths.Add(realPath);
isOK = true;
break;
}
if (::GetLastError() != ERROR_FILE_EXISTS)
break;
if (!archivePath.Temp)
break;
}
if (!isOK)
{
errorInfo.SystemError = ::GetLastError();
errorInfo.FileName = realPath;
errorInfo.Message = L"Can not open file";
return E_FAIL;
}
}
}
else
{
updateCallbackSpec->VolumesSizes = volumesSizes;
updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;
if (!archivePath.VolExtension.IsEmpty())
updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension;
}
CMyComPtr<ISetProperties> setProperties;
if (outArchive.QueryInterface(IID_ISetProperties, &setProperties) == S_OK)
{
UStringVector realNames;
std::vector<CPropVariant> values;
int i;
for(i = 0; i < compressionMethod.Properties.Size(); i++)
{
const CProperty &property = compressionMethod.Properties[i];
NCOM::CPropVariant propVariant;
if (!property.Value.IsEmpty())
ParseNumberString(property.Value, propVariant);
realNames.Add(property.Name);
values.push_back(propVariant);
}
CRecordVector<const wchar_t *> names;
for(i = 0; i < realNames.Size(); i++)
names.Add((const wchar_t *)realNames[i]);
RINOK(setProperties->SetProperties(&names.Front(),
&values.front(), names.Size()));
}
if (sfxMode)
{
CInFileStream *sfxStreamSpec = new CInFileStream;
CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
if (!sfxStreamSpec->Open(sfxModule))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"Can't open sfx module";
errorInfo.FileName = sfxModule;
return E_FAIL;
}
RINOK(CopyBlock(sfxStream, outStream));
}
HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(),
updateCallback);
callback->Finilize();
return result;
}
HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,
IInArchive *archive,
const UString &defaultItemName,
const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
CObjectVector<CArchiveItem> &archiveItems)
{
archiveItems.Clear();
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
archiveItems.Reserve(numItems);
for(UInt32 i = 0; i < numItems; i++)
{
CArchiveItem ai;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -