diff --git a/src/libpriv/rpmostree-core.c b/src/libpriv/rpmostree-core.c index df768887..3121045e 100644 --- a/src/libpriv/rpmostree-core.c +++ b/src/libpriv/rpmostree-core.c @@ -1360,12 +1360,9 @@ rpmostree_dnf_add_checksum_goal (GChecksum *checksum, for (i = 0; i < pkglist->len; i++) { DnfPackage *pkg = pkglist->pdata[i]; - int pkg_checksum_type; - const unsigned char *pkg_checksum_bytes = dnf_package_get_chksum (pkg, &pkg_checksum_type); - g_autofree char *pkg_checksum = hy_chksum_str (pkg_checksum_bytes, pkg_checksum_type); - char *pkg_checksum_with_type = g_strconcat (hy_chksum_name (pkg_checksum_type), ":", pkg_checksum, NULL); - - g_ptr_array_add (pkg_checksums, pkg_checksum_with_type); + g_autofree char* chksum_repr = NULL; + g_assert (rpmostree_get_repodata_chksum_repr (pkg, &chksum_repr, NULL)); + g_ptr_array_add (pkg_checksums, g_steal_pointer (&chksum_repr)); } g_ptr_array_sort (pkg_checksums, rpmostree_ptrarray_sort_compare_strings); diff --git a/src/libpriv/rpmostree-rpm-util.c b/src/libpriv/rpmostree-rpm-util.c index 9b59a27e..c51ba3a5 100644 --- a/src/libpriv/rpmostree-rpm-util.c +++ b/src/libpriv/rpmostree-rpm-util.c @@ -1057,3 +1057,30 @@ rpmostree_fcap_to_xattr_variant (const char *fcap) vfsbytes, FALSE)); return g_variant_ref_sink (g_variant_builder_end (&builder)); } + +/* Returns the checksum of the RPM we retrieved from the repodata XML. The + * actual checksum type used depends on how the repodata was created. Thus, the + * output is a string representation of the form "TYPE:HASH" where TYPE is the + * name of the checksum employed. In most cases, it will be "sha256" (the + * current default for `createrepo_c`). */ +gboolean +rpmostree_get_repodata_chksum_repr (DnfPackage *pkg, + char **out_chksum_repr, + GError **error) +{ + int chksum_type; + g_autofree char *chksum = NULL; + const unsigned char *chksum_raw = NULL; + + chksum_raw = dnf_package_get_chksum (pkg, &chksum_type); + if (chksum_raw) + chksum = hy_chksum_str (chksum_raw, chksum_type); + + if (chksum == NULL) + return glnx_throw (error, "Couldn't get chksum for pkg %s", + dnf_package_get_nevra(pkg)); + + *out_chksum_repr = + g_strconcat (hy_chksum_name (chksum_type), ":", chksum, NULL); + return TRUE; +} diff --git a/src/libpriv/rpmostree-rpm-util.h b/src/libpriv/rpmostree-rpm-util.h index 0368a79d..165483d4 100644 --- a/src/libpriv/rpmostree-rpm-util.h +++ b/src/libpriv/rpmostree-rpm-util.h @@ -166,3 +166,8 @@ typedef enum { char * rpmostree_pkg_custom_nevra_strdup (Header h, RpmOstreePkgNevraFlags flags); + +gboolean +rpmostree_get_repodata_chksum_repr (DnfPackage *pkg, + char **out_chksum_repr, + GError **error); diff --git a/src/libpriv/rpmostree-unpacker.c b/src/libpriv/rpmostree-unpacker.c index ceb341fe..5339cda0 100644 --- a/src/libpriv/rpmostree-unpacker.c +++ b/src/libpriv/rpmostree-unpacker.c @@ -431,7 +431,7 @@ get_lead_sig_header_as_bytes (RpmOstreeUnpacker *self, bytes_remaining); goto out; } - + ret = TRUE; *out_metadata = g_bytes_new_take (g_steal_pointer (&buf), self->cpio_offset); out: @@ -464,10 +464,13 @@ build_metadata_variant (RpmOstreeUnpacker *self, g_auto(GVariantBuilder) metadata_builder; g_variant_builder_init (&metadata_builder, (GVariantType*)"a{sv}"); - /* NB: We store the full header of the RPM in the commit for two reasons: - * first, it holds the file security capabilities, and secondly, we'll need to - * provide it to librpm when it updates the rpmdb (see - * rpmostree_context_assemble_commit()). */ + /* NB: We store the full header of the RPM in the commit for three reasons: + * 1. it holds the file security capabilities, which we need during checkout + * 2. we'll need to provide it to librpm when it updates the rpmdb (see + * rpmostree_context_assemble_commit()) + * 3. it's needed in the local pkgs paths to fool the libdnf stack (see + * rpmostree_context_prepare_install()) + */ { g_autoptr(GBytes) metadata = NULL; @@ -478,8 +481,6 @@ build_metadata_variant (RpmOstreeUnpacker *self, g_variant_new_from_bytes ((GVariantType*)"ay", metadata, TRUE)); - /* NB: the header also includes checksums for every entry in the (cut-off) - * archive, so there's no need to also bring that in */ g_checksum_update (pkg_checksum, g_bytes_get_data (metadata, NULL), g_bytes_get_size (metadata)); @@ -506,7 +507,7 @@ build_metadata_variant (RpmOstreeUnpacker *self, * compatible increments. */ g_variant_builder_add (&metadata_builder, "{sv}", "rpmostree.unpack_minor_version", - g_variant_new_uint32 (2)); + g_variant_new_uint32 (3)); if (self->pkg) { @@ -516,6 +517,16 @@ build_metadata_variant (RpmOstreeUnpacker *self, g_variant_builder_add (&metadata_builder, "{sv}", "rpmostree.repo", repo_metadata_to_variant (repo)); } + + /* include a checksum of the RPM as a whole; the actual algo used depends + * on how the repodata was created, so just keep a repr */ + g_autofree char* chksum_repr = NULL; + if (!rpmostree_get_repodata_chksum_repr (self->pkg, &chksum_repr, error)) + return FALSE; + + g_variant_builder_add (&metadata_builder, "{sv}", + "rpmostree.repodata_checksum", + g_variant_new_string (chksum_repr)); } *out_variant = g_variant_builder_end (&metadata_builder);