libextractor  1.11
About: GNU libextractor is a library used to extract meta-data from files of arbitrary type.
  Fossies Dox: libextractor-1.11.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

extractor_plugins.c
Go to the documentation of this file.
1 /*
2  This file is part of libextractor.
3  Copyright (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian Grothoff
4 
5  libextractor is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published
7  by the Free Software Foundation; either version 3, or (at your
8  option) any later version.
9 
10  libextractor is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with libextractor; see the file COPYING. If not, write to the
17  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19  */
20 /**
21  * @file main/extractor_plugins.c
22  * @brief code to load plugins
23  * @author Christian Grothoff
24  */
25 #include "extractor_plugins.h"
26 #include "extractor_plugpath.h"
27 #include "extractor_ipc.h"
28 #include "extractor_logging.h"
29 
30 
31 /**
32  * Try to resolve a plugin function.
33  *
34  * @param lib_handle library to search for the symbol
35  * @param prefix prefix to add
36  * @param sym_name base name for the symbol
37  * @param options set to special options requested by the plugin
38  * @return NULL on error, otherwise pointer to the symbol
39  */
40 static void *
41 get_symbol_with_prefix (void *lib_handle,
42  const char *template,
43  const char *prefix,
44  const char **options)
45 {
46  char *name;
47  void *symbol;
48  const char *sym_name;
49  char *sym;
50  char *dot;
51  const char *(*opt_fun)(void);
52 
53  if (NULL != options)
54  *options = NULL;
55  if (NULL == (sym_name = strrchr (prefix, '_')))
56  return NULL;
57  sym_name++;
58  if (NULL == (sym = strdup (sym_name)))
59  {
60  LOG_STRERROR ("strdup");
61  return NULL;
62  }
63  if (NULL != (dot = strchr (sym, '.')))
64  *dot = '\0';
65  if (NULL == (name = malloc (strlen (sym) + strlen (template) + 1)))
66  {
67  free (sym);
68  return NULL;
69  }
70  sprintf (name,
71  template,
72  sym);
73  /* try without '_' first */
74  symbol = lt_dlsym (lib_handle, name + 1);
75  if (NULL == symbol)
76  {
77  /* now try with the '_' */
78  char *first_error = strdup (lt_dlerror ());
79  symbol = lt_dlsym (lib_handle, name);
80  if (NULL == symbol)
81  {
82  LOG ("Resolving symbol `%s' failed, "
83  "so I tried `%s', but that failed also. Errors are: "
84  "`%s' and `%s'.\n",
85  name + 1,
86  name,
87  first_error == NULL ? "out of memory" : first_error,
88  lt_dlerror ());
89  }
90  if (NULL != first_error)
91  free (first_error);
92  }
93 
94  if ( (NULL != symbol) &&
95  (NULL != options) )
96  {
97  /* get special options */
98  sprintf (name,
99  "_EXTRACTOR_%s_options",
100  sym);
101  /* try without '_' first */
102  opt_fun = lt_dlsym (lib_handle, name + 1);
103  if (NULL == opt_fun)
104  opt_fun = lt_dlsym (lib_handle, name);
105  if (NULL != opt_fun)
106  *options = opt_fun ();
107  }
108  free (sym);
109  free (name);
110  return symbol;
111 }
112 
113 
114 /**
115  * Load a plugin.
116  *
117  * @param plugin plugin to load
118  * @return 0 on success, -1 on error
119  */
120 int
122 {
123 #if WINDOWS
124  wchar_t wlibname[4097];
125  char llibname[4097];
126 #endif
127  lt_dladvise advise;
128 
129  if (EXTRACTOR_OPTION_DISABLED == plugin->flags)
130  return -1;
131  if (NULL == plugin->libname)
132  plugin->libname = EXTRACTOR_find_plugin_ (plugin->short_libname);
133  if (NULL == plugin->libname)
134  {
135  LOG ("Failed to find plugin `%s'\n",
136  plugin->short_libname);
138  return -1;
139  }
140  lt_dladvise_init (&advise);
141  lt_dladvise_ext (&advise);
142  lt_dladvise_local (&advise);
143 #if WINDOWS
144  wlibname[0] = L'\0';
145  llibname[0] = '\0';
146  if ( (MultiByteToWideChar (CP_UTF8, 0, plugin->libname, -1,
147  wlibname, sizeof (wlibname)) <= 0) ||
148  (WideCharToMultiByte (CP_ACP, 0, wlibname, -1,
149  llibname, sizeof (llibname), NULL, NULL) < 0) )
150  {
151  LOG ("Loading `%s' plugin failed: %s\n",
152  plugin->short_libname,
153  "can't convert plugin name to local encoding");
154  free (plugin->libname);
155  plugin->libname = NULL;
157  return -1;
158  }
159  plugin->libraryHandle = lt_dlopenadvise (llibname,
160  advise);
161 #else
162  plugin->libraryHandle = lt_dlopenadvise (plugin->libname,
163  advise);
164 #endif
165  lt_dladvise_destroy (&advise);
166  if (NULL == plugin->libraryHandle)
167  {
168  LOG ("Loading `%s' plugin failed (using name `%s'): %s\n",
169  plugin->short_libname,
170  plugin->libname,
171  lt_dlerror ());
172  free (plugin->libname);
173  plugin->libname = NULL;
175  return -1;
176  }
178  "_EXTRACTOR_%s_extract_method",
179  plugin->libname,
180  &plugin->specials);
181  if (NULL == plugin->extract_method)
182  {
183  LOG ("Resolving `extract' method of plugin `%s' failed: %s\n",
184  plugin->short_libname,
185  lt_dlerror ());
186  lt_dlclose (plugin->libraryHandle);
187  free (plugin->libname);
188  plugin->libname = NULL;
190  return -1;
191  }
192  return 0;
193 }
194 
195 
196 /**
197  * Add a library for keyword extraction.
198  *
199  * @param prev the previous list of libraries, may be NULL
200  * @param library the name of the library
201  * @param options options to pass to the plugin
202  * @param flags options to use
203  * @return the new list of libraries, equal to prev iff an error occurred
204  */
205 struct EXTRACTOR_PluginList *
207  const char *library,
208  const char *options,
210 {
211  struct EXTRACTOR_PluginList *plugin;
212  struct EXTRACTOR_PluginList *pos;
213  char *libname;
214 
215  for (pos = prev; NULL != pos; pos = pos->next)
216  if (0 == strcmp (pos->short_libname, library))
217  return prev;
218  /* no change, library already loaded */
219  if (NULL == (libname = EXTRACTOR_find_plugin_ (library)))
220  {
221  LOG ("Could not load plugin `%s'\n",
222  library);
223  return prev;
224  }
225  if (NULL == (plugin = malloc (sizeof (struct EXTRACTOR_PluginList))))
226  return prev;
227  memset (plugin, 0, sizeof (struct EXTRACTOR_PluginList));
228  plugin->next = prev;
229  if (NULL == (plugin->short_libname = strdup (library)))
230  {
231  free (plugin);
232  return NULL;
233  }
234  plugin->libname = libname;
235  plugin->flags = flags;
236  if (NULL != options)
237  plugin->plugin_options = strdup (options);
238  else
239  plugin->plugin_options = NULL;
240  plugin->seek_request = -1;
241  return plugin;
242 }
243 
244 
245 /**
246  * Load multiple libraries as specified by the user.
247  *
248  * @param config a string given by the user that defines which
249  * libraries should be loaded. Has the format
250  * "[[-]LIBRARYNAME[(options)][:[-]LIBRARYNAME[(options)]]]*".
251  * For example, 'mp3:ogg.so' loads the
252  * mp3 and the ogg library. The '-' before the LIBRARYNAME
253  * indicates that the library should be removed from
254  * the library list.
255  * @param prev the previous list of libraries, may be NULL
256  * @param flags options to use
257  * @return the new list of libraries, equal to prev iff an error occurred
258  * or if config was empty (or NULL).
259  */
260 struct EXTRACTOR_PluginList *
262  const char *config,
264 {
265  char *cpy;
266  size_t pos;
267  size_t last;
268  ssize_t lastconf;
269  size_t len;
270 
271  if (NULL == config)
272  return prev;
273  if (NULL == (cpy = strdup (config)))
274  return prev;
275  len = strlen (config);
276  pos = 0;
277  last = 0;
278  lastconf = 0;
279  while (pos < len)
280  {
281  while ( (':' != cpy[pos]) &&
282  ('\0' != cpy[pos]) &&
283  ('(' != cpy[pos]) )
284  pos++;
285  switch (cpy[pos])
286  {
287  case '(':
288  cpy[pos++] = '\0'; /* replace '(' by termination */
289  lastconf = pos; /* start config from here, after (. */
290  while ( ('\0' != cpy[pos]) &&
291  (')' != cpy[pos]))
292  pos++; /* config until ) or EOS. */
293  if (')' == cpy[pos])
294  {
295  cpy[pos++] = '\0'; /* write end of config here. */
296  while ( (':' != cpy[pos]) &&
297  ('\0' != cpy[pos]) )
298  pos++; /* forward until real end of string found. */
299  cpy[pos++] = '\0';
300  }
301  else
302  {
303  cpy[pos++] = '\0'; /* end of string. */
304  }
305  break;
306  case ':':
307  case '\0':
308  lastconf = -1; /* NULL config when no (). */
309  cpy[pos++] = '\0'; /* replace ':' by termination */
310  break;
311  default:
312  ABORT ();
313  }
314  if ('-' == cpy[last])
315  {
316  last++;
317  prev = EXTRACTOR_plugin_remove (prev,
318  &cpy[last]);
319  }
320  else
321  {
322  prev = EXTRACTOR_plugin_add (prev,
323  &cpy[last],
324  (-1 != lastconf) ? &cpy[lastconf] : NULL,
325  flags);
326  }
327  last = pos;
328  }
329  free (cpy);
330  return prev;
331 }
332 
333 
334 /**
335  * Remove a plugin from a list.
336  *
337  * @param prev the current list of plugins
338  * @param library the name of the plugin to remove
339  * @return the reduced list, unchanged if the plugin was not loaded
340  */
341 struct EXTRACTOR_PluginList *
343  const char *library)
344 {
345  struct EXTRACTOR_PluginList *pos;
346  struct EXTRACTOR_PluginList *first;
347 
348  pos = prev;
349  first = prev;
350  while ( (NULL != pos) &&
351  (0 != strcmp (pos->short_libname, library)) )
352  {
353  prev = pos;
354  pos = pos->next;
355  }
356  if (NULL == pos)
357  {
358  LOG ("Unloading plugin `%s' failed!\n",
359  library);
360  return first;
361  }
362  /* found, close library */
363  if (first == pos)
364  first = pos->next;
365  else
366  prev->next = pos->next;
367  if (NULL != pos->channel)
369  if ( (NULL != pos->shm) &&
370  (0 == EXTRACTOR_IPC_shared_memory_change_rc_ (pos->shm, -1)) )
372  if (NULL != pos->short_libname)
373  free (pos->short_libname);
374  if (NULL != pos->libname)
375  free (pos->libname);
376  free (pos->plugin_options);
377  if (NULL != pos->libraryHandle)
378  lt_dlclose (pos->libraryHandle);
379  free (pos);
380  return first;
381 }
382 
383 
384 /**
385  * Remove all plugins from the given list (destroys the list).
386  *
387  * @param plugin the list of plugins
388  */
389 void
391 {
392  while (NULL != plugins)
393  plugins = EXTRACTOR_plugin_remove (plugins, plugins->short_libname);
394 }
395 
396 
397 /* end of extractor_plugins.c */
EXTRACTOR_Options
Definition: extractor.h:57
@ EXTRACTOR_OPTION_DISABLED
Definition: extractor.h:83
IPC with plugin (OS-independent API)
unsigned int EXTRACTOR_IPC_shared_memory_change_rc_(struct EXTRACTOR_SharedMemory *shm, int delta)
void EXTRACTOR_IPC_shared_memory_destroy_(struct EXTRACTOR_SharedMemory *shm)
void EXTRACTOR_IPC_channel_destroy_(struct EXTRACTOR_Channel *channel)
logging API for GNU libextractor
#define LOG(...)
#define LOG_STRERROR(syscall)
int EXTRACTOR_plugin_load_(struct EXTRACTOR_PluginList *plugin)
struct EXTRACTOR_PluginList * EXTRACTOR_plugin_remove(struct EXTRACTOR_PluginList *prev, const char *library)
void EXTRACTOR_plugin_remove_all(struct EXTRACTOR_PluginList *plugins)
struct EXTRACTOR_PluginList * EXTRACTOR_plugin_add_config(struct EXTRACTOR_PluginList *prev, const char *config, enum EXTRACTOR_Options flags)
static void * get_symbol_with_prefix(void *lib_handle, const char *template, const char *prefix, const char **options)
struct EXTRACTOR_PluginList * EXTRACTOR_plugin_add(struct EXTRACTOR_PluginList *prev, const char *library, const char *options, enum EXTRACTOR_Options flags)
code to load plugins
char * EXTRACTOR_find_plugin_(const char *short_name)
determine path where plugins are installed
#define NULL
Definition: getopt1.c:60
const char * name
#define ABORT()
Definition: platform.h:77
struct EXTRACTOR_Channel * channel
EXTRACTOR_extract_method extract_method
struct EXTRACTOR_PluginList * next
struct EXTRACTOR_SharedMemory * shm
enum EXTRACTOR_Options flags