[libgsf] GsfOutputIOChannel: fix seekability check.



commit 1e47bdb9ac38dfe7a4f4ce149f847d3037674e28
Author: Morten Welinder <terra gnome org>
Date:   Sat Nov 29 14:43:31 2014 -0500

    GsfOutputIOChannel: fix seekability check.

 ChangeLog                  |    8 +++++++
 NEWS                       |    1 +
 gsf/gsf-output-gio.c       |   51 +++++++++++++++----------------------------
 gsf/gsf-output-iochannel.c |    5 +++-
 4 files changed, 31 insertions(+), 34 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index b048e94..881b67e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2014-11-29  Morten Welinder  <terra gnome org>
 
+       * gsf/gsf-output-gio.c (gsf_output_gio_write): Simplify and handle
+       the zero bytes cases better.
+       (gsf_output_gio_new_full): Check seekability here and thus only
+       once.
+
+       * gsf/gsf-output-iochannel.c (gsf_output_iochannel_seek): Check
+       for is_seekable before trying to do so.
+
        * gsf/gsf-outfile-zip.c (gsf_outfile_zip_class_init): Properly
        install zip64 property.
        (zip_header_write): Fix auto-zip64 mode's writing of sizes.
diff --git a/NEWS b/NEWS
index 5dff056..c145ef0 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,7 @@ Morten:
        * Fix minor zip file issues.
        * Write zip archives with more than 64k+ members.
        * Store unix modtime in zip.  (Until that overflows.)
+       * Fix seekability checks in GsfOutputIOChannel.
 
 --------------------------------------------------------------------------
 libgsf 1.14.30
diff --git a/gsf/gsf-output-gio.c b/gsf/gsf-output-gio.c
index 72c7aa9..4985664 100644
--- a/gsf/gsf-output-gio.c
+++ b/gsf/gsf-output-gio.c
@@ -29,6 +29,7 @@ struct _GsfOutputGio {
        GsfOutput output;
        GFile *file;
        GOutputStream *stream;
+       gboolean can_seek;
 };
 
 typedef struct {
@@ -38,21 +39,8 @@ typedef struct {
 static gboolean
 can_seek (GOutputStream *stream)
 {
-       if (!G_IS_SEEKABLE (stream))
-               return FALSE;
-
-       return g_seekable_can_seek (G_SEEKABLE (stream));
-}
-
-static GsfOutput *
-wrap_if_not_seekable (GsfOutputGio *output, GError **err)
-{
-       if (!can_seek (output->stream)) {
-               (void)err;
-               /* todo: return a wrapper around the output that's seekable */
-       }
-
-       return GSF_OUTPUT (output);
+       return (G_IS_SEEKABLE (stream) &&
+               g_seekable_can_seek (G_SEEKABLE (stream)));
 }
 
 /**
@@ -75,11 +63,11 @@ gsf_output_gio_new_full (GFile *file, GError **err)
        }
 
        output = g_object_new (GSF_OUTPUT_GIO_TYPE, NULL);
-       output->file = file;
+       output->file = g_object_ref (output->file);
        output->stream = stream;
-       g_object_ref (output->file);
+       output->can_seek = can_seek (stream);
 
-       return wrap_if_not_seekable (output, err);
+       return GSF_OUTPUT (output);
 }
 
 /**
@@ -166,8 +154,7 @@ gsf_output_gio_finalize (GObject *obj)
        gsf_output_gio_close (GSF_OUTPUT(output));
 
        parent_class = g_type_class_peek (GSF_OUTPUT_TYPE);
-       if (parent_class && parent_class->finalize)
-               parent_class->finalize (obj);
+       parent_class->finalize (obj);
 }
 
 static gboolean
@@ -176,23 +163,20 @@ gsf_output_gio_write (GsfOutput *output,
                       guint8 const *buffer)
 {
        GsfOutputGio *gio = GSF_OUTPUT_GIO (output);
-       size_t total_written = 0;
 
        g_return_val_if_fail (gio != NULL, FALSE);
        g_return_val_if_fail (gio->stream != NULL, FALSE);
 
-       while (1) {
-               gssize nwritten;
-
-               nwritten = g_output_stream_write (gio->stream, (guint8 *)(buffer + total_written), (num_bytes 
- total_written), NULL, NULL);
-
-               if (nwritten >= 0) {
-                       total_written += nwritten;
-                       if (total_written == num_bytes)
-                               return TRUE;
-               } else {
+       while (num_bytes > 0) {
+               gssize nwritten =
+                       g_output_stream_write (gio->stream,
+                                              buffer, num_bytes,
+                                              NULL, NULL);
+               if (nwritten < 0)
                        return FALSE;
-               }
+
+               buffer += nwritten;
+               num_bytes -= nwritten;
        }
 
        return TRUE;
@@ -206,7 +190,7 @@ gsf_output_gio_seek (GsfOutput *output, gsf_off_t offset, GSeekType whence)
        g_return_val_if_fail (gio != NULL, FALSE);
        g_return_val_if_fail (gio->stream != NULL, FALSE);
 
-       if (!can_seek (gio->stream))
+       if (!gio->can_seek)
                return FALSE;
 
        return g_seekable_seek (G_SEEKABLE (gio->stream), offset, whence, NULL, NULL);
@@ -219,6 +203,7 @@ gsf_output_gio_init (GObject *obj)
 
        gio->file   = NULL;
        gio->stream = NULL;
+       gio->can_seek = FALSE;
 }
 
 static void
diff --git a/gsf/gsf-output-iochannel.c b/gsf/gsf-output-iochannel.c
index 1521784..f15aeb5 100644
--- a/gsf/gsf-output-iochannel.c
+++ b/gsf/gsf-output-iochannel.c
@@ -77,11 +77,14 @@ gsf_output_iochannel_seek (GsfOutput *output, gsf_off_t offset,
        GsfOutputIOChannel *io = GSF_OUTPUT_IOCHANNEL (output);
        GIOStatus status = G_IO_STATUS_NORMAL;
 
+       if (!io->channel->is_seekable)
+               return FALSE;
+
        status = g_io_channel_seek_position (io->channel, offset, whence, NULL);
        if (status == G_IO_STATUS_NORMAL)
                return TRUE;
 
-       gsf_output_set_error (output, status, " ");
+       gsf_output_set_error (output, status, "?");
        return FALSE;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]