summaryrefslogtreecommitdiff
path: root/backend/dll.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/dll.c')
-rw-r--r--backend/dll.c125
1 files changed, 98 insertions, 27 deletions
diff --git a/backend/dll.c b/backend/dll.c
index 5eaa046..73ffde4 100644
--- a/backend/dll.c
+++ b/backend/dll.c
@@ -42,7 +42,7 @@
allows managing an arbitrary number of SANE backends by using
dynamic linking to load backends on demand. */
-/* Please increase version number with every change
+/* Please increase version number with every change
(don't forget to update dll.desc) */
#define DLL_VERSION "1.0.13"
@@ -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,
@@ -353,7 +369,7 @@ load (struct backend *be)
image_id id = -1;
int i, w;
directory_which which[3] = { B_USER_ADDONS_DIRECTORY, B_COMMON_ADDONS_DIRECTORY, B_BEOS_ADDONS_DIRECTORY };
-
+
/* look for config files in SANE/conf */
for (w = 0; (w < 3) && (id < 0) && (find_directory(which[w],0,true,path,PATH_MAX) == 0); w++)
{
@@ -373,7 +389,7 @@ load (struct backend *be)
continue; /* try next path */
}
be->handle=(void *)id;
-
+
for (i = 0; i < NUM_OPS; ++i)
{
void *(*op) ();
@@ -492,7 +508,7 @@ load (struct backend *be)
break;
DBG (4, "load: couldn't open `%s' (%s)\n", libname, strerror (errno));
-#ifdef ALT_POSTFIX
+#ifdef ALT_POSTFIX
/* Some platforms have two ways of storing their libraries, try both
postfixes */
snprintf (libname, sizeof (libname), "%s/" PREFIX "%s" ALT_POSTFIX,
@@ -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);
@@ -882,7 +899,7 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
char path[1024];
directory_which which[3] = { B_USER_ADDONS_DIRECTORY, B_COMMON_ADDONS_DIRECTORY, B_BEOS_ADDONS_DIRECTORY };
int i;
-#endif
+#endif
DBG_INIT ();
@@ -934,7 +951,7 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
}
fclose (fp);
-#else
+#else
/* no ugly config files, just get scanners from their ~/config/add-ons/SANE */
/* look for drivers */
for (i = 0; i < 3; i++)
@@ -943,13 +960,13 @@ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
continue;
strcat(path,"/SANE/");
dir=opendir(path);
- if(!dir) continue;
+ if(!dir) continue;
while((dirent=readdir(dir)))
{
if((strcmp(dirent->d_name,".")==0) || (strcmp(dirent->d_name,"..")==0)) continue;
if((strcmp(dirent->d_name,"dll")==0)) continue;
- add_backend(dirent->d_name,0);
+ add_backend(dirent->d_name,0);
}
closedir(dir);
}
@@ -1155,7 +1172,8 @@ sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
SANE_Status
sane_open (SANE_String_Const full_name, SANE_Handle * meta_handle)
{
- const char *be_name, *dev_name;
+ char *be_name;
+ const char *dev_name;
struct meta_scanner *s;
SANE_Handle handle;
struct backend *be;
@@ -1176,29 +1194,78 @@ 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)
{
-#ifdef strndupa
- be_name = strndupa (full_name, dev_name - full_name);
-#else
- char *tmp;
+ 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;
+ }
- tmp = alloca (dev_name - full_name + 1);
- memcpy (tmp, full_name, dev_name - full_name);
- tmp[dev_name - full_name] = '\0';
- be_name = tmp;
-#endif
- ++dev_name; /* skip colon */
+ 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 = 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)
+ return SANE_STATUS_NO_MEM;
+
if (!be_name[0])
be = first_backend;
else
@@ -1210,8 +1277,12 @@ sane_open (SANE_String_Const full_name, SANE_Handle * meta_handle)
{
status = add_backend (be_name, &be);
if (status != SANE_STATUS_GOOD)
- return status;
+ {
+ free(be_name);
+ return status;
+ }
}
+ free(be_name);
if (!be->inited)
{