Commit 53b58229 authored by Michael Natterer's avatar Michael Natterer 😴

libgimpconfig: port GimpConfigWriter to GIO

parent 4e6a6079
......@@ -47,6 +47,8 @@ AM_CPPFLAGS = \
-DG_LOG_DOMAIN=\"LibGimpConfig\" \
-DGIMP_CONFIG_COMPILATION \
-I$(top_srcdir) \
$(GIO_UNIX_CFLAGS) \
$(GIO_WINDOWS_CFLAGS) \
$(GEGL_CFLAGS) \
$(CAIRO_CFLAGS) \
$(GDK_PIXBUF_CFLAGS) \
......@@ -113,11 +115,13 @@ libgimpconfig_@GIMP_API_VERSION@_la_LDFLAGS = \
EXTRA_libgimpconfig_@GIMP_API_VERSION@_la_DEPENDENCIES = $(gimpconfig_def)
libgimpconfig_@GIMP_API_VERSION@_la_LIBADD = \
$(libgimpbase) \
$(libgimpcolor) \
$(libgimpmath) \
$(GEGL_LIBS) \
$(CAIRO_LIBS) \
$(libgimpbase) \
$(libgimpcolor) \
$(libgimpmath) \
$(GIO_UNIX_LIBS) \
$(GIO_WINDOWS_LIBS) \
$(GEGL_LIBS) \
$(CAIRO_LIBS) \
$(GDK_PIXBUF_LIBS)
......
......@@ -21,21 +21,14 @@
#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>
#include <gio/gio.h>
#include <glib/gstdio.h>
#ifdef G_OS_WIN32
#include <io.h>
#include <gio/gwin32outputstream.h>
#else
#include <gio/gunixoutputstream.h>
#endif
#include "libgimpbase/gimpbase.h"
......@@ -63,14 +56,13 @@
struct _GimpConfigWriter
{
gint fd;
gchar *filename;
gchar *tmpname;
GError *error;
GString *buffer;
gboolean comment;
gint depth;
gint marker;
GOutputStream *output;
GFile *file;
GError *error;
GString *buffer;
gboolean comment;
gint depth;
gint marker;
};
......@@ -82,10 +74,27 @@ static gboolean gimp_config_writer_close_file (GimpConfigWriter *writer,
static inline void
gimp_config_writer_flush (GimpConfigWriter *writer)
{
if (write (writer->fd, writer->buffer->str, writer->buffer->len) < 0)
g_set_error (&writer->error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
_("Error writing to '%s': %s"),
gimp_filename_to_utf8 (writer->filename), g_strerror (errno));
gsize bytes_written;
GError *error = NULL;
if (! g_output_stream_write_all (writer->output,
writer->buffer->str,
writer->buffer->len,
&bytes_written,
NULL, &error))
{
const gchar *path;
if (writer->file)
path = gimp_file_get_utf8_name (writer->file);
else
path = "file descriptor";
g_set_error (&writer->error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
_("Error writing to '%s': %s"),
path, error->message);
g_clear_error (&error);
}
g_string_truncate (writer->buffer, 0);
}
......@@ -127,52 +136,16 @@ gimp_config_writer_new_file (const gchar *filename,
GError **error)
{
GimpConfigWriter *writer;
gchar *tmpname = NULL;
gint fd;
GFile *file;
g_return_val_if_fail (filename != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
if (atomic)
{
tmpname = g_strconcat (filename, "XXXXXX", NULL);
fd = g_mkstemp (tmpname);
file = g_file_new_for_path (filename);
if (fd == -1)
{
g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
_("Could not create temporary file for '%s': %s"),
gimp_filename_to_utf8 (filename), g_strerror (errno));
g_free (tmpname);
return NULL;
}
}
else
{
fd = g_creat (filename, 0644);
writer = gimp_config_writer_new_gfile (file, atomic, header, error);
if (fd == -1)
{
g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
_("Could not open '%s' for writing: %s"),
gimp_filename_to_utf8 (filename), g_strerror (errno));
return NULL;
}
}
writer = g_slice_new0 (GimpConfigWriter);
writer->fd = fd;
writer->filename = g_strdup (filename);
writer->tmpname = tmpname;
writer->buffer = g_string_new (NULL);
if (header)
{
gimp_config_writer_comment (writer, header);
gimp_config_writer_linefeed (writer);
}
g_object_unref (file);
return writer;
}
......@@ -200,15 +173,50 @@ gimp_config_writer_new_gfile (GFile *file,
GError **error)
{
GimpConfigWriter *writer;
gchar *path;
GOutputStream *output;
GError *my_error = NULL;
g_return_val_if_fail (G_IS_FILE (file), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
path = g_file_get_path (file);
if (atomic)
{
output = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE,
G_FILE_CREATE_NONE,
NULL, &my_error));
if (! output)
g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
_("Could not create temporary file for '%s': %s"),
gimp_file_get_utf8_name (file), my_error->message);
}
else
{
output = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE,
G_FILE_CREATE_REPLACE_DESTINATION,
NULL, &my_error));
if (! output)
g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
_("Could not open '%s' for writing: %s"),
gimp_file_get_utf8_name (file), my_error->message);
}
writer = gimp_config_writer_new_file (path, atomic, header, error);
if (! output)
{
g_clear_error (&my_error);
return NULL;
}
g_free (path);
writer = g_slice_new0 (GimpConfigWriter);
writer->output = output;
writer->file = g_object_ref (file);
writer->buffer = g_string_new (NULL);
if (header)
{
gimp_config_writer_comment (writer, header);
gimp_config_writer_linefeed (writer);
}
return writer;
}
......@@ -230,7 +238,12 @@ gimp_config_writer_new_fd (gint fd)
writer = g_slice_new0 (GimpConfigWriter);
writer->fd = fd;
#ifdef G_OS_WIN32
writer->output = g_win32_input_stream_new ((HANDLE *) fd, FALSE);
#else
writer->output = g_unix_output_stream_new (fd, FALSE);
#endif
writer->buffer = g_string_new (NULL);
return writer;
......@@ -529,7 +542,7 @@ gimp_config_writer_close (GimpConfigWriter *writer)
{
g_string_append_c (writer->buffer, '\n');
if (writer->fd)
if (writer->output)
gimp_config_writer_flush (writer);
}
}
......@@ -576,19 +589,15 @@ gimp_config_writer_finish (GimpConfigWriter *writer,
gimp_config_writer_comment (writer, footer);
}
if (writer->fd)
if (writer->output)
{
success = gimp_config_writer_close_file (writer, error);
g_free (writer->filename);
g_free (writer->tmpname);
if (writer->file)
g_object_unref (writer->file);
g_string_free (writer->buffer, TRUE);
}
else
{
success = TRUE;
}
if (writer->error)
{
......@@ -611,10 +620,18 @@ gimp_config_writer_linefeed (GimpConfigWriter *writer)
if (writer->buffer->len == 0 && !writer->comment)
{
if (write (writer->fd, "\n", 1) < 0)
g_set_error_literal (&writer->error,
GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
g_strerror (errno));
gsize bytes_written;
GError *error = NULL;
if (! g_output_stream_write_all (writer->output, "\n", 1,
&bytes_written,
NULL, &error))
{
g_set_error (&writer->error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
_("Error writing to '%s': %s"),
gimp_file_get_utf8_name (writer->file), error->message);
g_clear_error (&error);
}
}
else
{
......@@ -695,93 +712,35 @@ static gboolean
gimp_config_writer_close_file (GimpConfigWriter *writer,
GError **error)
{
g_return_val_if_fail (writer->fd != 0, FALSE);
GError *my_error = NULL;
if (! writer->filename)
g_return_val_if_fail (writer->output != NULL, FALSE);
if (! writer->file)
return TRUE;
if (writer->error)
{
close (writer->fd);
if (writer->tmpname)
g_unlink (writer->tmpname);
g_object_unref (writer->output);
writer->output = NULL;
return FALSE;
}
#ifdef HAVE_FSYNC
/* If the final destination exists, we want to sync the newly written
* file to ensure the data is on disk when we rename over the destination.
* otherwise if we get a system crash we can lose both the new and the
* old file on some filesystems. (I.E. those that don't guarantee the
* data is written to the disk before the metadata.)
*/
if (writer->tmpname && g_file_test (writer->filename, G_FILE_TEST_EXISTS))
if (! g_output_stream_close (writer->output, NULL, &my_error))
{
if (fsync (writer->fd) != 0)
{
g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
_("Error writing to temporary file for '%s': %s\n"
"The original file has not been touched."),
gimp_filename_to_utf8 (writer->filename),
g_strerror (errno));
close (writer->fd);
g_unlink (writer->tmpname);
g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
_("Error writing '%s': %s"),
gimp_file_get_utf8_name (writer->file), my_error->message);
g_clear_error (&my_error);
return FALSE;
}
}
#endif
if (close (writer->fd) != 0)
{
if (writer->tmpname)
{
if (g_file_test (writer->filename, G_FILE_TEST_EXISTS))
{
g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
_("Error writing to temporary file for '%s': %s\n"
"The original file has not been touched."),
gimp_filename_to_utf8 (writer->filename),
g_strerror (errno));
}
else
{
g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
_("Error writing to temporary file for '%s': %s\n"
"No file has been created."),
gimp_filename_to_utf8 (writer->filename),
g_strerror (errno));
}
g_unlink (writer->tmpname);
}
else
{
g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
_("Error writing to '%s': %s"),
gimp_filename_to_utf8 (writer->filename),
g_strerror (errno));
}
g_object_unref (writer->output);
writer->output = NULL;
return FALSE;
}
if (writer->tmpname)
{
if (g_rename (writer->tmpname, writer->filename) == -1)
{
g_set_error (error, GIMP_CONFIG_ERROR, GIMP_CONFIG_ERROR_WRITE,
_("Could not create '%s': %s"),
gimp_filename_to_utf8 (writer->filename),
g_strerror (errno));
g_unlink (writer->tmpname);
return FALSE;
}
}
g_object_unref (writer->output);
writer->output = NULL;
return TRUE;
}
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