[gcab] Should work on various byte-order



commit 70cc64483a1ebf183dba108b8decfeeff4de5e24
Author: Marc-Andrà Lureau <marcandre lureau gmail com>
Date:   Sat Dec 22 00:16:40 2012 +0100

    Should work on various byte-order

 libgcab/cabinet.c      |  117 ++++++++++++++++++++++++++----------------------
 libgcab/cabinet.h      |   24 ++++++++--
 libgcab/gcab-cabinet.c |   56 +++++++++++-----------
 3 files changed, 112 insertions(+), 85 deletions(-)
---
diff --git a/libgcab/cabinet.c b/libgcab/cabinet.c
index 0aeb959..a946968 100644
--- a/libgcab/cabinet.c
+++ b/libgcab/cabinet.c
@@ -43,60 +43,64 @@ cdata_set (cdata_t *cd, int type, guint8 *data, size_t size)
     }
 }
 
-#define W(data, count) \
-    g_output_stream_write (out, data, count, NULL, error)
-
-G_GNUC_INTERNAL gssize
-cheader_write (cheader_t *ch, GOutputStream *out, GError **error)
+#define W1(val) \
+    g_data_output_stream_put_byte (out, val, cancellable, error)
+#define W2(val) \
+    g_data_output_stream_put_uint16 (out, val, cancellable, error)
+#define W4(val) \
+    g_data_output_stream_put_uint32 (out, val, cancellable, error)
+#define WS(val) \
+    g_data_output_stream_put_string (out, val, cancellable, error)
+
+G_GNUC_INTERNAL gboolean
+cheader_write (cheader_t *ch, GDataOutputStream *out,
+               GCancellable *cancellable, GError **error)
 {
-    ch->versionMIN = 3;
-    ch->versionMAJ = 1;
-
-    if ((W ("MSCF", 4) == -1) ||
-        (W (&ch->res1, 4) == -1) ||
-        (W (&ch->size, 4) == -1) ||
-        (W (&ch->res2, 4) == -1) ||
-        (W (&ch->offsetfiles, 4) == -1) ||
-        (W (&ch->res3, 4) == -1) ||
-        (W (&ch->versionMIN, 1) == -1) ||
-        (W (&ch->versionMAJ, 1) == -1) ||
-        (W (&ch->nfolders, 2) == -1) ||
-        (W (&ch->nfiles, 2) == -1) ||
-        (W (&ch->flags, 2) == -1) ||
-        (W (&ch->setID, 2) == -1) ||
-        (W (&ch->cabID, 2) == -1))
-        return -1;
-
-    return 4 + 4 + 4 + 4 + 4 + 4 + 1 + 1 + 2 + 2 + 2 + 2 + 2;
+    if (!W1 ('M') || !W1 ('S') || !W1 ('C') || !W1 ('F') ||
+        !W4 (ch->res1) ||
+        !W4 (ch->size) ||
+        !W4 (ch->res2) ||
+        !W4 (ch->offsetfiles) ||
+        !W4 (ch->res3) ||
+        !W1 (ch->versionMIN = 3) ||
+        !W1 (ch->versionMAJ = 1) ||
+        !W2 (ch->nfolders) ||
+        !W2 (ch->nfiles) ||
+        !W2 (ch->flags) ||
+        !W2 (ch->setID) ||
+        !W2 (ch->cabID))
+        return FALSE;
+
+    return TRUE;
 }
 
-G_GNUC_INTERNAL gssize
-cfolder_write (cfolder_t *cf, GOutputStream *out, GError **error)
+G_GNUC_INTERNAL gboolean
+cfolder_write (cfolder_t *cf, GDataOutputStream *out,
+               GCancellable *cancellable, GError **error)
 {
-    if ((W (&cf->offsetdata, 4) == -1) ||
-        (W (&cf->ndatab, 2) == -1) ||
-        (W (&cf->typecomp, 2) == -1))
-        return -1;
+    if ((!W4 (cf->offsetdata)) ||
+        (!W2 (cf->ndatab)) ||
+        (!W2 (cf->typecomp)))
+        return FALSE;
 
-    return 4 + 2 + 2;
+    return TRUE;
 }
 
 
-G_GNUC_INTERNAL gssize
-cfile_write (cfile_t *cf, GOutputStream *out, GError **error)
+G_GNUC_INTERNAL gboolean
+cfile_write (cfile_t *cf, GDataOutputStream *out,
+             GCancellable *cancellable, GError **error)
 {
-    const gchar *name = cf->name;
-
-    if ((W (&cf->usize, 4) == -1) ||
-        (W (&cf->uoffset, 4) == -1) ||
-        (W (&cf->index, 2) == -1) ||
-        (W (&cf->date, 2) == -1) ||
-        (W (&cf->time, 2) == -1) ||
-        (W (&cf->fattr, 2) == -1) ||
-        (W (name, strlen (name) + 1) == -1))
-        return -1;
-
-    return 4 + 4 + 2 + 2 + 2 + 2 + strlen (name) + 1;
+    if ((!W4 (cf->usize)) ||
+        (!W4 (cf->uoffset)) ||
+        (!W2 (cf->index)) ||
+        (!W2 (cf->date)) ||
+        (!W2 (cf->time)) ||
+        (!W2 (cf->fattr)) ||
+        (!WS (cf->name) || !W1 (0)))
+        return FALSE;
+
+    return TRUE;
 }
 
 typedef unsigned long int CHECKSUM;
@@ -133,18 +137,25 @@ compute_checksum (guint8 *in, u2 ncbytes, CHECKSUM seed)
     return csum;
 }
 
-G_GNUC_INTERNAL gssize
-cdata_write(cdata_t *cd, GOutputStream *out, int type, guint8 *data, size_t size, GError **error)
+G_GNUC_INTERNAL gboolean
+cdata_write (cdata_t *cd, GDataOutputStream *out, int type,
+             guint8 *data, size_t size, gsize *bytes_written,
+             GCancellable *cancellable, GError **error)
 {
     cdata_set(cd, type, data, size);
     CHECKSUM datacsum = compute_checksum(cd->data, cd->ncbytes, 0);
     cd->checksum = compute_checksum ((guint8*)&cd->ncbytes, 4, datacsum);
+    GOutputStream *stream = g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (out));
+
+    *bytes_written = 0;
+
+    if ((!W4 (cd->checksum)) ||
+        (!W2 (cd->ncbytes)) ||
+        (!W2 (cd->nubytes)) ||
+        (g_output_stream_write (stream, cd->data, cd->ncbytes, cancellable, error) == -1))
+        return FALSE;
 
-    if ((W (&cd->checksum, 4) == -1) ||
-        (W (&cd->ncbytes, 2) == -1) ||
-        (W (&cd->nubytes, 2) == -1) ||
-        (W (cd->data, cd->ncbytes) == -1))
-        return -1;
+    *bytes_written = 4 + 2 + 2 + cd->ncbytes;
 
-    return 4 + 2 + 2 + cd->ncbytes;
+    return TRUE;
 }
diff --git a/libgcab/cabinet.h b/libgcab/cabinet.h
index 1eabc0c..3d575c9 100644
--- a/libgcab/cabinet.h
+++ b/libgcab/cabinet.h
@@ -80,9 +80,25 @@ struct cdata
     guint8 data[DATABLOCKSIZE*2];
 };
 
-gssize cheader_write (cheader_t *ch, GOutputStream *out, GError **error);
-gssize cfolder_write (cfolder_t *cf, GOutputStream *out, GError **error);
-gssize cdata_write (cdata_t *cd, GOutputStream *out, int type, guint8 *data, size_t size, GError **error);
-gssize cfile_write (cfile_t *cf, GOutputStream *out, GError **error);
+gboolean     cheader_write                      (cheader_t *ch,
+                                                 GDataOutputStream *out,
+                                                 GCancellable *cancellable,
+                                                 GError **error);
+gboolean     cfolder_write                      (cfolder_t *cf,
+                                                 GDataOutputStream *out,
+                                                 GCancellable *cancellable,
+                                                 GError **error);
+gboolean     cdata_write                        (cdata_t *cd,
+                                                 GDataOutputStream *out,
+                                                 int type,
+                                                 guint8 *data,
+                                                 size_t size,
+                                                 gsize *bytes_written,
+                                                 GCancellable *cancellable,
+                                                 GError **error);
+gboolean     cfile_write                        (cfile_t *cf,
+                                                 GDataOutputStream *out,
+                                                 GCancellable *cancellable,
+                                                 GError **error);
 
 #endif /* CABINET_H */
diff --git a/libgcab/gcab-cabinet.c b/libgcab/gcab-cabinet.c
index d0fe1b8..3dab4de 100644
--- a/libgcab/gcab-cabinet.c
+++ b/libgcab/gcab-cabinet.c
@@ -147,6 +147,12 @@ gcab_cabinet_write (GCabCabinet *self,
     GCabFolder *cabfolder = g_ptr_array_index (self->folders, 0);
     GCabFile *file;
     gsize nfiles = gcab_folder_get_nfiles (cabfolder);
+    GInputStream *in = NULL;
+    GDataOutputStream *dstream = NULL;
+    gboolean success = FALSE;
+
+    dstream = g_data_output_stream_new (out);
+    g_data_output_stream_set_byte_order (dstream, G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN);
 
     size_t sumstr = 0;
     g_hash_table_iter_init (&iter, cabfolder->files);
@@ -159,62 +165,53 @@ gcab_cabinet_write (GCabCabinet *self,
 
     if (!g_seekable_seek (G_SEEKABLE (out), folder.offsetdata,
                           G_SEEK_SET, NULL, error))
-        return FALSE;
-
+        goto end;
     gssize len, offset = 0;
     cdata_t block = { 0, };
     guint8 data[DATABLOCKSIZE];
-
+    gsize written;
     g_hash_table_iter_init (&iter, cabfolder->files);
     while (g_hash_table_iter_next (&iter, NULL, (gpointer*)&file)) {
         if (file_callback)
             file_callback (file, callback_data);
 
-        GInputStream *in = G_INPUT_STREAM (g_file_read (file->file, cancellable, error));
-        if (*error) {
-            g_object_unref (in);
-            return FALSE;
-        }
+        in = G_INPUT_STREAM (g_file_read (file->file, cancellable, error));
+        if (*error)
+            goto end;
 
         while ((len = g_input_stream_read (in,
                                            &data[offset], DATABLOCKSIZE - offset,
                                            cancellable, error)) == (DATABLOCKSIZE - offset)) {
-            ssize_t written = cdata_write (&block, out, folder.typecomp, data, DATABLOCKSIZE, error);
+            if (!cdata_write (&block, dstream, folder.typecomp, data, DATABLOCKSIZE, &written, cancellable, error))
+                goto end;
             header.size += written;
             offset = 0;
         }
 
-        if (len == -1) {
-            g_object_unref (in);
-            return FALSE;
-        }
+        if (len == -1)
+            goto end;
 
         offset += len;
-        g_object_unref (in);
     }
     if (offset != 0) {
-        ssize_t written = cdata_write (&block, out, folder.typecomp, data, offset, error);
-        if (written == -1)
-            return FALSE;
+        if (!cdata_write (&block, dstream, folder.typecomp, data, offset, &written, cancellable, error))
+            goto end;
         header.size += written;
     }
 
-    if (!g_output_stream_flush (out, cancellable, error))
-        return FALSE;
-
     if (!g_seekable_seek (G_SEEKABLE (out), 0,
                           G_SEEK_SET, cancellable, error))
-        return FALSE;
+        goto end;
 
     header.nfiles = nfiles;
     header.size += CFI_START + nfiles * 16; /* 1st part cfile struct = 16 bytes */
     header.size += sumstr;
 
-    if (cheader_write (&header, out, error) == -1)
-        return FALSE;
+    if (!cheader_write (&header, dstream, cancellable, error))
+        goto end;
 
-    if (cfolder_write (&folder, out, error) == -1)
-        return FALSE;
+    if (!cfolder_write (&folder, dstream, cancellable, error))
+        goto end;
 
     cfile_t *prevf = NULL;
     g_hash_table_iter_init (&iter, cabfolder->files);
@@ -222,12 +219,15 @@ gcab_cabinet_write (GCabCabinet *self,
         file->cfile.uoffset = prevf ? prevf->uoffset + prevf->usize : 0;
         prevf = &file->cfile;
 
-        if (cfile_write (&file->cfile, out, error) == -1)
-            return FALSE;
+        if (!cfile_write (&file->cfile, dstream, cancellable, error))
+            goto end;
     }
 
-    return TRUE;
+    success = TRUE;
 
+end:
+    g_clear_object (&dstream);
+    g_clear_object (&in);
 }
 
 /**



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