libgphoto2 photo camera library (libgphoto2) Internals  2.5.26
gphoto2-port-info-list.c
Go to the documentation of this file.
1 
23 #define _GNU_SOURCE
24 
25 #include "config.h"
26 
28 
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 #ifdef HAVE_REGEX
33 #include <regex.h>
34 #elif defined(_MSC_VER)
35 #pragma message("We need regex.h, but it has not been detected.")
36 #else
37 #warning We need regex.h, but it has not been detected.
38 #endif
39 
40 #include <ltdl.h>
41 
45 
46 #include "gphoto2-port-info.h"
47 
48 #ifdef ENABLE_NLS
49 # include <libintl.h>
50 # undef _
51 # define _(String) dgettext (GETTEXT_PACKAGE, String)
52 # ifdef gettext_noop
53 # define N_(String) gettext_noop (String)
54 # else
55 # define N_(String) (String)
56 # endif
57 #else
58 # define textdomain(String) (String)
59 # define gettext(String) (String)
60 # define dgettext(Domain,Message) (Message)
61 # define dcgettext(Domain,Message,Type) (Message)
62 # define bindtextdomain(Domain,Directory) (Domain)
63 # define bind_textdomain_codeset(Domain,codeset) (codeset)
64 # define ngettext(String1,String2,Count) ((Count==1)?String1:String2)
65 # define _(String) (String)
66 # define N_(String) (String)
67 #endif
68 
76  unsigned int count;
77  unsigned int iolib_count;
78 };
79 
80 #define CR(x) {int r=(x);if (r<0) return (r);}
81 
82 
95 const char*
96 gp_port_message_codeset (const char *codeset) {
97  return bind_textdomain_codeset (GETTEXT_PACKAGE, codeset);
98 }
99 
110 int
112 {
113  C_PARAMS (list);
114 
115  /*
116  * We put this in here because everybody needs to call this function
117  * before accessing ports...
118  */
119  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
120 
121  C_MEM (*list = calloc (1, sizeof (GPPortInfoList)));
122 
123  return (GP_OK);
124 }
125 
134 int
136 {
137  C_PARAMS (list);
138 
139  if (list->info) {
140  unsigned int i;
141 
142  for (i=0;i<list->count;i++) {
143  free (list->info[i]->name);
144  list->info[i]->name = NULL;
145  free (list->info[i]->path);
146  list->info[i]->path = NULL;
147  free (list->info[i]->library_filename);
148  list->info[i]->library_filename = NULL;
149  free (list->info[i]);
150  }
151  free (list->info);
152  list->info = NULL;
153  }
154  list->count = 0;
155 
156  free (list);
157 
158  return (GP_OK);
159 }
160 
176 int
178 {
179  unsigned int generic, i;
180 
181  C_PARAMS (list);
182 
183  C_MEM (list->info = realloc (list->info, sizeof (GPPortInfo) * (list->count + 1)));
184  list->count++;
185  list->info[list->count - 1] = info;
186 
187  /* Ignore generic entries */
188  for (generic = i = 0; i < list->count; i++)
189  if (!strlen (list->info[i]->name))
190  generic++;
191  return (list->count - 1 - generic);
192 }
193 
194 
195 static int
196 foreach_func (const char *filename, lt_ptr data)
197 {
198  GPPortInfoList *list = data;
199  lt_dlhandle lh;
200  GPPortLibraryType lib_type;
201  GPPortLibraryList lib_list;
202  GPPortType type;
203  unsigned int j, old_size = list->count;
204  int result;
205 
206  GP_LOG_D ("Called for filename '%s'.", filename );
207 
208  lh = lt_dlopenext (filename);
209  if (!lh) {
210  GP_LOG_D ("Could not load '%s': '%s'.", filename, lt_dlerror ());
211  return (0);
212  }
213 
214  lib_type = lt_dlsym (lh, "gp_port_library_type");
215  lib_list = lt_dlsym (lh, "gp_port_library_list");
216  if (!lib_type || !lib_list) {
217  GP_LOG_D ("Could not find some functions in '%s': '%s'.",
218  filename, lt_dlerror ());
219  lt_dlclose (lh);
220  return (0);
221  }
222 
223  type = lib_type ();
224  for (j = 0; j < list->count; j++)
225  if (list->info[j]->type == type)
226  break;
227  if (j != list->count) {
228  GP_LOG_D ("'%s' already loaded", filename);
229  lt_dlclose (lh);
230  return (0);
231  }
232 
233  result = lib_list (list);
234 #if !defined(VALGRIND)
235  lt_dlclose (lh);
236 #endif
237  if (result < 0) {
238  GP_LOG_E ("Error during assembling of port list: '%s' (%d).",
240  }
241 
242  if (old_size != list->count) {
243  /*
244  * It doesn't matter if lib_list returned a failure code,
245  * at least some entries were added
246  */
247  list->iolib_count++;
248 
249  for (j = old_size; j < list->count; j++){
250  GP_LOG_D ("Loaded '%s' ('%s') from '%s'.",
251  list->info[j]->name, list->info[j]->path,
252  filename);
253  list->info[j]->library_filename = strdup (filename);
254  }
255  }
256 
257  return (0);
258 }
259 
260 
273 int
275 {
276  const char *iolibs_env = getenv(IOLIBDIR_ENV);
277  const char *iolibs = (iolibs_env != NULL)?iolibs_env:IOLIBS;
278  int result;
279 
280  C_PARAMS (list);
281 
282  GP_LOG_D ("Using ltdl to load io-drivers from '%s'...", iolibs);
283  lt_dlinit ();
284  lt_dladdsearchdir (iolibs);
285  result = lt_dlforeachfile (iolibs, foreach_func, list);
286  lt_dlexit ();
287  if (result < 0)
288  return (result);
289  if (list->iolib_count == 0) {
290  GP_LOG_E ("No iolibs found in '%s'", iolibs);
291  return GP_ERROR_LIBRARY;
292  }
293  return (GP_OK);
294 }
295 
304 int
306 {
307  unsigned int count, i;
308 
309  C_PARAMS (list);
310 
311  GP_LOG_D ("Counting entries (%i available)...", list->count);
312 
313  /* Ignore generic entries */
314  count = list->count;
315  for (i = 0; i < list->count; i++)
316  if (!strlen (list->info[i]->name))
317  count--;
318 
319  GP_LOG_D ("%i regular entries available.", count);
320  return count;
321 }
322 
335 int
337 {
338  unsigned int i;
339  int result, generic;
340 #ifdef HAVE_REGEX
341  regex_t pattern;
342 #ifdef HAVE_GNU_REGEX
343  const char *rv;
344 #else
345  regmatch_t match;
346 #endif
347 #endif
348 
349  C_PARAMS (list && path);
350 
351  GP_LOG_D ("Looking for path '%s' (%i entries available)...", path, list->count);
352 
353  /* Exact match? */
354  for (generic = i = 0; i < list->count; i++)
355  if (!strlen (list->info[i]->name))
356  generic++;
357  else if (!strcmp (list->info[i]->path, path))
358  return (i - generic);
359 
360 #ifdef HAVE_REGEX
361  /* Regex match? */
362  GP_LOG_D ("Starting regex search for '%s'...", path);
363  for (i = 0; i < list->count; i++) {
364  GPPortInfo newinfo;
365 
366  if (strlen (list->info[i]->name))
367  continue;
368 
369  GP_LOG_D ("Trying '%s'...", list->info[i]->path);
370 
371  /* Compile the pattern */
372 #ifdef HAVE_GNU_REGEX
373  memset (&pattern, 0, sizeof (pattern));
374  rv = re_compile_pattern (list->info[i]->path,
375  strlen (list->info[i]->path), &pattern);
376  if (rv) {
377  GP_LOG_D ("%s", rv);
378  continue;
379  }
380 #else
381  result = regcomp (&pattern, list->info[i]->path, REG_ICASE);
382  if (result) {
383  char buf[1024];
384  if (regerror (result, &pattern, buf, sizeof (buf)))
385  GP_LOG_E ("%s", buf);
386  else
387  GP_LOG_E ("regcomp failed");
388  return (GP_ERROR_UNKNOWN_PORT);
389  }
390 #endif
391 
392  /* Try to match */
393 #ifdef HAVE_GNU_REGEX
394  result = re_match (&pattern, path, strlen (path), 0, NULL);
395  regfree (&pattern);
396  if (result < 0) {
397  GP_LOG_D ("re_match failed (%i)", result);
398  continue;
399  }
400 #else
401  result = regexec (&pattern, path, 1, &match, 0);
402  regfree (&pattern);
403  if (result) {
404  GP_LOG_D ("regexec failed");
405  continue;
406  }
407 #endif
408  gp_port_info_new (&newinfo);
409  gp_port_info_set_type (newinfo, list->info[i]->type);
410  newinfo->library_filename = strdup(list->info[i]->library_filename);
411  gp_port_info_set_name (newinfo, _("Generic Port"));
412  gp_port_info_set_path (newinfo, path);
413  CR (result = gp_port_info_list_append (list, newinfo));
414  return result;
415  }
416 #endif /* HAVE_REGEX */
417 
418  return (GP_ERROR_UNKNOWN_PORT);
419 }
420 
430 int
432 {
433  unsigned int i, generic;
434 
435  C_PARAMS (list && name);
436 
437  GP_LOG_D ("Looking up entry '%s'...", name);
438 
439  /* Ignore generic entries */
440  for (generic = i = 0; i < list->count; i++)
441  if (!strlen (list->info[i]->name))
442  generic++;
443  else if (!strcmp (list->info[i]->name, name))
444  return (i - generic);
445 
446  return (GP_ERROR_UNKNOWN_PORT);
447 }
448 
459 int
461 {
462  int i;
463 
464  C_PARAMS (list && info);
465 
466  GP_LOG_D ("Getting info of entry %i (%i available)...", n, list->count);
467 
468  C_PARAMS ((n >= 0) && (unsigned int)n < list->count);
469 
470  /* Ignore generic entries */
471  for (i = 0; i <= n; i++)
472  if (!strlen (list->info[i]->name)) {
473  n++;
474  C_PARAMS ((unsigned int)n < list->count);
475  }
476 
477  *info = list->info[n];
478  return GP_OK;
479 }
480 
481 
491 int
492 gp_port_info_get_name (GPPortInfo info, char **name) {
493  *name = info->name;
494  return GP_OK;
495 }
496 
507 int
508 gp_port_info_set_name (GPPortInfo info, const char *name) {
509  C_MEM (info->name = strdup (name));
510  return GP_OK;
511 }
512 
522 int
523 gp_port_info_get_path (GPPortInfo info, char **path) {
524  *path = info->path;
525  return GP_OK;
526 }
527 
538 int
539 gp_port_info_set_path (GPPortInfo info, const char *path) {
540  C_MEM (info->path = strdup (path));
541  return GP_OK;
542 }
543 
553 int
555  *type = info->type;
556  return GP_OK;
557 }
558 
569 int
571  info->type = type;
572  return GP_OK;
573 }
574 
584 int
586  C_MEM (*info = calloc (1, sizeof(struct _GPPortInfo)));
587  return GP_OK;
588 }
#define bind_textdomain_codeset(Domain, codeset)
int gp_port_info_set_name(GPPortInfo info, const char *name)
Set name of a specific port entry.
int gp_port_info_list_count(GPPortInfoList *list)
Number of ports in the list.
int gp_port_info_list_new(GPPortInfoList **list)
Create a new GPPortInfoList.
#define _(String)
const char * gp_port_message_codeset(const char *codeset)
Specify codeset for translations.
int gp_port_info_list_lookup_name(GPPortInfoList *list, const char *name)
Look up a name in the list.
int gp_port_info_set_path(GPPortInfo info, const char *path)
Set path of a specific port entry.
int gp_port_info_list_load(GPPortInfoList *list)
Load system ports.
int gp_port_info_get_type(GPPortInfo info, GPPortType *type)
Get type of a specific port entry.
int gp_port_info_list_get_info(GPPortInfoList *list, int n, GPPortInfo *info)
Get port information of specific entry.
int gp_port_info_new(GPPortInfo *info)
Create a new portinfo.
#define CR(x)
int gp_port_info_get_path(GPPortInfo info, char **path)
Get path of a specific port entry.
int gp_port_info_get_name(GPPortInfo info, char **name)
Get name of a specific port entry.
int gp_port_info_set_type(GPPortInfo info, GPPortType type)
Set type of a specific port entry.
int gp_port_info_list_free(GPPortInfoList *list)
Free a GPPortInfo list.
int gp_port_info_list_append(GPPortInfoList *list, GPPortInfo info)
Append a portinfo to the port information list.
int gp_port_info_list_lookup_path(GPPortInfoList *list, const char *path)
Lookup a specific path in the list.
#define bindtextdomain(Domain, Directory)
static int foreach_func(const char *filename, lt_ptr data)
GPPortType
The gphoto port type.
GPPortType(* GPPortLibraryType)(void)
int(* GPPortLibraryList)(GPPortInfoList *list)
const char * gp_port_result_as_string(int result)
#define GP_OK
Everything is OK.
#define GP_ERROR_LIBRARY
Error in the camera driver.
#define GP_ERROR_UNKNOWN_PORT
Unknown libgphoto2 port passed.
int result
char * library_filename
Internal pathname of the port driver. Do not use outside of the port library.
char * path
The path of this port (usb:001,023)
GPPortType type
The type of this port.
char * name
The name of this port (usb:)