diff options
author | Marc Laukien <marc@zeroc.com> | 2002-09-04 20:51:53 +0000 |
---|---|---|
committer | Marc Laukien <marc@zeroc.com> | 2002-09-04 20:51:53 +0000 |
commit | 19cfeafcaa8d74e597a1a47cdedbf7b71661703d (patch) | |
tree | b9246e3ec619f8cda002f36c0282dc4a9a23aaba /cpp/src | |
parent | more IcePatch work (diff) | |
download | ice-19cfeafcaa8d74e597a1a47cdedbf7b71661703d.tar.bz2 ice-19cfeafcaa8d74e597a1a47cdedbf7b71661703d.tar.xz ice-19cfeafcaa8d74e597a1a47cdedbf7b71661703d.zip |
more IcePatch work
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/IcePatch/Client.cpp | 2 | ||||
-rw-r--r-- | cpp/src/IcePatch/ClientUtil.cpp | 214 | ||||
-rw-r--r-- | cpp/src/IcePatch/IcePatchI.cpp | 62 | ||||
-rw-r--r-- | cpp/src/IcePatch/IcePatchI.h | 35 | ||||
-rw-r--r-- | cpp/src/IcePatch/Makefile | 3 | ||||
-rw-r--r-- | cpp/src/IcePatch/Server.cpp | 7 | ||||
-rw-r--r-- | cpp/src/IcePatch/Util.cpp | 277 |
7 files changed, 393 insertions, 207 deletions
diff --git a/cpp/src/IcePatch/Client.cpp b/cpp/src/IcePatch/Client.cpp index 2752706d817..21fc1f9880e 100644 --- a/cpp/src/IcePatch/Client.cpp +++ b/cpp/src/IcePatch/Client.cpp @@ -508,7 +508,7 @@ IcePatch::Client::patch(const DirectoryDescPtr& dirDesc, const string& indent) c { removeRecursive(*p + ".md5"); } - catch(const FileAccessException&); + catch(const FileAccessException&) { // Ignore, the MD5 file might not exist. } diff --git a/cpp/src/IcePatch/ClientUtil.cpp b/cpp/src/IcePatch/ClientUtil.cpp new file mode 100644 index 00000000000..d715d471893 --- /dev/null +++ b/cpp/src/IcePatch/ClientUtil.cpp @@ -0,0 +1,214 @@ +// ********************************************************************** +// +// Copyright (c) 2002 +// Mutable Realms, Inc. +// Huntsville, AL, USA +// +// All Rights Reserved +// +// ********************************************************************** + +#include <IcePatch/Util.h> +#include <IcePatch/ClientUtil.h> +#include <fstream> +#include <bzlib.h> + +using namespace std; +using namespace Ice; +using namespace IcePatch; + +string +IcePatch::pathToName(const string& path) +{ + string::size_type pos = path.rfind('/'); + if(pos == string::npos) + { + return path; + } + else + { + return path.substr(pos + 1); + } +} + +void +IcePatch::getRegular(const RegularPrx& regular, ProgressCB& progressCB) +{ + string path = identityToPath(regular->ice_getIdentity()); + string pathBZ2 = path + ".bz2"; + Int totalBZ2 = regular->getBZ2Size(); + Int posBZ2 = 0; + + // + // Check for partial BZ2 file. + // + FileInfo infoBZ2 = getFileInfo(pathBZ2, false); + if(infoBZ2.type == FileTypeRegular) + { + ByteSeq remoteBZ2MD5 = regular->getBZ2MD5(infoBZ2.size); + ByteSeq localBZ2MD5 = calcPartialMD5(pathBZ2, infoBZ2.size); + + if(remoteBZ2MD5 == localBZ2MD5) + { + posBZ2 = infoBZ2.size; + } + } + + // + // Get the BZ2 file. + // + progressCB.startDownload(totalBZ2, posBZ2); + + ofstream fileBZ2(pathBZ2.c_str(), ios::binary | (posBZ2 ? ios::app : 0)); + if(!fileBZ2) + { + FileAccessException ex; + ex.reason = "cannot open `" + pathBZ2 + "' for writing: " + strerror(errno); + throw ex; + } + + while(posBZ2 < totalBZ2) + { + static const Int numBZ2 = 64 * 1024; + + ByteSeq bytesBZ2 = regular->getBZ2(posBZ2, numBZ2); + if(bytesBZ2.empty()) + { + break; + } + + posBZ2 += bytesBZ2.size(); + + fileBZ2.write(&bytesBZ2[0], bytesBZ2.size()); + if(!fileBZ2) + { + FileAccessException ex; + ex.reason = "cannot write `" + pathBZ2 + "': " + strerror(errno); + throw ex; + } + + if(static_cast<Int>(bytesBZ2.size()) < numBZ2) + { + break; + } + + progressCB.updateDownload(totalBZ2, posBZ2); + } + + progressCB.finishedDownload(totalBZ2); + + fileBZ2.close(); + + // + // Read the BZ2 file in blocks and write the original file. + // + ofstream file(path.c_str(), ios::binary); + if(!file) + { + FileAccessException ex; + ex.reason = "cannot open `" + path + "' for writing: " + strerror(errno); + throw ex; + } + + FILE* stdioFileBZ2 = fopen(pathBZ2.c_str(), "rb"); + if(!stdioFileBZ2) + { + FileAccessException ex; + ex.reason = "cannot open `" + pathBZ2 + "' for reading: " + strerror(errno); + throw ex; + } + + int bzError; + BZFILE* bzFile = BZ2_bzReadOpen(&bzError, stdioFileBZ2, 0, 0, 0, 0); + if(bzError != BZ_OK) + { + FileAccessException ex; + ex.reason = "BZ2_bzReadOpen failed"; + if(bzError == BZ_IO_ERROR) + { + ex.reason += string(": ") + strerror(errno); + } + fclose(stdioFileBZ2); + throw ex; + } + + static const Int numBZ2 = 64 * 1024; + Byte bytesBZ2[numBZ2]; + + progressCB.startUncompress(totalBZ2, 0); + + while(bzError != BZ_STREAM_END) + { + int sz = BZ2_bzRead(&bzError, bzFile, bytesBZ2, numBZ2); + if(bzError != BZ_OK && bzError != BZ_STREAM_END) + { + FileAccessException ex; + ex.reason = "BZ2_bzRead failed"; + if(bzError == BZ_IO_ERROR) + { + ex.reason += string(": ") + strerror(errno); + } + BZ2_bzReadClose(&bzError, bzFile); + fclose(stdioFileBZ2); + throw ex; + } + + if(sz > 0) + { + long pos = ftell(stdioFileBZ2); + if(pos == -1) + { + FileAccessException ex; + ex.reason = "cannot get read position for `" + pathBZ2 + "': " + strerror(errno); + BZ2_bzReadClose(&bzError, bzFile); + fclose(stdioFileBZ2); + throw ex; + } + + progressCB.updateUncompress(totalBZ2, pos); + + file.write(bytesBZ2, sz); + if(!file) + { + FileAccessException ex; + ex.reason = "cannot write `" + path + "': " + strerror(errno); + BZ2_bzReadClose(&bzError, bzFile); + fclose(stdioFileBZ2); + throw ex; + } + } + } + + progressCB.finishedUncompress(totalBZ2); + + BZ2_bzReadClose(&bzError, bzFile); + if(bzError != BZ_OK) + { + FileAccessException ex; + ex.reason = "BZ2_bzReadClose failed"; + if(bzError == BZ_IO_ERROR) + { + ex.reason += string(": ") + strerror(errno); + } + fclose(stdioFileBZ2); + throw ex; + } + + fclose(stdioFileBZ2); + file.close(); + + // + // Remove the BZ2 file, it is not needed anymore. + // + if(::remove(pathBZ2.c_str()) == -1) + { + FileAccessException ex; + ex.reason = "cannot remove file `" + pathBZ2 + "': " + strerror(errno); + throw ex; + } + + // + // Create a MD5 file for the original file. + // + createMD5(path); +} diff --git a/cpp/src/IcePatch/IcePatchI.cpp b/cpp/src/IcePatch/IcePatchI.cpp index 502757b3232..55d8f66b387 100644 --- a/cpp/src/IcePatch/IcePatchI.cpp +++ b/cpp/src/IcePatch/IcePatchI.cpp @@ -15,15 +15,42 @@ using namespace std; using namespace Ice; using namespace IcePatch; -IceUtil::RWRecMutex IcePatch::FileI::_globalMutex; +static IceUtil::RWRecMutex globalMutex; + +IcePatch::InfoI::InfoI(const ObjectAdapterPtr& adapter) : + _adapter(adapter), + _busyTimeout(IceUtil::Time::seconds(adapter->getCommunicator()->getProperties()-> + getPropertyAsIntWithDefault("IcePatch.BusyTimeout", 10))) +{ +} + +Long +IcePatch::InfoI::getStamp(const Current& current) const +{ + // + // ".icepatch" is our reserved name for the IcePatch info object, + // as well as for the directory that contains IcePatch info. + // + assert(current.id.name == ".icepatch"); + + try + { + IceUtil::RWRecMutex::TryRLock sync(globalMutex, _busyTimeout); + return readStamp(); + } + catch(const IceUtil::LockedException&) + { + throw BusyException(); + } +} IcePatch::FileI::FileI(const ObjectAdapterPtr& adapter) : _adapter(adapter), - _logger(adapter->getCommunicator()->getLogger()) + _logger(adapter->getCommunicator()->getLogger()), + _traceLevel(adapter->getCommunicator()->getProperties()->getPropertyAsInt("IcePatch.Trace.Files")), + _busyTimeout(IceUtil::Time::seconds(adapter->getCommunicator()->getProperties()-> + getPropertyAsIntWithDefault("IcePatch.BusyTimeout", 10))) { - PropertiesPtr properties = adapter->getCommunicator()->getProperties(); - _traceLevel = properties->getPropertyAsInt("IcePatch.Trace.Files"); - _busyTimeout = IceUtil::Time::seconds(properties->getPropertyAsIntWithDefault("IcePatch.BusyTimeout", 10)); } IcePatch::DirectoryI::DirectoryI(const ObjectAdapterPtr& adapter) : @@ -32,7 +59,7 @@ IcePatch::DirectoryI::DirectoryI(const ObjectAdapterPtr& adapter) : } FileDescPtr -IcePatch::DirectoryI::describe(const Current& current) +IcePatch::DirectoryI::describe(const Current& current) const { // No mutex lock necessary. DirectoryDescPtr desc = new DirectoryDesc; @@ -41,17 +68,18 @@ IcePatch::DirectoryI::describe(const Current& current) } FileDescSeq -IcePatch::DirectoryI::getContents(const Current& current) +IcePatch::DirectoryI::getContents(const Current& current) const { StringSeq filteredPaths; try { - IceUtil::RWRecMutex::TryRLock sync(_globalMutex, _busyTimeout); + IceUtil::RWRecMutex::TryRLock sync(globalMutex, _busyTimeout); bool syncUpgraded = false; string path = identityToPath(current.id); StringSeq paths = readDirectory(path); + paths.erase(remove(paths.begin(), paths.end(), ".icepatch"), paths.end()); filteredPaths.reserve(paths.size() / 3); for(StringSeq::const_iterator p = paths.begin(); p != paths.end(); ++p) { @@ -67,6 +95,7 @@ IcePatch::DirectoryI::getContents(const Current& current) syncUpgraded = true; } StringSeq paths2 = readDirectory(path); + paths.erase(remove(paths2.begin(), paths2.end(), ".icepatch"), paths2.end()); pair<StringSeq::const_iterator, StringSeq::const_iterator> r2 = equal_range(paths2.begin(), paths2.end(), removeSuffix(*p)); if(r2.first == r2.second) @@ -122,11 +151,11 @@ IcePatch::RegularI::RegularI(const ObjectAdapterPtr& adapter) : } FileDescPtr -IcePatch::RegularI::describe(const Current& current) +IcePatch::RegularI::describe(const Current& current) const { try { - IceUtil::RWRecMutex::TryRLock sync(_globalMutex, _busyTimeout); + IceUtil::RWRecMutex::TryRLock sync(globalMutex, _busyTimeout); string path = identityToPath(current.id); FileInfo info = getFileInfo(path, true); @@ -141,6 +170,7 @@ IcePatch::RegularI::describe(const Current& current) if(infoMD5.type != FileTypeRegular || infoMD5.time <= info.time) { createMD5(path); + writeStamp(readStamp() + 1); if(_traceLevel > 0) { @@ -162,11 +192,11 @@ IcePatch::RegularI::describe(const Current& current) } Int -IcePatch::RegularI::getBZ2Size(const Current& current) +IcePatch::RegularI::getBZ2Size(const Current& current) const { try { - IceUtil::RWRecMutex::TryRLock sync(_globalMutex, _busyTimeout); + IceUtil::RWRecMutex::TryRLock sync(globalMutex, _busyTimeout); string path = identityToPath(current.id); FileInfo info = getFileInfo(path, true); @@ -206,11 +236,11 @@ IcePatch::RegularI::getBZ2Size(const Current& current) } ByteSeq -IcePatch::RegularI::getBZ2(Int pos, Int num, const Current& current) +IcePatch::RegularI::getBZ2(Int pos, Int num, const Current& current) const { try { - IceUtil::RWRecMutex::TryRLock sync(_globalMutex, _busyTimeout); + IceUtil::RWRecMutex::TryRLock sync(globalMutex, _busyTimeout); string path = identityToPath(current.id); FileInfo info = getFileInfo(path, true); @@ -243,11 +273,11 @@ IcePatch::RegularI::getBZ2(Int pos, Int num, const Current& current) } ByteSeq -IcePatch::RegularI::getBZ2MD5(Int size, const Current& current) +IcePatch::RegularI::getBZ2MD5(Int size, const Current& current) const { try { - IceUtil::RWRecMutex::TryRLock sync(_globalMutex, _busyTimeout); + IceUtil::RWRecMutex::TryRLock sync(globalMutex, _busyTimeout); string path = identityToPath(current.id); FileInfo info = getFileInfo(path, true); diff --git a/cpp/src/IcePatch/IcePatchI.h b/cpp/src/IcePatch/IcePatchI.h index 934cbf1058e..69a6316e014 100644 --- a/cpp/src/IcePatch/IcePatchI.h +++ b/cpp/src/IcePatch/IcePatchI.h @@ -18,6 +18,20 @@ namespace IcePatch { +class InfoI : public Info +{ +public: + + InfoI(const Ice::ObjectAdapterPtr&); + + Ice::Long getStamp(const Ice::Current&) const; + +private: + + const Ice::ObjectAdapterPtr _adapter; + const IceUtil::Time _busyTimeout; +}; + class FileI : virtual public File { public: @@ -26,11 +40,10 @@ public: protected: - Ice::ObjectAdapterPtr _adapter; - Ice::LoggerPtr _logger; - Ice::Int _traceLevel; - IceUtil::Time _busyTimeout; - static IceUtil::RWRecMutex _globalMutex; + const Ice::ObjectAdapterPtr _adapter; + const Ice::LoggerPtr _logger; + const Ice::Int _traceLevel; + const IceUtil::Time _busyTimeout; }; class DirectoryI : virtual public Directory, @@ -40,8 +53,8 @@ public: DirectoryI(const Ice::ObjectAdapterPtr&); - virtual FileDescPtr describe(const Ice::Current&); - virtual FileDescSeq getContents(const Ice::Current&); + virtual FileDescPtr describe(const Ice::Current&) const; + virtual FileDescSeq getContents(const Ice::Current&) const; }; class RegularI : virtual public Regular, @@ -51,10 +64,10 @@ public: RegularI(const Ice::ObjectAdapterPtr&); - virtual FileDescPtr describe(const Ice::Current&); - virtual Ice::Int getBZ2Size(const Ice::Current&); - virtual Ice::ByteSeq getBZ2(Ice::Int, Ice::Int, const Ice::Current&); - virtual Ice::ByteSeq getBZ2MD5(Ice::Int, const Ice::Current&); + virtual FileDescPtr describe(const Ice::Current&) const; + virtual Ice::Int getBZ2Size(const Ice::Current&) const; + virtual Ice::ByteSeq getBZ2(Ice::Int, Ice::Int, const Ice::Current&) const; + virtual Ice::ByteSeq getBZ2MD5(Ice::Int, const Ice::Current&) const; }; } diff --git a/cpp/src/IcePatch/Makefile b/cpp/src/IcePatch/Makefile index a01b561b99e..d45e84777a1 100644 --- a/cpp/src/IcePatch/Makefile +++ b/cpp/src/IcePatch/Makefile @@ -23,7 +23,8 @@ TARGETS = $(NAME) $(VERSIONED_NAME) $(CLIENT) $(SERVER) OBJS = IcePatch.o \ FileDescFactory.o \ - Util.o + Util.o \ + ClientUtil.o COBJS = Client.o diff --git a/cpp/src/IcePatch/Server.cpp b/cpp/src/IcePatch/Server.cpp index 1e804670ddd..8f83ba69a04 100644 --- a/cpp/src/IcePatch/Server.cpp +++ b/cpp/src/IcePatch/Server.cpp @@ -11,6 +11,7 @@ #include <IceUtil/IceUtil.h> #include <Ice/Application.h> #include <IcePatch/FileLocator.h> +#include <IcePatch/IcePatchI.h> #include <IcePatch/Util.h> #ifdef _WIN32 # include <direct.h> @@ -125,6 +126,12 @@ IcePatch::Server::run(int argc, char* argv[]) ObjectAdapterPtr adapter = communicator()->createObjectAdapterFromProperty("IcePatch", endpointsProperty); ServantLocatorPtr fileLocator = new FileLocator(adapter); adapter->addServantLocator(fileLocator, "IcePatch"); + + // + // Create the "info" Ice Object. + // + InfoPtr info = new InfoI(adapter); + adapter->add(info, pathToIdentity(".icepatch")); // .icepatch is reserved, so lets use this for info identity. // // Start the updater if an update period is set. diff --git a/cpp/src/IcePatch/Util.cpp b/cpp/src/IcePatch/Util.cpp index dbbed190626..2906620819f 100644 --- a/cpp/src/IcePatch/Util.cpp +++ b/cpp/src/IcePatch/Util.cpp @@ -9,6 +9,7 @@ // ********************************************************************** #include <IcePatch/Util.h> +#include <IceUtil/InputUtil.h> #include <fstream> #include <sys/stat.h> #include <openssl/md5.h> @@ -344,18 +345,21 @@ IcePatch::createMD5(const string& path) ByteSeq bytes; bytes.resize(info.size); - file.read(&bytes[0], bytes.size()); - if(!file) - { - FileAccessException ex; - ex.reason = "cannot read `" + path + "': " + strerror(errno); - throw ex; - } - if(file.gcount() < static_cast<int>(bytes.size())) + if(bytes.size() > 0) { - FileAccessException ex; - ex.reason = "could not read all bytes from `" + path + "'"; - throw ex; + file.read(&bytes[0], bytes.size()); + if(!file) + { + FileAccessException ex; + ex.reason = "cannot read `" + path + "': " + strerror(errno); + throw ex; + } + if(file.gcount() < static_cast<int>(bytes.size())) + { + FileAccessException ex; + ex.reason = "could not read all bytes from `" + path + "'"; + throw ex; + } } file.close(); @@ -365,7 +369,14 @@ IcePatch::createMD5(const string& path) // ByteSeq bytesMD5; bytesMD5.resize(16); - MD5(reinterpret_cast<unsigned char*>(&bytes[0]), bytes.size(), reinterpret_cast<unsigned char*>(&bytesMD5[0])); + if(bytes.size() > 0) + { + MD5(reinterpret_cast<unsigned char*>(&bytes[0]), bytes.size(), reinterpret_cast<unsigned char*>(&bytesMD5[0])); + } + else + { + fill(bytesMD5.begin(), bytesMD5.end(), 0); + } // // Save the MD5 hash value to a temporary MD5 file. @@ -436,18 +447,21 @@ IcePatch::calcPartialMD5(const string& path, Int size) ByteSeq bytes; bytes.resize(size); - file.read(&bytes[0], bytes.size()); - if(!file) + if(bytes.size() > 0) { - FileAccessException ex; - ex.reason = "cannot read `" + path + "': " + strerror(errno); - throw ex; - } - if(file.gcount() < static_cast<int>(bytes.size())) - { - FileAccessException ex; - ex.reason = "could not read all bytes from `" + path + "'"; - throw ex; + file.read(&bytes[0], bytes.size()); + if(!file) + { + FileAccessException ex; + ex.reason = "cannot read `" + path + "': " + strerror(errno); + throw ex; + } + if(file.gcount() < static_cast<int>(bytes.size())) + { + FileAccessException ex; + ex.reason = "could not read all bytes from `" + path + "'"; + throw ex; + } } file.close(); @@ -457,7 +471,14 @@ IcePatch::calcPartialMD5(const string& path, Int size) // ByteSeq bytesMD5; bytesMD5.resize(16); - MD5(reinterpret_cast<unsigned char*>(&bytes[0]), bytes.size(), reinterpret_cast<unsigned char*>(&bytesMD5[0])); + if(bytes.size() > 0) + { + MD5(reinterpret_cast<unsigned char*>(&bytes[0]), bytes.size(), reinterpret_cast<unsigned char*>(&bytesMD5[0])); + } + else + { + fill(bytesMD5.begin(), bytesMD5.end(), 0); + } return bytesMD5; } @@ -632,184 +653,84 @@ IcePatch::createBZ2(const string& path) } } -void -IcePatch::getRegular(const RegularPrx& regular, ProgressCB& progressCB) +Long +IcePatch::readStamp() { - string path = identityToPath(regular->ice_getIdentity()); - string pathBZ2 = path + ".bz2"; - Int totalBZ2 = regular->getBZ2Size(); - Int posBZ2 = 0; - - // - // Check for partial BZ2 file. - // - FileInfo infoBZ2 = getFileInfo(pathBZ2, false); - if(infoBZ2.type == FileTypeRegular) + ifstream fileStamp(".icepatch/stamp"); + if(!fileStamp) // Ignore any errors if the file cannot be read. { - ByteSeq remoteBZ2MD5 = regular->getBZ2MD5(infoBZ2.size); - ByteSeq localBZ2MD5 = calcPartialMD5(pathBZ2, infoBZ2.size); - - if(remoteBZ2MD5 == localBZ2MD5) - { - posBZ2 = infoBZ2.size; - } + return -1; } - // - // Get the BZ2 file. - // - progressCB.startDownload(totalBZ2, posBZ2); - - ofstream fileBZ2(pathBZ2.c_str(), ios::binary | (posBZ2 ? ios::app : 0)); - if(!fileBZ2) - { - FileAccessException ex; - ex.reason = "cannot open `" + pathBZ2 + "' for writing: " + strerror(errno); - throw ex; - } + string s; + fileStamp >> s; + fileStamp.close(); - while(posBZ2 < totalBZ2) + Long stamp; + string::size_type dummy; + if(!IceUtil::stringToInt64(s, stamp, dummy)) // Ignore errors during conversion. { - static const Int numBZ2 = 64 * 1024; - - ByteSeq bytesBZ2 = regular->getBZ2(posBZ2, numBZ2); - if(bytesBZ2.empty()) - { - break; - } - - posBZ2 += bytesBZ2.size(); - - fileBZ2.write(&bytesBZ2[0], bytesBZ2.size()); - if(!fileBZ2) - { - FileAccessException ex; - ex.reason = "cannot write `" + pathBZ2 + "': " + strerror(errno); - throw ex; - } - - if(static_cast<Int>(bytesBZ2.size()) < numBZ2) - { - break; - } - - progressCB.updateDownload(totalBZ2, posBZ2); + return -1; } - progressCB.finishedDownload(totalBZ2); + return stamp; +} - fileBZ2.close(); - - // - // Read the BZ2 file in blocks and write the original file. - // - ofstream file(path.c_str(), ios::binary); - if(!file) - { - FileAccessException ex; - ex.reason = "cannot open `" + path + "' for writing: " + strerror(errno); - throw ex; - } - - FILE* stdioFileBZ2 = fopen(pathBZ2.c_str(), "rb"); - if(!stdioFileBZ2) - { - FileAccessException ex; - ex.reason = "cannot open `" + pathBZ2 + "' for reading: " + strerror(errno); - throw ex; - } - - int bzError; - BZFILE* bzFile = BZ2_bzReadOpen(&bzError, stdioFileBZ2, 0, 0, 0, 0); - if(bzError != BZ_OK) +void +IcePatch::writeStamp(Long stamp) +{ + ofstream fileStamp(".icepatch/stamp"); + if(!fileStamp) { + // + // Prepare an exception, but don't throw yet. + // FileAccessException ex; - ex.reason = "BZ2_bzReadOpen failed"; - if(bzError == BZ_IO_ERROR) - { - ex.reason += string(": ") + strerror(errno); - } - fclose(stdioFileBZ2); - throw ex; - } - - static const Int numBZ2 = 64 * 1024; - Byte bytesBZ2[numBZ2]; - - progressCB.startUncompress(totalBZ2, 0); - - while(bzError != BZ_STREAM_END) - { - int sz = BZ2_bzRead(&bzError, bzFile, bytesBZ2, numBZ2); - if(bzError != BZ_OK && bzError != BZ_STREAM_END) + ex.reason = string("cannot open `.icepatch/stamp' for writing: ") + strerror(errno); + + // + // Check if the directory exists, and only throw the exception + // if it does exist. Otherwise create the directory, and try + // again. + // + FileInfo info = getFileInfo(".icepatch", false); + if(info.type == FileTypeDirectory) { - FileAccessException ex; - ex.reason = "BZ2_bzRead failed"; - if(bzError == BZ_IO_ERROR) - { - ex.reason += string(": ") + strerror(errno); - } - BZ2_bzReadClose(&bzError, bzFile); - fclose(stdioFileBZ2); + // + // If the directory exists, throw the exception. + // throw ex; } - - if(sz > 0) + else { - long pos = ftell(stdioFileBZ2); - if(pos == -1) + // + // If the directory does not exist, create it, and try + // again. + // + if(info.type != FileTypeNotExist) { - FileAccessException ex; - ex.reason = "cannot get read position for `" + pathBZ2 + "': " + strerror(errno); - BZ2_bzReadClose(&bzError, bzFile); - fclose(stdioFileBZ2); - throw ex; + removeRecursive(".icepatch"); } - - progressCB.updateUncompress(totalBZ2, pos); - file.write(bytesBZ2, sz); - if(!file) + createDirectory(".icepatch"); + + ofstream fileStamp(".icepatch/stamp"); + if(!fileStamp) { FileAccessException ex; - ex.reason = "cannot write `" + path + "': " + strerror(errno); - BZ2_bzReadClose(&bzError, bzFile); - fclose(stdioFileBZ2); + ex.reason = string("cannot open `.icepatch/stamp' for writing: ") + strerror(errno); throw ex; } + else + { + fileStamp << stamp << endl; + fileStamp.close(); + } } } - - progressCB.finishedUncompress(totalBZ2); - - BZ2_bzReadClose(&bzError, bzFile); - if(bzError != BZ_OK) - { - FileAccessException ex; - ex.reason = "BZ2_bzReadClose failed"; - if(bzError == BZ_IO_ERROR) - { - ex.reason += string(": ") + strerror(errno); - } - fclose(stdioFileBZ2); - throw ex; - } - - fclose(stdioFileBZ2); - file.close(); - - // - // Remove the BZ2 file, it is not needed anymore. - // - if(::remove(pathBZ2.c_str()) == -1) + else { - FileAccessException ex; - ex.reason = "cannot remove file `" + pathBZ2 + "': " + strerror(errno); - throw ex; + fileStamp << stamp << endl; + fileStamp.close(); } - - // - // Create a MD5 file for the original file. - // - createMD5(path); } |