675 lines
31 KiB
C++
675 lines
31 KiB
C++
// sync_info_client.cpp
|
|
// sync_client
|
|
// Created by housisong on 2019-09-18.
|
|
/*
|
|
The MIT License (MIT)
|
|
Copyright (c) 2019-2023 HouSisong
|
|
|
|
Permission is hereby granted, free of charge, to any person
|
|
obtaining a copy of this software and associated documentation
|
|
files (the "Software"), to deal in the Software without
|
|
restriction, including without limitation the rights to use,
|
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following
|
|
conditions:
|
|
|
|
The above copyright notice and this permission notice shall be
|
|
included in all copies of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
#include "sync_info_client.h"
|
|
#include "sync_client_type_private.h"
|
|
#include "../../file_for_patch.h"
|
|
#include "../../libHDiffPatch/HPatch/patch_private.h"
|
|
#if (_IS_NEED_DIR_DIFF_PATCH)
|
|
#include "../../dirDiffPatch/dir_patch/dir_patch_tools.h"
|
|
#include "../../dirDiffPatch/dir_diff/dir_diff_tools.h"
|
|
#endif
|
|
#if (_IS_NEED_DIR_DIFF_PATCH)
|
|
void TNewDataSyncInfo_dir_saveTo(TNewDataSyncInfo_dir* self,std::vector<hpatch_byte>& out_buf){
|
|
self->dir_newPathSumCharSize=0;
|
|
{
|
|
hdiff_private::packIncList(out_buf,self->dir_newExecuteIndexList,self->dir_newExecuteCount);
|
|
hdiff_private::packList(out_buf,self->dir_newSizeList,self->dir_newPathCount);
|
|
checkv(!self->dir_newNameList_isCString);
|
|
self->dir_newPathSumCharSize=hdiff_private::pushNameList(out_buf,self->dir_utf8NewRootPath,
|
|
(std::string*)self->dir_utf8NewNameList,self->dir_newPathCount);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
namespace sync_private{
|
|
#ifdef check
|
|
# undef check
|
|
#endif
|
|
#define check(v,errorCode) \
|
|
do{ if (!(v)) { if (result==kSyncClient_ok) result=errorCode; \
|
|
if (!_inClear) goto clear; } }while(0)
|
|
|
|
#define _clip_unpackUIntTo(puint,sclip) \
|
|
_TStreamCacheClip_unpackUIntWithTag(sclip,puint,0)
|
|
|
|
template<class Type_t>
|
|
static hpatch_BOOL __clip_unpackToType_t(Type_t* out_v,TStreamCacheClip* clip,hpatch_uint kTagBit=0){
|
|
if (sizeof(Type_t)==sizeof(hpatch_StreamPos_t)){
|
|
return _TStreamCacheClip_unpackUIntWithTag(clip,(hpatch_StreamPos_t*)out_v,kTagBit);
|
|
}else{
|
|
hpatch_StreamPos_t v;
|
|
hpatch_BOOL ret=_TStreamCacheClip_unpackUIntWithTag(clip,&v,kTagBit);
|
|
Type_t tv=(Type_t)v;
|
|
*out_v=tv;
|
|
return ret&&(tv==v);
|
|
}
|
|
}
|
|
|
|
inline static hpatch_BOOL _clip_unpackToUInt32(uint32_t* out_v,TStreamCacheClip* clip,hpatch_uint kTagBit=0){
|
|
return __clip_unpackToType_t<uint32_t>(out_v,clip,kTagBit);
|
|
}
|
|
inline static hpatch_BOOL _clip_unpackToSize_t(size_t* out_v,TStreamCacheClip* clip){
|
|
return __clip_unpackToType_t<size_t>(out_v,clip);
|
|
}
|
|
inline static hpatch_BOOL _clip_unpackToByte(hpatch_byte* out_v,TStreamCacheClip* clip){
|
|
return _TStreamCacheClip_readDataTo(clip,out_v,out_v+1);
|
|
}
|
|
|
|
struct TChecksumInputStream:public hpatch_TStreamInput {
|
|
inline TChecksumInputStream()
|
|
:_base(0),_checksumPlugin(0),_checksum(0),_curReadPos(0),_checksumByteSize(0),_checksumBuf(0) {
|
|
memset((hpatch_TStreamInput*)this,0,sizeof(hpatch_TStreamInput));
|
|
}
|
|
inline ~TChecksumInputStream(){
|
|
if (_checksum) _checksumPlugin->close(_checksumPlugin,_checksum);
|
|
if (_checksumBuf) free(_checksumBuf);
|
|
}
|
|
bool open(const hpatch_TStreamInput* base,hpatch_StreamPos_t newStreamSize,
|
|
hpatch_TChecksum* checksumPlugin){
|
|
assert(_checksum==0);
|
|
if (newStreamSize>base->streamSize)
|
|
return false;
|
|
_base=base;
|
|
_checksumPlugin=checksumPlugin;
|
|
this->streamImport=this;
|
|
this->streamSize=newStreamSize;
|
|
this->read=_read;
|
|
|
|
_checksumByteSize=_checksumPlugin->checksumByteSize();
|
|
_checksum=_checksumPlugin->open(_checksumPlugin);
|
|
_checksumBuf=(TByte*)malloc(_checksumByteSize);
|
|
if (_checksum)
|
|
_checksumPlugin->begin(_checksum);
|
|
return _checksum!=0;
|
|
}
|
|
bool reopen(hpatch_StreamPos_t newStreamSize){
|
|
if (newStreamSize>_base->streamSize)
|
|
return false;
|
|
this->streamSize=newStreamSize;
|
|
if (_checksum)
|
|
_checksumPlugin->begin(_checksum);
|
|
return _checksum!=0;
|
|
}
|
|
TByte* finish(){
|
|
_checksumPlugin->end(_checksum,_checksumBuf,_checksumBuf+_checksumByteSize);
|
|
return _checksumBuf;
|
|
}
|
|
inline size_t checksumByteSize()const{ return _checksumByteSize; }
|
|
private:
|
|
hpatch_BOOL _read_(hpatch_StreamPos_t readFromPos,unsigned char* out_data,unsigned char* out_data_end){
|
|
hpatch_BOOL result=_base->read(_base,readFromPos,out_data,out_data_end);
|
|
if (result){
|
|
size_t readSize=(size_t)(out_data_end-out_data);
|
|
if (readFromPos>_curReadPos) { assert(false); return hpatch_FALSE; }
|
|
// _curReadPos|
|
|
// [ readSize ]
|
|
if (readFromPos+readSize>_curReadPos){
|
|
_checksumPlugin->append(_checksum,out_data+(_curReadPos-readFromPos),out_data_end);
|
|
_curReadPos=readFromPos+readSize;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
static hpatch_BOOL _read(const struct hpatch_TStreamInput* stream,hpatch_StreamPos_t readFromPos,
|
|
unsigned char* out_data,unsigned char* out_data_end){
|
|
TChecksumInputStream* self=(TChecksumInputStream*)stream->streamImport;
|
|
return self->_read_(readFromPos,out_data,out_data_end);
|
|
}
|
|
const hpatch_TStreamInput* _base;
|
|
hpatch_TChecksum* _checksumPlugin;
|
|
hpatch_checksumHandle _checksum;
|
|
hpatch_StreamPos_t _curReadPos;
|
|
size_t _checksumByteSize;
|
|
TByte* _checksumBuf;
|
|
};
|
|
|
|
template<class TUInt>
|
|
hpatch_inline static
|
|
hpatch_BOOL _clip_readUIntTo(TUInt* result,TStreamCacheClip* sclip){
|
|
hpatch_StreamPos_t v;
|
|
hpatch_BOOL rt=_TStreamCacheClip_unpackUIntWithTag(sclip,&v,0);
|
|
if (rt){
|
|
*result=(TUInt)v;
|
|
if ((sizeof(TUInt)<sizeof(hpatch_StreamPos_t))&&((*result)!=v))
|
|
return hpatch_FALSE;
|
|
}
|
|
return rt;
|
|
}
|
|
|
|
} //namespace sync_private
|
|
using namespace sync_private;
|
|
|
|
|
|
TSyncClient_resultType _checkNewSyncInfoType(TStreamCacheClip* newSyncInfo_clip,hpatch_BOOL* out_newIsDir){
|
|
char tempType[hpatch_kMaxPluginTypeLength+1];
|
|
TSyncClient_resultType result=kSyncClient_ok;
|
|
int _inClear=0;
|
|
check(_TStreamCacheClip_readType_end(newSyncInfo_clip,'&',tempType),
|
|
kSyncClient_newSyncInfoTypeError);
|
|
if (0==strcmp(tempType,"HSyni23"))
|
|
*out_newIsDir=hpatch_FALSE;
|
|
#if (_IS_NEED_DIR_DIFF_PATCH)
|
|
else if (0==strcmp(tempType,"HDirSyni23"))
|
|
*out_newIsDir=hpatch_TRUE;
|
|
#endif
|
|
else //unknow type
|
|
check(hpatch_FALSE,kSyncClient_newSyncInfoTypeError);
|
|
clear:
|
|
_inClear=1;
|
|
return result;
|
|
}
|
|
|
|
TSyncClient_resultType checkNewSyncInfoType(const hpatch_TStreamInput* newSyncInfo,hpatch_BOOL* out_newIsDir){
|
|
TStreamCacheClip clip;
|
|
TByte temp_cache[hpatch_kMaxPluginTypeLength+1];
|
|
_TStreamCacheClip_init(&clip,newSyncInfo,0,newSyncInfo->streamSize,temp_cache,sizeof(temp_cache));
|
|
return _checkNewSyncInfoType(&clip,out_newIsDir);
|
|
}
|
|
|
|
TSyncClient_resultType checkNewSyncInfoType_by_file(const char* newSyncInfoFile,hpatch_BOOL* out_newIsDir){
|
|
hpatch_TFileStreamInput newSyncInfo;
|
|
hpatch_TFileStreamInput_init(&newSyncInfo);
|
|
TSyncClient_resultType result=kSyncClient_ok;
|
|
int _inClear=0;
|
|
check(hpatch_TFileStreamInput_open(&newSyncInfo,newSyncInfoFile), kSyncClient_newSyncInfoOpenError);
|
|
result=checkNewSyncInfoType(&newSyncInfo.base,out_newIsDir);
|
|
clear:
|
|
_inClear=1;
|
|
check(hpatch_TFileStreamInput_close(&newSyncInfo), kSyncClient_newSyncInfoCloseError);
|
|
return result;
|
|
}
|
|
|
|
static bool readSamePairListTo(TStreamCacheClip* codeClip,TSameNewBlockPair* samePairList,
|
|
size_t samePairCount,uint32_t kBlockCount){
|
|
uint32_t pre=0;
|
|
for (size_t i=0;i<samePairCount;++i){
|
|
TSameNewBlockPair& sp=samePairList[i];
|
|
uint32_t v;
|
|
if (!_clip_unpackToUInt32(&v,codeClip)) return false;
|
|
sp.curIndex=v+pre;
|
|
if (sp.curIndex>=kBlockCount) return false;
|
|
if (!_clip_unpackToUInt32(&v,codeClip)) return false;
|
|
if (v>sp.curIndex) return false;
|
|
sp.sameIndex=sp.curIndex-v;
|
|
pre=sp.curIndex;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool _clip_readSavedSize(uint32_t* value,uint32_t* tag,TStreamCacheClip* codeClip){
|
|
const hpatch_byte* buf=_TStreamCacheClip_accessData(codeClip,1);
|
|
if (buf==0) return false;
|
|
*tag=buf[0]>>7;
|
|
return _clip_unpackToUInt32(value,codeClip,1);
|
|
}
|
|
static bool readSavedSizesTo(TStreamCacheClip* codeClip,TNewDataSyncInfo* self){
|
|
uint32_t kBlockCount=(uint32_t)TNewDataSyncInfo_blockCount(self);
|
|
uint32_t backSize=0;
|
|
hpatch_StreamPos_t sumSavedSize=0;
|
|
for (uint32_t i=0; i<kBlockCount; ++i){
|
|
uint32_t savedSize;
|
|
uint32_t highTag;
|
|
if (!_clip_readSavedSize(&savedSize,&highTag,codeClip)) return false;
|
|
if (highTag==0){
|
|
savedSize+=backSize;
|
|
backSize=savedSize;
|
|
}else if (savedSize>0){
|
|
savedSize=backSize-savedSize;
|
|
backSize=savedSize;
|
|
}else{
|
|
backSize=self->kSyncBlockSize;
|
|
}
|
|
self->savedSizes[i]=savedSize;
|
|
sumSavedSize+=(savedSize>0)?savedSize:TNewDataSyncInfo_newDataBlockSize(self,i);
|
|
}
|
|
if (sumSavedSize>self->newSyncDataSize) return false;
|
|
return true;
|
|
}
|
|
|
|
static bool readPartHashTo(TStreamCacheClip* clip,TByte* partHash,size_t partBits,
|
|
TSameNewBlockPair* samePairList,size_t samePairCount,uint32_t kBlockCount){
|
|
uint32_t curPair=0;
|
|
TByte* curPartChecksum=partHash;
|
|
const size_t partBytes=_bitsToBytes(partBits);
|
|
size_t bitsValue=0;
|
|
size_t bitsCount=0;
|
|
const size_t highBit=(partBits&7)?(partBits&7):8;
|
|
for (size_t i=0; i<kBlockCount; ++i,curPartChecksum+=partBytes){
|
|
if ((curPair<samePairCount)&&(i==samePairList[curPair].curIndex)){
|
|
size_t sameIndex=samePairList[curPair].sameIndex;
|
|
memcpy(curPartChecksum,partHash+sameIndex*partBytes,partBytes);
|
|
++curPair;
|
|
}else{
|
|
for (size_t j=0;j<partBytes;++j){
|
|
if (bitsCount<8){//read a byte
|
|
hpatch_byte v;
|
|
if (!_TStreamCacheClip_readDataTo(clip,&v,(&v)+1))
|
|
return false;
|
|
bitsValue|=(((size_t)v)<<bitsCount);
|
|
bitsCount+=8;
|
|
}
|
|
if (j==0){
|
|
curPartChecksum[j]=bitsValue&((1<<highBit)-1);
|
|
bitsValue>>=highBit;
|
|
bitsCount-=highBit;
|
|
}else{
|
|
curPartChecksum[j]=(hpatch_byte)bitsValue;
|
|
bitsValue>>=8;
|
|
bitsCount-=8;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (bitsValue!=0) return false;
|
|
if (curPair!=samePairCount) return false;
|
|
return true;
|
|
}
|
|
|
|
typedef struct{
|
|
hsync_TDictDecompress* decompressPlugin;
|
|
hsync_dictDecompressHandle decompressHandle;
|
|
} _TDictDecompressInputStream;
|
|
|
|
#if (_IS_NEED_DIR_DIFF_PATCH)
|
|
static hpatch_BOOL _readDirHead(TNewDataSyncInfo_dir* dirInfo,TStreamCacheClip* clip){
|
|
if (!_clip_unpackToSize_t(&dirInfo->dir_newExecuteCount,clip)) return hpatch_FALSE;
|
|
if (!_clip_unpackToSize_t(&dirInfo->dir_newPathCount,clip)) return hpatch_FALSE;
|
|
if (!_clip_unpackToSize_t(&dirInfo->dir_newPathSumCharSize,clip)) return hpatch_FALSE;
|
|
return hpatch_TRUE;
|
|
}
|
|
#endif
|
|
|
|
static TSyncClient_resultType
|
|
_TNewDataSyncInfo_open(TNewDataSyncInfo* self,const hpatch_TStreamInput* newSyncInfo,
|
|
ISyncInfoListener *listener){
|
|
assert(self->_import==0);
|
|
hsync_TDictDecompress* decompressPlugin=0;
|
|
hpatch_TChecksum* strongChecksumPlugin=0;
|
|
TStreamCacheClip clip;
|
|
TSyncClient_resultType result=kSyncClient_ok;
|
|
int _inClear=0;
|
|
|
|
hpatch_BOOL newIsDir_byType=hpatch_FALSE;
|
|
uint32_t kBlockCount=0;
|
|
const char* checksumType=0;
|
|
char compressType[hpatch_kMaxPluginTypeLength+1];
|
|
hpatch_StreamPos_t headEndPos=0;
|
|
hpatch_StreamPos_t privateExternDataSize=0;
|
|
hpatch_StreamPos_t externDataSize=0;
|
|
hpatch_StreamPos_t uncompressDataSize=0;
|
|
hpatch_StreamPos_t compressDataSize=0;
|
|
_TDictDecompressInputStream decompresser;
|
|
TChecksumInputStream checksumInputStream;
|
|
const bool isChecksumNewSyncInfo=true;
|
|
uint8_t isSavedSizes=0;
|
|
const size_t kFileIOBufBetterSize=hpatch_kFileIOBufBetterSize;
|
|
TByte* temp_cache=(TByte*)malloc(kFileIOBufBetterSize);
|
|
check(temp_cache!=0,kSyncClient_memError);
|
|
memset(&decompresser,0,sizeof(decompresser));
|
|
{//head
|
|
char tempType[hpatch_kMaxPluginTypeLength+1];
|
|
const size_t kHeadCacheSize =1024*2;
|
|
assert(kFileIOBufBetterSize>=kHeadCacheSize);
|
|
_TStreamCacheClip_init(&clip,newSyncInfo,0,newSyncInfo->streamSize,
|
|
temp_cache,isChecksumNewSyncInfo?kHeadCacheSize:kFileIOBufBetterSize);
|
|
{//type
|
|
result=_checkNewSyncInfoType(&clip,&newIsDir_byType);
|
|
check(result==kSyncClient_ok,result);
|
|
}
|
|
{//read compressType
|
|
check(_TStreamCacheClip_readType_end(&clip,'&',compressType),kSyncClient_noDecompressPluginError);
|
|
|
|
}
|
|
{//read strongChecksumType
|
|
check(_TStreamCacheClip_readType_end(&clip,'\0',tempType),kSyncClient_noStrongChecksumPluginError);
|
|
strongChecksumPlugin=listener->findChecksumPlugin(listener,tempType);
|
|
check(strongChecksumPlugin!=0,kSyncClient_noStrongChecksumPluginError);
|
|
checksumType=strongChecksumPlugin->checksumType();
|
|
check(0==strcmp(tempType,checksumType),kSyncClient_noStrongChecksumPluginError);
|
|
self->_strongChecksumPlugin=strongChecksumPlugin;
|
|
}
|
|
check(_clip_unpackToSize_t(&self->dictSize,&clip), kSyncClient_newSyncInfoDataError);
|
|
if (strlen(compressType)>0){
|
|
decompressPlugin=listener->findDecompressPlugin(listener,compressType,self->dictSize);
|
|
check(decompressPlugin!=0,kSyncClient_noDecompressPluginError);
|
|
self->_decompressPlugin=decompressPlugin;
|
|
}
|
|
|
|
check(_clip_unpackToByte(&self->decompressInfoSize,&clip),kSyncClient_newSyncInfoDataError);
|
|
check(self->decompressInfoSize<=kDecompressInfoMaxSize,kSyncClient_newSyncInfoDataError);
|
|
check(_TStreamCacheClip_readDataTo(&clip,self->decompressInfo,
|
|
self->decompressInfo+self->decompressInfoSize),kSyncClient_newSyncInfoDataError);
|
|
|
|
check(_clip_unpackUIntTo(&self->newSyncDataSize,&clip),kSyncClient_newSyncInfoDataError);
|
|
check(_clip_unpackUIntTo(&self->newSyncDataOffsert,&clip),kSyncClient_newSyncInfoDataError);
|
|
check(_clip_unpackUIntTo(&self->newDataSize,&clip),kSyncClient_newSyncInfoDataError);
|
|
if (self->_decompressPlugin){
|
|
static const hpatch_StreamPos_t _kDictSizeSafeLimit =(1<<20)*16;
|
|
check((self->dictSize/2)<(self->newDataSize>=_kDictSizeSafeLimit?self->newDataSize:_kDictSizeSafeLimit),
|
|
kSyncClient_newSyncInfoDataError);
|
|
decompressPlugin=listener->findDecompressPlugin(listener,compressType,self->dictSize);
|
|
check(decompressPlugin!=0,kSyncClient_noDecompressPluginError);
|
|
self->_decompressPlugin=decompressPlugin;
|
|
}
|
|
|
|
check(_clip_unpackToUInt32(&self->kSyncBlockSize,&clip),kSyncClient_newSyncInfoDataError);
|
|
check((self->kSyncBlockSize<=(self->newDataSize<=_kSyncBlockSize_min_limit?_kSyncBlockSize_min_limit:self->newDataSize))
|
|
&&(self->kSyncBlockSize>=_kSyncBlockSize_min_limit),kSyncClient_newSyncInfoDataError);
|
|
check(_clip_unpackToSize_t(&self->kStrongChecksumByteSize,&clip),kSyncClient_newSyncInfoDataError);
|
|
check(strongChecksumPlugin->checksumByteSize()==self->kStrongChecksumByteSize,
|
|
kSyncClient_strongChecksumByteSizeError);
|
|
check(_clip_unpackToSize_t(&self->savedStrongChecksumBits,&clip),kSyncClient_newSyncInfoDataError);
|
|
self->savedStrongChecksumByteSize=_bitsToBytes(self->savedStrongChecksumBits);
|
|
check((self->savedStrongChecksumByteSize<=self->kStrongChecksumByteSize),
|
|
kSyncClient_strongChecksumByteSizeError);
|
|
check(_clip_unpackToSize_t(&self->savedRollHashBits,&clip),kSyncClient_newSyncInfoDataError);
|
|
check((size_t)(self->savedRollHashBits-1)<sizeof(uint64_t)*8,kSyncClient_newSyncInfoDataError);
|
|
self->savedRollHashByteSize=_bitsToBytes(self->savedRollHashBits);
|
|
check(_clip_unpackToUInt32(&self->samePairCount,&clip),kSyncClient_newSyncInfoDataError);
|
|
check(_clip_unpackToByte(&isSavedSizes,&clip),kSyncClient_newSyncInfoDataError);
|
|
check(_clip_unpackUIntTo(&privateExternDataSize,&clip),kSyncClient_newSyncInfoDataError);
|
|
check(_clip_unpackUIntTo(&externDataSize,&clip),kSyncClient_newSyncInfoDataError);
|
|
|
|
check(_clip_unpackUIntTo(&uncompressDataSize,&clip),kSyncClient_newSyncInfoDataError);
|
|
check(_clip_unpackUIntTo(&compressDataSize,&clip),kSyncClient_newSyncInfoDataError);
|
|
check((compressDataSize==0)||(compressDataSize<uncompressDataSize),kSyncClient_newSyncInfoDataError);
|
|
if (compressDataSize>0) check(decompressPlugin!=0,kSyncClient_newSyncInfoDataError);
|
|
|
|
check(_clip_unpackToByte(&self->isDirSyncInfo,&clip),kSyncClient_newSyncInfoDataError);
|
|
check(newIsDir_byType==self->isDirSyncInfo, kSyncClient_newSyncInfoTypeError);
|
|
#if (_IS_NEED_DIR_DIFF_PATCH)
|
|
if (self->isDirSyncInfo){
|
|
check(_clip_unpackToSize_t(&self->dirInfoSavedSize,&clip),kSyncClient_newSyncInfoDataError);
|
|
check(self->dirInfoSavedSize<self->newDataSize,kSyncClient_newSyncInfoDataError);
|
|
check(_readDirHead(&self->dirInfo,&clip),kSyncClient_newSyncInfoDataError);
|
|
}
|
|
#endif
|
|
check(_clip_unpackUIntTo(&self->newSyncInfoSize,&clip),kSyncClient_newSyncInfoDataError);
|
|
check(newSyncInfo->streamSize==self->newSyncInfoSize,kSyncClient_newSyncInfoDataError);
|
|
{
|
|
hpatch_StreamPos_t v=TNewDataSyncInfo_blockCount(self);
|
|
kBlockCount=(uint32_t)v;
|
|
check((kBlockCount==v),kSyncClient_newSyncInfoDataError);
|
|
}
|
|
headEndPos=_TStreamCacheClip_readPosOfSrcStream(&clip);
|
|
self->infoChecksumEndPos= headEndPos + privateExternDataSize + externDataSize
|
|
+ ((compressDataSize>0)?compressDataSize:uncompressDataSize)
|
|
+ self->kStrongChecksumByteSize*2;
|
|
}
|
|
hpatch_StreamPos_t memSize;
|
|
{//mem
|
|
size_t headMaxSize=sizeof(hpatch_StreamPos_t)*5+ strlen(compressType)+1+strlen(checksumType)+1
|
|
+self->kStrongChecksumByteSize*2+checkChecksumBufByteSize(self->kStrongChecksumByteSize);
|
|
TByte* curMem=0;
|
|
memSize=headMaxSize;
|
|
memSize+=self->samePairCount*sizeof(TSameNewBlockPair);
|
|
if (isSavedSizes)
|
|
memSize+=sizeof(uint32_t)*(hpatch_StreamPos_t)kBlockCount;
|
|
#if (_IS_NEED_DIR_DIFF_PATCH)
|
|
if (self->isDirSyncInfo){
|
|
self->dirInfo.dir_newNameList_isCString=hpatch_TRUE;
|
|
memSize+=self->dirInfo.dir_newPathSumCharSize + sizeof(const char*)*self->dirInfo.dir_newPathCount
|
|
+sizeof(hpatch_StreamPos_t)*self->dirInfo.dir_newPathCount
|
|
+sizeof(size_t)*self->dirInfo.dir_newExecuteCount;
|
|
}
|
|
#endif
|
|
memSize+=(self->savedRollHashByteSize+self->savedStrongChecksumByteSize)*(hpatch_StreamPos_t)kBlockCount;
|
|
|
|
const hpatch_StreamPos_t _kSafeTempMemSize=uncompressDataSize+compressDataSize+headMaxSize+1024;
|
|
if ((compressDataSize>0)&&(memSize<_kSafeTempMemSize))
|
|
memSize=_kSafeTempMemSize;
|
|
check(memSize==(size_t)memSize,kSyncClient_memError);
|
|
curMem=(TByte*)malloc((size_t)memSize);
|
|
check(curMem!=0,kSyncClient_memError);
|
|
self->_import=curMem;
|
|
|
|
if (decompressPlugin!=0){
|
|
self->compressType=(const char*)curMem;
|
|
curMem+=strlen(compressType)+1;
|
|
memcpy((TByte*)self->compressType,compressType,strlen(compressType)+1);
|
|
}
|
|
self->strongChecksumType=(const char*)curMem;
|
|
curMem+=strlen(checksumType)+1;
|
|
memcpy((TByte*)self->strongChecksumType,checksumType,curMem-(TByte*)self->strongChecksumType);
|
|
|
|
curMem=(TByte*)_hpatch_align_upper(curMem,sizeof(hpatch_StreamPos_t));
|
|
self->infoChecksum=curMem;
|
|
curMem+=self->kStrongChecksumByteSize;
|
|
self->infoPartHashChecksum=curMem;
|
|
curMem+=self->kStrongChecksumByteSize;
|
|
self->savedNewDataCheckChecksum=curMem;
|
|
curMem+=checkChecksumBufByteSize(self->kStrongChecksumByteSize);
|
|
|
|
curMem=(TByte*)_hpatch_align_upper(curMem,sizeof(hpatch_StreamPos_t));
|
|
self->samePairList=(TSameNewBlockPair*)curMem;
|
|
curMem+=self->samePairCount*sizeof(TSameNewBlockPair);
|
|
if (isSavedSizes){
|
|
self->savedSizes=(uint32_t*)curMem;
|
|
curMem+=sizeof(uint32_t)*(size_t)kBlockCount;
|
|
}
|
|
#if (_IS_NEED_DIR_DIFF_PATCH)
|
|
if (self->isDirSyncInfo){
|
|
curMem=(TByte*)_hpatch_align_upper(curMem,sizeof(hpatch_StreamPos_t));
|
|
self->dirInfo.dir_newSizeList=(hpatch_StreamPos_t*)curMem;
|
|
curMem+=sizeof(hpatch_StreamPos_t)*self->dirInfo.dir_newPathCount;
|
|
self->dirInfo.dir_utf8NewNameList=(const char**)curMem;
|
|
curMem+=sizeof(const char*)*self->dirInfo.dir_newPathCount;
|
|
self->dirInfo.dir_newExecuteIndexList=(size_t*)curMem;
|
|
curMem+=sizeof(size_t)*self->dirInfo.dir_newExecuteCount;
|
|
if (self->dirInfo.dir_newPathCount>0){
|
|
((const char**)self->dirInfo.dir_utf8NewNameList)[0]=(char*)curMem;
|
|
curMem+=self->dirInfo.dir_newPathSumCharSize;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
curMem=(TByte*)_hpatch_align_upper(curMem,sizeof(hpatch_StreamPos_t));
|
|
self->rollHashs=curMem;
|
|
curMem+=self->savedRollHashByteSize*(size_t)kBlockCount;
|
|
curMem=(TByte*)_hpatch_align_upper(curMem,sizeof(hpatch_StreamPos_t));
|
|
self->partChecksums=curMem;
|
|
curMem+=self->savedStrongChecksumByteSize*(size_t)kBlockCount;
|
|
assert(curMem<=(TByte*)self->_import+memSize);
|
|
}
|
|
if (isChecksumNewSyncInfo){
|
|
//reload clip for infoFullChecksum
|
|
check(checksumInputStream.open(newSyncInfo,self->infoChecksumEndPos-self->kStrongChecksumByteSize,
|
|
strongChecksumPlugin), kSyncClient_strongChecksumOpenError);
|
|
_TStreamCacheClip_init(&clip,&checksumInputStream,0,checksumInputStream.streamSize,
|
|
temp_cache,kFileIOBufBetterSize);
|
|
check(_TStreamCacheClip_skipData(&clip,headEndPos), //checksum head data[0--headEndPos)
|
|
kSyncClient_newSyncInfoDataError);
|
|
}
|
|
{//load saved newDataCheckChecksum
|
|
check(_TStreamCacheClip_readDataTo(&clip,self->savedNewDataCheckChecksum,self->savedNewDataCheckChecksum
|
|
+self->kStrongChecksumByteSize),kSyncClient_newSyncInfoDataError);
|
|
}
|
|
if (privateExternDataSize>0){
|
|
check(_TStreamCacheClip_skipData(&clip,privateExternDataSize), //reserved ,now unknow
|
|
kSyncClient_newSyncInfoDataError);
|
|
}
|
|
if (externDataSize>0){
|
|
check(_TStreamCacheClip_skipData(&clip,externDataSize), //reserved ,now unknow
|
|
kSyncClient_newSyncInfoDataError);
|
|
}
|
|
|
|
{// compressed? buf
|
|
#define _clear_decompresser(_decompresser) \
|
|
if (_decompresser.decompressHandle){ \
|
|
decompressPlugin->dictDecompressClose(decompressPlugin,_decompresser.decompressHandle); \
|
|
_decompresser.decompressHandle=0; }
|
|
TStreamCacheClip _cmCodeClip;
|
|
TStreamCacheClip* codeClip=0;
|
|
if (compressDataSize>0) {
|
|
TByte* decompressBuf=(TByte*)self->_import+(memSize-uncompressDataSize);
|
|
hpatch_byte* codeBuf=decompressBuf-compressDataSize;
|
|
hpatch_StreamPos_t curPos=_TStreamCacheClip_readPosOfSrcStream(&clip);
|
|
const hpatch_TStreamInput* inStream=isChecksumNewSyncInfo?&checksumInputStream:newSyncInfo;
|
|
|
|
check(inStream->read(inStream,curPos,codeBuf,codeBuf+compressDataSize),kSyncClient_newSyncInfoDataError);
|
|
decompresser.decompressPlugin=decompressPlugin;
|
|
decompresser.decompressHandle=decompressPlugin->dictDecompressOpen(decompressPlugin,1,(size_t)uncompressDataSize,0,0);
|
|
check((decompresser.decompressHandle!=0),kSyncClient_decompressOpenError);
|
|
check(decompressPlugin->dictDecompress(decompresser.decompressHandle,0,codeBuf,codeBuf+compressDataSize,
|
|
decompressBuf,decompressBuf+uncompressDataSize),
|
|
kSyncClient_decompressError);
|
|
|
|
codeClip=&_cmCodeClip;
|
|
_TStreamCacheClip_init(codeClip,0,0,0,decompressBuf,(size_t)uncompressDataSize);
|
|
codeClip->cacheBegin=0;
|
|
}else{
|
|
codeClip=&clip;
|
|
}
|
|
|
|
//samePairList
|
|
check(readSamePairListTo(codeClip,self->samePairList,self->samePairCount,kBlockCount),
|
|
kSyncClient_newSyncInfoDataError);
|
|
if (isSavedSizes) //savedSizes
|
|
check(readSavedSizesTo(codeClip,self),kSyncClient_newSyncInfoDataError);
|
|
else
|
|
assert(self->savedSizes==0);
|
|
if (compressDataSize>0)
|
|
_clear_decompresser(decompresser);
|
|
}
|
|
if (isChecksumNewSyncInfo){//info Checksum
|
|
check(newSyncInfo->read(newSyncInfo,checksumInputStream.streamSize,self->infoChecksum,
|
|
self->infoChecksum+self->kStrongChecksumByteSize),
|
|
kSyncClient_newSyncInfoDataError);
|
|
|
|
TByte* strongChecksumInfo=checksumInputStream.finish();
|
|
assert(self->kStrongChecksumByteSize==checksumInputStream.checksumByteSize());
|
|
check(0==memcmp(strongChecksumInfo,self->infoChecksum,self->kStrongChecksumByteSize),
|
|
kSyncClient_newSyncInfoChecksumError);
|
|
|
|
check(checksumInputStream.reopen(newSyncInfo->streamSize-self->kStrongChecksumByteSize),
|
|
kSyncClient_strongChecksumOpenError);
|
|
}
|
|
{
|
|
hpatch_StreamPos_t curPos=_TStreamCacheClip_readPosOfSrcStream(&clip);
|
|
const hpatch_TStreamInput* inStream=isChecksumNewSyncInfo?&checksumInputStream:newSyncInfo;
|
|
_TStreamCacheClip_init(&clip,inStream,curPos+compressDataSize,inStream->streamSize,
|
|
temp_cache,kFileIOBufBetterSize);
|
|
|
|
_TStreamCacheClip_skipData(&clip,self->kStrongChecksumByteSize);
|
|
}
|
|
|
|
//rollHashs
|
|
check(readPartHashTo(&clip,self->rollHashs,self->savedRollHashBits,self->samePairList,
|
|
self->samePairCount,kBlockCount), kSyncClient_newSyncInfoDataError);
|
|
//partStrongChecksums
|
|
check(readPartHashTo(&clip,self->partChecksums,self->savedStrongChecksumBits,
|
|
self->samePairList,self->samePairCount,
|
|
kBlockCount), kSyncClient_newSyncInfoDataError);
|
|
|
|
if (isChecksumNewSyncInfo){ //info partHash Checksum
|
|
const hpatch_StreamPos_t infoChecksumPos=_TStreamCacheClip_readPosOfSrcStream(&clip);
|
|
check(newSyncInfo->read(newSyncInfo,infoChecksumPos,self->infoPartHashChecksum,
|
|
self->infoPartHashChecksum+self->kStrongChecksumByteSize),
|
|
kSyncClient_newSyncInfoDataError);
|
|
|
|
TByte* strongChecksumInfo=checksumInputStream.finish();
|
|
assert(self->kStrongChecksumByteSize==checksumInputStream.checksumByteSize());
|
|
check(0==memcmp(strongChecksumInfo,self->infoPartHashChecksum,self->kStrongChecksumByteSize),
|
|
kSyncClient_newSyncInfoChecksumError);
|
|
}
|
|
check(_TStreamCacheClip_readPosOfSrcStream(&clip)+self->kStrongChecksumByteSize
|
|
==newSyncInfo->streamSize, kSyncClient_newSyncInfoDataError);
|
|
clear:
|
|
_inClear=1;
|
|
_clear_decompresser(decompresser);
|
|
if (result!=kSyncClient_ok) TNewDataSyncInfo_close(self);
|
|
if (temp_cache) free(temp_cache);
|
|
return result;
|
|
}
|
|
|
|
#if (_IS_NEED_DIR_DIFF_PATCH)
|
|
TSyncClient_resultType TNewDataSyncInfo_dir_load(TNewDataSyncInfo_dir* self,const hpatch_byte* buf,size_t bufSize){
|
|
TSyncClient_resultType result=kSyncClient_ok;
|
|
int _inClear=0;
|
|
TStreamCacheClip _clip;
|
|
TStreamCacheClip* clip=&_clip;
|
|
_TStreamCacheClip_init(clip,0,0,0,(hpatch_byte*)buf,bufSize);
|
|
clip->cacheBegin=0;
|
|
|
|
check(_readDirHead(self,clip),kSyncClient_savedNewDirInfoDataError);
|
|
|
|
//dir_newExecuteIndexList
|
|
check(readIncListTo(clip,self->dir_newExecuteIndexList,self->dir_newExecuteCount,
|
|
self->dir_newPathCount),kSyncClient_savedNewDirInfoDataError);
|
|
//dir_newSizeList
|
|
check(readListTo(clip,self->dir_newSizeList,self->dir_newPathCount),
|
|
kSyncClient_savedNewDirInfoDataError);
|
|
//dir_utf8NewNameList
|
|
if (self->dir_newPathCount>0){
|
|
char* charsBuf=((char**)self->dir_utf8NewNameList)[0];
|
|
check(_TStreamCacheClip_readDataTo(clip,(TByte*)charsBuf,
|
|
(TByte*)charsBuf+self->dir_newPathSumCharSize),
|
|
kSyncClient_savedNewDirInfoDataError);
|
|
formatDirTagForLoad(charsBuf,charsBuf+self->dir_newPathSumCharSize);
|
|
check(clipCStrsTo(charsBuf,charsBuf+self->dir_newPathSumCharSize,
|
|
(const char**)self->dir_utf8NewNameList,self->dir_newPathCount),
|
|
kSyncClient_savedNewDirInfoDataError);
|
|
}
|
|
clear:
|
|
_inClear=1;
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
void TNewDataSyncInfo_close(TNewDataSyncInfo* self){
|
|
if (self==0) return;
|
|
if (self->_import!=0) free(self->_import);
|
|
TNewDataSyncInfo_init(self);
|
|
}
|
|
|
|
TSyncClient_resultType TNewDataSyncInfo_open(TNewDataSyncInfo* self,const hpatch_TStreamInput* newSyncInfo,
|
|
ISyncInfoListener* listener){
|
|
TSyncClient_resultType result=_TNewDataSyncInfo_open(self,newSyncInfo,listener);
|
|
if ((result==kSyncClient_ok)&&listener->onLoadedNewSyncInfo)
|
|
listener->onLoadedNewSyncInfo(listener,self);
|
|
return result;
|
|
}
|
|
|
|
TSyncClient_resultType TNewDataSyncInfo_open_by_file(TNewDataSyncInfo* self,const char* newSyncInfoFile,
|
|
ISyncInfoListener *listener){
|
|
hpatch_TFileStreamInput newSyncInfo;
|
|
hpatch_TFileStreamInput_init(&newSyncInfo);
|
|
TSyncClient_resultType result=kSyncClient_ok;
|
|
int _inClear=0;
|
|
check(hpatch_TFileStreamInput_open(&newSyncInfo,newSyncInfoFile), kSyncClient_newSyncInfoOpenError);
|
|
result=_TNewDataSyncInfo_open(self,&newSyncInfo.base,listener);
|
|
clear:
|
|
_inClear=1;
|
|
check(hpatch_TFileStreamInput_close(&newSyncInfo), kSyncClient_newSyncInfoCloseError);
|
|
if ((result==kSyncClient_ok)&&listener->onLoadedNewSyncInfo)
|
|
listener->onLoadedNewSyncInfo(listener,self);
|
|
return result;
|
|
}
|
|
|