[ostree] lib: Create an internal static delta parsing/opening function



commit 56fc249d08d784ec481b71f2b13e2dbe509b0d9a
Author: Colin Walters <walters verbum org>
Date:   Sat Feb 6 13:56:19 2016 +0100

    lib: Create an internal static delta parsing/opening function
    
    We had code to deal with opening/checksumming/decompressing static
    deltas in a few places.  I'd like to teach `ostree static-delta show`
    how to display more information, and this will allow it to just use
    `_ostree_static_delta_part_open()` too.

 src/libostree/ostree-repo-pull.c                   |  117 ++++------
 src/libostree/ostree-repo-static-delta-core.c      |  238 +++++++++++++++++---
 src/libostree/ostree-repo-static-delta-private.h   |   33 ++--
 .../ostree-repo-static-delta-processing.c          |  141 +-----------
 4 files changed, 278 insertions(+), 251 deletions(-)
---
diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c
index 6e6f0cd..750c68f 100644
--- a/src/libostree/ostree-repo-pull.c
+++ b/src/libostree/ostree-repo-pull.c
@@ -935,8 +935,7 @@ static_deltapart_fetch_on_complete (GObject           *object,
   g_autoptr(GVariant) metadata = NULL;
   g_autofree char *temp_path = NULL;
   g_autoptr(GInputStream) in = NULL;
-  g_autofree char *actual_checksum = NULL;
-  g_autofree guint8 *csum = NULL;
+  g_autoptr(GVariant) part = NULL;
   GError *local_error = NULL;
   GError **error = &local_error;
   gs_fd_close int fd = -1;
@@ -950,54 +949,33 @@ static_deltapart_fetch_on_complete (GObject           *object,
   fd = openat (_ostree_fetcher_get_dfd (fetcher), temp_path, O_RDONLY | O_CLOEXEC);
   if (fd == -1)
     {
-      gs_set_error_from_errno (error, errno);
+      glnx_set_error_from_errno (error);
       goto out;
     }
-  in = g_unix_input_stream_new (fd, FALSE);
-
-  /* TODO - consider making async */
-  if (!ot_gio_checksum_stream (in, &csum, pull_data->cancellable, error))
-    goto out;
-
-  actual_checksum = ostree_checksum_from_bytes (csum);
 
-  if (strcmp (actual_checksum, fetch_data->expected_checksum) != 0)
+  /* From here on, if we fail to apply the delta, we'll re-fetch it */
+  if (unlinkat (_ostree_fetcher_get_dfd (fetcher), temp_path, 0) < 0)
     {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "Corrupted static delta part; checksum expected='%s' actual='%s'",
-                   fetch_data->expected_checksum, actual_checksum);
+      glnx_set_error_from_errno (error);
       goto out;
     }
 
-  /* Might as well close the fd here */
-  (void) g_input_stream_close (in, NULL, NULL);
+  in = g_unix_input_stream_new (fd, FALSE);
 
-  {
-    GMappedFile *mfile = NULL;
-    g_autoptr(GBytes) delta_data = NULL;
+  /* TODO - make async */
+  if (!_ostree_static_delta_part_open (in, NULL, 0, fetch_data->expected_checksum,
+                                       &part, pull_data->cancellable, error))
+    goto out;
 
-    mfile = g_mapped_file_new_from_fd (fd, FALSE, error);
-    if (!mfile)
-      goto out;
-    delta_data = g_mapped_file_get_bytes (mfile);
-    g_mapped_file_unref (mfile);
-
-    /* Unlink now while we're holding an open fd, so that on success
-     * or error, the file will be gone.  This is particularly
-     * important if say we hit e.g. ENOSPC.
-     */
-    (void) unlinkat (_ostree_fetcher_get_dfd (fetcher), temp_path, 0);
-
-    _ostree_static_delta_part_execute_async (pull_data->repo,
-                                             fetch_data->objects,
-                                             delta_data,
-                                             /* Trust checksums if summary was gpg signed */
-                                             pull_data->gpg_verify_summary && pull_data->summary_data_sig,
-                                             pull_data->cancellable,
-                                             on_static_delta_written,
-                                             fetch_data);
-    pull_data->n_outstanding_deltapart_write_requests++;
-  }
+  _ostree_static_delta_part_execute_async (pull_data->repo,
+                                           fetch_data->objects,
+                                           part,
+                                           /* Trust checksums if summary was gpg signed */
+                                           pull_data->gpg_verify_summary && pull_data->summary_data_sig,
+                                           pull_data->cancellable,
+                                           on_static_delta_written,
+                                           fetch_data);
+  pull_data->n_outstanding_deltapart_write_requests++;
 
  out:
   g_assert (pull_data->n_outstanding_deltapart_fetches > 0);
@@ -1604,10 +1582,10 @@ process_one_static_delta (OtPullData   *pull_data,
       FetchStaticDeltaData *fetch_data;
       g_autoptr(GVariant) csum_v = NULL;
       g_autoptr(GVariant) objects = NULL;
-      g_autoptr(GVariant) part_data = NULL;
-      g_autoptr(GBytes) delta_data = NULL;
+      g_autoptr(GBytes) inline_part_bytes = NULL;
       guint64 size, usize;
       guint32 version;
+      const gboolean trusted = pull_data->gpg_verify_summary && pull_data->summary_data_sig;
 
       header = g_variant_get_child_value (headers, i);
       g_variant_get (header, "(u aytt@ay)", &version, &csum_v, &size, &usize, &objects);
@@ -1623,31 +1601,6 @@ process_one_static_delta (OtPullData   *pull_data,
       if (!csum)
         goto out;
 
-      deltapart_path = _ostree_get_relative_static_delta_part_path (from_revision, to_revision, i);
-
-      part_data = g_variant_lookup_value (metadata, deltapart_path, G_VARIANT_TYPE ("(yay)"));
-      if (part_data)
-        {
-          g_autofree char *actual_checksum = NULL;
-          g_autofree char *expected_checksum = ostree_checksum_from_bytes_v (csum_v);
-
-          delta_data = g_variant_get_data_as_bytes (part_data);
-
-          /* For inline parts we are relying on per-commit GPG, so this isn't strictly necessary for 
security.
-           * See https://github.com/GNOME/ostree/pull/139
-           */
-          actual_checksum = g_compute_checksum_for_bytes (G_CHECKSUM_SHA256, delta_data);
-          if (strcmp (actual_checksum, expected_checksum) != 0)
-            {
-              g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                           "Corrupted static delta part; checksum expected='%s' actual='%s'",
-                           expected_checksum, actual_checksum);
-              goto out;
-            }
-        }
-
-      pull_data->total_deltapart_size += size;
-
       if (!_ostree_repo_static_delta_part_have_all_objects (pull_data->repo,
                                                             objects,
                                                             &have_all,
@@ -1663,18 +1616,38 @@ process_one_static_delta (OtPullData   *pull_data,
           continue;
         }
 
+      deltapart_path = _ostree_get_relative_static_delta_part_path (from_revision, to_revision, i);
+
+      { g_autoptr(GVariant) part_datav =
+          g_variant_lookup_value (metadata, deltapart_path, G_VARIANT_TYPE ("(yay)"));
+
+        if (part_datav)
+          inline_part_bytes = g_variant_get_data_as_bytes (part_datav);
+      }
+
+      pull_data->total_deltapart_size += size;
+
       fetch_data = g_new0 (FetchStaticDeltaData, 1);
       fetch_data->pull_data = pull_data;
       fetch_data->objects = g_variant_ref (objects);
       fetch_data->expected_checksum = ostree_checksum_from_bytes_v (csum_v);
 
-      if (delta_data != NULL)
+      if (inline_part_bytes != NULL)
         {
+          g_autoptr(GInputStream) memin = g_memory_input_stream_new_from_bytes (inline_part_bytes);
+          g_autoptr(GVariant) inline_delta_part = NULL;
+
+          /* For inline parts we are relying on per-commit GPG, so don't bother checksumming. */
+          if (!_ostree_static_delta_part_open (memin, inline_part_bytes,
+                                               OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM,
+                                               NULL, &inline_delta_part,
+                                               cancellable, error))
+            goto out;
+                                               
           _ostree_static_delta_part_execute_async (pull_data->repo,
                                                    fetch_data->objects,
-                                                   delta_data,
-                                                   /* Trust checksums if summary was gpg signed */
-                                                   pull_data->gpg_verify_summary && 
pull_data->summary_data_sig,
+                                                   inline_delta_part,
+                                                   trusted,
                                                    pull_data->cancellable,
                                                    on_static_delta_written,
                                                    fetch_data);
diff --git a/src/libostree/ostree-repo-static-delta-core.c b/src/libostree/ostree-repo-static-delta-core.c
index bc1b460..e9d5c15 100644
--- a/src/libostree/ostree-repo-static-delta-core.c
+++ b/src/libostree/ostree-repo-static-delta-core.c
@@ -20,9 +20,14 @@
 
 #include "config.h"
 
+#include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+#include <gio/gfiledescriptorbased.h>
 #include "ostree-core-private.h"
 #include "ostree-repo-private.h"
+#include "ostree-lzma-decompressor.h"
 #include "ostree-cmdprivate.h"
+#include "ostree-checksum-input-stream.h"
 #include "ostree-repo-static-delta-private.h"
 #include "otutil.h"
 
@@ -226,31 +231,45 @@ ostree_repo_static_delta_execute_offline (OstreeRepo                    *self,
 {
   gboolean ret = FALSE;
   guint i, n;
-  g_autoptr(GFile) meta_file = NULL;
-  g_autoptr(GFile) dir = NULL;
+  const char *dir_or_file_path = NULL;
+  glnx_fd_close int meta_fd = -1;
+  glnx_fd_close int dfd = -1;
   g_autoptr(GVariant) meta = NULL;
   g_autoptr(GVariant) headers = NULL;
   g_autoptr(GVariant) metadata = NULL;
   g_autoptr(GVariant) fallback = NULL;
   g_autofree char *to_checksum = NULL;
   g_autofree char *from_checksum = NULL;
-  GFileType file_type;
 
+  dir_or_file_path = gs_file_get_path_cached (dir_or_file);
 
-  file_type = g_file_query_file_type (dir_or_file, 0, cancellable);
-  if (file_type == G_FILE_TYPE_DIRECTORY)
+  /* First, try opening it as a directory */
+  dfd = glnx_opendirat_with_errno (AT_FDCWD, dir_or_file_path, TRUE);
+  if (dfd < 0)
     {
-      dir = g_object_ref (dir_or_file);
-      meta_file = g_file_get_child (dir, "superblock");
+      if (errno != ENOTDIR)
+        {
+          glnx_set_error_from_errno (error);
+          goto out;
+        }
+      else
+        {
+          g_autofree char *dir = dirname (g_strdup (dir_or_file_path));
+
+          if (!glnx_opendirat (AT_FDCWD, dir, TRUE, &dfd, error))
+            goto out;
+        }
     }
-  else
+
+  meta_fd = openat (dfd, "superblock", O_RDONLY | O_CLOEXEC);
+  if (meta_fd < 0)
     {
-      meta_file = g_object_ref (dir_or_file);
-      dir = g_file_get_parent (meta_file);
+      glnx_set_error_from_errno (error);
+      goto out;
     }
-
-  if (!ot_util_variant_map (meta_file, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT),
-                            FALSE, &meta, error))
+  
+  if (!ot_util_variant_map_fd (meta_fd, 0, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT),
+                               FALSE, &meta, error))
     goto out;
 
   /* Parsing OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT */
@@ -330,14 +349,18 @@ ostree_repo_static_delta_execute_offline (OstreeRepo                    *self,
       guint64 size;
       guint64 usize;
       const guchar *csum;
+      char checksum[65];
       gboolean have_all;
+      g_autoptr(GInputStream) part_in = NULL;
       g_autoptr(GBytes) delta_data = NULL;
-      g_autoptr(GVariant) part_data = NULL;
+      g_autoptr(GVariant) inline_part_data = NULL;
       g_autoptr(GVariant) header = NULL;
       g_autoptr(GVariant) csum_v = NULL;
       g_autoptr(GVariant) objects = NULL;
-      g_autoptr(GBytes) bytes = NULL;
+      g_autoptr(GVariant) part = NULL;
       g_autofree char *deltapart_path = NULL;
+      OstreeStaticDeltaOpenFlags delta_open_flags = 
+        skip_validation ? OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM : 0;
 
       header = g_variant_get_child_value (headers, i);
       g_variant_get (header, "(u aytt@ay)", &version, &csum_v, &size, &usize, &objects);
@@ -362,46 +385,195 @@ ostree_repo_static_delta_execute_offline (OstreeRepo                    *self,
       csum = ostree_checksum_bytes_peek_validate (csum_v, error);
       if (!csum)
         goto out;
+      ostree_checksum_inplace_from_bytes (csum, checksum);
 
       deltapart_path =
         _ostree_get_relative_static_delta_part_path (from_checksum, to_checksum, i);
 
-      part_data = g_variant_lookup_value (metadata, deltapart_path, G_VARIANT_TYPE("(yay)"));
-      if (part_data)
+      inline_part_data = g_variant_lookup_value (metadata, deltapart_path, G_VARIANT_TYPE("(yay)"));
+      if (inline_part_data)
         {
-          bytes = g_variant_get_data_as_bytes (part_data);
+          g_autoptr(GBytes) inline_part_bytes = g_variant_get_data_as_bytes (inline_part_data);
+          part_in = g_memory_input_stream_new_from_bytes (inline_part_bytes);
+
+          /* For inline parts, we don't checksum, because it's
+           * included with the metadata, so we're not trying to
+           * protect against MITM or such.  Non-security related
+           * checksums should be done at the underlying storage layer.
+           */
+          delta_open_flags |= OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM;
+
+          if (!_ostree_static_delta_part_open (part_in, inline_part_bytes, 
+                                               delta_open_flags,
+                                               NULL,
+                                               &part,
+                                               cancellable, error))
+            goto out;
         }
       else
         {
-          g_autoptr(GFile) part_path = ot_gfile_resolve_path_printf (dir, "%u", i);
-          GMappedFile *mfile = gs_file_map_noatime (part_path, cancellable, error);
-          if (!mfile)
+          g_autofree char *relpath = g_strdup_printf ("%u", i); /* TODO avoid malloc here */
+          glnx_fd_close int part_fd = openat (dfd, relpath, O_RDONLY | O_CLOEXEC);
+          if (part_fd < 0)
+            {
+              glnx_set_error_from_errno (error);
+              g_prefix_error (error, "Opening deltapart '%s': ", deltapart_path);
+              goto out;
+            }
+
+          part_in = g_unix_input_stream_new (part_fd, FALSE);
+
+          if (!_ostree_static_delta_part_open (part_in, NULL, 
+                                               delta_open_flags,
+                                               checksum,
+                                               &part,
+                                               cancellable, error))
             goto out;
+        }
 
-          bytes = g_mapped_file_get_bytes (mfile);
-          g_mapped_file_unref (mfile);
+      if (!_ostree_static_delta_part_execute (self, objects, part, skip_validation,
+                                              cancellable, error))
+        {
+          g_prefix_error (error, "Executing delta part %i: ", i);
+          goto out;
         }
+    }
+
+  ret = TRUE;
+ out:
+  return ret;
+}
+
+gboolean
+_ostree_static_delta_part_open (GInputStream   *part_in,
+                                GBytes         *inline_part_bytes,
+                                OstreeStaticDeltaOpenFlags flags,
+                                const char     *expected_checksum,
+                                GVariant    **out_part,
+                                GCancellable *cancellable,
+                                GError      **error)
+{
+  gboolean ret = FALSE;
+  const gboolean trusted = (flags & OSTREE_STATIC_DELTA_OPEN_FLAGS_VARIANT_TRUSTED) > 0;
+  const gboolean skip_checksum = (flags & OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM) > 0;
+  gsize bytes_read;
+  guint8 comptype;
+  g_autoptr(GChecksum) checksum = NULL;
+  g_autoptr(GInputStream) checksum_in = NULL;
+  g_autoptr(GVariant) ret_part = NULL;
+  GInputStream *source_in;
+
+  /* We either take a fd or a GBytes reference */
+  g_return_val_if_fail (G_IS_FILE_DESCRIPTOR_BASED (part_in) || inline_part_bytes != NULL, FALSE);
+  g_return_val_if_fail (skip_checksum || expected_checksum != NULL, FALSE);
+
+  if (!skip_checksum)
+    {
+      checksum = g_checksum_new (G_CHECKSUM_SHA256);
+      checksum_in = (GInputStream*)ostree_checksum_input_stream_new (part_in, checksum);
+      source_in = checksum_in;
+    }
+  else
+    {
+      source_in = part_in;
+    }
+
+  { guint8 buf[1];
+    /* First byte is compression type */
+    if (!g_input_stream_read_all (source_in, buf, sizeof(buf), &bytes_read,
+                                  cancellable, error))
+      {
+        g_prefix_error (error, "Reading initial compression flag byte: ");
+      goto out;
+      }
+    comptype = buf[0];
+  }
 
-      if (!skip_validation)
+  switch (comptype)
+    {
+    case 0:
+      if (!inline_part_bytes)
         {
-          g_autoptr(GInputStream) in = g_memory_input_stream_new_from_bytes (bytes);
+          int part_fd = g_file_descriptor_based_get_fd ((GFileDescriptorBased*)part_in);
 
-          g_autofree char *expected_checksum = ostree_checksum_from_bytes (csum);
-          if (!_ostree_static_delta_part_validate (self, in, i,
-                                                   expected_checksum,
-                                                   cancellable, error))
+          /* No compression, no checksums - a fast path */
+          if (!ot_util_variant_map_fd (part_fd, 1, G_VARIANT_TYPE 
(OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
+                                       trusted, &ret_part, error))
             goto out;
         }
+      else
+        {
+          g_autoptr(GBytes) content_bytes = g_bytes_new_from_bytes (inline_part_bytes, 1,
+                                                                    g_bytes_get_size (inline_part_bytes) - 
1);
+          ret_part = g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
+                                               content_bytes, trusted);
+        }
 
-      if (!_ostree_static_delta_part_execute (self, objects, bytes, skip_validation,
-                                              cancellable, error))
+      if (!skip_checksum)
+        g_checksum_update (checksum, g_variant_get_data (ret_part),
+                           g_variant_get_size (ret_part));
+      
+      break;
+    case 'x':
+      {
+        g_autofree char *tmppath = g_strdup ("/var/tmp/ostree-delta-XXXXXX");
+        g_autoptr(GConverter) decomp = (GConverter*) _ostree_lzma_decompressor_new ();
+        g_autoptr(GInputStream) convin = g_converter_input_stream_new (source_in, decomp);
+        g_autoptr(GOutputStream) unpacked_out = NULL;
+        glnx_fd_close int unpacked_fd = -1;
+        gssize n_bytes_written;
+
+        unpacked_fd = g_mkstemp_full (tmppath, O_RDWR | O_CLOEXEC, 0640);
+        if (unpacked_fd < 0)
+          {
+            glnx_set_error_from_errno (error);
+            goto out;
+          }
+        
+        /* Now make it autocleanup on process exit - in the future, we
+         * should consider caching unpacked deltas as well.
+         */
+        if (unlink (tmppath) < 0)
+          {
+            glnx_set_error_from_errno (error);
+            goto out;
+          }
+        
+        unpacked_out = g_unix_output_stream_new (unpacked_fd, FALSE);
+
+        n_bytes_written = g_output_stream_splice (unpacked_out, convin,
+                                                  G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
+                                                  G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+                                                  cancellable, error);
+        if (n_bytes_written < 0)
+          goto out;
+
+        if (!ot_util_variant_map_fd (unpacked_fd, 0, G_VARIANT_TYPE 
(OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
+                                     trusted, &ret_part, error))
+          goto out;
+      }
+      break;
+    default:
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Invalid compression type '%u'", comptype);
+      goto out;
+    }
+
+  if (checksum)
+    {
+      const char *actual_checksum = g_checksum_get_string (checksum);
+      g_assert (expected_checksum != NULL);
+      if (strcmp (actual_checksum, expected_checksum) != 0)
         {
-          g_prefix_error (error, "executing delta part %i: ", i);
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "Checksum mismatch in static delta part; expected=%s actual=%s",
+                       expected_checksum, actual_checksum);
           goto out;
         }
     }
-
+        
   ret = TRUE;
+  *out_part = g_steal_pointer (&ret_part);
  out:
   return ret;
 }
diff --git a/src/libostree/ostree-repo-static-delta-private.h 
b/src/libostree/ostree-repo-static-delta-private.h
index b0e82ad..55777fc 100644
--- a/src/libostree/ostree-repo-static-delta-private.h
+++ b/src/libostree/ostree-repo-static-delta-private.h
@@ -103,35 +103,36 @@ G_BEGIN_DECLS
  */ 
 #define OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT "(a{sv}tayay" OSTREE_COMMIT_GVARIANT_STRING "aya" 
OSTREE_STATIC_DELTA_META_ENTRY_FORMAT "a" OSTREE_STATIC_DELTA_FALLBACK_FORMAT ")"
 
+typedef enum {
+  OSTREE_STATIC_DELTA_OPEN_FLAGS_NONE = 0,
+  OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM = (1 << 0),
+  OSTREE_STATIC_DELTA_OPEN_FLAGS_VARIANT_TRUSTED = (1 << 1)
+} OstreeStaticDeltaOpenFlags;
+
+gboolean
+_ostree_static_delta_part_open (GInputStream   *part_in,
+                                GBytes         *inline_part_bytes,
+                                OstreeStaticDeltaOpenFlags flags,
+                                const char     *expected_checksum,
+                                GVariant    **out_part,
+                                GCancellable *cancellable,
+                                GError      **error);
+
 gboolean _ostree_static_delta_dump (OstreeRepo     *repo,
                                     const char *delta_id,
                                     GCancellable   *cancellable,
                                     GError        **error);
 
-gboolean _ostree_static_delta_part_validate (OstreeRepo     *repo,
-                                             GInputStream   *in,
-                                             guint           part_offset,
-                                             const char     *expected_checksum,
-                                             GCancellable   *cancellable,
-                                             GError        **error);
-
 gboolean _ostree_static_delta_part_execute (OstreeRepo      *repo,
                                             GVariant        *header,
-                                            GBytes          *partdata,
+                                            GVariant        *part_payload,
                                             gboolean         trusted,
                                             GCancellable    *cancellable,
                                             GError         **error);
 
-gboolean _ostree_static_delta_part_execute_raw (OstreeRepo      *repo,
-                                                GVariant        *header,
-                                                GVariant        *part,
-                                                gboolean         trusted,
-                                                GCancellable    *cancellable,
-                                                GError         **error);
-
 void _ostree_static_delta_part_execute_async (OstreeRepo      *repo,
                                               GVariant        *header,
-                                              GBytes          *partdata,
+                                              GVariant        *part_payload,
                                               gboolean         trusted,
                                               GCancellable    *cancellable,
                                               GAsyncReadyCallback  callback,
diff --git a/src/libostree/ostree-repo-static-delta-processing.c 
b/src/libostree/ostree-repo-static-delta-processing.c
index 10e533c..74423e7 100644
--- a/src/libostree/ostree-repo-static-delta-processing.c
+++ b/src/libostree/ostree-repo-static-delta-processing.c
@@ -150,42 +150,12 @@ open_output_target (StaticDeltaExecutionState   *state,
 }
 
 gboolean
-_ostree_static_delta_part_validate (OstreeRepo     *repo,
-                                    GInputStream   *in,
-                                    guint           part_offset,
-                                    const char     *expected_checksum,
-                                    GCancellable   *cancellable,
-                                    GError        **error)
-{
-  gboolean ret = FALSE;
-  g_autofree guchar *actual_checksum_bytes = NULL;
-  g_autofree char *actual_checksum = NULL;
-  
-  if (!ot_gio_checksum_stream (in, &actual_checksum_bytes,
-                               cancellable, error))
-    goto out;
-
-  actual_checksum = ostree_checksum_from_bytes (actual_checksum_bytes);
-  if (strcmp (actual_checksum, expected_checksum) != 0)
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "Checksum mismatch in static delta part %u; expected=%s actual=%s",
-                   part_offset, expected_checksum, actual_checksum);
-      goto out;
-    }
-  
-  ret = TRUE;
- out:
-  return ret;
-}
-
-gboolean
-_ostree_static_delta_part_execute_raw (OstreeRepo      *repo,
-                                       GVariant        *objects,
-                                       GVariant        *part,
-                                       gboolean         trusted,
-                                       GCancellable    *cancellable,
-                                       GError         **error)
+_ostree_static_delta_part_execute (OstreeRepo      *repo,
+                                   GVariant        *objects,
+                                   GVariant        *part,
+                                   gboolean         trusted,
+                                   GCancellable    *cancellable,
+                                   GError         **error)
 {
   gboolean ret = FALSE;
   guint8 *checksums_data;
@@ -280,99 +250,10 @@ _ostree_static_delta_part_execute_raw (OstreeRepo      *repo,
   return ret;
 }
 
-static gboolean
-decompress_all (GConverter   *converter,
-                GBytes       *data,
-                GBytes      **out_uncompressed,
-                GCancellable *cancellable,
-                GError      **error)
-{
-  gboolean ret = FALSE;
-  g_autoptr(GMemoryInputStream) memin = (GMemoryInputStream*)g_memory_input_stream_new_from_bytes (data);
-  g_autoptr(GMemoryOutputStream) memout = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, 
g_realloc, g_free);
-  g_autoptr(GInputStream) convin = g_converter_input_stream_new ((GInputStream*)memin, converter);
-
-  {
-    gssize n_bytes_written = g_output_stream_splice ((GOutputStream*)memout, convin,
-                                                     G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
-                                                     G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
-                                                     cancellable, error);
-      if (n_bytes_written < 0)
-        goto out;
-  }
-
-  ret = TRUE;
-  *out_uncompressed = g_memory_output_stream_steal_as_bytes (memout);
- out:
-  return ret;
-}
-
-gboolean
-_ostree_static_delta_part_execute (OstreeRepo      *repo,
-                                   GVariant        *header,
-                                   GBytes          *part_bytes,
-                                   gboolean         trusted,
-                                   GCancellable    *cancellable,
-                                   GError         **error)
-{
-  gboolean ret = FALSE;
-  gsize partlen;
-  const guint8*partdata;
-  g_autoptr(GBytes) part_payload_bytes = NULL;
-  g_autoptr(GBytes) payload_data = NULL;
-  g_autoptr(GVariant) payload = NULL;
-  guint8 comptype;
-
-  partdata = g_bytes_get_data (part_bytes, &partlen);
-  
-  if (partlen < 1)
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "Corrupted 0 length delta part");
-      goto out;
-    }
-        
-  /* First byte is compression type */
-  comptype = partdata[0];
-  /* Then the rest may be compressed or uncompressed */
-  part_payload_bytes = g_bytes_new_from_bytes (part_bytes, 1, partlen - 1);
-  switch (comptype)
-    {
-    case 0:
-      /* No compression */
-      payload_data = g_bytes_ref (part_payload_bytes);
-      break;
-    case 'x':
-      {
-        g_autoptr(GConverter) decomp =
-          (GConverter*) _ostree_lzma_decompressor_new ();
-
-        if (!decompress_all (decomp, part_payload_bytes, &payload_data,
-                             cancellable, error))
-          goto out;
-      }
-      break;
-    default:
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "Invalid compression type '%u'", comptype);
-      goto out;
-    }
-        
-  payload = g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
-                                      payload_data, FALSE);
-  if (!_ostree_static_delta_part_execute_raw (repo, header, payload, trusted,
-                                              cancellable, error))
-    goto out;
-
-  ret = TRUE;
- out:
-  return ret;
-}
-
 typedef struct {
   OstreeRepo *repo;
   GVariant *header;
-  GBytes *partdata;
+  GVariant *part;
   GCancellable *cancellable;
   GSimpleAsyncResult *result;
   gboolean trusted;
@@ -385,7 +266,7 @@ static_delta_part_execute_async_data_free (gpointer user_data)
 
   g_clear_object (&data->repo);
   g_variant_unref (data->header);
-  g_bytes_unref (data->partdata);
+  g_variant_unref (data->part);
   g_clear_object (&data->cancellable);
   g_free (data);
 }
@@ -401,7 +282,7 @@ static_delta_part_execute_thread (GSimpleAsyncResult  *res,
   data = g_simple_async_result_get_op_res_gpointer (res);
   if (!_ostree_static_delta_part_execute (data->repo,
                                           data->header,
-                                          data->partdata,
+                                          data->part,
                                           data->trusted,
                                           cancellable, &error))
     g_simple_async_result_take_error (res, error);
@@ -410,7 +291,7 @@ static_delta_part_execute_thread (GSimpleAsyncResult  *res,
 void
 _ostree_static_delta_part_execute_async (OstreeRepo      *repo,
                                          GVariant        *header,
-                                         GBytes          *partdata,
+                                         GVariant        *part,
                                          gboolean         trusted,
                                          GCancellable    *cancellable,
                                          GAsyncReadyCallback  callback,
@@ -421,7 +302,7 @@ _ostree_static_delta_part_execute_async (OstreeRepo      *repo,
   asyncdata = g_new0 (StaticDeltaPartExecuteAsyncData, 1);
   asyncdata->repo = g_object_ref (repo);
   asyncdata->header = g_variant_ref (header);
-  asyncdata->partdata = g_bytes_ref (partdata);
+  asyncdata->part = g_variant_ref (part);
   asyncdata->trusted = trusted;
   asyncdata->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
 


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