Add GFileIOStream class
authorAlexander Larsson <alexl@redhat.com>
Tue, 12 May 2009 14:59:36 +0000 (16:59 +0200)
committerAlexander Larsson <alexl@redhat.com>
Wed, 13 May 2009 12:42:46 +0000 (14:42 +0200)
This is similar to GFileInputStream and GFileOutputStream for GIOStreams.
The default implementations chain to the Output stream.

gio/Makefile.am
gio/gfileiostream.c [new file with mode: 0644]
gio/gfileiostream.h [new file with mode: 0644]
gio/gio.h
gio/gio.symbols
gio/giostream.c
gio/giotypes.h

index 78c2c3f..76e402d 100644 (file)
@@ -199,6 +199,7 @@ libgio_2_0_la_SOURCES =             \
        gfilemonitor.c          \
        gfilenamecompleter.c    \
        gfileoutputstream.c     \
+       gfileiostream.c         \
        gfilterinputstream.c    \
        gfilteroutputstream.c   \
        gicon.c                 \
@@ -315,6 +316,7 @@ gio_headers =                       \
        gfilemonitor.h          \
        gfilenamecompleter.h    \
        gfileoutputstream.h     \
+       gfileiostream.h         \
        gfilterinputstream.h    \
        gfilteroutputstream.h   \
        gicon.h                 \
diff --git a/gio/gfileiostream.c b/gio/gfileiostream.c
new file mode 100644 (file)
index 0000000..9491e76
--- /dev/null
@@ -0,0 +1,671 @@
+/* GIO - GLib Input, IO and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <gfileiostream.h>
+#include <gseekable.h>
+#include "gsimpleasyncresult.h"
+#include "gasyncresult.h"
+#include "gcancellable.h"
+#include "gioerror.h"
+#include "gfileoutputstream.h"
+#include "glibintl.h"
+
+#include "gioalias.h"
+
+/**
+ * SECTION:gfileiostream
+ * @short_description: read write streams for File
+ * @include: gio/gio.h
+ * @see_also: #GIOStream, #GFileInputStream, #GFileOutputStream, #GSeekable
+ *
+ * GFileIOStream provides io streams that both read and write to the same
+ * file handle.
+ *
+ * GFileIOStream implements #GSeekable, which allows the io
+ * stream to jump to arbitrary positions in the file and to truncate
+ * the file, provided the filesystem of the file supports these
+ * operations. In addition to the generic g_seekable_ API,
+ * GFileIOStream has its own API for seeking and positioning.
+ * To find the position of a file io stream, use
+ * g_file_io_stream_tell(). To find out if a file io
+ * stream supports seeking, use g_file_io_stream_can_seek().
+ * To position a file io stream, use g_file_io_stream_seek().
+ * To find out if a file io stream supports truncating, use
+ * g_file_io_stream_can_truncate(). To truncate a file io
+ * stream, use g_file_io_stream_truncate().
+ *
+ * Since: 2.22
+ **/
+
+static void       g_file_io_stream_seekable_iface_init    (GSeekableIface       *iface);
+static goffset    g_file_io_stream_seekable_tell          (GSeekable            *seekable);
+static gboolean   g_file_io_stream_seekable_can_seek      (GSeekable            *seekable);
+static gboolean   g_file_io_stream_seekable_seek          (GSeekable            *seekable,
+                                                          goffset               offset,
+                                                          GSeekType             type,
+                                                          GCancellable         *cancellable,
+                                                          GError              **error);
+static gboolean   g_file_io_stream_seekable_can_truncate  (GSeekable            *seekable);
+static gboolean   g_file_io_stream_seekable_truncate      (GSeekable            *seekable,
+                                                          goffset               offset,
+                                                          GCancellable         *cancellable,
+                                                          GError              **error);
+static void       g_file_io_stream_real_query_info_async  (GFileIOStream    *stream,
+                                                          const char           *attributes,
+                                                          int                   io_priority,
+                                                          GCancellable         *cancellable,
+                                                          GAsyncReadyCallback   callback,
+                                                          gpointer              user_data);
+static GFileInfo *g_file_io_stream_real_query_info_finish (GFileIOStream    *stream,
+                                                          GAsyncResult         *result,
+                                                          GError              **error);
+
+G_DEFINE_TYPE_WITH_CODE (GFileIOStream, g_file_io_stream, G_TYPE_IO_STREAM,
+                        G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
+                                               g_file_io_stream_seekable_iface_init));
+
+struct _GFileIOStreamPrivate {
+  GAsyncReadyCallback outstanding_callback;
+};
+
+static void
+g_file_io_stream_seekable_iface_init (GSeekableIface *iface)
+{
+  iface->tell = g_file_io_stream_seekable_tell;
+  iface->can_seek = g_file_io_stream_seekable_can_seek;
+  iface->seek = g_file_io_stream_seekable_seek;
+  iface->can_truncate = g_file_io_stream_seekable_can_truncate;
+  iface->truncate_fn = g_file_io_stream_seekable_truncate;
+}
+
+static void
+g_file_io_stream_init (GFileIOStream *stream)
+{
+  stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
+                                             G_TYPE_FILE_IO_STREAM,
+                                             GFileIOStreamPrivate);
+}
+
+/**
+ * g_file_io_stream_query_info:
+ * @stream: a #GFileIOStream.
+ * @attributes: a file attribute query string.
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @error: a #GError, %NULL to ignore.
+ *
+ * Queries a file io stream for the given @attributes.
+ * This function blocks while querying the stream. For the asynchronous
+ * version of this function, see g_file_io_stream_query_info_async().
+ * While the stream is blocked, the stream will set the pending flag
+ * internally, and any other operations on the stream will fail with
+ * %G_IO_ERROR_PENDING.
+ *
+ * Can fail if the stream was already closed (with @error being set to
+ * %G_IO_ERROR_CLOSED), the stream has pending operations (with @error being
+ * set to %G_IO_ERROR_PENDING), or if querying info is not supported for
+ * the stream's interface (with @error being set to %G_IO_ERROR_NOT_SUPPORTED). I
+ * all cases of failure, %NULL will be returned.
+ *
+ * If @cancellable is not %NULL, then the operation can be cancelled by
+ * triggering the cancellable object from another thread. If the operation
+ * was cancelled, the error %G_IO_ERROR_CANCELLED will be set, and %NULL will
+ * be returned.
+ *
+ * Returns: a #GFileInfo for the @stream, or %NULL on error.
+ *
+ * Since: 2.22
+ **/
+GFileInfo *
+g_file_io_stream_query_info (GFileIOStream      *stream,
+                            const char             *attributes,
+                            GCancellable           *cancellable,
+                            GError                **error)
+{
+  GFileIOStreamClass *class;
+  GIOStream *io_stream;
+  GFileInfo *info;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), NULL);
+
+  io_stream = G_IO_STREAM (stream);
+
+  if (!g_io_stream_set_pending (io_stream, error))
+    return NULL;
+
+  info = NULL;
+
+  if (cancellable)
+    g_cancellable_push_current (cancellable);
+
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+  if (class->query_info)
+    info = class->query_info (stream, attributes, cancellable, error);
+  else
+    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                         _("Stream doesn't support query_info"));
+
+  if (cancellable)
+    g_cancellable_pop_current (cancellable);
+
+  g_io_stream_clear_pending (io_stream);
+
+  return info;
+}
+
+static void
+async_ready_callback_wrapper (GObject *source_object,
+                             GAsyncResult *res,
+                             gpointer      user_data)
+{
+  GFileIOStream *stream = G_FILE_IO_STREAM (source_object);
+
+  g_io_stream_clear_pending (G_IO_STREAM (stream));
+  if (stream->priv->outstanding_callback)
+    (*stream->priv->outstanding_callback) (source_object, res, user_data);
+  g_object_unref (stream);
+}
+
+/**
+ * g_file_io_stream_query_info_async:
+ * @stream: a #GFileIOStream.
+ * @attributes: a file attribute query string.
+ * @io_priority: the <link linkend="gio-GIOScheduler">I/O priority</link>
+ *     of the request.
+ * @cancellable: optional #GCancellable object, %NULL to ignore.
+ * @callback: callback to call when the request is satisfied
+ * @user_data: the data to pass to callback function
+ *
+ * Asynchronously queries the @stream for a #GFileInfo. When completed,
+ * @callback will be called with a #GAsyncResult which can be used to
+ * finish the operation with g_file_io_stream_query_info_finish().
+ *
+ * For the synchronous version of this function, see
+ * g_file_io_stream_query_info().
+ *
+ * Since: 2.22
+ **/
+void
+g_file_io_stream_query_info_async (GFileIOStream     *stream,
+                                         const char           *attributes,
+                                         int                   io_priority,
+                                         GCancellable         *cancellable,
+                                         GAsyncReadyCallback   callback,
+                                         gpointer              user_data)
+{
+  GFileIOStreamClass *klass;
+  GIOStream *io_stream;
+  GError *error = NULL;
+
+  g_return_if_fail (G_IS_FILE_IO_STREAM (stream));
+
+  io_stream = G_IO_STREAM (stream);
+
+  if (!g_io_stream_set_pending (io_stream, &error))
+    {
+      g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
+                                           callback,
+                                           user_data,
+                                           error);
+      g_error_free (error);
+      return;
+    }
+
+  klass = G_FILE_IO_STREAM_GET_CLASS (stream);
+
+  stream->priv->outstanding_callback = callback;
+  g_object_ref (stream);
+  klass->query_info_async (stream, attributes, io_priority, cancellable,
+                             async_ready_callback_wrapper, user_data);
+}
+
+/**
+ * g_file_io_stream_query_info_finish:
+ * @stream: a #GFileIOStream.
+ * @result: a #GAsyncResult.
+ * @error: a #GError, %NULL to ignore.
+ *
+ * Finalizes the asynchronous query started
+ * by g_file_io_stream_query_info_async().
+ *
+ * Returns: A #GFileInfo for the finished query.
+ *
+ * Since: 2.22
+ **/
+GFileInfo *
+g_file_io_stream_query_info_finish (GFileIOStream     *stream,
+                                          GAsyncResult         *result,
+                                          GError              **error)
+{
+  GSimpleAsyncResult *simple;
+  GFileIOStreamClass *class;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), NULL);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+  if (G_IS_SIMPLE_ASYNC_RESULT (result))
+    {
+      simple = G_SIMPLE_ASYNC_RESULT (result);
+      if (g_simple_async_result_propagate_error (simple, error))
+       return NULL;
+    }
+
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+  return class->query_info_finish (stream, result, error);
+}
+
+/**
+ * g_file_io_stream_get_etag:
+ * @stream: a #GFileIOStream.
+ *
+ * Gets the entity tag for the file when it has been written.
+ * This must be called after the stream has been written
+ * and closed, as the etag can change while writing.
+ *
+ * Returns: the entity tag for the stream.
+ *
+ * Since: 2.22
+ **/
+char *
+g_file_io_stream_get_etag (GFileIOStream  *stream)
+{
+  GFileIOStreamClass *class;
+  GIOStream *io_stream;
+  char *etag;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), NULL);
+
+  io_stream = G_IO_STREAM (stream);
+
+  if (!g_io_stream_is_closed (io_stream))
+    {
+      g_warning ("stream is not closed yet, can't get etag");
+      return NULL;
+    }
+
+  etag = NULL;
+
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+  if (class->get_etag)
+    etag = class->get_etag (stream);
+
+  return etag;
+}
+
+static goffset
+g_file_io_stream_tell (GFileIOStream  *stream)
+{
+  GFileIOStreamClass *class;
+  goffset offset;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), 0);
+
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+
+  offset = 0;
+  if (class->tell)
+    offset = class->tell (stream);
+
+  return offset;
+}
+
+static goffset
+g_file_io_stream_seekable_tell (GSeekable *seekable)
+{
+  return g_file_io_stream_tell (G_FILE_IO_STREAM (seekable));
+}
+
+static gboolean
+g_file_io_stream_can_seek (GFileIOStream  *stream)
+{
+  GFileIOStreamClass *class;
+  gboolean can_seek;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), FALSE);
+
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+
+  can_seek = FALSE;
+  if (class->seek)
+    {
+      can_seek = TRUE;
+      if (class->can_seek)
+       can_seek = class->can_seek (stream);
+    }
+
+  return can_seek;
+}
+
+static gboolean
+g_file_io_stream_seekable_can_seek (GSeekable *seekable)
+{
+  return g_file_io_stream_can_seek (G_FILE_IO_STREAM (seekable));
+}
+
+static gboolean
+g_file_io_stream_seek (GFileIOStream  *stream,
+                      goffset             offset,
+                      GSeekType           type,
+                      GCancellable       *cancellable,
+                      GError            **error)
+{
+  GFileIOStreamClass *class;
+  GIOStream *io_stream;
+  gboolean res;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), FALSE);
+
+  io_stream = G_IO_STREAM (stream);
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+
+  if (!class->seek)
+    {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                           _("Seek not supported on stream"));
+      return FALSE;
+    }
+
+  if (!g_io_stream_set_pending (io_stream, error))
+    return FALSE;
+
+  if (cancellable)
+    g_cancellable_push_current (cancellable);
+
+  res = class->seek (stream, offset, type, cancellable, error);
+
+  if (cancellable)
+    g_cancellable_pop_current (cancellable);
+
+  g_io_stream_clear_pending (io_stream);
+
+  return res;
+}
+
+static gboolean
+g_file_io_stream_seekable_seek (GSeekable  *seekable,
+                                   goffset     offset,
+                                   GSeekType   type,
+                                   GCancellable  *cancellable,
+                                   GError    **error)
+{
+  return g_file_io_stream_seek (G_FILE_IO_STREAM (seekable),
+                               offset, type, cancellable, error);
+}
+
+static gboolean
+g_file_io_stream_can_truncate (GFileIOStream  *stream)
+{
+  GFileIOStreamClass *class;
+  gboolean can_truncate;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), FALSE);
+
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+
+  can_truncate = FALSE;
+  if (class->truncate_fn)
+    {
+      can_truncate = TRUE;
+      if (class->can_truncate)
+       can_truncate = class->can_truncate (stream);
+    }
+
+  return can_truncate;
+}
+
+static gboolean
+g_file_io_stream_seekable_can_truncate (GSeekable  *seekable)
+{
+  return g_file_io_stream_can_truncate (G_FILE_IO_STREAM (seekable));
+}
+
+static gboolean
+g_file_io_stream_truncate (GFileIOStream  *stream,
+                          goffset             size,
+                          GCancellable       *cancellable,
+                          GError            **error)
+{
+  GFileIOStreamClass *class;
+  GIOStream *io_stream;
+  gboolean res;
+
+  g_return_val_if_fail (G_IS_FILE_IO_STREAM (stream), FALSE);
+
+  io_stream = G_IO_STREAM (stream);
+  class = G_FILE_IO_STREAM_GET_CLASS (stream);
+
+  if (!class->truncate_fn)
+    {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                           _("Truncate not supported on stream"));
+      return FALSE;
+    }
+
+  if (!g_io_stream_set_pending (io_stream, error))
+    return FALSE;
+
+  if (cancellable)
+    g_cancellable_push_current (cancellable);
+
+  res = class->truncate_fn (stream, size, cancellable, error);
+
+  if (cancellable)
+    g_cancellable_pop_current (cancellable);
+
+  g_io_stream_clear_pending (io_stream);
+
+  return res;
+}
+
+static gboolean
+g_file_io_stream_seekable_truncate (GSeekable     *seekable,
+                                   goffset        size,
+                                   GCancellable  *cancellable,
+                                   GError       **error)
+{
+  return g_file_io_stream_truncate (G_FILE_IO_STREAM (seekable),
+                                       size, cancellable, error);
+}
+/*****************************************************
+ *   Default implementations based on output stream  *
+ *****************************************************/
+
+static goffset
+g_file_io_stream_real_tell (GFileIOStream    *stream)
+{
+  GOutputStream *out;
+  GSeekable *seekable;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  seekable = G_SEEKABLE (out);
+
+  return g_seekable_tell (seekable);
+}
+
+static gboolean
+g_file_io_stream_real_can_seek (GFileIOStream    *stream)
+{
+  GOutputStream *out;
+  GSeekable *seekable;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  seekable = G_SEEKABLE (out);
+
+  return g_seekable_can_seek (seekable);
+}
+
+static gboolean
+g_file_io_stream_real_seek (GFileIOStream    *stream,
+                           goffset           offset,
+                           GSeekType         type,
+                           GCancellable     *cancellable,
+                           GError          **error)
+{
+  GOutputStream *out;
+  GSeekable *seekable;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  seekable = G_SEEKABLE (out);
+
+  return g_seekable_seek (seekable, offset, type, cancellable, error);
+}
+
+static  gboolean
+g_file_io_stream_real_can_truncate (GFileIOStream    *stream)
+{
+  GOutputStream *out;
+  GSeekable *seekable;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  seekable = G_SEEKABLE (out);
+
+  return g_seekable_can_truncate (seekable);
+}
+
+static gboolean
+g_file_io_stream_real_truncate_fn (GFileIOStream    *stream,
+                                  goffset               size,
+                                  GCancellable         *cancellable,
+                                  GError              **error)
+{
+  GOutputStream *out;
+  GSeekable *seekable;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  seekable = G_SEEKABLE (out);
+
+  return g_seekable_truncate (seekable, size, cancellable, error);
+}
+
+static char *
+g_file_io_stream_real_get_etag (GFileIOStream    *stream)
+{
+  GOutputStream *out;
+  GFileOutputStream *file_out;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  file_out = G_FILE_OUTPUT_STREAM (out);
+
+  return g_file_output_stream_get_etag (file_out);
+}
+
+static GFileInfo *
+g_file_io_stream_real_query_info (GFileIOStream    *stream,
+                                 const char           *attributes,
+                                 GCancellable         *cancellable,
+                                 GError              **error)
+{
+  GOutputStream *out;
+  GFileOutputStream *file_out;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  file_out = G_FILE_OUTPUT_STREAM (out);
+
+  return g_file_output_stream_query_info (file_out,
+                                         attributes, cancellable, error);
+}
+
+typedef struct {
+  GObject *object;
+  GAsyncReadyCallback callback;
+  gpointer user_data;
+} AsyncOpWrapper;
+
+static AsyncOpWrapper *
+async_op_wrapper_new (gpointer object,
+                     GAsyncReadyCallback callback,
+                     gpointer user_data)
+{
+  AsyncOpWrapper *data;
+
+  data = g_new0 (AsyncOpWrapper, 1);
+  data->object = g_object_ref (object);
+  data->callback = callback;
+  data->user_data = user_data;
+}
+
+static void
+async_op_wrapper_callback (GObject *source_object,
+                          GAsyncResult *res,
+                          gpointer user_data)
+{
+  AsyncOpWrapper *data  = user_data;
+  data->callback (data->object, res, data->user_data);
+  g_object_unref (data->object);
+  g_free (data);
+}
+
+static void
+g_file_io_stream_real_query_info_async (GFileIOStream     *stream,
+                                       const char           *attributes,
+                                       int                   io_priority,
+                                       GCancellable         *cancellable,
+                                       GAsyncReadyCallback   callback,
+                                       gpointer              user_data)
+{
+  GOutputStream *out;
+  GFileOutputStream *file_out;
+  AsyncOpWrapper *data;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  file_out = G_FILE_OUTPUT_STREAM (out);
+
+  data = async_op_wrapper_new (stream, callback, user_data);
+  g_file_output_stream_query_info_async (file_out,
+                                        attributes, io_priority,
+                                        cancellable, async_op_wrapper_callback, data);
+}
+
+static GFileInfo *
+g_file_io_stream_real_query_info_finish (GFileIOStream     *stream,
+                                        GAsyncResult      *res,
+                                        GError           **error)
+{
+  GOutputStream *out;
+  GFileOutputStream *file_out;
+
+  out = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+  file_out = G_FILE_OUTPUT_STREAM (out);
+
+  return g_file_output_stream_query_info_finish (file_out, res, error);
+}
+
+static void
+g_file_io_stream_class_init (GFileIOStreamClass *klass)
+{
+  g_type_class_add_private (klass, sizeof (GFileIOStreamPrivate));
+
+  klass->tell = g_file_io_stream_real_tell;
+  klass->can_seek = g_file_io_stream_real_can_seek;
+  klass->seek = g_file_io_stream_real_seek;
+  klass->can_truncate = g_file_io_stream_real_can_truncate;
+  klass->truncate_fn = g_file_io_stream_real_truncate_fn;
+  klass->query_info = g_file_io_stream_real_query_info;
+  klass->query_info_async = g_file_io_stream_real_query_info_async;
+  klass->query_info_finish = g_file_io_stream_real_query_info_finish;
+  klass->get_etag = g_file_io_stream_real_get_etag;
+}
+
+#define __G_FILE_IO_STREAM_C__
+#include "gioaliasdef.c"
diff --git a/gio/gfileiostream.h b/gio/gfileiostream.h
new file mode 100644 (file)
index 0000000..09c9922
--- /dev/null
@@ -0,0 +1,118 @@
+/* GIO - GLib Input, Io and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only <gio/gio.h> can be included directly."
+#endif
+
+#ifndef __G_FILE_IO_STREAM_H__
+#define __G_FILE_IO_STREAM_H__
+
+#include <gio/giostream.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_FILE_IO_STREAM         (g_file_io_stream_get_type ())
+#define G_FILE_IO_STREAM(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FILE_IO_STREAM, GFileIOStream))
+#define G_FILE_IO_STREAM_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_FILE_IO_STREAM, GFileIOStreamClass))
+#define G_IS_FILE_IO_STREAM(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_FILE_IO_STREAM))
+#define G_IS_FILE_IO_STREAM_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_FILE_IO_STREAM))
+#define G_FILE_IO_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_FILE_IO_STREAM, GFileIOStreamClass))
+
+/**
+ * GFileIOStream:
+ *
+ * A subclass of GIOStream for opened files. This adds
+ * a few file-specific operations and seeking and truncating.
+ *
+ * #GFileIOStream implements GSeekable.
+ **/
+typedef struct _GFileIOStreamClass    GFileIOStreamClass;
+typedef struct _GFileIOStreamPrivate  GFileIOStreamPrivate;
+
+struct _GFileIOStream
+{
+  GIOStream parent_instance;
+
+  /*< private >*/
+  GFileIOStreamPrivate *priv;
+};
+
+struct _GFileIOStreamClass
+{
+  GIOStreamClass parent_class;
+
+  goffset     (* tell)              (GFileIOStream    *stream);
+  gboolean    (* can_seek)          (GFileIOStream    *stream);
+  gboolean    (* seek)             (GFileIOStream    *stream,
+                                     goffset               offset,
+                                     GSeekType             type,
+                                     GCancellable         *cancellable,
+                                     GError              **error);
+  gboolean    (* can_truncate)      (GFileIOStream    *stream);
+  gboolean    (* truncate_fn)       (GFileIOStream    *stream,
+                                     goffset               size,
+                                     GCancellable         *cancellable,
+                                     GError              **error);
+  GFileInfo * (* query_info)        (GFileIOStream    *stream,
+                                     const char           *attributes,
+                                     GCancellable         *cancellable,
+                                     GError              **error);
+  void        (* query_info_async)  (GFileIOStream     *stream,
+                                     const char            *attributes,
+                                     int                   io_priority,
+                                     GCancellable         *cancellable,
+                                     GAsyncReadyCallback   callback,
+                                     gpointer              user_data);
+  GFileInfo * (* query_info_finish) (GFileIOStream     *stream,
+                                     GAsyncResult         *res,
+                                     GError              **error);
+  char      * (* get_etag)          (GFileIOStream    *stream);
+
+  /* Padding for future expansion */
+  void (*_g_reserved1) (void);
+  void (*_g_reserved2) (void);
+  void (*_g_reserved3) (void);
+  void (*_g_reserved4) (void);
+  void (*_g_reserved5) (void);
+};
+
+GType      g_file_io_stream_get_type          (void) G_GNUC_CONST;
+
+GFileInfo *g_file_io_stream_query_info        (GFileIOStream    *stream,
+                                              const char           *attributes,
+                                              GCancellable         *cancellable,
+                                              GError              **error);
+void       g_file_io_stream_query_info_async  (GFileIOStream    *stream,
+                                              const char           *attributes,
+                                              int                   io_priority,
+                                              GCancellable         *cancellable,
+                                              GAsyncReadyCallback   callback,
+                                              gpointer              user_data);
+GFileInfo *g_file_io_stream_query_info_finish (GFileIOStream    *stream,
+                                              GAsyncResult         *result,
+                                              GError              **error);
+char *     g_file_io_stream_get_etag          (GFileIOStream    *stream);
+
+G_END_DECLS
+
+#endif /* __G_FILE_FILE_IO_STREAM_H__ */
index 63d0b79..f12d2ed 100644 (file)
--- a/gio/gio.h
+++ b/gio/gio.h
@@ -58,6 +58,7 @@
 #include <gio/giomodule.h>
 #include <gio/gioscheduler.h>
 #include <gio/giostream.h>
+#include <gio/gfileiostream.h>
 #include <gio/gloadableicon.h>
 #include <gio/gmemoryinputstream.h>
 #include <gio/gmemoryoutputstream.h>
index 9ebc37c..2671194 100644 (file)
@@ -458,6 +458,16 @@ g_file_output_stream_get_etag
 #endif
 #endif
 
+#if IN_HEADER(__G_FILE_IO_STREAM_H__)
+#if IN_FILE(__G_FILE_IO_STREAM_C__)
+g_file_io_stream_get_type  G_GNUC_CONST
+g_file_io_stream_query_info
+g_file_io_stream_query_info_async
+g_file_io_stream_query_info_finish
+g_file_io_stream_get_etag
+#endif
+#endif
+
 #if IN_HEADER(__G_FILTER_INPUT_STREAM_H__)
 #if IN_FILE(__G_FILTER_INPUT_STREAM_C__)
 g_filter_input_stream_get_type  G_GNUC_CONST
index 6f3de48..6c3a073 100644 (file)
@@ -96,9 +96,6 @@ g_io_stream_finalize (GObject *object)
 
   stream = G_IO_STREAM (object);
 
-  if (!stream->priv->closed)
-    g_io_stream_close (stream, NULL, NULL);
-
   G_OBJECT_CLASS (g_io_stream_parent_class)->finalize (object);
 }
 
index 9af8651..3a3c361 100644 (file)
@@ -70,6 +70,7 @@ typedef struct _GFileAttributeInfo            GFileAttributeInfo;
 typedef struct _GFileAttributeInfoList        GFileAttributeInfoList;
 typedef struct _GFileInputStream              GFileInputStream;
 typedef struct _GFileOutputStream             GFileOutputStream;
+typedef struct _GFileIOStream                 GFileIOStream;
 typedef struct _GFileIcon                     GFileIcon;
 typedef struct _GFilenameCompleter            GFilenameCompleter;