app, libgimpconfig: make various usage of g_file_replace() safer.

When an error occurs, we want to prevent overwriting any previous
version of the file by incomplete contents. So run
g_output_stream_close() with a cancelled GCancellable to do so.
See also discussion in #2565.
This commit is contained in:
Jehan 2018-11-26 15:40:38 +01:00
parent 076b53511a
commit 613bf7c5ab
12 changed files with 141 additions and 25 deletions

View File

@ -288,17 +288,25 @@ gimp_internal_data_save_data_file (Gimp *gimp,
success = FALSE;
}
}
else if (error && *error)
{
g_prefix_error (error,
_("Error saving '%s': "),
gimp_file_get_utf8_name (file));
}
else
{
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE,
_("Error saving '%s'"),
gimp_file_get_utf8_name (file));
GCancellable *cancellable = g_cancellable_new ();
g_cancellable_cancel (cancellable);
if (error && *error)
{
g_prefix_error (error,
_("Error saving '%s': "),
gimp_file_get_utf8_name (file));
}
else
{
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE,
_("Error saving '%s'"),
gimp_file_get_utf8_name (file));
}
g_output_stream_close (output, cancellable, NULL);
g_object_unref (cancellable);
}
g_object_unref (output);

View File

@ -138,12 +138,24 @@ gimp_tags_user_install (void)
else if (! g_output_stream_write_all (output,
tags_installer.buf->str,
tags_installer.buf->len,
NULL, NULL, &error) ||
! g_output_stream_close (output, NULL, &error))
NULL, NULL, &error))
{
GCancellable *cancellable = g_cancellable_new ();
g_printerr (_("Error writing '%s': %s"),
gimp_file_get_utf8_name (file), error->message);
result = FALSE;
/* Cancel the overwrite initiated by g_file_replace(). */
g_cancellable_cancel (cancellable);
g_output_stream_close (output, cancellable, NULL);
g_object_unref (cancellable);
}
else if (! g_output_stream_close (output, NULL, &error))
{
g_printerr (_("Error closing '%s': %s"),
gimp_file_get_utf8_name (file), error->message);
result = FALSE;
}
if (output)

View File

@ -592,17 +592,25 @@ gimp_data_save (GimpData *data,
success = FALSE;
}
}
else if (error && *error)
{
g_prefix_error (error,
_("Error saving '%s': "),
gimp_file_get_utf8_name (private->file));
}
else
{
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE,
_("Error saving '%s'"),
gimp_file_get_utf8_name (private->file));
GCancellable *cancellable = g_cancellable_new ();
g_cancellable_cancel (cancellable);
if (error && *error)
{
g_prefix_error (error,
_("Error saving '%s': "),
gimp_file_get_utf8_name (private->file));
}
else
{
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE,
_("Error saving '%s'"),
gimp_file_get_utf8_name (private->file));
}
g_output_stream_close (output, cancellable, NULL);
g_object_unref (cancellable);
}
g_object_unref (output);

View File

@ -207,13 +207,21 @@ gimp_gradient_save_pov (GimpGradient *gradient,
if (! g_output_stream_write_all (output, string->str, string->len,
NULL, NULL, &my_error))
{
GCancellable *cancellable = g_cancellable_new ();
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE,
_("Writing POV file '%s' failed: %s"),
gimp_file_get_utf8_name (file),
my_error->message);
g_clear_error (&my_error);
g_string_free (string, TRUE);
/* Cancel the overwrite initiated by g_file_replace(). */
g_cancellable_cancel (cancellable);
g_output_stream_close (output, cancellable, NULL);
g_object_unref (cancellable);
g_object_unref (output);
return FALSE;
}

View File

@ -430,11 +430,22 @@ gimp_tag_cache_save (GimpTagCache *cache)
g_printerr ("%s\n", error->message);
}
else if (! g_output_stream_write_all (output, buf->str, buf->len,
NULL, NULL, &error) ||
! g_output_stream_close (output, NULL, &error))
NULL, NULL, &error))
{
GCancellable *cancellable = g_cancellable_new ();
g_printerr (_("Error writing '%s': %s\n"),
gimp_file_get_utf8_name (file), error->message);
/* Cancel the overwrite initiated by g_file_replace(). */
g_cancellable_cancel (cancellable);
g_output_stream_close (output, cancellable, NULL);
g_object_unref (cancellable);
}
else if (! g_output_stream_close (output, NULL, &error))
{
g_printerr (_("Error closing '%s': %s\n"),
gimp_file_get_utf8_name (file), error->message);
}
if (output)

View File

@ -285,13 +285,26 @@ themes_apply_theme (Gimp *gimp,
"/* end of theme.css */\n",
gimp_file_get_utf8_name (css_user),
esc_css_theme,
esc_css_user) ||
! g_output_stream_close (output, NULL, &error))
esc_css_user))
{
GCancellable *cancellable = g_cancellable_new ();
gimp_message (gimp, NULL, GIMP_MESSAGE_ERROR,
_("Error writing '%s': %s"),
gimp_file_get_utf8_name (theme_css), error->message);
g_clear_error (&error);
/* Cancel the overwrite initiated by g_file_replace(). */
g_cancellable_cancel (cancellable);
g_output_stream_close (output, cancellable, NULL);
g_object_unref (cancellable);
}
else if (! g_output_stream_close (output, NULL, &error))
{
gimp_message (gimp, NULL, GIMP_MESSAGE_ERROR,
_("Error closing '%s': %s"),
gimp_file_get_utf8_name (theme_css), error->message);
g_clear_error (&error);
}
g_free (esc_css_theme);

View File

@ -136,10 +136,17 @@ gimp_pdb_dump (GimpPDB *pdb,
if (pdb_dump.error)
{
GCancellable *cancellable = g_cancellable_new ();
g_set_error (error, pdb_dump.error->domain, pdb_dump.error->code,
_("Writing PDB file '%s' failed: %s"),
gimp_file_get_utf8_name (file), pdb_dump.error->message);
g_clear_error (&pdb_dump.error);
/* Cancel the overwrite initiated by g_file_replace(). */
g_cancellable_cancel (cancellable);
g_output_stream_close (pdb_dump.output, cancellable, NULL);
g_object_unref (cancellable);
g_object_unref (pdb_dump.output);
return FALSE;

View File

@ -221,6 +221,8 @@ gimp_filter_tool_settings_export (GimpSettingsBox *box,
if (! tool_class->settings_export (filter_tool, output, &error))
{
GCancellable *cancellable = g_cancellable_new ();
gimp_message (GIMP_TOOL (filter_tool)->tool_info->gimp,
G_OBJECT (gimp_tool_gui_get_dialog (filter_tool->gui)),
GIMP_MESSAGE_ERROR,
@ -228,7 +230,13 @@ gimp_filter_tool_settings_export (GimpSettingsBox *box,
gimp_file_get_utf8_name (file),
error->message);
g_clear_error (&error);
/* Cancel the overwrite initiated by g_file_replace(). */
g_cancellable_cancel (cancellable);
g_output_stream_close (output, cancellable, NULL);
g_object_unref (cancellable);
g_object_unref (output);
return FALSE;
}

View File

@ -83,12 +83,20 @@ gimp_vectors_export_file (GimpImage *image,
if (! g_output_stream_write_all (output, string->str, string->len,
NULL, NULL, &my_error))
{
GCancellable *cancellable = g_cancellable_new ();
g_set_error (error, my_error->domain, my_error->code,
_("Writing SVG file '%s' failed: %s"),
gimp_file_get_utf8_name (file), my_error->message);
g_clear_error (&my_error);
g_string_free (string, TRUE);
/* Cancel the overwrite initiated by g_file_replace(). */
g_cancellable_cancel (cancellable);
g_output_stream_close (output, cancellable, NULL);
g_object_unref (cancellable);
g_object_unref (output);
return FALSE;
}

View File

@ -4344,8 +4344,15 @@ gimp_dashboard_log_start_recording (GimpDashboard *dashboard,
if (priv->log_error)
{
GCancellable *cancellable = g_cancellable_new ();
gimp_backtrace_stop ();
/* Cancel the overwrite initiated by g_file_replace(). */
g_cancellable_cancel (cancellable);
g_output_stream_close (priv->log_output, cancellable, NULL);
g_object_unref (cancellable);
g_clear_object (&priv->log_output);
g_propagate_error (error, priv->log_error);
@ -4422,7 +4429,18 @@ gimp_dashboard_log_stop_recording (GimpDashboard *dashboard,
gimp_backtrace_stop ();
if (! priv->log_error)
g_output_stream_close (priv->log_output, NULL, &priv->log_error);
{
g_output_stream_close (priv->log_output, NULL, &priv->log_error);
}
else
{
GCancellable *cancellable = g_cancellable_new ();
/* Cancel the overwrite initiated by g_file_replace(). */
g_cancellable_cancel (cancellable);
g_output_stream_close (priv->log_output, cancellable, NULL);
g_object_unref (cancellable);
}
g_clear_object (&priv->log_output);

View File

@ -1764,12 +1764,20 @@ gimp_text_buffer_save (GimpTextBuffer *buffer,
if (! g_output_stream_write_all (output, text_contents, text_length,
NULL, NULL, &my_error))
{
GCancellable *cancellable = g_cancellable_new ();
g_set_error (error, my_error->domain, my_error->code,
_("Writing text file '%s' failed: %s"),
gimp_file_get_utf8_name (file), my_error->message);
g_clear_error (&my_error);
g_free (text_contents);
/* Cancel the overwrite initiated by g_file_replace(). */
g_cancellable_cancel (cancellable);
g_output_stream_close (output, cancellable, NULL);
g_object_unref (cancellable);
g_object_unref (output);
return FALSE;
}

View File

@ -760,6 +760,13 @@ gimp_config_writer_close_output (GimpConfigWriter *writer,
if (writer->error)
{
GCancellable *cancellable = g_cancellable_new ();
/* Cancel the overwrite initiated by g_file_replace(). */
g_cancellable_cancel (cancellable);
g_output_stream_close (writer->output, cancellable, NULL);
g_object_unref (cancellable);
g_object_unref (writer->output);
writer->output = NULL;