⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 update.cpp

📁 由7-zip提供的压缩、解压缩程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -