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