summaryrefslogtreecommitdiff
path: root/src/libostree/ostree-core.c
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 /src/libostree/ostree-core.c
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.
Diffstat (limited to 'src/libostree/ostree-core.c')
-rw-r--r--src/libostree/ostree-core.c112
1 files changed, 112 insertions, 0 deletions
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,