From 7eb7b473a04ccad9457bbd0de1bc6c7f52d11b93 Mon Sep 17 00:00:00 2001 From: Florian Festi Date: Fri, 27 Sep 2024 15:24:31 +0200 Subject: [PATCH] Add rpmlogOnce() and rpmlogReset() These are internal only for now to allow us gain soem more confidence on the design. rpmlogOnce allows showing a log message only once. rpmlogReset allows purging the list of known message keys for a given domain. This allows for different live times e.g. per transaction or per package. Use in handleHdrVS. This does not add a new test case but various existing test cases fail when the NOKEY message is omited or shown more than once. The code uses the pointer to the rpmts object as a domain and resets it when the rpmts is freed. Resolves: #3336 Resolves: #3395 --- lib/package.cc | 31 +++++++-------------------- lib/rpmts.cc | 2 ++ rpmio/rpmlog.cc | 45 +++++++++++++++++++++++++++++++++++++++- rpmio/rpmlog_internal.hh | 23 ++++++++++++++++++++ 4 files changed, 76 insertions(+), 25 deletions(-) create mode 100644 rpmio/rpmlog_internal.hh diff --git a/lib/package.cc b/lib/package.cc index 73e9f60505..a7aa62cbc2 100644 --- a/lib/package.cc +++ b/lib/package.cc @@ -18,6 +18,7 @@ #include "rpmlead.hh" #include "rpmio_internal.hh" /* fd digest bits */ +#include "rpmlog_internal.hh" /* rpmlogOnce */ #include "header_internal.hh" /* XXX headerCheck */ #include "rpmvs.hh" @@ -31,6 +32,7 @@ struct pkgdata_s { hdrvsmsg msgfunc; const char *fn; char *msg; + uint64_t logDomain; rpmRC rc; }; @@ -110,28 +112,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(const char *keyid) -{ - static std::mutex keyid_mutex; - static std::set keyids; - int seen = 0; - - if (keyid == NULL) - 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; @@ -170,6 +150,7 @@ rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, char ** msg) .msgfunc = appendhdrmsg, .fn = NULL, .msg = NULL, + .logDomain = (uint64_t) ts, .rc = RPMRC_OK, }; @@ -294,8 +275,8 @@ static void loghdrmsg(struct rpmsinfo_s *sinfo, struct pkgdata_s *pkgdata, 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; + if (rpmlogOnce(pkgdata->logDomain, sinfo->keyid, RPMLOG_WARNING, "%s: %s\n", pkgdata->fn, msg)) + goto exit; break; case RPMRC_NOTFOUND: /* Signature/digest not present. */ lvl = RPMLOG_WARNING; @@ -307,6 +288,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) diff --git a/lib/rpmts.cc b/lib/rpmts.cc index cb894af532..758b893354 100644 --- a/lib/rpmts.cc +++ b/lib/rpmts.cc @@ -30,6 +30,7 @@ #include "rpmplugins.hh" #include "rpmts_internal.hh" #include "rpmte_internal.hh" +#include "rpmlog_internal.hh" #include "misc.hh" #include "rpmtriggers.hh" @@ -575,6 +576,7 @@ rpmts rpmtsFree(rpmts ts) ts->plugins = rpmpluginsFree(ts->plugins); rpmtriggersFree(ts->trigs2run); + rpmlogReset((uint64_t) ts); if (_rpmts_stats) rpmtsPrintStats(ts); diff --git a/rpmio/rpmlog.cc b/rpmio/rpmlog.cc index 6253e45d51..26322a3c45 100644 --- a/rpmio/rpmlog.cc +++ b/rpmio/rpmlog.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -22,6 +23,7 @@ struct rpmlogCtx_s { unsigned mask; int nrecsPri[RPMLOG_NPRIS]; std::vector recs; + std::map, int>> seen; rpmlogCallback cbfunc; rpmlogCallbackData cbdata; FILE *stdlog; @@ -41,7 +43,7 @@ using rdlock = std::shared_lock; static rpmlogCtx rpmlogCtxAcquire() { static struct rpmlogCtx_s _globalCtx = { RPMLOG_UPTO(RPMLOG_NOTICE), - {0}, {}, NULL, NULL, NULL }; + {0}, {}, {}, NULL, NULL, NULL }; return &_globalCtx; } @@ -127,6 +129,7 @@ void rpmlogClose (void) wrlock lock(ctx->mutex); ctx->recs.clear(); + ctx->seen.clear(); memset(ctx->nrecsPri, 0, sizeof(ctx->nrecsPri)); } @@ -412,3 +415,43 @@ void rpmlog (int code, const char *fmt, ...) exit: errno = saved_errno; } + +int rpmlogOnce (uint64_t domain, const char * key, int code, const char *fmt, ...) +{ + int saved_errno = errno; + rpmlogCtx ctx = rpmlogCtxAcquire(); + int newkey = 0; + + if (ctx) { + wrlock lock(ctx->mutex); + newkey = !ctx->seen[domain][{code, key}]++; + } + + if (newkey) { + va_list ap; + char *msg = NULL; + va_start(ap, fmt); + if (rvasprintf(&msg, fmt, ap) >= 0) { + rpmlog(code, msg); + free(msg); + } + va_end(ap); + } + errno = saved_errno; + return newkey; +} + +void rpmlogReset(uint64_t domain, int mode=0) +{ + rpmlogCtx ctx = rpmlogCtxAcquire(); + std::map, int> domain_data = {}; + + if (ctx) { + wrlock lock(ctx->mutex); + if (mode) + domain_data = ctx->seen[domain]; + ctx->seen.erase(domain); + } + + /* Implement other modes here */ +} diff --git a/rpmio/rpmlog_internal.hh b/rpmio/rpmlog_internal.hh new file mode 100644 index 0000000000..8024eddc0c --- /dev/null +++ b/rpmio/rpmlog_internal.hh @@ -0,0 +1,23 @@ +#ifndef H_RPMLOG_INTERNAL +#define H_RPMLOG_INTERNAL 1 + + +/** \ingroup rpmlog + * Generate a log message using FMT string and option arguments. + * Only actually log on the first time passing the key value + * @param domain group of messages to be reset together + * @param key key to match log messages together + * @param code rpmlogLvl + * @param fmt format string and parameter to render + * @return 1 if actually logging 0 otherwise + */ +int rpmlogOnce (uint64_t domain, const char * key, int code, const char *fmt, ...) RPM_GNUC_PRINTF(4, 5); + +/** \ingroup rpmlog + * Clear memory of logmessages for a given domain + * @param domain group of messages to be reset together + * @param mode curretnly only 0 supported whihc drops everything + */ +void rpmlogReset(uint64_t domain, int mode=0); + +#endif