"Fossies" - the Fresh Open Source Software Archive

Member "libgphoto2-2.5.27/libgphoto2_port/libgphoto2_port/gphoto2-port-info-list.c" (19 Oct 2020, 14283 Bytes) of package /linux/privat/libgphoto2-2.5.27.tar.bz2:


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 "gphoto2-port-info-list.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.5.26_vs_2.5.27.

    1 /** \file
    2  *
    3  * \author Copyright 2001 Lutz Mueller <lutz@users.sf.net>
    4  *
    5  * \par License
    6  * This library is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU Lesser General Public
    8  * License as published by the Free Software Foundation; either
    9  * version 2 of the License, or (at your option) any later version.
   10  *
   11  * \par
   12  * This library is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15  * Lesser General Public License for more details.
   16  *
   17  * \par
   18  * You should have received a copy of the GNU Lesser General Public
   19  * License along with this library; if not, write to the
   20  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   21  * Boston, MA  02110-1301  USA
   22  */
   23 #define _GNU_SOURCE
   24 #define _DARWIN_C_SOURCE
   25 
   26 #include "config.h"
   27 
   28 #include <gphoto2/gphoto2-port-info-list.h>
   29 
   30 #include <stdlib.h>
   31 #include <string.h>
   32 #include <stdio.h>
   33 #ifdef HAVE_REGEX
   34 #include <regex.h>
   35 #elif defined(_MSC_VER)
   36 #pragma message("We need regex.h, but it has not been detected.")
   37 #else
   38 #warning We need regex.h, but it has not been detected.
   39 #endif
   40 
   41 #include <ltdl.h>
   42 
   43 #include <gphoto2/gphoto2-port-result.h>
   44 #include <gphoto2/gphoto2-port-library.h>
   45 #include <gphoto2/gphoto2-port-log.h>
   46 
   47 #include "gphoto2-port-info.h"
   48 
   49 #ifdef ENABLE_NLS
   50 #  include <libintl.h>
   51 #  undef _
   52 #  define _(String) dgettext (GETTEXT_PACKAGE, String)
   53 #  ifdef gettext_noop
   54 #    define N_(String) gettext_noop (String)
   55 #  else
   56 #    define N_(String) (String)
   57 #  endif
   58 #else
   59 #  define textdomain(String) (String)
   60 #  define gettext(String) (String)
   61 #  define dgettext(Domain,Message) (Message)
   62 #  define dcgettext(Domain,Message,Type) (Message)
   63 #  define bindtextdomain(Domain,Directory) (Domain)
   64 #  define bind_textdomain_codeset(Domain,codeset) (codeset)
   65 #  define ngettext(String1,String2,Count) ((Count==1)?String1:String2)
   66 #  define _(String) (String)
   67 #  define N_(String) (String)
   68 #endif
   69 
   70 /**
   71  * \internal GPPortInfoList:
   72  *
   73  * The internals of this list are private.
   74  **/
   75 struct _GPPortInfoList {
   76     GPPortInfo *info;
   77     unsigned int count;
   78     unsigned int iolib_count;
   79 };
   80 
   81 #define CR(x)         {int r=(x);if (r<0) return (r);}
   82 
   83 
   84 /**
   85  * \brief Specify codeset for translations
   86  *
   87  * This function specifies the codeset that are used for the translated
   88  * strings that are passed back by the libgphoto2_port functions.
   89  *
   90  * This function is called by the gp_message_codeset() function, there is
   91  * no need to call it yourself.
   92  *
   93  * \param codeset new codeset to use
   94  * \return the previous codeset
   95  */
   96 const char*
   97 gp_port_message_codeset (const char *codeset) {
   98     return bind_textdomain_codeset (GETTEXT_PACKAGE, codeset);
   99 }
  100 
  101 /**
  102  * \brief Create a new GPPortInfoList
  103  *
  104  * \param list pointer to a GPPortInfoList* which is allocated
  105  *
  106  * Creates a new list which can later be filled with port infos (#GPPortInfo)
  107  * using #gp_port_info_list_load.
  108  *
  109  * \return a gphoto2 error code
  110  **/
  111 int
  112 gp_port_info_list_new (GPPortInfoList **list)
  113 {
  114     C_PARAMS (list);
  115 
  116     /*
  117      * We put this in here because everybody needs to call this function
  118      * before accessing ports...
  119      */
  120     bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
  121 
  122     C_MEM (*list = calloc (1, sizeof (GPPortInfoList)));
  123 
  124     return (GP_OK);
  125 }
  126 
  127 /**
  128  * \brief Free a GPPortInfo list
  129  * \param list a #GPPortInfoList
  130  *
  131  * Frees a GPPortInfoList structure and its internal data structures.
  132  *
  133  * \return a gphoto2 error code
  134  **/
  135 int
  136 gp_port_info_list_free (GPPortInfoList *list)
  137 {
  138     C_PARAMS (list);
  139 
  140     if (list->info) {
  141         unsigned int i;
  142 
  143         for (i=0;i<list->count;i++) {
  144             free (list->info[i]->name);
  145             list->info[i]->name = NULL;
  146             free (list->info[i]->path);
  147             list->info[i]->path = NULL;
  148             free (list->info[i]->library_filename);
  149             list->info[i]->library_filename = NULL;
  150             free (list->info[i]);
  151         }
  152         free (list->info);
  153         list->info = NULL;
  154     }
  155     list->count = 0;
  156 
  157     free (list);
  158 
  159     return (GP_OK);
  160 }
  161 
  162 /**
  163  * \brief Append a portinfo to the port information list
  164  *
  165  * \param list a #GPPortInfoList
  166  * \param info the info to append
  167  *
  168  * Appends an entry to the list. This function is typically called by
  169  * an io-driver during #gp_port_library_list. If you leave info.name blank,
  170  * #gp_port_info_list_lookup_path will try to match non-existent paths
  171  * against info.path and - if successful - will append this entry to the
  172  * list.
  173  *
  174  * \return A gphoto2 error code, or an index into the port list (excluding generic entries).
  175  *         which can be used for gp_port_info_list_get_info.
  176  **/
  177 int
  178 gp_port_info_list_append (GPPortInfoList *list, GPPortInfo info)
  179 {
  180     unsigned int generic, i;
  181 
  182     C_PARAMS (list);
  183 
  184     C_MEM (list->info = realloc (list->info, sizeof (GPPortInfo) * (list->count + 1)));
  185     list->count++;
  186     list->info[list->count - 1] = info;
  187 
  188     /* Ignore generic entries */
  189     for (generic = i = 0; i < list->count; i++)
  190         if (!strlen (list->info[i]->name))
  191             generic++;
  192         return (list->count - 1 - generic);
  193 }
  194 
  195 
  196 static int
  197 foreach_func (const char *filename, lt_ptr data)
  198 {
  199     GPPortInfoList *list = data;
  200     lt_dlhandle lh;
  201     GPPortLibraryType lib_type;
  202     GPPortLibraryList lib_list;
  203     GPPortType type;
  204     unsigned int j, old_size = list->count;
  205     int result;
  206 
  207     GP_LOG_D ("Called for filename '%s'.", filename );
  208 
  209     lh = lt_dlopenext (filename);
  210     if (!lh) {
  211         GP_LOG_D ("Could not load '%s': '%s'.", filename, lt_dlerror ());
  212         return (0);
  213     }
  214 
  215     lib_type = lt_dlsym (lh, "gp_port_library_type");
  216     lib_list = lt_dlsym (lh, "gp_port_library_list");
  217     if (!lib_type || !lib_list) {
  218         GP_LOG_D ("Could not find some functions in '%s': '%s'.",
  219             filename, lt_dlerror ());
  220         lt_dlclose (lh);
  221         return (0);
  222     }
  223 
  224     type = lib_type ();
  225     for (j = 0; j < list->count; j++)
  226         if (list->info[j]->type == type)
  227             break;
  228     if (j != list->count) {
  229         GP_LOG_D ("'%s' already loaded", filename);
  230         lt_dlclose (lh);
  231         return (0);
  232     }
  233 
  234     result = lib_list (list);
  235 #if !defined(VALGRIND)
  236     lt_dlclose (lh);
  237 #endif
  238     if (result < 0) {
  239         GP_LOG_E ("Error during assembling of port list: '%s' (%d).",
  240             gp_port_result_as_string (result), result);
  241     }
  242 
  243     if (old_size != list->count) {
  244         /*
  245          * It doesn't matter if lib_list returned a failure code,
  246          * at least some entries were added
  247          */
  248         list->iolib_count++;
  249 
  250         for (j = old_size; j < list->count; j++){
  251             GP_LOG_D ("Loaded '%s' ('%s') from '%s'.",
  252                 list->info[j]->name, list->info[j]->path,
  253                 filename);
  254             list->info[j]->library_filename = strdup (filename);
  255         }
  256     }
  257 
  258     return (0);
  259 }
  260 
  261 
  262 /**
  263  * \brief Load system ports
  264  *
  265  * \param list a #GPPortInfoList
  266  *
  267  * Searches the system for io-drivers and appends them to the list. You would
  268  * normally call this function once after #gp_port_info_list_new and then
  269  * use this list in order to supply #gp_port_set_info with parameters or to do
  270  * autodetection.
  271  *
  272  * \return a gphoto2 error code
  273  **/
  274 int
  275 gp_port_info_list_load (GPPortInfoList *list)
  276 {
  277     const char *iolibs_env = getenv(IOLIBDIR_ENV);
  278     const char *iolibs = (iolibs_env != NULL)?iolibs_env:IOLIBS;
  279     int result;
  280 
  281     C_PARAMS (list);
  282 
  283     GP_LOG_D ("Using ltdl to load io-drivers from '%s'...", iolibs);
  284     lt_dlinit ();
  285     lt_dladdsearchdir (iolibs);
  286     result = lt_dlforeachfile (iolibs, foreach_func, list);
  287     lt_dlexit ();
  288     if (result < 0)
  289         return (result);
  290     if (list->iolib_count == 0) {
  291         GP_LOG_E ("No iolibs found in '%s'", iolibs);
  292         return GP_ERROR_LIBRARY;
  293     }
  294         return (GP_OK);
  295 }
  296 
  297 /**
  298  * \brief Number of ports in the list
  299  * \param list a #GPPortInfoList
  300  *
  301  * Returns the number of entries in the passed list.
  302  *
  303  * \return The number of entries or a gphoto2 error code
  304  **/
  305 int
  306 gp_port_info_list_count (GPPortInfoList *list)
  307 {
  308     unsigned int count, i;
  309 
  310     C_PARAMS (list);
  311 
  312     GP_LOG_D ("Counting entries (%i available)...", list->count);
  313 
  314     /* Ignore generic entries */
  315     count = list->count;
  316     for (i = 0; i < list->count; i++)
  317         if (!strlen (list->info[i]->name))
  318             count--;
  319 
  320     GP_LOG_D ("%i regular entries available.", count);
  321     return count;
  322 }
  323 
  324 /**
  325  * \brief Lookup a specific path in the list
  326  *
  327  * \param list a #GPPortInfoList
  328  * \param path a path
  329  *
  330  * Looks for an entry in the list with the supplied path. If no exact match
  331  * can be found, a regex search will be performed in the hope some driver
  332  * claimed ports like "serial:*".
  333  *
  334  * \return The index of the entry or a gphoto2 error code
  335  **/
  336 int
  337 gp_port_info_list_lookup_path (GPPortInfoList *list, const char *path)
  338 {
  339     unsigned int i;
  340     int result, generic;
  341 #ifdef HAVE_REGEX
  342     regex_t pattern;
  343 #ifdef HAVE_GNU_REGEX
  344     const char *rv;
  345 #else
  346     regmatch_t match;
  347 #endif
  348 #endif
  349 
  350     C_PARAMS (list && path);
  351 
  352     GP_LOG_D ("Looking for path '%s' (%i entries available)...", path, list->count);
  353 
  354     /* Exact match? */
  355     for (generic = i = 0; i < list->count; i++)
  356         if (!strlen (list->info[i]->name))
  357             generic++;
  358         else if (!strcmp (list->info[i]->path, path))
  359             return (i - generic);
  360 
  361 #ifdef HAVE_REGEX
  362     /* Regex match? */
  363     GP_LOG_D ("Starting regex search for '%s'...", path);
  364     for (i = 0; i < list->count; i++) {
  365         GPPortInfo newinfo;
  366 
  367         if (strlen (list->info[i]->name))
  368             continue;
  369 
  370         GP_LOG_D ("Trying '%s'...", list->info[i]->path);
  371 
  372         /* Compile the pattern */
  373 #ifdef HAVE_GNU_REGEX
  374         memset (&pattern, 0, sizeof (pattern));
  375         rv = re_compile_pattern (list->info[i]->path,
  376                      strlen (list->info[i]->path), &pattern);
  377         if (rv) {
  378             GP_LOG_D ("%s", rv);
  379             continue;
  380         }
  381 #else
  382         result = regcomp (&pattern, list->info[i]->path, REG_ICASE);
  383         if (result) {
  384             char buf[1024];
  385             if (regerror (result, &pattern, buf, sizeof (buf)))
  386                 GP_LOG_E ("%s", buf);
  387             else
  388                 GP_LOG_E ("regcomp failed");
  389             return (GP_ERROR_UNKNOWN_PORT);
  390         }
  391 #endif
  392 
  393         /* Try to match */
  394 #ifdef HAVE_GNU_REGEX
  395         result = re_match (&pattern, path, strlen (path), 0, NULL);
  396         regfree (&pattern);
  397         if (result < 0) {
  398             GP_LOG_D ("re_match failed (%i)", result);
  399             continue;
  400         }
  401 #else
  402         result = regexec (&pattern, path, 1, &match, 0);
  403         regfree (&pattern);
  404         if (result) {
  405             GP_LOG_D ("regexec failed");
  406             continue;
  407         }
  408 #endif
  409         gp_port_info_new (&newinfo);
  410         gp_port_info_set_type (newinfo, list->info[i]->type);
  411         newinfo->library_filename = strdup(list->info[i]->library_filename);
  412         gp_port_info_set_name (newinfo, _("Generic Port"));
  413         gp_port_info_set_path (newinfo, path);
  414         CR (result = gp_port_info_list_append (list, newinfo));
  415         return result;
  416     }
  417 #endif /* HAVE_REGEX */
  418 
  419     return (GP_ERROR_UNKNOWN_PORT);
  420 }
  421 
  422 /**
  423  * \brief Look up a name in the list
  424  * \param list a #GPPortInfoList
  425  * \param name a name
  426  *
  427  * Looks for an entry in the list with the exact given name.
  428  *
  429  * \return The index of the entry or a gphoto2 error code
  430  **/
  431 int
  432 gp_port_info_list_lookup_name (GPPortInfoList *list, const char *name)
  433 {
  434     unsigned int i, generic;
  435 
  436     C_PARAMS (list && name);
  437 
  438     GP_LOG_D ("Looking up entry '%s'...", name);
  439 
  440     /* Ignore generic entries */
  441     for (generic = i = 0; i < list->count; i++)
  442         if (!strlen (list->info[i]->name))
  443             generic++;
  444         else if (!strcmp (list->info[i]->name, name))
  445             return (i - generic);
  446 
  447     return (GP_ERROR_UNKNOWN_PORT);
  448 }
  449 
  450 /**
  451  * \brief Get port information of specific entry
  452  * \param list a #GPPortInfoList
  453  * \param n the index of the entry
  454  * \param info the returned information
  455  *
  456  * Returns a pointer to the current port entry.
  457  *
  458  * \return a gphoto2 error code
  459  **/
  460 int
  461 gp_port_info_list_get_info (GPPortInfoList *list, int n, GPPortInfo *info)
  462 {
  463     int i;
  464 
  465     C_PARAMS (list && info);
  466 
  467     GP_LOG_D ("Getting info of entry %i (%i available)...", n, list->count);
  468 
  469     C_PARAMS ((n >= 0) && (unsigned int)n < list->count);
  470 
  471     /* Ignore generic entries */
  472     for (i = 0; i <= n; i++)
  473         if (!strlen (list->info[i]->name)) {
  474             n++;
  475             C_PARAMS ((unsigned int)n < list->count);
  476         }
  477 
  478     *info = list->info[n];
  479     return GP_OK;
  480 }
  481 
  482 
  483 /**
  484  * \brief Get name of a specific port entry
  485  * \param info a #GPPortInfo
  486  * \param name a pointer to a char* which will receive the name
  487  *
  488  * Retreives the name of the passed in GPPortInfo, by reference.
  489  *
  490  * \return a gphoto2 error code
  491  **/
  492 int
  493 gp_port_info_get_name (GPPortInfo info, char **name) {
  494     *name = info->name;
  495     return GP_OK;
  496 }
  497 
  498 /**
  499  * \brief Set name of a specific port entry
  500  * \param info a #GPPortInfo
  501  * \param name a char* pointer which will receive the name
  502  *
  503  * Sets the name of the passed in GPPortInfo
  504  * This is a libgphoto2_port internal function.
  505  *
  506  * \return a gphoto2 error code
  507  **/
  508 int
  509 gp_port_info_set_name (GPPortInfo info, const char *name) {
  510     C_MEM (info->name = strdup (name));
  511     return GP_OK;
  512 }
  513 
  514 /**
  515  * \brief Get path of a specific port entry
  516  * \param info a #GPPortInfo
  517  * \param path a pointer to a char* which will receive the path
  518  *
  519  * Retreives the path of the passed in GPPortInfo, by reference.
  520  *
  521  * \return a gphoto2 error code
  522  **/
  523 int
  524 gp_port_info_get_path (GPPortInfo info, char **path) {
  525     *path = info->path;
  526     return GP_OK;
  527 }
  528 
  529 /**
  530  * \brief Set path of a specific port entry
  531  * \param info a #GPPortInfo
  532  * \param path a char* pointer which will receive the path
  533  *
  534  * Sets the path of the passed in GPPortInfo
  535  * This is a libgphoto2_port internal function.
  536  *
  537  * \return a gphoto2 error code
  538  **/
  539 int
  540 gp_port_info_set_path (GPPortInfo info, const char *path) {
  541     C_MEM (info->path = strdup (path));
  542     return GP_OK;
  543 }
  544 
  545 /**
  546  * \brief Get type of a specific port entry
  547  * \param info a #GPPortInfo
  548  * \param type a pointer to a GPPortType variable which will receive the type
  549  *
  550  * Retreives the type of the passed in GPPortInfo
  551  *
  552  * \return a gphoto2 error code
  553  **/
  554 int
  555 gp_port_info_get_type (GPPortInfo info, GPPortType *type) {
  556     *type = info->type;
  557     return GP_OK;
  558 }
  559 
  560 /**
  561  * \brief Set type of a specific port entry
  562  * \param info a #GPPortInfo
  563  * \param type a GPPortType variable which will has the type
  564  *
  565  * Sets the type of the passed in GPPortInfo
  566  * This is a libgphoto2_port internal function.
  567  *
  568  * \return a gphoto2 error code
  569  **/
  570 int
  571 gp_port_info_set_type (GPPortInfo info, GPPortType type) {
  572     info->type = type;
  573     return GP_OK;
  574 }
  575 
  576 /**
  577  * \brief Create a new portinfo
  578  * \param info pointer to a #GPPortInfo
  579  *
  580  * Allocates and initializes a GPPortInfo structure.
  581  * This is a libgphoto2_port internal function.
  582  *
  583  * \return a gphoto2 error code
  584  **/
  585 int
  586 gp_port_info_new (GPPortInfo *info) {
  587     C_MEM (*info = calloc (1, sizeof(struct _GPPortInfo)));
  588     return GP_OK;
  589 }