summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorMarc Laukien <marc@zeroc.com>2002-09-04 20:51:53 +0000
committerMarc Laukien <marc@zeroc.com>2002-09-04 20:51:53 +0000
commit19cfeafcaa8d74e597a1a47cdedbf7b71661703d (patch)
treeb9246e3ec619f8cda002f36c0282dc4a9a23aaba /cpp/src
parentmore IcePatch work (diff)
downloadice-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.cpp2
-rw-r--r--cpp/src/IcePatch/ClientUtil.cpp214
-rw-r--r--cpp/src/IcePatch/IcePatchI.cpp62
-rw-r--r--cpp/src/IcePatch/IcePatchI.h35
-rw-r--r--cpp/src/IcePatch/Makefile3
-rw-r--r--cpp/src/IcePatch/Server.cpp7
-rw-r--r--cpp/src/IcePatch/Util.cpp277
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);
}