diff options
author | Dan Nicholson <nicholson@endlessm.com> | 2020-01-20 19:54:00 -0700 |
---|---|---|
committer | Dan Nicholson <nicholson@endlessm.com> | 2020-01-20 20:46:29 -0700 |
commit | 260bcd11938be8fbe49846eff913206e5df4168a (patch) | |
tree | 7946386a88e06507ef507925cc50ab515af52ed7 | |
parent | fcbb453443c4f22e8621c8593877ab775e5a5884 (diff) | |
download | ostree-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.am | 5 | ||||
-rw-r--r-- | apidoc/ostree-sections.txt | 1 | ||||
-rw-r--r-- | src/libostree/libostree-devel.sym | 1 | ||||
-rw-r--r-- | src/libostree/ostree-core-private.h | 3 | ||||
-rw-r--r-- | src/libostree/ostree-core.c | 112 | ||||
-rw-r--r-- | src/libostree/ostree-core.h | 5 | ||||
-rw-r--r-- | src/libostree/ostree-repo-private.h | 2 |
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" |