From 7b1d935ade4179b77b20da853867ba45057a02da Mon Sep 17 00:00:00 2001 From: chantra Date: Mar 29 2022 16:32:13 +0000 Subject: clear execstack, don't require --nodigest for rpm -i, and bump version --- diff --git a/SOURCES/cow...cow_signvalidation.diff b/SOURCES/cow...cow_signvalidation.diff index 3ca1c8e..7408370 100644 --- a/SOURCES/cow...cow_signvalidation.diff +++ b/SOURCES/cow...cow_signvalidation.diff @@ -163,7 +163,7 @@ index feda3750c..6972602e0 100644 Fclose(payload); free(tid); diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c -index 40a3ab83f..dc1726a18 100644 +index 40a3ab83f..7f856154e 100644 --- a/lib/rpmchecksig.c +++ b/lib/rpmchecksig.c @@ -20,6 +20,7 @@ @@ -174,125 +174,117 @@ index 40a3ab83f..dc1726a18 100644 #include "lib/rpmvs.h" #include "debug.h" -@@ -220,6 +221,71 @@ rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd, - return rc; +@@ -221,36 +222,24 @@ rpmRC rpmpkgRead(struct rpmvs_s *vs, FD_t fd, } -+static int rpmpkgVerifySigsTranscoded(FD_t fd){ -+ rpm_loff_t current; -+ uint64_t magic; -+ rpm_loff_t offset; -+ int32_t rc; -+ size_t len; -+ uint64_t content_len; -+ char *content = NULL; -+ -+ current = Ftell(fd); -+ -+ if(Fseek(fd, -(sizeof(magic) + 3 * sizeof(offset) ), SEEK_END) < 0) { -+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: failed to seek for offset\n")); -+ rc = -1; -+ goto exit; -+ } -+ -+ len = sizeof(offset); -+ if (Fread(&offset, len, 1, fd) != len) { -+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read Signature Verification offset\n")); -+ rc = -1; -+ goto exit; -+ } -+ -+ if(Fseek(fd, offset, SEEK_SET) < 0) { -+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to seek signature verification offset\n")); -+ rc = -1; -+ goto exit; -+ } -+ len = sizeof(rc); -+ if (Fread(&rc, len, 1, fd) != len) { -+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read Signature Verification RC\n")); -+ rc = -1; -+ goto exit; -+ } -+ -+ len = sizeof(content_len); -+ if (Fread(&content_len, len, 1, fd) != len) { -+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read signature content length\n")); -+ goto exit; -+ } -+ -+ content = malloc(content_len + 1); -+ if(content == NULL) { -+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to allocate memory to read signature content\n")); -+ goto exit; -+ } -+ content[content_len] = 0; -+ if (Fread(content, content_len, 1, fd) != content_len) { -+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: Failed to read signature content\n")); -+ goto exit; -+ } -+ -+ rpmlog(RPMLOG_NOTICE, "%s", content); -+exit: -+ if(content){ -+ free(content); -+ } -+ if (Fseek(fd, current, SEEK_SET) < 0) { -+ rpmlog(RPMLOG_ERR, _("rpmpkgVerifySigsTranscoded: unable to seek back to original location\n")); -+ } -+ return rc; -+ -+} -+ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, - FD_t fd, const char *fn) +- FD_t fd, const char *fn) ++ FD_t fd, rpmsinfoCb cb, void *cbdata) { -@@ -229,10 +295,14 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, - .verbose = rpmIsVerbose(), - }; + char *msg = NULL; +- struct vfydata_s vd = { .seen = 0, +- .bad = 0, +- .verbose = rpmIsVerbose(), +- }; int rc; - struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring); - rpmlog(RPMLOG_NOTICE, "%s:%s", fn, vd.verbose ? "\n" : ""); - +- rpmlog(RPMLOG_NOTICE, "%s:%s", fn, vd.verbose ? "\n" : ""); ++ + if(isTranscodedRpm(fd) == RPMRC_OK){ -+ return rpmpkgVerifySigsTranscoded(fd); ++ return extentsVerifySigs(fd, 1); + } -+ struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring); + ++ struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring); + rc = rpmpkgRead(vs, fd, NULL, NULL, &msg); if (rc) -@@ -260,6 +330,29 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, + goto exit; + +- rc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, vfyCb, &vd); +- +- if (!vd.verbose) { +- if (vd.seen & RPMSIG_DIGEST_TYPE) { +- rpmlog(RPMLOG_NOTICE, " %s", (vd.bad & RPMSIG_DIGEST_TYPE) ? +- _("DIGESTS") : _("digests")); +- } +- if (vd.seen & RPMSIG_SIGNATURE_TYPE) { +- rpmlog(RPMLOG_NOTICE, " %s", (vd.bad & RPMSIG_SIGNATURE_TYPE) ? +- _("SIGNATURES") : _("signatures")); +- } +- rpmlog(RPMLOG_NOTICE, " %s\n", rc ? _("NOT OK") : _("OK")); +- } ++ rc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, cb, cbdata); + + exit: + if (rc && msg) +@@ -260,15 +249,39 @@ static int rpmpkgVerifySigs(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, return rc; } -+static int rpmpkgVerifySigsFD(rpmKeyring keyring, int vfylevel, rpmVSFlags flags, -+ FD_t fd, rpmsinfoCb cb, void *cbdata) -+{ -+ char *msg = NULL; -+ int rc; -+ struct rpmvs_s *vs = rpmvsCreate(vfylevel, flags, keyring); -+ -+ rc = rpmpkgRead(vs, fd, NULL, NULL, &msg); -+ -+ if (rc) -+ goto exit; -+ -+ rc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, cb, cbdata); -+ -+exit: -+ if (rc && msg) -+ rpmlog(RPMLOG_ERR, "%s\n", msg); -+ rpmvsFree(vs); -+ free(msg); -+ return rc; ++static void rpmkgVerifySigsPreLogging(struct vfydata_s *vd, const char *fn){ ++ rpmlog(RPMLOG_NOTICE, "%s:%s", fn, vd->verbose ? "\n" : ""); +} + ++static void rpmkgVerifySigsPostLogging(struct vfydata_s *vd, int rc){ ++ if (!vd->verbose) { ++ if (vd->seen & RPMSIG_DIGEST_TYPE) { ++ rpmlog(RPMLOG_NOTICE, " %s", (vd->bad & RPMSIG_DIGEST_TYPE) ? ++ _("DIGESTS") : _("digests")); ++ } ++ if (vd->seen & RPMSIG_SIGNATURE_TYPE) { ++ rpmlog(RPMLOG_NOTICE, " %s", (vd->bad & RPMSIG_SIGNATURE_TYPE) ? ++ _("SIGNATURES") : _("signatures")); ++ } ++ rpmlog(RPMLOG_NOTICE, " %s\n", rc ? _("NOT OK") : _("OK")); ++ } ++} + /* Wrapper around rpmkVerifySigs to preserve API */ int rpmVerifySignatures(QVA_t qva, rpmts ts, FD_t fd, const char * fn) { -@@ -304,3 +397,53 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv) + int rc = 1; /* assume failure */ ++ struct vfydata_s vd = { .seen = 0, ++ .bad = 0, ++ .verbose = rpmIsVerbose(), ++ }; + if (ts && qva && fd && fn) { + rpmKeyring keyring = rpmtsGetKeyring(ts, 1); + rpmVSFlags vsflags = rpmtsVfyFlags(ts); + int vfylevel = rpmtsVfyLevel(ts); +- rc = rpmpkgVerifySigs(keyring, vfylevel, vsflags, fd, fn); ++ rpmkgVerifySigsPreLogging(&vd, fn); ++ rc = rpmpkgVerifySigs(keyring, vfylevel, vsflags, fd, vfyCb, &vd); ++ rpmkgVerifySigsPostLogging(&vd, rc); + rpmKeyringFree(keyring); + } + return rc; +@@ -290,12 +303,22 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv) + + while ((arg = *argv++) != NULL) { + FD_t fd = Fopen(arg, "r.ufdio"); ++ struct vfydata_s vd = { .seen = 0, ++ .bad = 0, ++ .verbose = rpmIsVerbose(), ++ }; + if (fd == NULL || Ferror(fd)) { + rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n"), + arg, Fstrerror(fd)); + res++; +- } else if (rpmpkgVerifySigs(keyring, vfylevel, vsflags, fd, arg)) { ++ } else { ++ rpmkgVerifySigsPreLogging(&vd, arg); ++ int rc = rpmpkgVerifySigs(keyring, vfylevel, vsflags, fd, ++ vfyCb, &vd); ++ rpmkgVerifySigsPostLogging(&vd, rc); ++ if (rc) { + res++; ++ } + } + + Fclose(fd); +@@ -304,3 +327,53 @@ int rpmcliVerifySignatures(rpmts ts, ARGV_const_t argv) rpmKeyringFree(keyring); return res; } @@ -308,7 +300,7 @@ index 40a3ab83f..dc1726a18 100644 + struct vfydatafd_s *vd = cbdata; + char *vmsg, *msg; + size_t n; -+ size_t remainder = BUFSIZ - vd->len; ++ size_t remainder = BUFSIZ - vd->len >= 0 ? BUFSIZ - vd->len : 0; + + vmsg = rpmsinfoMsg(sinfo); + rasprintf(&msg, " %s\n", vmsg); @@ -336,7 +328,7 @@ index 40a3ab83f..dc1726a18 100644 + rpmtsSetVfyLevel(ts, vfylevel); + } + -+ if (!rpmpkgVerifySigsFD(keyring, vfylevel, vsflags, fdi, vfyFDCb, &vd)) { ++ if (!rpmpkgVerifySigs(keyring, vfylevel, vsflags, fdi, vfyFDCb, &vd)) { + rc = RPMRC_OK; + } + *msg = strdup(vd.msg); @@ -369,22 +361,83 @@ index 906fe9951..7ff48b37a 100644 #endif diff --git a/lib/rpmextents.c b/lib/rpmextents.c new file mode 100644 -index 000000000..015277751 +index 000000000..ac43264af --- /dev/null +++ b/lib/rpmextents.c -@@ -0,0 +1,46 @@ +@@ -0,0 +1,110 @@ + +#include "system.h" + +#include +#include ++#include ++#include ++ + +#include "lib/rpmextents_internal.h" + -+rpmRC isTranscodedRpm(FD_t fd) { ++ ++int extentsVerifySigs(FD_t fd, int print_content){ ++ rpm_loff_t current; ++ int32_t rc; ++ size_t len; ++ uint64_t content_len; ++ char *content = NULL; ++ struct extents_footer_t footer; ++ ++ current = Ftell(fd); ++ ++ if(extentsFooterFromFD(fd, &footer) != RPMRC_OK) { ++ rc = -1; ++ goto exit; ++ } ++ if(Fseek(fd, footer.offsets.checksig_offset, SEEK_SET) < 0) { ++ rpmlog(RPMLOG_ERR, _("extentsVerifySigs: Failed to seek signature verification offset\n")); ++ rc = -1; ++ goto exit; ++ } ++ len = sizeof(rc); ++ if (Fread(&rc, len, 1, fd) != len) { ++ rpmlog(RPMLOG_ERR, _("extentsVerifySigs: Failed to read Signature Verification RC\n")); ++ rc = -1; ++ goto exit; ++ } ++ ++ if(print_content) { ++ len = sizeof(content_len); ++ if (Fread(&content_len, len, 1, fd) != len) { ++ rpmlog(RPMLOG_ERR, _("extentsVerifySigs: Failed to read signature content length\n")); ++ goto exit; ++ } ++ ++ content = rmalloc(content_len + 1); ++ if(content == NULL) { ++ rpmlog(RPMLOG_ERR, _("extentsVerifySigs: Failed to allocate memory to read signature content\n")); ++ goto exit; ++ } ++ content[content_len] = 0; ++ if (Fread(content, content_len, 1, fd) != content_len) { ++ rpmlog(RPMLOG_ERR, _("extentsVerifySigs: Failed to read signature content\n")); ++ goto exit; ++ } ++ ++ rpmlog(RPMLOG_NOTICE, "%s", content); ++ } ++exit: ++ if(content){ ++ rfree(content); ++ } ++ if (Fseek(fd, current, SEEK_SET) < 0) { ++ rpmlog(RPMLOG_ERR, _("extentsVerifySigs: unable to seek back to original location\n")); ++ } ++ return rc; ++ ++} ++ ++rpmRC extentsFooterFromFD(FD_t fd, struct extents_footer_t *footer) { ++ + rpmRC rc = RPMRC_NOTFOUND; + rpm_loff_t current; -+ extents_magic_t magic; + size_t len; + + // If the file is not seekable, we cannot detect whether or not it is transcoded. @@ -393,19 +446,17 @@ index 000000000..015277751 + } + current = Ftell(fd); + -+ if(Fseek(fd, -(sizeof(magic)), SEEK_END) < 0) { -+ rpmlog(RPMLOG_ERR, _("isTranscodedRpm: failed to seek for magic\n")); ++ len = sizeof(struct extents_footer_t); ++ if(Fseek(fd, -len, SEEK_END) < 0) { + rc = RPMRC_FAIL; + goto exit; + } -+ len = sizeof(magic); -+ if (Fread(&magic, len, 1, fd) != len) { -+ rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to read magic\n")); ++ if (Fread(footer, len, 1, fd) != len) { ++ rpmlog(RPMLOG_ERR, _("isTranscodedRpm: unable to read footer\n")); + rc = RPMRC_FAIL; + goto exit; + } -+ if (magic != EXTENTS_MAGIC) { -+ rpmlog(RPMLOG_DEBUG, _("isTranscodedRpm: not transcoded\n")); ++ if (footer->magic != EXTENTS_MAGIC) { + rc = RPMRC_NOTFOUND; + goto exit; + } @@ -418,13 +469,18 @@ index 000000000..015277751 + return rc; +} + ++rpmRC isTranscodedRpm(FD_t fd) { ++ struct extents_footer_t footer; ++ return extentsFooterFromFD(fd, &footer); ++} ++ + diff --git a/lib/rpmextents_internal.h b/lib/rpmextents_internal.h new file mode 100644 -index 000000000..57cecfc31 +index 000000000..0a3318c8e --- /dev/null +++ b/lib/rpmextents_internal.h -@@ -0,0 +1,22 @@ +@@ -0,0 +1,58 @@ +#ifndef _RPMEXTENTS_INTERNAL_H +#define _RPMEXTENTS_INTERNAL_H + @@ -434,6 +490,10 @@ index 000000000..57cecfc31 + +#include + ++/** \ingroup rpmextents ++ * RPM extents library ++ */ ++ +/* magic value at end of file (64 bits) that indicates this is a transcoded + * rpm. + */ @@ -441,12 +501,44 @@ index 000000000..57cecfc31 + +typedef uint64_t extents_magic_t; + ++struct __attribute__ ((__packed__)) extents_footer_offsets_t { ++ off64_t checksig_offset; ++ off64_t table_offset; ++ off64_t csum_offset; ++}; ++ ++struct __attribute__ ((__packed__)) extents_footer_t { ++ struct extents_footer_offsets_t offsets; ++ extents_magic_t magic; ++}; ++ ++/** \ingroup rpmextents ++ * Checks the results of the signature verification ran during transcoding. ++ * @param fd The FD_t of the transcoded RPM ++ * @param print_content Whether or not to print the result from rpmsig ++ * @return The number of checks that `rpmvsVerify` failed during transcoding. ++ */ ++int extentsVerifySigs(FD_t fd, int print_content); ++ ++/** \ingroup rpmextents ++ * Read the RPM Extents footer from a file descriptor. ++ * @param fd The FD_t of the transcoded RPM ++ * @param[out] footer A pointer to an allocated extents_footer_t with a copy of the footer. ++ * @return RPMRC_OK on success, RPMRC_NOTFOUND if not a transcoded file, RPMRC_FAIL on any failure. ++ */ ++rpmRC extentsFooterFromFD(FD_t fd, struct extents_footer_t *footer); ++ ++/** \ingroup rpmextents ++ * Check if a RPM is a transcoded RPM ++ * @param fd The FD_t of the transcoded RPM ++ * return RPMRC_OK on success, RPMRC_NOTFOUND if not a transcoded file, RPMRC_FAIL on any failure. ++ */ +rpmRC isTranscodedRpm(FD_t fd); + +#ifdef __cplusplus +} +#endif -+#endif ++#endif /* _RPMEXTENTS_INTERNAL_H */ diff --git a/lib/rpmplugin.h b/lib/rpmplugin.h index fd81aec8d..6dbbcff35 100644 --- a/lib/rpmplugin.h @@ -581,8 +673,50 @@ index 39762c376..88807c53c 100644 #ifdef __cplusplus } #endif +diff --git a/lib/transaction.c b/lib/transaction.c +index 36c2a7a64..a476a5365 100644 +--- a/lib/transaction.c ++++ b/lib/transaction.c +@@ -37,6 +37,7 @@ + #include "lib/rpmfi_internal.h" /* only internal apis */ + #include "lib/rpmte_internal.h" /* only internal apis */ + #include "lib/rpmts_internal.h" ++#include "lib/rpmextents_internal.h" + #include "lib/rpmvs.h" + #include "rpmio/rpmhook.h" + #include "lib/rpmtriggers.h" +@@ -1255,10 +1256,16 @@ + .signature = RPMRC_NOTFOUND, + .vfylevel = vfylevel, + }; ++ int verified = 0; + rpmRC prc = RPMRC_FAIL; + + rpmtsNotify(ts, p, RPMCALLBACK_VERIFY_PROGRESS, oc++, total); + FD_t fd = rpmtsNotify(ts, p, RPMCALLBACK_INST_OPEN_FILE, 0, 0); ++ if(fd != NULL && isTranscodedRpm(fd) == RPMRC_OK) { ++ /* Transcoded RPMs are validated at transcoding time */ ++ prc = RPMRC_OK; ++ verified = 1; ++ } else { + if (fd != NULL) { + prc = rpmpkgRead(vs, fd, NULL, NULL, &vd.msg); + rpmtsNotify(ts, p, RPMCALLBACK_INST_CLOSE_FILE, 0, 0); +@@ -1267,8 +1274,11 @@ + if (prc == RPMRC_OK) + prc = rpmvsVerify(vs, RPMSIG_VERIFIABLE_TYPE, vfyCb, &vd); + ++ verified = vd.signature == RPMRC_OK; ++ } ++ + /* Record verify result, signatures only for now */ +- rpmteSetVerified(p, vd.signature == RPMRC_OK); ++ rpmteSetVerified(p, verified); + + if (prc) + rpmteAddProblem(p, RPMPROB_VERIFY, NULL, vd.msg, 0); diff --git a/plugins/reflink.c b/plugins/reflink.c -index 513887604..4fc1d74d1 100644 +index 513887604..69e6b51e6 100644 --- a/plugins/reflink.c +++ b/plugins/reflink.c @@ -13,6 +13,7 @@ @@ -614,7 +748,7 @@ index 513887604..4fc1d74d1 100644 struct reflink_state_s { /* Stuff that's used across rpms */ long fundamental_block_size; -@@ -58,6 +54,7 @@ struct reflink_state_s { +@@ -58,10 +54,55 @@ struct reflink_state_s { FD_t fd; rpmfiles files; inodeIndexHash inodeIndexes; @@ -622,7 +756,55 @@ index 513887604..4fc1d74d1 100644 }; typedef struct reflink_state_s * reflink_state; -@@ -96,51 +93,35 @@ static void reflink_cleanup(rpmPlugin plugin) { + ++/* ++ * bsearch_r: implements a re-entrant version of stdlib's bsearch. ++ * code taken and adapted from /usr/include/bits/stdlib-bsearch.h ++ */ ++inline void * ++bsearch_r (const void *__key, const void *__base, size_t __nmemb, size_t __size, ++ __compar_d_fn_t __compar, void *__arg) ++{ ++ size_t __l, __u, __idx; ++ const void *__p; ++ int __comparison; ++ ++ __l = 0; ++ __u = __nmemb; ++ while (__l < __u) ++ { ++ __idx = (__l + __u) / 2; ++ __p = (const void *) (((const char *) __base) + (__idx * __size)); ++ __comparison = (*__compar) (__key, __p, __arg); ++ if (__comparison < 0) ++ __u = __idx; ++ else if (__comparison > 0) ++ __l = __idx + 1; ++ else ++ { ++#if __GNUC_PREREQ(4, 6) ++# pragma GCC diagnostic push ++# pragma GCC diagnostic ignored "-Wcast-qual" ++#endif ++ return (void *) __p; ++#if __GNUC_PREREQ(4, 6) ++# pragma GCC diagnostic pop ++#endif ++ } ++ } ++ ++ return NULL; ++} ++ ++static int cmpdigest(const void *k1, const void *k2, void *data) { ++ rpmlog(RPMLOG_DEBUG, _("reflink: cmpdigest k1=%p k2=%p\n"), k1, k2); ++ return memcmp(k1, k2, *(int *)data); ++} ++ + static int inodeCmp(rpm_ino_t a, rpm_ino_t b) + { + return (a != b); +@@ -96,51 +137,35 @@ static void reflink_cleanup(rpmPlugin plugin) { } static rpmRC reflink_psm_pre(rpmPlugin plugin, rpmte te) { @@ -690,7 +872,7 @@ index 513887604..4fc1d74d1 100644 rpmlog(RPMLOG_ERR, _("reflink: failed to seek for tail %p\n"), state->fd); return RPMRC_FAIL; -@@ -182,7 +163,7 @@ static rpmRC reflink_psm_pre(rpmPlugin plugin, rpmte te) { +@@ -182,7 +207,7 @@ static rpmRC reflink_psm_pre(rpmPlugin plugin, rpmte te) { return RPMRC_FAIL; } state->inodeIndexes = inodeIndexHashCreate( @@ -699,7 +881,33 @@ index 513887604..4fc1d74d1 100644 ); } -@@ -239,13 +220,13 @@ rpm_loff_t find(const unsigned char *digest, reflink_state state) { +@@ -217,21 +242,13 @@ static rpmRC reflink_psm_post(rpmPlugin plugin, rpmte te, int res) + rpm_loff_t find(const unsigned char *digest, reflink_state state); + + rpm_loff_t find(const unsigned char *digest, reflink_state state) { +-# if defined(__GNUC__) +- /* GCC nested function because bsearch's comparison function can't access +- * state-keysize otherwise +- */ +- int cmpdigest(const void *k1, const void *k2) { +- rpmlog(RPMLOG_DEBUG, _("reflink: cmpdigest k1=%p k2=%p\n"), k1, k2); +- return memcmp(k1, k2, state->keysize); +- } +-# endif + rpmlog(RPMLOG_DEBUG, +- _("reflink: bsearch(key=%p, base=%p, nmemb=%d, size=%lu)\n"), ++ _("reflink: bsearch_r(key=%p, base=%p, nmemb=%d, size=%lu)\n"), + digest, state->table, state->keys, + state->keysize + sizeof(rpm_loff_t)); +- char *entry = bsearch(digest, state->table, state->keys, +- state->keysize + sizeof(rpm_loff_t), cmpdigest); ++ char *entry = bsearch_r(digest, state->table, state->keys, ++ state->keysize + sizeof(rpm_loff_t), cmpdigest, ++ &state->keysize); + if (entry == NULL) { + return NOT_FOUND; + } +@@ -239,13 +256,13 @@ rpm_loff_t find(const unsigned char *digest, reflink_state state) { return offset; } @@ -715,7 +923,7 @@ index 513887604..4fc1d74d1 100644 reflink_state state = rpmPluginGetData(plugin); if (state->table == NULL) { -@@ -262,18 +243,15 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path, +@@ -262,18 +279,15 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path, /* check for hard link entry in table. GetEntry overwrites hlix with * the address of the first match. */ @@ -738,7 +946,7 @@ index 513887604..4fc1d74d1 100644 return RPMRC_PLUGIN_CONTENTS; } /* if we didn't hard link, then we'll track this inode as being -@@ -281,7 +259,7 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path, +@@ -281,7 +295,7 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path, */ if (rpmfiFNlink(fi) > 1) { /* minor optimization: only store files with more than one link */ @@ -747,7 +955,7 @@ index 513887604..4fc1d74d1 100644 } /* derived from wfd_open in fsm.c */ mode_t old_umask = umask(0577); -@@ -366,10 +344,21 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path, +@@ -366,10 +380,21 @@ static rpmRC reflink_fsm_file_pre(rpmPlugin plugin, rpmfi fi, const char* path, return RPMRC_OK; } @@ -771,7 +979,7 @@ index 513887604..4fc1d74d1 100644 + .fsm_file_archive_reader = reflink_fsm_file_archive_reader, }; diff --git a/rpm2extents.c b/rpm2extents.c -index c111be0a2..a326e3857 100644 +index c111be0a2..7dd5128de 100644 --- a/rpm2extents.c +++ b/rpm2extents.c @@ -2,7 +2,9 @@ @@ -807,7 +1015,7 @@ index c111be0a2..a326e3857 100644 struct digestoffset { const unsigned char * digest; rpm_loff_t pos; -@@ -51,38 +50,47 @@ rpm_loff_t pad_to(rpm_loff_t pos, rpm_loff_t unit) +@@ -51,38 +50,49 @@ rpm_loff_t pad_to(rpm_loff_t pos, rpm_loff_t unit) return (unit - (pos % unit)) % unit; } @@ -858,8 +1066,10 @@ index c111be0a2..a326e3857 100644 len = sizeof(fdilength); - if (Fwrite(&fdilength, len, 1, validationo) != len) { +- fprintf(stderr, _("Unable to write input length %zd\n"), fdilength); + if (Fwrite(&fdilength, len, 1, fdo) != len) { - fprintf(stderr, _("Unable to write input length %zd\n"), fdilength); ++ rpmlog(RPMLOG_ERR, _("Unable to write input length %zd: %d, %s\n"), ++ fdilength, errno, strerror(errno)); goto exit; } len = sizeof(algos_len); @@ -867,44 +1077,54 @@ index c111be0a2..a326e3857 100644 - fprintf(stderr, _("Unable to write number of validation digests\n")); + if (Fwrite(&algos_len, len, 1, fdo) != len) { + algo_digest_len = (uint32_t)filedigest_len; -+ fprintf(stderr, _("Unable to write number of digests\n")); ++ rpmlog(RPMLOG_ERR, _("Unable to write number of digests: %d, %s\n"), ++ errno, strerror(errno)); goto exit; } for (algo = 0; algo < algos_len; algo++) { -@@ -93,24 +101,24 @@ static int digestor( +@@ -93,25 +103,29 @@ static int digestor( algo_digest_len = (uint32_t)filedigest_len; len = sizeof(algo_name_len); - if (Fwrite(&algo_name_len, len, 1, validationo) != len) { -+ if (Fwrite(&algo_name_len, len, 1, fdo) != len) { - fprintf(stderr, +- fprintf(stderr, - _("Unable to write validation algo name length\n")); -+ _("Unable to write digest algo name length\n")); ++ if (Fwrite(&algo_name_len, len, 1, fdo) != len) { ++ rpmlog(RPMLOG_ERR, ++ _("Unable to write digest algo name length: %d, %s\n"), ++ errno, strerror(errno)); goto exit; } len = sizeof(algo_digest_len); - if (Fwrite(&algo_digest_len, len, 1, validationo) != len) { -+ if (Fwrite(&algo_digest_len, len, 1, fdo) != len) { - fprintf(stderr, +- fprintf(stderr, - _("Unable to write number of bytes for validation digest\n")); -+ _("Unable to write number of bytes for digest\n")); ++ if (Fwrite(&algo_digest_len, len, 1, fdo) != len) { ++ rpmlog(RPMLOG_ERR, ++ _("Unable to write number of bytes for digest: %d, %s\n"), ++ errno, strerror(errno)); goto exit; } - if (Fwrite(algo_name, algo_name_len, 1, validationo) != algo_name_len) { - fprintf(stderr, _("Unable to write validation algo name\n")); + if (Fwrite(algo_name, algo_name_len, 1, fdo) != algo_name_len) { -+ fprintf(stderr, _("Unable to write digest algo name\n")); ++ rpmlog(RPMLOG_ERR, _("Unable to write digest algo name: %d, %s\n"), ++ errno, strerror(errno)); goto exit; } - if (Fwrite(filedigest, algo_digest_len, 1, validationo ) != algo_digest_len) { -+ if (Fwrite(filedigest, algo_digest_len, 1, fdo ) != algo_digest_len) { - fprintf(stderr, +- fprintf(stderr, - _("Unable to write validation digest value %u, %zu\n"), -+ _("Unable to write digest value %u, %zu\n"), - algo_digest_len, filedigest_len); +- algo_digest_len, filedigest_len); ++ if (Fwrite(filedigest, algo_digest_len, 1, fdo ) != algo_digest_len) { ++ rpmlog(RPMLOG_ERR, ++ _("Unable to write digest value %u, %zu: %d, %s\n"), ++ algo_digest_len, filedigest_len, ++ errno, strerror(errno)); goto exit; } -@@ -120,7 +128,69 @@ static int digestor( + } +@@ -120,7 +134,80 @@ static int digestor( return rc; } @@ -914,22 +1134,29 @@ index c111be0a2..a326e3857 100644 + rpmRC rc = RPMRC_FAIL; + + if(rpmvsrc){ -+ fprintf(stderr, _("Error verifying package signatures\n")); ++ rpmlog(RPMLOG_WARNING, ++ _("Error verifying package signatures:\n%s\n"), msg); + } + + len = sizeof(rpmvsrc); + if (Fwrite(&rpmvsrc, len, 1, fdo) != len) { -+ fprintf(stderr, _("Unable to write signature verification RC code %d\n"), rpmvsrc); ++ rpmlog(RPMLOG_ERR, ++ _("Unable to write signature verification RC code %d: %d, %s\n"), ++ rpmvsrc, errno, strerror(errno)); + goto exit; + } + size_t content_len = msg ? strlen(msg) : 0; + len = sizeof(content_len); + if (Fwrite(&content_len, len, 1, fdo) != len) { -+ fprintf(stderr, _("Unable to write signature verification output length %zd\n"), content_len); ++ rpmlog(RPMLOG_ERR, ++ _("Unable to write signature verification output length %zd: %d, %s\n"), ++ content_len, errno, strerror(errno)); + goto exit; + } + if (Fwrite(msg, content_len, 1, fdo) != content_len) { -+ fprintf(stderr, _("Unable to write signature verification output %s\n"), msg); ++ rpmlog(RPMLOG_ERR, ++ _("Unable to write signature verification output %s: %d, %s\n"), ++ msg, errno, strerror(errno)); + goto exit; + } + @@ -955,12 +1182,16 @@ index c111be0a2..a326e3857 100644 + + // Write result of digest computation + if(FDWriteDigests(fdi, digesto, algos, algos_len) != RPMRC_OK) { -+ fprintf(stderr, _("Failed to write digests")); ++ rpmlog(RPMLOG_ERR, _("Failed to write digests: %d, %s\n"), ++ errno, strerror(errno)); + goto exit; + } + + // Write result of signature validation. + if(FDWriteSignaturesValidation(sigo, rpmvsrc, msg)) { ++ rpmlog(RPMLOG_ERR, ++ _("Failed to write signature verification result: %d, %s\n"), ++ errno, strerror(errno)); + goto exit; + } + rc = RPMRC_OK; @@ -975,7 +1206,7 @@ index c111be0a2..a326e3857 100644 { uint32_t diglen; /* GNU C extension: can use diglen from outer context */ -@@ -148,7 +218,7 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) +@@ -148,7 +235,7 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) rpm_mode_t mode; char *rpmio_flags = NULL, *zeros; const unsigned char *digest; @@ -984,14 +1215,75 @@ index c111be0a2..a326e3857 100644 uint32_t offset_ix = 0; size_t len; int next = 0; -@@ -253,6 +323,16 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) +@@ -156,24 +243,24 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) + fdo = fdDup(STDOUT_FILENO); + + if (rpmReadPackageRaw(fdi, &sigh, &h)) { +- fprintf(stderr, _("Error reading package\n")); ++ rpmlog(RPMLOG_ERR, _("Error reading package\n")); + exit(EXIT_FAILURE); + } + + if (rpmLeadWrite(fdo, h)) + { +- fprintf(stderr, _("Unable to write package lead: %s\n"), ++ rpmlog(RPMLOG_ERR, _("Unable to write package lead: %s\n"), + Fstrerror(fdo)); + exit(EXIT_FAILURE); + } + + if (rpmWriteSignature(fdo, sigh)) { +- fprintf(stderr, _("Unable to write signature: %s\n"), Fstrerror(fdo)); ++ rpmlog(RPMLOG_ERR, _("Unable to write signature: %s\n"), Fstrerror(fdo)); + exit(EXIT_FAILURE); + } + + if (headerWrite(fdo, h, HEADER_MAGIC_YES)) { +- fprintf(stderr, _("Unable to write headers: %s\n"), Fstrerror(fdo)); ++ rpmlog(RPMLOG_ERR, _("Unable to write headers: %s\n"), Fstrerror(fdo)); + exit(EXIT_FAILURE); + } + +@@ -187,7 +274,7 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) + free(rpmio_flags); + + if (gzdi == NULL) { +- fprintf(stderr, _("cannot re-open payload: %s\n"), Fstrerror(gzdi)); ++ rpmlog(RPMLOG_ERR, _("cannot re-open payload: %s\n"), Fstrerror(gzdi)); + exit(EXIT_FAILURE); + } + +@@ -230,7 +317,7 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) + } + pad = pad_to(pos, fundamental_block_size); + if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) { +- fprintf(stderr, _("Unable to write padding\n")); ++ rpmlog(RPMLOG_ERR, _("Unable to write padding\n")); + rc = RPMRC_FAIL; + goto exit; + } +@@ -243,7 +330,12 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) + size = rpmfiFSize(fi); + rc = rpmfiArchiveReadToFile(fi, fdo, 0); + if (rc != RPMRC_OK) { +- fprintf(stderr, _("rpmfiArchiveReadToFile failed with %d\n"), rc); ++ char *errstr = rpmfileStrerror(rc); ++ rpmlog(RPMLOG_ERR, ++ _("rpmfiArchiveReadToFile failed while extracting "\ ++ "\"%s\" with RC %d: %s\n"), ++ rpmfiFN(fi), rc, errstr); ++ free(errstr); + goto exit; + } + pos += size; +@@ -253,42 +345,53 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) qsort(offsets, (size_t)offset_ix, sizeof(struct digestoffset), digestoffsetCmp); + validation_pos = pos; + ssize_t validation_len = ufdCopy(validationi, fdo); + if (validation_len == -1) { -+ fprintf(stderr, _("validation output ufdCopy failed\n")); ++ rpmlog(RPMLOG_ERR, _("validation output ufdCopy failed\n")); + rc = RPMRC_FAIL; + goto exit; + } @@ -1000,8 +1292,30 @@ index c111be0a2..a326e3857 100644 + len = sizeof(offset_ix); if (Fwrite(&offset_ix, len, 1, fdo) != len) { - fprintf(stderr, _("Unable to write length of table\n")); -@@ -278,17 +358,18 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) +- fprintf(stderr, _("Unable to write length of table\n")); ++ rpmlog(RPMLOG_ERR, _("Unable to write length of table\n")); + rc = RPMRC_FAIL; + goto exit; + } + len = sizeof(diglen); + if (Fwrite(&diglen, len, 1, fdo) != len) { +- fprintf(stderr, _("Unable to write length of digest\n")); ++ rpmlog(RPMLOG_ERR, _("Unable to write length of digest\n")); + rc = RPMRC_FAIL; + goto exit; + } + len = sizeof(rpm_loff_t); + for (int x = 0; x < offset_ix; x++) { + if (Fwrite(offsets[x].digest, diglen, 1, fdo) != diglen) { +- fprintf(stderr, _("Unable to write digest\n")); ++ rpmlog(RPMLOG_ERR, _("Unable to write digest\n")); + rc = RPMRC_FAIL; + goto exit; + } + if (Fwrite(&offsets[x].pos, len, 1, fdo) != len) { +- fprintf(stderr, _("Unable to write offset\n")); ++ rpmlog(RPMLOG_ERR, _("Unable to write offset\n")); + rc = RPMRC_FAIL; goto exit; } } @@ -1014,9 +1328,10 @@ index c111be0a2..a326e3857 100644 - ssize_t validation_len = ufdCopy(validationi, fdo); - if (validation_len == -1) { +- fprintf(stderr, _("digest table ufdCopy failed\n")); + ssize_t digest_len = ufdCopy(digestori, fdo); + if (digest_len == -1) { - fprintf(stderr, _("digest table ufdCopy failed\n")); ++ rpmlog(RPMLOG_ERR, _("digest table ufdCopy failed\n")); rc = RPMRC_FAIL; goto exit; } @@ -1024,33 +1339,38 @@ index c111be0a2..a326e3857 100644 /* add more padding so the last file can be cloned. It doesn't matter that * the table and validation etc are in this space. In fact, it's pretty * efficient if it is. -@@ -302,17 +383,22 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) +@@ -297,25 +400,15 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) + pad = pad_to((validation_pos + validation_len + 2 * sizeof(rpm_loff_t) + + sizeof(uint64_t)), fundamental_block_size); + if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) { +- fprintf(stderr, _("Unable to write final padding\n")); ++ rpmlog(RPMLOG_ERR, _("Unable to write final padding\n")); + rc = RPMRC_FAIL; goto exit; } zeros = _free(zeros); - if (Fwrite(&pos, len, 1, fdo) != len) { -+ if (Fwrite(&validation_pos, len, 1, fdo) != len) { -+ fprintf(stderr, _("Unable to write offset of validation output\n")); -+ rc = RPMRC_FAIL; -+ goto exit; -+ } -+ if (Fwrite(&digest_table_pos, len, 1, fdo) != len) { - fprintf(stderr, _("Unable to write offset of digest table\n")); - rc = RPMRC_FAIL; - goto exit; - } +- fprintf(stderr, _("Unable to write offset of digest table\n")); +- rc = RPMRC_FAIL; +- goto exit; +- } - if (Fwrite(&validation_pos, len, 1, fdo) != len) { -+ if (Fwrite(&digest_pos, len, 1, fdo) != len) { - fprintf(stderr, _("Unable to write offset of validation table\n")); +- fprintf(stderr, _("Unable to write offset of validation table\n")); +- rc = RPMRC_FAIL; +- goto exit; +- } +- uint64_t magic = MAGIC; +- len = sizeof(magic); +- if (Fwrite(&magic, len, 1, fdo) != len) { +- fprintf(stderr, _("Unable to write magic\n")); ++ struct extents_footer_t footer = {.offsets = {validation_pos, digest_table_pos, digest_pos}, .magic = EXTENTS_MAGIC}; ++ len = sizeof(footer); ++ if (Fwrite(&footer, len, 1, fdo) != len) { ++ rpmlog(RPMLOG_ERR, _("Unable to write footer\n")); rc = RPMRC_FAIL; goto exit; } -- uint64_t magic = MAGIC; -+ extents_magic_t magic = EXTENTS_MAGIC; - len = sizeof(magic); - if (Fwrite(&magic, len, 1, fdo) != len) { - fprintf(stderr, _("Unable to write magic\n")); -@@ -327,104 +413,200 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) +@@ -327,104 +420,202 @@ static rpmRC process_package(FD_t fdi, FD_t validationi) return rc; } @@ -1075,7 +1395,9 @@ index c111be0a2..a326e3857 100644 + for(int i=0; i < len; i++) { + wrbytes = Fwrite(buf, sizeof(buf[0]), rdbytes, fds[i]); + if (wrbytes != rdbytes) { -+ fprintf(stderr, "Error wriing to FD %d: %s\n", i, Fstrerror(fds[i])); ++ rpmlog(RPMLOG_ERR, ++ _("Error wriing to FD %d: %s\n"), ++ i, Fstrerror(fds[i])); + total = -1; + break; + } @@ -1119,7 +1441,7 @@ index c111be0a2..a326e3857 100644 - _("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n")); - exit(EXIT_FAILURE); + if (pipe(processorpipefd) == -1) { -+ fprintf(stderr, _("Processor pipe failure\n")); ++ rpmlog(RPMLOG_ERR, _("Processor pipe failure\n")); + return RPMRC_FAIL; } @@ -1132,7 +1454,7 @@ index c111be0a2..a326e3857 100644 - exit(EXIT_FAILURE); - } + if (pipe(validatorpipefd) == -1) { -+ fprintf(stderr, _("Validator pipe failure\n")); ++ rpmlog(RPMLOG_ERR, _("Validator pipe failure\n")); + return RPMRC_FAIL; } @@ -1141,7 +1463,7 @@ index c111be0a2..a326e3857 100644 - fprintf(stderr, _("Main pipe failure\n")); - exit(EXIT_FAILURE); + if (pipe(meta_digestpipefd) == -1) { -+ fprintf(stderr, _("Meta digest pipe failure\n")); ++ rpmlog(RPMLOG_ERR, _("Meta digest pipe failure\n")); + return RPMRC_FAIL; } - if (pipe(metapipefd) == -1) { @@ -1149,7 +1471,7 @@ index c111be0a2..a326e3857 100644 - exit(EXIT_FAILURE); + + if (pipe(meta_rpmsignpipefd) == -1) { -+ fprintf(stderr, _("Meta rpm signature pipe failure\n")); ++ rpmlog(RPMLOG_ERR, _("Meta rpm signature pipe failure\n")); + return RPMRC_FAIL; } - cpid = fork(); @@ -1179,7 +1501,7 @@ index c111be0a2..a326e3857 100644 + close(meta_rpmsignpipefd[1]); + rc = validator(fdi, digesto, sigo, algos, algos_len); + if(rc != RPMRC_OK) { -+ fprintf(stderr, _("Validator failed\n")); ++ rpmlog(RPMLOG_ERR, _("Validator failed with RC %d\n"), rc); + } Fclose(fdi); + Fclose(digesto); @@ -1222,7 +1544,7 @@ index c111be0a2..a326e3857 100644 + + rc = process_package(fdi, digestori, sigi); + if(rc != RPMRC_OK) { -+ fprintf(stderr, _("Validator failed\n")); ++ rpmlog(RPMLOG_ERR, _("Package processor failed: %d\n"), rc); } - } - w = waitpid(cpid, &wstatus, 0); @@ -1271,19 +1593,19 @@ index c111be0a2..a326e3857 100644 + rc = RPMRC_OK; + offt = ufdTee(fdi, fds, 2); + if(offt == -1){ -+ fprintf(stderr, _("Failed to tee RPM\n")); ++ rpmlog(RPMLOG_ERR, _("Failed to tee RPM\n")); + rc = RPMRC_FAIL; + } + Fclose(fds[0]); + Fclose(fds[1]); + w = waitpid(cpids[0], &wstatus, 0); + if (w == -1) { -+ fprintf(stderr, _("waitpid cpids[0] failed\n")); ++ rpmlog(RPMLOG_ERR, _("waitpid cpids[0] failed\n")); + rc = RPMRC_FAIL; + } + w = waitpid(cpids[1], &wstatus, 0); + if (w == -1) { -+ fprintf(stderr, _("waitpid cpids[1] failed\n")); ++ rpmlog(RPMLOG_ERR, _("waitpid cpids[1] failed\n")); + rc = RPMRC_FAIL; + } } @@ -1306,8 +1628,8 @@ index c111be0a2..a326e3857 100644 + poptSetOtherOptionHelp(optCon, "[OPTIONS]* "); + + if (poptPeekArg(optCon) == NULL) { -+ fprintf(stderr, -+ _("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n")); ++ rpmlog(RPMLOG_ERR, ++ _("Need at least one DIGESTALGO parameter, e.g. 'SHA256'\n")); + poptPrintUsage(optCon, stderr, 0); + exit(EXIT_FAILURE); + } @@ -1319,9 +1641,9 @@ index c111be0a2..a326e3857 100644 + for (int x = 0; x < nb_algos; x++) { + if (pgpStringVal(PGPVAL_HASHALGO, args[x], &algos[x]) != 0) + { -+ fprintf(stderr, -+ _("Unable to resolve '%s' as a digest algorithm, exiting\n"), -+ args[x]); ++ rpmlog(RPMLOG_ERR, ++ _("Unable to resolve '%s' as a digest algorithm, exiting\n"), ++ args[x]); + exit(EXIT_FAILURE); } } @@ -1484,10 +1806,10 @@ index c3189d327..a110564e2 100644 (unset RPM_CONFIGDIR RPM_POPTEXEC_PATH; cd ${RPMTEST} && \ diff --git a/tests/rpm2extents.at b/tests/rpm2extents.at new file mode 100644 -index 000000000..29165c1b9 +index 000000000..5135c9cf8 --- /dev/null +++ b/tests/rpm2extents.at -@@ -0,0 +1,141 @@ +@@ -0,0 +1,140 @@ +# rpm2extents.at: Some very basic checks +# +# Copyright (C) 2022 Manu Bretelle @@ -1592,43 +1914,42 @@ index 000000000..29165c1b9 +RPMDB_INIT + +runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/hello-2.0-1.x86_64.rpm 2> /dev/null -+runroot_plugins rpm -i --nodigest --nodeps --undefine=%__transaction_dbus_announce /tmp/hello-2.0-1.x86_64.rpm ++runroot_plugins rpm -i --nodeps --undefine=%__transaction_dbus_announce /tmp/hello-2.0-1.x86_64.rpm ++test -f ${RPMTEST}/usr/bin/hello +], +[0], +[], +[]) +AT_CLEANUP + -+AT_SETUP([reflink hardlink package]) -+AT_KEYWORDS([reflink hardlink]) -+AT_SKIP_IF([$REFLINK_DISABLED]) ++AT_SETUP([reflink ignores non-transcoded package]) ++AT_KEYWORDS([reflink]) +AT_CHECK([ +RPMDB_INIT + -+PKG=hlinktest-1.0-1.noarch.rpm -+runroot_other cat /data/RPMS/${PKG} | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/${PKG} 2> /dev/null -+runroot_plugins rpm -i --nodigest --nodeps --undefine=%__transaction_dbus_announce /tmp/${PKG} ++runroot_plugins rpm -i --nodeps --undefine=%__transaction_dbus_announce /data/RPMS/hello-2.0-1.x86_64.rpm && exit $? ++# Check that the file is properly installed in chroot ++test -f ${RPMTEST}/usr/bin/hello +], +[0], +[], +[]) +AT_CLEANUP + -+AT_SETUP([rpm2extents install package]) -+AT_KEYWORDS([rpm2extents reflink]) ++AT_SETUP([reflink hardlink package]) ++AT_KEYWORDS([reflink hardlink]) +AT_SKIP_IF([$REFLINK_DISABLED]) +AT_CHECK([ +RPMDB_INIT + -+runroot_other cat /data/RPMS/hello-2.0-1.x86_64.rpm | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/hello-2.0-1.x86_64.rpm 2> /dev/null -+runroot_plugins rpm -i --nodigest --nodeps --undefine=%__transaction_dbus_announce /tmp/hello-2.0-1.x86_64.rpm ++PKG=hlinktest-1.0-1.noarch.rpm ++runroot_other cat /data/RPMS/${PKG} | runroot_other rpm2extents SHA256 > ${RPMTEST}/tmp/${PKG} 2> /dev/null ++runroot_plugins rpm -i --nodeps --undefine=%__transaction_dbus_announce /tmp/${PKG} +], +[0], +[], +[]) +AT_CLEANUP -+ -+ diff --git a/tests/rpmtests.at b/tests/rpmtests.at index a1adab8e0..205fed6a3 100644 --- a/tests/rpmtests.at diff --git a/SPECS/rpm.spec b/SPECS/rpm.spec index 2243c83..9cb5f43 100644 --- a/SPECS/rpm.spec +++ b/SPECS/rpm.spec @@ -42,7 +42,7 @@ %global rpmver 4.14.3 #global snapver rc2 -%global rel 21.5 +%global rel 21.6 %global srcver %{version}%{?snapver:-%{snapver}} %global srcdir %{?snapver:testing}%{!?snapver:%{name}-%(echo %{version} | cut -d'.' -f1-2).x} @@ -799,6 +799,10 @@ make check || cat tests/rpmtests.log %doc doc/librpm/html/* %changelog +* Fri Mar 25 2022 Manu Bretelle - 4.14.3-21.6 +- Make `rpm -i` work without `--nodigest` +- Remove need of executable stack for reflink plugin + * Fri Mar 04 2022 Manu Bretelle - 4.14.3-21.5 - Backport GH#1040 to allow ndb DB query on read-only FS