📄 update.cpp
字号:
// Update.cpp#include "StdAfx.h"#ifdef _WIN32#include <mapi.h>#endif#include "Update.h"#include "Common/IntToString.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 "Windows/Synchronization.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"#include "SetProperties.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"#endifstatic 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 HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream){ CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);}class COutMultiVolStream: public IOutStream, public CMyUnknownImp{ int _streamIndex; // required stream UInt64 _offsetPos; // offset from start of _streamIndex index UInt64 _absPos; UInt64 _length; struct CSubStreamInfo { CMyComPtr<IOutStream> Stream; UString Name; UInt64 Pos; UInt64 RealSize; }; CObjectVector<CSubStreamInfo> Streams;public: // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; CRecordVector<UInt64> Sizes; UString Prefix; CTempFiles *TempFiles; void Init() { _streamIndex = 0; _offsetPos = 0; _absPos = 0; _length = 0; } MY_UNKNOWN_IMP1(IOutStream) STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); STDMETHOD(SetSize)(Int64 newSize);};// static NSynchronization::CCriticalSection g_TempPathsCS;STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize){ if(processedSize != NULL) *processedSize = 0; while(size > 0) { if (_streamIndex >= Streams.Size()) { CSubStreamInfo subStream; wchar_t temp[32]; ConvertUInt64ToString(_streamIndex + 1, temp); UString res = temp; while (res.Length() < 3) res = UString(L'0') + res; UString name = Prefix + res; COutFileStream *streamSpec = new COutFileStream; subStream.Stream = streamSpec; if(!streamSpec->Create(name, false)) return ::GetLastError(); { // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS); TempFiles->Paths.Add(name); } subStream.Pos = 0; subStream.RealSize = 0; subStream.Name = name; Streams.Add(subStream); continue; } CSubStreamInfo &subStream = Streams[_streamIndex]; int index = _streamIndex; if (index >= Sizes.Size()) index = Sizes.Size() - 1; UInt64 volSize = Sizes[index]; if (_offsetPos >= volSize) { _offsetPos -= volSize; _streamIndex++; continue; } if (_offsetPos != subStream.Pos) { // CMyComPtr<IOutStream> outStream; // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); subStream.Pos = _offsetPos; } UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos); UInt32 realProcessed; RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); data = (void *)((Byte *)data + realProcessed); size -= realProcessed; subStream.Pos += realProcessed; _offsetPos += realProcessed; _absPos += realProcessed; if (_absPos > _length) _length = _absPos; if (_offsetPos > subStream.RealSize) subStream.RealSize = _offsetPos; if(processedSize != NULL) *processedSize += realProcessed; if (subStream.Pos == volSize) { _streamIndex++; _offsetPos = 0; } if (realProcessed == 0 && curSize != 0) return E_FAIL; break; } return S_OK;}STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition){ if(seekOrigin >= 3) return STG_E_INVALIDFUNCTION; switch(seekOrigin) { case STREAM_SEEK_SET: _absPos = offset; break; case STREAM_SEEK_CUR: _absPos += offset; break; case STREAM_SEEK_END: _absPos = _length + offset; break; } _offsetPos = _absPos; if (newPosition != NULL) *newPosition = _absPos; _streamIndex = 0; return S_OK;}STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize){ if (newSize < 0) return E_INVALIDARG; int i = 0; while (i < Streams.Size()) { CSubStreamInfo &subStream = Streams[i++]; if ((UInt64)newSize < subStream.RealSize) { RINOK(subStream.Stream->SetSize(newSize)); subStream.RealSize = newSize; break; } newSize -= subStream.RealSize; } while (i < Streams.Size()) { { CSubStreamInfo &subStream = Streams.Back(); subStream.Stream.Release(); NDirectory::DeleteFileAlways(subStream.Name); } Streams.DeleteBack(); } _offsetPos = _absPos; _streamIndex = 0; _length = newSize; return S_OK;}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; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -