470
static void FromUpdateItemToFileItem(const CUpdateItem &updateItem,
490
static void FromUpdateItemToFileItem(const CUpdateItem &ui,
491
CFileItem &file, CFileItem2 &file2)
473
file.Name = NItemName::MakeLegalName(updateItem.Name);
474
if (updateItem.AttributesAreDefined)
475
file.SetAttributes(updateItem.Attributes);
477
if (updateItem.IsCreationTimeDefined)
478
file.SetCreationTime(updateItem.CreationTime);
479
if (updateItem.IsLastWriteTimeDefined)
480
file.SetLastWriteTime(updateItem.LastWriteTime);
481
if (updateItem.IsLastAccessTimeDefined)
482
file.SetLastAccessTime(updateItem.LastAccessTime);
484
file.UnPackSize = updateItem.Size;
485
file.IsDirectory = updateItem.IsDirectory;
486
file.IsAnti = updateItem.IsAnti;
487
file.HasStream = updateItem.HasStream();
493
file.Name = NItemName::MakeLegalName(ui.Name);
494
if (ui.AttribDefined)
495
file.SetAttrib(ui.Attrib);
497
file2.CTime = ui.CTime; file2.CTimeDefined = ui.CTimeDefined;
498
file2.ATime = ui.ATime; file2.ATimeDefined = ui.ATimeDefined;
499
file2.MTime = ui.MTime; file2.MTimeDefined = ui.MTimeDefined;
500
file2.IsAnti = ui.IsAnti;
501
file2.StartPosDefined = false;
504
file.IsDir = ui.IsDir;
505
file.HasStream = ui.HasStream();
490
508
static HRESULT Update2(
491
509
DECL_EXTERNAL_CODECS_LOC_VARS
492
510
IInStream *inStream,
493
const CArchiveDatabaseEx *database,
511
const CArchiveDatabaseEx *db,
494
512
const CObjectVector<CUpdateItem> &updateItems,
513
COutArchive &archive,
514
CArchiveDatabase &newDatabase,
495
515
ISequentialOutStream *seqOutStream,
496
516
IArchiveUpdateCallback *updateCallback,
497
517
const CUpdateOptions &options)
598
615
int folderIndex = folderRefs[i];
600
617
lps->ProgressOffset = complexity;
601
UInt64 packSize = database->GetFolderFullPackSize(folderIndex);
618
UInt64 packSize = db->GetFolderFullPackSize(folderIndex);
602
619
RINOK(WriteRange(inStream, archive.SeqStream,
603
database->GetFolderStreamPos(folderIndex, 0), packSize, progress));
620
db->GetFolderStreamPos(folderIndex, 0), packSize, progress));
604
621
complexity += packSize;
606
const CFolder &folder = database->Folders[folderIndex];
607
CNum startIndex = database->FolderStartPackStreamIndex[folderIndex];
623
const CFolder &folder = db->Folders[folderIndex];
624
CNum startIndex = db->FolderStartPackStreamIndex[folderIndex];
608
625
for (int j = 0; j < folder.PackStreams.Size(); j++)
610
newDatabase.PackSizes.Add(database->PackSizes[startIndex + j]);
611
// newDatabase.PackCRCsDefined.Add(database.PackCRCsDefined[startIndex + j]);
612
// newDatabase.PackCRCs.Add(database.PackCRCs[startIndex + j]);
627
newDatabase.PackSizes.Add(db->PackSizes[startIndex + j]);
628
// newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]);
629
// newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);
614
631
newDatabase.Folders.Add(folder);
616
CNum numUnPackStreams = database->NumUnPackStreamsVector[folderIndex];
617
newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams);
633
CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
634
newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams);
619
636
CNum indexInFolder = 0;
620
for (CNum fi = database->FolderStartFileIndex[folderIndex];
621
indexInFolder < numUnPackStreams; fi++)
637
for (CNum fi = db->FolderStartFileIndex[folderIndex];
638
indexInFolder < numUnpackStreams; fi++)
623
CFileItem file = database->Files[fi];
642
db->GetFile(fi, file, file2);
624
643
if (file.HasStream)
627
646
int updateIndex = fileIndexToUpdateIndexMap[fi];
628
647
if (updateIndex >= 0)
630
const CUpdateItem &updateItem = updateItems[updateIndex];
631
if (updateItem.NewProperties)
649
const CUpdateItem &ui = updateItems[updateIndex];
650
if (ui.NewProperties)
634
FromUpdateItemToFileItem(updateItem, file2);
635
file2.UnPackSize = file.UnPackSize;
636
file2.FileCRC = file.FileCRC;
637
file2.IsFileCRCDefined = file.IsFileCRCDefined;
638
file2.HasStream = file.HasStream;
653
FromUpdateItemToFileItem(ui, uf, file2);
656
uf.CrcDefined = file.CrcDefined;
657
uf.HasStream = file.HasStream;
642
newDatabase.Files.Add(file);
661
newDatabase.AddFile(file, file2);
666
folderRefs.ClearAndFree();
667
fileIndexToUpdateIndexMap.ClearAndFree();
647
669
/////////////////////////////////////////
648
670
// Compress New Files
650
672
CObjectVector<CSolidGroup> groups;
651
SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter,
673
SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter,
652
674
updateItems, groups);
654
676
const UInt32 kMinReduceSize = (1 << 16);
724
746
int startPackIndex = newDatabase.PackSizes.Size();
725
747
RINOK(encoder.Encode(
726
748
EXTERNAL_CODECS_LOC_VARS
727
solidInStream, NULL, &inSizeForReduce, folderItem,
749
solidInStream, NULL, &inSizeForReduce, folderItem,
728
750
archive.SeqStream, newDatabase.PackSizes, progress));
730
752
for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
731
753
lps->OutSize += newDatabase.PackSizes[startPackIndex];
733
lps->InSize += folderItem.GetUnPackSize();
755
lps->InSize += folderItem.GetUnpackSize();
735
757
// newDatabase.PackCRCsDefined.Add(false);
736
758
// newDatabase.PackCRCs.Add(0);
738
760
newDatabase.Folders.Add(folderItem);
740
CNum numUnPackStreams = 0;
762
CNum numUnpackStreams = 0;
741
763
for (int subIndex = 0; subIndex < numSubFiles; subIndex++)
743
const CUpdateItem &updateItem = updateItems[indices[i + subIndex]];
765
const CUpdateItem &ui = updateItems[indices[i + subIndex]];
745
if (updateItem.NewProperties)
746
FromUpdateItemToFileItem(updateItem, file);
768
if (ui.NewProperties)
769
FromUpdateItemToFileItem(ui, file, file2);
748
file = database->Files[updateItem.IndexInArchive];
749
if (file.IsAnti || file.IsDirectory)
771
db->GetFile(ui.IndexInArchive, file, file2);
772
if (file2.IsAnti || file.IsDir)
788
813
CRecordVector<int> emptyRefs;
789
814
for(i = 0; i < updateItems.Size(); i++)
791
const CUpdateItem &updateItem = updateItems[i];
792
if (updateItem.NewData)
816
const CUpdateItem &ui = updateItems[i];
794
if (updateItem.HasStream())
798
if (updateItem.IndexInArchive != -1)
799
if (database->Files[updateItem.IndexInArchive].HasStream)
823
if (ui.IndexInArchive != -1)
824
if (db->Files[ui.IndexInArchive].HasStream)
801
826
emptyRefs.Add(i);
803
828
emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
804
for(i = 0; i < emptyRefs.Size(); i++)
829
for (i = 0; i < emptyRefs.Size(); i++)
806
const CUpdateItem &updateItem = updateItems[emptyRefs[i]];
831
const CUpdateItem &ui = updateItems[emptyRefs[i]];
808
if (updateItem.NewProperties)
809
FromUpdateItemToFileItem(updateItem, file);
834
if (ui.NewProperties)
835
FromUpdateItemToFileItem(ui, file, file2);
811
file = database->Files[updateItem.IndexInArchive];
812
newDatabase.Files.Add(file);
817
if (newDatabase.Files.Size() != updateItems.Size())
821
return archive.WriteDatabase(EXTERNAL_CODECS_LOC_VARS
822
newDatabase, options.HeaderMethod, options.HeaderOptions);
827
static const UInt64 k_Copy = 0x0;
829
static HRESULT WriteVolumeHeader(COutArchive &archive, CFileItem &file, const CUpdateOptions &options)
832
coder.NumInStreams = coder.NumOutStreams = 1;
833
coder.MethodID = k_Copy;
836
folder.Coders.Add(coder);
837
folder.PackStreams.Add(0);
839
CNum numUnPackStreams = 0;
840
if (file.UnPackSize != 0)
842
file.IsFileCRCDefined = true;
843
file.HasStream = true;
849
file.IsFileCRCDefined = false;
850
file.HasStream = false;
852
folder.UnPackSizes.Add(file.UnPackSize);
854
CArchiveDatabase newDatabase;
855
newDatabase.Files.Add(file);
856
newDatabase.Folders.Add(folder);
857
newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams);
858
newDatabase.PackSizes.Add(file.UnPackSize);
859
newDatabase.PackCRCsDefined.Add(false);
860
newDatabase.PackCRCs.Add(file.FileCRC);
862
return archive.WriteDatabase(newDatabase,
863
options.HeaderMethod,
868
HRESULT UpdateVolume(
870
const CArchiveDatabaseEx *database,
871
CObjectVector<CUpdateItem> &updateItems,
872
ISequentialOutStream *seqOutStream,
873
IArchiveUpdateCallback *updateCallback,
874
const CUpdateOptions &options)
876
if (updateItems.Size() != 1)
879
CMyComPtr<IArchiveUpdateCallback2> volumeCallback;
880
RINOK(updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&volumeCallback));
884
CMyComPtr<ISequentialInStream> fileStream;
885
HRESULT result = updateCallback->GetStream(0, &fileStream);
886
if (result != S_OK && result != S_FALSE)
888
if (result == S_FALSE)
893
const CUpdateItem &updateItem = updateItems[0];
894
if (updateItem.NewProperties)
895
FromUpdateItemToFileItem(updateItem, file);
897
file = database->Files[updateItem.IndexInArchive];
898
if (file.IsAnti || file.IsDirectory)
901
UInt64 complexity = 0;
902
file.IsStartPosDefined = true;
904
for (UInt64 volumeIndex = 0; true; volumeIndex++)
907
RINOK(volumeCallback->GetVolumeSize(volumeIndex, &volSize));
908
UInt64 pureSize = COutArchive::GetVolPureSize(volSize, file.Name.Length(), true);
909
CMyComPtr<ISequentialOutStream> volumeStream;
910
RINOK(volumeCallback->GetVolumeStream(volumeIndex, &volumeStream));
913
RINOK(archive.Create(volumeStream, true));
914
RINOK(archive.SkeepPrefixArchiveHeader());
916
CSequentialInStreamWithCRC *inCrcStreamSpec = new CSequentialInStreamWithCRC;
917
CMyComPtr<ISequentialInStream> inCrcStream = inCrcStreamSpec;
918
inCrcStreamSpec->Init(fileStream);
920
RINOK(WriteRange(inCrcStream, volumeStream, pureSize, updateCallback, complexity));
921
file.UnPackSize = inCrcStreamSpec->GetSize();
922
if (file.UnPackSize == 0)
924
file.FileCRC = inCrcStreamSpec->GetCRC();
925
RINOK(WriteVolumeHeader(archive, file, options));
926
file.StartPos += file.UnPackSize;
927
if (file.UnPackSize < pureSize)
933
class COutVolumeStream:
934
public ISequentialOutStream,
940
CMyComPtr<ISequentialOutStream> _volumeStream;
941
COutArchive _archive;
948
CUpdateOptions _options;
949
CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
950
void Init(IArchiveUpdateCallback2 *volumeCallback,
954
_file.IsStartPosDefined = true;
957
VolumeCallback = volumeCallback;
963
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
966
HRESULT COutVolumeStream::Flush()
970
_file.UnPackSize = _curPos;
971
_file.FileCRC = _crc.GetDigest();
972
RINOK(WriteVolumeHeader(_archive, _file, _options));
974
_volumeStream.Release();
975
_file.StartPos += _file.UnPackSize;
980
STDMETHODIMP COutVolumeStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
982
if(processedSize != NULL)
988
RINOK(VolumeCallback->GetVolumeSize(_volIndex, &_volSize));
989
RINOK(VolumeCallback->GetVolumeStream(_volIndex, &_volumeStream));
992
RINOK(_archive.Create(_volumeStream, true));
993
RINOK(_archive.SkeepPrefixArchiveHeader());
997
UInt64 pureSize = COutArchive::GetVolPureSize(_volSize, _file.Name.Length());
998
UInt32 curSize = (UInt32)MyMin(UInt64(size), pureSize - _curPos);
1000
_crc.Update(data, curSize);
1001
UInt32 realProcessed;
1002
RINOK(_volumeStream->Write(data, curSize, &realProcessed))
1003
data = (void *)((Byte *)data + realProcessed);
1004
size -= realProcessed;
1005
if(processedSize != NULL)
1006
*processedSize += realProcessed;
1007
_curPos += realProcessed;
1008
if (realProcessed != curSize && realProcessed == 0)
1010
if (_curPos == pureSize)
837
db->GetFile(ui.IndexInArchive, file, file2);
838
newDatabase.AddFile(file, file2);
842
newDatabase.ReserveDown();
1021
847
DECL_EXTERNAL_CODECS_LOC_VARS
1022
848
IInStream *inStream,
1023
const CArchiveDatabaseEx *database,
849
const CArchiveDatabaseEx *db,
1024
850
const CObjectVector<CUpdateItem> &updateItems,
851
COutArchive &archive,
852
CArchiveDatabase &newDatabase,
1025
853
ISequentialOutStream *seqOutStream,
1026
854
IArchiveUpdateCallback *updateCallback,
1027
855
const CUpdateOptions &options)
1033
858
EXTERNAL_CODECS_LOC_VARS
1034
inStream, database, updateItems,
1035
seqOutStream, updateCallback, options);
1037
if (options.VolumeMode)
1038
return UpdateVolume(inStream, database, updateItems,
1039
seqOutStream, updateCallback, options);
1040
COutVolumeStream *volStreamSpec = new COutVolumeStream;
1041
CMyComPtr<ISequentialOutStream> volStream = volStreamSpec;
1042
CMyComPtr<IArchiveUpdateCallback2> volumeCallback;
1043
RINOK(updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&volumeCallback));
1044
if (!volumeCallback)
1046
volStreamSpec->Init(volumeCallback, L"a.7z");
1047
volStreamSpec->_options = options;
1048
RINOK(Update2(inStream, database, updateItems,
1049
volStream, updateCallback, options));
1050
return volStreamSpec->Flush();
859
inStream, db, updateItems,
860
archive, newDatabase, seqOutStream, updateCallback, options);