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

📄 update.cpp

📁 免费压缩软件7zip的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -