Commit 613bf7c5 authored by Jehan's avatar Jehan

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.
parent 076b5351
...@@ -288,17 +288,25 @@ gimp_internal_data_save_data_file (Gimp *gimp, ...@@ -288,17 +288,25 @@ gimp_internal_data_save_data_file (Gimp *gimp,
success = FALSE; success = FALSE;
} }
} }
else if (error && *error)
{
g_prefix_error (error,
_("Error saving '%s': "),
gimp_file_get_utf8_name (file));
}
else else
{ {
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE, GCancellable *cancellable = g_cancellable_new ();
_("Error saving '%s'"),
gimp_file_get_utf8_name (file)); 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); g_object_unref (output);
......
...@@ -138,12 +138,24 @@ gimp_tags_user_install (void) ...@@ -138,12 +138,24 @@ gimp_tags_user_install (void)
else if (! g_output_stream_write_all (output, else if (! g_output_stream_write_all (output,
tags_installer.buf->str, tags_installer.buf->str,
tags_installer.buf->len, tags_installer.buf->len,
NULL, NULL, &error) || NULL, NULL, &error))
! g_output_stream_close (output, NULL, &error))
{ {
GCancellable *cancellable = g_cancellable_new ();
g_printerr (_("Error writing '%s': %s"), g_printerr (_("Error writing '%s': %s"),
gimp_file_get_utf8_name (file), error->message); gimp_file_get_utf8_name (file), error->message);
result = FALSE; 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) if (output)
......
...@@ -592,17 +592,25 @@ gimp_data_save (GimpData *data, ...@@ -592,17 +592,25 @@ gimp_data_save (GimpData *data,
success = FALSE; success = FALSE;
} }
} }
else if (error && *error)
{
g_prefix_error (error,
_("Error saving '%s': "),
gimp_file_get_utf8_name (private->file));
}
else else
{ {
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE, GCancellable *cancellable = g_cancellable_new ();
_("Error saving '%s'"),
gimp_file_get_utf8_name (private->file)); 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); g_object_unref (output);
......
...@@ -207,13 +207,21 @@ gimp_gradient_save_pov (GimpGradient *gradient, ...@@ -207,13 +207,21 @@ gimp_gradient_save_pov (GimpGradient *gradient,
if (! g_output_stream_write_all (output, string->str, string->len, if (! g_output_stream_write_all (output, string->str, string->len,
NULL, NULL, &my_error)) NULL, NULL, &my_error))
{ {
GCancellable *cancellable = g_cancellable_new ();
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE, g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE,
_("Writing POV file '%s' failed: %s"), _("Writing POV file '%s' failed: %s"),
gimp_file_get_utf8_name (file), gimp_file_get_utf8_name (file),
my_error->message); my_error->message);
g_clear_error (&my_error); g_clear_error (&my_error);
g_string_free (string, TRUE); 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); g_object_unref (output);
return FALSE; return FALSE;
} }
......
...@@ -430,11 +430,22 @@ gimp_tag_cache_save (GimpTagCache *cache) ...@@ -430,11 +430,22 @@ gimp_tag_cache_save (GimpTagCache *cache)
g_printerr ("%s\n", error->message); g_printerr ("%s\n", error->message);
} }
else if (! g_output_stream_write_all (output, buf->str, buf->len, else if (! g_output_stream_write_all (output, buf->str, buf->len,
NULL, NULL, &error) || NULL, NULL, &error))
! g_output_stream_close (output, NULL, &error))
{ {
GCancellable *cancellable = g_cancellable_new ();
g_printerr (_("Error writing '%s': %s\n"), g_printerr (_("Error writing '%s': %s\n"),
gimp_file_get_utf8_name (file), error->message); 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) if (output)
......
...@@ -285,13 +285,26 @@ themes_apply_theme (Gimp *gimp, ...@@ -285,13 +285,26 @@ themes_apply_theme (Gimp *gimp,
"/* end of theme.css */\n", "/* end of theme.css */\n",
gimp_file_get_utf8_name (css_user), gimp_file_get_utf8_name (css_user),
esc_css_theme, esc_css_theme,
esc_css_user) || esc_css_user))
! g_output_stream_close (output, NULL, &error))
{ {
GCancellable *cancellable = g_cancellable_new ();
gimp_message (gimp, NULL, GIMP_MESSAGE_ERROR, gimp_message (gimp, NULL, GIMP_MESSAGE_ERROR,
_("Error writing '%s': %s"), _("Error writing '%s': %s"),
gimp_file_get_utf8_name (theme_css), error->message); gimp_file_get_utf8_name (theme_css), error->message);
g_clear_error (&error); 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); g_free (esc_css_theme);
......
...@@ -136,10 +136,17 @@ gimp_pdb_dump (GimpPDB *pdb, ...@@ -136,10 +136,17 @@ gimp_pdb_dump (GimpPDB *pdb,
if (pdb_dump.error) if (pdb_dump.error)
{ {
GCancellable *cancellable = g_cancellable_new ();
g_set_error (error, pdb_dump.error->domain, pdb_dump.error->code, g_set_error (error, pdb_dump.error->domain, pdb_dump.error->code,
_("Writing PDB file '%s' failed: %s"), _("Writing PDB file '%s' failed: %s"),
gimp_file_get_utf8_name (file), pdb_dump.error->message); gimp_file_get_utf8_name (file), pdb_dump.error->message);
g_clear_error (&pdb_dump.error); 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); g_object_unref (pdb_dump.output);
return FALSE; return FALSE;
......
...@@ -221,6 +221,8 @@ gimp_filter_tool_settings_export (GimpSettingsBox *box, ...@@ -221,6 +221,8 @@ gimp_filter_tool_settings_export (GimpSettingsBox *box,
if (! tool_class->settings_export (filter_tool, output, &error)) if (! tool_class->settings_export (filter_tool, output, &error))
{ {
GCancellable *cancellable = g_cancellable_new ();
gimp_message (GIMP_TOOL (filter_tool)->tool_info->gimp, gimp_message (GIMP_TOOL (filter_tool)->tool_info->gimp,
G_OBJECT (gimp_tool_gui_get_dialog (filter_tool->gui)), G_OBJECT (gimp_tool_gui_get_dialog (filter_tool->gui)),
GIMP_MESSAGE_ERROR, GIMP_MESSAGE_ERROR,
...@@ -228,7 +230,13 @@ gimp_filter_tool_settings_export (GimpSettingsBox *box, ...@@ -228,7 +230,13 @@ gimp_filter_tool_settings_export (GimpSettingsBox *box,
gimp_file_get_utf8_name (file), gimp_file_get_utf8_name (file),
error->message); error->message);
g_clear_error (&error); 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); g_object_unref (output);
return FALSE; return FALSE;
} }
......
...@@ -83,12 +83,20 @@ gimp_vectors_export_file (GimpImage *image, ...@@ -83,12 +83,20 @@ gimp_vectors_export_file (GimpImage *image,
if (! g_output_stream_write_all (output, string->str, string->len, if (! g_output_stream_write_all (output, string->str, string->len,
NULL, NULL, &my_error)) NULL, NULL, &my_error))
{ {
GCancellable *cancellable = g_cancellable_new ();
g_set_error (error, my_error->domain, my_error->code, g_set_error (error, my_error->domain, my_error->code,
_("Writing SVG file '%s' failed: %s"), _("Writing SVG file '%s' failed: %s"),
gimp_file_get_utf8_name (file), my_error->message); gimp_file_get_utf8_name (file), my_error->message);
g_clear_error (&my_error); g_clear_error (&my_error);
g_string_free (string, TRUE); 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); g_object_unref (output);
return FALSE; return FALSE;
} }
......
...@@ -4344,8 +4344,15 @@ gimp_dashboard_log_start_recording (GimpDashboard *dashboard, ...@@ -4344,8 +4344,15 @@ gimp_dashboard_log_start_recording (GimpDashboard *dashboard,
if (priv->log_error) if (priv->log_error)
{ {
GCancellable *cancellable = g_cancellable_new ();
gimp_backtrace_stop (); 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_clear_object (&priv->log_output);
g_propagate_error (error, priv->log_error); g_propagate_error (error, priv->log_error);
...@@ -4422,7 +4429,18 @@ gimp_dashboard_log_stop_recording (GimpDashboard *dashboard, ...@@ -4422,7 +4429,18 @@ gimp_dashboard_log_stop_recording (GimpDashboard *dashboard,
gimp_backtrace_stop (); gimp_backtrace_stop ();
if (! priv->log_error) 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); g_clear_object (&priv->log_output);
......
...@@ -1764,12 +1764,20 @@ gimp_text_buffer_save (GimpTextBuffer *buffer, ...@@ -1764,12 +1764,20 @@ gimp_text_buffer_save (GimpTextBuffer *buffer,
if (! g_output_stream_write_all (output, text_contents, text_length, if (! g_output_stream_write_all (output, text_contents, text_length,
NULL, NULL, &my_error)) NULL, NULL, &my_error))
{ {
GCancellable *cancellable = g_cancellable_new ();
g_set_error (error, my_error->domain, my_error->code, g_set_error (error, my_error->domain, my_error->code,
_("Writing text file '%s' failed: %s"), _("Writing text file '%s' failed: %s"),
gimp_file_get_utf8_name (file), my_error->message); gimp_file_get_utf8_name (file), my_error->message);
g_clear_error (&my_error); g_clear_error (&my_error);
g_free (text_contents); 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); g_object_unref (output);
return FALSE; return FALSE;
} }
......
...@@ -760,6 +760,13 @@ gimp_config_writer_close_output (GimpConfigWriter *writer, ...@@ -760,6 +760,13 @@ gimp_config_writer_close_output (GimpConfigWriter *writer,
if (writer->error) 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); g_object_unref (writer->output);
writer->output = NULL; writer->output = NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment