IceBox::ServiceManagerI::ServiceManagerI(CommunicatorPtr communicator, int& argc, char* argv[]) : _communicator(communicator), _adminEnabled(false), _pendingStatusChanges(false), _traceServiceObserver(0) { #ifndef ICE_CPP11_MAPPING const_cast<CallbackPtr&>(_observerCompletedCB) = newCallback(this, &ServiceManagerI::observerCompleted); #endif _logger = _communicator->getLogger(); PropertiesPtr props = _communicator->getProperties(); _traceServiceObserver = props->getPropertyAsInt("IceBox.Trace.ServiceObserver"); if(props->getProperty("Ice.Admin.Enabled") == "") { _adminEnabled = props->getProperty("Ice.Admin.Endpoints") != ""; } else { _adminEnabled = props->getPropertyAsInt("Ice.Admin.Enabled") > 0; } if(_adminEnabled) { StringSeq facetSeq = props->getPropertyAsList("Ice.Admin.Facets"); if(!facetSeq.empty()) { _adminFacetFilter.insert(facetSeq.begin(), facetSeq.end()); } } for(int i = 1; i < argc; i++) { _argv.push_back(argv[i]); } }
int Activator::activate(const string& name, const string& exePath, const string& pwdPath, #ifndef _WIN32 uid_t uid, gid_t gid, #endif const Ice::StringSeq& options, const Ice::StringSeq& envs, const ServerIPtr& server) { IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this); if(_deactivating) { throw string("The node is being shutdown."); } string path = exePath; if(path.empty()) { throw string("The server executable path is empty."); } string pwd = IcePatch2Internal::simplify(pwdPath); #ifdef _WIN32 if(!IceUtilInternal::isAbsolutePath(path)) { if(path.find('/') == string::npos) { // // Get the absolute pathname of the executable. // wchar_t absbuf[_MAX_PATH]; wchar_t* fPart; wstring ext = path.size() <= 4 || path[path.size() - 4] != '.' ? L".exe" : L""; // // IceGrid doesn't support to use string converters, so don't need to use // any string converter in wstringToString conversions. // if(SearchPathW(NULL, IceUtil::stringToWstring(path).c_str(), ext.c_str(), _MAX_PATH, absbuf, &fPart) == 0) { if(_traceLevels->activator > 0) { Trace out(_traceLevels->logger, _traceLevels->activatorCat); out << "couldn't find `" << path << "' executable."; } throw string("Couldn't find `" + path + "' executable."); } path = IceUtil::wstringToString(absbuf); } else if(!pwd.empty()) { path = pwd + "/" + path; } } // // Get the absolute pathname of the working directory. // // IceGrid doesn't support to use string converters, so // don't need to use any string converter in stringToWstring // conversions. // if(!pwd.empty()) { wchar_t absbuf[_MAX_PATH]; if(_wfullpath(absbuf, IceUtil::stringToWstring(pwd).c_str(), _MAX_PATH) == NULL) { if(_traceLevels->activator > 0) { Trace out(_traceLevels->logger, _traceLevels->activatorCat); out << "cannot convert `" << pwd << "' into an absolute path"; } throw string("The server working directory path `" + pwd + "' can't be converted into an absolute path."); } pwd = IceUtil::wstringToString(absbuf); } #endif // // Setup arguments. // StringSeq args; args.push_back(path); args.insert(args.end(), options.begin(), options.end()); if(_traceLevels->activator > 0) { Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); out << "activating server `" << name << "'"; if(_traceLevels->activator > 1) { out << "\n"; out << "path = " << path << "\n"; if(pwd.empty()) { string cwd; if(IceUtilInternal::getcwd(cwd) == 0) { out << "pwd = " << cwd << "\n"; } } else { out << "pwd = " << pwd << "\n"; } #ifndef _WIN32 out << "uid/gid = " << uid << "/" << gid << "\n"; #endif if(!envs.empty()) { out << "envs = " << toString(envs, ", ") << "\n"; } if(!args.empty()) { out << "args = " << toString(args); } } } // // Activate and create. // #ifdef _WIN32 // // Compose command line. // string cmd; for(StringSeq::const_iterator p = args.begin(); p != args.end(); ++p) { if(p != args.begin()) { cmd.push_back(' '); } // // Enclose arguments containing spaces in double quotes. // if((*p).find(' ') != string::npos) { cmd.push_back('"'); cmd.append(*p); cmd.push_back('"'); } else { cmd.append(*p); } } // // IceGrid doesn't support to use string converters, so don't need to use // any string converter in stringToWstring conversions. // wstring wpwd = IceUtil::stringToWstring(pwd); const wchar_t* dir = !wpwd.empty() ? wpwd.c_str() : NULL; // // Make a copy of the command line. // wchar_t* cmdbuf = _wcsdup(IceUtil::stringToWstring(cmd).c_str()); // // Create the environment block for the child process. We start with the environment // of this process, and then merge environment variables from the server description. // Since Windows is case insensitive wrt environment variables we convert the keys to // uppercase to ensure matches are found. // const wchar_t* env = NULL; wstring envbuf; if(!envs.empty()) { map<wstring, wstring, UnicodeStringLess> envMap; LPVOID parentEnv = GetEnvironmentStringsW(); const wchar_t* var = reinterpret_cast<const wchar_t*>(parentEnv); if(*var == L'=') { // // The environment block may start with some information about the // current drive and working directory. This is indicated by a leading // '=' character, so we skip to the first '\0' byte. // while(*var != L'\0') var++; var++; } while(*var != L'\0') { wstring s(var); wstring::size_type pos = s.find(L'='); if(pos != wstring::npos) { envMap[s.substr(0, pos)] = s.substr(pos + 1); } var += s.size(); var++; // Skip the '\0' byte } FreeEnvironmentStringsW(static_cast<wchar_t*>(parentEnv)); for(StringSeq::const_iterator p = envs.begin(); p != envs.end(); ++p) { // // IceGrid doesn't support to use string converters, so don't need to use // any string converter in stringToWstring conversions. // wstring s = IceUtil::stringToWstring(*p); wstring::size_type pos = s.find(L'='); if(pos != wstring::npos) { envMap[s.substr(0, pos)] = s.substr(pos + 1); } } for(map<wstring, wstring, UnicodeStringLess>::const_iterator q = envMap.begin(); q != envMap.end(); ++q) { envbuf.append(q->first); envbuf.push_back(L'='); envbuf.append(q->second); envbuf.push_back(L'\0'); } envbuf.push_back(L'\0'); env = envbuf.c_str(); } Process process; STARTUPINFOW si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); BOOL b = CreateProcessW( NULL, // Executable cmdbuf, // Command line NULL, // Process attributes NULL, // Thread attributes FALSE, // Do NOT inherit handles CREATE_NEW_PROCESS_GROUP | CREATE_UNICODE_ENVIRONMENT, // Process creation flags (LPVOID)env, // Process environment dir, // Current directory &si, // Startup info &pi // Process info ); free(cmdbuf); if(!b) { throw IceUtilInternal::lastErrorToString(); } // // Caller is responsible for closing handles in PROCESS_INFORMATION. We don't need to // keep the thread handle, so we close it now. The process handle will be closed later. // CloseHandle(pi.hThread); process.activator = this; process.pid = pi.dwProcessId; process.hnd = pi.hProcess; process.server = server; map<string, Process>::iterator it = _processes.insert(make_pair(name, process)).first; Process* pp = &it->second; if(!RegisterWaitForSingleObject(&pp->waithnd, pp->hnd, activatorWaitCallback, pp, INFINITE, WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE)) { throw IceUtilInternal::lastErrorToString(); } // // Don't print the following trace, this might interfer with the // output of the started process if it fails with an error message. // // if(_traceLevels->activator > 0) // { // Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); // out << "activated server `" << name << "' (pid = " << pi.dwProcessId << ")"; // } return static_cast<Ice::Int>(process.pid); #else int fds[2]; if(pipe(fds) != 0) { SyscallException ex(__FILE__, __LINE__); ex.error = getSystemErrno(); throw ex; } int errorFds[2]; if(pipe(errorFds) != 0) { SyscallException ex(__FILE__, __LINE__); ex.error = getSystemErrno(); throw ex; } // // Convert to standard argc/argv. // IceUtilInternal::ArgVector av(args); IceUtilInternal::ArgVector env(envs); // // Current directory // const char* pwdCStr = pwd.c_str(); pid_t pid = fork(); if(pid == -1) { SyscallException ex(__FILE__, __LINE__); ex.error = getSystemErrno(); throw ex; } if(pid == 0) // Child process. { // // Until exec, we can only use async-signal safe functions // // // Unblock signals blocked by IceUtil::CtrlCHandler. // sigset_t sigs; sigemptyset(&sigs); sigaddset(&sigs, SIGHUP); sigaddset(&sigs, SIGINT); sigaddset(&sigs, SIGTERM); sigprocmask(SIG_UNBLOCK, &sigs, 0); // // Change the uid/gid under which the process will run. // if(setgid(gid) == -1) { ostringstream os; os << gid; reportChildError(getSystemErrno(), errorFds[1], "cannot set process group id", os.str().c_str(), _traceLevels); } errno = 0; struct passwd* pw = getpwuid(uid); if(!pw) { if(errno) { reportChildError(getSystemErrno(), errorFds[1], "cannot read the password database", "", _traceLevels); } else { ostringstream os; os << uid; reportChildError(getSystemErrno(), errorFds[1], "unknown user uid" , os.str().c_str(), _traceLevels); } } // // Don't initialize supplementary groups if we are not running as root. // if(getuid() == 0 && initgroups(pw->pw_name, gid) == -1) { ostringstream os; os << pw->pw_name; reportChildError(getSystemErrno(), errorFds[1], "cannot initialize process supplementary group access list for user", os.str().c_str(), _traceLevels); } if(setuid(uid) == -1) { ostringstream os; os << uid; reportChildError(getSystemErrno(), errorFds[1], "cannot set process user id", os.str().c_str(), _traceLevels); } // // Assign a new process group for this process. // setpgid(0, 0); // // Close all file descriptors, except for standard input, // standard output, standard error, and the write side // of the newly created pipe. // int maxFd = static_cast<int>(sysconf(_SC_OPEN_MAX)); for(int fd = 3; fd < maxFd; ++fd) { if(fd != fds[1] && fd != errorFds[1]) { close(fd); } } for(int i = 0; i < env.argc; i++) { // // Each env is leaked on purpose ... see man putenv(). // if(putenv(strdup(env.argv[i])) != 0) { reportChildError(errno, errorFds[1], "cannot set environment variable", env.argv[i], _traceLevels); } } // // Change working directory. // if(strlen(pwdCStr) != 0) { if(chdir(pwdCStr) == -1) { reportChildError(errno, errorFds[1], "cannot change working directory to", pwdCStr, _traceLevels); } } // // Close on exec the error message file descriptor. // int flags = fcntl(errorFds[1], F_GETFD); flags |= 1; // FD_CLOEXEC if(fcntl(errorFds[1], F_SETFD, flags) == -1) { close(errorFds[1]); errorFds[1] = -1; } if(execvp(av.argv[0], av.argv) == -1) { if(errorFds[1] != -1) { reportChildError(errno, errorFds[1], "cannot execute", av.argv[0], _traceLevels); } else { reportChildError(errno, fds[1], "cannot execute", av.argv[0], _traceLevels); } } } else // Parent process. { close(fds[1]); close(errorFds[1]); // // Read a potential error message over the error message pipe. // char s[16]; ssize_t rs; string message; while((rs = read(errorFds[0], &s, 16)) > 0) { message.append(s, rs); } // // If an error occured before the exec() we do some cleanup and throw. // if(!message.empty()) { close(fds[0]); close(errorFds[0]); waitPid(pid); throw message; } // // Otherwise, the exec() was successfull and we don't need the error message // pipe anymore. // close(errorFds[0]); Process process; process.pid = pid; process.pipeFd = fds[0]; process.server = server; _processes.insert(make_pair(name, process)); int flags = fcntl(process.pipeFd, F_GETFL); flags |= O_NONBLOCK; fcntl(process.pipeFd, F_SETFL, flags); setInterrupt(); // // Don't print the following trace, this might interfere with the // output of the started process if it fails with an error message. // // if(_traceLevels->activator > 0) // { // Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat); // out << "activated server `" << name << "' (pid = " << pid << ")"; // } } return pid; #endif }
int Client::run(int argc, char* argv[]) { IceUtilInternal::Options opts; opts.addOpt("h", "help"); opts.addOpt("v", "version"); opts.addOpt("d", "debug"); opts.addOpt("", "import", IceUtilInternal::Options::NeedArg); opts.addOpt("", "export", IceUtilInternal::Options::NeedArg); opts.addOpt("", "dbhome", IceUtilInternal::Options::NeedArg); opts.addOpt("", "dbpath", IceUtilInternal::Options::NeedArg); opts.addOpt("", "mapsize", IceUtilInternal::Options::NeedArg); opts.addOpt("", "server-version", IceUtilInternal::Options::NeedArg); vector<string> args; try { args = opts.parse(argc, const_cast<const char**>(argv)); } catch(const IceUtilInternal::BadOptException& e) { cerr << e.reason << endl; usage(); return EXIT_FAILURE; } if(!args.empty()) { cerr << argv[0] << ": too many arguments" << endl; usage(); return EXIT_FAILURE; } if(opts.isSet("help")) { usage(); return EXIT_SUCCESS; } if(opts.isSet("version")) { cout << ICE_STRING_VERSION << endl; return EXIT_SUCCESS; } if(!(opts.isSet("import") ^ opts.isSet("export"))) { cerr << "Either --import or --export must be set" << endl; usage(); return EXIT_FAILURE; } if(!(opts.isSet("dbhome") ^ opts.isSet("dbpath"))) { cerr << "Set the database environment directory with either --dbhome or --dbpath" << endl; usage(); return EXIT_FAILURE; } bool debug = opts.isSet("debug"); bool import = opts.isSet("import"); string dbFile = opts.optArg(import ? "import" : "export"); string dbPath; if(opts.isSet("dbhome")) { dbPath = opts.optArg("dbhome"); } else { dbPath = opts.optArg("dbpath"); } string mapSizeStr = opts.optArg("mapsize"); size_t mapSize = IceDB::getMapSize(atoi(mapSizeStr.c_str())); string serverVersion = opts.optArg("server-version"); try { IceGrid::AllData data; IceDB::IceContext dbContext; dbContext.communicator = communicator(); dbContext.encoding.major = 1; dbContext.encoding.minor = 1; if(import) { cout << "Importing database to directory `" << dbPath << "' from file `" << dbFile << "'" << endl; if(!IceUtilInternal::directoryExists(dbPath)) { cerr << "Output directory does not exist: " << dbPath << endl; return EXIT_FAILURE; } StringSeq files = IcePatch2Internal::readDirectory(dbPath); if(!files.empty()) { cerr << "Output directory is not empty: " << dbPath << endl; return EXIT_FAILURE; } ifstream fs(dbFile.c_str(), ios::binary); if(fs.fail()) { cerr << "Could not open input file: " << strerror(errno) << endl; return EXIT_FAILURE; } fs.unsetf(ios::skipws); fs.seekg(0, ios::end); streampos fileSize = fs.tellg(); fs.seekg(0, ios::beg); vector<Ice::Byte> buf; buf.reserve(static_cast<size_t>(fileSize)); buf.insert(buf.begin(), istream_iterator<Ice::Byte>(fs), istream_iterator<Ice::Byte>()); fs.close(); if(!serverVersion.empty()) { ValueFactoryPtr factory = new ValueFactoryI(serverVersion); communicator()->addValueFactory(factory, "::IceGrid::ServerDescriptor"); communicator()->addValueFactory(factory, "::IceGrid::IceBoxDescriptor"); } Ice::InputStreamPtr stream = Ice::wrapInputStream(communicator(), buf, dbContext.encoding); string type; int version; stream->read(type); if(type != "IceGrid") { cerr << "Incorrect input file type: " << type << endl; return EXIT_FAILURE; } stream->read(version); if(version / 100 == 305) { if(debug) { cout << "Reading Ice 3.5.x data" << endl; } skipFilter = true; } stream->read(data); { IceDB::Env env(dbPath, 5, mapSize); IceDB::ReadWriteTxn txn(env); if(debug) { cout << "Writing Applications Map:" << endl; } IceDB::Dbi<string, ApplicationInfo, IceDB::IceContext, Ice::OutputStreamPtr> apps(txn, "applications", dbContext, MDB_CREATE); for(ApplicationInfoSeq::const_iterator p = data.applications.begin(); p != data.applications.end(); ++p) { if(debug) { cout << " NAME = " << p->descriptor.name << endl; } apps.put(txn, p->descriptor.name, *p); } if(debug) { cout << "Writing Adapters Map:" << endl; } IceDB::Dbi<string, AdapterInfo, IceDB::IceContext, Ice::OutputStreamPtr> adpts(txn, "adapters", dbContext, MDB_CREATE); for(AdapterInfoSeq::const_iterator p = data.adapters.begin(); p != data.adapters.end(); ++p) { if(debug) { cout << " NAME = " << p->id << endl; } adpts.put(txn, p->id, *p); } if(debug) { cout << "Writing Objects Map:" << endl; } IceDB::Dbi<Identity, ObjectInfo, IceDB::IceContext, Ice::OutputStreamPtr> objs(txn, "objects", dbContext, MDB_CREATE); for(ObjectInfoSeq::const_iterator p = data.objects.begin(); p != data.objects.end(); ++p) { if(debug) { cout << " NAME = " << communicator()->identityToString(p->proxy->ice_getIdentity()) << endl; } objs.put(txn, p->proxy->ice_getIdentity(), *p); } if(debug) { cout << "Writing Internal Objects Map:" << endl; } IceDB::Dbi<Identity, ObjectInfo, IceDB::IceContext, Ice::OutputStreamPtr> internalObjs(txn, "internal-objects", dbContext, MDB_CREATE); for(ObjectInfoSeq::const_iterator p = data.internalObjects.begin(); p != data.internalObjects.end(); ++p) { if(debug) { cout << " NAME = " << communicator()->identityToString(p->proxy->ice_getIdentity()) << endl; } internalObjs.put(txn, p->proxy->ice_getIdentity(), *p); } if(debug) { cout << "Writing Serials Map:" << endl; } IceDB::Dbi<string, Long, IceDB::IceContext, Ice::OutputStreamPtr> srls(txn, "serials", dbContext, MDB_CREATE); for(StringLongDict::const_iterator p = data.serials.begin(); p != data.serials.end(); ++p) { if(debug) { cout << " NAME = " << p->first << endl; } srls.put(txn, p->first, p->second); } txn.commit(); env.close(); } } else { cout << "Exporting database from directory `" << dbPath << "' to file `" << dbFile << "'" << endl; { IceDB::Env env(dbPath, 5); IceDB::ReadOnlyTxn txn(env); if(debug) { cout << "Reading Application Map:" << endl; } IceDB::Dbi<string, IceGrid::ApplicationInfo, IceDB::IceContext, Ice::OutputStreamPtr> applications(txn, "applications", dbContext, 0); string name; ApplicationInfo application; IceDB::ReadOnlyCursor<string, IceGrid::ApplicationInfo, IceDB::IceContext, Ice::OutputStreamPtr> appCursor(applications, txn); while(appCursor.get(name, application, MDB_NEXT)) { if(debug) { cout << " APPLICATION = " << name << endl; } data.applications.push_back(application); } appCursor.close(); if(debug) { cout << "Reading Adapter Map:" << endl; } IceDB::Dbi<string, IceGrid::AdapterInfo, IceDB::IceContext, Ice::OutputStreamPtr> adapters(txn, "adapters", dbContext, 0); AdapterInfo adapter; IceDB::ReadOnlyCursor<string, IceGrid::AdapterInfo, IceDB::IceContext, Ice::OutputStreamPtr> adapterCursor(adapters, txn); while(adapterCursor.get(name, adapter, MDB_NEXT)) { if(debug) { cout << " ADAPTER = " << name << endl; } data.adapters.push_back(adapter); } adapterCursor.close(); if(debug) { cout << "Reading Object Map:" << endl; } IceDB::Dbi<Identity, IceGrid::ObjectInfo, IceDB::IceContext, Ice::OutputStreamPtr> objects(txn, "objects", dbContext, 0); Identity id; ObjectInfo object; IceDB::ReadOnlyCursor<Identity, IceGrid::ObjectInfo, IceDB::IceContext, Ice::OutputStreamPtr> objCursor(objects, txn); while(objCursor.get(id, object, MDB_NEXT)) { if(debug) { cout << " IDENTITY = " << communicator()->identityToString(id) << endl; } data.objects.push_back(object); } objCursor.close(); if(debug) { cout << "Reading Internal Object Map:" << endl; } IceDB::Dbi<Identity, IceGrid::ObjectInfo, IceDB::IceContext, Ice::OutputStreamPtr> internalObjects(txn, "internal-objects", dbContext, 0); IceDB::ReadOnlyCursor<Identity, IceGrid::ObjectInfo, IceDB::IceContext, Ice::OutputStreamPtr> iobjCursor(internalObjects, txn); while(iobjCursor.get(id, object, MDB_NEXT)) { if(debug) { cout << " IDENTITY = " << communicator()->identityToString(id) << endl; } data.internalObjects.push_back(object); } iobjCursor.close(); if(debug) { cout << "Reading Serials Map:" << endl; } IceDB::Dbi<string, Long, IceDB::IceContext, Ice::OutputStreamPtr> serials(txn, "serials", dbContext, 0); Long serial; IceDB::ReadOnlyCursor<string, Long, IceDB::IceContext, Ice::OutputStreamPtr> serialCursor(serials, txn); while(serialCursor.get(name, serial, MDB_NEXT)) { if(debug) { cout << " NAME = " << name << endl; } data.serials.insert(std::make_pair(name, serial)); } serialCursor.close(); txn.rollback(); env.close(); } Ice::OutputStreamPtr stream = Ice::createOutputStream(communicator(), dbContext.encoding); stream->write("IceGrid"); stream->write(ICE_INT_VERSION); stream->write(data); pair<const Ice::Byte*, const Ice::Byte*> buf = stream->finished(); ofstream fs(dbFile.c_str(), ios::binary); if(fs.fail()) { cerr << "Could not open output file: " << strerror(errno) << endl; return EXIT_FAILURE; } fs.write(reinterpret_cast<const char*>(buf.first), buf.second - buf.first); fs.close(); } } catch(const IceUtil::Exception& ex) { cerr << (import ? "Import" : "Export") << " failed:\n" << ex << endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }
void Ice::PluginManagerI::loadPlugin(const string& name, const string& pluginSpec, StringSeq& cmdArgs) { assert(_communicator); string entryPoint; StringSeq args; if(!pluginSpec.empty()) { // // Split the entire property value into arguments. An entry point containing spaces // must be enclosed in quotes. // try { args = IceUtilInternal::Options::split(pluginSpec); } catch(const IceUtilInternal::BadOptException& ex) { PluginInitializationException e(__FILE__, __LINE__); e.reason = "invalid arguments for plug-in `" + name + "':\n" + ex.reason; throw e; } assert(!args.empty()); // // Shift the arguments. // entryPoint = args[0]; args.erase(args.begin()); // // Convert command-line options into properties. First we // convert the options from the plug-in configuration, then // we convert the options from the application command-line. // PropertiesPtr properties = _communicator->getProperties(); args = properties->parseCommandLineOptions(name, args); cmdArgs = properties->parseCommandLineOptions(name, cmdArgs); } PluginFactory factory = 0; DynamicLibraryPtr library; // // Always check the static plugin factory table first, it takes // precedence over the the entryPoint specified in the plugin // property value. // if(factories) { map<string, PluginFactory>::const_iterator p = factories->find(name); if(p != factories->end()) { factory = p->second; } } // // If we didn't find the factory, get the factory using the entry // point symbol. // if(!factory) { assert(!entryPoint.empty()); library = new DynamicLibrary(); DynamicLibrary::symbol_type sym = library->loadEntryPoint(entryPoint); if(sym == 0) { ostringstream out; string msg = library->getErrorMessage(); out << "unable to load entry point `" << entryPoint << "'"; if(!msg.empty()) { out << ": " + msg; } PluginInitializationException ex(__FILE__, __LINE__); ex.reason = out.str(); throw ex; } #ifdef __IBMCPP__ // xlC warns when casting a void* to function pointer # pragma report(disable, "1540-0216") #endif factory = reinterpret_cast<PluginFactory>(sym); } // // Invoke the factory function. No exceptions can be raised // by the factory function because it's declared extern "C". // PluginPtr plugin(factory(_communicator, name, args)); if(!plugin) { PluginInitializationException e(__FILE__, __LINE__); ostringstream out; out << "failure in entry point `" << entryPoint << "'"; e.reason = out.str(); throw e; } PluginInfo info; info.name = name; info.plugin = plugin; _plugins.push_back(info); if(library) { _libraries->add(library); } }
int main(int argc, char* argv[]) #endif { Ice::StringSeq originalArgs = Ice::argsToStringSeq(argc, argv); assert(originalArgs.size() > 0); const string appName = originalArgs[0]; string dataDir; StringSeq fileSeq; int compress = 1; bool verbose; bool caseInsensitive; IceUtilInternal::Options opts; opts.addOpt("h", "help"); opts.addOpt("v", "version"); opts.addOpt("z", "compress"); opts.addOpt("Z", "no-compress"); opts.addOpt("V", "verbose"); opts.addOpt("i", "case-insensitive"); vector<string> args; try { args = opts.parse(originalArgs); } catch(const IceUtilInternal::BadOptException& e) { cerr << e.reason << endl; usage(appName); return EXIT_FAILURE; } if(opts.isSet("help")) { usage(appName); return EXIT_SUCCESS; } if(opts.isSet("version")) { cout << ICE_STRING_VERSION << endl; return EXIT_SUCCESS; } bool doCompress = opts.isSet("compress"); bool dontCompress = opts.isSet("no-compress"); if(doCompress && dontCompress) { cerr << appName << ": only one of -z and -Z are mutually exclusive" << endl; usage(appName); return EXIT_FAILURE; } if(doCompress) { compress = 2; } else if(dontCompress) { compress = 0; } verbose = opts.isSet("verbose"); caseInsensitive = opts.isSet("case-insensitive"); if(args.empty()) { cerr << appName << ": no data directory specified" << endl; usage(appName); 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 { string absDataDir = dataDir; string cwd; if(IceUtilInternal::getcwd(cwd) != 0) { throw "cannot get the current directory:\n" + IceUtilInternal::lastErrorToString(); } if(!IceUtilInternal::isAbsolutePath(absDataDir)) { absDataDir = simplify(cwd + '/' + absDataDir); } for(StringSeq::iterator p = fileSeq.begin(); p != fileSeq.end(); ++p) { if(!IceUtilInternal::isAbsolutePath(*p)) { *p = cwd + '/' + *p; } } // // We must call simplify() here: under Cygwin, any path starting with // a double slash simply doesn't work. But, if dataDir is "/", we end // up with paths that start with "//" unless we call simplify(). // string absDataDirWithSlash = simplify(absDataDir + '/'); for(StringSeq::iterator p = fileSeq.begin(); p != fileSeq.end(); ++p) { if(p->compare(0, absDataDirWithSlash.size(), absDataDirWithSlash) != 0) { throw "`" + *p + "' is not a path in `" + dataDir + "'"; } p->erase(0, absDataDirWithSlash.size()); } LargeFileInfoSeq infoSeq; if(fileSeq.empty()) { CalcCB calcCB; if(!getFileInfoSeq(absDataDir, compress, verbose ? &calcCB : 0, infoSeq)) { return EXIT_FAILURE; } } else { loadFileInfoSeq(absDataDir, infoSeq); for(StringSeq::iterator p = fileSeq.begin(); p != fileSeq.end(); ++p) { LargeFileInfoSeq partialInfoSeq; CalcCB calcCB; if(!getFileInfoSeqSubDir(absDataDir, *p, compress, verbose ? &calcCB : 0, partialInfoSeq)) { return EXIT_FAILURE; } LargeFileInfoSeq newInfoSeq; newInfoSeq.reserve(infoSeq.size()); set_difference(infoSeq.begin(), infoSeq.end(), partialInfoSeq.begin(), partialInfoSeq.end(), back_inserter(newInfoSeq), FileInfoPathLess()); infoSeq.swap(newInfoSeq); newInfoSeq.clear(); newInfoSeq.reserve(infoSeq.size() + partialInfoSeq.size()); set_union(infoSeq.begin(), infoSeq.end(), partialInfoSeq.begin(), partialInfoSeq.end(), back_inserter(newInfoSeq), FileInfoPathLess()); infoSeq.swap(newInfoSeq); } } if(caseInsensitive) { LargeFileInfoSeq newInfoSeq = infoSeq; sort(newInfoSeq.begin(), newInfoSeq.end(), IFileInfoPathLess()); string ex; LargeFileInfoSeq::iterator p = newInfoSeq.begin(); while((p = adjacent_find(p, newInfoSeq.end(), IFileInfoPathEqual())) != newInfoSeq.end()) { do { ex += '\n' + dataDir + '/' + p->path; ++p; } while(p < newInfoSeq.end() && IFileInfoPathEqual()(*(p - 1), *p)); } if(!ex.empty()) { ex = "duplicate files:" + ex; throw ex; } } saveFileInfoSeq(absDataDir, infoSeq); } catch(const string& ex) { cerr << appName << ": " << ex << endl; return EXIT_FAILURE; } catch(const char* ex) { cerr << appName << ": " << ex << endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }