diff options
Diffstat (limited to 'backend/dll.c')
| -rw-r--r-- | backend/dll.c | 90 | 
1 files changed, 81 insertions, 9 deletions
| diff --git a/backend/dll.c b/backend/dll.c index 8f0983d..73ffde4 100644 --- a/backend/dll.c +++ b/backend/dll.c @@ -89,6 +89,20 @@ posix_dlsym (void *handle, const char *func)  }  # pragma GCC diagnostic pop +  /* Similar to the above, GCC also warns about conversion between +     pointers to functions.  The ISO C standard says that invoking a +     converted pointer to a function whose type is not compatible with +     the pointed-to type, the behavior is undefined.  Although GCC is +     correct to warn about this, the dll backend has been using these +     conversions without issues for a very long time already. + +     Rather than push/pop around every use, which would get very ugly +     real fast, ignore this particular warning for the remainder of +     the file. +   */ +# pragma GCC diagnostic ignored "-Wpragmas" /* backward compatibility */ +# pragma GCC diagnostic ignored "-Wcast-function-type" +    /* Older versions of dlopen() don't define RTLD_NOW and RTLD_LAZY.       They all seem to use a mode of 1 to indicate RTLD_NOW and some do       not support RTLD_LAZY at all.  Hence, unless defined, we define @@ -139,6 +153,8 @@ posix_dlsym (void *handle, const char *func)  #define DLL_CONFIG_FILE "dll.conf"  #define DLL_ALIASES_FILE "dll.aliases" +#include "../include/sane/sanei_usb.h" +  enum SANE_Ops  {    OP_INIT = 0, @@ -797,7 +813,8 @@ read_dlld (void)    DIR *dlld;    struct dirent *dllconf;    struct stat st; -  char conffile[PATH_MAX], dlldir[PATH_MAX]; +  char dlldir[PATH_MAX]; +  char conffile[PATH_MAX + strlen("/") + NAME_MAX];    size_t len, plen;    const char *dir_list;    char *copy, *next, *dir; @@ -849,7 +866,7 @@ read_dlld (void)            || (dllconf->d_name[len-1] == '#'))          continue; -      snprintf (conffile, PATH_MAX, "%s/%s", dlldir, dllconf->d_name); +      snprintf (conffile, sizeof(conffile), "%s/%s", dlldir, dllconf->d_name);        DBG (5, "sane_init/read_dlld: considering %s\n", conffile); @@ -1177,18 +1194,73 @@ sane_open (SANE_String_Const full_name, SANE_Handle * meta_handle)      }    dev_name = strchr (full_name, ':'); + +  int is_fakeusb = 0, is_fakeusbdev = 0, is_fakeusbout = 0; +    if (dev_name)      { -      be_name = strndup(full_name, dev_name - full_name); -      ++dev_name;		/* skip colon */ +      is_fakeusb = strncmp(full_name, "fakeusb", dev_name - full_name) == 0 && +          dev_name - full_name == 7; +      is_fakeusbdev = strncmp(full_name, "fakeusbdev", dev_name - full_name) == 0 && +          dev_name - full_name == 10; +      is_fakeusbout = strncmp(full_name, "fakeusbout", dev_name - full_name) == 0 && +          dev_name - full_name == 10; +    } + +  if (is_fakeusb || is_fakeusbdev) +    { +      ++dev_name; // skip colon +      status = sanei_usb_testing_enable_replay(dev_name, is_fakeusbdev); +      if (status != SANE_STATUS_GOOD) +        return status; + +      be_name = sanei_usb_testing_get_backend(); +      if (be_name == NULL) +        { +          DBG (0, "%s: unknown backend for testing\n", __func__); +          return SANE_STATUS_ACCESS_DENIED; +        }      }    else      { -      /* if no colon interpret full_name as the backend name; an empty -         backend device name will cause us to open the first device of -         that backend.  */ -      be_name = strdup(full_name); -      dev_name = ""; +      char* fakeusbout_path = NULL; +      if (is_fakeusbout) +      { +        ++dev_name; // skip colon + +        const char* path_end = strchr(dev_name, ':'); +        if (path_end == NULL) +          { +            DBG (0, "%s: the device name does not contain path\n", __func__); +            return SANE_STATUS_INVAL; +          } +        fakeusbout_path = strndup(dev_name, path_end - dev_name); + +        full_name = path_end + 1; // skip colon +        dev_name = strchr(full_name, ':'); +      } + +      if (dev_name) +        { +          be_name = strndup(full_name, dev_name - full_name); +          ++dev_name;		/* skip colon */ +        } +      else +        { +          /* if no colon interpret full_name as the backend name; an empty +             backend device name will cause us to open the first device of +             that backend.  */ +          be_name = strdup(full_name); +          dev_name = ""; +        } + +      if (is_fakeusbout) +        { +          status = sanei_usb_testing_enable_record(fakeusbout_path, be_name); +          free(fakeusbout_path); +          if (status != SANE_STATUS_GOOD) +            return status; +        }      }    if (!be_name) | 
