diff options
Diffstat (limited to 'cpp/src/IcePatch2Lib')
-rwxr-xr-x | cpp/src/IcePatch2Lib/.depend.mak | 5 | ||||
-rw-r--r-- | cpp/src/IcePatch2Lib/ClientUtil.cpp | 575 | ||||
-rw-r--r-- | cpp/src/IcePatch2Lib/Makefile | 2 | ||||
-rwxr-xr-x | cpp/src/IcePatch2Lib/Makefile.mak | 2 | ||||
-rw-r--r-- | cpp/src/IcePatch2Lib/Util.cpp | 212 | ||||
-rw-r--r-- | cpp/src/IcePatch2Lib/Util.h | 207 |
6 files changed, 694 insertions, 309 deletions
diff --git a/cpp/src/IcePatch2Lib/.depend.mak b/cpp/src/IcePatch2Lib/.depend.mak index 3ac917cdeac..7593b4c14c3 100755 --- a/cpp/src/IcePatch2Lib/.depend.mak +++ b/cpp/src/IcePatch2Lib/.depend.mak @@ -129,7 +129,7 @@ ClientUtil.obj: \ "$(includedir)\IcePatch2\FileServer.h" \ "$(includedir)\IcePatch2\FileInfo.h" \ "$(includedir)\IcePatch2\Config.h" \ - "$(includedir)\IcePatch2\Util.h" \ + "Util.h" \ Util.obj: \ Util.cpp \ @@ -164,7 +164,7 @@ Util.obj: \ "$(includedir)\IceUtil\StringUtil.h" \ "..\..\src\IceUtil\FileUtil.h" \ "$(includedir)\IceUtil\SHA1.h" \ - "$(includedir)\IcePatch2\Util.h" \ + "Util.h" \ "$(includedir)\Ice\Ice.h" \ "$(includedir)\Ice\Config.h" \ "$(includedir)\Ice\DeprecatedStringConverter.h" \ @@ -260,6 +260,7 @@ Util.obj: \ "$(includedir)\Ice\Service.h" \ "$(includedir)\IcePatch2\FileInfo.h" \ "$(includedir)\IcePatch2\Config.h" \ + "$(includedir)\IcePatch2\FileServer.h" \ FileInfo.obj: \ FileInfo.cpp \ diff --git a/cpp/src/IcePatch2Lib/ClientUtil.cpp b/cpp/src/IcePatch2Lib/ClientUtil.cpp index 89eda0a3c30..eaa381722ef 100644 --- a/cpp/src/IcePatch2Lib/ClientUtil.cpp +++ b/cpp/src/IcePatch2Lib/ClientUtil.cpp @@ -11,7 +11,7 @@ #include <IceUtil/FileUtil.h> #define ICE_PATCH2_API_EXPORTS #include <IcePatch2/ClientUtil.h> -#include <IcePatch2/Util.h> +#include <IcePatch2Lib/Util.h> #include <list> #include <iterator> @@ -19,175 +19,194 @@ using namespace std; using namespace Ice; using namespace IceUtil; using namespace IcePatch2; +using namespace IcePatch2Internal; -namespace IcePatch2 +namespace { class Decompressor : public IceUtil::Thread, public IceUtil::Monitor<IceUtil::Mutex> { public: - Decompressor(const string& dataDir) : - _dataDir(dataDir), - _destroy(false) - { - } + Decompressor(const string&); + virtual ~Decompressor(); - virtual ~Decompressor() - { - assert(_destroy); - } + void destroy(); + void add(const LargeFileInfo&); + void exception() const; + void log(FILE* fp); + virtual void run(); - void - destroy() - { - IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); - _destroy = true; - notify(); - } - - void - add(const FileInfo& info) - { - IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); - if(!_exception.empty()) - { - throw _exception; - } - _files.push_back(info); - notify(); - } +private: - void - exception() const - { - IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); - if(!_exception.empty()) - { - throw _exception; - } - } + const string _dataDir; - void - log(FILE* fp) - { - IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + string _exception; + list<LargeFileInfo> _files; + LargeFileInfoSeq _filesDone; + bool _destroy; +}; +typedef IceUtil::Handle<Decompressor> DecompressorPtr; - for(FileInfoSeq::const_iterator p = _filesDone.begin(); p != _filesDone.end(); ++p) - { - if(fputc('+', fp) == EOF || !writeFileInfo(fp, *p)) - { - throw "error writing log file:\n" + IceUtilInternal::lastErrorToString(); - } - } +class PatcherI : public Patcher +{ +public: - _filesDone.clear(); - } + PatcherI(const Ice::CommunicatorPtr&, const PatcherFeedbackPtr&); + PatcherI(const FileServerPrx&, const PatcherFeedbackPtr&, const std::string&, bool, Ice::Int, Ice::Int); + virtual ~PatcherI(); - virtual void - run() - { - FileInfo info; - - while(true) - { - { - IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); - - if(!info.path.empty()) - { - _filesDone.push_back(info); - } - - while(!_destroy && _files.empty()) - { - wait(); - } - - if(!_files.empty()) - { - info = _files.front(); - _files.pop_front(); - } - else - { - return; - } - } - - try - { - decompressFile(_dataDir + '/' + info.path); - setFileFlags(_dataDir + '/' + info.path, info); - remove(_dataDir + '/' + info.path + ".bz2"); - } - catch(const string& ex) - { - IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); - _destroy = true; - _exception = ex; - return; - } - } - } + virtual bool prepare(); + virtual bool patch(const std::string&); + virtual void finish(); private: - const string _dataDir; - - string _exception; - list<FileInfo> _files; - FileInfoSeq _filesDone; + void init(const FileServerPrx&); + bool removeFiles(const LargeFileInfoSeq&); + bool updateFiles(const LargeFileInfoSeq&); + bool updateFilesInternal(const LargeFileInfoSeq&, const DecompressorPtr&); + bool updateFlags(const LargeFileInfoSeq&); - bool _destroy; + const PatcherFeedbackPtr _feedback; + const std::string _dataDir; + const bool _thorough; + const Ice::Int _chunkSize; + const Ice::Int _remove; + const FileServerPrx _serverCompress; + const FileServerPrx _serverNoCompress; + + LargeFileInfoSeq _localFiles; + LargeFileInfoSeq _updateFiles; + LargeFileInfoSeq _updateFlags; + LargeFileInfoSeq _removeFiles; + + FILE* _log; + bool _useSmallFileAPI; }; +Decompressor::Decompressor(const string& dataDir) : + _dataDir(dataDir), + _destroy(false) +{ } -namespace +Decompressor::~Decompressor() { + assert(_destroy); +} -string -getDataDir(const CommunicatorPtr& communicator, const string& defaultValue) +void +Decompressor::destroy() { - return communicator->getProperties()->getPropertyWithDefault("IcePatch2Client.Directory", defaultValue); + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + _destroy = true; + notify(); } -int -getThorough(const CommunicatorPtr& communicator, int defaultValue) +void +Decompressor::add(const LargeFileInfo& info) { - return communicator->getProperties()->getPropertyAsIntWithDefault("IcePatch2Client.Thorough", defaultValue); + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + if(!_exception.empty()) + { + throw _exception; + } + _files.push_back(info); + notify(); } -int -getChunkSize(const CommunicatorPtr& communicator, int defaultValue) +void +Decompressor::exception() const { - return communicator->getProperties()->getPropertyAsIntWithDefault("IcePatch2Client.ChunkSize", defaultValue); + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + if(!_exception.empty()) + { + throw _exception; + } } -int -getRemove(const CommunicatorPtr& communicator, int defaultValue) +void +Decompressor::log(FILE* fp) { - return communicator->getProperties()->getPropertyAsIntWithDefault("IcePatch2Client.Remove", defaultValue); + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + + for(LargeFileInfoSeq::const_iterator p = _filesDone.begin(); p != _filesDone.end(); ++p) + { + if(fputc('+', fp) == EOF || !writeFileInfo(fp, *p)) + { + throw "error writing log file:\n" + IceUtilInternal::lastErrorToString(); + } + } + + _filesDone.clear(); } +void +Decompressor::run() +{ + LargeFileInfo info; + + while(true) + { + { + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + + if(!info.path.empty()) + { + _filesDone.push_back(info); + } + + while(!_destroy && _files.empty()) + { + wait(); + } + + if(!_files.empty()) + { + info = _files.front(); + _files.pop_front(); + } + else + { + return; + } + } + + try + { + decompressFile(_dataDir + '/' + info.path); + setFileFlags(_dataDir + '/' + info.path, info); + remove(_dataDir + '/' + info.path + ".bz2"); + } + catch(const string& ex) + { + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); + _destroy = true; + _exception = ex; + return; + } + } } -IcePatch2::Patcher::Patcher(const CommunicatorPtr& communicator, const PatcherFeedbackPtr& feedback) : +PatcherI::PatcherI(const CommunicatorPtr& communicator, const PatcherFeedbackPtr& feedback) : _feedback(feedback), - _dataDir(getDataDir(communicator, ".")), - _thorough(getThorough(communicator, 0) > 0), - _chunkSize(getChunkSize(communicator, 100)), - _remove(getRemove(communicator, 1)), - _log(0) + _dataDir(communicator->getProperties()->getPropertyWithDefault("IcePatch2Client.Directory", ".")), + _thorough(communicator->getProperties()->getPropertyAsIntWithDefault("IcePatch2Client.Thorough", 0) > 0), + _chunkSize(communicator->getProperties()->getPropertyAsIntWithDefault("IcePatch2Client.ChunkSize", 100)), + _remove(communicator->getProperties()->getPropertyAsIntWithDefault("IcePatch2Client.Remove", 1)), + _log(0), + _useSmallFileAPI(false) { - const PropertiesPtr properties = communicator->getProperties(); const char* clientProxyProperty = "IcePatch2Client.Proxy"; - std::string clientProxy = properties->getProperty(clientProxyProperty); - ObjectPrx serverBase = communicator->stringToProxy(clientProxy); + string clientProxy = communicator->getProperties()->getProperty(clientProxyProperty); + if(clientProxy.empty()) + { + throw "property `IcePatch2Client.Proxy' is not set"; + } - FileServerPrx server = FileServerPrx::checkedCast(serverBase); + FileServerPrx server = FileServerPrx::checkedCast(communicator->stringToProxy(clientProxy)); if(!server) { throw "proxy `" + clientProxy + "' is not a file server."; @@ -196,22 +215,23 @@ IcePatch2::Patcher::Patcher(const CommunicatorPtr& communicator, const PatcherFe init(server); } -IcePatch2::Patcher::Patcher(const FileServerPrx& server, - const PatcherFeedbackPtr& feedback, - const string& dataDir, - bool thorough, - Ice::Int chunkSize, - Ice::Int remove) : +PatcherI::PatcherI(const FileServerPrx& server, + const PatcherFeedbackPtr& feedback, + const string& dataDir, + bool thorough, + Ice::Int chunkSize, + Ice::Int remove) : _feedback(feedback), _dataDir(dataDir), _thorough(thorough), _chunkSize(chunkSize), - _remove(remove) + _remove(remove), + _useSmallFileAPI(false) { init(server); } -IcePatch2::Patcher::~Patcher() +PatcherI::~PatcherI() { if(_log != 0) { @@ -220,9 +240,6 @@ IcePatch2::Patcher::~Patcher() } } -namespace -{ - class PatcherGetFileInfoSeqCB : public GetFileInfoSeqCB { public: @@ -255,10 +272,8 @@ private: const PatcherFeedbackPtr _feedback; }; -} - bool -IcePatch2::Patcher::prepare() +PatcherI::prepare() { _localFiles.clear(); @@ -316,95 +331,122 @@ IcePatch2::Patcher::prepare() { throw string("server returned illegal value"); } - - AsyncResultPtr curCB; - AsyncResultPtr nxtCB; - for(int node0 = 0; node0 < 256; ++node0) + while(true) { - if(tree0.nodes[node0].checksum != checksumSeq[node0]) + AsyncResultPtr curCB; + AsyncResultPtr nxtCB; + try { - if(!curCB) - { - assert(!nxtCB); - curCB = _serverCompress->begin_getFileInfoSeq(node0); - } - else - { - assert(nxtCB); - swap(nxtCB, curCB); - } - - int node0Nxt = node0; - - do + for(int node0 = 0; node0 < 256; ++node0) { - ++node0Nxt; - } - while(node0Nxt < 256 && tree0.nodes[node0Nxt].checksum == checksumSeq[node0Nxt]); + if(tree0.nodes[node0].checksum != checksumSeq[node0]) + { + if(!curCB) + { + assert(!nxtCB); + curCB = _useSmallFileAPI ? _serverCompress->begin_getFileInfoSeq(node0) : + _serverCompress->begin_getLargeFileInfoSeq(node0); + } + else + { + assert(nxtCB); + swap(nxtCB, curCB); + } + + int node0Nxt = node0; + + do + { + ++node0Nxt; + } + while(node0Nxt < 256 && tree0.nodes[node0Nxt].checksum == checksumSeq[node0Nxt]); - if(node0Nxt < 256) - { - nxtCB = _serverCompress->begin_getFileInfoSeq(node0Nxt); - } + if(node0Nxt < 256) + { + nxtCB = _useSmallFileAPI ? _serverCompress->begin_getFileInfoSeq(node0Nxt) : + _serverCompress->begin_getLargeFileInfoSeq(node0Nxt); + } - FileInfoSeq files = _serverCompress->end_getFileInfoSeq(curCB); - - sort(files.begin(), files.end(), FileInfoLess()); - files.erase(unique(files.begin(), files.end(), FileInfoEqual()), files.end()); - - // - // Compute the set of files which were removed. - // - set_difference(tree0.nodes[node0].files.begin(), - tree0.nodes[node0].files.end(), - files.begin(), - files.end(), - back_inserter(_removeFiles), - FileInfoWithoutFlagsLess()); // NOTE: We ignore the flags here. - - // - // Compute the set of files which were updated (either the file contents, flags or both). - // - FileInfoSeq updatedFiles; - updatedFiles.reserve(files.size()); - - set_difference(files.begin(), - files.end(), - tree0.nodes[node0].files.begin(), - tree0.nodes[node0].files.end(), - back_inserter(updatedFiles), - FileInfoLess()); - - // - // Compute the set of files whose contents was updated. - // - FileInfoSeq contentsUpdatedFiles; - contentsUpdatedFiles.reserve(files.size()); - - set_difference(files.begin(), - files.end(), - tree0.nodes[node0].files.begin(), - tree0.nodes[node0].files.end(), - back_inserter(contentsUpdatedFiles), - FileInfoWithoutFlagsLess()); // NOTE: We ignore the flags here. - copy(contentsUpdatedFiles.begin(), contentsUpdatedFiles.end(), back_inserter(_updateFiles)); - - // - // Compute the set of files whose flags were updated. - // - set_difference(updatedFiles.begin(), - updatedFiles.end(), - contentsUpdatedFiles.begin(), - contentsUpdatedFiles.end(), - back_inserter(_updateFlags), - FileInfoLess()); - } + LargeFileInfoSeq files; + if(_useSmallFileAPI) + { + FileInfoSeq smallFiles = _serverCompress->end_getFileInfoSeq(curCB); + files.resize(smallFiles.size()); + transform(smallFiles.begin(), smallFiles.end(), files.begin(), toLargeFileInfo); + } + else + { + files = _serverCompress->end_getLargeFileInfoSeq(curCB); + } + + sort(files.begin(), files.end(), FileInfoLess()); + files.erase(unique(files.begin(), files.end(), FileInfoEqual()), files.end()); + + // + // Compute the set of files which were removed. + // + set_difference(tree0.nodes[node0].files.begin(), + tree0.nodes[node0].files.end(), + files.begin(), + files.end(), + back_inserter(_removeFiles), + FileInfoWithoutFlagsLess()); // NOTE: We ignore the flags here. + + // + // Compute the set of files which were updated (either the file contents, flags or both). + // + LargeFileInfoSeq updatedFiles; + updatedFiles.reserve(files.size()); + + set_difference(files.begin(), + files.end(), + tree0.nodes[node0].files.begin(), + tree0.nodes[node0].files.end(), + back_inserter(updatedFiles), + FileInfoLess()); + + // + // Compute the set of files whose contents was updated. + // + LargeFileInfoSeq contentsUpdatedFiles; + contentsUpdatedFiles.reserve(files.size()); + + set_difference(files.begin(), + files.end(), + tree0.nodes[node0].files.begin(), + tree0.nodes[node0].files.end(), + back_inserter(contentsUpdatedFiles), + FileInfoWithoutFlagsLess()); // NOTE: We ignore the flags here. + copy(contentsUpdatedFiles.begin(), contentsUpdatedFiles.end(), back_inserter(_updateFiles)); + + // + // Compute the set of files whose flags were updated. + // + set_difference(updatedFiles.begin(), + updatedFiles.end(), + contentsUpdatedFiles.begin(), + contentsUpdatedFiles.end(), + back_inserter(_updateFlags), + FileInfoLess()); + } - if(!_feedback->fileListProgress((node0 + 1) * 100 / 256)) + if(!_feedback->fileListProgress((node0 + 1) * 100 / 256)) + { + return false; + } + } + } + catch(const Ice::OperationNotExistException&) { - return false; + if(!_useSmallFileAPI) + { + _useSmallFileAPI = true; + continue; + } + throw; } + break; } if(!_feedback->fileListEnd()) @@ -428,7 +470,7 @@ IcePatch2::Patcher::prepare() } bool -IcePatch2::Patcher::patch(const string& d) +PatcherI::patch(const string& d) { string dir = simplify(d); @@ -464,8 +506,8 @@ IcePatch2::Patcher::patch(const string& d) { string dirWithSlash = simplify(dir + '/'); - FileInfoSeq remove; - for(FileInfoSeq::const_iterator p = _removeFiles.begin(); p != _removeFiles.end(); ++p) + LargeFileInfoSeq remove; + for(LargeFileInfoSeq::const_iterator p = _removeFiles.begin(); p != _removeFiles.end(); ++p) { if(p->path == dir) { @@ -477,8 +519,8 @@ IcePatch2::Patcher::patch(const string& d) } } - FileInfoSeq update; - for(FileInfoSeq::const_iterator p = _updateFiles.begin(); p != _updateFiles.end(); ++p) + LargeFileInfoSeq update; + for(LargeFileInfoSeq::const_iterator p = _updateFiles.begin(); p != _updateFiles.end(); ++p) { if(p->path == dir) { @@ -490,8 +532,8 @@ IcePatch2::Patcher::patch(const string& d) } } - FileInfoSeq updateFlag; - for(FileInfoSeq::const_iterator p = _updateFlags.begin(); p != _updateFlags.end(); ++p) + LargeFileInfoSeq updateFlag; + for(LargeFileInfoSeq::const_iterator p = _updateFlags.begin(); p != _updateFlags.end(); ++p) { if(p->path == dir) { @@ -532,7 +574,7 @@ IcePatch2::Patcher::patch(const string& d) } void -IcePatch2::Patcher::finish() +PatcherI::finish() { if(_log != 0) { @@ -544,7 +586,7 @@ IcePatch2::Patcher::finish() } void -IcePatch2::Patcher::init(const FileServerPrx& server) +PatcherI::init(const FileServerPrx& server) { if(_dataDir.empty()) { @@ -592,14 +634,14 @@ IcePatch2::Patcher::init(const FileServerPrx& server) } bool -IcePatch2::Patcher::removeFiles(const FileInfoSeq& files) +PatcherI::removeFiles(const LargeFileInfoSeq& files) { if(_remove < 1) { return true; } - for(FileInfoSeq::const_reverse_iterator p = files.rbegin(); p != files.rend(); ++p) + for(LargeFileInfoSeq::const_reverse_iterator p = files.rbegin(); p != files.rend(); ++p) { try { @@ -618,7 +660,7 @@ IcePatch2::Patcher::removeFiles(const FileInfoSeq& files) } } - FileInfoSeq newLocalFiles; + LargeFileInfoSeq newLocalFiles; newLocalFiles.reserve(_localFiles.size()); set_difference(_localFiles.begin(), @@ -630,7 +672,7 @@ IcePatch2::Patcher::removeFiles(const FileInfoSeq& files) _localFiles.swap(newLocalFiles); - FileInfoSeq newRemoveFiles; + LargeFileInfoSeq newRemoveFiles; set_difference(_removeFiles.begin(), _removeFiles.end(), @@ -643,9 +685,9 @@ IcePatch2::Patcher::removeFiles(const FileInfoSeq& files) return true; } - + bool -IcePatch2::Patcher::updateFiles(const FileInfoSeq& files) +PatcherI::updateFiles(const LargeFileInfoSeq& files) { DecompressorPtr decompressor = new Decompressor(_dataDir); #if defined(__hppa) @@ -680,12 +722,12 @@ IcePatch2::Patcher::updateFiles(const FileInfoSeq& files) } bool -IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const DecompressorPtr& decompressor) +PatcherI::updateFilesInternal(const LargeFileInfoSeq& files, const DecompressorPtr& decompressor) { Long total = 0; Long updated = 0; - for(FileInfoSeq::const_iterator p = files.begin(); p != files.end(); ++p) + for(LargeFileInfoSeq::const_iterator p = files.begin(); p != files.end(); ++p) { if(p->size > 0) // Regular, non-empty file? { @@ -696,7 +738,7 @@ IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const Decompre AsyncResultPtr curCB; AsyncResultPtr nxtCB; - for(FileInfoSeq::const_iterator p = files.begin(); p != files.end(); ++p) + for(LargeFileInfoSeq::const_iterator p = files.begin(); p != files.end(); ++p) { if(p->size < 0) // Directory? { @@ -749,14 +791,16 @@ IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const Decompre try { - Int pos = 0; + Ice::Long pos = 0; while(pos < p->size) { if(!curCB) { assert(!nxtCB); - curCB = _serverNoCompress->begin_getFileCompressed(p->path, pos, _chunkSize); + curCB = _useSmallFileAPI ? + _serverNoCompress->begin_getFileCompressed(p->path, static_cast<Ice::Int>(pos), _chunkSize) : + _serverNoCompress->begin_getLargeFileCompressed(p->path, pos, _chunkSize); } else { @@ -766,11 +810,13 @@ IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const Decompre if(pos + _chunkSize < p->size) { - nxtCB = _serverNoCompress->begin_getFileCompressed(p->path, pos + _chunkSize, _chunkSize); + nxtCB = _useSmallFileAPI ? + _serverNoCompress->begin_getFileCompressed(p->path, static_cast<Ice::Int>(pos + _chunkSize), _chunkSize) : + _serverNoCompress->begin_getLargeFileCompressed(p->path, pos + _chunkSize, _chunkSize); } else { - FileInfoSeq::const_iterator q = p + 1; + LargeFileInfoSeq::const_iterator q = p + 1; while(q != files.end() && q->size <= 0) { @@ -779,7 +825,9 @@ IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const Decompre if(q != files.end()) { - nxtCB = _serverNoCompress->begin_getFileCompressed(q->path, 0, _chunkSize); + nxtCB = _useSmallFileAPI ? + _serverNoCompress->begin_getFileCompressed(q->path, 0, _chunkSize) : + _serverNoCompress->begin_getLargeFileCompressed(q->path, 0, _chunkSize); } } @@ -787,7 +835,8 @@ IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const Decompre try { - bytes = _serverNoCompress->end_getFileCompressed(curCB); + bytes = _useSmallFileAPI ? _serverNoCompress->end_getFileCompressed(curCB) : + _serverNoCompress->end_getLargeFileCompressed(curCB); } catch(const FileAccessException& ex) { @@ -804,7 +853,7 @@ IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const Decompre throw ": cannot write `" + pathBZ2 + "':\n" + IceUtilInternal::lastErrorToString(); } - pos += static_cast<int>(bytes.size()); + pos += bytes.size(); updated += bytes.size(); if(!_feedback->patchProgress(pos, p->size, updated, total)) @@ -833,7 +882,7 @@ IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const Decompre } } - FileInfoSeq newLocalFiles; + LargeFileInfoSeq newLocalFiles; newLocalFiles.reserve(_localFiles.size()); set_union(_localFiles.begin(), @@ -845,7 +894,7 @@ IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const Decompre _localFiles.swap(newLocalFiles); - FileInfoSeq newUpdateFiles; + LargeFileInfoSeq newUpdateFiles; set_difference(_updateFiles.begin(), _updateFiles.end(), @@ -860,9 +909,9 @@ IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const Decompre } bool -IcePatch2::Patcher::updateFlags(const FileInfoSeq& files) +PatcherI::updateFlags(const LargeFileInfoSeq& files) { - for(FileInfoSeq::const_iterator p = files.begin(); p != files.end(); ++p) + for(LargeFileInfoSeq::const_iterator p = files.begin(); p != files.end(); ++p) { if(p->size >= 0) // Regular file? { @@ -874,7 +923,7 @@ IcePatch2::Patcher::updateFlags(const FileInfoSeq& files) // Remove the old files whose flags were updated from the set of // local files. // - FileInfoSeq localFiles; + LargeFileInfoSeq localFiles; localFiles.reserve(_localFiles.size()); set_difference(_localFiles.begin(), _localFiles.end(), @@ -894,7 +943,7 @@ IcePatch2::Patcher::updateFlags(const FileInfoSeq& files) back_inserter(_localFiles), FileInfoLess()); - FileInfoSeq newUpdateFlags; + LargeFileInfoSeq newUpdateFlags; set_difference(_updateFlags.begin(), _updateFlags.end(), @@ -908,3 +957,25 @@ IcePatch2::Patcher::updateFlags(const FileInfoSeq& files) return true; } +} + +PatcherPtr +PatcherFactory::create(const Ice::CommunicatorPtr& communicator, const PatcherFeedbackPtr& feedback) +{ + return new PatcherI(communicator, feedback); +} + +// +// Create a patcher with the given parameters. These parameters +// are equivalent to the configuration properties described above. +// +PatcherPtr +PatcherFactory::create(const FileServerPrx& server, + const PatcherFeedbackPtr& feedback, + const string& dataDir, + bool thorough, + Ice::Int chunkSize, + Ice::Int remove) +{ + return new PatcherI(server, feedback, dataDir, thorough, chunkSize, remove); +} diff --git a/cpp/src/IcePatch2Lib/Makefile b/cpp/src/IcePatch2Lib/Makefile index 871a9ed02e9..80a59f38bfb 100644 --- a/cpp/src/IcePatch2Lib/Makefile +++ b/cpp/src/IcePatch2Lib/Makefile @@ -27,7 +27,7 @@ SDIR = $(slicedir)/IcePatch2 include $(top_srcdir)/config/Make.rules -CPPFLAGS := -I. -I.. $(CPPFLAGS) $(OPENSSL_FLAGS) $(BZIP2_FLAGS) +CPPFLAGS := -I. -I.. $(CPPFLAGS) $(OPENSSL_FLAGS) $(BZIP2_FLAGS) -Wno-deprecated-declarations SLICE2CPPFLAGS := --ice --include-dir IcePatch2 --dll-export ICE_PATCH2_API $(SLICE2CPPFLAGS) LINKWITH := $(BZIP2_RPATH_LINK) -lIce -lIceUtil $(OPENSSL_LIBS) $(BZIP2_LIBS) diff --git a/cpp/src/IcePatch2Lib/Makefile.mak b/cpp/src/IcePatch2Lib/Makefile.mak index a2c29ccbf84..ec9456261d9 100755 --- a/cpp/src/IcePatch2Lib/Makefile.mak +++ b/cpp/src/IcePatch2Lib/Makefile.mak @@ -26,7 +26,7 @@ SDIR = $(slicedir)\IcePatch2 !include $(top_srcdir)\config\Make.rules.mak -CPPFLAGS = -I. -I.. $(CPPFLAGS) -DWIN32_LEAN_AND_MEAN +CPPFLAGS = -I. -I.. $(CPPFLAGS) -DWIN32_LEAN_AND_MEAN -wd4996 SLICE2CPPFLAGS = --ice --include-dir IcePatch2 --dll-export ICE_PATCH2_API $(SLICE2CPPFLAGS) diff --git a/cpp/src/IcePatch2Lib/Util.cpp b/cpp/src/IcePatch2Lib/Util.cpp index ab27759d87a..948a3646d5c 100644 --- a/cpp/src/IcePatch2Lib/Util.cpp +++ b/cpp/src/IcePatch2Lib/Util.cpp @@ -20,9 +20,11 @@ #include <IceUtil/StringUtil.h> #include <IceUtil/FileUtil.h> #include <IceUtil/SHA1.h> +#include <IceUtil/Exception.h> #define ICE_PATCH2_API_EXPORTS -#include <IcePatch2/Util.h> +#include <IcePatch2Lib/Util.h> +#include <IcePatch2/FileServer.h> #include <bzlib.h> #include <iomanip> @@ -40,17 +42,54 @@ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif -const char* IcePatch2::checksumFile = "IcePatch2.sum"; -const char* IcePatch2::logFile = "IcePatch2.log"; +const char* IcePatch2Internal::checksumFile = "IcePatch2.sum"; +const char* IcePatch2Internal::logFile = "IcePatch2.log"; using namespace std; using namespace Ice; using namespace IcePatch2; +using namespace IcePatch2Internal; + +FileInfo +IcePatch2Internal::toFileInfo(const LargeFileInfo& largeInfo) +{ + if(largeInfo.size > 0x7FFFFFFF) + { + ostringstream os; + os << "cannot encode size `" << largeInfo.size << "' for file `" << largeInfo.path << "' as Ice::Int" << endl; + throw FileSizeRangeException(os.str()); + } + + FileInfo info; + info.path = largeInfo.path; + info.checksum = largeInfo.checksum; + info.size = static_cast<Ice::Int>(largeInfo.size), + info.executable = largeInfo.executable; + + return info; +} + +LargeFileInfo +IcePatch2Internal::toLargeFileInfo(const FileInfo& info) +{ + LargeFileInfo largeInfo; + largeInfo.path = info.path; + largeInfo.checksum = info.checksum; + largeInfo.size = info.size; + largeInfo.executable = info.executable; + return largeInfo; +} + +bool +IcePatch2Internal::writeFileInfo(FILE* fp, const FileInfo& info) +{ + return writeFileInfo(fp, toLargeFileInfo(info)); +} bool -IcePatch2::writeFileInfo(FILE* fp, const FileInfo& info) +IcePatch2Internal::writeFileInfo(FILE* fp, const LargeFileInfo& info) { - int rc = fprintf(fp, "%s\t%s\t%d\t%d\n", + int rc = fprintf(fp, "%s\t%s\t%ld\t%d\n", IceUtilInternal::escapeString(info.path, "").c_str(), bytesToString(info.checksum).c_str(), info.size, @@ -59,7 +98,19 @@ IcePatch2::writeFileInfo(FILE* fp, const FileInfo& info) } bool -IcePatch2::readFileInfo(FILE* fp, FileInfo& info) +IcePatch2Internal::readFileInfo(FILE* fp, FileInfo& info) +{ + LargeFileInfo largeInfo; + bool retval = readFileInfo(fp, largeInfo); + if(retval) + { + info = toFileInfo(largeInfo); + } + return retval; +} + +bool +IcePatch2Internal::readFileInfo(FILE* fp, LargeFileInfo& info) { string data; char buf[BUFSIZ]; @@ -101,7 +152,7 @@ IcePatch2::readFileInfo(FILE* fp, FileInfo& info) } string -IcePatch2::bytesToString(const ByteSeq& bytes) +IcePatch2Internal::bytesToString(const ByteSeq& bytes) { /* ostringstream s; @@ -129,7 +180,7 @@ IcePatch2::bytesToString(const ByteSeq& bytes) } ByteSeq -IcePatch2::stringToBytes(const string& str) +IcePatch2Internal::stringToBytes(const string& str) { ByteSeq bytes; bytes.reserve((str.size() + 1) / 2); @@ -174,7 +225,7 @@ IcePatch2::stringToBytes(const string& str) } string -IcePatch2::simplify(const string& path) +IcePatch2Internal::simplify(const string& path) { string result = path; @@ -250,7 +301,7 @@ IcePatch2::simplify(const string& path) } bool -IcePatch2::isRoot(const string& pa) +IcePatch2Internal::isRoot(const string& pa) { string path = simplify(pa); #ifdef _WIN32 @@ -262,7 +313,7 @@ IcePatch2::isRoot(const string& pa) } string -IcePatch2::getSuffix(const string& pa) +IcePatch2Internal::getSuffix(const string& pa) { const string path = simplify(pa); @@ -278,7 +329,7 @@ IcePatch2::getSuffix(const string& pa) } string -IcePatch2::getWithoutSuffix(const string& pa) +IcePatch2Internal::getWithoutSuffix(const string& pa) { const string path = simplify(pa); @@ -294,7 +345,7 @@ IcePatch2::getWithoutSuffix(const string& pa) } bool -IcePatch2::ignoreSuffix(const string& path) +IcePatch2Internal::ignoreSuffix(const string& path) { string suffix = getSuffix(path); return suffix == "md5" // For legacy IcePatch. @@ -304,7 +355,7 @@ IcePatch2::ignoreSuffix(const string& path) } string -IcePatch2::getBasename(const string& pa) +IcePatch2Internal::getBasename(const string& pa) { const string path = simplify(pa); @@ -320,7 +371,7 @@ IcePatch2::getBasename(const string& pa) } string -IcePatch2::getDirname(const string& pa) +IcePatch2Internal::getDirname(const string& pa) { const string path = simplify(pa); @@ -336,7 +387,7 @@ IcePatch2::getDirname(const string& pa) } void -IcePatch2::rename(const string& fromPa, const string& toPa) +IcePatch2Internal::rename(const string& fromPa, const string& toPa) { const string fromPath = simplify(fromPa); @@ -350,7 +401,7 @@ IcePatch2::rename(const string& fromPa, const string& toPa) } void -IcePatch2::remove(const string& pa) +IcePatch2Internal::remove(const string& pa) { const string path = simplify(pa); @@ -381,7 +432,7 @@ IcePatch2::remove(const string& pa) } void -IcePatch2::removeRecursive(const string& pa) +IcePatch2Internal::removeRecursive(const string& pa) { const string path = simplify(pa); @@ -417,7 +468,7 @@ IcePatch2::removeRecursive(const string& pa) } StringSeq -IcePatch2::readDirectory(const string& pa) +IcePatch2Internal::readDirectory(const string& pa) { const string path = simplify(pa); @@ -498,7 +549,7 @@ IcePatch2::readDirectory(const string& pa) } void -IcePatch2::createDirectory(const string& pa) +IcePatch2Internal::createDirectory(const string& pa) { const string path = simplify(pa); @@ -512,7 +563,7 @@ IcePatch2::createDirectory(const string& pa) } void -IcePatch2::createDirectoryRecursive(const string& pa) +IcePatch2Internal::createDirectoryRecursive(const string& pa) { const string path = simplify(pa); @@ -544,7 +595,7 @@ IcePatch2::createDirectoryRecursive(const string& pa) } void -IcePatch2::compressBytesToFile(const string& pa, const ByteSeq& bytes, Int pos) +IcePatch2Internal::compressBytesToFile(const string& pa, const ByteSeq& bytes, Int pos) { const string path = simplify(pa); @@ -596,11 +647,11 @@ IcePatch2::compressBytesToFile(const string& pa, const ByteSeq& bytes, Int pos) } void -IcePatch2::decompressFile(const string& pa) +IcePatch2Internal::decompressFile(const string& pa) { const string path = simplify(pa); const string pathBZ2 = path + ".bz2"; - + FILE* fp = 0; FILE* stdioFileBZ2 = 0; int bzError; @@ -695,9 +746,15 @@ IcePatch2::decompressFile(const string& pa) fclose(fp); } +void +IcePatch2Internal::setFileFlags(const string& pa, const FileInfo& info) +{ + setFileFlags(pa, toLargeFileInfo(info)); +} + #ifndef _WIN32 void -IcePatch2::setFileFlags(const string& pa, const FileInfo& info) +IcePatch2Internal::setFileFlags(const string& pa, const LargeFileInfo& info) { const string path = simplify(pa); IceUtilInternal::structstat buf; @@ -709,14 +766,17 @@ IcePatch2::setFileFlags(const string& pa, const FileInfo& info) } #else // Windows doesn't support the executable flag void -IcePatch2::setFileFlags(const string&, const FileInfo&) +IcePatch2Internal::setFileFlags(const string&, const LargeFileInfo&) { } #endif +namespace +{ + static bool -getFileInfoSeqInt(const string& basePath, const string& relPath, int compress, GetFileInfoSeqCB* cb, - FileInfoSeq& infoSeq) +getFileInfoSeqInternal(const string& basePath, const string& relPath, int compress, GetFileInfoSeqCB* cb, + LargeFileInfoSeq& infoSeq) { if(relPath == checksumFile || relPath == logFile) { @@ -779,7 +839,7 @@ getFileInfoSeqInt(const string& basePath, const string& relPath, int compress, G if(S_ISDIR(buf.st_mode)) { - FileInfo info; + LargeFileInfo info; info.path = relPath; info.size = -1; info.executable = false; @@ -803,7 +863,7 @@ getFileInfoSeqInt(const string& basePath, const string& relPath, int compress, G StringSeq content = readDirectory(path); for(StringSeq::const_iterator p = content.begin(); p != content.end() ; ++p) { - if(!getFileInfoSeqInt(basePath, simplify(relPath + '/' + *p), compress, cb, infoSeq)) + if(!getFileInfoSeqInternal(basePath, simplify(relPath + '/' + *p), compress, cb, infoSeq)) { return false; } @@ -811,7 +871,7 @@ getFileInfoSeqInt(const string& basePath, const string& relPath, int compress, G } else if(S_ISREG(buf.st_mode)) { - FileInfo info; + LargeFileInfo info; info.path = relPath; info.size = 0; #ifdef _WIN32 @@ -841,7 +901,7 @@ getFileInfoSeqInt(const string& basePath, const string& relPath, int compress, G } else { - info.size = static_cast<Int>(bufBZ2.st_size); + info.size = bufBZ2.st_size; } } @@ -900,10 +960,10 @@ getFileInfoSeqInt(const string& basePath, const string& relPath, int compress, G } } - unsigned int bytesLeft = static_cast<unsigned int>(buf.st_size); + long bytesLeft = buf.st_size; while(bytesLeft > 0) { - ByteSeq bytes(min(bytesLeft, 1024u*1024)); + ByteSeq bytes(min(bytesLeft, 1024l*1024)); if( #if defined(_MSC_VER) _read(fd, &bytes[0], static_cast<unsigned int>(bytes.size())) @@ -921,7 +981,6 @@ getFileInfoSeqInt(const string& basePath, const string& relPath, int compress, G throw "cannot read from `" + path + "':\n" + IceUtilInternal::lastErrorToString(); } bytesLeft -= static_cast<unsigned int>(bytes.size()); - if(doCompress) { BZ2_bzWrite(&bzError, bzFile, const_cast<Byte*>(&bytes[0]), static_cast<int>(bytes.size())); @@ -967,7 +1026,7 @@ getFileInfoSeqInt(const string& basePath, const string& relPath, int compress, G throw "cannot stat `" + pathBZ2 + "':\n" + IceUtilInternal::lastErrorToString(); } - info.size = static_cast<Int>(bufBZ2.st_size); + info.size = bufBZ2.st_size; } } hasher.finalize(bytesSHA); @@ -982,21 +1041,44 @@ getFileInfoSeqInt(const string& basePath, const string& relPath, int compress, G return true; } +} + +bool +IcePatch2Internal::getFileInfoSeq(const string& basePath, int compress, GetFileInfoSeqCB* cb, FileInfoSeq& infoSeq) +{ + LargeFileInfoSeq largeInfoSeq; + bool retval = getFileInfoSeq(basePath, compress, cb, largeInfoSeq); + infoSeq.resize(largeInfoSeq.size()); + transform(largeInfoSeq.begin(), largeInfoSeq.end(), infoSeq.begin(), toFileInfo); + return retval; +} + bool -IcePatch2::getFileInfoSeq(const string& basePath, int compress, GetFileInfoSeqCB* cb, - FileInfoSeq& infoSeq) +IcePatch2Internal::getFileInfoSeq(const string& basePath, int compress, GetFileInfoSeqCB* cb, + LargeFileInfoSeq& infoSeq) { return getFileInfoSeqSubDir(basePath, ".", compress, cb, infoSeq); } bool -IcePatch2::getFileInfoSeqSubDir(const string& basePa, const string& relPa, int compress, GetFileInfoSeqCB* cb, - FileInfoSeq& infoSeq) +IcePatch2Internal::getFileInfoSeqSubDir(const string& basePa, const string& relPa, int compress, GetFileInfoSeqCB* cb, + FileInfoSeq& infoSeq) +{ + LargeFileInfoSeq largeInfoSeq; + bool retval = getFileInfoSeqSubDir(basePa, relPa, compress, cb, largeInfoSeq); + infoSeq.resize(largeInfoSeq.size()); + transform(largeInfoSeq.begin(), largeInfoSeq.end(), infoSeq.begin(), toFileInfo); + return retval; +} + +bool +IcePatch2Internal::getFileInfoSeqSubDir(const string& basePa, const string& relPa, int compress, GetFileInfoSeqCB* cb, + LargeFileInfoSeq& infoSeq) { const string basePath = simplify(basePa); const string relPath = simplify(relPa); - if(!getFileInfoSeqInt(basePath, relPath, compress, cb, infoSeq)) + if(!getFileInfoSeqInternal(basePath, relPath, compress, cb, infoSeq)) { return false; } @@ -1008,11 +1090,18 @@ IcePatch2::getFileInfoSeqSubDir(const string& basePa, const string& relPa, int c } void -IcePatch2::saveFileInfoSeq(const string& pa, const FileInfoSeq& infoSeq) +IcePatch2Internal::saveFileInfoSeq(const string& pa, const FileInfoSeq& infoSeq) +{ + LargeFileInfoSeq largeInfoSeq(infoSeq.size()); + transform(infoSeq.begin(), infoSeq.end(), largeInfoSeq.begin(), toLargeFileInfo); + saveFileInfoSeq(pa, largeInfoSeq); +} + +void +IcePatch2Internal::saveFileInfoSeq(const string& pa, const LargeFileInfoSeq& infoSeq) { { const string path = simplify(pa + '/' + checksumFile); - FILE* fp = IceUtilInternal::fopen(path, "w"); if(!fp) { @@ -1020,7 +1109,7 @@ IcePatch2::saveFileInfoSeq(const string& pa, const FileInfoSeq& infoSeq) } try { - for(FileInfoSeq::const_iterator p = infoSeq.begin(); p != infoSeq.end(); ++p) + for(LargeFileInfoSeq::const_iterator p = infoSeq.begin(); p != infoSeq.end(); ++p) { if(!writeFileInfo(fp, *p)) { @@ -1050,7 +1139,16 @@ IcePatch2::saveFileInfoSeq(const string& pa, const FileInfoSeq& infoSeq) } void -IcePatch2::loadFileInfoSeq(const string& pa, FileInfoSeq& infoSeq) +IcePatch2Internal::loadFileInfoSeq(const string& pa, FileInfoSeq& infoSeq) +{ + LargeFileInfoSeq largeInfoSeq; + loadFileInfoSeq(pa, largeInfoSeq); + infoSeq.resize(largeInfoSeq.size()); + transform(largeInfoSeq.begin(), largeInfoSeq.end(), infoSeq.begin(), toFileInfo); +} + +void +IcePatch2Internal::loadFileInfoSeq(const string& pa, LargeFileInfoSeq& infoSeq) { { const string path = simplify(pa + '/' + checksumFile); @@ -1063,7 +1161,7 @@ IcePatch2::loadFileInfoSeq(const string& pa, FileInfoSeq& infoSeq) while(true) { - FileInfo info; + LargeFileInfo info; if(readFileInfo(fp, info)) { infoSeq.push_back(info); @@ -1085,8 +1183,8 @@ IcePatch2::loadFileInfoSeq(const string& pa, FileInfoSeq& infoSeq) FILE* fp = IceUtilInternal::fopen(pathLog, "r"); if(fp != 0) { - FileInfoSeq remove; - FileInfoSeq update; + LargeFileInfoSeq remove; + LargeFileInfoSeq update; while(true) { @@ -1096,7 +1194,7 @@ IcePatch2::loadFileInfoSeq(const string& pa, FileInfoSeq& infoSeq) break; } - FileInfo info; + LargeFileInfo info; if(!readFileInfo(fp, info)) { break; @@ -1119,7 +1217,7 @@ IcePatch2::loadFileInfoSeq(const string& pa, FileInfoSeq& infoSeq) sort(update.begin(), update.end(), FileInfoLess()); update.erase(unique(update.begin(), update.end(), FileInfoEqual()), update.end()); - FileInfoSeq newInfoSeq; + LargeFileInfoSeq newInfoSeq; newInfoSeq.reserve(infoSeq.size()); set_difference(infoSeq.begin(), @@ -1149,7 +1247,15 @@ IcePatch2::loadFileInfoSeq(const string& pa, FileInfoSeq& infoSeq) } void -IcePatch2::getFileTree0(const FileInfoSeq& infoSeq, FileTree0& tree0) +IcePatch2Internal::getFileTree0(const FileInfoSeq& infoSeq, FileTree0& tree0) +{ + LargeFileInfoSeq largeInfoSeq(infoSeq.size()); + transform(infoSeq.begin(), infoSeq.end(), largeInfoSeq.begin(), toLargeFileInfo); + getFileTree0(largeInfoSeq, tree0); +} + +void +IcePatch2Internal::getFileTree0(const LargeFileInfoSeq& infoSeq, FileTree0& tree0) { tree0.nodes.resize(256); tree0.checksum.resize(20); @@ -1165,7 +1271,7 @@ IcePatch2::getFileTree0(const FileInfoSeq& infoSeq, FileTree0& tree0) tree1.files.clear(); tree1.checksum.resize(20); - for(FileInfoSeq::const_iterator p = infoSeq.begin(); p != infoSeq.end(); ++p) + for(LargeFileInfoSeq::const_iterator p = infoSeq.begin(); p != infoSeq.end(); ++p) { if(i == static_cast<int>(p->checksum[0])) { @@ -1177,7 +1283,7 @@ IcePatch2::getFileTree0(const FileInfoSeq& infoSeq, FileTree0& tree0) allChecksums1.resize(tree1.files.size() * 21); // 20 bytes for the checksum + 1 byte for the flag ByteSeq::iterator c1 = allChecksums1.begin(); - for(FileInfoSeq::const_iterator p = tree1.files.begin(); p != tree1.files.end(); ++p, c1 += 21) + for(LargeFileInfoSeq::const_iterator p = tree1.files.begin(); p != tree1.files.end(); ++p, c1 += 21) { copy(p->checksum.begin(), p->checksum.end(), c1); *(c1 + 20) = p->executable; diff --git a/cpp/src/IcePatch2Lib/Util.h b/cpp/src/IcePatch2Lib/Util.h new file mode 100644 index 00000000000..4f243a5d640 --- /dev/null +++ b/cpp/src/IcePatch2Lib/Util.h @@ -0,0 +1,207 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICE_PATCH2_UTIL_H +#define ICE_PATCH2_UTIL_H + +#include <Ice/Ice.h> +#include <IcePatch2/FileInfo.h> +#include <stdio.h> + +namespace IcePatch2Internal +{ + +ICE_PATCH2_API extern const char* checksumFile; +ICE_PATCH2_API extern const char* logFile; + +ICE_PATCH2_API std::string lastError(); + +ICE_PATCH2_API std::string bytesToString(const Ice::ByteSeq&); +ICE_PATCH2_API Ice::ByteSeq stringToBytes(const std::string&); + +ICE_PATCH2_API std::string simplify(const std::string&); + +ICE_PATCH2_API bool isRoot(const std::string&); + +ICE_PATCH2_API std::string getSuffix(const std::string&); +ICE_PATCH2_API std::string getWithoutSuffix(const std::string&); +ICE_PATCH2_API bool ignoreSuffix(const std::string&); + +ICE_PATCH2_API std::string getBasename(const std::string&); +ICE_PATCH2_API std::string getDirname(const std::string&); + +ICE_PATCH2_API void rename(const std::string&, const std::string&); + +ICE_PATCH2_API void remove(const std::string&); +ICE_PATCH2_API void removeRecursive(const std::string&); + +ICE_PATCH2_API Ice::StringSeq readDirectory(const std::string&); + +ICE_PATCH2_API void createDirectory(const std::string&); +ICE_PATCH2_API void createDirectoryRecursive(const std::string&); + +ICE_PATCH2_API void compressBytesToFile(const std::string&, const Ice::ByteSeq&, Ice::Int); +ICE_PATCH2_API void decompressFile(const std::string&); + +ICE_PATCH2_API void setFileFlags(const std::string&, const IcePatch2::FileInfo&); +ICE_PATCH2_API void setFileFlags(const std::string&, const IcePatch2::LargeFileInfo&); + +struct FileInfoEqual : public std::binary_function<const IcePatch2::LargeFileInfo&, const IcePatch2::LargeFileInfo&, bool> +{ + bool + operator()(const IcePatch2::LargeFileInfo& lhs, const IcePatch2::LargeFileInfo& rhs) + { + if(lhs.path != rhs.path) + { + return false; + } + + // + // For the size portion of the comparison, we only distinquish + // between file (size >= 0) and directory (size == -1). We do + // not take the actual size into account, as it might be set + // to 0 if no compressed file is available. + // + Ice::Long lsz = lhs.size > 0 ? 0 : lhs.size; + Ice::Long rsz = rhs.size > 0 ? 0 : rhs.size; + if(lsz != rsz) + { + return false; + } + + if(lhs.executable != rhs.executable) + { + return false; + } + + return lhs.checksum == rhs.checksum; + } +}; + +struct FileInfoWithoutFlagsLess : public std::binary_function<const IcePatch2::LargeFileInfo&, const IcePatch2::LargeFileInfo&, bool> +{ + bool + operator()(const IcePatch2::LargeFileInfo& lhs, const IcePatch2::LargeFileInfo& rhs) + { + return compareWithoutFlags(lhs, rhs) < 0; + } + + int + compareWithoutFlags(const IcePatch2::LargeFileInfo& lhs, const IcePatch2::LargeFileInfo& rhs) + { + if(lhs.path < rhs.path) + { + return -1; + } + else if(rhs.path < lhs.path) + { + return 1; + } + + // + // For the size portion of the comparison, we only distinquish + // between file (size >= 0) and directory (size == -1). We do + // not take the actual size into account, as it might be set + // to 0 if no compressed file is available. + // + Ice::Long lsz = lhs.size > 0 ? 0 : lhs.size; + Ice::Long rsz = rhs.size > 0 ? 0 : rhs.size; + if(lsz < rsz) + { + return -1; + } + else if(rsz < lsz) + { + return 1; + } + + if(lhs.checksum < rhs.checksum) + { + return -1; + } + else if(rhs.checksum < lhs.checksum) + { + return 1; + } + + return 0; + } +}; + +struct FileInfoLess : public FileInfoWithoutFlagsLess +{ + bool + operator()(const IcePatch2::LargeFileInfo& lhs, const IcePatch2::LargeFileInfo& rhs) + { + int rc = compareWithoutFlags(lhs, rhs); + if(rc < 0) + { + return true; + } + else if(rc > 0) + { + return false; + } + + return lhs.executable < rhs.executable; + } +}; + +class ICE_PATCH2_API GetFileInfoSeqCB +{ +public: + + virtual ~GetFileInfoSeqCB() { } + + virtual bool remove(const std::string&) = 0; + virtual bool checksum(const std::string&) = 0; + virtual bool compress(const std::string&) = 0; +}; + +ICE_PATCH2_API bool getFileInfoSeq(const std::string&, int, GetFileInfoSeqCB*, IcePatch2::FileInfoSeq&); +ICE_PATCH2_API bool getFileInfoSeq(const std::string&, int, GetFileInfoSeqCB*, IcePatch2::LargeFileInfoSeq&); + +ICE_PATCH2_API bool getFileInfoSeqSubDir(const std::string&, const std::string&, int, GetFileInfoSeqCB*, IcePatch2::FileInfoSeq&); +ICE_PATCH2_API bool getFileInfoSeqSubDir(const std::string&, const std::string&, int, GetFileInfoSeqCB*, IcePatch2::LargeFileInfoSeq&); + +ICE_PATCH2_API void saveFileInfoSeq(const std::string&, const IcePatch2::FileInfoSeq&); +ICE_PATCH2_API void saveFileInfoSeq(const std::string&, const IcePatch2::LargeFileInfoSeq&); + +ICE_PATCH2_API void loadFileInfoSeq(const std::string&, IcePatch2::FileInfoSeq&); +ICE_PATCH2_API void loadFileInfoSeq(const std::string&, IcePatch2::LargeFileInfoSeq&); + +ICE_PATCH2_API bool readFileInfo(FILE*, IcePatch2::FileInfo&); +ICE_PATCH2_API bool readFileInfo(FILE*, IcePatch2::LargeFileInfo&); + +ICE_PATCH2_API IcePatch2::FileInfo toFileInfo(const IcePatch2::LargeFileInfo&); +ICE_PATCH2_API IcePatch2::LargeFileInfo toLargeFileInfo(const IcePatch2::FileInfo&); + +ICE_PATCH2_API bool writeFileInfo(FILE*, const IcePatch2::FileInfo&); +ICE_PATCH2_API bool writeFileInfo(FILE*, const IcePatch2::LargeFileInfo&); + +struct FileTree1 +{ + IcePatch2::LargeFileInfoSeq files; + Ice::ByteSeq checksum; +}; + +typedef std::vector<FileTree1> FileTree1Seq; + +struct FileTree0 +{ + FileTree1Seq nodes; + Ice::ByteSeq checksum; +}; + +ICE_PATCH2_API void getFileTree0(const IcePatch2::FileInfoSeq&, FileTree0&); +ICE_PATCH2_API void getFileTree0(const IcePatch2::LargeFileInfoSeq&, FileTree0&); + +} + +#endif |