diff options
author | Marc Laukien <marc@zeroc.com> | 2005-01-27 21:22:48 +0000 |
---|---|---|
committer | Marc Laukien <marc@zeroc.com> | 2005-01-27 21:22:48 +0000 |
commit | 1decea8e7dcbf1c7836d27401d63229c49191556 (patch) | |
tree | d4bd9e931ea34841bc194b711f77f9cec4a499b3 /cpp | |
parent | bug fix for thread per connection (diff) | |
download | ice-1decea8e7dcbf1c7836d27401d63229c49191556.tar.bz2 ice-1decea8e7dcbf1c7836d27401d63229c49191556.tar.xz ice-1decea8e7dcbf1c7836d27401d63229c49191556.zip |
icepatch2 changes
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/include/Ice/LoggerUtil.h | 27 | ||||
-rwxr-xr-x | cpp/include/IcePatch2/ClientUtil.h | 2 | ||||
-rw-r--r-- | cpp/include/IcePatch2/Util.h | 14 | ||||
-rw-r--r-- | cpp/slice/IcePatch2/FileServer.ice | 59 | ||||
-rw-r--r-- | cpp/src/Ice/LoggerUtil.cpp | 34 | ||||
-rw-r--r-- | cpp/src/IcePatch2/.depend | 2 | ||||
-rw-r--r-- | cpp/src/IcePatch2/Calc.cpp | 78 | ||||
-rw-r--r-- | cpp/src/IcePatch2/Client.cpp | 23 | ||||
-rwxr-xr-x | cpp/src/IcePatch2/ClientUtil.cpp | 93 | ||||
-rw-r--r-- | cpp/src/IcePatch2/FileServerI.cpp | 56 | ||||
-rw-r--r-- | cpp/src/IcePatch2/FileServerI.h | 5 | ||||
-rw-r--r-- | cpp/src/IcePatch2/Server.cpp | 59 | ||||
-rw-r--r-- | cpp/src/IcePatch2/Util.cpp | 300 |
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) |