[evolution-ews/gnome-3-8] Merge incremental patch support from master



commit e3aeb612bdca2541a7548225c62e77e3916f2327
Author: David Woodhouse <David Woodhouse intel com>
Date:   Wed May 15 15:34:49 2013 +0100

    Merge incremental patch support from master
    
    Synchronise with commit 9583a8a6d7d9a8dc4b05cae04349f134cb37c9dc

 src/addressbook/lzx/ews-oal-decompress.c      |  227 ++++++++++++++++++++++++-
 src/addressbook/lzx/ews-oal-decompress.h      |    4 +
 src/addressbook/lzx/gal-lzx-decompress-test.c |   22 ++-
 3 files changed, 244 insertions(+), 9 deletions(-)
---
diff --git a/src/addressbook/lzx/ews-oal-decompress.c b/src/addressbook/lzx/ews-oal-decompress.c
index 6b204dd..96872a2 100644
--- a/src/addressbook/lzx/ews-oal-decompress.c
+++ b/src/addressbook/lzx/ews-oal-decompress.c
@@ -167,7 +167,7 @@ oal_decompress_v4_full_detail_file (const gchar *filename,
        }
 
        output = fopen (output_filename, "wb");
-       if (!input) {
+       if (!output) {
                g_set_error_literal (&err, g_quark_from_string ("lzx"), 1, "unable to open the output file");
                ret = FALSE;
                goto exit;
@@ -221,14 +221,13 @@ oal_decompress_v4_full_detail_file (const gchar *filename,
                                window_bits = 25;
 
                        lzs = lzxd_init (input, output, window_bits,
-                                        0, 16, lzx_b->ucomp_size, 1);
+                                        0, 4096, lzx_b->ucomp_size, 1);
                        if (!lzs) {
                                g_set_error_literal (&err, g_quark_from_string ("lzx"), 1, "decompression 
failed (lzxd_init)");
                                ret = FALSE;
                                goto exit;
                        }
-
-                       if (lzxd_decompress (lzs, lzs->length) != LZX_ERR_OK) {
+                       if (lzxd_decompress (lzs, lzx_b->ucomp_size) != LZX_ERR_OK) {
                                g_set_error_literal (&err, g_quark_from_string ("lzx"), 1, "decompression 
failed (lzxd_decompress)");
                                ret = FALSE;
                                goto exit;
@@ -261,3 +260,223 @@ exit:
 
        return ret;
 }
+
+typedef struct {
+       guint32 h_version;
+       guint32 l_version;
+       guint32 max_block_size;
+       guint32 source_size;
+       guint32 target_size;
+       guint32 source_crc;
+       guint32 target_crc;
+} LzxPatchHeader;
+
+typedef struct {
+       guint32 patch_size;
+       guint32 target_size;
+       guint32 source_size;
+       guint32 crc;
+} LzxPatchBlockHeader;
+
+
+static LzxPatchHeader *
+read_patch_headers (FILE *input,
+              GError **error)
+{
+       LzxPatchHeader *lzx_h;
+       gboolean success;
+
+       lzx_h = g_new0 (LzxPatchHeader, 1);
+
+       success = read_uint32 (input, &lzx_h->h_version);
+       if (!success)
+               goto exit;
+       success = read_uint32 (input, &lzx_h->l_version);
+       if (!success)
+               goto exit;
+
+       if (lzx_h->h_version !=  0x00000003 || lzx_h->l_version != 0x00000002) {
+               g_free (lzx_h);
+               /* set the right domain later */
+               g_set_error_literal (error, g_quark_from_string ("lzx"), 1, "wrong version header");
+               return NULL;
+       }
+
+       success = read_uint32 (input, &lzx_h->max_block_size);
+       if (!success)
+               goto exit;
+       success = read_uint32 (input, &lzx_h->source_size);
+       if (!success)
+               goto exit;
+       success = read_uint32 (input, &lzx_h->target_size);
+       if (!success)
+               goto exit;
+       success = read_uint32 (input, &lzx_h->source_crc);
+       if (!success)
+               goto exit;
+       success = read_uint32 (input, &lzx_h->target_crc);
+       if (!success)
+               goto exit;
+
+exit:
+       if (!success) {
+               /* set the right domain later */
+               g_set_error_literal (error, g_quark_from_string ("lzx"), 1, "Unable to read lzx main header");
+
+               g_free (lzx_h);
+               lzx_h = NULL;
+       }
+
+       return lzx_h;
+}
+
+static LzxPatchBlockHeader *
+read_patch_block_header (FILE *input,
+                        GError **error)
+{
+       LzxPatchBlockHeader *lzx_b;
+       gboolean success;
+
+       lzx_b = g_new0 (LzxPatchBlockHeader, 1);
+
+       success = read_uint32 (input, &lzx_b->patch_size);
+       if (!success)
+               goto exit;
+
+       success = read_uint32 (input, &lzx_b->target_size);
+       if (!success)
+               goto exit;
+
+       success = read_uint32 (input, &lzx_b->source_size);
+       if (!success)
+               goto exit;
+
+       success = read_uint32 (input, &lzx_b->crc);
+
+exit:
+       if (!success) {
+               /* set the right domain later */
+               g_set_error_literal (error, g_quark_from_string ("lzx"), 1, "Unable to read lzx block 
header");
+
+               g_free (lzx_b);
+               lzx_b = NULL;
+       }
+
+       return  lzx_b;
+}
+
+gboolean
+oal_apply_binpatch (const gchar *filename, const gchar *orig_filename,
+                   const gchar *output_filename,
+                   GError **error)
+{
+       LzxPatchHeader *lzx_h = NULL;
+       guint total_decomp_size = 0;
+       FILE *input = NULL, *output = NULL, *orig_input = NULL;
+       gboolean ret = TRUE;
+       GError *err = NULL;
+
+       input = fopen (filename, "rb");
+       if (!input) {
+               g_set_error_literal (&err, g_quark_from_string ("lzx"), 1, "unable to open the input file");
+               ret = FALSE;
+               goto exit;
+       }
+
+       orig_input = fopen (orig_filename, "rb");
+       if (!orig_input) {
+               g_set_error_literal (&err, g_quark_from_string ("lzx"), 1, "unable to open the reference 
input file");
+               ret = FALSE;
+               goto exit;
+       }
+
+       output = fopen (output_filename, "wb");
+       if (!output) {
+               g_set_error_literal (&err, g_quark_from_string ("lzx"), 1, "unable to open the output file");
+               ret = FALSE;
+               goto exit;
+       }
+
+       lzx_h = read_patch_headers (input, &err);
+       if (!lzx_h) {
+               ret = FALSE;
+               goto exit;
+       }
+
+       /* TODO decompressing multiple lzx_blocks has not been tested yet. Will need to get a setup and test 
it. */
+       do {
+               LzxPatchBlockHeader *lzx_b;
+               struct lzxd_stream *lzs;
+               goffset offset;
+               guint ref_size, window_bits;
+
+               lzx_b = read_patch_block_header (input, &err);
+               if (err) {
+                       printf("err block header\n");
+                       ret = FALSE;
+                       goto exit;
+               }
+
+               /* note the file offset */
+               offset = ftell(input);
+
+               /* The window size should be the smallest power of two
+                  between 2^17 and 2^25 that is greater than or equal
+                  to the sum of the size of the reference data
+                  rounded up to a multiple of 32768 and the size of
+                  the subject data. */
+               ref_size = (lzx_b->source_size + 32767) & ~32767;
+               window_bits = g_bit_nth_msf(ref_size + lzx_b->target_size - 1, -1) + 1;
+
+               if (window_bits < 17)
+                       window_bits = 17;
+               else if (window_bits > 25)
+                       window_bits = 25;
+
+               lzs = lzxd_init (input, output, window_bits,
+                                0, 4096, lzx_b->target_size, 1);
+               if (!lzs) {
+                       g_set_error_literal (&err, g_quark_from_string ("lzx"), 1, "decompression failed 
(lzxd_init)");
+                       ret = FALSE;
+                       goto exit;
+               }
+               if (lzxd_set_reference_data(lzs, orig_input, lzx_b->source_size)) {
+                       g_set_error_literal (&err, g_quark_from_string ("lzx"), 1, "decompression failed 
(lzxd_set_reference_data)");
+                       ret = FALSE;
+                       goto exit;
+               }
+               if (lzxd_decompress (lzs, lzs->length) != LZX_ERR_OK) {
+                       g_set_error_literal (&err, g_quark_from_string ("lzx"), 1, "decompression failed 
(lzxd_decompress)");
+                       ret = FALSE;
+                       goto exit;
+               }
+
+               /* Set the fp to beggining of next block. This is a HACK, looks like decompress reads beyond 
the block.
+                * Since we can identify the next block start from block header, we just reset the offset */
+               offset += lzx_b->patch_size;
+               fseek (input, offset, SEEK_SET);
+
+               total_decomp_size += lzx_b->target_size;
+               g_free (lzx_b);
+       } while (total_decomp_size < lzx_h->target_size);
+
+exit:
+       if (input)
+               fclose (input);
+
+       if (orig_input)
+               fclose (orig_input);
+
+       if (output)
+               fclose (output);
+
+       if (err) {
+               ret = FALSE;
+               g_propagate_error (error, err);
+               g_unlink (output_filename);
+       }
+
+       g_free (lzx_h);
+
+       return ret;
+}
diff --git a/src/addressbook/lzx/ews-oal-decompress.h b/src/addressbook/lzx/ews-oal-decompress.h
index cf07b58..c9b6af4 100644
--- a/src/addressbook/lzx/ews-oal-decompress.h
+++ b/src/addressbook/lzx/ews-oal-decompress.h
@@ -27,5 +27,9 @@
 
 gboolean
 oal_decompress_v4_full_detail_file (const gchar *filename, const gchar *output_filename, GError **error);
+gboolean
+oal_apply_binpatch (const gchar *filename, const gchar *orig_filename,
+                   const gchar *output_filename,
+                   GError **error);
 
 #endif
diff --git a/src/addressbook/lzx/gal-lzx-decompress-test.c b/src/addressbook/lzx/gal-lzx-decompress-test.c
index 213aad3..9185ca8 100644
--- a/src/addressbook/lzx/gal-lzx-decompress-test.c
+++ b/src/addressbook/lzx/gal-lzx-decompress-test.c
@@ -1,19 +1,31 @@
 
 #include "ews-oal-decompress.h"
+#include <glib.h>
 
 gint
-main (gint argc,
-      gchar *argv[])
+main (gint argc, gchar *argv[])
 {
-       if (argc != 3) {
+       GError *error = NULL;
+
+       if (argc != 3 && argc != 4) {
                g_print ("Pass an lzx file and an output filename as argument \n");
                return -1;
        }
 
-       if (oal_decompress_v4_full_detail_file (argv[1], argv[2], NULL))
+       if (argc == 4) {
+               g_print("Applying binary patch %s to %s to create %s\n",
+                       argv[1], argv[2], argv[3]);
+               if (oal_apply_binpatch(argv[1], argv[2], argv[3], &error))
+                       g_print("Successfully applied\n");
+               else
+                       g_print("apply failed: %s\n", error->message);
+       } else
+
+
+       if (oal_decompress_v4_full_detail_file (argv[1], argv[2], &error))
                g_print ("Successfully decompressed \n");
        else
-               g_print ("decompression failed \n");
+               g_print ("decompression failed: %s\n", error->message);
 
        return 0;
 }


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