diff --git a/include/rpm/rpmts.h b/include/rpm/rpmts.h index dc5b31c55c..6090f1704b 100644 --- a/include/rpm/rpmts.h +++ b/include/rpm/rpmts.h @@ -663,6 +663,16 @@ int rpmtsGetNotifyStyle(rpmts ts); */ int rpmtsSetChangeCallback(rpmts ts, rpmtsChangeFunction notify, void *data); +/** \ingroup rpmts + * Log messages with the same key just once + * @param ts transaction set + * @param key key to match log messages together + * @param code rpmlogLvl + * @param fmt format string and parameter to render + * @return 0 for the first call with this key value 1 otherwise + */ +int rpmtsLogOnce(rpmts ts, const char * key, int code, const char * fmt, ...) RPM_GNUC_PRINTF(4, 5); + /** \ingroup rpmts * Create an empty transaction set. * @return new transaction set diff --git a/lib/package.cc b/lib/package.cc index 1267522fe4..5460b6645c 100644 --- a/lib/package.cc +++ b/lib/package.cc @@ -27,6 +27,7 @@ typedef struct pkgdata_s *pkgdatap; typedef void (*hdrvsmsg)(struct rpmsinfo_s *sinfo, pkgdatap pkgdata, const char *msg); struct pkgdata_s { + rpmts ts; hdrvsmsg msgfunc; const char *fn; char *msg; @@ -109,28 +110,6 @@ rpmTagVal headerMergeLegacySigs(Header h, Header sigh, char **msg) return xl->stag; } -/** - * Remember current key id. - * XXX: This s*** needs to die. Hook it into keyring or sumthin... - * @param keyid signature keyid - * @return 0 if new keyid, otherwise 1 - */ -static int stashKeyid(unsigned int keyid) -{ - static std::mutex keyid_mutex; - static std::set keyids; - int seen = 0; - - if (keyid == 0) - return 0; - - std::lock_guard lock(keyid_mutex); - auto ret = keyids.insert(keyid); - seen = (ret.second == false); - - return seen; -} - static int handleHdrVS(struct rpmsinfo_s *sinfo, void *cbdata) { struct pkgdata_s *pkgdata = (struct pkgdata_s *)cbdata; @@ -287,14 +266,19 @@ static void loghdrmsg(struct rpmsinfo_s *sinfo, struct pkgdata_s *pkgdata, const char *msg) { int lvl = RPMLOG_DEBUG; + char * signid = NULL; + int printed = 0; switch (sinfo->rc) { case RPMRC_OK: /* Signature is OK. */ break; case RPMRC_NOTTRUSTED: /* Signature is OK, but key is not trusted. */ case RPMRC_NOKEY: /* Public key is unavailable. */ /* XXX Print NOKEY/NOTTRUSTED warning only once. */ - if (stashKeyid(sinfo->keyid) == 0) - lvl = RPMLOG_WARNING; + signid = rpmhex(pgpDigParamsSignID(sinfo->sig), PGP_KEYID_LEN); + printed = rpmtsLogOnce(pkgdata->ts, signid, RPMLOG_WARNING, "%s: %s\n", pkgdata->fn, msg); + free(signid); + if (!printed) + goto exit; break; case RPMRC_NOTFOUND: /* Signature/digest not present. */ lvl = RPMLOG_WARNING; @@ -306,6 +290,8 @@ static void loghdrmsg(struct rpmsinfo_s *sinfo, struct pkgdata_s *pkgdata, } rpmlog(lvl, "%s: %s\n", pkgdata->fn, msg); + exit: + ; } rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp) @@ -319,6 +305,7 @@ rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp) rpmKeyring keyring = rpmtsGetKeyring(ts, 1); struct rpmvs_s *vs = rpmvsCreate(0, vsflags, keyring); struct pkgdata_s pkgdata = { + .ts = ts, .msgfunc = loghdrmsg, .fn = fn ? fn : Fdescr(fd), .msg = NULL, diff --git a/lib/rpmts.cc b/lib/rpmts.cc index c014b2b049..8fda592a7c 100644 --- a/lib/rpmts.cc +++ b/lib/rpmts.cc @@ -1260,6 +1260,26 @@ int rpmtsSetChangeCallback(rpmts ts, rpmtsChangeFunction change, void *data) return 0; } +int rpmtsLogOnce(rpmts ts, const char * key, int code, const char * fmt, ...) +{ + int saved_errno = errno; + va_list ap; + char *msg = NULL; + int seen = 0; + auto ret = ts->logged_once.insert(key); + seen = (ret.second == false); + if (!seen) { + va_start(ap, fmt); + if (rvasprintf(&msg, fmt, ap) >= 0) { + rpmlog(code, msg); + free(msg); + } + va_end(ap); + } + errno = saved_errno; + return seen; +} + tsMembers rpmtsMembers(rpmts ts) { return (ts != NULL) ? ts->members : NULL; @@ -1368,6 +1388,7 @@ rpmts rpmtsCreate(void) ts->trigs2run = rpmtriggersCreate(10); ts->min_writes = (rpmExpandNumeric("%{?_minimize_writes}") > 0); + ts->logged_once = {}; return rpmtsLink(ts); } diff --git a/lib/rpmts_internal.hh b/lib/rpmts_internal.hh index ded10ec092..2517ad6514 100644 --- a/lib/rpmts_internal.hh +++ b/lib/rpmts_internal.hh @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -100,6 +101,7 @@ struct rpmts_s { int min_writes; /*!< macro minimize_writes used */ time_t overrideTime; /*!< Time value used when overriding system clock. */ + std::set logged_once; /* Messages already logged */ }; /** \ingroup rpmts diff --git a/lib/rpmvs.cc b/lib/rpmvs.cc index 6d95363aff..d423a7f6df 100644 --- a/lib/rpmvs.cc +++ b/lib/rpmvs.cc @@ -196,7 +196,6 @@ static void rpmsinfoInit(const struct vfyinfo_s *vinfo, char *lints = NULL; int ec = pgpPrtParams2((const uint8_t *)data, dlen, PGPTAG_SIGNATURE, &sinfo->sig, &lints); - const uint8_t *signid; if (ec) { if (lints) { rasprintf(&sinfo->msg, @@ -214,8 +213,6 @@ static void rpmsinfoInit(const struct vfyinfo_s *vinfo, free(lints); } sinfo->hashalgo = pgpDigParamsAlgo(sinfo->sig, PGPVAL_HASHALGO); - signid = pgpDigParamsSignID(sinfo->sig); /* 8 bytes key id */ - sinfo->keyid = signid[4] << 24 | signid[5] << 16 | signid[6] << 8 | signid[7]; } else if (sinfo->type == RPMSIG_DIGEST_TYPE) { if (td->type == RPM_BIN_TYPE) { sinfo->dig = rpmhex((const uint8_t *)data, dlen);