CLAM-Development  1.4.0
RunTimeLibraryLoader.cxx
Go to the documentation of this file.
2 
3 #include <iostream>
4 #include <cstdlib>
5 #include <dirent.h>
6 #ifdef WIN32
7 # include "CLAM_windows.h"
8 #else
9 # include <dlfcn.h>
10 #endif
11 
12 #include <fstream>
13 
14 #include "ProcessingFactory.hxx"
15 
16 static bool debug = false;
17 
18 
20 {
22  std::list<std::string> usedLibraries=GetUsedLibraries();
23  std::list<std::string>::const_iterator itLibraries;
24  // iterate on used libraries
25  for (itLibraries=usedLibraries.begin();itLibraries!=usedLibraries.end();itLibraries++)
26  {
28  keys=factory.GetKeys("library",(*itLibraries));
29  CLAM::ProcessingFactory::Keys::const_iterator itKeys;
30  // iterate on used creators of the library
31  for(itKeys=keys.begin();itKeys!=keys.end();itKeys++)
32  {
33  factory.DeleteCreator(*itKeys);
34  }
36  {
37  void * handle=GetLibraryHandler(*itLibraries);
38  ReleaseLibraryHandler(handle,(*itLibraries));
39  }
40  }
41  Load();
42 }
43 
45 {
47  std::list<std::string> usedLibraries;
48  CLAM::ProcessingFactory::Values librariesValues=factory.GetSetOfValues("library");
49  CLAM::ProcessingFactory::Values::const_iterator itLibraries;
50  for (itLibraries=librariesValues.begin();itLibraries!=librariesValues.end();itLibraries++)
51  {
52  const std::string & path=getPathFromFullFileName(*itLibraries);
53  if (IsOnPath(path))
54  usedLibraries.push_back(*itLibraries);
55  }
56  return usedLibraries;
57 }
58 
59 bool RunTimeLibraryLoader::IsOnPath(const std::string & path) const
60 {
61  std::string paths = GetPaths();
62  std::vector <std::string> environmentPaths = SplitPathVariable(paths);
63  for (unsigned i=0; i<environmentPaths.size(); i++)
64  {
65  if (environmentPaths[i]==path)
66  return true;
67  }
68  return false;
69 }
70 
72 {
73  std::string path = GetPaths();
74  // for each path, load libraries
75  std::vector <std::string> environmentPaths = SplitPathVariable(path);
76  for (unsigned i=0; i<environmentPaths.size(); i++)
77  {
78  debug && std::cout << "RunTimeLibraryLoader: Scanning for libraries in " << environmentPaths[i] << std::endl;
79  LoadLibrariesFromPath(environmentPaths[i]);
80  }
81 }
82 void RunTimeLibraryLoader::LoadLibrariesFromPath(const std::string & path) const
83 {
84  DIR* dir = opendir(path.c_str());
85  if (!dir) return;
86  while ( struct dirent * dirEntry = readdir(dir) )
87  {
88  std::string pluginFilename(dirEntry->d_name);
89  if(pluginFilename == "." || pluginFilename == "..")
90  continue;
91  debug && std::cout << "RunTimeLibraryLoader: Found file " << pluginFilename << std::endl;
92  std::string pluginFullFilename(path + std::string("/") + pluginFilename);
93  void * handle = FullyLoadLibrary(pluginFullFilename);
94 
95  // TODO: throw exception and have catch in main()
96  if (handle == NULL)
97  {
98  std::cout << "Error loading: " << pluginFullFilename
99  << " reason: " << LibraryLoadError()
100  << std::endl;
101  }
102 
103  SetupLibrary( handle, pluginFullFilename );
104  }
105  closedir(dir);
106 }
107 
108 
109 void * RunTimeLibraryLoader::FullyLoadLibrary(const std::string & libraryPath)
110 {
111 #ifdef WIN32
112 // SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
113 // SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX );
114  return LoadLibrary(libraryPath.c_str());
115 #else
116  return dlopen( libraryPath.c_str(), RTLD_NOW);
117 #endif
118 }
119 
120 
121 void * RunTimeLibraryLoader::LazyLoadLibrary(const std::string & libraryPath)
122 {
123 #ifdef WIN32
124 // TODO: if windows allow it, add here a lazy load
125  return 0;
126 #else
127  return dlopen( libraryPath.c_str(), RTLD_LAZY);
128 #endif
129 }
130 
131 
132 void * RunTimeLibraryLoader::GetSymbol(void * libraryHandler, const std::string & symbolName)
133 {
134 #ifdef WIN32
135  return (void*) GetProcAddress((HMODULE)libraryHandler, symbolName.c_str());
136 #else
137  return dlsym(libraryHandler, symbolName.c_str());
138 #endif
139 }
140 
141 
142 void * RunTimeLibraryLoader::GetLibraryHandler(const std::string & libraryPath) const
143 {
144 #ifdef WIN32 //TODO: does windows have an equivalent method to have the handler?
145  return 0;
146 #else
147  return dlopen (libraryPath.c_str(), RTLD_NOLOAD);
148 #endif
149 }
150 
151 //TODO: the name argument will be used to check on the plugins map
152 // returns false on success, true on fail
153 bool RunTimeLibraryLoader::ReleaseLibraryHandler(void* handle, const std::string pluginFullFilename)
154 {
155  if (!handle)
156  {
157  std::cout<<"Cannot release an empty handle!"<<std::endl;
158  return true;
159  }
160 #ifdef WIN32
161  return !FreeLibrary((HMODULE)handle);
162 #else
163  return dlclose(handle);
164 #endif
165 }
166 
168 {
169 #ifdef WIN32
170  LPVOID lpMsgBuf;
171  FormatMessage(
172  FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
173  NULL,
174  GetLastError(),
175  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
176  (LPTSTR) &lpMsgBuf,
177  0, NULL );
178  std::string message((char*)lpMsgBuf);
179  LocalFree(lpMsgBuf);
180  return message;
181 #else
182  return dlerror();
183 #endif
184 }
185 
186 const std::string RunTimeLibraryLoader::FileOfSymbol (void * symbolAddress)
187 {
188 #ifdef WIN32
189  char pluginpath[1024];
190  HMODULE module;
191  GetModuleHandleExA(
192  GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
193  (char *)symbolAddress,
194  &module);
195  GetModuleFileNameA(module, pluginpath, 1024);
196  FreeLibrary(module);
197  return pluginpath;
198 #else
199  Dl_info info;
200  int ok=dladdr(symbolAddress,&info);
201  if (ok)
202  return info.dli_fname;
203 #endif
204  return "";
205 }
206 
207 std::vector<std::string> RunTimeLibraryLoader::SplitPathVariable(const std::string & pathVariable) const
208 {
209  std::string content=pathVariable;
210  std::vector<std::string> result;
211  while (!content.empty())
212  {
213  size_t separatorPos = content.find(pathSeparator());
214  if (separatorPos == std::string::npos)
215  {
216  result.push_back(content);
217  break;
218  }
219  result.push_back(content.substr(0, separatorPos));
220  content = content.substr(separatorPos+1);
221  }
222  return result;
223 }
224 
225 const std::string RunTimeLibraryLoader::GetPaths() const
226 {
227  const char * envPath = getenv(pathEnvironmentVar());
228  const char * envHome = getenv("HOME");
229  std::string path = envPath ? envPath : "";
230  if (envHome)
231  {
232  path += std::string(path.empty()? "":pathSeparator()) + envHome + homePath();
233  }
234  // add standardPath to the env path string (i.e. path1:path2)
235  for (const char ** standardPath=standardPaths(); *standardPath; standardPath++)
236  path += std::string(path.empty()? "":pathSeparator()) + *standardPath;
237  return path;
238 }
239 
240 
241 const std::string RunTimeLibraryLoader::CompletePathFor(const std::string & subpathAndName) const
242 {
243  std::string paths=GetPaths();
244  std::vector <std::string> environmentPaths = SplitPathVariable(paths);
245  for (unsigned i=0; i<environmentPaths.size(); i++)
246  {
247  // get file name:
248  std::string fileName = subpathAndName.substr( subpathAndName.rfind("/")+1);
249  // testDir= root_path + subpath:
250  std::string testDir = environmentPaths[i] + "/" + subpathAndName.substr(0, subpathAndName.size()-fileName.size());
251  // check if directory exists:
252  DIR* dir = opendir(testDir.c_str());
253  if (not dir)
254  continue; // directory doesn't match, skip
255  closedir(dir);
256  // check if file exists:
257  std::fstream fin;
258  std::string completeFileName=testDir+fileName;
259  fin.open(completeFileName.c_str(),std::ios::in);
260  if (not fin.is_open())
261  continue; // file doesn't exist, skip
262  fin.close();
263  return completeFileName;
264  }
265  return "";
266 }