summaryrefslogtreecommitdiff
path: root/backend/dll.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/dll.c')
-rw-r--r--backend/dll.c90
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)