summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Laukien <marc@zeroc.com>2005-01-27 21:22:48 +0000
committerMarc Laukien <marc@zeroc.com>2005-01-27 21:22:48 +0000
commit1decea8e7dcbf1c7836d27401d63229c49191556 (patch)
treed4bd9e931ea34841bc194b711f77f9cec4a499b3
parentbug fix for thread per connection (diff)
downloadice-1decea8e7dcbf1c7836d27401d63229c49191556.tar.bz2
ice-1decea8e7dcbf1c7836d27401d63229c49191556.tar.xz
ice-1decea8e7dcbf1c7836d27401d63229c49191556.zip
icepatch2 changes
-rw-r--r--cpp/include/Ice/LoggerUtil.h27
-rwxr-xr-xcpp/include/IcePatch2/ClientUtil.h2
-rw-r--r--cpp/include/IcePatch2/Util.h14
-rw-r--r--cpp/slice/IcePatch2/FileServer.ice59
-rw-r--r--cpp/src/Ice/LoggerUtil.cpp34
-rw-r--r--cpp/src/IcePatch2/.depend2
-rw-r--r--cpp/src/IcePatch2/Calc.cpp78
-rw-r--r--cpp/src/IcePatch2/Client.cpp23
-rwxr-xr-xcpp/src/IcePatch2/ClientUtil.cpp93
-rw-r--r--cpp/src/IcePatch2/FileServerI.cpp56
-rw-r--r--cpp/src/IcePatch2/FileServerI.h5
-rw-r--r--cpp/src/IcePatch2/Server.cpp59
-rw-r--r--cpp/src/IcePatch2/Util.cpp300
13 files changed, 364 insertions, 388 deletions
diff --git a/cpp/include/Ice/LoggerUtil.h b/cpp/include/Ice/LoggerUtil.h
index 2b1c2c42ec1..9cbecdabe8c 100644
--- a/cpp/include/Ice/LoggerUtil.h
+++ b/cpp/include/Ice/LoggerUtil.h
@@ -15,6 +15,33 @@
namespace Ice
{
+class ICE_API Print : public IceUtil::noncopyable
+{
+public:
+
+ Print(const LoggerPtr&);
+ ~Print();
+
+ void flush();
+
+ std::ostringstream& __str(); // For internal use only. Don't use in your code.
+
+private:
+
+ LoggerPtr _logger;
+ std::ostringstream _str;
+};
+
+template<typename T>
+inline Print&
+operator<<(Print& out, const T& val)
+{
+ out.__str() << val;
+ return out;
+}
+
+ICE_API Print& operator<<(Print&, std::ios_base& (*)(std::ios_base&));
+
class ICE_API Warning : public IceUtil::noncopyable
{
public:
diff --git a/cpp/include/IcePatch2/ClientUtil.h b/cpp/include/IcePatch2/ClientUtil.h
index c5940c820eb..bbed567035b 100755
--- a/cpp/include/IcePatch2/ClientUtil.h
+++ b/cpp/include/IcePatch2/ClientUtil.h
@@ -75,7 +75,7 @@ private:
const PatcherFeedbackPtr _feedback;
const std::string _dataDir;
const bool _thorough;
- Ice::Int _chunkSize;
+ const Ice::Int _chunkSize;
const Ice::Int _remove;
const FileServerPrx _serverCompress;
const FileServerPrx _serverNoCompress;
diff --git a/cpp/include/IcePatch2/Util.h b/cpp/include/IcePatch2/Util.h
index cabe5d8af1e..23617060a00 100644
--- a/cpp/include/IcePatch2/Util.h
+++ b/cpp/include/IcePatch2/Util.h
@@ -24,7 +24,7 @@ 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 normalize(const std::string&);
+ICE_PATCH2_API std::string simplify(const std::string&);
ICE_PATCH2_API std::string getSuffix(const std::string&);
ICE_PATCH2_API std::string getWithoutSuffix(const std::string&);
@@ -108,15 +108,6 @@ struct FileInfoLess: public std::binary_function<const FileInfo&, const FileInfo
}
};
-struct PathLess: public std::binary_function<const FileInfo&, const FileInfo&, bool>
-{
- bool
- operator()(const FileInfo& lhs, const FileInfo& rhs)
- {
- return lhs.path < rhs.path;
- }
-};
-
class ICE_PATCH2_API GetFileInfoSeqCB
{
public:
@@ -128,7 +119,8 @@ public:
virtual bool compress(const std::string&) = 0;
};
-ICE_PATCH2_API void getFileInfoSeq(const std::string&, int, GetFileInfoSeqCB*, FileInfoSeq&);
+ICE_PATCH2_API bool getFileInfoSeq(const std::string&, int, GetFileInfoSeqCB*, FileInfoSeq&);
+ICE_PATCH2_API bool getFileInfoSeqSubDir(const std::string&, const std::string&, int, GetFileInfoSeqCB*, FileInfoSeq&);
ICE_PATCH2_API void saveFileInfoSeq(const std::string&, const FileInfoSeq&);
ICE_PATCH2_API void loadFileInfoSeq(const std::string&, FileInfoSeq&);
diff --git a/cpp/slice/IcePatch2/FileServer.ice b/cpp/slice/IcePatch2/FileServer.ice
index f57b7f6d11e..a45dcf4e751 100644
--- a/cpp/slice/IcePatch2/FileServer.ice
+++ b/cpp/slice/IcePatch2/FileServer.ice
@@ -12,30 +12,28 @@
#include <IcePatch2/FileInfo.ice>
-module IcePatch2
-{
-
/**
*
- * The number of partitions in the file set. [getCheckSumSeq]
- * returns a sequence with [NumPartitions] elements, and
- * [getFileInfoSeq] expects an argument in the range
- * <literal>0</literal> to <literal>NumPartitions - 1</literal>.
+ * &IcePatch2; can be used to update file hiearchies in a simple and
+ * efficient manner. Checksums ensure file integrity, and data is
+ * compressed before download.
*
**/
-const int NumPartitions = 256;
+module IcePatch2
+{
/**
*
- * A sequence of byte sequences. Each element is the checksum for a partition.
+ * A sequence of byte sequences. Each element is the checksum for a
+ * partition.
*
**/
sequence<Ice::ByteSeq> ByteSeqSeq;
/**
*
- * This exception is raised if the [partition] argument for [getFileInfoSeq]
- * is not in the range <literal>0</literal> to <literal>NumPartitions - 1</literal>.
+ * This exception is raised if the [partition] argument for
+ * [getFileInfoSeq] is not in the range 0-255.
*
**/
exception PartitionOutOfRangeException
@@ -44,8 +42,8 @@ exception PartitionOutOfRangeException
/**
*
- * This exception is raised if [getFileCompressed] cannot read the contents
- * of a file.
+ * This exception is raised if [getFileCompressed] cannot read the
+ * contents of a file.
*
**/
exception FileAccessException
@@ -62,13 +60,15 @@ interface FileServer
{
/**
*
- * Return the [FileInfoSeq] for the specified partition. If the partion
- * number is out of range, the operation throws [PartitionOutOfRangException].
+ * Return the [FileInfoSeq] for the specified partition. If the
+ * partion number is out of range, the operation throws
+ * [PartitionOutOfRangException].
+ *
+ * @param partition The partition number in the range 0-255.
*
- * @param partition The partition number (in the range <literal>0</literal>
- * to <literal>NumPartitions - 1</literal>).
+ * @return A sequence containing the [FileInfo] structures for
+ * files in the specified partition.
*
- * @return A sequence containing the [FileInfo] structures for files in the specified partition.
**/
["ami"] nonmutating FileInfoSeq getFileInfoSeq(int partition)
throws PartitionOutOfRangeException;
@@ -77,10 +77,11 @@ interface FileServer
*
* Return the checksums for all partitions.
*
- * @return A sequence containing <literal>NumPartitions</literal> checksums. Partitions
- * with a checksum that differs from the previous checksum for the same partition
- * contain updated files. Partitions with a checksum that is identical to the
- * previous checksum do not contain updated files.
+ * @return A sequence containing 256 checksums. Partitions with a
+ * checksum that differs from the previous checksum for the same
+ * partition contain updated files. Partitions with a checksum
+ * that is identical to the previous checksum do not contain
+ * updated files.
*
**/
nonmutating ByteSeqSeq getChecksumSeq();
@@ -97,19 +98,19 @@ interface FileServer
/**
*
- * Read the specified file. If the read operation fails, the operation
- * throws [FileAccessException].
+ * Read the specified file. If the read operation fails, the
+ * operation throws [FileAccessException]. This operation may only
+ * return fewer bytes than requested in case there was an
+ * end-of-file condition.
*
- * @param path The pathname (relative to the data directory) for the file to be read.
+ * @param path The pathname (relative to the data directory) for
+ * the file to be read.
*
* @param pos The file offset at which to begin reading.
*
* @param num The number of bytes to be read.
*
- * @return A sequence containing the (compressed) file contents. The operation may
- * return fewer bytes than requested, either because end-of-file was reached, or
- * because more than <literal>IcePatch2.MaxReadSize * 1024</literal> bytes were
- * requested.
+ * @return A sequence containing the compressed file contents.
*
**/
["ami"] nonmutating Ice::ByteSeq getFileCompressed(string path, int pos, int num)
diff --git a/cpp/src/Ice/LoggerUtil.cpp b/cpp/src/Ice/LoggerUtil.cpp
index 5e87c44cb5b..d9d80c52720 100644
--- a/cpp/src/Ice/LoggerUtil.cpp
+++ b/cpp/src/Ice/LoggerUtil.cpp
@@ -14,6 +14,40 @@ using namespace std;
using namespace Ice;
using namespace IceInternal;
+Ice::Print::Print(const LoggerPtr& logger) :
+ _logger(logger)
+{
+}
+
+Ice::Print::~Print()
+{
+ flush();
+}
+
+void
+Ice::Print::flush()
+{
+ string s = _str.str();
+ if(!s.empty())
+ {
+ _logger->print(s);
+ }
+ _str.str("");
+}
+
+ostringstream&
+Ice::Print::__str()
+{
+ return _str;
+}
+
+Print&
+Ice::operator<<(Print& out, ios_base& (*val)(ios_base&))
+{
+ out.__str() << val;
+ return out;
+}
+
Ice::Warning::Warning(const LoggerPtr& logger) :
_logger(logger)
{
diff --git a/cpp/src/IcePatch2/.depend b/cpp/src/IcePatch2/.depend
index 42a44ecd1b4..2fec3e158f7 100644
--- a/cpp/src/IcePatch2/.depend
+++ b/cpp/src/IcePatch2/.depend
@@ -6,3 +6,5 @@ Server.o: Server.cpp ../../include/IceUtil/Options.h ../../include/IceUtil/Confi
FileServerI.o: FileServerI.cpp ../IcePatch2/FileServerI.h ../../include/IcePatch2/Util.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/IceUtil/Exception.h ../../include/IceUtil/Config.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionIF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/ConnectionF.h ../../include/Ice/Identity.h ../../include/Ice/StreamF.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/FacetMap.h ../../include/Ice/ServantLocator.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/IceUtil/GCRecMutex.h ../../include/IceUtil/RecMutex.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Incoming.h ../../include/Ice/ServantManagerF.h ../../include/Ice/BasicStream.h ../../include/Ice/Buffer.h ../../include/Ice/Process.h ../../include/Ice/Outgoing.h ../../include/Ice/Direct.h ../../include/Ice/Application.h ../../include/Ice/Connection.h ../../include/Ice/Functional.h ../../include/IceUtil/Functional.h ../../include/Ice/Stream.h ../../include/IcePatch2/FileInfo.h ../../include/IcePatch2/FileServer.h ../../include/Ice/UserExceptionFactory.h ../../include/Ice/FactoryTable.h ../../include/Ice/FactoryTableDef.h ../../include/IceUtil/StaticMutex.h ../../include/Ice/UserExceptionFactoryF.h
Client.o: Client.cpp ../../include/IceUtil/Options.h ../../include/IceUtil/Config.h ../../include/IceUtil/RecMutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h ../../include/Ice/Application.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionIF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/ConnectionF.h ../../include/Ice/Identity.h ../../include/Ice/StreamF.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/FacetMap.h ../../include/Ice/ServantLocator.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/IceUtil/GCRecMutex.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Incoming.h ../../include/Ice/ServantManagerF.h ../../include/Ice/BasicStream.h ../../include/Ice/Buffer.h ../../include/Ice/Process.h ../../include/Ice/Outgoing.h ../../include/Ice/Direct.h ../../include/Ice/Connection.h ../../include/Ice/Functional.h ../../include/IceUtil/Functional.h ../../include/Ice/Stream.h ../../include/IcePatch2/Util.h ../../include/IcePatch2/FileInfo.h ../../include/IcePatch2/ClientUtil.h ../../include/IceUtil/Thread.h ../../include/IcePatch2/FileServer.h ../../include/Ice/UserExceptionFactory.h ../../include/Ice/FactoryTable.h ../../include/Ice/FactoryTableDef.h ../../include/IceUtil/StaticMutex.h ../../include/Ice/UserExceptionFactoryF.h
Calc.o: Calc.cpp ../../include/IceUtil/Options.h ../../include/IceUtil/Config.h ../../include/IceUtil/RecMutex.h ../../include/IceUtil/Lock.h ../../include/IceUtil/ThreadException.h ../../include/IceUtil/Exception.h ../../include/IcePatch2/Util.h ../../include/Ice/Ice.h ../../include/Ice/Initialize.h ../../include/Ice/CommunicatorF.h ../../include/Ice/LocalObjectF.h ../../include/Ice/Handle.h ../../include/IceUtil/Handle.h ../../include/Ice/Config.h ../../include/Ice/ProxyF.h ../../include/Ice/ProxyHandle.h ../../include/Ice/ObjectF.h ../../include/Ice/Exception.h ../../include/Ice/LocalObject.h ../../include/IceUtil/Shared.h ../../include/Ice/PropertiesF.h ../../include/Ice/InstanceF.h ../../include/Ice/BuiltinSequences.h ../../include/Ice/Proxy.h ../../include/IceUtil/Mutex.h ../../include/Ice/ProxyFactoryF.h ../../include/Ice/ConnectionIF.h ../../include/Ice/EndpointF.h ../../include/Ice/ObjectAdapterF.h ../../include/Ice/ReferenceF.h ../../include/Ice/OutgoingAsyncF.h ../../include/Ice/Current.h ../../include/Ice/ConnectionF.h ../../include/Ice/Identity.h ../../include/Ice/StreamF.h ../../include/Ice/LocalException.h ../../include/Ice/Properties.h ../../include/Ice/Logger.h ../../include/Ice/LoggerUtil.h ../../include/Ice/LoggerF.h ../../include/Ice/Stats.h ../../include/Ice/Communicator.h ../../include/Ice/StatsF.h ../../include/Ice/ObjectFactoryF.h ../../include/Ice/RouterF.h ../../include/Ice/LocatorF.h ../../include/Ice/PluginF.h ../../include/Ice/ObjectFactory.h ../../include/Ice/ObjectAdapter.h ../../include/Ice/ServantLocatorF.h ../../include/Ice/FacetMap.h ../../include/Ice/ServantLocator.h ../../include/Ice/Object.h ../../include/IceUtil/GCShared.h ../../include/IceUtil/GCRecMutex.h ../../include/Ice/IncomingAsyncF.h ../../include/Ice/IdentityUtil.h ../../include/Ice/OutgoingAsync.h ../../include/IceUtil/Monitor.h ../../include/IceUtil/Cond.h ../../include/IceUtil/Time.h ../../include/Ice/IncomingAsync.h ../../include/Ice/Incoming.h ../../include/Ice/ServantManagerF.h ../../include/Ice/BasicStream.h ../../include/Ice/Buffer.h ../../include/Ice/Process.h ../../include/Ice/Outgoing.h ../../include/Ice/Direct.h ../../include/Ice/Application.h ../../include/Ice/Connection.h ../../include/Ice/Functional.h ../../include/IceUtil/Functional.h ../../include/Ice/Stream.h ../../include/IcePatch2/FileInfo.h
+FileInfo.cpp: ../../slice/IcePatch2/FileInfo.ice ../../slice/Ice/BuiltinSequences.ice
+FileServer.cpp: ../../slice/IcePatch2/FileServer.ice ../../slice/IcePatch2/FileInfo.ice ../../slice/Ice/BuiltinSequences.ice
diff --git a/cpp/src/IcePatch2/Calc.cpp b/cpp/src/IcePatch2/Calc.cpp
index 29b7199ee1e..358794c146d 100644
--- a/cpp/src/IcePatch2/Calc.cpp
+++ b/cpp/src/IcePatch2/Calc.cpp
@@ -174,36 +174,68 @@ main(int argc, char* argv[])
usage(argv[0]);
return EXIT_FAILURE;
}
+ dataDir = simplify(args[0]);
+
+ for(vector<string>::size_type i = 1; i < args.size(); ++i)
+ {
+ fileSeq.push_back(simplify(args[i]));
+ }
try
{
- //
- // Make working directory the data directory *before* calling normalize() for
- // for the first time (because normalize caches the current working directory).
- //
- if(chdir(args[0].c_str()) != 0)
+ StringSeq::iterator p;
+ string absDataDir = dataDir;
+
+#ifdef _WIN32
+ char cwd[_MAX_PATH];
+ if(_getcwd(cwd, _MAX_PATH) == NULL)
{
- string msg = "cannot change working directory to `" + args[0] + "': " + lastError();
- throw msg;
+ throw "cannot get the current directory:\n" + lastError();
}
- dataDir = normalize(".");
- string dataDirWithSlash = dataDir + "/";
-
- for(vector<string>::size_type i = 1; i < args.size(); ++i)
+
+ if(absDataDir[0] != '/' && !(absDataDir.size() > 1 && isalpha(absDataDir[0]) && absDataDir[1] == ':'))
+ {
+ absDataDir = string(cwd) + '/' + absDataDir;
+ }
+
+ for(p = fileSeq.begin(); p != fileSeq.end(); ++p)
+ {
+ if((*p)[0] != '/' && !(p->size() > 1 && isalpha((*p)[0]) && (*p)[1] == ':'))
+ {
+ *p = string(cwd) + '/' + *p;
+ }
+ }
+#else
+ char cwd[PATH_MAX];
+ if(getcwd(cwd, PATH_MAX) == NULL)
{
- fileSeq.push_back(normalize(args[i]));
+ throw "cannot get the current directory:\n" + lastError();
}
+
+ if(absDataDir[0] != '/')
+ {
+ absDataDir = string(cwd) + '/' + absDataDir;
+ }
+
+ for(p = fileSeq.begin(); p != fileSeq.end(); ++p)
+ {
+ if((*p)[0] != '/')
+ {
+ *p = string(cwd) + '/' + *p;
+ }
+ }
+#endif
- StringSeq::iterator p;
+ string absDataDirWithSlash = absDataDir + '/';
+
for(p = fileSeq.begin(); p != fileSeq.end(); ++p)
{
- if(p->compare(0, dataDirWithSlash.size(), dataDirWithSlash) != 0)
+ if(p->compare(0, absDataDirWithSlash.size(), absDataDirWithSlash) != 0)
{
throw "`" + *p + "' is not a path in `" + dataDir + "'";
}
- p->erase(0, dataDirWithSlash.size());
- *p = "./" + *p;
+ p->erase(0, absDataDirWithSlash.size());
}
FileInfoSeq infoSeq;
@@ -211,18 +243,24 @@ main(int argc, char* argv[])
if(fileSeq.empty())
{
CalcCB calcCB;
- getFileInfoSeq(".", compress, verbose ? &calcCB : 0, infoSeq);
+ if(!getFileInfoSeq(absDataDir, compress, verbose ? &calcCB : 0, infoSeq))
+ {
+ return EXIT_FAILURE;
+ }
}
else
{
- loadFileInfoSeq(".", infoSeq);
+ loadFileInfoSeq(absDataDir, infoSeq);
for(p = fileSeq.begin(); p != fileSeq.end(); ++p)
{
FileInfoSeq partialInfoSeq;
CalcCB calcCB;
- getFileInfoSeq(*p, compress, verbose ? &calcCB : 0, partialInfoSeq);
+ if(!getFileInfoSeqSubDir(absDataDir, *p, compress, verbose ? &calcCB : 0, partialInfoSeq))
+ {
+ return EXIT_FAILURE;
+ }
FileInfoSeq newInfoSeq;
newInfoSeq.reserve(infoSeq.size());
@@ -274,7 +312,7 @@ main(int argc, char* argv[])
}
}
- saveFileInfoSeq(dataDir, infoSeq);
+ saveFileInfoSeq(absDataDir, infoSeq);
}
catch(const string& ex)
{
diff --git a/cpp/src/IcePatch2/Client.cpp b/cpp/src/IcePatch2/Client.cpp
index ce6752b215b..8c9581061f2 100644
--- a/cpp/src/IcePatch2/Client.cpp
+++ b/cpp/src/IcePatch2/Client.cpp
@@ -14,7 +14,6 @@
#ifdef _WIN32
# include <conio.h>
-# include <direct.h>
#else
# include <fcntl.h>
# include <termios.h>
@@ -254,25 +253,11 @@ Client::run(int argc, char* argv[])
usage(argv[0]);
return EXIT_FAILURE;
}
- if(args.empty())
+ if(args.size() == 1)
{
- cerr << argv[0] << ": no data directory specified" << endl;
- usage(argv[0]);
- return EXIT_FAILURE;
- }
-
- //
- // Make working directory the data directory *before* calling normalize() for
- // for the first time (because normalize caches the current working directory).
- //
- if(chdir(args[0].c_str()) != 0)
- {
- string msg = "cannot change working directory to `" + args[0] + "': " + lastError();
- throw msg;
+ properties->setProperty("IcePatch2.Directory", args[0]);
}
- properties->setProperty("IcePatch2.Directory", normalize("."));
-
bool aborted = false;
try
@@ -284,7 +269,7 @@ Client::run(int argc, char* argv[])
if(!aborted)
{
- aborted = !patcher->patch(".");
+ aborted = !patcher->patch("");
}
if(!aborted)
@@ -318,7 +303,7 @@ Client::usage(const string& appName)
"-v, --version Display the Ice version.\n"
"-t, --thorough Recalculate all checksums.";
- cerr << "Usage: " << appName << " [options] DIR" << endl;
+ cerr << "Usage: " << appName << " [options] [DIR]" << endl;
cerr << options << endl;
}
diff --git a/cpp/src/IcePatch2/ClientUtil.cpp b/cpp/src/IcePatch2/ClientUtil.cpp
index 83e5791baab..a8d86f9e006 100755
--- a/cpp/src/IcePatch2/ClientUtil.cpp
+++ b/cpp/src/IcePatch2/ClientUtil.cpp
@@ -114,8 +114,8 @@ public:
try
{
- decompressFile(info.path);
- remove(info.path + ".bz2");
+ decompressFile(_dataDir + '/' + info.path);
+ remove(_dataDir + '/' + info.path + ".bz2");
}
catch(const string& ex)
{
@@ -142,34 +142,45 @@ private:
IcePatch2::Patcher::Patcher(const CommunicatorPtr& communicator, const PatcherFeedbackPtr& feedback) :
_feedback(feedback),
- _dataDir(normalize(communicator->getProperties()->getPropertyWithDefault("IcePatch2.Directory", "."))),
+ _dataDir(simplify(communicator->getProperties()->getProperty("IcePatch2.Directory"))),
_thorough(communicator->getProperties()->getPropertyAsInt("IcePatch2.Thorough") > 0),
- _chunkSize(communicator->getProperties()->getPropertyAsIntWithDefault("IcePatch2.ChunkSize", 100)),
+ _chunkSize(communicator->getProperties()->getPropertyAsIntWithDefault("IcePatch2.ChunkSize", 100000)),
_remove(communicator->getProperties()->getPropertyAsIntWithDefault("IcePatch2.Remove", 1))
{
- if(chdir(_dataDir.c_str()) != 0)
+ if(_dataDir.empty())
{
- throw string("cannot change directory to `" + _dataDir + "': " + lastError());
+ throw string("no data directory specified");
}
- int sizeMax = communicator->getProperties()->getPropertyAsIntWithDefault("Ice.MessageSizeMax", 1024);
if(_chunkSize < 1)
{
const_cast<Int&>(_chunkSize) = 1;
}
- else if(_chunkSize > sizeMax)
- {
- _chunkSize = sizeMax;
- }
- if(_chunkSize == sizeMax)
+
+#ifdef _WIN32
+ if(_dataDir[0] != '/' && !(_dataDir.size() > 1 && isalpha(_dataDir[0]) && _dataDir[1] == ':'))
{
- _chunkSize = _chunkSize * 1024 - 512; // Leave some headroom for protocol header.
+ char cwd[_MAX_PATH];
+ if(_getcwd(cwd, _MAX_PATH) == NULL)
+ {
+ throw "cannot get the current directory:\n" + lastError();
+ }
+
+ const_cast<string&>(_dataDir) = string(cwd) + '/' + _dataDir;
}
- else
+#else
+ if(_dataDir[0] != '/')
{
- _chunkSize *= 1024;
+ char cwd[PATH_MAX];
+ if(getcwd(cwd, PATH_MAX) == NULL)
+ {
+ throw "cannot get the current directory:\n" + lastError();
+ }
+
+ const_cast<string&>(_dataDir) = string(cwd) + '/' + _dataDir;
}
-
+#endif
+
PropertiesPtr properties = communicator->getProperties();
const char* endpointsProperty = "IcePatch2.Endpoints";
@@ -318,7 +329,10 @@ IcePatch2::Patcher::prepare()
}
PatcherGetFileInfoSeqCB cb(_feedback);
- getFileInfoSeq(".", 0, &cb, _localFiles);
+ if(!getFileInfoSeq(_dataDir, 0, &cb, _localFiles))
+ {
+ return false;
+ }
if(!_feedback->checksumEnd())
{
@@ -339,7 +353,7 @@ IcePatch2::Patcher::prepare()
}
ByteSeqSeq checksumSeq = _serverCompress->getChecksumSeq();
- if(static_cast<int>(checksumSeq.size()) != NumPartitions)
+ if(checksumSeq.size() != 256)
{
throw string("server returned illegal value");
}
@@ -347,7 +361,7 @@ IcePatch2::Patcher::prepare()
AMIGetFileInfoSeqPtr curCB;
AMIGetFileInfoSeqPtr nxtCB;
- for(int node0 = 0; node0 < NumPartitions; ++node0)
+ for(int node0 = 0; node0 < 256; ++node0)
{
if(tree0.nodes[node0].checksum != checksumSeq[node0])
{
@@ -370,9 +384,9 @@ IcePatch2::Patcher::prepare()
{
++node0Nxt;
}
- while(node0Nxt < NumPartitions && tree0.nodes[node0Nxt].checksum == checksumSeq[node0Nxt]);
+ while(node0Nxt < 256 && tree0.nodes[node0Nxt].checksum == checksumSeq[node0Nxt]);
- if(node0Nxt < NumPartitions)
+ if(node0Nxt < 256)
{
_serverNoCompress->getFileInfoSeq_async(nxtCB, node0Nxt);
}
@@ -397,7 +411,7 @@ IcePatch2::Patcher::prepare()
FileInfoLess());
}
- if(!_feedback->fileListProgress((node0 + 1) * 100 / NumPartitions))
+ if(!_feedback->fileListProgress((node0 + 1) * 100 / 256))
{
return false;
}
@@ -409,23 +423,14 @@ IcePatch2::Patcher::prepare()
}
}
- sort(_updateFiles.begin(), _updateFiles.end(), FileInfoLess());
sort(_removeFiles.begin(), _removeFiles.end(), FileInfoLess());
+ sort(_updateFiles.begin(), _updateFiles.end(), FileInfoLess());
- //
- // Remove the data dir itself from the list of files to be removed.
- //
- FileInfo fi;
- fi.path = _dataDir;
- pair<FileInfoSeq::iterator, FileInfoSeq::iterator> p
- = equal_range(_removeFiles.begin(), _removeFiles.end(), fi, PathLess());
- _removeFiles.erase(p.first, p.second);
-
- string patchLog = _dataDir + "/" + logFile;
- _log.open(patchLog.c_str());
+ string pathLog = simplify(_dataDir + '/' + logFile);
+ _log.open(pathLog.c_str());
if(!_log)
{
- throw "cannot open `" + patchLog + "' for writing:\n" + lastError();
+ throw "cannot open `" + pathLog + "' for writing:\n" + lastError();
}
return true;
@@ -434,9 +439,9 @@ IcePatch2::Patcher::prepare()
bool
IcePatch2::Patcher::patch(const string& d)
{
- string dir = normalize(d);
+ string dir = simplify(d);
- if(dir == _dataDir)
+ if(dir.empty() || dir == ".")
{
if(!_removeFiles.empty())
{
@@ -528,7 +533,7 @@ IcePatch2::Patcher::removeFiles(const FileInfoSeq& files)
{
try
{
- remove(p->path);
+ remove(_dataDir + '/' + p->path);
_log << '-' << *p << endl;
}
catch(...)
@@ -677,7 +682,7 @@ IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const Decompre
{
if(p->size < 0) // Directory?
{
- createDirectoryRecursive(p->path);
+ createDirectoryRecursive(_dataDir + '/' + p->path);
_log << '+' << *p << endl;
}
else // Regular file.
@@ -689,14 +694,18 @@ IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const Decompre
if(p->size == 0)
{
- ofstream file(p->path.c_str(), ios::binary);
+ string path = _dataDir + '/' + p->path;
+ ofstream file(path.c_str(), ios::binary);
}
else
{
- string pathBZ2 = p->path + ".bz2";
+ string pathBZ2 = _dataDir + '/' + p->path + ".bz2";
string dir = getDirname(pathBZ2);
- createDirectoryRecursive(dir);
+ if(!dir.empty())
+ {
+ createDirectoryRecursive(dir);
+ }
try
{
diff --git a/cpp/src/IcePatch2/FileServerI.cpp b/cpp/src/IcePatch2/FileServerI.cpp
index c627d2180a9..98b9c0d6e01 100644
--- a/cpp/src/IcePatch2/FileServerI.cpp
+++ b/cpp/src/IcePatch2/FileServerI.cpp
@@ -22,53 +22,32 @@ using namespace std;
using namespace Ice;
using namespace IcePatch2;
-IcePatch2::FileServerI::FileServerI(const CommunicatorPtr& communicator,
- const std::string& dataDir,
- const FileInfoSeq& infoSeq) :
- _dataDir(normalize(dataDir)),
- _dataDirWithSlash(_dataDir + "/")
+IcePatch2::FileServerI::FileServerI(const std::string& dataDir, const FileInfoSeq& infoSeq) :
+ _dataDir(dataDir)
{
- int sizeMax = communicator->getProperties()->getPropertyAsIntWithDefault("Ice.MessageSizeMax", 1024);
- _maxReadSize = communicator->getProperties()->getPropertyAsIntWithDefault("IcePatch2.MaxReadSize", 256);
- if(_maxReadSize < 1)
- {
- _maxReadSize = 1;
- }
- else if(_maxReadSize > sizeMax)
- {
- _maxReadSize = sizeMax;
- }
- if(_maxReadSize == sizeMax)
- {
- _maxReadSize = _maxReadSize * 1024 - 512; // Leave some headroom for protocol header.
- }
- else
- {
- _maxReadSize *= 1024;
- }
FileTree0& tree0 = const_cast<FileTree0&>(_tree0);
getFileTree0(infoSeq, tree0);
}
FileInfoSeq
-IcePatch2::FileServerI::getFileInfoSeq(Int partition, const Current&) const
+IcePatch2::FileServerI::getFileInfoSeq(Int node0, const Current&) const
{
- if(partition < 0 || partition > 255)
+ if(node0 < 0 || node0 > 255)
{
throw PartitionOutOfRangeException();
}
- return _tree0.nodes[partition].files;
+ return _tree0.nodes[node0].files;
}
ByteSeqSeq
IcePatch2::FileServerI::getChecksumSeq(const Current&) const
{
- ByteSeqSeq checksums(NumPartitions);
+ ByteSeqSeq checksums(256);
- for(int part = 0; part < NumPartitions; ++part)
+ for(int node0 = 0; node0 < 256; ++node0)
{
- checksums[part] = _tree0.nodes[part].checksum;
+ checksums[node0] = _tree0.nodes[node0].checksum;
}
return checksums;
@@ -83,24 +62,19 @@ IcePatch2::FileServerI::getChecksum(const Current&) const
ByteSeq
IcePatch2::FileServerI::getFileCompressed(const string& pa, Int pos, Int num, const Current&) const
{
- string path = normalize(pa) + ".bz2";
- if(path.compare(0, _dataDirWithSlash.size(), _dataDirWithSlash) != 0)
- {
- FileAccessException ex;
- ex.reason = "`" + pa + "' is not a path in `" + _dataDir + "'";
- throw ex;
- }
+ string path = simplify(_dataDir + '/' + pa);
+ path += ".bz2";
+
+ //
+ // TODO: Check if path is allowed, i.e., make sure that it neither
+ // is absolute, nor that it contains illegal "..".
+ //
if(num <= 0 || pos < 0)
{
return ByteSeq();
}
- if(num > _maxReadSize)
- {
- num = _maxReadSize;
- }
-
#ifdef _WIN32
int fd = open(path.c_str(), _O_RDONLY | _O_BINARY);
#else
diff --git a/cpp/src/IcePatch2/FileServerI.h b/cpp/src/IcePatch2/FileServerI.h
index 448b3e7abe6..b9684fcea8d 100644
--- a/cpp/src/IcePatch2/FileServerI.h
+++ b/cpp/src/IcePatch2/FileServerI.h
@@ -20,7 +20,7 @@ class FileServerI : public FileServer
{
public:
- FileServerI(const Ice::CommunicatorPtr& communicator, const std::string&, const FileInfoSeq&);
+ FileServerI(const std::string&, const FileInfoSeq&);
FileInfoSeq getFileInfoSeq(Ice::Int, const Ice::Current&) const;
@@ -33,10 +33,7 @@ public:
private:
const std::string _dataDir;
- const std::string _dataDirWithSlash;
const FileTree0 _tree0;
-
- int _maxReadSize; // Max number of bytes returned per RPC.
};
}
diff --git a/cpp/src/IcePatch2/Server.cpp b/cpp/src/IcePatch2/Server.cpp
index 1085cd734a8..b0696deab15 100644
--- a/cpp/src/IcePatch2/Server.cpp
+++ b/cpp/src/IcePatch2/Server.cpp
@@ -59,20 +59,19 @@ private:
void usage(const std::string&);
- LoggerPtr _logger;
+ const LoggerPtr _logger;
};
};
-IcePatch2::PatcherService::PatcherService()
+IcePatch2::PatcherService::PatcherService() :
+ _logger(communicator()->getLogger())
{
}
bool
IcePatch2::PatcherService::start(int argc, char* argv[])
{
- _logger = communicator()->getLogger();
-
string dataDir;
IceUtil::Options opts;
@@ -108,14 +107,14 @@ IcePatch2::PatcherService::start(int argc, char* argv[])
usage(argv[0]);
return false;
}
-
- PropertiesPtr properties = communicator()->getProperties();
-
- if(!args.empty())
+ if(args.size() == 1)
{
dataDir = args[0];
}
- else
+
+ PropertiesPtr properties = communicator()->getProperties();
+
+ if(dataDir.empty())
{
dataDir = properties->getProperty("IcePatch2.Directory");
if(dataDir.empty())
@@ -130,16 +129,23 @@ IcePatch2::PatcherService::start(int argc, char* argv[])
try
{
- //
- // Make working directory the data directory *before* calling normalize() for
- // for the first time (because normalize caches the current working directory).
- //
- if(chdir(dataDir.c_str()) != 0)
+#ifdef _WIN32
+ if(dataDir[0] != '/' && !(dataDir.size() > 1 && isalpha(dataDir[0]) && dataDir[1] == ':'))
+ {
+ char cwd[_MAX_PATH];
+ if(_getcwd(cwd, _MAX_PATH) == NULL)
+#else
+ if(dataDir[0] != '/')
{
- string msg = "cannot change working directory to `" + dataDir + "': " + lastError();
- throw msg;
+ char cwd[PATH_MAX];
+ if(getcwd(cwd, PATH_MAX) == NULL)
+#endif
+ {
+ throw "cannot get the current directory:\n" + lastError();
+ }
+
+ dataDir = string(cwd) + '/' + dataDir;
}
- dataDir = normalize(".");
loadFileInfoSeq(dataDir, infoSeq);
}
@@ -157,9 +163,8 @@ IcePatch2::PatcherService::start(int argc, char* argv[])
const char* endpointsProperty = "IcePatch2.Endpoints";
if(properties->getProperty(endpointsProperty).empty())
{
- ostringstream os;
- os << "property `" << endpointsProperty << "' is not set";
- _logger->error(os.str());
+ Error err(_logger);
+ err << "property `" << endpointsProperty << "' is not set";
return false;
}
ObjectAdapterPtr adapter = communicator()->createObjectAdapter("IcePatch2");
@@ -173,7 +178,7 @@ IcePatch2::PatcherService::start(int argc, char* argv[])
const char* idProperty = "IcePatch2.Identity";
Identity id = stringToIdentity(properties->getPropertyWithDefault(idProperty, "IcePatch2/server"));
- adapter->add(new FileServerI(communicator(), dataDir, infoSeq), id);
+ adapter->add(new FileServerI(dataDir, infoSeq), id);
if(adminAdapter)
{
@@ -243,8 +248,9 @@ IcePatch2::PatcherService::usage(const string& appName)
// --nochdir is intentionally not shown here. (See the comment in main().)
);
#endif
- _logger->print("Usage: " + appName + " [options] [DIR]");
- _logger->print(options);
+
+ Print out(_logger);
+ out << "Usage: " << appName << " [options] [DIR]\n" << options;
}
int
@@ -257,9 +263,10 @@ main(int argc, char* argv[])
status = svc.main(argc, argv);
#else
//
- // For UNIX, force --nochdir option, so the service isn't started with /
- // as the working directory. That way, if the data directory is
- // specified as a relative path, we don't misinterpret that path.
+ // For UNIX, force --nochdir option, so the service isn't started
+ // with / as the working directory. That way, if the data
+ // directory is specified as a relative path, we don't
+ // misinterpret that path.
//
char** v = new char*[argc + 2];
char** vsave = new char*[argc + 2]; // We need to keep a copy of the vector because svc.main modifies argv.
diff --git a/cpp/src/IcePatch2/Util.cpp b/cpp/src/IcePatch2/Util.cpp
index eae69fe9c76..0a71e26b11f 100644
--- a/cpp/src/IcePatch2/Util.cpp
+++ b/cpp/src/IcePatch2/Util.cpp
@@ -26,6 +26,9 @@
# include <dirent.h>
#endif
+const char* IcePatch2::checksumFile = "IcePatch2.sum";
+const char* IcePatch2::logFile = "IcePatch2.log";
+
//
// Sun-OS doesn't have scandir() or alphasort().
//
@@ -100,9 +103,6 @@ using namespace std;
using namespace Ice;
using namespace IcePatch2;
-const char* IcePatch2::checksumFile = "IcePatch2.sum";
-const char* IcePatch2::logFile = "IcePatch2.log";
-
string
IcePatch2::lastError()
{
@@ -214,23 +214,13 @@ IcePatch2::stringToBytes(const string& str)
}
string
-IcePatch2::normalize(const string& path)
+IcePatch2::simplify(const string& path)
{
- static string cwd;
- static string drive;
-
string result = path;
- string::size_type pos;
- if(result.empty())
- {
- throw "Invalid empty path";
- }
+ string::size_type pos;
#ifdef _WIN32
- //
- // Turn backslashes into forward slashes.
- //
for(pos = 0; pos < result.size(); ++pos)
{
if(result[pos] == '\\')
@@ -240,147 +230,66 @@ IcePatch2::normalize(const string& path)
}
#endif
- //
- // Get current working directory the first time we come through here.
- //
- {
- static bool cwdDone = false;
- static IceUtil::StaticMutex m = ICE_STATIC_MUTEX_INITIALIZER;
-
- IceUtil::StaticMutex::Lock sync(m);
-
- if(!cwdDone)
- {
-#ifdef _WIN32
- char buf[MAX_PATH];
- if(_getcwd(buf, sizeof(buf)) == NULL)
-#else
- char buf[PATH_MAX];
- if(getcwd(buf, sizeof(buf)) == NULL)
-#endif
- {
- throw "cannot get the current directory:\n" + lastError();
- }
-#ifdef _WIN32
- for(pos = 0; buf[pos] != '\0'; ++pos)
- {
- if(buf[pos] == '\\')
- {
- buf[pos] = '/';
- }
- }
-#endif
- cwd = buf;
- drive = cwd.substr(0, 2);
- cwdDone = true;
- }
- }
-
- //
- // Create absolute path. For Windows, we make sure that there always is a drive letter.
- // Otherwise, if the data directory is specified as C:/, and we ask for a file /a, we
- // end up with C:/a. This avoids erroneously concluding that C:/a is not the same file as /a.
- //
- bool isAbsolute;
-#ifdef _WIN32
- isAbsolute = result[0] == '/' || (result.size() > 1 && isalpha(result[0]) && result[1] == ':');
- if(result[0] == '/')
- {
- result = drive + result;
- }
-#else
- isAbsolute = result[0] == '/';
-#endif
- if(!isAbsolute)
- {
- result = cwd + "/" + result;
- }
-
- //
- // Get rid of multiple adjacent slashes.
- //
pos = 0;
while((pos = result.find("//", pos)) != string::npos)
{
result.erase(pos, 1);
}
- //
- // Split out the path components and put them into a vector.
- //
-#ifdef _WIN32
- pos = 2; // Slash follows the drive letter and colon.
-#else
pos = 0;
-#endif
- vector<string> vec;
- while(pos != string::npos)
+ while((pos = result.find("/./", pos)) != string::npos)
{
- string::size_type end = result.find('/', pos + 1);
- string component;
- if(end != string::npos)
- {
- component = result.substr(pos + 1, end - (pos + 1));
- }
- else
- {
- component = result.substr(pos + 1);
- }
-
- if(component.empty())
- {
- ; // Ignore empty component caused by trailing slash in original path.
- }
- else if(component == ".")
- {
- ; // Ignore '.'
- }
- else if(component == "..")
- {
- if(!vec.empty())
- {
- vec.erase(vec.end() - 1); // Jump up one level, except at the root.
- }
- }
- else
- {
- vec.push_back(component);
- }
+ result.erase(pos, 2);
+ }
- pos = end;
+ if(result.substr(0, 2) == "./")
+ {
+ result.erase(0, 2);
}
-#ifdef _WIN32
- result = drive;
-#else
- result.clear();
-#endif
+ if(result.size() >= 2 && result.substr(result.size() - 2, 2) == "/.")
+ {
+ result.erase(result.size() - 2, 2);
+ }
- for(vector<string>::const_iterator i = vec.begin(); i != vec.end(); ++i)
+ if(result.size() >= 1 && result[result.size() - 1] == '/')
{
- result += "/" + *i;
+ result.erase(result.size() - 1);
}
+
return result;
}
string
IcePatch2::getSuffix(const string& pa)
{
- const string name = getBasename(pa);
- string::size_type pos = name.rfind('.'); // '.' must appear in final path component.
- return pos == string::npos ? string() : name.substr(pos + 1);
+ const string path = simplify(pa);
+
+ string::size_type pos = path.rfind('.');
+ if(pos == string::npos)
+ {
+ return string();
+ }
+ else
+ {
+ return path.substr(pos + 1);
+ }
}
string
IcePatch2::getWithoutSuffix(const string& pa)
{
- const string path = normalize(pa);
- if(getBasename(pa).rfind('.') == string::npos) // '.' must appear in final path component.
+ const string path = simplify(pa);
+
+ string::size_type pos = path.rfind('.');
+ if(pos == string::npos)
{
- return path;
+ return path;
+ }
+ else
+ {
+ return path.substr(0, pos);
}
- string::size_type pos = path.rfind('.');
- return path.substr(0, pos);
}
bool
@@ -393,59 +302,43 @@ IcePatch2::ignoreSuffix(const string& path)
|| suffix == "bz2temp";
}
-static bool
-isRoot(const string& pa)
-{
-#ifdef _WIN32
- if(pa.size() == 3 && isalpha(pa[0]) && pa[1] == ':' && pa[2] == '/')
- {
- return true;
- }
-#endif
- return pa == "/";
-}
-
string
IcePatch2::getBasename(const string& pa)
{
- const string path = normalize(pa);
- if(isRoot(path))
+ const string path = simplify(pa);
+
+ string::size_type pos = path.rfind('/');
+ if(pos == string::npos)
{
- return path;
+ return path;
+ }
+ else
+ {
+ return path.substr(pos + 1);
}
- string::size_type pos = path.rfind('/');
- return path.substr(pos + 1);
}
string
IcePatch2::getDirname(const string& pa)
{
- string path = normalize(pa);
- if(isRoot(path))
- {
- return path;
- }
+ const string path = simplify(pa);
+
string::size_type pos = path.rfind('/');
- path = path.substr(0, pos);
-#ifdef _WIN32
- if(path.size() == 2 && isalpha(path[0]) && path[1] == ':')
+ if(pos == string::npos)
{
- return path + "/";
+ return string();
}
-#else
- if(path.empty())
+ else
{
- return "/";
+ return path.substr(0, pos);
}
-#endif
- return path;
}
void
IcePatch2::rename(const string& fromPa, const string& toPa)
{
- const string fromPath = normalize(fromPa);
- const string toPath = normalize(toPa);
+ const string fromPath = simplify(fromPa);
+ const string toPath = simplify(toPa);
::remove(toPath.c_str()); // We ignore errors, as the file we are renaming to might not exist.
@@ -458,7 +351,7 @@ IcePatch2::rename(const string& fromPa, const string& toPa)
void
IcePatch2::remove(const string& pa)
{
- const string path = normalize(pa);
+ const string path = simplify(pa);
struct stat buf;
if(stat(path.c_str(), &buf) == -1)
@@ -489,7 +382,7 @@ IcePatch2::remove(const string& pa)
void
IcePatch2::removeRecursive(const string& pa)
{
- const string path = normalize(pa);
+ const string path = simplify(pa);
struct stat buf;
if(stat(path.c_str(), &buf) == -1)
@@ -526,7 +419,7 @@ IcePatch2::removeRecursive(const string& pa)
StringSeq
IcePatch2::readDirectory(const string& pa)
{
- const string path = normalize(pa);
+ const string path = simplify(pa);
#ifdef _WIN32
@@ -602,7 +495,7 @@ IcePatch2::readDirectory(const string& pa)
void
IcePatch2::createDirectory(const string& pa)
{
- const string path = normalize(pa);
+ const string path = simplify(pa);
#ifdef _WIN32
if(_mkdir(path.c_str()) == -1)
@@ -620,10 +513,10 @@ IcePatch2::createDirectory(const string& pa)
void
IcePatch2::createDirectoryRecursive(const string& pa)
{
- const string path = normalize(pa);
+ const string path = simplify(pa);
string dir = getDirname(path);
- if(!isRoot(dir))
+ if(!dir.empty())
{
createDirectoryRecursive(dir);
}
@@ -644,7 +537,7 @@ IcePatch2::createDirectoryRecursive(const string& pa)
void
IcePatch2::compressBytesToFile(const string& pa, const ByteSeq& bytes, Int pos)
{
- const string path = normalize(pa);
+ const string path = simplify(pa);
FILE* stdioFile = fopen(path.c_str(), "wb");
if(!stdioFile)
@@ -696,7 +589,7 @@ IcePatch2::compressBytesToFile(const string& pa, const ByteSeq& bytes, Int pos)
void
IcePatch2::decompressFile(const string& pa)
{
- const string path = normalize(pa);
+ const string path = simplify(pa);
const string pathBZ2 = path + ".bz2";
ofstream file(path.c_str(), ios::binary);
@@ -778,21 +671,23 @@ IcePatch2::decompressFile(const string& pa)
}
static bool
-getFileInfoSeqInt(const string& path, int compress, GetFileInfoSeqCB* cb, FileInfoSeq& infoSeq)
+getFileInfoSeqInt(const string& basePath, const string& relPath, int compress, GetFileInfoSeqCB* cb,
+ FileInfoSeq& infoSeq)
{
- string basename = getBasename(path);
- if(basename == checksumFile || basename == logFile) // Don't transmit these.
+ if(relPath == checksumFile || relPath == logFile)
{
return true;
}
+ const string path = basePath + '/' + relPath;
+
if(ignoreSuffix(path))
{
const string pathWithoutSuffix = getWithoutSuffix(path);
if(ignoreSuffix(pathWithoutSuffix))
{
- if(cb && !cb->remove(path))
+ if(cb && !cb->remove(relPath))
{
return false;
}
@@ -806,7 +701,7 @@ getFileInfoSeqInt(const string& path, int compress, GetFileInfoSeqCB* cb, FileIn
{
if(errno == ENOENT)
{
- if(cb && !cb->remove(path))
+ if(cb && !cb->remove(relPath))
{
return false;
}
@@ -820,7 +715,7 @@ getFileInfoSeqInt(const string& path, int compress, GetFileInfoSeqCB* cb, FileIn
}
else if(buf.st_size == 0)
{
- if(cb && !cb->remove(path))
+ if(cb && !cb->remove(relPath))
{
return false;
}
@@ -837,14 +732,14 @@ getFileInfoSeqInt(const string& path, int compress, GetFileInfoSeqCB* cb, FileIn
throw "cannot stat `" + path + "':\n" + lastError();
}
- FileInfo info;
- info.path = path;
if(S_ISDIR(buf.st_mode))
{
+ FileInfo info;
+ info.path = relPath;
info.size = -1;
- ByteSeq bytes(path.size());
- copy(path.begin(), path.end(), bytes.begin());
+ ByteSeq bytes(relPath.size());
+ copy(relPath.begin(), relPath.end(), bytes.begin());
ByteSeq bytesSHA(20);
if(!bytes.empty())
@@ -863,7 +758,7 @@ getFileInfoSeqInt(const string& path, int compress, GetFileInfoSeqCB* cb, FileIn
StringSeq content = readDirectory(path);
for(StringSeq::const_iterator p = content.begin(); p != content.end() ; ++p)
{
- if(!getFileInfoSeqInt(path + "/" + *p, compress, cb, infoSeq))
+ if(!getFileInfoSeqInt(basePath, simplify(relPath + '/' + *p), compress, cb, infoSeq))
{
return false;
}
@@ -871,10 +766,12 @@ getFileInfoSeqInt(const string& path, int compress, GetFileInfoSeqCB* cb, FileIn
}
else if(S_ISREG(buf.st_mode))
{
+ FileInfo info;
+ info.path = relPath;
info.size = 0;
- ByteSeq bytes(path.size() + buf.st_size);
- copy(path.begin(), path.end(), bytes.begin());
+ ByteSeq bytes(relPath.size() + buf.st_size);
+ copy(relPath.begin(), relPath.end(), bytes.begin());
if(buf.st_size != 0)
{
@@ -888,7 +785,7 @@ getFileInfoSeqInt(const string& path, int compress, GetFileInfoSeqCB* cb, FileIn
throw "cannot open `" + path + "' for reading:\n" + lastError();
}
- if(read(fd, &bytes[path.size()], buf.st_size) == -1)
+ if(read(fd, &bytes[relPath.size()], buf.st_size) == -1)
{
close(fd);
throw "cannot read from `" + path + "':\n" + lastError();
@@ -908,7 +805,7 @@ getFileInfoSeqInt(const string& path, int compress, GetFileInfoSeqCB* cb, FileIn
if(compress >= 2 || stat(pathBZ2.c_str(), &bufBZ2) == -1 || buf.st_mtime >= bufBZ2.st_mtime)
{
- if(cb && !cb->compress(path))
+ if(cb && !cb->compress(relPath))
{
return false;
}
@@ -921,7 +818,7 @@ getFileInfoSeqInt(const string& path, int compress, GetFileInfoSeqCB* cb, FileIn
//
const string pathBZ2Temp = path + ".bz2temp";
- compressBytesToFile(pathBZ2Temp, bytes, path.size());
+ compressBytesToFile(pathBZ2Temp, bytes, relPath.size());
rename(pathBZ2Temp, pathBZ2);
@@ -935,7 +832,7 @@ getFileInfoSeqInt(const string& path, int compress, GetFileInfoSeqCB* cb, FileIn
}
}
- if(cb && !cb->checksum(path))
+ if(cb && !cb->checksum(relPath))
{
return false;
}
@@ -959,23 +856,36 @@ getFileInfoSeqInt(const string& path, int compress, GetFileInfoSeqCB* cb, FileIn
return true;
}
-void
-IcePatch2::getFileInfoSeq(const string& path, int compress, GetFileInfoSeqCB* cb, FileInfoSeq& infoSeq)
+bool
+IcePatch2::getFileInfoSeq(const string& basePath, int compress, GetFileInfoSeqCB* cb,
+ FileInfoSeq& infoSeq)
{
- if(!getFileInfoSeqInt(path, compress, cb, infoSeq))
+ return getFileInfoSeqSubDir(basePath, ".", compress, cb, infoSeq);
+}
+
+bool
+IcePatch2::getFileInfoSeqSubDir(const string& basePa, const string& relPa, int compress, GetFileInfoSeqCB* cb,
+ FileInfoSeq& infoSeq)
+{
+ const string basePath = simplify(basePa);
+ const string relPath = simplify(relPa);
+
+ if(!getFileInfoSeqInt(basePath, relPath, compress, cb, infoSeq))
{
- return;
+ return false;
}
sort(infoSeq.begin(), infoSeq.end(), FileInfoLess());
infoSeq.erase(unique(infoSeq.begin(), infoSeq.end(), FileInfoEqual()), infoSeq.end());
+
+ return true;
}
void
IcePatch2::saveFileInfoSeq(const string& pa, const FileInfoSeq& infoSeq)
{
{
- const string path = normalize(pa + "/" + checksumFile);
+ const string path = simplify(pa + '/' + checksumFile);
ofstream os(path.c_str());
if(!os)
@@ -990,7 +900,7 @@ IcePatch2::saveFileInfoSeq(const string& pa, const FileInfoSeq& infoSeq)
}
{
- const string pathLog = normalize(pa + "/" + logFile);
+ const string pathLog = simplify(pa + '/' + logFile);
try
{
@@ -1006,7 +916,7 @@ void
IcePatch2::loadFileInfoSeq(const string& pa, FileInfoSeq& infoSeq)
{
{
- const string path = normalize(pa + "/" + checksumFile);
+ const string path = simplify(pa + '/' + checksumFile);
ifstream is(path.c_str());
if(!is)
@@ -1030,7 +940,7 @@ IcePatch2::loadFileInfoSeq(const string& pa, FileInfoSeq& infoSeq)
}
{
- const string pathLog = normalize(pa + "/" + logFile);
+ const string pathLog = simplify(pa + '/' + logFile);
ifstream is(pathLog.c_str());
if(is)