summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/doc/Properties.sgml126
-rw-r--r--cpp/slice/Glacier/Glacier.ice42
-rw-r--r--cpp/slice/Ice/Communicator.ice2
-rw-r--r--cpp/src/Glacier/GlacierI.cpp48
-rw-r--r--cpp/src/Glacier/GlacierI.h17
-rw-r--r--cpp/src/Glacier/GlacierRouter.cpp12
-rw-r--r--cpp/src/Glacier/GlacierStarter.cpp79
-rw-r--r--cpp/src/IcePatch/Client.cpp654
-rw-r--r--cpp/src/IcePatch/FileDescFactory.cpp76
-rw-r--r--cpp/src/IcePatch/FileLocator.cpp198
-rw-r--r--cpp/src/IcePatch/IcePatchI.cpp186
-rw-r--r--cpp/src/IcePatch/Server.cpp410
-rw-r--r--cpp/src/IcePatch/Util.cpp1376
-rw-r--r--cpp/test/Glacier/starter/Client.cpp2
-rw-r--r--cpp/test/Glacier/starter/passwords1
-rwxr-xr-xcpp/test/Glacier/starter/run.py1
16 files changed, 1696 insertions, 1534 deletions
diff --git a/cpp/doc/Properties.sgml b/cpp/doc/Properties.sgml
index 3e776e2c1f7..0ed741aa086 100644
--- a/cpp/doc/Properties.sgml
+++ b/cpp/doc/Properties.sgml
@@ -975,6 +975,41 @@ Defines the endpoints of the &Glacier; router starter. (Unix only.)
</section>
</section>
+<section><title>Glacier.Starter.PasswordVerifier</title>
+<section><title>Synopsis</title>
+<synopsis>
+Glacier.Starter.PasswordVerifier=<replaceable>proxy</replaceable>
+</synopsis>
+</section>
+<section>
+<title>Description</title>
+<para>
+If set, the specified password verifier will be used. If not set, a
+built-in <literal>crypt</literal>-based password verifier will be used.
+</para>
+</section>
+</section>
+
+<section><title>Glacier.Starter.CryptPasswords</title>
+<section><title>Synopsis</title>
+<synopsis>
+Glacier.Starter.CryptPasswords=<replaceable>file</replaceable>
+</synopsis>
+</section>
+<section>
+<title>Description</title>
+<para>
+The pathname of the file that contains user-id / password pairs, with
+the passwords being encrypted by the <literal>crypt</literal>
+algorithm. The default pathname is
+"<literal>passwords</literal>". This file is only used for the
+built-in <literal>crypt</literal>-based password verifier, meaning
+that the property is ignored if
+<literal>Glacier.Starter.PasswordVerifier</literal> is set.
+</para>
+</section>
+</section>
+
<section><title>Glacier.Starter.RouterPath</title>
<section><title>Synopsis</title>
<synopsis>
@@ -1076,13 +1111,12 @@ Glacier.Starter.Certificate.Country=<replaceable>country code</replaceable>
<section>
<title>Description</title>
<para>
-This property provides a method with which to specify the country code portion of the
-Distinguished Name (DN) values that will be present in certificates generated by the
-Glacier Router Starter for client apps and the Glacier Router itself.
-</para>
-<para>
-Examples of valid values for this field are 'US' for the United States and 'CA' for
-Canada. The default value for this property, if not specified, is US.
+This property provides a method with which to specify the country code
+portion of the Distinguished Name (DN) values that will be present in
+certificates generated by the Glacier Router Starter for client apps
+and the Glacier Router itself. Examples of valid values for this field
+are "US" for the United States and "CA" for Canada. The default value
+is "US".
</para>
</section>
</section>
@@ -1096,13 +1130,12 @@ Glacier.Starter.Certificate.StateProvince=<replaceable>state/province code</repl
<section>
<title>Description</title>
<para>
-This property provides a method with which to specify the state or province code
-portion of the Distinguished Name (DN) values that will be present in certificates
-generated by the Glacier Router Starter for client apps and the Glacier Router itself.
-</para>
-<para>
-Examples of valid values for this field are 'CA' for California and 'British Columbia'
-for British Columbia, Canada. The default value for this property, if not specified, is DC.
+This property provides a method with which to specify the state or
+province code portion of the Distinguished Name (DN) values that will
+be present in certificates generated by the Glacier Router Starter for
+client apps and the Glacier Router itself. Examples of valid values
+for this field are "CA" for California and "British Columbia" for
+British Columbia, Canada. The default value is "DC".
</para>
</section>
</section>
@@ -1116,13 +1149,11 @@ Glacier.Starter.Certificate.Locality=<replaceable>city or town name</replaceable
<section>
<title>Description</title>
<para>
-This property provides a method with which to specify the locality portion of the
-Distinguished Name (DN) values that will be present in certificates generated by
-the Glacier Router Starter for client apps and the Glacier Router itself.
-</para>
-<para>
-The locality is usually the name of the city or town. The default value for this
-property, if not specified, is Washington.
+This property provides a method with which to specify the locality
+portion of the Distinguished Name (DN) values that will be present in
+certificates generated by the Glacier Router Starter for client apps
+and the Glacier Router itself. The locality is usually the name of the
+city or town. The default value is "Washington".
</para>
</section>
</section>
@@ -1136,14 +1167,12 @@ Glacier.Starter.Certificate.Organization=<replaceable>organization or company na
<section>
<title>Description</title>
<para>
-This property provides a method with which to specify the organization portion of
-the Distinguished Name (DN) values that will be present in certificates generated
-by the Glacier Router Starter for client apps and the Glacier Router itself.
-</para>
-<para>
-The organization is usually the name of the company or organization to which the
-certificate has been granted. The default value for this property, if not
-specified, is "Some Company Inc.".
+This property provides a method with which to specify the organization
+portion of the Distinguished Name (DN) values that will be present in
+certificates generated by the Glacier Router Starter for client apps
+and the Glacier Router itself. The organization is usually the name of
+the company or organization to which the certificate has been granted.
+The default value is "Some Company Inc.".
</para>
</section>
</section>
@@ -1157,15 +1186,13 @@ Glacier.Starter.Certificate.OrganizationalUnit=<replaceable>department</replacea
<section>
<title>Description</title>
<para>
-This property provides a method with which to specify the organizational unit
-portion of the Distinguished Name (DN) values that will be present in
-certificates generated by the Glacier Router Starter for client apps and the
-Glacier Router itself.
-</para>
-<para>
-The organization unit is usually the name of the department within the company
-or organization structure to which the certificate has been granted. The
-default value for this property, if not specified, is "Sales".
+This property provides a method with which to specify the
+organizational unit portion of the Distinguished Name (DN) values that
+will be present in certificates generated by the Glacier Router
+Starter for client apps and the Glacier Router itself. The
+organization unit is usually the name of the department within the
+company or organization structure to which the certificate has been
+granted. The default value is "Sales".
</para>
</section>
</section>
@@ -1181,13 +1208,11 @@ Glacier.Starter.Certificate.CommonName=<replaceable>contact name</replaceable>
<para>
This property provides a method with which to specify the common name
portion of the Distinguished Name (DN) values that will be present in
-certificates generated by the Glacier Router Starter for client apps and the
-Glacier Router itself.
-</para>
-<para>
-The common name is usually the name of the contact (a person's name) within
-the company and department to which the certificate has been granted. The
-default value for this property, if not specified, is "John Doe".
+certificates generated by the Glacier Router Starter for client apps
+and the Glacier Router itself. The common name is usually the name of
+the contact (a person's name) within the company and department to
+which the certificate has been granted. The default value is "John
+Doe".
</para>
</section>
</section>
@@ -1211,10 +1236,7 @@ Although modulus size is determined by the needs of the particular application,
care should be taken not to specify a size that is too large, as certificate
generation is an expensive operation. Sizes less than 512 bits are not
supported, and sizes that exceed 2048 bits should be chosen with generation
-times in mind.
-</para>
-<para>
-If not specified, the default value of this property is 1024 bits.
+times in mind. The default value is 1024 bits.
</para>
</section>
</section>
@@ -1230,11 +1252,7 @@ Glacier.Starter.Certificate.SecondsValid=<replaceable>seconds</replaceable>
<para>
This property provides a method with which to specify the number of seconds
that certificates generated by the Glacier Router Starter are valid before
-they will expire.
-</para>
-<para>
-If this value is not specified, the default value of 1 day (86,400 seconds)
-will be used.
+they will expire. The default value of 1 day (86,400 seconds).
</para>
</section>
</section>
diff --git a/cpp/slice/Glacier/Glacier.ice b/cpp/slice/Glacier/Glacier.ice
index 7174194e3fc..5f997f1bc32 100644
--- a/cpp/slice/Glacier/Glacier.ice
+++ b/cpp/slice/Glacier/Glacier.ice
@@ -16,7 +16,7 @@
/**
*
- * &Glacier; is the Ice firewall and router.
+ * &Glacier; is the &Ice; firewall and router.
*
**/
module Glacier
@@ -56,9 +56,14 @@ interface Starter
* router is returned to the caller.
*
* @param userId The user id for which to check the password.
+ *
* @param password The password for the given user id.
- * @param privateKey The RSA Private Key (DER encoded) for the client to use.
- * @param publicKey The RSA Public Key (DER encoded) for the client to use.
+ *
+ * @param privateKey The RSA Private Key (DER encoded) for the
+ * client to use. (Only for SSL.)
+ *
+ * @param publicKey The RSA Public Key (DER encoded) for the
+ * client to use. (Only for SSL.)
*
* @return A proxy to the router that has been started.
*
@@ -71,6 +76,37 @@ interface Starter
throws InvalidPasswordException, CannotStartRouterException;
};
+/**
+ *
+ * The &Glacier; router starter password verifier.
+ *
+ **/
+interface PasswordVerifier
+{
+ /**
+ *
+ * Check whether a password is valid.
+ *
+ * @param userId The user id for which to check the password.
+ *
+ * @param password The password to check.
+ *
+ * @return True if the password is valid, or false otherwise.
+ *
+ **/
+ ["nonmutating"]
+ bool checkPassword(string userId, string password);
+
+ /**
+ *
+ * Called when the password verifier is not needed anymore by the
+ * &Glacier; router starter.
+ *
+ **/
+ ["nonmutating"]
+ void destroy();
+};
+
};
#endif
diff --git a/cpp/slice/Ice/Communicator.ice b/cpp/slice/Ice/Communicator.ice
index 9a707d18284..2d86f4514cf 100644
--- a/cpp/slice/Ice/Communicator.ice
+++ b/cpp/slice/Ice/Communicator.ice
@@ -103,7 +103,7 @@ local interface Communicator
/**
*
* Convert a string into a Proxy. For example,
- * [MyCategory#MyObject:tcp -h some_host -p 10000] creates a proxy
+ * [MyCategory/MyObject:tcp -h some_host -p 10000] creates a proxy
* that refers to the Ice Object having an identity with a name
* "MyObject" and a category "MyCategory", with the server running
* on host "some_host", port 10000.
diff --git a/cpp/src/Glacier/GlacierI.cpp b/cpp/src/Glacier/GlacierI.cpp
index b7f6984f5e9..0c349062f9d 100644
--- a/cpp/src/Glacier/GlacierI.cpp
+++ b/cpp/src/Glacier/GlacierI.cpp
@@ -16,6 +16,7 @@
#include <Ice/RSAKeyPair.h>
#include <Glacier/GlacierI.h>
#include <fcntl.h>
+#include <shadow.h>
using namespace std;
using namespace Ice;
@@ -23,11 +24,14 @@ using namespace Glacier;
using IceSSL::OpenSSL::RSAKeyPairPtr;
-Glacier::StarterI::StarterI(const CommunicatorPtr& communicator) :
+Glacier::StarterI::StarterI(const CommunicatorPtr& communicator, const PasswordVerifierPrx& verifier) :
_communicator(communicator),
_logger(_communicator->getLogger()),
- _properties(_communicator->getProperties())
+ _properties(_communicator->getProperties()),
+ _verifier(verifier)
{
+ assert(_verifier);
+
_traceLevel = atoi(_properties->getProperty("Glacier.Trace.Starter").c_str());
// Set up the Certificate Generation context
@@ -71,9 +75,10 @@ Glacier::StarterI::startRouter(const string& userId, const string& password, Byt
{
assert(_communicator); // Destroyed?
- //
- // TODO: userId/password check.
- //
+ if (!_verifier->checkPassword(userId, password))
+ {
+ throw InvalidPasswordException();
+ }
//
// Create a certificate for the client and the router.
@@ -371,3 +376,36 @@ Glacier::StarterI::startRouter(const string& userId, const string& password, Byt
assert(false); // Should never be reached.
return 0; // To keep the compiler from complaining.
}
+
+Glacier::CryptPasswordVerifierI::CryptPasswordVerifierI(const map<string, string>& passwords) :
+ _passwords(passwords)
+{
+}
+
+bool
+Glacier::CryptPasswordVerifierI::checkPassword(const string& userId, const string& password, const Current&)
+{
+ map<string, string>::const_iterator p = _passwords.find(userId);
+
+ if (p == _passwords.end())
+ {
+ return false;
+ }
+
+ if (p->second.size() != 13) // Crypt passwords are 13 characters long.
+ {
+ return false;
+ }
+
+ {
+ IceUtil::Lock<IceUtil::Mutex> sync(*this); // Need a lock as crypt() is not reentrant.
+
+ return p->second == crypt(password.c_str(), p->second.substr(0, 2).c_str());
+ }
+}
+
+void
+Glacier::CryptPasswordVerifierI::destroy(const Current&)
+{
+ // Nothing to do.
+}
diff --git a/cpp/src/Glacier/GlacierI.h b/cpp/src/Glacier/GlacierI.h
index b3407de39c9..2343e0b146d 100644
--- a/cpp/src/Glacier/GlacierI.h
+++ b/cpp/src/Glacier/GlacierI.h
@@ -25,7 +25,7 @@ class StarterI : public Starter
{
public:
- StarterI(const Ice::CommunicatorPtr&);
+ StarterI(const Ice::CommunicatorPtr&, const PasswordVerifierPrx&);
void destroy();
@@ -41,11 +41,26 @@ private:
Ice::CommunicatorPtr _communicator;
Ice::LoggerPtr _logger;
Ice::PropertiesPtr _properties;
+ PasswordVerifierPrx _verifier;
int _traceLevel;
RSACertificateGenContext _certContext;
RSACertificateGen _certificateGenerator;
};
+class CryptPasswordVerifierI : public PasswordVerifier, public IceUtil::Mutex
+{
+public:
+
+ CryptPasswordVerifierI(const std::map<std::string, std::string>&);
+
+ virtual bool checkPassword(const std::string&, const std::string&, const Ice::Current&);
+ virtual void destroy(const Ice::Current&);
+
+private:
+
+ const std::map<std::string, std::string> _passwords;
+};
+
}
#endif
diff --git a/cpp/src/Glacier/GlacierRouter.cpp b/cpp/src/Glacier/GlacierRouter.cpp
index 142c9ab8cda..3d392fe2bbe 100644
--- a/cpp/src/Glacier/GlacierRouter.cpp
+++ b/cpp/src/Glacier/GlacierRouter.cpp
@@ -152,12 +152,12 @@ Glacier::Router::run(int argc, char* argv[])
}
//
- // Create routing table
+ // Create the routing table.
//
IceInternal::RoutingTablePtr routingTable = new IceInternal::RoutingTable;
//
- // Initialize Client Object Adapter
+ // Initialize the client object adapter.
//
const char* clientEndpointsProperty = "Glacier.Client.Endpoints";
string clientEndpoints = properties->getProperty(clientEndpointsProperty);
@@ -166,13 +166,12 @@ Glacier::Router::run(int argc, char* argv[])
cerr << appName() << ": property `" << clientEndpointsProperty << "' is not set" << endl;
return EXIT_FAILURE;
}
-
ObjectAdapterPtr clientAdapter = communicator()->createObjectAdapterFromProperty("Client",
clientEndpointsProperty);
clientAdapter->activate();
//
- // Initialize Server Object Adapter
+ // Initialize the server object adapter.
//
const char* serverEndpointsProperty = "Glacier.Server.Endpoints";
string serverEndpoints = properties->getProperty(serverEndpointsProperty);
@@ -190,7 +189,6 @@ Glacier::Router::run(int argc, char* argv[])
ObjectPtr clientBlobject = new ClientBlobject(communicator(), routingTable);
Ice::ServantLocatorPtr clientServantLocator = new Glacier::ServantLocator(clientBlobject);
clientAdapter->addServantLocator(clientServantLocator, "");
-
if (serverAdapter)
{
ObjectPtr serverBlobject = new ServerBlobject(clientAdapter);
@@ -199,7 +197,7 @@ Glacier::Router::run(int argc, char* argv[])
}
//
- // Initialize Router
+ // Initialize the router object adapter and the router object.
//
const char* routerEndpointsProperty = "Glacier.Router.Endpoints";
string routerEndpoints = properties->getProperty(routerEndpointsProperty);
@@ -208,14 +206,12 @@ Glacier::Router::run(int argc, char* argv[])
cerr << appName() << ": property `" << routerEndpointsProperty << "' is not set" << endl;
return EXIT_FAILURE;
}
-
const char* routerIdentityProperty = "Glacier.Router.Identity";
string routerIdentity = properties->getProperty(routerIdentityProperty);
if (routerIdentity.empty())
{
routerIdentity = "Glacier/router";
}
-
ObjectAdapterPtr routerAdapter =
communicator()->createObjectAdapterFromProperty("Router", routerEndpointsProperty);
RouterPtr router = new RouterI(clientAdapter, serverAdapter, routingTable);
diff --git a/cpp/src/Glacier/GlacierStarter.cpp b/cpp/src/Glacier/GlacierStarter.cpp
index 1e8c3002079..bedaa8192d7 100644
--- a/cpp/src/Glacier/GlacierStarter.cpp
+++ b/cpp/src/Glacier/GlacierStarter.cpp
@@ -16,6 +16,7 @@
#include <Glacier/GlacierI.h>
#include <signal.h>
#include <sys/wait.h>
+#include <fstream>
using namespace std;
using namespace Ice;
@@ -70,21 +71,76 @@ Glacier::Router::run(int argc, char* argv[])
PropertiesPtr properties = communicator()->getProperties();
//
- // Initialize Starter Object Adapter
+ // Initialize the object adapter.
//
- const char* starterEndpointsProperty = "Glacier.Starter.Endpoints";
- string starterEndpoints = properties->getProperty(starterEndpointsProperty);
- if (starterEndpoints.empty())
+ const char* endpointsProperty = "Glacier.Starter.Endpoints";
+ string endpoints = properties->getProperty(endpointsProperty);
+ if (endpoints.empty())
{
- cerr << appName() << ": property `" << starterEndpointsProperty << "' is not set" << endl;
+ cerr << appName() << ": property `" << endpointsProperty << "' is not set" << endl;
return EXIT_FAILURE;
}
+ ObjectAdapterPtr adapter = communicator()->createObjectAdapterFromProperty("Starter", endpointsProperty);
- ObjectAdapterPtr starterAdapter = communicator()->createObjectAdapterFromProperty("Starter",
- starterEndpointsProperty);
- StarterPtr starter = new StarterI(communicator());
- starterAdapter->add(starter, stringToIdentity("Glacier/starter"));
- starterAdapter->activate();
+ //
+ // Get the password verifier, or create one if no verifier is
+ // specified.
+ //
+ string verifierProperty = properties->getProperty("Glacier.Starter.PasswordVerifier");
+ PasswordVerifierPrx verifier;
+ if (!verifierProperty.empty())
+ {
+ verifier = PasswordVerifierPrx::checkedCast(communicator()->stringToProxy(verifierProperty));
+ if (!verifier)
+ {
+ cerr << appName() << ": password verifier `" << verifierProperty << "' is invalid" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+ else
+ {
+ string passwordsProperty = properties->getPropertyWithDefault("Glacier.Starter.CryptPasswords", "passwords");
+
+ ifstream passwordFile(passwordsProperty.c_str());
+ if (!passwordFile)
+ {
+ cerr << appName() << ": cannot open `" << passwordsProperty << "' for reading: " << strerror(errno)
+ << endl;
+ return EXIT_FAILURE;
+ }
+
+ map<string, string> passwords;
+
+ while(true)
+ {
+ string userId;
+ passwordFile >> userId;
+ if (!passwordFile)
+ {
+ break;
+ }
+
+ string password;
+ passwordFile >> password;
+ if (!passwordFile)
+ {
+ break;
+ }
+
+ assert(!userId.empty());
+ assert(!password.empty());
+ passwords.insert(make_pair(userId, password));
+ }
+
+ verifier = PasswordVerifierPrx::uncheckedCast(adapter->addWithUUID(new CryptPasswordVerifierI(passwords)));
+ }
+
+ //
+ // Create the starter object and activate the object adapter.
+ //
+ StarterPtr starter = new StarterI(communicator(), verifier);
+ adapter->add(starter, stringToIdentity("Glacier/starter"));
+ adapter->activate();
//
// We're done, let's wait for shutdown.
@@ -92,11 +148,12 @@ Glacier::Router::run(int argc, char* argv[])
communicator()->waitForShutdown();
//
- // Destroy the starter.
+ // Destroy the starter and the password verifier.
//
StarterI* st = dynamic_cast<StarterI*>(starter.get());
assert(st);
st->destroy();
+ verifier->destroy();
return EXIT_SUCCESS;
}
diff --git a/cpp/src/IcePatch/Client.cpp b/cpp/src/IcePatch/Client.cpp
index 5161e887151..f5ea8c0602c 100644
--- a/cpp/src/IcePatch/Client.cpp
+++ b/cpp/src/IcePatch/Client.cpp
@@ -1,327 +1,327 @@
-// **********************************************************************
-//
-// Copyright (c) 2002
-// MutableRealms, Inc.
-// Huntsville, AL, USA
-//
-// All Rights Reserved
-//
-// **********************************************************************
-
-#include <Ice/Application.h>
-#include <IcePatch/FileDescFactory.h>
-#include <IcePatch/Util.h>
-#include <iomanip>
-
-using namespace std;
-using namespace Ice;
-using namespace IcePatch;
-
-namespace IcePatch
-{
-
-class Client : public Application
-{
-public:
-
- void usage();
- virtual int run(int, char*[]);
-
- static string pathToName(const string&);
- static void patch(const FileDescSeq&, const string&);
-};
-
-};
-
-void
-IcePatch::Client::usage()
-{
- cerr << "Usage: " << appName() << " [options]\n";
- cerr <<
- "Options:\n"
- "-h, --help Show this message.\n"
- "-v, --version Display the Ice version.\n"
- ;
-}
-
-int
-IcePatch::Client::run(int argc, char* argv[])
-{
- try
- {
- for (int i = 1; i < argc; ++i)
- {
- if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
- {
- usage();
- return EXIT_SUCCESS;
- }
- else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0)
- {
- cout << ICE_STRING_VERSION << endl;
- return EXIT_SUCCESS;
- }
- else
- {
- cerr << appName() << ": unknown option `" << argv[i] << "'" << endl;
- usage();
- return EXIT_FAILURE;
- }
- }
-
- PropertiesPtr properties = communicator()->getProperties();
-
- //
- // Get the IcePatch endpoints.
- //
- const char* endpointsProperty = "IcePatch.Endpoints";
- string endpoints = properties->getProperty(endpointsProperty);
- if (endpoints.empty())
- {
- cerr << appName() << ": property `" << endpointsProperty << "' is not set" << endl;
- return EXIT_FAILURE;
- }
-
- //
- // Get the working directory and change to this directory.
- //
- const char* directoryProperty = "IcePatch.Directory";
- string directory = properties->getProperty(directoryProperty);
- if (!directory.empty())
- {
- changeDirectory(directory);
- }
-
- //
- // Create and install the node description factory.
- //
- ObjectFactoryPtr factory = new FileDescFactory;
- communicator()->addObjectFactory(factory, "::IcePatch::DirectoryDesc");
- communicator()->addObjectFactory(factory, "::IcePatch::RegularDesc");
-
- //
- // Patch all files.
- //
- Identity identity = pathToIdentity(".");
- ObjectPrx topObj = communicator()->stringToProxy(identityToString(identity) + ':' + endpoints);
- FilePrx top = FilePrx::checkedCast(topObj);
- assert(top);
- DirectoryDescPtr topDesc = DirectoryDescPtr::dynamicCast(top->describe());
- assert(topDesc);
- string path = identityToPath(topDesc->directory->ice_getIdentity());
- cout << pathToName(path) << endl;
- cout << "|" << endl;
- patch(topDesc->directory->getContents(), "");
- }
- catch (const FileAccessException& ex)
- {
- cerr << appName() << ": " << ex << ":\n" << ex.reason << endl;
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
-
-string
-IcePatch::Client::pathToName(const string& path)
-{
- string::size_type pos = path.rfind('/');
- if (pos == string::npos)
- {
- return path;
- }
- else
- {
- return path.substr(pos + 1);
- }
-}
-
-class MyProgressCB : public ProgressCB
-{
-public:
-
- virtual void startDownload(Int)
- {
- cout << "download 0% " << flush;
- }
-
- virtual void updateDownload(Int total, Int pos)
- {
- Ice::Int percent = pos * 100 / total;
- cout << "\b\b\b\b\b" << setw(3) << percent << "% " << flush;
- }
-
- virtual void finishedDownload(Int total)
- {
- cout << "\b\b\b\b\b" << "100% " << flush;
- }
-
- virtual void startUncompress(Int)
- {
- cout << "uncompress 0% " << flush;
- }
-
- virtual void updateUncompress(Int total, Int pos)
- {
- updateDownload(total, pos);
- }
-
- virtual void finishedUncompress(Int total)
- {
- finishedDownload(total);
- }
-};
-
-void
-IcePatch::Client::patch(const FileDescSeq& fileDescSeq, const string& indent)
-{
- if (fileDescSeq.empty())
- {
- return;
- }
-
- for (unsigned int i = 0; i < fileDescSeq.size(); ++i)
- {
- string path;
- DirectoryDescPtr directoryDesc = DirectoryDescPtr::dynamicCast(fileDescSeq[i]);
- RegularDescPtr regularDesc;
- if (directoryDesc)
- {
- path = identityToPath(directoryDesc->directory->ice_getIdentity());
- }
- else
- {
- regularDesc = RegularDescPtr::dynamicCast(fileDescSeq[i]);
- assert(regularDesc);
- path = identityToPath(regularDesc->regular->ice_getIdentity());
- }
-
- bool last = (i == fileDescSeq.size() - 1);
-
- if (directoryDesc)
- {
- string newIndent;
- if (last)
- {
- newIndent = indent + " ";
- }
- else
- {
- newIndent = indent + "| ";
- }
- cout << indent << "+-" << pathToName(path) << ": " << flush;
-
- FileInfo info = getFileInfo(path, false);
- switch (info.type)
- {
- case FileTypeNotExist:
- {
- cout << "creating directory... " << flush;
- createDirectory(path);
- break;
- }
-
- case FileTypeDirectory:
- {
- break;
- }
-
- case FileTypeRegular:
- {
- cout << "removing file... " << flush;
- removeRecursive(path);
- cout << "creating directory... " << flush;
- createDirectory(path);
- break;
- }
-
- case FileTypeUnknown:
- {
- cout << "removing unknown file... " << flush;
- removeRecursive(path);
- cout << "creating directory... " << flush;
- createDirectory(path);
- break;
- }
- }
-
- cout << "ok" << endl;
-
- cout << newIndent << "|" << endl;
- patch(directoryDesc->directory->getContents(), newIndent);
- }
- else
- {
- assert(regularDesc);
- cout << indent << "+-" << pathToName(path) << ": " << flush;
-
- MyProgressCB progressCB;
-
- FileInfo info = getFileInfo(path, false);
- switch (info.type)
- {
- case FileTypeNotExist:
- {
- cout << "getting file... " << flush;
- getRegular(regularDesc->regular, progressCB);
- break;
- }
-
- case FileTypeDirectory:
- {
- cout << "removing directory... " << flush;
- removeRecursive(path);
- cout << "getting file... " << flush;
- getRegular(regularDesc->regular, progressCB);
- break;
- }
-
- case FileTypeRegular:
- {
- ByteSeq md5;
-
- string pathMD5 = path + ".md5";
- FileInfo infoMD5 = getFileInfo(pathMD5, false);
- if (infoMD5.type == FileTypeRegular && infoMD5.time >= info.time)
- {
- md5 = getMD5(path);
- }
-
- if (md5 != regularDesc->md5)
- {
- cout << "removing file... " << flush;
- removeRecursive(path);
- cout << "getting file... " << flush;
- getRegular(regularDesc->regular, progressCB);
- }
-
- break;
- }
-
- case FileTypeUnknown:
- {
- cout << "removing unknown file... " << flush;
- removeRecursive(path);
- cout << "getting file... " << flush;
- getRegular(regularDesc->regular, progressCB);
- break;
- }
- }
-
- cout << "ok" << endl;
-
- if (last)
- {
- cout << indent << endl;
- }
- }
- }
-}
-
-int
-main(int argc, char* argv[])
-{
- addArgumentPrefix("IcePatch");
- Client app;
- return app.main(argc, argv);
-}
+// **********************************************************************
+//
+// Copyright (c) 2002
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <Ice/Application.h>
+#include <IcePatch/FileDescFactory.h>
+#include <IcePatch/Util.h>
+#include <iomanip>
+
+using namespace std;
+using namespace Ice;
+using namespace IcePatch;
+
+namespace IcePatch
+{
+
+class Client : public Application
+{
+public:
+
+ void usage();
+ virtual int run(int, char*[]);
+
+ static string pathToName(const string&);
+ static void patch(const FileDescSeq&, const string&);
+};
+
+};
+
+void
+IcePatch::Client::usage()
+{
+ cerr << "Usage: " << appName() << " [options]\n";
+ cerr <<
+ "Options:\n"
+ "-h, --help Show this message.\n"
+ "-v, --version Display the Ice version.\n"
+ ;
+}
+
+int
+IcePatch::Client::run(int argc, char* argv[])
+{
+ try
+ {
+ for (int i = 1; i < argc; ++i)
+ {
+ if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
+ {
+ usage();
+ return EXIT_SUCCESS;
+ }
+ else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0)
+ {
+ cout << ICE_STRING_VERSION << endl;
+ return EXIT_SUCCESS;
+ }
+ else
+ {
+ cerr << appName() << ": unknown option `" << argv[i] << "'" << endl;
+ usage();
+ return EXIT_FAILURE;
+ }
+ }
+
+ PropertiesPtr properties = communicator()->getProperties();
+
+ //
+ // Get the IcePatch endpoints.
+ //
+ const char* endpointsProperty = "IcePatch.Endpoints";
+ string endpoints = properties->getProperty(endpointsProperty);
+ if (endpoints.empty())
+ {
+ cerr << appName() << ": property `" << endpointsProperty << "' is not set" << endl;
+ return EXIT_FAILURE;
+ }
+
+ //
+ // Get the working directory and change to this directory.
+ //
+ const char* directoryProperty = "IcePatch.Directory";
+ string directory = properties->getProperty(directoryProperty);
+ if (!directory.empty())
+ {
+ changeDirectory(directory);
+ }
+
+ //
+ // Create and install the node description factory.
+ //
+ ObjectFactoryPtr factory = new FileDescFactory;
+ communicator()->addObjectFactory(factory, "::IcePatch::DirectoryDesc");
+ communicator()->addObjectFactory(factory, "::IcePatch::RegularDesc");
+
+ //
+ // Patch all files.
+ //
+ Identity identity = pathToIdentity(".");
+ ObjectPrx topObj = communicator()->stringToProxy(identityToString(identity) + ':' + endpoints);
+ FilePrx top = FilePrx::checkedCast(topObj);
+ assert(top);
+ DirectoryDescPtr topDesc = DirectoryDescPtr::dynamicCast(top->describe());
+ assert(topDesc);
+ string path = identityToPath(topDesc->directory->ice_getIdentity());
+ cout << pathToName(path) << endl;
+ cout << "|" << endl;
+ patch(topDesc->directory->getContents(), "");
+ }
+ catch (const FileAccessException& ex)
+ {
+ cerr << appName() << ": " << ex << ":\n" << ex.reason << endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+string
+IcePatch::Client::pathToName(const string& path)
+{
+ string::size_type pos = path.rfind('/');
+ if (pos == string::npos)
+ {
+ return path;
+ }
+ else
+ {
+ return path.substr(pos + 1);
+ }
+}
+
+class MyProgressCB : public ProgressCB
+{
+public:
+
+ virtual void startDownload(Int)
+ {
+ cout << "download 0% " << flush;
+ }
+
+ virtual void updateDownload(Int total, Int pos)
+ {
+ Ice::Int percent = pos * 100 / total;
+ cout << "\b\b\b\b\b" << setw(3) << percent << "% " << flush;
+ }
+
+ virtual void finishedDownload(Int total)
+ {
+ cout << "\b\b\b\b\b" << "100% " << flush;
+ }
+
+ virtual void startUncompress(Int)
+ {
+ cout << "uncompress 0% " << flush;
+ }
+
+ virtual void updateUncompress(Int total, Int pos)
+ {
+ updateDownload(total, pos);
+ }
+
+ virtual void finishedUncompress(Int total)
+ {
+ finishedDownload(total);
+ }
+};
+
+void
+IcePatch::Client::patch(const FileDescSeq& fileDescSeq, const string& indent)
+{
+ if (fileDescSeq.empty())
+ {
+ return;
+ }
+
+ for (unsigned int i = 0; i < fileDescSeq.size(); ++i)
+ {
+ string path;
+ DirectoryDescPtr directoryDesc = DirectoryDescPtr::dynamicCast(fileDescSeq[i]);
+ RegularDescPtr regularDesc;
+ if (directoryDesc)
+ {
+ path = identityToPath(directoryDesc->directory->ice_getIdentity());
+ }
+ else
+ {
+ regularDesc = RegularDescPtr::dynamicCast(fileDescSeq[i]);
+ assert(regularDesc);
+ path = identityToPath(regularDesc->regular->ice_getIdentity());
+ }
+
+ bool last = (i == fileDescSeq.size() - 1);
+
+ if (directoryDesc)
+ {
+ string newIndent;
+ if (last)
+ {
+ newIndent = indent + " ";
+ }
+ else
+ {
+ newIndent = indent + "| ";
+ }
+ cout << indent << "+-" << pathToName(path) << ": " << flush;
+
+ FileInfo info = getFileInfo(path, false);
+ switch (info.type)
+ {
+ case FileTypeNotExist:
+ {
+ cout << "creating directory... " << flush;
+ createDirectory(path);
+ break;
+ }
+
+ case FileTypeDirectory:
+ {
+ break;
+ }
+
+ case FileTypeRegular:
+ {
+ cout << "removing file... " << flush;
+ removeRecursive(path);
+ cout << "creating directory... " << flush;
+ createDirectory(path);
+ break;
+ }
+
+ case FileTypeUnknown:
+ {
+ cout << "removing unknown file... " << flush;
+ removeRecursive(path);
+ cout << "creating directory... " << flush;
+ createDirectory(path);
+ break;
+ }
+ }
+
+ cout << "ok" << endl;
+
+ cout << newIndent << "|" << endl;
+ patch(directoryDesc->directory->getContents(), newIndent);
+ }
+ else
+ {
+ assert(regularDesc);
+ cout << indent << "+-" << pathToName(path) << ": " << flush;
+
+ MyProgressCB progressCB;
+
+ FileInfo info = getFileInfo(path, false);
+ switch (info.type)
+ {
+ case FileTypeNotExist:
+ {
+ cout << "getting file... " << flush;
+ getRegular(regularDesc->regular, progressCB);
+ break;
+ }
+
+ case FileTypeDirectory:
+ {
+ cout << "removing directory... " << flush;
+ removeRecursive(path);
+ cout << "getting file... " << flush;
+ getRegular(regularDesc->regular, progressCB);
+ break;
+ }
+
+ case FileTypeRegular:
+ {
+ ByteSeq md5;
+
+ string pathMD5 = path + ".md5";
+ FileInfo infoMD5 = getFileInfo(pathMD5, false);
+ if (infoMD5.type == FileTypeRegular && infoMD5.time >= info.time)
+ {
+ md5 = getMD5(path);
+ }
+
+ if (md5 != regularDesc->md5)
+ {
+ cout << "removing file... " << flush;
+ removeRecursive(path);
+ cout << "getting file... " << flush;
+ getRegular(regularDesc->regular, progressCB);
+ }
+
+ break;
+ }
+
+ case FileTypeUnknown:
+ {
+ cout << "removing unknown file... " << flush;
+ removeRecursive(path);
+ cout << "getting file... " << flush;
+ getRegular(regularDesc->regular, progressCB);
+ break;
+ }
+ }
+
+ cout << "ok" << endl;
+
+ if (last)
+ {
+ cout << indent << endl;
+ }
+ }
+ }
+}
+
+int
+main(int argc, char* argv[])
+{
+ addArgumentPrefix("IcePatch");
+ Client app;
+ return app.main(argc, argv);
+}
diff --git a/cpp/src/IcePatch/FileDescFactory.cpp b/cpp/src/IcePatch/FileDescFactory.cpp
index 4b7c9fc442e..76044fd700d 100644
--- a/cpp/src/IcePatch/FileDescFactory.cpp
+++ b/cpp/src/IcePatch/FileDescFactory.cpp
@@ -1,38 +1,38 @@
-// **********************************************************************
-//
-// Copyright (c) 2002
-// MutableRealms, Inc.
-// Huntsville, AL, USA
-//
-// All Rights Reserved
-//
-// **********************************************************************
-
-#include <IcePatch/FileDescFactory.h>
-
-using namespace std;
-using namespace Ice;
-using namespace IcePatch;
-
-ObjectPtr
-IcePatch::FileDescFactory::create(const std::string& type)
-{
- if (type == "::IcePatch::DirectoryDesc")
- {
- return new DirectoryDesc;
- }
-
- if (type == "::IcePatch::RegularDesc")
- {
- return new RegularDesc;
- }
-
- assert(false);
- return 0; // To keep the compiler from complaining.
-}
-
-void
-IcePatch::FileDescFactory::destroy()
-{
- // Nothing to do.
-}
+// **********************************************************************
+//
+// Copyright (c) 2002
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <IcePatch/FileDescFactory.h>
+
+using namespace std;
+using namespace Ice;
+using namespace IcePatch;
+
+ObjectPtr
+IcePatch::FileDescFactory::create(const std::string& type)
+{
+ if (type == "::IcePatch::DirectoryDesc")
+ {
+ return new DirectoryDesc;
+ }
+
+ if (type == "::IcePatch::RegularDesc")
+ {
+ return new RegularDesc;
+ }
+
+ assert(false);
+ return 0; // To keep the compiler from complaining.
+}
+
+void
+IcePatch::FileDescFactory::destroy()
+{
+ // Nothing to do.
+}
diff --git a/cpp/src/IcePatch/FileLocator.cpp b/cpp/src/IcePatch/FileLocator.cpp
index 182db254f85..cdd001cd84d 100644
--- a/cpp/src/IcePatch/FileLocator.cpp
+++ b/cpp/src/IcePatch/FileLocator.cpp
@@ -1,99 +1,99 @@
-// **********************************************************************
-//
-// Copyright (c) 2002
-// MutableRealms, Inc.
-// Huntsville, AL, USA
-//
-// All Rights Reserved
-//
-// **********************************************************************
-
-#include <IcePatch/FileLocator.h>
-#include <IcePatch/Util.h>
-#include <IcePatch/IcePatchI.h>
-
-using namespace std;
-using namespace Ice;
-using namespace IcePatch;
-
-IcePatch::FileLocator::FileLocator(const Ice::ObjectAdapterPtr& adapter) :
- _directory(new DirectoryI(adapter)),
- _regular(new RegularI(adapter))
-{
-}
-
-ObjectPtr
-IcePatch::FileLocator::locate(const ObjectAdapterPtr& adapter, const Current& current, LocalObjectPtr&)
-{
- //
- // Check whether the path is valid.
- //
- string path = identityToPath(current.identity);
-
- if (path.empty())
- {
- return 0;
- }
-
- if (path[0] == '/') // Path must not start with '/'.
- {
- return 0;
- }
-
- if (path.find("..") != string::npos) // Path must not contain '..'.
- {
- return 0;
- }
-
- if (path.find(':') == 1) // Path cannot contain ':' as second character.
- {
- return 0;
- }
-
- FileInfo info;
- try
- {
- info = getFileInfo(path, true);
- }
- catch (const FileAccessException& ex)
- {
- Warning out(adapter->getCommunicator()->getLogger());
- out << ex << ":\n" << ex.reason;
- return 0;
- }
-
- switch (info.type)
- {
- case FileTypeDirectory:
- {
- return _directory;
- }
-
- case FileTypeRegular:
- {
- return _regular;
- }
-
- default:
- {
- return 0;
- }
- }
-}
-
-void
-IcePatch::FileLocator::finished(const ObjectAdapterPtr&, const Current& current, const ObjectPtr&,
- const LocalObjectPtr&)
-{
- // Nothing to do.
-}
-
-void
-IcePatch::FileLocator::deactivate()
-{
- //
- // Break cyclic dependencies.
- //
- _directory = 0;
- _regular = 0;
-}
+// **********************************************************************
+//
+// Copyright (c) 2002
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <IcePatch/FileLocator.h>
+#include <IcePatch/Util.h>
+#include <IcePatch/IcePatchI.h>
+
+using namespace std;
+using namespace Ice;
+using namespace IcePatch;
+
+IcePatch::FileLocator::FileLocator(const Ice::ObjectAdapterPtr& adapter) :
+ _directory(new DirectoryI(adapter)),
+ _regular(new RegularI(adapter))
+{
+}
+
+ObjectPtr
+IcePatch::FileLocator::locate(const ObjectAdapterPtr& adapter, const Current& current, LocalObjectPtr&)
+{
+ //
+ // Check whether the path is valid.
+ //
+ string path = identityToPath(current.identity);
+
+ if (path.empty())
+ {
+ return 0;
+ }
+
+ if (path[0] == '/') // Path must not start with '/'.
+ {
+ return 0;
+ }
+
+ if (path.find("..") != string::npos) // Path must not contain '..'.
+ {
+ return 0;
+ }
+
+ if (path.find(':') == 1) // Path cannot contain ':' as second character.
+ {
+ return 0;
+ }
+
+ FileInfo info;
+ try
+ {
+ info = getFileInfo(path, true);
+ }
+ catch (const FileAccessException& ex)
+ {
+ Warning out(adapter->getCommunicator()->getLogger());
+ out << ex << ":\n" << ex.reason;
+ return 0;
+ }
+
+ switch (info.type)
+ {
+ case FileTypeDirectory:
+ {
+ return _directory;
+ }
+
+ case FileTypeRegular:
+ {
+ return _regular;
+ }
+
+ default:
+ {
+ return 0;
+ }
+ }
+}
+
+void
+IcePatch::FileLocator::finished(const ObjectAdapterPtr&, const Current& current, const ObjectPtr&,
+ const LocalObjectPtr&)
+{
+ // Nothing to do.
+}
+
+void
+IcePatch::FileLocator::deactivate()
+{
+ //
+ // Break cyclic dependencies.
+ //
+ _directory = 0;
+ _regular = 0;
+}
diff --git a/cpp/src/IcePatch/IcePatchI.cpp b/cpp/src/IcePatch/IcePatchI.cpp
index 8e836f5df9b..54f33440c71 100644
--- a/cpp/src/IcePatch/IcePatchI.cpp
+++ b/cpp/src/IcePatch/IcePatchI.cpp
@@ -1,93 +1,93 @@
-// **********************************************************************
-//
-// Copyright (c) 2002
-// MutableRealms, Inc.
-// Huntsville, AL, USA
-//
-// All Rights Reserved
-//
-// **********************************************************************
-
-#include <IcePatch/IcePatchI.h>
-#include <IcePatch/Util.h>
-
-using namespace std;
-using namespace Ice;
-using namespace IcePatch;
-
-IcePatch::FileI::FileI(const ObjectAdapterPtr& adapter) :
- _adapter(adapter)
-{
-}
-
-IcePatch::DirectoryI::DirectoryI(const ObjectAdapterPtr& adapter) :
- FileI(adapter)
-{
-}
-
-FileDescPtr
-IcePatch::DirectoryI::describe(const Ice::Current& current)
-{
- DirectoryDescPtr desc = new DirectoryDesc;
- desc->directory = DirectoryPrx::uncheckedCast(_adapter->createProxy(current.identity));
- return desc;
-}
-
-FileDescSeq
-IcePatch::DirectoryI::getContents(const Ice::Current& current)
-{
- StringSeq paths = readDirectory(identityToPath(current.identity));
-
- FileDescSeq result;
- result.reserve(paths.size());
-
- StringSeq::const_iterator p;
- for (p = paths.begin(); p != paths.end(); ++p)
- {
- if (ignoreSuffix(*p))
- {
- continue;
- }
-
- FilePrx file = FilePrx::uncheckedCast(_adapter->createProxy(pathToIdentity(*p)));
- try
- {
- result.push_back(file->describe());
- }
- catch (const ObjectNotExistException&)
- {
- //
- // Ignore. This can for example happen if the file
- // locator cannot call stat() on the file.
- //
- }
- }
-
- return result;
-}
-
-IcePatch::RegularI::RegularI(const ObjectAdapterPtr& adapter) :
- FileI(adapter)
-{
-}
-
-FileDescPtr
-IcePatch::RegularI::describe(const Ice::Current& current)
-{
- RegularDescPtr desc = new RegularDesc;
- desc->regular = RegularPrx::uncheckedCast(_adapter->createProxy(current.identity));
- desc->md5 = getMD5(identityToPath(current.identity));
- return desc;
-}
-
-Int
-IcePatch::RegularI::getBZ2Size(const Ice::Current& current)
-{
- return getFileInfo(identityToPath(current.identity) + ".bz2", true).size;
-}
-
-ByteSeq
-IcePatch::RegularI::getBZ2(Ice::Int pos, Ice::Int num, const Ice::Current& current)
-{
- return IcePatch::getBZ2(identityToPath(current.identity), pos, num);
-}
+// **********************************************************************
+//
+// Copyright (c) 2002
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <IcePatch/IcePatchI.h>
+#include <IcePatch/Util.h>
+
+using namespace std;
+using namespace Ice;
+using namespace IcePatch;
+
+IcePatch::FileI::FileI(const ObjectAdapterPtr& adapter) :
+ _adapter(adapter)
+{
+}
+
+IcePatch::DirectoryI::DirectoryI(const ObjectAdapterPtr& adapter) :
+ FileI(adapter)
+{
+}
+
+FileDescPtr
+IcePatch::DirectoryI::describe(const Ice::Current& current)
+{
+ DirectoryDescPtr desc = new DirectoryDesc;
+ desc->directory = DirectoryPrx::uncheckedCast(_adapter->createProxy(current.identity));
+ return desc;
+}
+
+FileDescSeq
+IcePatch::DirectoryI::getContents(const Ice::Current& current)
+{
+ StringSeq paths = readDirectory(identityToPath(current.identity));
+
+ FileDescSeq result;
+ result.reserve(paths.size());
+
+ StringSeq::const_iterator p;
+ for (p = paths.begin(); p != paths.end(); ++p)
+ {
+ if (ignoreSuffix(*p))
+ {
+ continue;
+ }
+
+ FilePrx file = FilePrx::uncheckedCast(_adapter->createProxy(pathToIdentity(*p)));
+ try
+ {
+ result.push_back(file->describe());
+ }
+ catch (const ObjectNotExistException&)
+ {
+ //
+ // Ignore. This can for example happen if the file
+ // locator cannot call stat() on the file.
+ //
+ }
+ }
+
+ return result;
+}
+
+IcePatch::RegularI::RegularI(const ObjectAdapterPtr& adapter) :
+ FileI(adapter)
+{
+}
+
+FileDescPtr
+IcePatch::RegularI::describe(const Ice::Current& current)
+{
+ RegularDescPtr desc = new RegularDesc;
+ desc->regular = RegularPrx::uncheckedCast(_adapter->createProxy(current.identity));
+ desc->md5 = getMD5(identityToPath(current.identity));
+ return desc;
+}
+
+Int
+IcePatch::RegularI::getBZ2Size(const Ice::Current& current)
+{
+ return getFileInfo(identityToPath(current.identity) + ".bz2", true).size;
+}
+
+ByteSeq
+IcePatch::RegularI::getBZ2(Ice::Int pos, Ice::Int num, const Ice::Current& current)
+{
+ return IcePatch::getBZ2(identityToPath(current.identity), pos, num);
+}
diff --git a/cpp/src/IcePatch/Server.cpp b/cpp/src/IcePatch/Server.cpp
index 931a7527d07..fadbf596b95 100644
--- a/cpp/src/IcePatch/Server.cpp
+++ b/cpp/src/IcePatch/Server.cpp
@@ -1,205 +1,205 @@
-// **********************************************************************
-//
-// Copyright (c) 2002
-// MutableRealms, Inc.
-// Huntsville, AL, USA
-//
-// All Rights Reserved
-//
-// **********************************************************************
-
-#include <Ice/Application.h>
-#include <IcePatch/FileLocator.h>
-#include <IcePatch/Util.h>
-
-using namespace std;
-using namespace Ice;
-using namespace IcePatch;
-
-namespace IcePatch
-{
-
-class Server : public Application
-{
-public:
-
- void usage();
- virtual int run(int, char*[]);
-
- static void removeOrphanedRecursive(const string&);
- static void updateRecursive(const string&);
-};
-
-};
-
-void
-IcePatch::Server::usage()
-{
- cerr << "Usage: " << appName() << " [options]\n";
- cerr <<
- "Options:\n"
- "-h, --help Show this message.\n"
- "-v, --version Display the Ice version.\n"
- ;
-}
-
-int
-IcePatch::Server::run(int argc, char* argv[])
-{
- try
- {
- for (int i = 1; i < argc; ++i)
- {
- if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
- {
- usage();
- return EXIT_SUCCESS;
- }
- else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0)
- {
- cout << ICE_STRING_VERSION << endl;
- return EXIT_SUCCESS;
- }
- else
- {
- cerr << appName() << ": unknown option `" << argv[i] << "'" << endl;
- usage();
- return EXIT_FAILURE;
- }
- }
-
- PropertiesPtr properties = communicator()->getProperties();
-
- //
- // Get the IcePatch endpoints.
- //
- const char* endpointsProperty = "IcePatch.Endpoints";
- string endpoints = properties->getProperty(endpointsProperty);
- if (endpoints.empty())
- {
- cerr << appName() << ": property `" << endpointsProperty << "' is not set" << endl;
- return EXIT_FAILURE;
- }
-
- //
- // Get the working directory and change to this directory.
- //
- const char* directoryProperty = "IcePatch.Directory";
- string directory = properties->getProperty(directoryProperty);
- if (!directory.empty())
- {
- changeDirectory(directory);
- }
-
- //
- // Remove orphaned MD5 and BZ2 files.
- // Create MD5 and BZ2 files.
- //
- removeOrphanedRecursive(".");
- updateRecursive(".");
-
- //
- // Create and initialize the object adapter and the file locator.
- //
- ObjectAdapterPtr adapter = communicator()->createObjectAdapterFromProperty("IcePatch", endpointsProperty);
- ServantLocatorPtr fileLocator = new FileLocator(adapter);
- adapter->addServantLocator(fileLocator, "IcePatch");
- adapter->activate();
-
- //
- // We're done, let's wait for shutdown.
- //
- communicator()->waitForShutdown();
- }
- catch (const FileAccessException& ex)
- {
- cerr << appName() << ": " << ex << ":\n" << ex.reason << endl;
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
-
-void
-IcePatch::Server::removeOrphanedRecursive(const string& path)
-{
- assert(getFileInfo(path, true).type == FileTypeDirectory);
-
- StringSeq paths = readDirectory(path);
- StringSeq::const_iterator p;
- for (p = paths.begin(); p != paths.end(); ++p)
- {
- if (ignoreSuffix(*p))
- {
- pair<StringSeq::const_iterator, StringSeq::const_iterator> r =
- equal_range(paths.begin(), paths.end(), removeSuffix(*p));
- if (r.first == r.second)
- {
- cout << "removing orphaned file `" << *p << "'... " << flush;
- removeRecursive(*p);
- cout << "ok" << endl;
- }
- }
- else
- {
- if (getFileInfo(*p, true).type == FileTypeDirectory)
- {
- removeOrphanedRecursive(*p);
- }
- }
- }
-
- if (readDirectory(path).empty())
- {
- cout << "removing empty directory `" << *p << "'... " << flush;
- removeRecursive(path);
- cout << "ok" << endl;
- }
-}
-
-void
-IcePatch::Server::updateRecursive(const string& path)
-{
- if (ignoreSuffix(path))
- {
- return;
- }
-
- FileInfo info = getFileInfo(path, true);
-
- if (info.type == FileTypeDirectory)
- {
- StringSeq paths = readDirectory(path);
- StringSeq::const_iterator p;
- for (p = paths.begin(); p != paths.end(); ++p)
- {
- updateRecursive(*p);
- }
- }
- else if (info.type == FileTypeRegular)
- {
- FileInfo infoMD5 = getFileInfo(path + ".md5", false);
- if (infoMD5.type != FileTypeRegular || infoMD5.time < info.time)
- {
- cout << "creating .md5 file for `" << path << "'... " << flush;
- createMD5(path);
- cout << "ok" << endl;
- }
-
- FileInfo infoBZ2 = getFileInfo(path + ".bz2", false);
- if (infoBZ2.type != FileTypeRegular || infoBZ2.time < info.time)
- {
- cout << "creating .bz2 file for `" << path << "'... " << flush;
- createBZ2(path);
- cout << "ok" << endl;
- }
- }
-}
-
-int
-main(int argc, char* argv[])
-{
- addArgumentPrefix("IcePatch");
- Server app;
- return app.main(argc, argv);
-}
+// **********************************************************************
+//
+// Copyright (c) 2002
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <Ice/Application.h>
+#include <IcePatch/FileLocator.h>
+#include <IcePatch/Util.h>
+
+using namespace std;
+using namespace Ice;
+using namespace IcePatch;
+
+namespace IcePatch
+{
+
+class Server : public Application
+{
+public:
+
+ void usage();
+ virtual int run(int, char*[]);
+
+ static void removeOrphanedRecursive(const string&);
+ static void updateRecursive(const string&);
+};
+
+};
+
+void
+IcePatch::Server::usage()
+{
+ cerr << "Usage: " << appName() << " [options]\n";
+ cerr <<
+ "Options:\n"
+ "-h, --help Show this message.\n"
+ "-v, --version Display the Ice version.\n"
+ ;
+}
+
+int
+IcePatch::Server::run(int argc, char* argv[])
+{
+ try
+ {
+ for (int i = 1; i < argc; ++i)
+ {
+ if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
+ {
+ usage();
+ return EXIT_SUCCESS;
+ }
+ else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0)
+ {
+ cout << ICE_STRING_VERSION << endl;
+ return EXIT_SUCCESS;
+ }
+ else
+ {
+ cerr << appName() << ": unknown option `" << argv[i] << "'" << endl;
+ usage();
+ return EXIT_FAILURE;
+ }
+ }
+
+ PropertiesPtr properties = communicator()->getProperties();
+
+ //
+ // Get the IcePatch endpoints.
+ //
+ const char* endpointsProperty = "IcePatch.Endpoints";
+ string endpoints = properties->getProperty(endpointsProperty);
+ if (endpoints.empty())
+ {
+ cerr << appName() << ": property `" << endpointsProperty << "' is not set" << endl;
+ return EXIT_FAILURE;
+ }
+
+ //
+ // Get the working directory and change to this directory.
+ //
+ const char* directoryProperty = "IcePatch.Directory";
+ string directory = properties->getProperty(directoryProperty);
+ if (!directory.empty())
+ {
+ changeDirectory(directory);
+ }
+
+ //
+ // Remove orphaned MD5 and BZ2 files.
+ // Create MD5 and BZ2 files.
+ //
+ removeOrphanedRecursive(".");
+ updateRecursive(".");
+
+ //
+ // Create and initialize the object adapter and the file locator.
+ //
+ ObjectAdapterPtr adapter = communicator()->createObjectAdapterFromProperty("IcePatch", endpointsProperty);
+ ServantLocatorPtr fileLocator = new FileLocator(adapter);
+ adapter->addServantLocator(fileLocator, "IcePatch");
+ adapter->activate();
+
+ //
+ // We're done, let's wait for shutdown.
+ //
+ communicator()->waitForShutdown();
+ }
+ catch (const FileAccessException& ex)
+ {
+ cerr << appName() << ": " << ex << ":\n" << ex.reason << endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+void
+IcePatch::Server::removeOrphanedRecursive(const string& path)
+{
+ assert(getFileInfo(path, true).type == FileTypeDirectory);
+
+ StringSeq paths = readDirectory(path);
+ StringSeq::const_iterator p;
+ for (p = paths.begin(); p != paths.end(); ++p)
+ {
+ if (ignoreSuffix(*p))
+ {
+ pair<StringSeq::const_iterator, StringSeq::const_iterator> r =
+ equal_range(paths.begin(), paths.end(), removeSuffix(*p));
+ if (r.first == r.second)
+ {
+ cout << "removing orphaned file `" << *p << "'... " << flush;
+ removeRecursive(*p);
+ cout << "ok" << endl;
+ }
+ }
+ else
+ {
+ if (getFileInfo(*p, true).type == FileTypeDirectory)
+ {
+ removeOrphanedRecursive(*p);
+ }
+ }
+ }
+
+ if (readDirectory(path).empty())
+ {
+ cout << "removing empty directory `" << *p << "'... " << flush;
+ removeRecursive(path);
+ cout << "ok" << endl;
+ }
+}
+
+void
+IcePatch::Server::updateRecursive(const string& path)
+{
+ if (ignoreSuffix(path))
+ {
+ return;
+ }
+
+ FileInfo info = getFileInfo(path, true);
+
+ if (info.type == FileTypeDirectory)
+ {
+ StringSeq paths = readDirectory(path);
+ StringSeq::const_iterator p;
+ for (p = paths.begin(); p != paths.end(); ++p)
+ {
+ updateRecursive(*p);
+ }
+ }
+ else if (info.type == FileTypeRegular)
+ {
+ FileInfo infoMD5 = getFileInfo(path + ".md5", false);
+ if (infoMD5.type != FileTypeRegular || infoMD5.time < info.time)
+ {
+ cout << "creating .md5 file for `" << path << "'... " << flush;
+ createMD5(path);
+ cout << "ok" << endl;
+ }
+
+ FileInfo infoBZ2 = getFileInfo(path + ".bz2", false);
+ if (infoBZ2.type != FileTypeRegular || infoBZ2.time < info.time)
+ {
+ cout << "creating .bz2 file for `" << path << "'... " << flush;
+ createBZ2(path);
+ cout << "ok" << endl;
+ }
+ }
+}
+
+int
+main(int argc, char* argv[])
+{
+ addArgumentPrefix("IcePatch");
+ Server app;
+ return app.main(argc, argv);
+}
diff --git a/cpp/src/IcePatch/Util.cpp b/cpp/src/IcePatch/Util.cpp
index 2b61340faca..473b36ed53d 100644
--- a/cpp/src/IcePatch/Util.cpp
+++ b/cpp/src/IcePatch/Util.cpp
@@ -1,688 +1,688 @@
-// **********************************************************************
-//
-// Copyright (c) 2002
-// MutableRealms, Inc.
-// Huntsville, AL, USA
-//
-// All Rights Reserved
-//
-// **********************************************************************
-
-#include <IcePatch/Util.h>
-#include <fstream>
-#include <sys/stat.h>
-#include <openssl/md5.h>
-#include <bzlib.h>
-
-#ifndef _WIN32
-# include <unistd.h>
-# include <dirent.h>
-#else
-# include <direct.h>
-# include <io.h>
-# define S_ISDIR(mode) ((mode) & _S_IFDIR)
-# define S_ISREG(mode) ((mode) & _S_IFREG)
-#endif
-
-using namespace std;
-using namespace Ice;
-using namespace IcePatch;
-
-string
-normalizePath(const string& path)
-{
- string result = path;
-
- string::size_type pos;
-
- for (pos = 0; pos < result.size(); ++pos)
- {
- if (result[pos] == '\\')
- {
- result[pos] = '/';
- }
- }
-
- pos = 0;
- while ((pos = result.find("//", pos)) != string::npos)
- {
- result.erase(pos, 1);
- }
-
- pos = 0;
- while ((pos = result.find("/./", pos)) != string::npos)
- {
- result.erase(pos, 2);
- }
-
- if (result.substr(0, 2) == "./")
- {
- result.erase(0, 2);
- }
-
- return result;
-}
-
-string
-IcePatch::identityToPath(const Identity& ident)
-{
- assert(ident.category == "IcePatch");
- return normalizePath(ident.name);
-}
-
-Identity
-IcePatch::pathToIdentity(const string& path)
-{
- Identity ident;
- ident.category = "IcePatch";
- ident.name = normalizePath(path);
- return ident;
-}
-
-string
-IcePatch::getSuffix(const string& path)
-{
- string::size_type pos = path.rfind('.');
- if (pos == string::npos)
- {
- return string();
- }
- else
- {
- return path.substr(pos + 1);
- }
-}
-
-bool
-IcePatch::ignoreSuffix(const string& path)
-{
- string suffix = getSuffix(path);
- return suffix == "md5" || suffix == "md5temp" || suffix == "bz2" || suffix == "bz2temp";
-}
-
-string
-IcePatch::removeSuffix(const string& path)
-{
- string::size_type pos = path.rfind('.');
- if (pos == string::npos)
- {
- return path;
- }
- else
- {
- return path.substr(0, pos);
- }
-}
-
-FileInfo
-IcePatch::getFileInfo(const string& path, bool exceptionIfNotExist)
-{
- struct stat buf;
- if (::stat(path.c_str(), &buf) == -1)
- {
- if (!exceptionIfNotExist && errno == ENOENT)
- {
- FileInfo result;
- result.size = 0;
- result.time = 0;
- result.type = FileTypeNotExist;
- return result;
- }
- else
- {
- FileAccessException ex;
- ex.reason = "cannot stat `" + path + "': " + strerror(errno);
- throw ex;
- }
- }
-
- FileInfo result;
- result.size = buf.st_size;
- result.time = buf.st_mtime;
-
- if (S_ISDIR(buf.st_mode))
- {
- result.type = FileTypeDirectory;
- }
- else if (S_ISREG(buf.st_mode))
- {
- result.type = FileTypeRegular;
- }
- else
- {
- result.type = FileTypeUnknown;
- }
-
- return result;
-}
-
-void
-IcePatch::removeRecursive(const string& path)
-{
- if (getFileInfo(path, true).type == FileTypeDirectory)
- {
- StringSeq paths = readDirectory(path);
- for (StringSeq::const_iterator p = paths.begin(); p != paths.end(); ++p)
- {
- removeRecursive(*p);
- }
- }
-
- if (::remove(path.c_str()) == -1)
- {
- FileAccessException ex;
- ex.reason = "cannot remove file `" + path + "': " + strerror(errno);
- throw ex;
- }
-}
-
-void
-IcePatch::changeDirectory(const string& path)
-{
-#ifdef _WIN32
- if (_chdir(path.c_str()) == -1)
-#else
- if (chdir(path.c_str()) == -1)
-#endif
- {
- FileAccessException ex;
- ex.reason = "cannot change to directory `" + path + "': " + strerror(errno);
- throw ex;
- }
-}
-
-StringSeq
-IcePatch::readDirectory(const string& path)
-{
-#ifdef _WIN32
-
- struct _finddata_t data;
- long h = _findfirst((path + "/*").c_str(), &data);
- if (h == -1)
- {
- FileAccessException ex;
- ex.reason = "cannot read directory `" + path + "': " + strerror(errno);
- throw ex;
- }
-
- StringSeq result;
-
- while (true)
- {
- string name = data.name;
-
- if (name != ".." && name != ".")
- {
- result.push_back(normalizePath(path + '/' + name));
- }
-
- if (_findnext(h, &data) == -1)
- {
- if (errno == ENOENT)
- {
- break;
- }
-
- FileAccessException ex;
- ex.reason = "cannot read directory `" + path + "': " + strerror(errno);
- _findclose(h);
- throw ex;
- }
- }
-
- _findclose(h);
-
- sort(result.begin(), result.end());
-
- return result;
-
-#else
-
- struct dirent **namelist;
- int n = ::scandir(path.c_str(), &namelist, 0, alphasort);
- if (n < 0)
- {
- FileAccessException ex;
- ex.reason = "cannot read directory `" + path + "': " + strerror(errno);
- throw ex;
- }
-
- StringSeq result;
- result.reserve(n - 2);
-
- for (int i = 0; i < n; ++i)
- {
- string name = namelist[i]->d_name;
-
- free(namelist[i]);
-
- if (name != ".." && name != ".")
- {
- result.push_back(normalizePath(path + '/' + name));
- }
- }
-
- free(namelist);
- return result;
-
-#endif
-}
-
-void
-IcePatch::createDirectory(const string& path)
-{
-#ifdef _WIN32
- if (::_mkdir(path.c_str()) == -1)
-#else
- if (::mkdir(path.c_str(), 00777) == -1)
-#endif
- {
- FileAccessException ex;
- ex.reason = "cannot create directory `" + path + "': " + strerror(errno);
- throw ex;
- }
-}
-
-ByteSeq
-IcePatch::getMD5(const string& path)
-{
- string pathMD5 = path + ".md5";
- ifstream fileMD5(pathMD5.c_str(), ios::binary);
- if (!fileMD5)
- {
- FileAccessException ex;
- ex.reason = "cannot open `" + pathMD5 + "' for reading: " + strerror(errno);
- throw ex;
- }
- ByteSeq bytesMD5;
- bytesMD5.resize(16);
- fileMD5.read(&bytesMD5[0], 16);
- if (!fileMD5)
- {
- FileAccessException ex;
- ex.reason = "cannot read `" + pathMD5 + "': " + strerror(errno);
- throw ex;
- }
- if (fileMD5.gcount() < 16)
- {
- FileAccessException ex;
- ex.reason = "could not read 16 bytes from `" + pathMD5 + "'";
- throw ex;
- }
- fileMD5.close();
- return bytesMD5;
-}
-
-void
-IcePatch::createMD5(const string& path)
-{
- FileInfo info = getFileInfo(path, true);
- assert(info.type == FileTypeRegular);
-
- //
- // Read the original file.
- //
- ifstream file(path.c_str(), ios::binary);
- if (!file)
- {
- FileAccessException ex;
- ex.reason = "cannot open `" + path + "' for reading: " + strerror(errno);
- throw ex;
- }
- ByteSeq bytes;
- bytes.resize(info.size);
- file.read(&bytes[0], bytes.size());
- if (!file)
- {
- FileAccessException ex;
- ex.reason = "cannot read `" + path + "': " + strerror(errno);
- throw ex;
- }
- if (file.gcount() < static_cast<int>(bytes.size()))
- {
- FileAccessException ex;
- ex.reason = "could not read all bytes from `" + path + "'";
- throw ex;
- }
- file.close();
-
- //
- // Create the MD5 hash value.
- //
- ByteSeq bytesMD5;
- bytesMD5.resize(16);
- MD5(reinterpret_cast<unsigned char*>(&bytes[0]), bytes.size(), reinterpret_cast<unsigned char*>(&bytesMD5[0]));
-
- //
- // Save the MD5 hash value to a temporary MD5 file.
- //
- string pathMD5 = path + ".md5";
- string pathMD5Temp = path + ".md5temp";
- ofstream fileMD5(pathMD5Temp.c_str(), ios::binary);
- if (!fileMD5)
- {
- FileAccessException ex;
- ex.reason = "cannot open `" + pathMD5Temp + "' for writing: " + strerror(errno);
- throw ex;
- }
- fileMD5.write(&bytesMD5[0], 16);
- if (!fileMD5)
- {
- FileAccessException ex;
- ex.reason = "cannot write `" + pathMD5Temp + "': " + strerror(errno);
- throw ex;
- }
- fileMD5.close();
-
- //
- // Rename the temporary MD5 file to the final MD5 file. This is
- // done so that there can be no partial MD5 files after an
- // abortive application termination.
- //
- ::remove(pathMD5.c_str());
- if (::rename(pathMD5Temp.c_str(), pathMD5.c_str()) == -1)
- {
- FileAccessException ex;
- ex.reason = "cannot rename `" + pathMD5Temp + "' to `" + pathMD5 + "': " + strerror(errno);
- throw ex;
- }
-}
-
-ByteSeq
-IcePatch::getBZ2(const string& path, Int pos, Int num)
-{
- string pathBZ2 = path + ".bz2";
- ifstream fileBZ2(pathBZ2.c_str(), ios::binary);
- if (!fileBZ2)
- {
- FileAccessException ex;
- ex.reason = "cannot open `" + pathBZ2 + "' for reading: " + strerror(errno);
- throw ex;
- }
- fileBZ2.seekg(pos);
- if (!fileBZ2)
- {
- FileAccessException ex;
- ostringstream out;
- out << "cannot seek position " << pos << " in file `" << path << "':" << strerror(errno);
- ex.reason = out.str();
- throw ex;
- }
- ByteSeq bytesBZ2;
- bytesBZ2.resize(num);
- fileBZ2.read(&bytesBZ2[0], bytesBZ2.size());
- if (!fileBZ2 && !fileBZ2.eof())
- {
- FileAccessException ex;
- ex.reason = "cannot read `" + pathBZ2 + "': " + strerror(errno);
- throw ex;
- }
- bytesBZ2.resize(fileBZ2.gcount());
- fileBZ2.close();
- return bytesBZ2;
-}
-
-void
-IcePatch::createBZ2(const string& path)
-{
- FileInfo info = getFileInfo(path, true);
- assert(info.type == FileTypeRegular);
-
- //
- // Read the original file in blocks and write a temporary BZ2
- // file.
- //
- ifstream file(path.c_str(), ios::binary);
- if (!file)
- {
- FileAccessException ex;
- ex.reason = "cannot open `" + path + "' for reading: " + strerror(errno);
- throw ex;
- }
-
- string pathBZ2 = path + ".bz2";
- string pathBZ2Temp = path + ".bz2temp";
- FILE* stdioFileBZ2 = fopen(pathBZ2Temp.c_str(), "wb");
- if (!stdioFileBZ2)
- {
- FileAccessException ex;
- ex.reason = "cannot open `" + pathBZ2Temp + "' for writing: " + strerror(errno);
- throw ex;
- }
-
- int bzError;
- BZFILE* bzFile = BZ2_bzWriteOpen(&bzError, stdioFileBZ2, 5, 0, 0);
- if (bzError != BZ_OK)
- {
- FileAccessException ex;
- ex.reason = "BZ2_bzWriteOpen failed";
- if (bzError == BZ_IO_ERROR)
- {
- ex.reason += string(": ") + strerror(errno);
- }
- fclose(stdioFileBZ2);
- throw ex;
- }
-
- static const Int num = 64 * 1024;
- Byte bytes[num];
-
- while (!file.eof())
- {
- file.read(bytes, num);
- if (!file && !file.eof())
- {
- FileAccessException ex;
- ex.reason = "cannot read `" + path + "': " + strerror(errno);
- BZ2_bzWriteClose(&bzError, bzFile, 0, 0, 0);
- fclose(stdioFileBZ2);
- throw ex;
- }
-
- if (file.gcount() > 0)
- {
- BZ2_bzWrite(&bzError, bzFile, bytes, file.gcount());
- if (bzError != BZ_OK)
- {
- FileAccessException ex;
- ex.reason = "BZ2_bzWrite failed";
- if (bzError == BZ_IO_ERROR)
- {
- ex.reason += string(": ") + strerror(errno);
- }
- BZ2_bzWriteClose(&bzError, bzFile, 0, 0, 0);
- fclose(stdioFileBZ2);
- throw ex;
- }
- }
- }
-
- BZ2_bzWriteClose(&bzError, bzFile, 0, 0, 0);
- if (bzError != BZ_OK)
- {
- FileAccessException ex;
- ex.reason = "BZ2_bzWriteClose failed";
- if (bzError == BZ_IO_ERROR)
- {
- ex.reason += string(": ") + strerror(errno);
- }
- fclose(stdioFileBZ2);
- throw ex;
- }
-
- fclose(stdioFileBZ2);
- file.close();
-
- //
- // Rename the temporary BZ2 file to the final BZ2 file. This is
- // done so that there can be no partial BZ2 files after an
- // abortive application termination.
- //
- ::remove(pathBZ2.c_str());
- if (::rename(pathBZ2Temp.c_str(), pathBZ2.c_str()) == -1)
- {
- FileAccessException ex;
- ex.reason = "cannot rename `" + pathBZ2Temp + "' to `" + pathBZ2 + "': " + strerror(errno);
- throw ex;
- }
-}
-
-void
-IcePatch::getRegular(const RegularPrx& regular, ProgressCB& progressCB)
-{
- string path = identityToPath(regular->ice_getIdentity());
- string pathBZ2 = path + ".bz2";
- Int totalBZ2 = regular->getBZ2Size();
-
- //
- // Get the BZ2 file.
- //
- progressCB.startDownload(totalBZ2);
-
- ofstream fileBZ2(pathBZ2.c_str(), ios::binary);
- if (!fileBZ2)
- {
- FileAccessException ex;
- ex.reason = "cannot open `" + pathBZ2 + "' for writing: " + strerror(errno);
- throw ex;
- }
-
- ByteSeq bytesBZ2;
- Int pos = 0;
- while(pos < totalBZ2)
- {
- static const Int num = 64 * 1024;
-
- bytesBZ2 = regular->getBZ2(pos, num);
- if (bytesBZ2.empty())
- {
- break;
- }
-
- pos += bytesBZ2.size();
-
- fileBZ2.write(&bytesBZ2[0], bytesBZ2.size());
- if (!fileBZ2)
- {
- FileAccessException ex;
- ex.reason = "cannot write `" + pathBZ2 + "': " + strerror(errno);
- throw ex;
- }
-
- if (static_cast<Int>(bytesBZ2.size()) < num)
- {
- break;
- }
-
- progressCB.updateDownload(totalBZ2, pos);
- }
-
- progressCB.finishedDownload(totalBZ2);
-
- fileBZ2.close();
-
- //
- // Read the BZ2 file in blocks and write the original file.
- //
- ofstream file(path.c_str(), ios::binary);
- if (!file)
- {
- FileAccessException ex;
- ex.reason = "cannot open `" + path + "' for writing: " + strerror(errno);
- throw ex;
- }
-
- FILE* stdioFileBZ2 = fopen(pathBZ2.c_str(), "rb");
- if (!stdioFileBZ2)
- {
- FileAccessException ex;
- ex.reason = "cannot open `" + pathBZ2 + "' for reading: " + strerror(errno);
- throw ex;
- }
-
- int bzError;
- BZFILE* bzFile = BZ2_bzReadOpen(&bzError, stdioFileBZ2, 0, 0, 0, 0);
- if (bzError != BZ_OK)
- {
- FileAccessException ex;
- ex.reason = "BZ2_bzReadOpen failed";
- if (bzError == BZ_IO_ERROR)
- {
- ex.reason += string(": ") + strerror(errno);
- }
- fclose(stdioFileBZ2);
- throw ex;
- }
-
- static const Int num = 64 * 1024;
- Byte bytes[num];
-
- progressCB.startUncompress(totalBZ2);
- int countBZ2 = 0;
-
- while (bzError != BZ_STREAM_END)
- {
- int sz = BZ2_bzRead(&bzError, bzFile, bytes, num);
- if (bzError != BZ_OK && bzError != BZ_STREAM_END)
- {
- FileAccessException ex;
- ex.reason = "BZ2_bzRead failed";
- if (bzError == BZ_IO_ERROR)
- {
- ex.reason += string(": ") + strerror(errno);
- }
- BZ2_bzReadClose(&bzError, bzFile);
- fclose(stdioFileBZ2);
- throw ex;
- }
-
- if (sz > 0)
- {
- countBZ2 += sz;
- progressCB.updateUncompress(totalBZ2, countBZ2);
-
- file.write(bytes, sz);
- if (!file)
- {
- FileAccessException ex;
- ex.reason = "cannot write `" + path + "': " + strerror(errno);
- BZ2_bzReadClose(&bzError, bzFile);
- fclose(stdioFileBZ2);
- throw ex;
- }
- }
- }
-
- progressCB.finishedUncompress(totalBZ2);
-
- BZ2_bzReadClose(&bzError, bzFile);
- if (bzError != BZ_OK)
- {
- FileAccessException ex;
- ex.reason = "BZ2_bzReadClose failed";
- if (bzError == BZ_IO_ERROR)
- {
- ex.reason += string(": ") + strerror(errno);
- }
- fclose(stdioFileBZ2);
- throw ex;
- }
-
- fclose(stdioFileBZ2);
- file.close();
-
- //
- // Remove the BZ2 file, it is not needed anymore.
- //
- if (::remove(pathBZ2.c_str()) == -1)
- {
- FileAccessException ex;
- ex.reason = "cannot remove file `" + pathBZ2 + "': " + strerror(errno);
- throw ex;
- }
-
- //
- // Create a MD5 file for the original file.
- //
- createMD5(path);
-}
+// **********************************************************************
+//
+// Copyright (c) 2002
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <IcePatch/Util.h>
+#include <fstream>
+#include <sys/stat.h>
+#include <openssl/md5.h>
+#include <bzlib.h>
+
+#ifndef _WIN32
+# include <unistd.h>
+# include <dirent.h>
+#else
+# include <direct.h>
+# include <io.h>
+# define S_ISDIR(mode) ((mode) & _S_IFDIR)
+# define S_ISREG(mode) ((mode) & _S_IFREG)
+#endif
+
+using namespace std;
+using namespace Ice;
+using namespace IcePatch;
+
+string
+normalizePath(const string& path)
+{
+ string result = path;
+
+ string::size_type pos;
+
+ for (pos = 0; pos < result.size(); ++pos)
+ {
+ if (result[pos] == '\\')
+ {
+ result[pos] = '/';
+ }
+ }
+
+ pos = 0;
+ while ((pos = result.find("//", pos)) != string::npos)
+ {
+ result.erase(pos, 1);
+ }
+
+ pos = 0;
+ while ((pos = result.find("/./", pos)) != string::npos)
+ {
+ result.erase(pos, 2);
+ }
+
+ if (result.substr(0, 2) == "./")
+ {
+ result.erase(0, 2);
+ }
+
+ return result;
+}
+
+string
+IcePatch::identityToPath(const Identity& ident)
+{
+ assert(ident.category == "IcePatch");
+ return normalizePath(ident.name);
+}
+
+Identity
+IcePatch::pathToIdentity(const string& path)
+{
+ Identity ident;
+ ident.category = "IcePatch";
+ ident.name = normalizePath(path);
+ return ident;
+}
+
+string
+IcePatch::getSuffix(const string& path)
+{
+ string::size_type pos = path.rfind('.');
+ if (pos == string::npos)
+ {
+ return string();
+ }
+ else
+ {
+ return path.substr(pos + 1);
+ }
+}
+
+bool
+IcePatch::ignoreSuffix(const string& path)
+{
+ string suffix = getSuffix(path);
+ return suffix == "md5" || suffix == "md5temp" || suffix == "bz2" || suffix == "bz2temp";
+}
+
+string
+IcePatch::removeSuffix(const string& path)
+{
+ string::size_type pos = path.rfind('.');
+ if (pos == string::npos)
+ {
+ return path;
+ }
+ else
+ {
+ return path.substr(0, pos);
+ }
+}
+
+FileInfo
+IcePatch::getFileInfo(const string& path, bool exceptionIfNotExist)
+{
+ struct stat buf;
+ if (::stat(path.c_str(), &buf) == -1)
+ {
+ if (!exceptionIfNotExist && errno == ENOENT)
+ {
+ FileInfo result;
+ result.size = 0;
+ result.time = 0;
+ result.type = FileTypeNotExist;
+ return result;
+ }
+ else
+ {
+ FileAccessException ex;
+ ex.reason = "cannot stat `" + path + "': " + strerror(errno);
+ throw ex;
+ }
+ }
+
+ FileInfo result;
+ result.size = buf.st_size;
+ result.time = buf.st_mtime;
+
+ if (S_ISDIR(buf.st_mode))
+ {
+ result.type = FileTypeDirectory;
+ }
+ else if (S_ISREG(buf.st_mode))
+ {
+ result.type = FileTypeRegular;
+ }
+ else
+ {
+ result.type = FileTypeUnknown;
+ }
+
+ return result;
+}
+
+void
+IcePatch::removeRecursive(const string& path)
+{
+ if (getFileInfo(path, true).type == FileTypeDirectory)
+ {
+ StringSeq paths = readDirectory(path);
+ for (StringSeq::const_iterator p = paths.begin(); p != paths.end(); ++p)
+ {
+ removeRecursive(*p);
+ }
+ }
+
+ if (::remove(path.c_str()) == -1)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot remove file `" + path + "': " + strerror(errno);
+ throw ex;
+ }
+}
+
+void
+IcePatch::changeDirectory(const string& path)
+{
+#ifdef _WIN32
+ if (_chdir(path.c_str()) == -1)
+#else
+ if (chdir(path.c_str()) == -1)
+#endif
+ {
+ FileAccessException ex;
+ ex.reason = "cannot change to directory `" + path + "': " + strerror(errno);
+ throw ex;
+ }
+}
+
+StringSeq
+IcePatch::readDirectory(const string& path)
+{
+#ifdef _WIN32
+
+ struct _finddata_t data;
+ long h = _findfirst((path + "/*").c_str(), &data);
+ if (h == -1)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot read directory `" + path + "': " + strerror(errno);
+ throw ex;
+ }
+
+ StringSeq result;
+
+ while (true)
+ {
+ string name = data.name;
+
+ if (name != ".." && name != ".")
+ {
+ result.push_back(normalizePath(path + '/' + name));
+ }
+
+ if (_findnext(h, &data) == -1)
+ {
+ if (errno == ENOENT)
+ {
+ break;
+ }
+
+ FileAccessException ex;
+ ex.reason = "cannot read directory `" + path + "': " + strerror(errno);
+ _findclose(h);
+ throw ex;
+ }
+ }
+
+ _findclose(h);
+
+ sort(result.begin(), result.end());
+
+ return result;
+
+#else
+
+ struct dirent **namelist;
+ int n = ::scandir(path.c_str(), &namelist, 0, alphasort);
+ if (n < 0)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot read directory `" + path + "': " + strerror(errno);
+ throw ex;
+ }
+
+ StringSeq result;
+ result.reserve(n - 2);
+
+ for (int i = 0; i < n; ++i)
+ {
+ string name = namelist[i]->d_name;
+
+ free(namelist[i]);
+
+ if (name != ".." && name != ".")
+ {
+ result.push_back(normalizePath(path + '/' + name));
+ }
+ }
+
+ free(namelist);
+ return result;
+
+#endif
+}
+
+void
+IcePatch::createDirectory(const string& path)
+{
+#ifdef _WIN32
+ if (::_mkdir(path.c_str()) == -1)
+#else
+ if (::mkdir(path.c_str(), 00777) == -1)
+#endif
+ {
+ FileAccessException ex;
+ ex.reason = "cannot create directory `" + path + "': " + strerror(errno);
+ throw ex;
+ }
+}
+
+ByteSeq
+IcePatch::getMD5(const string& path)
+{
+ string pathMD5 = path + ".md5";
+ ifstream fileMD5(pathMD5.c_str(), ios::binary);
+ if (!fileMD5)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot open `" + pathMD5 + "' for reading: " + strerror(errno);
+ throw ex;
+ }
+ ByteSeq bytesMD5;
+ bytesMD5.resize(16);
+ fileMD5.read(&bytesMD5[0], 16);
+ if (!fileMD5)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot read `" + pathMD5 + "': " + strerror(errno);
+ throw ex;
+ }
+ if (fileMD5.gcount() < 16)
+ {
+ FileAccessException ex;
+ ex.reason = "could not read 16 bytes from `" + pathMD5 + "'";
+ throw ex;
+ }
+ fileMD5.close();
+ return bytesMD5;
+}
+
+void
+IcePatch::createMD5(const string& path)
+{
+ FileInfo info = getFileInfo(path, true);
+ assert(info.type == FileTypeRegular);
+
+ //
+ // Read the original file.
+ //
+ ifstream file(path.c_str(), ios::binary);
+ if (!file)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot open `" + path + "' for reading: " + strerror(errno);
+ throw ex;
+ }
+ ByteSeq bytes;
+ bytes.resize(info.size);
+ file.read(&bytes[0], bytes.size());
+ if (!file)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot read `" + path + "': " + strerror(errno);
+ throw ex;
+ }
+ if (file.gcount() < static_cast<int>(bytes.size()))
+ {
+ FileAccessException ex;
+ ex.reason = "could not read all bytes from `" + path + "'";
+ throw ex;
+ }
+ file.close();
+
+ //
+ // Create the MD5 hash value.
+ //
+ ByteSeq bytesMD5;
+ bytesMD5.resize(16);
+ MD5(reinterpret_cast<unsigned char*>(&bytes[0]), bytes.size(), reinterpret_cast<unsigned char*>(&bytesMD5[0]));
+
+ //
+ // Save the MD5 hash value to a temporary MD5 file.
+ //
+ string pathMD5 = path + ".md5";
+ string pathMD5Temp = path + ".md5temp";
+ ofstream fileMD5(pathMD5Temp.c_str(), ios::binary);
+ if (!fileMD5)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot open `" + pathMD5Temp + "' for writing: " + strerror(errno);
+ throw ex;
+ }
+ fileMD5.write(&bytesMD5[0], 16);
+ if (!fileMD5)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot write `" + pathMD5Temp + "': " + strerror(errno);
+ throw ex;
+ }
+ fileMD5.close();
+
+ //
+ // Rename the temporary MD5 file to the final MD5 file. This is
+ // done so that there can be no partial MD5 files after an
+ // abortive application termination.
+ //
+ ::remove(pathMD5.c_str());
+ if (::rename(pathMD5Temp.c_str(), pathMD5.c_str()) == -1)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot rename `" + pathMD5Temp + "' to `" + pathMD5 + "': " + strerror(errno);
+ throw ex;
+ }
+}
+
+ByteSeq
+IcePatch::getBZ2(const string& path, Int pos, Int num)
+{
+ string pathBZ2 = path + ".bz2";
+ ifstream fileBZ2(pathBZ2.c_str(), ios::binary);
+ if (!fileBZ2)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot open `" + pathBZ2 + "' for reading: " + strerror(errno);
+ throw ex;
+ }
+ fileBZ2.seekg(pos);
+ if (!fileBZ2)
+ {
+ FileAccessException ex;
+ ostringstream out;
+ out << "cannot seek position " << pos << " in file `" << path << "':" << strerror(errno);
+ ex.reason = out.str();
+ throw ex;
+ }
+ ByteSeq bytesBZ2;
+ bytesBZ2.resize(num);
+ fileBZ2.read(&bytesBZ2[0], bytesBZ2.size());
+ if (!fileBZ2 && !fileBZ2.eof())
+ {
+ FileAccessException ex;
+ ex.reason = "cannot read `" + pathBZ2 + "': " + strerror(errno);
+ throw ex;
+ }
+ bytesBZ2.resize(fileBZ2.gcount());
+ fileBZ2.close();
+ return bytesBZ2;
+}
+
+void
+IcePatch::createBZ2(const string& path)
+{
+ FileInfo info = getFileInfo(path, true);
+ assert(info.type == FileTypeRegular);
+
+ //
+ // Read the original file in blocks and write a temporary BZ2
+ // file.
+ //
+ ifstream file(path.c_str(), ios::binary);
+ if (!file)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot open `" + path + "' for reading: " + strerror(errno);
+ throw ex;
+ }
+
+ string pathBZ2 = path + ".bz2";
+ string pathBZ2Temp = path + ".bz2temp";
+ FILE* stdioFileBZ2 = fopen(pathBZ2Temp.c_str(), "wb");
+ if (!stdioFileBZ2)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot open `" + pathBZ2Temp + "' for writing: " + strerror(errno);
+ throw ex;
+ }
+
+ int bzError;
+ BZFILE* bzFile = BZ2_bzWriteOpen(&bzError, stdioFileBZ2, 5, 0, 0);
+ if (bzError != BZ_OK)
+ {
+ FileAccessException ex;
+ ex.reason = "BZ2_bzWriteOpen failed";
+ if (bzError == BZ_IO_ERROR)
+ {
+ ex.reason += string(": ") + strerror(errno);
+ }
+ fclose(stdioFileBZ2);
+ throw ex;
+ }
+
+ static const Int num = 64 * 1024;
+ Byte bytes[num];
+
+ while (!file.eof())
+ {
+ file.read(bytes, num);
+ if (!file && !file.eof())
+ {
+ FileAccessException ex;
+ ex.reason = "cannot read `" + path + "': " + strerror(errno);
+ BZ2_bzWriteClose(&bzError, bzFile, 0, 0, 0);
+ fclose(stdioFileBZ2);
+ throw ex;
+ }
+
+ if (file.gcount() > 0)
+ {
+ BZ2_bzWrite(&bzError, bzFile, bytes, file.gcount());
+ if (bzError != BZ_OK)
+ {
+ FileAccessException ex;
+ ex.reason = "BZ2_bzWrite failed";
+ if (bzError == BZ_IO_ERROR)
+ {
+ ex.reason += string(": ") + strerror(errno);
+ }
+ BZ2_bzWriteClose(&bzError, bzFile, 0, 0, 0);
+ fclose(stdioFileBZ2);
+ throw ex;
+ }
+ }
+ }
+
+ BZ2_bzWriteClose(&bzError, bzFile, 0, 0, 0);
+ if (bzError != BZ_OK)
+ {
+ FileAccessException ex;
+ ex.reason = "BZ2_bzWriteClose failed";
+ if (bzError == BZ_IO_ERROR)
+ {
+ ex.reason += string(": ") + strerror(errno);
+ }
+ fclose(stdioFileBZ2);
+ throw ex;
+ }
+
+ fclose(stdioFileBZ2);
+ file.close();
+
+ //
+ // Rename the temporary BZ2 file to the final BZ2 file. This is
+ // done so that there can be no partial BZ2 files after an
+ // abortive application termination.
+ //
+ ::remove(pathBZ2.c_str());
+ if (::rename(pathBZ2Temp.c_str(), pathBZ2.c_str()) == -1)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot rename `" + pathBZ2Temp + "' to `" + pathBZ2 + "': " + strerror(errno);
+ throw ex;
+ }
+}
+
+void
+IcePatch::getRegular(const RegularPrx& regular, ProgressCB& progressCB)
+{
+ string path = identityToPath(regular->ice_getIdentity());
+ string pathBZ2 = path + ".bz2";
+ Int totalBZ2 = regular->getBZ2Size();
+
+ //
+ // Get the BZ2 file.
+ //
+ progressCB.startDownload(totalBZ2);
+
+ ofstream fileBZ2(pathBZ2.c_str(), ios::binary);
+ if (!fileBZ2)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot open `" + pathBZ2 + "' for writing: " + strerror(errno);
+ throw ex;
+ }
+
+ ByteSeq bytesBZ2;
+ Int pos = 0;
+ while(pos < totalBZ2)
+ {
+ static const Int num = 64 * 1024;
+
+ bytesBZ2 = regular->getBZ2(pos, num);
+ if (bytesBZ2.empty())
+ {
+ break;
+ }
+
+ pos += bytesBZ2.size();
+
+ fileBZ2.write(&bytesBZ2[0], bytesBZ2.size());
+ if (!fileBZ2)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot write `" + pathBZ2 + "': " + strerror(errno);
+ throw ex;
+ }
+
+ if (static_cast<Int>(bytesBZ2.size()) < num)
+ {
+ break;
+ }
+
+ progressCB.updateDownload(totalBZ2, pos);
+ }
+
+ progressCB.finishedDownload(totalBZ2);
+
+ fileBZ2.close();
+
+ //
+ // Read the BZ2 file in blocks and write the original file.
+ //
+ ofstream file(path.c_str(), ios::binary);
+ if (!file)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot open `" + path + "' for writing: " + strerror(errno);
+ throw ex;
+ }
+
+ FILE* stdioFileBZ2 = fopen(pathBZ2.c_str(), "rb");
+ if (!stdioFileBZ2)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot open `" + pathBZ2 + "' for reading: " + strerror(errno);
+ throw ex;
+ }
+
+ int bzError;
+ BZFILE* bzFile = BZ2_bzReadOpen(&bzError, stdioFileBZ2, 0, 0, 0, 0);
+ if (bzError != BZ_OK)
+ {
+ FileAccessException ex;
+ ex.reason = "BZ2_bzReadOpen failed";
+ if (bzError == BZ_IO_ERROR)
+ {
+ ex.reason += string(": ") + strerror(errno);
+ }
+ fclose(stdioFileBZ2);
+ throw ex;
+ }
+
+ static const Int num = 64 * 1024;
+ Byte bytes[num];
+
+ progressCB.startUncompress(totalBZ2);
+ int countBZ2 = 0;
+
+ while (bzError != BZ_STREAM_END)
+ {
+ int sz = BZ2_bzRead(&bzError, bzFile, bytes, num);
+ if (bzError != BZ_OK && bzError != BZ_STREAM_END)
+ {
+ FileAccessException ex;
+ ex.reason = "BZ2_bzRead failed";
+ if (bzError == BZ_IO_ERROR)
+ {
+ ex.reason += string(": ") + strerror(errno);
+ }
+ BZ2_bzReadClose(&bzError, bzFile);
+ fclose(stdioFileBZ2);
+ throw ex;
+ }
+
+ if (sz > 0)
+ {
+ countBZ2 += sz;
+ progressCB.updateUncompress(totalBZ2, countBZ2);
+
+ file.write(bytes, sz);
+ if (!file)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot write `" + path + "': " + strerror(errno);
+ BZ2_bzReadClose(&bzError, bzFile);
+ fclose(stdioFileBZ2);
+ throw ex;
+ }
+ }
+ }
+
+ progressCB.finishedUncompress(totalBZ2);
+
+ BZ2_bzReadClose(&bzError, bzFile);
+ if (bzError != BZ_OK)
+ {
+ FileAccessException ex;
+ ex.reason = "BZ2_bzReadClose failed";
+ if (bzError == BZ_IO_ERROR)
+ {
+ ex.reason += string(": ") + strerror(errno);
+ }
+ fclose(stdioFileBZ2);
+ throw ex;
+ }
+
+ fclose(stdioFileBZ2);
+ file.close();
+
+ //
+ // Remove the BZ2 file, it is not needed anymore.
+ //
+ if (::remove(pathBZ2.c_str()) == -1)
+ {
+ FileAccessException ex;
+ ex.reason = "cannot remove file `" + pathBZ2 + "': " + strerror(errno);
+ throw ex;
+ }
+
+ //
+ // Create a MD5 file for the original file.
+ //
+ createMD5(path);
+}
diff --git a/cpp/test/Glacier/starter/Client.cpp b/cpp/test/Glacier/starter/Client.cpp
index 67f07ac38be..2a5536cfbe3 100644
--- a/cpp/test/Glacier/starter/Client.cpp
+++ b/cpp/test/Glacier/starter/Client.cpp
@@ -73,7 +73,7 @@ CallbackClient::run(int argc, char* argv[])
RouterPrx router;
try
{
- router = starter->startRouter("", "", privateKey, publicKey, routerCert);
+ router = starter->startRouter("dummy", "abc123", privateKey, publicKey, routerCert);
}
catch (const Glacier::CannotStartRouterException& ex)
{
diff --git a/cpp/test/Glacier/starter/passwords b/cpp/test/Glacier/starter/passwords
new file mode 100644
index 00000000000..2b10070db5c
--- /dev/null
+++ b/cpp/test/Glacier/starter/passwords
@@ -0,0 +1 @@
+dummy xxMqsnnDcK8tw \ No newline at end of file
diff --git a/cpp/test/Glacier/starter/run.py b/cpp/test/Glacier/starter/run.py
index 2dbca1f396a..334755fb45e 100755
--- a/cpp/test/Glacier/starter/run.py
+++ b/cpp/test/Glacier/starter/run.py
@@ -29,6 +29,7 @@ updatedClientOptions = TestUtil.clientOptions.replace("TOPLEVELDIR", toplevel)
updatedClientServerOptions = TestUtil.clientServerOptions.replace("TOPLEVELDIR", toplevel)
command = starter + updatedClientServerOptions + \
+ r' --Glacier.Starter.CryptPasswords="' + toplevel + r'/test/Glacier/starter/passwords"' + \
r' --Glacier.Starter.RouterPath=' + router + \
r' --Glacier.Starter.Endpoints="default -p 12346 -t 5000"' + \
r' --Glacier.Router.Endpoints="default"' + \