diff --git a/.gitignore b/.gitignore index 448633a..b822708 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/rpm-ostree-2020.7.tar.xz +SOURCES/rpm-ostree-2021.5.tar.xz diff --git a/.rpm-ostree.metadata b/.rpm-ostree.metadata index 5457220..e49e9f6 100644 --- a/.rpm-ostree.metadata +++ b/.rpm-ostree.metadata @@ -1 +1 @@ -d17719c3f3574bc49348124d5636035a55c8ccdc SOURCES/rpm-ostree-2020.7.tar.xz +0bd34ca2600986c3416961ee028946d0e68da21f SOURCES/rpm-ostree-2021.5.tar.xz diff --git a/SOURCES/0001-github-jmesmon-rust-systemd-pr200.patch b/SOURCES/0001-github-jmesmon-rust-systemd-pr200.patch new file mode 100644 index 0000000..631f458 --- /dev/null +++ b/SOURCES/0001-github-jmesmon-rust-systemd-pr200.patch @@ -0,0 +1,87 @@ +diff --git rpm-ostree-2021.5/vendor/libsystemd-sys/.cargo-checksum.json rpm-ostree-2021.5/vendor/libsystemd-sys/.cargo-checksum.json +index ef0104f..18671cd 100644 +--- rpm-ostree-2021.5/vendor/libsystemd-sys/.cargo-checksum.json ++++ rpm-ostree-2021.5/vendor/libsystemd-sys/.cargo-checksum.json +@@ -1 +1 @@ +-{"files": {"Cargo.toml": "29598137eb17a38f964952574d6f13f17d30b1f6d262a35ae5a1e9cc6f7ee180", "build.rs": "cb99af17b48e1874905513f956e99a1e5d7d55305b4d587c219719481d37ba1c", "src/bus/mod.rs": "ecd83596dd27674a43369dbeb88b9446e0907abb146e9f17e0499cda77aec22c", "src/bus/protocol.rs": "db8b3f47ba396b12868b4700b627683748682936ad4aad98ec4489c7c29450bd", "src/bus/vtable.rs": "547c322b93466b1919de3086304fa7f0ed650bde3556b349b5eebf35ec5fd0d1", "src/daemon.rs": "8ac4c744fe37beca7dfcd3e3d2ccab7150a709969d41ed38b980635a4f585f4b", "src/event.rs": "defaeb91eaddf36aa848e05d54def27351e35605dde5b451230866ce35c8a242", "src/id128.rs": "b7d7767fef5e2799450f694a4b7bfaf483819ffdc6b1fc3b9b21b41d0e9cfa30", "src/journal.rs": "af4a90da1bf57d2601248588766df3ad92a44558e026092850e7b555088787fa", "src/lib.rs": "7239092e42a3e7d0039f8436402a946a2cc8ffd3070fe4b6d81e255533cc4088", "src/login.rs": "eae9145e5ffe7f5050c58fa4757202a6eb5a5885b52d8ff1ebe44484608065c8", "tests/journal-send.rs": "ca18cc28bad06f8a55e910501de9681b410718afb6e1bd603c6b5063a07b6a63"}, "package": "6e03fd580bcecda68dcdcd5297085ade6a3dc552cd8b030d2b94a9b089ef7ab8"} +\ No newline at end of file ++{"files": {}, "package": "6e03fd580bcecda68dcdcd5297085ade6a3dc552cd8b030d2b94a9b089ef7ab8"} +diff --git rpm-ostree-2021.5/vendor/libsystemd-sys/src/journal.rs rpm-ostree-2021.5/vendor/libsystemd-sys/src/journal.rs +index 5980b81..68e4e68 100644 +--- rpm-ostree-2021.5/vendor/libsystemd-sys/src/journal.rs ++++ rpm-ostree-2021.5/vendor/libsystemd-sys/src/journal.rs +@@ -27,11 +27,6 @@ extern "C" { + // (we don't need to do c-style format strings) + + pub fn sd_journal_open(ret: *mut *mut sd_journal, flags: c_int) -> c_int; +- pub fn sd_journal_open_namespace( +- ret: *mut *mut sd_journal, +- namespace: *const c_char, +- flags: c_int, +- ) -> c_int; + pub fn sd_journal_open_directory( + ret: *mut *mut sd_journal, + path: *const c_char, +diff --git rpm-ostree-2021.5/vendor/systemd/.cargo-checksum.json rpm-ostree-2021.5/vendor/systemd/.cargo-checksum.json +index bc8d44c..9136865 100644 +--- rpm-ostree-2021.5/vendor/systemd/.cargo-checksum.json ++++ rpm-ostree-2021.5/vendor/systemd/.cargo-checksum.json +@@ -1 +1 @@ +-{"files": {"Cargo.toml": "70c57c11076fa8ba3826afe5db35c07ebc7312286ac4586b5387dc80d2adf719", "README.md": "13664522a229dc1e862dc11dd1f840cf4aa238c64578a0fc906f0caa3f7f494d", "src/bus/mod.rs": "559f1e10c6eb881629cfa3eb936890cdfbe1a44c186de95ea720c765be83cb39", "src/bus/types.rs": "25abd29a6c8695a37f42e708aa6cf26d7f833941742a80a78b3fc9012ad9e981", "src/daemon.rs": "f8d5e7584ea6543c3b5d8f45033d125af4511d8a0014f783944323458b693db3", "src/id128.rs": "a58b281ab0e52dd378bffd3fe161b9c73f2983a795e951ed70b3b0a8b333c62f", "src/journal.rs": "2281b81cfd7dc6c614b7a5fea4a4851a0f61e1dc780b11e10270264398d00345", "src/lib.rs": "6ee64a876e7b4157b2edea726e4bdf086f294df5a44c4d7eb09eee8883945755", "src/login.rs": "abed971dba12598f062cb78da3fc97e3c73db71eab3dade46c4f68fe9e4d7ca4"}, "package": "f722cabda922e471742300045f56dbaa53fafbb4520fca304e51258019bfe91d"} +\ No newline at end of file ++{"files": {}, "package": "f722cabda922e471742300045f56dbaa53fafbb4520fca304e51258019bfe91d"} +diff --git rpm-ostree-2021.5/vendor/systemd/src/journal.rs rpm-ostree-2021.5/vendor/systemd/src/journal.rs +index c49e891..6757a40 100644 +--- rpm-ostree-2021.5/vendor/systemd/src/journal.rs ++++ rpm-ostree-2021.5/vendor/systemd/src/journal.rs +@@ -396,22 +396,7 @@ impl OpenOptions { + /// + /// `sd_journal_open()`: https://www.freedesktop.org/software/systemd/man/sd_journal_open.html + pub fn open(&self) -> Result { +- Journal::open_with_opts_ns::<&std::ffi::CStr>(None, self) +- } +- +- /// Open the log journal for reading in the given namespace. Entries included are dependent on +- /// options. +- /// +- /// Note that some options (`SD_JOURNAL_ALL_NAMESPACES`) affect whether `namespace` is +- /// considered. Our API doesn't check for unused data here, but users are encouraged to avoid +- /// passing unused data by using [`OpenOptions::open()`] instead when a namespace argument is +- /// not required. +- /// +- /// This corresponds to [`sd_journal_open_namespace()`] +- /// +- /// `sd_journal_open_namespace()`: https://www.freedesktop.org/software/systemd/man/sd_journal_open.html +- pub fn open_namespace(&self, namespace: A) -> Result { +- Journal::open_with_opts_ns(Some(namespace), self) ++ Journal::open_with_opts::<&std::ffi::CStr>(self) + } + } + +@@ -508,10 +493,7 @@ impl OpenFilesOptions { + } + + impl Journal { +- fn open_with_opts_ns( +- namespace: Option, +- opts: &OpenOptions, +- ) -> Result { ++ fn open_with_opts(opts: &OpenOptions) -> Result { + let mut flags = opts.extra_raw_flags; + if opts.current_user { + flags |= ffi::SD_JOURNAL_CURRENT_USER; +@@ -535,13 +517,8 @@ impl Journal { + flags |= ffi::SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE; + } + +- let ns = namespace.map(|a| a.into_cstr()); +- let ns_p = ns +- .as_ref() +- .map(|a| a.as_ref().as_ptr()) +- .unwrap_or(ptr::null()); + let mut jp = MaybeUninit::uninit(); +- crate::ffi_result(unsafe { ffi::sd_journal_open_namespace(jp.as_mut_ptr(), ns_p, flags) })?; ++ crate::ffi_result(unsafe { ffi::sd_journal_open(jp.as_mut_ptr(), flags) })?; + Ok(unsafe { Journal::from_ptr(jp.assume_init()) }) + } + diff --git a/SOURCES/0002-github-coreos-rpm-ostree-pr2869.patch b/SOURCES/0002-github-coreos-rpm-ostree-pr2869.patch new file mode 100644 index 0000000..78cf393 --- /dev/null +++ b/SOURCES/0002-github-coreos-rpm-ostree-pr2869.patch @@ -0,0 +1,798 @@ +From 63275852afc4ab0bd0c45ac80f8f865c222759ac Mon Sep 17 00:00:00 2001 +From: Luca BRUNO +Date: Mon, 31 May 2021 10:15:55 +0000 +Subject: [PATCH 1/6] lib: temporarily fork rpmver logic + +This adds an internal temporary copy of the rpm version comparison +logic from librpmio (LGPL). +It allows relaxing the minimum library version to >= 4.14. +--- + Makefile-lib.am | 1 + + configure.ac | 6 + + src/lib/rpmostree-package.c | 7 +- + src/lib/rpmver-private.c | 223 ++++++++++++++++++++++++++++++++++++ + src/lib/rpmver-private.h | 108 +++++++++++++++++ + 5 files changed, 344 insertions(+), 1 deletion(-) + create mode 100644 src/lib/rpmver-private.c + create mode 100644 src/lib/rpmver-private.h + +diff --git a/Makefile-lib.am b/Makefile-lib.am +index bef049e1e7..f9d67f5c57 100644 +--- a/Makefile-lib.am ++++ b/Makefile-lib.am +@@ -28,6 +28,7 @@ librpmostree_1_la_SOURCES = \ + src/lib/rpmostree.c \ + src/lib/rpmostree-db.c \ + src/lib/rpmostree-package.c \ ++ src/lib/rpmver-private.c \ + $(NULL) + + librpmostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/libglnx -I$(srcdir)/src/libpriv -I$(srcdir)/src/lib \ +diff --git a/configure.ac b/configure.ac +index e763781566..ef5551657f 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -53,6 +53,12 @@ dnl RHEL8.1 has old libarchive + AS_IF([pkg-config --atleast-version=3.3.3 libarchive], + [AC_DEFINE([HAVE_LIBARCHIVE_ZSTD], 1, [Define if we have libarchive with zstd])]) + ++# rpmver is available in rpm >= 4.16, el8 is still on 4.14 ++AC_SEARCH_LIBS([rpmverCmp], [rpm], ++ AC_DEFINE([BUILDOPT_HAVE_RPMVER], 1, [Whether rpmver API is available in librpmio]), ++ AC_DEFINE([BUILDOPT_HAVE_RPMVER], 0, [Whether rpmver API is available in librpmio]) ++) ++ + dnl We don't *actually* use this ourself, but librepo does, and libdnf gets confused + dnl if librepo doesn't support it. + have_zchunk=no +diff --git a/src/lib/rpmostree-package.c b/src/lib/rpmostree-package.c +index 8575c4a5ed..3bb03bfef0 100644 +--- a/src/lib/rpmostree-package.c ++++ b/src/lib/rpmostree-package.c +@@ -32,12 +32,17 @@ + + #include + #include +-#include + #include "libglnx.h" + + #include "rpmostree-shlib-ipc-private.h" + #include "rpmostree-package-priv.h" + ++#if BUILDOPT_HAVE_RPMVER ++#include ++#else ++#include "rpmver-private.h" ++#endif ++ + typedef GObjectClass RpmOstreePackageClass; + + /* Since the class is small, we perform a poor man's polymorphism; RpmOstreePackage objects +diff --git a/src/lib/rpmver-private.c b/src/lib/rpmver-private.c +new file mode 100644 +index 0000000000..117df79206 +--- /dev/null ++++ b/src/lib/rpmver-private.c +@@ -0,0 +1,223 @@ ++// Temporary forked internal copy of: ++// https://github.com/rpm-software-management/rpm/blob/rpm-4.16.1.3/rpmio/rpmver.c ++// SPDX-License-Identifier: LGPL-2.1-or-later ++ ++/* NOTE(lucab): compatibility changes to avoid touching the source. ++ * The *malloc functions have different behaviors when size=0, but this is not ++ * a concern here because all calls in this file have strictly-positive size. ++ */ ++#include "config.h" ++#if !BUILDOPT_HAVE_RPMVER ++#include ++#define xmalloc(_size) g_malloc((_size)) ++#define free(_mem) g_free((_mem)) ++#include "rpmver-private.h" ++ ++#include ++#include ++ ++struct rpmver_s { ++ const char *e; ++ const char *v; ++ const char *r; ++ char arena[]; ++}; ++ ++/** ++ * Split EVR into epoch, version, and release components. ++ * @param evr [epoch:]version[-release] string ++ * @retval *ep pointer to epoch ++ * @retval *vp pointer to version ++ * @retval *rp pointer to release ++ */ ++static ++void parseEVR(char * evr, ++ const char ** ep, ++ const char ** vp, ++ const char ** rp) ++{ ++ const char *epoch; ++ const char *version; /* assume only version is present */ ++ const char *release; ++ char *s, *se; ++ ++ s = evr; ++ while (*s && risdigit(*s)) s++; /* s points to epoch terminator */ ++ se = strrchr(s, '-'); /* se points to version terminator */ ++ ++ if (*s == ':') { ++ epoch = evr; ++ *s++ = '\0'; ++ version = s; ++ if (*epoch == '\0') epoch = "0"; ++ } else { ++ epoch = NULL; /* XXX disable epoch compare if missing */ ++ version = evr; ++ } ++ if (se) { ++ *se++ = '\0'; ++ release = se; ++ } else { ++ release = NULL; ++ } ++ ++ if (ep) *ep = epoch; ++ if (vp) *vp = version; ++ if (rp) *rp = release; ++} ++ ++int rpmverOverlap(rpmver v1, rpmsenseFlags f1, rpmver v2, rpmsenseFlags f2) ++{ ++ int sense = 0; ++ int result = 0; ++ ++ /* Compare {A,B} [epoch:]version[-release] */ ++ if (v1->e && *v1->e && v2->e && *v2->e) ++ sense = rpmvercmp(v1->e, v2->e); ++ else if (v1->e && *v1->e && atol(v1->e) > 0) { ++ sense = 1; ++ } else if (v2->e && *v2->e && atol(v2->e) > 0) ++ sense = -1; ++ ++ if (sense == 0) { ++ sense = rpmvercmp(v1->v, v2->v); ++ if (sense == 0) { ++ if (v1->r && *v1->r && v2->r && *v2->r) { ++ sense = rpmvercmp(v1->r, v2->r); ++ } else { ++ /* always matches if the side with no release has SENSE_EQUAL */ ++ if ((v1->r && *v1->r && (f2 & RPMSENSE_EQUAL)) || ++ (v2->r && *v2->r && (f1 & RPMSENSE_EQUAL))) { ++ result = 1; ++ goto exit; ++ } ++ } ++ } ++ } ++ ++ /* Detect overlap of {A,B} range. */ ++ if (sense < 0 && ((f1 & RPMSENSE_GREATER) || (f2 & RPMSENSE_LESS))) { ++ result = 1; ++ } else if (sense > 0 && ((f1 & RPMSENSE_LESS) || (f2 & RPMSENSE_GREATER))) { ++ result = 1; ++ } else if (sense == 0 && ++ (((f1 & RPMSENSE_EQUAL) && (f2 & RPMSENSE_EQUAL)) || ++ ((f1 & RPMSENSE_LESS) && (f2 & RPMSENSE_LESS)) || ++ ((f1 & RPMSENSE_GREATER) && (f2 & RPMSENSE_GREATER)))) { ++ result = 1; ++ } ++ ++exit: ++ return result; ++} ++ ++static int compare_values(const char *str1, const char *str2) ++{ ++ if (!str1 && !str2) ++ return 0; ++ else if (str1 && !str2) ++ return 1; ++ else if (!str1 && str2) ++ return -1; ++ return rpmvercmp(str1, str2); ++} ++ ++int rpmverCmp(rpmver v1, rpmver v2) ++{ ++ const char *e1 = (v1->e != NULL) ? v1->e : "0"; ++ const char *e2 = (v2->e != NULL) ? v2->e : "0"; ++ ++ int rc = compare_values(e1, e2); ++ if (!rc) { ++ rc = compare_values(v1->v, v2->v); ++ if (!rc) ++ rc = compare_values(v1->r, v2->r); ++ } ++ return rc; ++} ++ ++uint32_t rpmverEVal(rpmver rv) ++{ ++ return (rv != NULL && rv->e != NULL) ? atol(rv->e) : 0; ++} ++ ++const char *rpmverE(rpmver rv) ++{ ++ return (rv != NULL) ? rv->e : NULL; ++} ++ ++const char *rpmverV(rpmver rv) ++{ ++ return (rv != NULL) ? rv->v : NULL; ++} ++ ++const char *rpmverR(rpmver rv) ++{ ++ return (rv != NULL) ? rv->r : NULL; ++} ++ ++char *rpmverEVR(rpmver rv) ++{ ++ char *EVR = NULL; ++ if (rv) { ++ rstrscat(&EVR, rv->e ? rv-> e : "", rv->e ? ":" : "", ++ rv->v, ++ rv->r ? "-" : "", rv->r ? rv->r : "", NULL); ++ } ++ return EVR; ++} ++ ++rpmver rpmverParse(const char *evr) ++{ ++ rpmver rv = NULL; ++ if (evr && *evr) { ++ size_t evrlen = strlen(evr) + 1; ++ rv = xmalloc(sizeof(*rv) + evrlen); ++ memcpy(rv->arena, evr, evrlen); ++ parseEVR(rv->arena, &rv->e, &rv->v, &rv->r); ++ } ++ return rv; ++} ++ ++rpmver rpmverNew(const char *e, const char *v, const char *r) ++{ ++ rpmver rv = NULL; ++ ++ if (v && *v) { ++ size_t nb = strlen(v) + 1; ++ nb += (e != NULL) ? strlen(e) + 1 : 0; ++ nb += (r != NULL) ? strlen(r) + 1 : 0; ++ rv = xmalloc(sizeof(*rv) + nb); ++ ++ rv->e = NULL; ++ rv->v = NULL; ++ rv->r = NULL; ++ ++ char *p = rv->arena; ++ if (e) { ++ rv->e = p; ++ p = stpcpy(p, e); ++ p++; ++ } ++ ++ rv->v = p; ++ p = stpcpy(p, v); ++ p++; ++ ++ if (r) { ++ rv->r = p; ++ p = stpcpy(p, r); ++ p++; ++ } ++ } ++ return rv; ++} ++ ++rpmver rpmverFree(rpmver rv) ++{ ++ if (rv) { ++ free(rv); ++ } ++ return NULL; ++} ++#endif +diff --git a/src/lib/rpmver-private.h b/src/lib/rpmver-private.h +new file mode 100644 +index 0000000000..f875c2f9d3 +--- /dev/null ++++ b/src/lib/rpmver-private.h +@@ -0,0 +1,108 @@ ++// Temporary forked internal copy of ++// https://github.com/rpm-software-management/rpm/blob/rpm-4.16.1.3/rpmio/rpmver.h ++// SPDX-License-Identifier: LGPL-2.1-or-later ++ ++#ifndef _RPMVER_H ++#define _RPMVER_H ++ ++#include ++#include /* sense flags */ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++// NOTE(lucab): Backported from . ++#ifndef rpmver ++typedef struct rpmver_s * rpmver; ++#endif ++ ++/** \ingroup rpmver ++ * Segmented string compare for version or release strings. ++ * ++ * @param a 1st string ++ * @param b 2nd string ++ * @return +1 if a is "newer", 0 if equal, -1 if b is "newer" ++ */ ++int rpmvercmp(const char * a, const char * b); ++ ++/** \ingroup rpmver ++ * Parse rpm version handle from evr string ++ * ++ * @param evr [epoch:]version[-release] string ++ * @return rpm version, NULL on invalid evr ++ */ ++rpmver rpmverParse(const char *evr); ++ ++/** \ingroup rpmver ++ * Create new rpm version handle from e, v, r components ++ * ++ * @param e epoch (or NULL) ++ * @param v version ++ * @param r release (or NULL) ++ * @return rpm version, NULL on invalid ++ */ ++rpmver rpmverNew(const char *e, const char *v, const char *r); ++ ++/** \ingroup rpmver ++ * Free rpm version handle ++ * ++ * @param rv rpm version handle ++ * @return NULL always ++ */ ++rpmver rpmverFree(rpmver rv); ++ ++/** \ingroup rpmver ++ * @param rv rpm version handle ++ * @return numerical value of epoch ++ */ ++uint32_t rpmverEVal(rpmver rv); ++ ++/** \ingroup rpmver ++ * @param rv rpm version handle ++ * @return epoch portion ++ */ ++const char *rpmverE(rpmver rv); ++ ++/** \ingroup rpmver ++ * @param rv rpm version handle ++ * @return version portion ++ */ ++const char *rpmverV(rpmver rv); ++ ++/** \ingroup rpmver ++ * @param rv rpm version handle ++ * @return release portion ++ */ ++const char *rpmverR(rpmver rv); ++ ++/** \ingroup rpmver ++ * @param rv rpm version handle ++ * @return formatted [E:]V[-R] string (malloced) ++ */ ++char *rpmverEVR(rpmver rv); ++ ++/** \ingroup rpmver ++ * Compare two rpm version handles ++ * ++ * @param v1 1st version handle ++ * @param v2 2nd version handle ++ * @return 0 if equal, -1 if v1 smaller, 1 if greater, than v2 ++ */ ++int rpmverCmp(rpmver v1, rpmver v2); ++ ++/** \ingroup rpmver ++ * Determine whether two versioned ranges overlap. ++ * @param v1 1st version ++ * @param f1 1st sense flags ++ * @param v2 2nd version ++ * @param f2 2nd sense flags ++ * @return 1 if ranges overlap, 0 otherwise ++ */ ++int rpmverOverlap(rpmver v1, rpmsenseFlags f1, rpmver v2, rpmsenseFlags f2); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _RPMVER_H */ + +From a74a3163b2ae315b5f95d9d7642e868794c47628 Mon Sep 17 00:00:00 2001 +From: Luca BRUNO +Date: Mon, 31 May 2021 11:00:10 +0000 +Subject: [PATCH 2/6] lib/rpmver: replace tabs with spaces + +--- + src/lib/rpmver-private.c | 160 +++++++++++++++++++-------------------- + src/lib/rpmver-private.h | 60 +++++++-------- + 2 files changed, 110 insertions(+), 110 deletions(-) + +diff --git a/src/lib/rpmver-private.c b/src/lib/rpmver-private.c +index 117df79206..6882be0d1e 100644 +--- a/src/lib/rpmver-private.c ++++ b/src/lib/rpmver-private.c +@@ -25,40 +25,40 @@ struct rpmver_s { + + /** + * Split EVR into epoch, version, and release components. +- * @param evr [epoch:]version[-release] string +- * @retval *ep pointer to epoch +- * @retval *vp pointer to version +- * @retval *rp pointer to release ++ * @param evr [epoch:]version[-release] string ++ * @retval *ep pointer to epoch ++ * @retval *vp pointer to version ++ * @retval *rp pointer to release + */ + static + void parseEVR(char * evr, +- const char ** ep, +- const char ** vp, +- const char ** rp) ++ const char ** ep, ++ const char ** vp, ++ const char ** rp) + { + const char *epoch; +- const char *version; /* assume only version is present */ ++ const char *version; /* assume only version is present */ + const char *release; + char *s, *se; + + s = evr; +- while (*s && risdigit(*s)) s++; /* s points to epoch terminator */ +- se = strrchr(s, '-'); /* se points to version terminator */ ++ while (*s && risdigit(*s)) s++; /* s points to epoch terminator */ ++ se = strrchr(s, '-'); /* se points to version terminator */ + + if (*s == ':') { +- epoch = evr; +- *s++ = '\0'; +- version = s; +- if (*epoch == '\0') epoch = "0"; ++ epoch = evr; ++ *s++ = '\0'; ++ version = s; ++ if (*epoch == '\0') epoch = "0"; + } else { +- epoch = NULL; /* XXX disable epoch compare if missing */ +- version = evr; ++ epoch = NULL; /* XXX disable epoch compare if missing */ ++ version = evr; + } + if (se) { +- *se++ = '\0'; +- release = se; ++ *se++ = '\0'; ++ release = se; + } else { +- release = NULL; ++ release = NULL; + } + + if (ep) *ep = epoch; +@@ -73,38 +73,38 @@ int rpmverOverlap(rpmver v1, rpmsenseFlags f1, rpmver v2, rpmsenseFlags f2) + + /* Compare {A,B} [epoch:]version[-release] */ + if (v1->e && *v1->e && v2->e && *v2->e) +- sense = rpmvercmp(v1->e, v2->e); ++ sense = rpmvercmp(v1->e, v2->e); + else if (v1->e && *v1->e && atol(v1->e) > 0) { +- sense = 1; ++ sense = 1; + } else if (v2->e && *v2->e && atol(v2->e) > 0) +- sense = -1; ++ sense = -1; + + if (sense == 0) { +- sense = rpmvercmp(v1->v, v2->v); +- if (sense == 0) { +- if (v1->r && *v1->r && v2->r && *v2->r) { +- sense = rpmvercmp(v1->r, v2->r); +- } else { +- /* always matches if the side with no release has SENSE_EQUAL */ +- if ((v1->r && *v1->r && (f2 & RPMSENSE_EQUAL)) || +- (v2->r && *v2->r && (f1 & RPMSENSE_EQUAL))) { +- result = 1; +- goto exit; +- } +- } +- } ++ sense = rpmvercmp(v1->v, v2->v); ++ if (sense == 0) { ++ if (v1->r && *v1->r && v2->r && *v2->r) { ++ sense = rpmvercmp(v1->r, v2->r); ++ } else { ++ /* always matches if the side with no release has SENSE_EQUAL */ ++ if ((v1->r && *v1->r && (f2 & RPMSENSE_EQUAL)) || ++ (v2->r && *v2->r && (f1 & RPMSENSE_EQUAL))) { ++ result = 1; ++ goto exit; ++ } ++ } ++ } + } + + /* Detect overlap of {A,B} range. */ + if (sense < 0 && ((f1 & RPMSENSE_GREATER) || (f2 & RPMSENSE_LESS))) { +- result = 1; ++ result = 1; + } else if (sense > 0 && ((f1 & RPMSENSE_LESS) || (f2 & RPMSENSE_GREATER))) { +- result = 1; ++ result = 1; + } else if (sense == 0 && +- (((f1 & RPMSENSE_EQUAL) && (f2 & RPMSENSE_EQUAL)) || +- ((f1 & RPMSENSE_LESS) && (f2 & RPMSENSE_LESS)) || +- ((f1 & RPMSENSE_GREATER) && (f2 & RPMSENSE_GREATER)))) { +- result = 1; ++ (((f1 & RPMSENSE_EQUAL) && (f2 & RPMSENSE_EQUAL)) || ++ ((f1 & RPMSENSE_LESS) && (f2 & RPMSENSE_LESS)) || ++ ((f1 & RPMSENSE_GREATER) && (f2 & RPMSENSE_GREATER)))) { ++ result = 1; + } + + exit: +@@ -114,11 +114,11 @@ int rpmverOverlap(rpmver v1, rpmsenseFlags f1, rpmver v2, rpmsenseFlags f2) + static int compare_values(const char *str1, const char *str2) + { + if (!str1 && !str2) +- return 0; ++ return 0; + else if (str1 && !str2) +- return 1; ++ return 1; + else if (!str1 && str2) +- return -1; ++ return -1; + return rpmvercmp(str1, str2); + } + +@@ -129,9 +129,9 @@ int rpmverCmp(rpmver v1, rpmver v2) + + int rc = compare_values(e1, e2); + if (!rc) { +- rc = compare_values(v1->v, v2->v); +- if (!rc) +- rc = compare_values(v1->r, v2->r); ++ rc = compare_values(v1->v, v2->v); ++ if (!rc) ++ rc = compare_values(v1->r, v2->r); + } + return rc; + } +@@ -160,9 +160,9 @@ char *rpmverEVR(rpmver rv) + { + char *EVR = NULL; + if (rv) { +- rstrscat(&EVR, rv->e ? rv-> e : "", rv->e ? ":" : "", +- rv->v, +- rv->r ? "-" : "", rv->r ? rv->r : "", NULL); ++ rstrscat(&EVR, rv->e ? rv-> e : "", rv->e ? ":" : "", ++ rv->v, ++ rv->r ? "-" : "", rv->r ? rv->r : "", NULL); + } + return EVR; + } +@@ -171,10 +171,10 @@ rpmver rpmverParse(const char *evr) + { + rpmver rv = NULL; + if (evr && *evr) { +- size_t evrlen = strlen(evr) + 1; +- rv = xmalloc(sizeof(*rv) + evrlen); +- memcpy(rv->arena, evr, evrlen); +- parseEVR(rv->arena, &rv->e, &rv->v, &rv->r); ++ size_t evrlen = strlen(evr) + 1; ++ rv = xmalloc(sizeof(*rv) + evrlen); ++ memcpy(rv->arena, evr, evrlen); ++ parseEVR(rv->arena, &rv->e, &rv->v, &rv->r); + } + return rv; + } +@@ -184,31 +184,31 @@ rpmver rpmverNew(const char *e, const char *v, const char *r) + rpmver rv = NULL; + + if (v && *v) { +- size_t nb = strlen(v) + 1; +- nb += (e != NULL) ? strlen(e) + 1 : 0; +- nb += (r != NULL) ? strlen(r) + 1 : 0; +- rv = xmalloc(sizeof(*rv) + nb); +- +- rv->e = NULL; +- rv->v = NULL; +- rv->r = NULL; +- +- char *p = rv->arena; +- if (e) { +- rv->e = p; +- p = stpcpy(p, e); +- p++; +- } +- +- rv->v = p; +- p = stpcpy(p, v); +- p++; +- +- if (r) { +- rv->r = p; +- p = stpcpy(p, r); +- p++; +- } ++ size_t nb = strlen(v) + 1; ++ nb += (e != NULL) ? strlen(e) + 1 : 0; ++ nb += (r != NULL) ? strlen(r) + 1 : 0; ++ rv = xmalloc(sizeof(*rv) + nb); ++ ++ rv->e = NULL; ++ rv->v = NULL; ++ rv->r = NULL; ++ ++ char *p = rv->arena; ++ if (e) { ++ rv->e = p; ++ p = stpcpy(p, e); ++ p++; ++ } ++ ++ rv->v = p; ++ p = stpcpy(p, v); ++ p++; ++ ++ if (r) { ++ rv->r = p; ++ p = stpcpy(p, r); ++ p++; ++ } + } + return rv; + } +@@ -216,7 +216,7 @@ rpmver rpmverNew(const char *e, const char *v, const char *r) + rpmver rpmverFree(rpmver rv) + { + if (rv) { +- free(rv); ++ free(rv); + } + return NULL; + } +diff --git a/src/lib/rpmver-private.h b/src/lib/rpmver-private.h +index f875c2f9d3..458279e202 100644 +--- a/src/lib/rpmver-private.h ++++ b/src/lib/rpmver-private.h +@@ -6,7 +6,7 @@ + #define _RPMVER_H + + #include +-#include /* sense flags */ ++#include /* sense flags */ + + #ifdef __cplusplus + extern "C" { +@@ -20,84 +20,84 @@ typedef struct rpmver_s * rpmver; + /** \ingroup rpmver + * Segmented string compare for version or release strings. + * +- * @param a 1st string +- * @param b 2nd string +- * @return +1 if a is "newer", 0 if equal, -1 if b is "newer" ++ * @param a 1st string ++ * @param b 2nd string ++ * @return +1 if a is "newer", 0 if equal, -1 if b is "newer" + */ + int rpmvercmp(const char * a, const char * b); + + /** \ingroup rpmver + * Parse rpm version handle from evr string + * +- * @param evr [epoch:]version[-release] string +- * @return rpm version, NULL on invalid evr ++ * @param evr [epoch:]version[-release] string ++ * @return rpm version, NULL on invalid evr + */ + rpmver rpmverParse(const char *evr); + + /** \ingroup rpmver + * Create new rpm version handle from e, v, r components + * +- * @param e epoch (or NULL) +- * @param v version +- * @param r release (or NULL) +- * @return rpm version, NULL on invalid ++ * @param e epoch (or NULL) ++ * @param v version ++ * @param r release (or NULL) ++ * @return rpm version, NULL on invalid + */ + rpmver rpmverNew(const char *e, const char *v, const char *r); + + /** \ingroup rpmver + * Free rpm version handle + * +- * @param rv rpm version handle +- * @return NULL always ++ * @param rv rpm version handle ++ * @return NULL always + */ + rpmver rpmverFree(rpmver rv); + + /** \ingroup rpmver +- * @param rv rpm version handle +- * @return numerical value of epoch ++ * @param rv rpm version handle ++ * @return numerical value of epoch + */ + uint32_t rpmverEVal(rpmver rv); + + /** \ingroup rpmver +- * @param rv rpm version handle +- * @return epoch portion ++ * @param rv rpm version handle ++ * @return epoch portion + */ + const char *rpmverE(rpmver rv); + + /** \ingroup rpmver +- * @param rv rpm version handle +- * @return version portion ++ * @param rv rpm version handle ++ * @return version portion + */ + const char *rpmverV(rpmver rv); + + /** \ingroup rpmver +- * @param rv rpm version handle +- * @return release portion ++ * @param rv rpm version handle ++ * @return release portion + */ + const char *rpmverR(rpmver rv); + + /** \ingroup rpmver +- * @param rv rpm version handle +- * @return formatted [E:]V[-R] string (malloced) ++ * @param rv rpm version handle ++ * @return formatted [E:]V[-R] string (malloced) + */ + char *rpmverEVR(rpmver rv); + + /** \ingroup rpmver + * Compare two rpm version handles + * +- * @param v1 1st version handle +- * @param v2 2nd version handle +- * @return 0 if equal, -1 if v1 smaller, 1 if greater, than v2 ++ * @param v1 1st version handle ++ * @param v2 2nd version handle ++ * @return 0 if equal, -1 if v1 smaller, 1 if greater, than v2 + */ + int rpmverCmp(rpmver v1, rpmver v2); + + /** \ingroup rpmver + * Determine whether two versioned ranges overlap. +- * @param v1 1st version +- * @param f1 1st sense flags +- * @param v2 2nd version +- * @param f2 2nd sense flags +- * @return 1 if ranges overlap, 0 otherwise ++ * @param v1 1st version ++ * @param f1 1st sense flags ++ * @param v2 2nd version ++ * @param f2 2nd sense flags ++ * @return 1 if ranges overlap, 0 otherwise + */ + int rpmverOverlap(rpmver v1, rpmsenseFlags f1, rpmver v2, rpmsenseFlags f2); + diff --git a/SOURCES/0003-github-coreos-rpm-ostree-pr2870.patch b/SOURCES/0003-github-coreos-rpm-ostree-pr2870.patch new file mode 100644 index 0000000..c0f7f1c --- /dev/null +++ b/SOURCES/0003-github-coreos-rpm-ostree-pr2870.patch @@ -0,0 +1,29 @@ +From c497411e3bc24538a26bc249245ebcebe8fff337 Mon Sep 17 00:00:00 2001 +From: Luca BRUNO +Date: Wed, 2 Jun 2021 11:53:54 +0000 +Subject: [PATCH] makefile/lib: filter out private sources from gir list + +This excludes C source files too (instead of just headers) from the list of +source files scanned by gir. +It fixes the following error: +``` +src/lib/rpmver-private.c:27: Error: RpmOstree: identifier not found on the first line: + * Split EVR into epoch, version, and release components. +``` +--- + Makefile-lib.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile-lib.am b/Makefile-lib.am +index f9d67f5c5..cc4b4de61 100644 +--- a/Makefile-lib.am ++++ b/Makefile-lib.am +@@ -44,7 +44,7 @@ RpmOstree_1_0_gir_INCLUDES = OSTree-1.0 Gio-2.0 + RpmOstree_1_0_gir_CFLAGS = $(librpmostree_1_la_CFLAGS) + RpmOstree_1_0_gir_LIBS = librpmostree-1.la + RpmOstree_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=RpmOstree --symbol-prefix=rpm_ostree +-RpmOstree_1_0_gir_FILES = $(librpmostreeinclude_HEADERS) $(filter-out %-private.h,$(librpmostree_1_la_SOURCES)) ++RpmOstree_1_0_gir_FILES = $(librpmostreeinclude_HEADERS) $(filter-out %-private.c %-private.h,$(librpmostree_1_la_SOURCES)) + INTROSPECTION_GIRS += RpmOstree-1.0.gir + gir_DATA += RpmOstree-1.0.gir + typelib_DATA += RpmOstree-1.0.typelib diff --git a/SOURCES/0004-github-coreos-rpm-ostree-pr2872.patch b/SOURCES/0004-github-coreos-rpm-ostree-pr2872.patch new file mode 100644 index 0000000..4beefd5 --- /dev/null +++ b/SOURCES/0004-github-coreos-rpm-ostree-pr2872.patch @@ -0,0 +1,97 @@ +From eca59b67b3350d3b49db5844eb143b428c95ca37 Mon Sep 17 00:00:00 2001 +From: Luca BRUNO +Date: Wed, 2 Jun 2021 12:40:44 +0000 +Subject: [PATCH 1/2] libdnf-sys/build: gracefully handle older gpgme versions + +This tries to gracefully handle environments where gpgme +library cannot be directly discovered via pkg-config. +Older gpgme versions (including 1.13) do not provide a +.pc file, so in that case the build-script attempts to +fallback to hardcoded library flags. +--- + rust/libdnf-sys/Cargo.toml | 3 ++- + rust/libdnf-sys/build.rs | 5 +++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/rust/libdnf-sys/Cargo.toml b/rust/libdnf-sys/Cargo.toml +index 8695ad8c08..e20f04d0c8 100644 +--- a/rust/libdnf-sys/Cargo.toml ++++ b/rust/libdnf-sys/Cargo.toml +@@ -26,7 +26,8 @@ rpm = "4" + librepo = "1" + libsolv = "0.7" + libsolvext = "0.7" +-gpgme = "1" ++# Older libgpgme did not provide a pkg-config file ++gpgme = { version = "1", optional = true } + openssl = "1" + libcurl = "7" + sqlite3 = "3" +diff --git a/rust/libdnf-sys/build.rs b/rust/libdnf-sys/build.rs +index 43f61a3544..ec86ca6a6f 100644 +--- a/rust/libdnf-sys/build.rs ++++ b/rust/libdnf-sys/build.rs +@@ -3,6 +3,7 @@ use anyhow::Result; + + fn main() -> Result<()> { + let libs = system_deps::Config::new().probe()?; ++ let has_gpgme_pkgconfig = libs.get_by_name("gpgme").is_some(); + + // first, the submodule proper + let libdnf = cmake::Config::new("../../libdnf") +@@ -31,6 +32,10 @@ fn main() -> Result<()> { + .always_configure(false) + .build_target("all") + .build(); ++ // NOTE(lucab): consider using `gpgme-config` it this stops working. ++ if !has_gpgme_pkgconfig { ++ println!("cargo:rustc-link-lib=gpgme"); ++ } + println!( + "cargo:rustc-link-search=native={}/build/libdnf", + libdnf.display() + +From d874de293c27f2ed762f212ab65fb054a8006fc3 Mon Sep 17 00:00:00 2001 +From: Luca BRUNO +Date: Wed, 2 Jun 2021 13:10:24 +0000 +Subject: [PATCH 2/2] libdnf-sys/build: auto-enable zchunk if present + +This adds an optional dependencies on the `zck` library (zchunk), +and automatically forwards it to libdnf configuration. +It allows to gracefully degrade in older environments where zchunk +is not present, and also matches autoconf behavior. +--- + rust/libdnf-sys/Cargo.toml | 1 + + rust/libdnf-sys/build.rs | 3 +++ + 2 files changed, 4 insertions(+) + +diff --git a/rust/libdnf-sys/Cargo.toml b/rust/libdnf-sys/Cargo.toml +index e20f04d0c8..13e0eca318 100644 +--- a/rust/libdnf-sys/Cargo.toml ++++ b/rust/libdnf-sys/Cargo.toml +@@ -34,3 +34,4 @@ sqlite3 = "3" + modulemd = { name = "modulemd-2.0", version = "2" } + jsonc = { name = "json-c", version = "0" } + glib = { name = "glib-2.0", version = "2" } ++zck = { version = "0.9", optional = true } +diff --git a/rust/libdnf-sys/build.rs b/rust/libdnf-sys/build.rs +index ec86ca6a6f..df07cc7cb7 100644 +--- a/rust/libdnf-sys/build.rs ++++ b/rust/libdnf-sys/build.rs +@@ -4,6 +4,7 @@ use anyhow::Result; + fn main() -> Result<()> { + let libs = system_deps::Config::new().probe()?; + let has_gpgme_pkgconfig = libs.get_by_name("gpgme").is_some(); ++ let with_zck: u8 = libs.get_by_name("zck").is_some().into(); + + // first, the submodule proper + let libdnf = cmake::Config::new("../../libdnf") +@@ -24,6 +25,8 @@ fn main() -> Result<()> { + // We don't need docs + .define("WITH_HTML:BOOL", "0") + .define("WITH_MAN:BOOL", "0") ++ // Auto-enable zchunk, if present ++ .define("WITH_ZCHUNK:BOOL", format!("{}", with_zck)) + // Don't need bindings + .define("WITH_BINDINGS:BOOL", "0") + // Needed in Koji at least because timestamps(?) diff --git a/SOURCES/0005-github-rpm-libdnf-pr1274.patch b/SOURCES/0005-github-rpm-libdnf-pr1274.patch new file mode 100644 index 0000000..9f75bf6 --- /dev/null +++ b/SOURCES/0005-github-rpm-libdnf-pr1274.patch @@ -0,0 +1,38 @@ +From 27a8e7be662b9fca6badc8925d5991d5d7abfcfc Mon Sep 17 00:00:00 2001 +From: Jonathan Lebon +Date: Wed, 16 Jun 2021 09:11:43 -0400 +Subject: [PATCH] os-release.cpp: make initLibRpm call dnf_context_globals_init + +We shouldn't have our separate static var here. Otherwise clients will +incur `rpmReadConfigFiles` twice which breaks their ability to +consistently override macros. + +Reported-by: Luca Bruno +Reported-by: Christian Kellner + +Fixes: #1273 +--- + libdnf/utils/os-release.cpp | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/libdnf/libdnf/utils/os-release.cpp b/libdnf/libdnf/utils/os-release.cpp +index 1d8a95be65..e2f3d06dd0 100644 +--- a/libdnf/libdnf/utils/os-release.cpp ++++ b/libdnf/libdnf/utils/os-release.cpp +@@ -80,12 +80,10 @@ std::map getOsReleaseData() + + static void initLibRpm() + { +- static bool libRpmInitiated{false}; +- if (libRpmInitiated) return; +- if (rpmReadConfigFiles(NULL, NULL) != 0) { +- throw std::runtime_error("failed to read rpm config files\n"); +- } +- libRpmInitiated = true; ++ // call dnf_context_globals_init to ensure this only happens once ++ g_autoptr(GError) local_error = NULL; ++ if (!dnf_context_globals_init(&local_error)) ++ throw std::runtime_error(local_error->message); + } + + static std::string getBaseArch() diff --git a/SOURCES/0006-github-coreos-rpm-ostree-pr2897.patch b/SOURCES/0006-github-coreos-rpm-ostree-pr2897.patch new file mode 100644 index 0000000..e902c1a --- /dev/null +++ b/SOURCES/0006-github-coreos-rpm-ostree-pr2897.patch @@ -0,0 +1,212 @@ +From 8c533c5aab948fff3ebef12a6d965c9303302c35 Mon Sep 17 00:00:00 2001 +From: Luca BRUNO +Date: Thu, 17 Jun 2021 08:30:00 +0000 +Subject: [PATCH 1/3] builtin/tree: inject _dbpath macro file in postprocessing + step + +This wires the _dbpath macro injection logic to `compose postprocess`, +in order to make sure that the rpm configuration in the commit +matches the location of the rpmdb database. +--- + rust/src/composepost.rs | 12 +++++++++--- + rust/src/lib.rs | 1 + + src/libpriv/rpmostree-postprocess.cxx | 3 +++ + 3 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/rust/src/composepost.rs b/rust/src/composepost.rs +index c63ca8fa5..4e000a97e 100644 +--- a/rust/src/composepost.rs ++++ b/rust/src/composepost.rs +@@ -172,9 +172,15 @@ fn postprocess_presets(rootfs_dfd: &openat::Dir) -> Result<()> { + Ok(()) + } + +-// We keep hitting issues with the ostree-remount preset not being +-// enabled; let's just do this rather than trying to propagate the +-// preset everywhere. ++/// Write an RPM macro file to ensure the rpmdb path is set on the client side. ++pub fn compose_postprocess_rpm_macro(rootfs_dfd: i32) -> CxxResult<()> { ++ let rootfs = &crate::ffiutil::ffi_view_openat_dir(rootfs_dfd); ++ postprocess_rpm_macro(rootfs)?; ++ Ok(()) ++} ++ ++/// Ensure our own `_dbpath` macro exists in the tree. ++#[context("Writing _dbpath RPM macro")] + fn postprocess_rpm_macro(rootfs_dfd: &openat::Dir) -> Result<()> { + let rpm_macros_dir = "usr/lib/rpm/macros.d"; + rootfs_dfd.ensure_dir_all(rpm_macros_dir, 0o755)?; +diff --git a/rust/src/lib.rs b/rust/src/lib.rs +index 4c328fe4c..658a7fa95 100644 +--- a/rust/src/lib.rs ++++ b/rust/src/lib.rs +@@ -160,6 +160,7 @@ pub mod ffi { + rootfs_dfd: i32, + cancellable: Pin<&mut GCancellable>, + ) -> Result<()>; ++ fn compose_postprocess_rpm_macro(rootfs_dfd: i32) -> Result<()>; + } + + // A grab-bag of metadata from the deployment's ostree commit +diff --git a/src/libpriv/rpmostree-postprocess.cxx b/src/libpriv/rpmostree-postprocess.cxx +index 42aa0b569..781c3a15c 100644 +--- a/src/libpriv/rpmostree-postprocess.cxx ++++ b/src/libpriv/rpmostree-postprocess.cxx +@@ -649,6 +649,9 @@ rpmostree_rootfs_postprocess_common (int rootfs_fd, + } + } + ++ /* Make sure there is an RPM macro in place pointing to the rpmdb in /usr */ ++ rpmostreecxx::compose_postprocess_rpm_macro(rootfs_fd); ++ + if (!rpmostree_cleanup_leftover_rpmdb_files (rootfs_fd, cancellable, error)) + return FALSE; + + +From ac7c64428594726a5420b1c11d7b6d6a48ffc0a8 Mon Sep 17 00:00:00 2001 +From: Luca BRUNO +Date: Sun, 13 Jun 2021 13:50:39 +0000 +Subject: [PATCH 2/3] libpriv/core: set _dbpath macro in dnf context + +This ensures that the `_dbpath` macro is always in all dnf contexts, +in order to use the rpmdb under /usr. +Setting it explicitly makes sure that there is no logic implicitly +relying on host configuration. This is particularly relevant in +server-side compose cases, which are more likely to be running in +an environment without rpm-ostree macro file. +--- + src/libpriv/rpmostree-core.cxx | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/libpriv/rpmostree-core.cxx b/src/libpriv/rpmostree-core.cxx +index 12381e20e..ab0e0ef54 100644 +--- a/src/libpriv/rpmostree-core.cxx ++++ b/src/libpriv/rpmostree-core.cxx +@@ -379,6 +379,9 @@ rpmostree_context_new_client (OstreeRepo *repo) + dnf_context_set_zchunk (self->dnfctx, FALSE); + #endif + ++ /* The rpmdb is at /usr/share/rpm */ ++ dnf_context_set_rpm_macro (self->dnfctx, "_dbpath", "/" RPMOSTREE_RPMDB_LOCATION); ++ + return self; + } + + +From bfdebee9f8b0bf7c4488bcfe723b12faed784da8 Mon Sep 17 00:00:00 2001 +From: Colin Walters +Date: Fri, 11 Jun 2021 15:33:30 +0000 +Subject: [PATCH 3/3] builtin/tree: explicitly set _dbpath macro in global + libdnf initialization + +This ensures that the `_dbpath` macro is always in all dnf contexts, +in order to use the rpmdb under /usr. +Setting it explicitly makes sure that there is no logic implicitly +relying on host configuration. This is particularly relevant in +server-side compose cases, which are more likely to be running in +an environment without rpm-ostree macro file. +--- + src/app/rpmostree-compose-builtin-tree.cxx | 2 ++ + src/libpriv/rpmostree-core.cxx | 32 +++++++++++++++++++--- + src/libpriv/rpmostree-core.h | 4 +++ + src/libpriv/rpmostree-rpm-util.cxx | 2 ++ + 4 files changed, 36 insertions(+), 4 deletions(-) + +diff --git a/src/app/rpmostree-compose-builtin-tree.cxx b/src/app/rpmostree-compose-builtin-tree.cxx +index 4d88ee95f..d6eef2c44 100644 +--- a/src/app/rpmostree-compose-builtin-tree.cxx ++++ b/src/app/rpmostree-compose-builtin-tree.cxx +@@ -574,6 +574,8 @@ rpm_ostree_compose_context_new (const char *treefile_pathstr, + { + g_autoptr(RpmOstreeTreeComposeContext) self = g_new0 (RpmOstreeTreeComposeContext, 1); + ++ rpmostreecxx::core_libdnf_process_global_init(); ++ + /* Init fds to -1 */ + self->workdir_dfd = self->rootfs_dfd = self->cachedir_dfd = -1; + /* Test whether or not bwrap is going to work - we will fail inside e.g. a Docker +diff --git a/src/libpriv/rpmostree-core.cxx b/src/libpriv/rpmostree-core.cxx +index ab0e0ef54..e142ccd76 100644 +--- a/src/libpriv/rpmostree-core.cxx ++++ b/src/libpriv/rpmostree-core.cxx +@@ -653,6 +653,32 @@ rpmostree_context_set_treespec (RpmOstreeContext *self, RpmOstreeTreespec *trees + self->spec = (RpmOstreeTreespec*)g_object_ref (treespec); + } + ++namespace rpmostreecxx { ++// Sadly, like most of librpm, macros are a process-global state. ++// For rpm-ostree, the dbpath must be overriden. ++void ++core_libdnf_process_global_init() ++{ ++ static gsize initialized = 0; ++ ++ if (g_once_init_enter (&initialized)) ++ { ++ g_autoptr(GError) error = NULL; ++ /* Fatally error out if this fails */ ++ if (!dnf_context_globals_init (&error)) ++ g_error ("%s", error->message); ++ ++ /* This is what we use as default. Note we should be able to drop this in the ++ * future on the *client side* now that we inject a macro to set that value in our OSTrees. ++ */ ++ free (rpmExpand ("%define _dbpath /" RPMOSTREE_RPMDB_LOCATION, NULL)); ++ ++ g_once_init_leave (&initialized, 1); ++ } ++} ++ ++} /* namespace */ ++ + /* Wraps `dnf_context_setup()`, and initializes state based on the treespec + * @spec. Another way to say it is we pair `DnfContext` with an + * `RpmOstreeTreespec`. For example, we handle "instlangs", set the rpmdb root +@@ -674,6 +700,8 @@ rpmostree_context_setup (RpmOstreeContext *self, + /* This exists (as a canonically empty dir) at least on RHEL7+ */ + static const char emptydir_path[] = "/usr/share/empty"; + ++ rpmostreecxx::core_libdnf_process_global_init(); ++ + /* Auto-synthesize a spec for now; this will be removed */ + if (!self->spec) + rpmostree_context_set_treespec (self, NULL); +@@ -710,10 +738,6 @@ rpmostree_context_setup (RpmOstreeContext *self, + dnf_context_set_rpm_macro (self->dnfctx, "_install_langs", instlangs.c_str()); + } + +- /* This is what we use as default. Note we should be able to drop this in the +- * future now that we inject a macro to set that value in our OSTrees. */ +- dnf_context_set_rpm_macro (self->dnfctx, "_dbpath", "/" RPMOSTREE_RPMDB_LOCATION); +- + /* Set the database backend only in the compose path. It then becomes the default + * for any client side layering. + */ +diff --git a/src/libpriv/rpmostree-core.h b/src/libpriv/rpmostree-core.h +index 1db1014cd..cea97028e 100644 +--- a/src/libpriv/rpmostree-core.h ++++ b/src/libpriv/rpmostree-core.h +@@ -78,6 +78,10 @@ char* rpmostree_refspec_to_string (RpmOstreeRefspecType reftype, + char* rpmostree_refspec_canonicalize (const char *orig_refspec, + GError **error); + ++namespace rpmostreecxx { ++void core_libdnf_process_global_init(); ++} ++ + RpmOstreeContext *rpmostree_context_new_client (OstreeRepo *repo); + + RpmOstreeContext *rpmostree_context_new_compose (int basedir_dfd, +diff --git a/src/libpriv/rpmostree-rpm-util.cxx b/src/libpriv/rpmostree-rpm-util.cxx +index 57bdda4ed..19640b864 100644 +--- a/src/libpriv/rpmostree-rpm-util.cxx ++++ b/src/libpriv/rpmostree-rpm-util.cxx +@@ -851,6 +851,8 @@ get_sack_for_root (int dfd, + GLNX_AUTO_PREFIX_ERROR ("Loading sack", error); + g_assert (out_sack != NULL); + ++ rpmostreecxx::core_libdnf_process_global_init(); ++ + g_autofree char *fullpath = glnx_fdrel_abspath (dfd, path); + + g_autoptr(DnfSack) sack = dnf_sack_new (); diff --git a/SOURCES/0007-adjust-prebuilt-bindings.patch b/SOURCES/0007-adjust-prebuilt-bindings.patch new file mode 100644 index 0000000..ce1f6d2 --- /dev/null +++ b/SOURCES/0007-adjust-prebuilt-bindings.patch @@ -0,0 +1,42 @@ +diff --git a/rpmostree-cxxrs-prebuilt.cxx b/rpmostree-cxxrs-prebuilt.cxx +index 46985b6f..e73f5d1c 100644 +--- a/rpmostree-cxxrs-prebuilt.cxx ++++ b/rpmostree-cxxrs-prebuilt.cxx +@@ -1457,6 +1457,8 @@ void rpmostreecxx$cxxbridge1$cliwrap_destdir(::rust::String *return$) noexcept; + + ::rust::repr::PtrLen rpmostreecxx$cxxbridge1$prepare_rpmdb_base_location(::std::int32_t rootfs_dfd, ::rpmostreecxx::GCancellable &cancellable) noexcept; + ++::rust::repr::PtrLen rpmostreecxx$cxxbridge1$compose_postprocess_rpm_macro(::std::int32_t rootfs_dfd) noexcept; ++ + void rpmostreecxx$cxxbridge1$deployment_generate_id(::rpmostreecxx::OstreeDeployment &deployment, ::rust::String *return$) noexcept; + + ::rust::repr::PtrLen rpmostreecxx$cxxbridge1$deployment_populate_variant(::rpmostreecxx::OstreeSysroot &sysroot, ::rpmostreecxx::OstreeDeployment &deployment, ::rpmostreecxx::GVariantDict &dict) noexcept; +@@ -2079,6 +2081,13 @@ void prepare_rpmdb_base_location(::std::int32_t rootfs_dfd, ::rpmostreecxx::GCan + } + } + ++void compose_postprocess_rpm_macro(::std::int32_t rootfs_dfd) { ++ ::rust::repr::PtrLen error$ = rpmostreecxx$cxxbridge1$compose_postprocess_rpm_macro(rootfs_dfd); ++ if (error$.ptr) { ++ throw ::rust::impl<::rust::Error>::error(error$); ++ } ++} ++ + ::rust::String deployment_generate_id(::rpmostreecxx::OstreeDeployment &deployment) noexcept { + ::rust::MaybeUninit<::rust::String> return$; + rpmostreecxx$cxxbridge1$deployment_generate_id(deployment, &return$.value); +diff --git a/rpmostree-cxxrs-prebuilt.h b/rpmostree-cxxrs-prebuilt.h +index 631ea2b9..9428089b 100644 +--- a/rpmostree-cxxrs-prebuilt.h ++++ b/rpmostree-cxxrs-prebuilt.h +@@ -1249,6 +1249,8 @@ void workaround_selinux_cross_labeling(::std::int32_t rootfs_dfd, ::rpmostreecxx + + void prepare_rpmdb_base_location(::std::int32_t rootfs_dfd, ::rpmostreecxx::GCancellable &cancellable); + ++void compose_postprocess_rpm_macro(::std::int32_t rootfs_dfd); ++ + ::rust::String deployment_generate_id(::rpmostreecxx::OstreeDeployment &deployment) noexcept; + + void deployment_populate_variant(::rpmostreecxx::OstreeSysroot &sysroot, ::rpmostreecxx::OstreeDeployment &deployment, ::rpmostreecxx::GVariantDict &dict); + + diff --git a/SPECS/rpm-ostree.spec b/SPECS/rpm-ostree.spec index 47be5eb..2e72488 100644 --- a/SPECS/rpm-ostree.spec +++ b/SPECS/rpm-ostree.spec @@ -1,30 +1,49 @@ # The canonical copy of this spec file is upstream at: -# https://github.com/projectatomic/rpm-ostree/blob/master/packaging/rpm-ostree.spec.in +# https://github.com/coreos/rpm-ostree/blob/main/packaging/rpm-ostree.spec.in Summary: Hybrid image/package system Name: rpm-ostree -Version: 2020.7 -Release: 3%{?dist} -#VCS: https://github.com/cgwalters/rpm-ostree -# This tarball is generated via "cd packaging && make -f Makefile.dist-packaging dist-snapshot" -# in the upstream git. If rust is enabled, it contains vendored sources. -Source0: rpm-ostree-%{version}.tar.xz +Version: 2021.5 +Release: 2%{?dist} License: LGPLv2+ -URL: https://github.com/projectatomic/rpm-ostree +URL: https://github.com/coreos/rpm-ostree +# This tarball is generated via "cd packaging && make -f Makefile.dist-packaging dist-snapshot" +# in the upstream git. It also contains vendored Rust sources. +Source0: https://github.com/coreos/rpm-ostree/releases/download/v%{version}/rpm-ostree-%{version}.tar.xz -%if !%{defined rust_arches} -# It's not defined yet in the base CentOS7 root -%define rust_arches x86_64 i686 armv7hl aarch64 ppc64 ppc64le s390x -%endif # defined rust_arches +Patch01: 0001-github-jmesmon-rust-systemd-pr200.patch +Patch02: 0002-github-coreos-rpm-ostree-pr2869.patch +Patch03: 0003-github-coreos-rpm-ostree-pr2870.patch +Patch04: 0004-github-coreos-rpm-ostree-pr2872.patch +Patch05: 0005-github-rpm-libdnf-pr1274.patch +Patch06: 0006-github-coreos-rpm-ostree-pr2897.patch +Patch07: 0007-adjust-prebuilt-bindings.patch ExclusiveArch: %{rust_arches} -%if 0%{?fedora} +BuildRequires: make +%if 0%{?rhel} && !0%{?eln} +BuildRequires: rust-toolset +%else +BuildRequires: rust-packaging BuildRequires: cargo BuildRequires: rust +%endif + +# Enable ASAN + UBSAN +%bcond_with sanitizers + +# RHEL8 doesn't ship zchunk today. See also the comments +# in configure.ac around this as libdnf/librepo need to be in +# sync, and today we bundle libdnf but not librepo. +%if 0%{?rhel} && 0%{?rhel} <= 8 +%bcond_with zchunk %else -# assume el8 -BuildRequires: rust-toolset +%bcond_without zchunk +%endif + +%if 0%{?fedora} >= 34 +%define sqlite_rpmdb_default "--enable-sqlite-rpmdb-default" %endif # For the autofiles bits below @@ -34,54 +53,60 @@ BuildRequires: autoconf automake libtool git # For docs BuildRequires: chrpath BuildRequires: gtk-doc -BuildRequires: gperf BuildRequires: gnome-common BuildRequires: /usr/bin/g-ir-scanner # Core requirements # One way to check this: `objdump -p /path/to/rpm-ostree | grep LIBOSTREE` and pick the highest (though that might miss e.g. new struct members) -BuildRequires: pkgconfig(ostree-1) >= 2019.2 +BuildRequires: pkgconfig(ostree-1) >= 2020.7 BuildRequires: pkgconfig(polkit-gobject-1) BuildRequires: pkgconfig(json-glib-1.0) -BuildRequires: pkgconfig(rpm) +BuildRequires: pkgconfig(rpm) >= 4.14.0 BuildRequires: pkgconfig(libarchive) BuildRequires: pkgconfig(libsystemd) BuildRequires: libcap-devel BuildRequires: libattr-devel -# We currently interact directly with librepo +# We currently interact directly with librepo (libdnf below also pulls it in, +# but duplicating to be clear) BuildRequires: pkgconfig(librepo) # Needed by curl-rust BuildRequires: pkgconfig(libcurl) -# libdnf bundling -# We're using RPATH to pick up our bundled version -%global __requires_exclude ^libdnf[.]so[.].*$ - -# Our bundled libdnf.so.2 is for us only -%global __provides_exclude_from ^%{_libdir}/%{name}/.*$ - BuildRequires: cmake BuildRequires: pkgconfig(expat) BuildRequires: pkgconfig(check) + +# We use some libsolv types directly too (libdnf below also pulls it in, +# but duplicating to be clear) BuildRequires: pkgconfig(libsolv) # We need g++ for libdnf BuildRequires: gcc-c++ -# more libdnf build deps (see libdnf's spec for versions) +# more libdnf build deps (see libdnf's spec for versions; maintain ordering) +%global libsolv_version 0.7.17 +%global libmodulemd_version 2.11.2-2 +%global librepo_version 1.13.0 %global swig_version 3.0.12 -%global libmodulemd_version 2.5.0 BuildRequires: swig >= %{swig_version} BuildRequires: pkgconfig(modulemd-2.0) >= %{libmodulemd_version} +BuildRequires: pkgconfig(librepo) >= %{librepo_version} +BuildRequires: libsolv-devel >= %{libsolv_version} BuildRequires: pkgconfig(json-c) BuildRequires: pkgconfig(cppunit) BuildRequires: pkgconfig(sqlite3) BuildRequires: pkgconfig(smartcols) +%if %{with zchunk} +BuildRequires: pkgconfig(zck) >= 0.9.11 +%endif BuildRequires: gpgme-devel +# Runtime libdnf deps Requires: libmodulemd%{?_isa} >= %{libmodulemd_version} +Requires: libsolv%{?_isa} >= %{libsolv_version} +Requires: librepo%{?_isa} >= %{librepo_version} # For now...see https://github.com/projectatomic/rpm-ostree/pull/637 # and https://github.com/fedora-infra/fedmsg-atomic-composer/pull/17 @@ -119,11 +144,18 @@ The %{name}-devel package includes the header files for %{name}-libs. %build env NOCONFIGURE=1 ./autogen.sh -%configure --disable-silent-rules --enable-gtk-doc -make %{?_smp_mflags} +# Since we're hybrid C++/Rust we need to propagate this manually; +# the %%configure macro today assumes (reasonably) that one is building +# C/C++ and sets C{,XX}FLAGS +%if 0%{?build_rustflags:1} +export RUSTFLAGS="%{build_rustflags}" +%endif +%configure --disable-silent-rules --enable-gtk-doc %{?sqlite_rpmdb_default} %{?with_sanitizers:--enable-sanitizers} + +%make_build %install -make install DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p -c" +%make_install INSTALL="install -p -c" find $RPM_BUILD_ROOT -name '*.la' -delete # I try to do continuous delivery via rpmdistro-gitoverlay while @@ -184,9 +216,19 @@ $PYTHON autofiles.py > files.devel \ %files devel -f files.devel %changelog -* Wed Feb 24 2021 Jonathan Lebon - 2020.7-3 -- Respin to restore order in the world (of RPM versions) - Resolves: #1894061 +* Fri Jun 18 2021 Luca BRUNO - 2021.5-2 +- Backport _dbpath fixes, see + https://github.com/coreos/rpm-ostree/issues/2904 + Resolves: rhbz#1973579 + +* Wed May 12 2021 Luca BRUNO - 2021.5-1 +- New upstream version + https://github.com/coreos/rpm-ostree/releases/tag/v2021.5 + Resolves: rhbz#1959874 + +* Tue Mar 30 2021 Colin Walters - 2020.7-4 +- Backport https://github.com/coreos/rpm-ostree/pull/2386/commits/aa8e49aaeddfc5d38651fa08f46e059655818fd1 + Resolves: #1944760 * Thu Nov 05 2020 Colin Walters - 2020.7-2 - Update to 2020.7