summaryrefslogtreecommitdiff
path: root/backend/test.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/test.c')
-rw-r--r--backend/test.c198
1 files changed, 167 insertions, 31 deletions
diff --git a/backend/test.c b/backend/test.c
index a1e186e..075fdfa 100644
--- a/backend/test.c
+++ b/backend/test.c
@@ -17,9 +17,7 @@
General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
As a special exception, the authors of SANE give permission for
additional uses of the libraries contained in this release of SANE.
@@ -237,35 +235,34 @@ static SANE_String_Const source_list[] = {
static double random_factor; /* use for fuzzyness of parameters */
-/* initial values */
+/* initial values. Initial string values are set in sane_init() */
static SANE_Word init_number_of_devices = 2;
static SANE_Fixed init_tl_x = SANE_FIX (0.0);
static SANE_Fixed init_tl_y = SANE_FIX (0.0);
static SANE_Fixed init_br_x = SANE_FIX (80.0);
static SANE_Fixed init_br_y = SANE_FIX (100.0);
static SANE_Word init_resolution = 50;
-static SANE_String init_mode =SANE_VALUE_SCAN_MODE_GRAY;
+static SANE_String init_mode = NULL;
static SANE_Word init_depth = 8;
static SANE_Bool init_hand_scanner = SANE_FALSE;
static SANE_Bool init_three_pass = SANE_FALSE;
-static SANE_String init_three_pass_order = "RGB";
-static SANE_String init_scan_source = "Flatbed";
-static SANE_String init_test_picture = "Solid black";
+static SANE_String init_three_pass_order = NULL;
+static SANE_String init_scan_source = NULL;
+static SANE_String init_test_picture = NULL;
static SANE_Bool init_invert_endianess = SANE_FALSE;
static SANE_Bool init_read_limit = SANE_FALSE;
static SANE_Word init_read_limit_size = 1;
static SANE_Bool init_read_delay = SANE_FALSE;
static SANE_Word init_read_delay_duration = 1000;
-static SANE_String init_read_status_code = "Default";
+static SANE_String init_read_status_code = NULL;
static SANE_Bool init_fuzzy_parameters = SANE_FALSE;
static SANE_Word init_ppl_loss = 0;
static SANE_Bool init_non_blocking = SANE_FALSE;
static SANE_Bool init_select_fd = SANE_FALSE;
static SANE_Bool init_enable_test_options = SANE_FALSE;
-static SANE_String init_string = "This is the contents of the string option. "
- "Fill some more words to see how the frontend behaves.";
-static SANE_String init_string_constraint_string_list = "First entry";
-static SANE_String init_string_constraint_long_string_list = "First entry";
+static SANE_String init_string = NULL;
+static SANE_String init_string_constraint_string_list = NULL;
+static SANE_String init_string_constraint_long_string_list = NULL;
/* Test if this machine is little endian (from coolscan.c) */
static SANE_Bool
@@ -320,6 +317,38 @@ check_handle (SANE_Handle handle)
return SANE_FALSE;
}
+static void
+cleanup_options (Test_Device * test_device)
+{
+ DBG (2, "cleanup_options: test_device=%p\n", (void *) test_device);
+
+ free(test_device->val[opt_mode].s);
+ test_device->val[opt_mode].s = NULL;
+
+ free(test_device->val[opt_three_pass_order].s);
+ test_device->val[opt_three_pass_order].s = NULL;
+
+ free(test_device->val[opt_scan_source].s);
+ test_device->val[opt_scan_source].s = NULL;
+
+ free(test_device->val[opt_test_picture].s);
+ test_device->val[opt_test_picture].s = NULL;
+
+ free(test_device->val[opt_read_status_code].s);
+ test_device->val[opt_read_status_code].s = NULL;
+
+ free(test_device->val[opt_string].s);
+ test_device->val[opt_string].s = NULL;
+
+ free(test_device->val[opt_string_constraint_string_list].s);
+ test_device->val[opt_string_constraint_string_list].s = NULL;
+
+ free(test_device->val[opt_string_constraint_long_string_list].s);
+ test_device->val[opt_string_constraint_long_string_list].s = NULL;
+
+ test_device->options_initialized = SANE_FALSE;
+}
+
static SANE_Status
init_options (Test_Device * test_device)
{
@@ -368,7 +397,7 @@ init_options (Test_Device * test_device)
od->constraint.string_list = mode_list;
test_device->val[opt_mode].s = malloc (od->size);
if (!test_device->val[opt_mode].s)
- return SANE_STATUS_NO_MEM;
+ goto fail;
strcpy (test_device->val[opt_mode].s, init_mode);
/* opt_depth */
@@ -435,7 +464,7 @@ init_options (Test_Device * test_device)
od->constraint.string_list = order_list;
test_device->val[opt_three_pass_order].s = malloc (od->size);
if (!test_device->val[opt_three_pass_order].s)
- return SANE_STATUS_NO_MEM;
+ goto fail;
strcpy (test_device->val[opt_three_pass_order].s, init_three_pass_order);
/* opt_resolution */
@@ -464,7 +493,7 @@ init_options (Test_Device * test_device)
od->constraint.string_list = source_list;
test_device->val[opt_scan_source].s = malloc (od->size);
if (!test_device->val[opt_scan_source].s)
- return SANE_STATUS_NO_MEM;
+ goto fail;
strcpy (test_device->val[opt_scan_source].s, init_scan_source);
/* opt_special_group */
@@ -500,7 +529,7 @@ init_options (Test_Device * test_device)
od->constraint.string_list = test_picture_list;
test_device->val[opt_test_picture].s = malloc (od->size);
if (!test_device->val[opt_test_picture].s)
- return SANE_STATUS_NO_MEM;
+ goto fail;
strcpy (test_device->val[opt_test_picture].s, init_test_picture);
/* opt_invert_endianness */
@@ -595,7 +624,7 @@ init_options (Test_Device * test_device)
od->constraint.string_list = read_status_code_list;
test_device->val[opt_read_status_code].s = malloc (od->size);
if (!test_device->val[opt_read_status_code].s)
- return SANE_STATUS_NO_MEM;
+ goto fail;
strcpy (test_device->val[opt_read_status_code].s, init_read_status_code);
/* opt_ppl_loss */
@@ -1129,7 +1158,7 @@ init_options (Test_Device * test_device)
od->constraint.string_list = 0;
test_device->val[opt_string].s = malloc (od->size);
if (!test_device->val[opt_string].s)
- return SANE_STATUS_NO_MEM;
+ goto fail;
strcpy (test_device->val[opt_string].s, init_string);
/* opt_string_constraint_string_list */
@@ -1148,7 +1177,7 @@ init_options (Test_Device * test_device)
od->constraint.string_list = string_constraint_string_list;
test_device->val[opt_string_constraint_string_list].s = malloc (od->size);
if (!test_device->val[opt_string_constraint_string_list].s)
- return SANE_STATUS_NO_MEM;
+ goto fail;
strcpy (test_device->val[opt_string_constraint_string_list].s,
init_string_constraint_string_list);
@@ -1169,7 +1198,7 @@ init_options (Test_Device * test_device)
test_device->val[opt_string_constraint_long_string_list].s =
malloc (od->size);
if (!test_device->val[opt_string_constraint_long_string_list].s)
- return SANE_STATUS_NO_MEM;
+ goto fail;
strcpy (test_device->val[opt_string_constraint_long_string_list].s,
init_string_constraint_long_string_list);
@@ -1202,6 +1231,43 @@ init_options (Test_Device * test_device)
test_device->val[opt_button].w = 0;
return SANE_STATUS_GOOD;
+
+fail:
+ cleanup_options (test_device);
+ return SANE_STATUS_NO_MEM;
+}
+
+static void
+cleanup_initial_string_values ()
+{
+ // Cleanup backing memory for initial values of string options.
+ free (init_mode);
+ init_mode = NULL;
+ free (init_three_pass_order);
+ init_three_pass_order = NULL;
+ free (init_scan_source);
+ init_scan_source = NULL;
+ free (init_test_picture);
+ init_test_picture = NULL;
+ free (init_read_status_code);
+ init_read_status_code = NULL;
+ free (init_string);
+ init_string = NULL;
+ free (init_string_constraint_string_list);
+ init_string_constraint_string_list = NULL;
+ free (init_string_constraint_long_string_list);
+ init_string_constraint_long_string_list = NULL;
+}
+
+static void
+cleanup_test_device (Test_Device * test_device)
+{
+ DBG (2, "cleanup_test_device: test_device=%p\n", (void *) test_device);
+ if (test_device->options_initialized)
+ cleanup_options (test_device);
+ if (test_device->name)
+ free (test_device->name);
+ free (test_device);
}
static SANE_Status
@@ -1331,7 +1397,11 @@ read_option (SANE_String line, SANE_String option_string,
{
DBG (3, "read_option: set option `%s' to `%s'\n", option_string,
word);
+ if (*(SANE_String *) value)
+ free (*(SANE_String *) value);
*(SANE_String *) value = strdup (word);
+ if (!*(SANE_String *) value)
+ return SANE_STATUS_NO_MEM;
}
break;
}
@@ -1575,6 +1645,49 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un
if (inited)
DBG (3, "sane_init: warning: already inited\n");
+ // Setup initial values of string options. Call free initially in case we've
+ // already called sane_init and these values are already non-null.
+ free (init_mode);
+ init_mode = strdup (SANE_VALUE_SCAN_MODE_GRAY);
+ if (!init_mode)
+ goto fail;
+
+ free (init_three_pass_order);
+ init_three_pass_order = strdup ("RGB");
+ if (!init_three_pass_order)
+ goto fail;
+
+ free (init_scan_source);
+ init_scan_source = strdup ("Flatbed");
+ if (!init_scan_source)
+ goto fail;
+
+ free (init_test_picture);
+ init_test_picture = strdup ("Solid black");
+ if (!init_test_picture)
+ goto fail;
+
+ free (init_read_status_code);
+ init_read_status_code = strdup ("Default");
+ if (!init_read_status_code)
+ goto fail;
+
+ free (init_string);
+ init_string = strdup ("This is the contents of the string option. "
+ "Fill some more words to see how the frontend behaves.");
+ if (!init_string)
+ goto fail;
+
+ free (init_string_constraint_string_list);
+ init_string_constraint_string_list = strdup ("First entry");
+ if (!init_string_constraint_string_list)
+ goto fail;
+
+ free (init_string_constraint_long_string_list);
+ init_string_constraint_long_string_list = strdup ("First entry");
+ if (!init_string_constraint_long_string_list)
+ goto fail;
+
fp = sanei_config_open (TEST_CONFIG_FILE);
if (fp)
{
@@ -1713,14 +1826,14 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un
sane_device_list =
malloc ((init_number_of_devices + 1) * sizeof (sane_device));
if (!sane_device_list)
- return SANE_STATUS_NO_MEM;
+ goto fail;
for (num = 0; num < init_number_of_devices; num++)
{
SANE_Char number_string[PATH_MAX];
- test_device = malloc (sizeof (*test_device));
+ test_device = calloc (sizeof (*test_device), 1);
if (!test_device)
- return SANE_STATUS_NO_MEM;
+ goto fail_device;
test_device->sane.vendor = "Noname";
test_device->sane.type = "virtual device";
test_device->sane.model = "frontend-tester";
@@ -1728,7 +1841,7 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un
number_string[sizeof (number_string) - 1] = '\0';
test_device->name = strdup (number_string);
if (!test_device->name)
- return SANE_STATUS_NO_MEM;
+ goto fail_name;
test_device->sane.name = test_device->name;
if (previous_device)
previous_device->next = test_device;
@@ -1740,6 +1853,7 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un
test_device->eof = SANE_FALSE;
test_device->scanning = SANE_FALSE;
test_device->cancelled = SANE_FALSE;
+ test_device->options_initialized = SANE_FALSE;
sanei_thread_initialize (test_device->reader_pid);
test_device->pipe = -1;
DBG (4, "sane_init: new device: `%s' is a %s %s %s\n",
@@ -1752,6 +1866,25 @@ sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_un
random_factor = ((double) rand ()) / RAND_MAX + 0.5;
inited = SANE_TRUE;
return SANE_STATUS_GOOD;
+
+fail_name:
+ // test_device refers to the last device we were creating, which has not
+ // yet been added to the linked list of devices.
+ free (test_device);
+fail_device:
+ // Now, iterate through the linked list of devices to clean up any successful
+ // devices.
+ test_device = first_test_device;
+ while (test_device)
+ {
+ previous_device = test_device;
+ test_device = test_device->next;
+ cleanup_test_device (previous_device);
+ }
+ free (sane_device_list);
+fail:
+ cleanup_initial_string_values ();
+ return SANE_STATUS_NO_MEM;
}
void
@@ -1772,15 +1905,15 @@ sane_exit (void)
DBG (4, "sane_exit: freeing device %s\n", test_device->name);
previous_device = test_device;
test_device = test_device->next;
- if (previous_device->name)
- free (previous_device->name);
- free (previous_device);
+ cleanup_test_device (previous_device);
}
DBG (4, "sane_exit: freeing device list\n");
if (sane_device_list)
free (sane_device_list);
sane_device_list = NULL;
first_test_device = NULL;
+
+ cleanup_initial_string_values ();
inited = SANE_FALSE;
return;
}
@@ -1855,9 +1988,12 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle)
test_device->open = SANE_TRUE;
*handle = test_device;
- status = init_options (test_device);
- if (status != SANE_STATUS_GOOD)
- return status;
+ if (!test_device->options_initialized) {
+ status = init_options (test_device);
+ if (status != SANE_STATUS_GOOD)
+ return status;
+ test_device->options_initialized = SANE_TRUE;
+ }
test_device->open = SANE_TRUE;
test_device->scanning = SANE_FALSE;