[ostree] core: Add API for just effectively stat()ing packed files



commit 8f0afd1f5443b262f4e469ff26f5dc763f00e473
Author: Colin Walters <walters verbum org>
Date:   Tue Nov 8 19:37:41 2011 -0500

    core: Add API for just effectively stat()ing packed files
    
    This will allow us to implement more of a VFS-like API on top.

 libostree/ostree-core.c |   81 +++++++++++++++++++++++++++++++++-------------
 libostree/ostree-core.h |   10 +++++-
 2 files changed, 67 insertions(+), 24 deletions(-)
---
diff --git a/libostree/ostree-core.c b/libostree/ostree-core.c
index a54f628..904ce05 100644
--- a/libostree/ostree-core.c
+++ b/libostree/ostree-core.c
@@ -627,29 +627,20 @@ unpack_meta (const char   *path,
   return ret;
 }
 
-
-static gboolean
-unpack_file (const char   *path,
-             const char   *dest_path,    
-             GChecksum   **out_checksum,
-             GError      **error)
+gboolean
+ostree_parse_packed_file (GFile            *file,
+                          GVariant    **out_metadata,
+                          GInputStream **out_content,
+                          GCancellable *cancellable,
+                          GError      **error)
 {
   gboolean ret = FALSE;
-  GFile *file = NULL;
-  GFile *dest_file = NULL;
   char *metadata_buf = NULL;
-  GVariant *metadata = NULL;
-  GVariant *xattrs = NULL;
+  GVariant *ret_metadata = NULL;
   GFileInputStream *in = NULL;
-  GFileOutputStream *out = NULL;
-  GChecksum *ret_checksum = NULL;
   guint32 metadata_len;
-  guint32 version, uid, gid, mode;
-  guint64 content_len;
   gsize bytes_read;
 
-  file = ot_util_new_file_for_path (path);
-
   in = g_file_read (file, NULL, error);
   if (!in)
     goto out;
@@ -664,6 +655,13 @@ unpack_file (const char   *path,
     }
       
   metadata_len = GUINT32_FROM_BE (metadata_len);
+  if (metadata_len > OSTREE_MAX_METADATA_SIZE)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Corrupted packfile; metadata length %u is larger than maximum %u",
+                   metadata_len, OSTREE_MAX_METADATA_SIZE);
+      goto out;
+    }
   metadata_buf = g_malloc (metadata_len);
 
   if (!g_input_stream_read_all ((GInputStream*)in, metadata_buf, metadata_len, &bytes_read, NULL, error))
@@ -675,9 +673,47 @@ unpack_file (const char   *path,
       goto out;
     }
 
-  metadata = g_variant_new_from_data (G_VARIANT_TYPE (OSTREE_PACK_FILE_VARIANT_FORMAT),
-                                      metadata_buf, metadata_len, FALSE, NULL, NULL);
-      
+  ret_metadata = g_variant_new_from_data (G_VARIANT_TYPE (OSTREE_PACK_FILE_VARIANT_FORMAT),
+                                          metadata_buf, metadata_len, FALSE,
+                                          (GDestroyNotify)g_free,
+                                          metadata_buf);
+  metadata_buf = NULL;
+
+  ret = TRUE;
+  *out_metadata = ret_metadata;
+  ret_metadata = NULL;
+  *out_content = (GInputStream*)in;
+  in = NULL;
+ out:
+  g_clear_object (&in);
+  if (ret_metadata)
+   g_variant_unref (ret_metadata);
+  return ret;
+}
+
+static gboolean
+unpack_file (const char   *path,
+             const char   *dest_path,    
+             GChecksum   **out_checksum,
+             GError      **error)
+{
+  gboolean ret = FALSE;
+  GFile *file = NULL;
+  GFile *dest_file = NULL;
+  GVariant *metadata = NULL;
+  GVariant *xattrs = NULL;
+  GInputStream *in = NULL;
+  GFileOutputStream *out = NULL;
+  GChecksum *ret_checksum = NULL;
+  guint32 version, uid, gid, mode;
+  guint64 content_len;
+  gsize bytes_read;
+
+  file = ot_util_new_file_for_path (path);
+
+  if (!ostree_parse_packed_file (file, &metadata, &in, NULL, error))
+    goto out;
+
   g_variant_get (metadata, "(uuuu a(ayay)t)",
                  &version, &uid, &gid, &mode,
                  &xattrs, &content_len);
@@ -697,7 +733,7 @@ unpack_file (const char   *path,
       if (!out)
         goto out;
 
-      if (!splice_and_checksum ((GOutputStream*)out, (GInputStream*)in, ret_checksum, NULL, error))
+      if (!splice_and_checksum ((GOutputStream*)out, in, ret_checksum, NULL, error))
         goto out;
 
       if (!g_output_stream_close ((GOutputStream*)out, NULL, error))
@@ -707,7 +743,7 @@ unpack_file (const char   *path,
     {
       char target[PATH_MAX+1];
 
-      if (!g_input_stream_read_all ((GInputStream*)in, target, sizeof(target)-1, &bytes_read, NULL, error))
+      if (!g_input_stream_read_all (in, target, sizeof(target)-1, &bytes_read, NULL, error))
         goto out;
       target[bytes_read] = '\0';
       if (ret_checksum)
@@ -722,7 +758,7 @@ unpack_file (const char   *path,
     {
       guint32 dev;
 
-      if (!g_input_stream_read_all ((GInputStream*)in, &dev, 4, &bytes_read, NULL, error))
+      if (!g_input_stream_read_all (in, &dev, 4, &bytes_read, NULL, error))
         goto out;
       if (bytes_read != 4)
         {
@@ -773,7 +809,6 @@ unpack_file (const char   *path,
     (void) unlink (dest_path);
   if (ret_checksum)
     g_checksum_free (ret_checksum);
-  g_free (metadata_buf);
   g_clear_object (&file);
   g_clear_object (&dest_file);
   g_clear_object (&in);
diff --git a/libostree/ostree-core.h b/libostree/ostree-core.h
index 959a46b..3dc70b4 100644
--- a/libostree/ostree-core.h
+++ b/libostree/ostree-core.h
@@ -26,6 +26,8 @@
 
 G_BEGIN_DECLS
 
+#define OSTREE_MAX_METADATA_SIZE (1 << 26)
+
 #define OSTREE_GIO_FAST_QUERYINFO "standard::name,standard::type,standard::is-symlink,standard::symlink-target,unix::*"
 
 #define OSTREE_EMPTY_STRING_SHA256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
@@ -128,11 +130,17 @@ gboolean ostree_stat_and_checksum_file (int dirfd, const char *path,
 #define OSTREE_PACK_FILE_VARIANT_FORMAT "(uuuua(ayay)t)"
 
 gboolean  ostree_pack_object (GOutputStream     *output,
-                              GFile             *path,
+                              GFile             *file,
                               OstreeObjectType  objtype,
                               GCancellable     *cancellable,
                               GError          **error);
 
+gboolean ostree_parse_packed_file (GFile            *file,
+                                   GVariant    **out_metadata,
+                                   GInputStream **out_content,
+                                   GCancellable *cancellable,
+                                   GError      **error);
+
 gboolean ostree_unpack_object (const char   *path,
                                OstreeObjectType  objtype,
                                const char   *dest_path,    



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