"Fossies" - the Fresh Open Source Software Archive

Member "libextractor-1.11/src/main/extractor_plugins.c" (30 Jan 2021, 11165 Bytes) of package /linux/privat/libextractor-1.11.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "extractor_plugins.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.10_vs_1.11.

    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
  121 EXTRACTOR_plugin_load_ (struct EXTRACTOR_PluginList *plugin)
  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);
  137     plugin->flags = EXTRACTOR_OPTION_DISABLED;
  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;
  156     plugin->flags = EXTRACTOR_OPTION_DISABLED;
  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;
  174     plugin->flags = EXTRACTOR_OPTION_DISABLED;
  175     return -1;
  176   }
  177   plugin->extract_method = get_symbol_with_prefix (plugin->libraryHandle,
  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;
  189     plugin->flags = EXTRACTOR_OPTION_DISABLED;
  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 *
  206 EXTRACTOR_plugin_add (struct EXTRACTOR_PluginList *prev,
  207                       const char *library,
  208                       const char *options,
  209                       enum EXTRACTOR_Options flags)
  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 *
  261 EXTRACTOR_plugin_add_config (struct EXTRACTOR_PluginList *prev,
  262                              const char *config,
  263                              enum EXTRACTOR_Options flags)
  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 *
  342 EXTRACTOR_plugin_remove (struct EXTRACTOR_PluginList *prev,
  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)
  368     EXTRACTOR_IPC_channel_destroy_ (pos->channel);
  369   if ( (NULL != pos->shm) &&
  370        (0 == EXTRACTOR_IPC_shared_memory_change_rc_ (pos->shm, -1)) )
  371     EXTRACTOR_IPC_shared_memory_destroy_ (pos->shm);
  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
  390 EXTRACTOR_plugin_remove_all (struct EXTRACTOR_PluginList *plugins)
  391 {
  392   while (NULL != plugins)
  393     plugins = EXTRACTOR_plugin_remove (plugins, plugins->short_libname);
  394 }
  395 
  396 
  397 /* end of extractor_plugins.c */