summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Nicholson <nicholson@endlessm.com>2020-01-20 19:54:00 -0700
committerDan Nicholson <nicholson@endlessm.com>2020-01-20 20:46:29 -0700
commit260bcd11938be8fbe49846eff913206e5df4168a (patch)
tree7946386a88e06507ef507925cc50ab515af52ed7
parentfcbb453443c4f22e8621c8593877ab775e5a5884 (diff)
downloadostree-260bcd11938be8fbe49846eff913206e5df4168a.tar.gz
core: Add ostree_commit_get_object_sizes API
This function parses the object listing in the `ostree.sizes` metadata and returns an array of `OstreeCommitSizesEntry` structures. Unfortunately, for reasons I don't understand, the linker wants to resolve `_ostree_read_varuint64` from `ostree-core.c` even though it's not used by `test-checksum.c` at all.
-rw-r--r--Makefile-tests.am5
-rw-r--r--apidoc/ostree-sections.txt1
-rw-r--r--src/libostree/libostree-devel.sym1
-rw-r--r--src/libostree/ostree-core-private.h3
-rw-r--r--src/libostree/ostree-core.c112
-rw-r--r--src/libostree/ostree-core.h5
-rw-r--r--src/libostree/ostree-repo-private.h2
7 files changed, 126 insertions, 3 deletions
diff --git a/Makefile-tests.am b/Makefile-tests.am
index fc2f2d91..a4acb8e0 100644
--- a/Makefile-tests.am
+++ b/Makefile-tests.am
@@ -347,7 +347,10 @@ tests_test_varint_LDADD = $(TESTS_LDADD)
tests_test_bsdiff_CFLAGS = $(TESTS_CFLAGS)
tests_test_bsdiff_LDADD = libbsdiff.la $(TESTS_LDADD)
-tests_test_checksum_SOURCES = src/libostree/ostree-core.c tests/test-checksum.c
+tests_test_checksum_SOURCES = \
+ src/libostree/ostree-core.c \
+ src/libostree/ostree-varint.c \
+ tests/test-checksum.c
tests_test_checksum_CFLAGS = $(TESTS_CFLAGS) $(libglnx_cflags)
tests_test_checksum_LDADD = $(TESTS_LDADD)
diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt
index 33035ca7..32cf5228 100644
--- a/apidoc/ostree-sections.txt
+++ b/apidoc/ostree-sections.txt
@@ -151,6 +151,7 @@ ostree_validate_structureof_dirmeta
ostree_commit_get_parent
ostree_commit_get_timestamp
ostree_commit_get_content_checksum
+ostree_commit_get_object_sizes
OstreeCommitSizesEntry
ostree_commit_sizes_entry_new
ostree_commit_sizes_entry_copy
diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym
index 8e7473c5..ff5f52c4 100644
--- a/src/libostree/libostree-devel.sym
+++ b/src/libostree/libostree-devel.sym
@@ -20,6 +20,7 @@
/* Add new symbols here. Release commits should copy this section into -released.sym. */
LIBOSTREE_2019.7 {
global:
+ ostree_commit_get_object_sizes;
ostree_commit_sizes_entry_copy;
ostree_commit_sizes_entry_free;
ostree_commit_sizes_entry_get_type;
diff --git a/src/libostree/ostree-core-private.h b/src/libostree/ostree-core-private.h
index 43cf22c4..c1a82386 100644
--- a/src/libostree/ostree-core-private.h
+++ b/src/libostree/ostree-core-private.h
@@ -102,6 +102,9 @@ _ostree_checksum_inplace_from_bytes_v (GVariant *csum_v, char *buf)
*/
#define _OSTREE_LOOSE_PATH_MAX (256)
+/* GVariant format for ostree.sizes metadata entries. */
+#define _OSTREE_OBJECT_SIZES_ENTRY_SIGNATURE "ay"
+
char *
_ostree_get_relative_object_path (const char *checksum,
OstreeObjectType type,
diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c
index 160f954f..4667dd8f 100644
--- a/src/libostree/ostree-core.c
+++ b/src/libostree/ostree-core.c
@@ -32,6 +32,7 @@
#include "ostree.h"
#include "ostree-core-private.h"
#include "ostree-chain-input-stream.h"
+#include "ostree-varint.h"
#include "otutil.h"
/* Generic ABI checks */
@@ -2500,6 +2501,117 @@ ostree_commit_sizes_entry_free (OstreeCommitSizesEntry *entry)
g_free (entry);
}
+static gboolean
+read_sizes_entry (GVariant *entry,
+ OstreeCommitSizesEntry **out_sizes,
+ GError **error)
+{
+ gsize entry_size = g_variant_get_size (entry);
+ g_return_val_if_fail (entry_size >= OSTREE_SHA256_DIGEST_LEN + 2, FALSE);
+
+ const guchar *buffer = g_variant_get_data (entry);
+ if (buffer == NULL)
+ return glnx_throw (error, "Could not read ostree.sizes metadata entry");
+
+ char checksum[OSTREE_SHA256_STRING_LEN + 1];
+ ostree_checksum_inplace_from_bytes (buffer, checksum);
+ buffer += OSTREE_SHA256_DIGEST_LEN;
+ entry_size -= OSTREE_SHA256_DIGEST_LEN;
+
+ gsize bytes_read = 0;
+ guint64 archived = 0;
+ if (!_ostree_read_varuint64 (buffer, entry_size, &archived, &bytes_read))
+ return glnx_throw (error, "Unexpected EOF reading ostree.sizes varint");
+ buffer += bytes_read;
+ entry_size -= bytes_read;
+
+ guint64 unpacked = 0;
+ if (!_ostree_read_varuint64 (buffer, entry_size, &unpacked, &bytes_read))
+ return glnx_throw (error, "Unexpected EOF reading ostree.sizes varint");
+ buffer += bytes_read;
+ entry_size -= bytes_read;
+
+ /* On newer commits, an additional byte is used for the object type. */
+ OstreeObjectType objtype;
+ if (entry_size > 0)
+ {
+ objtype = *buffer;
+ if (objtype < OSTREE_OBJECT_TYPE_FILE || objtype > OSTREE_OBJECT_TYPE_LAST)
+ return glnx_throw (error, "Unexpected ostree.sizes object type %u",
+ objtype);
+ buffer++;
+ entry_size--;
+ }
+ else
+ {
+ /* Assume the object is a file. */
+ objtype = OSTREE_OBJECT_TYPE_FILE;
+ }
+
+ g_autoptr(OstreeCommitSizesEntry) sizes = ostree_commit_sizes_entry_new (checksum,
+ objtype,
+ unpacked,
+ archived);
+
+ if (out_sizes != NULL)
+ *out_sizes = g_steal_pointer (&sizes);
+
+ return TRUE;
+}
+
+/**
+ * ostree_commit_get_object_sizes:
+ * @commit_variant: (not nullable): variant of type %OSTREE_OBJECT_TYPE_COMMIT
+ * @out_sizes_entries: (out) (element-type OstreeCommitSizesEntry) (transfer container) (optional):
+ * return location for an array of object size entries
+ * @error: Error
+ *
+ * Reads a commit's "ostree.sizes" metadata and returns an array of
+ * #OstreeCommitSizesEntry in @out_sizes_entries. Each element
+ * represents an object in the commit. If the commit does not contain
+ * the "ostree.sizes" metadata, a %G_IO_ERROR_NOT_FOUND error will be
+ * returned.
+ *
+ * Since: 2019.7
+ */
+gboolean
+ostree_commit_get_object_sizes (GVariant *commit_variant,
+ GPtrArray **out_sizes_entries,
+ GError **error)
+{
+ g_return_val_if_fail (commit_variant != NULL, FALSE);
+
+ g_autoptr(GVariant) metadata = g_variant_get_child_value (commit_variant, 0);
+ g_autoptr(GVariant) sizes_variant =
+ g_variant_lookup_value (metadata, "ostree.sizes",
+ G_VARIANT_TYPE ("a" _OSTREE_OBJECT_SIZES_ENTRY_SIGNATURE));
+ if (sizes_variant == NULL)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ "No metadata key ostree.sizes in commit");
+ return FALSE;
+ }
+
+ g_autoptr(GPtrArray) sizes_entries =
+ g_ptr_array_new_with_free_func ((GDestroyNotify) ostree_commit_sizes_entry_free);
+ g_autoptr(GVariant) entry = NULL;
+ GVariantIter entry_iter;
+ g_variant_iter_init (&entry_iter, sizes_variant);
+ while ((entry = g_variant_iter_next_value (&entry_iter)))
+ {
+ OstreeCommitSizesEntry *sizes_entry = NULL;
+ if (!read_sizes_entry (entry, &sizes_entry, error))
+ return FALSE;
+ g_clear_pointer (&entry, g_variant_unref);
+ g_ptr_array_add (sizes_entries, sizes_entry);
+ }
+
+ if (out_sizes_entries != NULL)
+ *out_sizes_entries = g_steal_pointer (&sizes_entries);
+
+ return TRUE;
+}
+
/* Used in pull/deploy to validate we're not being downgraded */
gboolean
_ostree_compare_timestamps (const char *current_rev,
diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h
index a61ae06c..10601123 100644
--- a/src/libostree/ostree-core.h
+++ b/src/libostree/ostree-core.h
@@ -554,6 +554,11 @@ _OSTREE_PUBLIC
void ostree_commit_sizes_entry_free (OstreeCommitSizesEntry *entry);
_OSTREE_PUBLIC
+gboolean ostree_commit_get_object_sizes (GVariant *commit_variant,
+ GPtrArray **out_sizes_entries,
+ GError **error);
+
+_OSTREE_PUBLIC
gboolean ostree_check_version (guint required_year, guint required_release);
G_END_DECLS
diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h
index 2864d81e..0465327c 100644
--- a/src/libostree/ostree-repo-private.h
+++ b/src/libostree/ostree-repo-private.h
@@ -31,8 +31,6 @@ G_BEGIN_DECLS
#define OSTREE_DELTAPART_VERSION (0)
-#define _OSTREE_OBJECT_SIZES_ENTRY_SIGNATURE "ay"
-
#define _OSTREE_SUMMARY_CACHE_DIR "summaries"
#define _OSTREE_CACHE_DIR "cache"