diff --git a/src/device.c b/src/device.c
index 1b2f37d..ccaf629 100644
--- a/src/device.c
+++ b/src/device.c
@@ -110,6 +110,7 @@ struct FprintDevicePrivate {
/* Required to restart the operation on a retry failure. */
FpPrint *verify_data;
GPtrArray *identify_data;
+ int enroll_data;
/* whether we're running an identify, or a verify */
FprintDeviceAction current_action;
@@ -375,6 +376,8 @@ enroll_result_to_name (gboolean completed, gboolean enrolled, GError *error)
*/
if (g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_PROTO))
return "enroll-disconnected";
+ else if (g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_FULL))
+ return "enroll-data-full";
return "enroll-unknown-error";
}
@@ -956,6 +959,75 @@ static void enroll_progress_cb(FpDevice *dev,
g_signal_emit(rdev, signals[SIGNAL_ENROLL_STATUS], 0, name, FALSE);
}
+static gboolean try_delete_print(FprintDevice *rdev)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) device_prints = NULL;
+ FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
+ GSList *users, *user;
+
+ device_prints = fp_device_list_prints_sync (priv->dev, NULL, &error);
+ if (!device_prints) {
+ g_warning ("Failed to query prints: %s", error->message);
+ return FALSE;
+ }
+
+ g_debug ("Device has %d prints stored", device_prints->len);
+
+ users = store.discover_users();
+
+ for (user = users; user; user = user->next) {
+ const gchar *username = user->data;
+ GSList *fingers, *finger;
+
+ fingers = store.discover_prints (priv->dev, username);
+
+ for (finger = fingers; finger; finger = finger->next) {
+ g_autoptr(FpPrint) print = NULL;
+ guint index;
+
+ store.print_data_load (priv->dev,
+ GPOINTER_TO_INT (fingers->data),
+ username,
+ &print);
+
+ if (!print)
+ continue;
+
+ if (!g_ptr_array_find_with_equal_func (device_prints,
+ print,
+ (GEqualFunc) fp_print_equal,
+ &index))
+ continue;
+
+ /* Found an equal print, remove it */
+ g_ptr_array_remove_index (device_prints, index);
+ }
+
+ g_slist_free (fingers);
+ }
+
+ g_slist_free_full (users, g_free);
+
+ g_debug ("Device has %d prints stored that we do not need", device_prints->len);
+ if (device_prints->len == 0)
+ return FALSE;
+
+ /* Just delete the first print in the list at this point.
+ * We could be smarter and fetch some more metadata. */
+ fp_device_delete_print_sync (priv->dev,
+ g_ptr_array_index (device_prints, 0),
+ NULL,
+ &error);
+
+ if (error) {
+ g_warning ("Failed to garbage collect a print: %s", error->message);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static FpPrint*
fprint_device_create_enroll_template(FprintDevice *rdev, gint finger_num)
{
@@ -987,6 +1059,29 @@ static void enroll_cb(FpDevice *dev, GAsyncResult *res, void *user_data)
const char *name;
print = fp_device_enroll_finish (dev, res, &error);
+
+ /* We need to special case the issue where the on device storage
+ * is completely full. In that case, we check whether we can delete
+ * a print that is not coming from us; assuming it is from an old
+ * installation.
+ * We do this synchronously, which is not great but should be good
+ * enough. */
+ if (g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_FULL)) {
+ g_debug ("Device storage is full, trying to garbage collect old prints");
+ if (try_delete_print (rdev)) {
+ /* Success? Then restart the operation */
+ fp_device_enroll (priv->dev,
+ fprint_device_create_enroll_template (rdev, priv->enroll_data),
+ priv->current_cancellable,
+ enroll_progress_cb,
+ rdev,
+ NULL,
+ (GAsyncReadyCallback) enroll_cb,
+ rdev);
+ return;
+ }
+ }
+
name = enroll_result_to_name (TRUE, print != NULL, error);
g_debug ("enroll_cb: result %s", name);
@@ -1053,6 +1148,7 @@ static void fprint_device_enroll_start(FprintDevice *rdev,
g_debug("start enrollment device %d finger %d", priv->id, finger_num);
priv->current_cancellable = g_cancellable_new ();
+ priv->enroll_data = finger_num;
fp_device_enroll (priv->dev,
fprint_device_create_enroll_template (rdev, priv->enroll_data),
priv->current_cancellable,
diff --git a/src/device.xml b/src/device.xml
index 99912ad..14f7664 100644
--- a/src/device.xml
+++ b/src/device.xml
@@ -245,6 +245,16 @@
The user should remove their finger from the reader and retry scanning their finger, the enrollment is still ongoing.
+
+ enroll-data-full
+
+ No further prints can be enrolled on this device, Device.EnrollStop should now be called.
+
+ Delete other prints from the device first to continue
+ (e.g. from other users). Note that old prints or prints from other operating systems may be deleted automatically
+ to resolve this error without any notification.
+
+
enroll-disconnected