unpacker: embed RPM checksum in metadata
In addition to the header checksum, we also want a checksum of the RPM file itself. This will allow us to know right away whether an RPM with the same NEVRA in the repos is actually the same one we already imported. Closes: #769 Approved by: cgwalters
This commit is contained in:
parent
fa10f36fb6
commit
eff00053ef
@ -1360,12 +1360,9 @@ rpmostree_dnf_add_checksum_goal (GChecksum *checksum,
|
|||||||
for (i = 0; i < pkglist->len; i++)
|
for (i = 0; i < pkglist->len; i++)
|
||||||
{
|
{
|
||||||
DnfPackage *pkg = pkglist->pdata[i];
|
DnfPackage *pkg = pkglist->pdata[i];
|
||||||
int pkg_checksum_type;
|
g_autofree char* chksum_repr = NULL;
|
||||||
const unsigned char *pkg_checksum_bytes = dnf_package_get_chksum (pkg, &pkg_checksum_type);
|
g_assert (rpmostree_get_repodata_chksum_repr (pkg, &chksum_repr, NULL));
|
||||||
g_autofree char *pkg_checksum = hy_chksum_str (pkg_checksum_bytes, pkg_checksum_type);
|
g_ptr_array_add (pkg_checksums, g_steal_pointer (&chksum_repr));
|
||||||
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_ptr_array_sort (pkg_checksums, rpmostree_ptrarray_sort_compare_strings);
|
g_ptr_array_sort (pkg_checksums, rpmostree_ptrarray_sort_compare_strings);
|
||||||
|
@ -1057,3 +1057,30 @@ rpmostree_fcap_to_xattr_variant (const char *fcap)
|
|||||||
vfsbytes, FALSE));
|
vfsbytes, FALSE));
|
||||||
return g_variant_ref_sink (g_variant_builder_end (&builder));
|
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;
|
||||||
|
}
|
||||||
|
@ -166,3 +166,8 @@ typedef enum {
|
|||||||
|
|
||||||
char *
|
char *
|
||||||
rpmostree_pkg_custom_nevra_strdup (Header h, RpmOstreePkgNevraFlags flags);
|
rpmostree_pkg_custom_nevra_strdup (Header h, RpmOstreePkgNevraFlags flags);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
rpmostree_get_repodata_chksum_repr (DnfPackage *pkg,
|
||||||
|
char **out_chksum_repr,
|
||||||
|
GError **error);
|
||||||
|
@ -431,7 +431,7 @@ get_lead_sig_header_as_bytes (RpmOstreeUnpacker *self,
|
|||||||
bytes_remaining);
|
bytes_remaining);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
*out_metadata = g_bytes_new_take (g_steal_pointer (&buf), self->cpio_offset);
|
*out_metadata = g_bytes_new_take (g_steal_pointer (&buf), self->cpio_offset);
|
||||||
out:
|
out:
|
||||||
@ -464,10 +464,13 @@ build_metadata_variant (RpmOstreeUnpacker *self,
|
|||||||
g_auto(GVariantBuilder) metadata_builder;
|
g_auto(GVariantBuilder) metadata_builder;
|
||||||
g_variant_builder_init (&metadata_builder, (GVariantType*)"a{sv}");
|
g_variant_builder_init (&metadata_builder, (GVariantType*)"a{sv}");
|
||||||
|
|
||||||
/* NB: We store the full header of the RPM in the commit for two reasons:
|
/* NB: We store the full header of the RPM in the commit for three reasons:
|
||||||
* first, it holds the file security capabilities, and secondly, we'll need to
|
* 1. it holds the file security capabilities, which we need during checkout
|
||||||
* provide it to librpm when it updates the rpmdb (see
|
* 2. we'll need to provide it to librpm when it updates the rpmdb (see
|
||||||
* rpmostree_context_assemble_commit()). */
|
* 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;
|
g_autoptr(GBytes) metadata = NULL;
|
||||||
|
|
||||||
@ -478,8 +481,6 @@ build_metadata_variant (RpmOstreeUnpacker *self,
|
|||||||
g_variant_new_from_bytes ((GVariantType*)"ay",
|
g_variant_new_from_bytes ((GVariantType*)"ay",
|
||||||
metadata, TRUE));
|
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_checksum_update (pkg_checksum, g_bytes_get_data (metadata, NULL),
|
||||||
g_bytes_get_size (metadata));
|
g_bytes_get_size (metadata));
|
||||||
|
|
||||||
@ -506,7 +507,7 @@ build_metadata_variant (RpmOstreeUnpacker *self,
|
|||||||
* compatible increments.
|
* compatible increments.
|
||||||
*/
|
*/
|
||||||
g_variant_builder_add (&metadata_builder, "{sv}", "rpmostree.unpack_minor_version",
|
g_variant_builder_add (&metadata_builder, "{sv}", "rpmostree.unpack_minor_version",
|
||||||
g_variant_new_uint32 (2));
|
g_variant_new_uint32 (3));
|
||||||
|
|
||||||
if (self->pkg)
|
if (self->pkg)
|
||||||
{
|
{
|
||||||
@ -516,6 +517,16 @@ build_metadata_variant (RpmOstreeUnpacker *self,
|
|||||||
g_variant_builder_add (&metadata_builder, "{sv}", "rpmostree.repo",
|
g_variant_builder_add (&metadata_builder, "{sv}", "rpmostree.repo",
|
||||||
repo_metadata_to_variant (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);
|
*out_variant = g_variant_builder_end (&metadata_builder);
|
||||||
|
Loading…
Reference in New Issue
Block a user