Only sign files when the entire file has been copied

For large files, EVENT_CREATED gets emitted when the first chunk hits the disk,
not when the file has finished copying. To fix, just wait for the file monitor
to hint that all the changes in the operation have happened and then process
the firmware files.
This commit is contained in:
Richard Hughes 2015-07-23 09:15:26 +01:00
parent 152670a371
commit 0950db9340

View File

@ -40,6 +40,7 @@ typedef struct {
gchar *key_id; gchar *key_id;
gboolean set_owner; gboolean set_owner;
FuKeyring *keyring; FuKeyring *keyring;
GPtrArray *pending_files;
} FuSignPrivate; } FuSignPrivate;
/** /**
@ -238,20 +239,39 @@ fu_sign_monitor_changed_cb (GFileMonitor *monitor,
GFileMonitorEvent event_type, GFileMonitorEvent event_type,
FuSignPrivate *priv) FuSignPrivate *priv)
{ {
_cleanup_error_free_ GError *error = NULL; guint i;
_cleanup_free_ gchar *fn_src = NULL; const gchar *fn;
/* only new files */ /* we don't want to process the file when the event is EVENT_CREATED as
if (event_type != G_FILE_MONITOR_EVENT_CREATED) * the file may still be in the process of being transferred */
return; switch (event_type) {
fn_src = g_file_get_path (file); case G_FILE_MONITOR_EVENT_CREATED:
if (fn_src == NULL) g_ptr_array_add (priv->pending_files, g_file_get_path (file));
return; break;
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
/* process file */ for (i = 0; i < priv->pending_files->len; i++) {
if (!fu_sign_process_file (priv, fn_src, &error)) { _cleanup_error_free_ GError *error = NULL;
g_warning ("failed to process %s: %s", fn_src, error->message); fn = g_ptr_array_index (priv->pending_files, i);
return; if (!fu_sign_process_file (priv, fn, &error)) {
g_warning ("failed to process %s: %s",
fn, error->message);
continue;
}
}
g_ptr_array_set_size (priv->pending_files, 0);
break;
case G_FILE_MONITOR_EVENT_DELETED:
for (i = 0; i < priv->pending_files->len; i++) {
_cleanup_free_ gchar *fn_src = g_file_get_path (file);
fn = g_ptr_array_index (priv->pending_files, i);
if (g_strcmp0 (fn, fn_src) == 0) {
g_ptr_array_remove_index_fast (priv->pending_files, i);
break;
}
}
break;
default:
break;
} }
} }
@ -337,6 +357,7 @@ main (int argc, char *argv[])
priv->destination = g_strdup (destination); priv->destination = g_strdup (destination);
priv->key_id = g_strdup (key_id); priv->key_id = g_strdup (key_id);
priv->keyring = fu_keyring_new (); priv->keyring = fu_keyring_new ();
priv->pending_files = g_ptr_array_new_with_free_func (g_free);
priv->set_owner = g_key_file_get_boolean (config, "fwupd", "SetDestinationOwner", NULL); priv->set_owner = g_key_file_get_boolean (config, "fwupd", "SetDestinationOwner", NULL);
if (priv->key_id != NULL && if (priv->key_id != NULL &&
!fu_keyring_set_signing_key (priv->keyring, priv->key_id, &error)) { !fu_keyring_set_signing_key (priv->keyring, priv->key_id, &error)) {
@ -374,6 +395,7 @@ main (int argc, char *argv[])
out: out:
if (priv != NULL) { if (priv != NULL) {
g_object_unref (priv->keyring); g_object_unref (priv->keyring);
g_ptr_array_unref (priv->pending_files);
g_free (priv->source); g_free (priv->source);
g_free (priv->destination); g_free (priv->destination);
g_free (priv->key_id); g_free (priv->key_id);