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

📄 zipupdate.cpp

📁 由7-zip提供的压缩、解压缩程序
💻 CPP
字号:
// ZipUpdate.cpp#include "StdAfx.h"#include "ZipUpdate.h"#include "ZipAddCommon.h"#include "ZipOut.h"#include "Common/Defs.h"#include "Common/AutoPtr.h"#include "Common/StringConvert.h"#include "Windows/Defs.h"#include "../../Common/ProgressUtils.h"#include "../../Common/LimitedStreams.h"#include "../../Compress/Copy/CopyCoder.h"#include "../Common/InStreamWithCRC.h"namespace NArchive {namespace NZip {static const Byte kMadeByHostOS = NFileHeader::NHostOS::kFAT;static const Byte kExtractHostOS = NFileHeader::NHostOS::kFAT;static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStored;static const Byte kExtractVersionForDirectory = NFileHeader::NCompressionMethod::kStoreExtractVersion;static HRESULT CopyBlock(ISequentialInStream *inStream,     ISequentialOutStream *outStream, ICompressProgressInfo *progress){  CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;  return copyCoder->Code(inStream, outStream, NULL, NULL, progress);}HRESULT CopyBlockToArchive(ISequentialInStream *inStream,     COutArchive &outArchive, ICompressProgressInfo *progress){  CMyComPtr<ISequentialOutStream> outStream;  outArchive.CreateStreamForCopying(&outStream);  return CopyBlock(inStream, outStream, progress);}static HRESULT WriteRange(IInStream *inStream,     COutArchive &outArchive,     const CUpdateRange &range,     IProgress *progress,    UInt64 &currentComplexity){  UInt64 position;  inStream->Seek(range.Position, STREAM_SEEK_SET, &position);  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;  CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);  streamSpec->Init(inStream, range.Size);  CLocalProgress *localProgressSpec = new CLocalProgress;  CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;  localProgressSpec->Init(progress, true);    CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;  CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;  localCompressProgressSpec->Init(localProgress, &currentComplexity, &currentComplexity);  HRESULT result = CopyBlockToArchive(inStreamLimited, outArchive, compressProgress);  currentComplexity += range.Size;  return result;}static HRESULT UpdateOneFile(IInStream *inStream,     COutArchive &archive,     const CCompressionMethodMode &options,    CAddCommon &compressor,     const CUpdateItem &updateItem,     UInt64 &currentComplexity,    IArchiveUpdateCallback *updateCallback,    CItemEx &fileHeader,    CMyComPtr<ISequentialInStream> &fileInStream2){  CMyComPtr<IInStream> fileInStream;  if (fileInStream2)  {    RINOK(fileInStream2.QueryInterface(IID_IInStream, &fileInStream));  }  bool isDirectory;  UInt64 fileSize = updateItem.Size;  fileHeader.UnPackSize = fileSize;  if (updateItem.NewProperties)  {    isDirectory = updateItem.IsDirectory;    fileHeader.Name = updateItem.Name;     fileHeader.ExternalAttributes = updateItem.Attributes;    fileHeader.Time = updateItem.Time;  }  else    isDirectory = fileHeader.IsDirectory();  archive.PrepareWriteCompressedData(fileHeader.Name.Length(), fileSize);  fileHeader.LocalHeaderPosition = archive.GetCurrentPosition();  fileHeader.MadeByVersion.HostOS = kMadeByHostOS;  fileHeader.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion;    fileHeader.ExtractVersion.HostOS = kExtractHostOS;  fileHeader.InternalAttributes = 0; // test it  fileHeader.ClearFlags();  if(isDirectory)  {    fileHeader.ExtractVersion.Version = kExtractVersionForDirectory;    fileHeader.CompressionMethod = kMethodForDirectory;    fileHeader.PackSize = 0;    fileHeader.FileCRC = 0; // test it  }  else  {    {      CSequentialInStreamWithCRC *inSecStreamSpec = 0;      CInStreamWithCRC *inStreamSpec = 0;      CMyComPtr<ISequentialInStream> fileSecInStream;      if (fileInStream)      {        inStreamSpec = new CInStreamWithCRC;        fileSecInStream = inStreamSpec;        inStreamSpec->Init(fileInStream);      }      else      {        inSecStreamSpec = new CSequentialInStreamWithCRC;        fileSecInStream = inSecStreamSpec;        inSecStreamSpec->Init(fileInStream2);      }      CCompressingResult compressingResult;      CMyComPtr<IOutStream> outStream;      archive.CreateStreamForCompressing(&outStream);      CLocalProgress *localProgressSpec = new CLocalProgress;      CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;      localProgressSpec->Init(updateCallback, true);        CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;      CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;      localCompressProgressSpec->Init(localProgress, &currentComplexity, NULL);      RINOK(compressor.Compress(fileSecInStream, outStream, fileSize, compressProgress, compressingResult));      fileHeader.PackSize = compressingResult.PackSize;      fileHeader.CompressionMethod = compressingResult.Method;      fileHeader.ExtractVersion.Version = compressingResult.ExtractVersion;      if (inStreamSpec != 0)      {        fileHeader.FileCRC = inStreamSpec->GetCRC();        fileHeader.UnPackSize = inStreamSpec->GetSize();      }      else      {        fileHeader.FileCRC = inSecStreamSpec->GetCRC();        fileHeader.UnPackSize = inSecStreamSpec->GetSize();      }    }  }  fileHeader.SetEncrypted(!isDirectory && options.PasswordIsDefined);  /*  fileHeader.CommentSize = (updateItem.Commented) ?       WORD(updateItem.CommentRange.Size) : 0;  */  fileHeader.LocalExtraSize = 0;    // fileHeader.CentralExtraSize = 0;  RINOK(archive.WriteLocalHeader(fileHeader));  currentComplexity += fileSize;  return updateCallback->SetOperationResult(      NArchive::NUpdate::NOperationResult::kOK);}static HRESULT Update2(COutArchive &archive,     IInStream *inStream,    const CObjectVector<CItemEx> &inputItems,    const CObjectVector<CUpdateItem> &updateItems,    const CCompressionMethodMode *options,     const CByteBuffer &comment,    IArchiveUpdateCallback *updateCallback){  UInt64 complexity = 0;   int i;  for(i = 0; i < updateItems.Size(); i++)  {    const CUpdateItem &updateItem = updateItems[i];    if (updateItem.NewData)    {      complexity += updateItem.Size;      /*      if (updateItem.Commented)        complexity += updateItem.CommentRange.Size;      */    }    else    {      const CItemEx &inputItem = inputItems[updateItem.IndexInArchive];      complexity += inputItem.GetLocalFullSize();      // complexity += inputItem.GetCentralExtraPlusCommentSize();    }    complexity += NFileHeader::kLocalBlockSize;    complexity += NFileHeader::kCentralBlockSize;  }  if (comment != 0)    complexity += comment.GetCapacity();  complexity++; // end of central    updateCallback->SetTotal(complexity);  CMyAutoPtr<CAddCommon> compressor;    complexity = 0;    CObjectVector<CItem> items;  CRecordVector<UInt32> updateIndices;  for(i = 0; i < updateItems.Size(); i++)  {    const CUpdateItem &updateItem = updateItems[i];    RINOK(updateCallback->SetCompleted(&complexity));    CItemEx item;    if (!updateItem.NewProperties || !updateItem.NewData)      item = inputItems[updateItem.IndexInArchive];    if (updateItem.NewData)    {      if(compressor.get() == NULL)      {        CMyAutoPtr<CAddCommon> tmp(new CAddCommon(*options));        compressor = tmp;      }      CMyComPtr<ISequentialInStream> fileInStream2;      HRESULT res = updateCallback->GetStream(updateItem.IndexInClient, &fileInStream2);      if (res == S_FALSE)      {        complexity += updateItem.Size;        complexity++;        RINOK(updateCallback->SetOperationResult(            NArchive::NUpdate::NOperationResult::kOK));        continue;      }      RINOK(res);      RINOK(UpdateOneFile(inStream, archive, *options,           *compressor, updateItem, complexity, updateCallback, item,          fileInStream2));    }    else    {      // item = inputItems[copyIndices[copyIndexIndex++]];      if (updateItem.NewProperties)      {        if (item.HasDescriptor())          return E_NOTIMPL;                // use old name size.        // CUpdateRange range(item.GetLocalExtraPosition(), item.LocalExtraSize + item.PackSize);        CUpdateRange range(item.GetDataPosition(), item.PackSize);        // item.ExternalAttributes = updateItem.Attributes;        // Test it        item.Name = updateItem.Name;         item.Time = updateItem.Time;        item.CentralExtra.Clear();        item.LocalExtraSize = 0;        archive.PrepareWriteCompressedData2(item.Name.Length(), item.UnPackSize, item.PackSize);        item.LocalHeaderPosition = archive.GetCurrentPosition();        archive.SeekToPackedDataPosition();        RINOK(WriteRange(inStream, archive, range, updateCallback, complexity));        archive.WriteLocalHeader(item);      }      else      {        CUpdateRange range(item.LocalHeaderPosition, item.GetLocalFullSize());              // set new header position        item.LocalHeaderPosition = archive.GetCurrentPosition();                 RINOK(WriteRange(inStream, archive, range, updateCallback, complexity));        archive.MoveBasePosition(range.Size);      }    }    items.Add(item);    updateIndices.Add(i);    complexity += NFileHeader::kLocalBlockSize;  }  archive.WriteCentralDir(items, comment);  return S_OK;}HRESULT Update(        const CObjectVector<CItemEx> &inputItems,    const CObjectVector<CUpdateItem> &updateItems,    ISequentialOutStream *seqOutStream,    CInArchive *inArchive,    CCompressionMethodMode *compressionMethodMode,    IArchiveUpdateCallback *updateCallback){  CMyComPtr<IOutStream> outStream;  RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));  if (!outStream)    return E_NOTIMPL;  CInArchiveInfo archiveInfo;  if(inArchive != 0)    inArchive->GetArchiveInfo(archiveInfo);  else    archiveInfo.StartPosition = 0;    COutArchive outArchive;  outArchive.Create(outStream);  if (archiveInfo.StartPosition > 0)  {    CMyComPtr<ISequentialInStream> inStream;    inStream.Attach(inArchive->CreateLimitedStream(0, archiveInfo.StartPosition));    RINOK(CopyBlockToArchive(inStream, outArchive, NULL));    outArchive.MoveBasePosition(archiveInfo.StartPosition);  }  CMyComPtr<IInStream> inStream;  if(inArchive != 0)    inStream.Attach(inArchive->CreateStream());  return Update2(outArchive, inStream,       inputItems, updateItems,       compressionMethodMode,       archiveInfo.Comment, updateCallback);}}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -