CLAM-Development
1.1
|
00001 #include "RunTimeLibraryLoader.hxx" 00002 00003 #include <iostream> 00004 #include <cstdlib> 00005 #include <dirent.h> 00006 #ifdef WIN32 00007 # include <windows.h> 00008 # undef GetClassName 00009 #else 00010 # include <dlfcn.h> 00011 #endif 00012 00013 #include <fstream> 00014 00015 #include "ProcessingFactory.hxx" 00016 00017 00018 void RunTimeLibraryLoader::ReLoad() 00019 { 00020 CLAM::ProcessingFactory& factory = CLAM::ProcessingFactory::GetInstance(); 00021 std::list<std::string> usedLibraries=GetUsedLibraries(); 00022 std::list<std::string>::const_iterator itLibraries; 00023 // iterate on used libraries 00024 for (itLibraries=usedLibraries.begin();itLibraries!=usedLibraries.end();itLibraries++) 00025 { 00026 CLAM::ProcessingFactory::Keys keys; 00027 keys=factory.GetKeys("library",(*itLibraries)); 00028 CLAM::ProcessingFactory::Keys::const_iterator itKeys; 00029 // iterate on used creators of the library 00030 for(itKeys=keys.begin();itKeys!=keys.end();itKeys++) 00031 { 00032 factory.DeleteCreator(*itKeys); 00033 } 00034 if (needReleaseHandlerOnReload()) 00035 { 00036 void * handle=GetLibraryHandler(*itLibraries); 00037 ReleaseLibraryHandler(handle,(*itLibraries)); 00038 } 00039 } 00040 Load(); 00041 } 00042 00043 const std::list<std::string> RunTimeLibraryLoader::GetUsedLibraries() 00044 { 00045 CLAM::ProcessingFactory& factory = CLAM::ProcessingFactory::GetInstance(); 00046 std::list<std::string> usedLibraries; 00047 CLAM::ProcessingFactory::Values librariesValues=factory.GetSetOfValues("library"); 00048 CLAM::ProcessingFactory::Values::const_iterator itLibraries; 00049 for (itLibraries=librariesValues.begin();itLibraries!=librariesValues.end();itLibraries++) 00050 { 00051 const std::string & path=getPathFromFullFileName(*itLibraries); 00052 if (IsOnPath(path)) 00053 usedLibraries.push_back(*itLibraries); 00054 } 00055 return usedLibraries; 00056 } 00057 00058 bool RunTimeLibraryLoader::IsOnPath(const std::string & path) const 00059 { 00060 std::string paths = GetPaths(); 00061 std::vector <std::string> environmentPaths = SplitPathVariable(paths); 00062 for (unsigned i=0; i<environmentPaths.size(); i++) 00063 { 00064 if (environmentPaths[i]==path) 00065 return true; 00066 } 00067 return false; 00068 } 00069 00070 const std::string RunTimeLibraryLoader::FileOfSymbol (void * symbolAddress) 00071 { 00072 #ifndef WIN32 00073 Dl_info info; 00074 int ok=dladdr(symbolAddress,&info); 00075 if (ok) 00076 return info.dli_fname; 00077 #endif 00078 return ""; 00079 } 00080 00081 void RunTimeLibraryLoader::Load() const 00082 { 00083 std::string path = GetPaths(); 00084 // for each path, load libraries 00085 std::vector <std::string> environmentPaths = SplitPathVariable(path); 00086 for (unsigned i=0; i<environmentPaths.size(); i++) 00087 { 00088 LoadLibrariesFromPath(environmentPaths[i]); 00089 } 00090 } 00091 00092 void RunTimeLibraryLoader::LoadLibrariesFromPath(const std::string & path) const 00093 { 00094 DIR* dir = opendir(path.c_str()); 00095 if (!dir) 00096 { 00097 return; 00098 } 00099 while ( struct dirent * dirEntry = readdir(dir) ) 00100 { 00101 std::string pluginFilename(dirEntry->d_name); 00102 if(pluginFilename == "." || pluginFilename == "..") 00103 continue; 00104 std::string pluginFullFilename(path + std::string("/") + pluginFilename); 00105 void * handle = FullyLoadLibrary(pluginFullFilename); 00106 SetupLibrary( handle, pluginFullFilename ); 00107 // std::cout<<"loaded plugin: "<<pluginFullFilename<<std::endl; 00108 } 00109 closedir(dir); 00110 } 00111 00112 00113 void * RunTimeLibraryLoader::FullyLoadLibrary(const std::string & libraryPath) 00114 { 00115 // std::cout << "[" << libraryType() << " Plugins] FullyLoading " << libraryPath << std::endl; 00116 #ifdef WIN32 00117 // SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | 00118 // SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX ); 00119 return LoadLibrary(libraryPath.c_str()); 00120 #else 00121 return dlopen( libraryPath.c_str(), RTLD_NOW); 00122 #endif 00123 } 00124 00125 00126 void * RunTimeLibraryLoader::LazyLoadLibrary(const std::string & libraryPath) 00127 { 00128 #ifdef WIN32 00129 // TODO: if windows allow it, add here a lazy load 00130 return 0; 00131 #else 00132 return dlopen( libraryPath.c_str(), RTLD_LAZY); 00133 #endif 00134 } 00135 00136 00137 00138 void * RunTimeLibraryLoader::GetLibraryHandler(const std::string & libraryPath) const 00139 { 00140 #ifdef WIN32 //TODO: does windows have an equivalent method to have the handler? 00141 return 0; 00142 #else 00143 return dlopen (libraryPath.c_str(), RTLD_NOLOAD); 00144 #endif 00145 } 00146 00147 //TODO: the name argument will be used to check on the plugins map 00148 // returns false on success, true on fail 00149 bool RunTimeLibraryLoader::ReleaseLibraryHandler(void* handle, const std::string pluginFullFilename) 00150 { 00151 if (!handle) 00152 { 00153 std::cout<<"Cannot release an empty handle!"<<std::endl; 00154 return true; 00155 } 00156 #ifdef WIN32 00157 return (!FreeLibrary((HMODULE)handle)); 00158 #else 00159 return (dlclose(handle)); 00160 #endif 00161 } 00162 00163 const std::string RunTimeLibraryLoader::LibraryLoadError() 00164 { 00165 #ifdef WIN32 00166 LPVOID lpMsgBuf; 00167 FormatMessage( 00168 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 00169 NULL, 00170 GetLastError(), 00171 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 00172 (LPTSTR) &lpMsgBuf, 00173 0, NULL ); 00174 std::string message((char*)lpMsgBuf); 00175 LocalFree(lpMsgBuf); 00176 return message; 00177 #else 00178 return dlerror(); 00179 #endif 00180 } 00181 std::vector<std::string> RunTimeLibraryLoader::SplitPathVariable(const std::string & pathVariable) const 00182 { 00183 std::string content=pathVariable; 00184 std::vector<std::string> result; 00185 while (!content.empty()) 00186 { 00187 size_t separatorPos = content.find(pathSeparator()); 00188 if (separatorPos == std::string::npos) 00189 { 00190 result.push_back(content); 00191 break; 00192 } 00193 result.push_back(content.substr(0, separatorPos)); 00194 content = content.substr(separatorPos+1); 00195 } 00196 return result; 00197 } 00198 00199 const std::string RunTimeLibraryLoader::GetPaths() const 00200 { 00201 const char * envPath = getenv(pathEnvironmentVar()); 00202 const char * envHome = getenv("HOME"); 00203 std::string path = envPath ? envPath : ""; 00204 if (envHome) 00205 { 00206 path += std::string(path.empty()? "":pathSeparator()) + envHome + homePath(); 00207 } 00208 // add standardPath to the env path string (i.e. path1:path2) 00209 for (const char ** standardPath=standardPaths(); *standardPath; standardPath++) 00210 path += std::string(path.empty()? "":pathSeparator()) + *standardPath; 00211 return path; 00212 } 00213 00214 00215 const std::string RunTimeLibraryLoader::CompletePathFor(const std::string & subpathAndName) const 00216 { 00217 std::string paths=GetPaths(); 00218 std::vector <std::string> environmentPaths = SplitPathVariable(paths); 00219 for (unsigned i=0; i<environmentPaths.size(); i++) 00220 { 00221 // get file name: 00222 std::string fileName = subpathAndName.substr( subpathAndName.rfind("/")+1); 00223 // testDir= root_path + subpath: 00224 std::string testDir = environmentPaths[i] + "/" + subpathAndName.substr(0, subpathAndName.size()-fileName.size()); 00225 // check if directory exists: 00226 DIR* dir = opendir(testDir.c_str()); 00227 if (not dir) 00228 continue; // directory doesn't match, skip 00229 closedir(dir); 00230 // check if file exists: 00231 std::fstream fin; 00232 std::string completeFileName=testDir+fileName; 00233 fin.open(completeFileName.c_str(),std::ios::in); 00234 if (not fin.is_open()) 00235 continue; // file doesn't exist, skip 00236 fin.close(); 00237 return completeFileName; 00238 } 00239 return ""; 00240 }