Fix: Treat x86_64_v2 as x86_64 in architecture checks

This commit is contained in:
Eduard Abdullin 2026-06-20 03:50:05 +00:00 committed by root
commit 28c8338557
6 changed files with 2411 additions and 3 deletions

View File

@ -0,0 +1,97 @@
From c0e4c08533e3e899d7e1cc0d9885e83ea1e1bdfb Mon Sep 17 00:00:00 2001
From: Dave Cantrell <dcantrell@redhat.com>
Date: Mon, 20 Apr 2026 15:05:04 -0400
Subject: [PATCH] Prevent buffer overruns in findPreambleTag() for language
string
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is technically possible and there is a reproducer for it, but I
would not consider this a critical problem. If you have a really long
language identifier string in a preamble tag and it's larger than
BUFSIZ on the platform, you get a SIGSEGV. Not a surprise.
In spec files you can have stuff like this in the preamble:
Summary: Here is a short summary
Summary(de): Hier ist eine kurze Zusammenfassung
Summary(eo): Jen mallonga resumo
Summary(Elvish): Sí na- a estent summarui
Summary(ga_ie): Is coimriú ghearr é seo
Summary(Klingon): naDev 'oH ngaj summary
And findPreambleTag() is eventually called to pick up those language
identifiers in parens. Usually the identifiers are two characters,
but sometimes they are three or four. The parser in the library scans
a character at a time until it hits the closing paren and just stuffs
it all in the 'lang' buffer. The problem is that buffer is BUFSIZ and
there is no bounds checking to see if the string in the spec file in
parens is larger than what BUFSIZ can hold. So it is technically
possible to provide a spec file with a completely useless huge string
as a language identifier that then crashes the spec file parser.
This patch adds some bounds checking to that reading loop to prevent
this incredibly rare yet technically possible issue. I don't bother
growing the buffer if we're still reading characters because honestly
if we have more than BUFSIZ in parens, we've got a garbage spec file.
The patch does ensure the unused space in BUFSIZ is NULL and that the
lang buffer is NULL terminated so it's moderately useful in later
parts of the code.
Signed-off-by: Dave Cantrell <dcantrell@redhat.com>
(backported from commit b6f2cc52fcc7eedf0095c2bf0495e4b6aafd87cb)
---
build/parsePreamble.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/build/parsePreamble.c b/build/parsePreamble.c
index 3693746f8..e14664939 100644
--- a/build/parsePreamble.c
+++ b/build/parsePreamble.c
@@ -1064,10 +1064,11 @@ static struct PreambleRec_s const preambleList[] = {
/**
*/
static int findPreambleTag(rpmSpec spec,rpmTagVal * tag,
- const char ** macro, char * lang)
+ const char ** macro, char * lang, size_t langsize)
{
PreambleRec p;
char *s;
+ size_t l = 0;
for (p = preambleList; p->token != NULL; p++) {
if (!(p->token && !rstrncasecmp(spec->line, p->token, p->len)))
@@ -1097,14 +1098,17 @@ static int findPreambleTag(rpmSpec spec,rpmTagVal * tag,
case 2:
if (*s == ':') {
/* Type 1 is multilang, 2 is qualifiers with no defaults */
- strcpy(lang, (p->type == 1) ? RPMBUILD_DEFAULT_LANG : "");
+ rstrlcpy(lang, (p->type == 1) ? RPMBUILD_DEFAULT_LANG : "", langsize);
+ l = strlen(lang);
break;
}
if (*s != '(') return 1;
s++;
SKIPSPACE(s);
- while (!risspace(*s) && *s != ')')
+ while (!risspace(*s) && *s != ')' && l < (langsize - 1)) {
*lang++ = *s++;
+ l++;
+ }
*lang = '\0';
SKIPSPACE(s);
if (*s != ')') return 1;
@@ -1173,7 +1177,7 @@ int parsePreamble(rpmSpec spec, int initialPackage)
linep = spec->line;
SKIPSPACE(linep);
if (*linep != '\0') {
- if (findPreambleTag(spec, &tag, &macro, lang)) {
+ if (findPreambleTag(spec, &tag, &macro, lang, sizeof(lang))) {
if (spec->lineNum == 1 &&
(unsigned char)(spec->line[0]) == 0xed &&
(unsigned char)(spec->line[1]) == 0xab &&
--
2.54.0

View File

@ -25,4 +25,8 @@ prepare:
how: shell
script: touch /etc/yum.repos.d/test-dummy.repo
adjust:
- enabled: false
when: arch != x86_64
continue: false

File diff suppressed because it is too large Load Diff

428
rpm-4.19.x-add-parkdb.patch Normal file
View File

@ -0,0 +1,428 @@
From 17a703eb3dfa7e2da4f441bd200d2548aef64025 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Tue, 2 Jun 2026 10:02:53 +0200
Subject: [PATCH 1/2] Extract common database rebuild logic
No functional change, just prepares the ground for the next commit.
(backported from commit 1dcddf95b7d956f5d024f63a531ea58bc485efe5)
---
lib/rpmts.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/lib/rpmts.c b/lib/rpmts.c
index 2f293e751..bc52a2f28 100644
--- a/lib/rpmts.c
+++ b/lib/rpmts.c
@@ -137,12 +137,10 @@ int rpmtsSetDBMode(rpmts ts, int dbmode)
return rc;
}
-
-int rpmtsRebuildDB(rpmts ts)
+static int rebuildDB(rpmts ts, int rebuildflags)
{
int rc = -1;
rpmtxn txn = NULL;
- int rebuildflags = 0;
/* Cannot do this on a populated transaction set */
if (rpmtsNElements(ts) > 0)
@@ -162,6 +160,11 @@ int rpmtsRebuildDB(rpmts ts)
return rc;
}
+int rpmtsRebuildDB(rpmts ts)
+{
+ return rebuildDB(ts, 0);
+}
+
int rpmtsVerifyDB(rpmts ts)
{
int rc = -1;
--
2.54.0
From 845be24a9128d73d6307cec8692c5783a7671a61 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Wed, 3 Jun 2026 14:19:41 +0200
Subject: [PATCH 2/2] Add support for database parking
Prior to including the RPM database on read-only media (such as a base
image in rpm-ostree), it should undergo some housekeeping and cleanup.
Add a new "parking" operation to rpmdb(8) and the corresponding API to
do just that.
This operation consists of a database rebuild coupled with an optional,
backend specific action triggered by passing a new flag RPMDB_FLAG_PARK
on database open. Since the action may take place on database close, let
the backend report a failure to park that way by handling the result in
rpmdbRebuild().
Implement such an action in the sqlite backend where it actually makes a
difference: Commit a8588f8e3970223f0b2fcc5d679dcb176f2e317b enabled WAL
mode but sqlite recommends that the database be converted to the default
DELETE journal mode prior to "burning" it onto read-only media [*]. Make
sure to do the conversion on database close since we may write to the
database during the rebuild, and that should always happen in WAL mode.
As a nice side effect with the sqlite backend, parking the database will
automatically remove the *-wal and *-shm files from %_dbpath, making it
usable in reproducible images. Hint at that in the man page but make it
clear that this is not a guarantee (but rather an implementation detail
of sqlite). Make use of this property in the test, though.
By parking, the database does not become read-only, and the parked state
does not stick when opening the database for writing (as we re-establish
WAL mode in such a case). This allows for the database to be immediately
writable inside a container running on top of a base image that includes
the database, without the user having to unpark it first.
[*] https://sqlite.org/wal.html#read_only_databases
Fixes: #2219
(backported from commit 1825517392c1a04b1f3bc6a89d308fdda2927edd)
---
docs/man/rpmdb.8.md | 13 +++++++++++--
include/rpm/rpmts.h | 7 +++++++
lib/backend/dbi.h | 1 +
lib/backend/sqlite.c | 17 +++++++++++++++--
lib/rpmdb.c | 7 +++++--
lib/rpmdb_internal.h | 1 +
lib/rpmts.c | 5 +++++
python/rpmts-py.c | 15 +++++++++++++++
tools/rpmdb.c | 6 ++++++
9 files changed, 66 insertions(+), 6 deletions(-)
diff --git a/docs/man/rpmdb.8.md b/docs/man/rpmdb.8.md
index 8ad1ce3bb..7d308ca98 100644
--- a/docs/man/rpmdb.8.md
+++ b/docs/man/rpmdb.8.md
@@ -12,7 +12,7 @@ rpmdb - RPM Database Tool
SYNOPSIS
========
-**rpmdb** {**\--initdb\|\--rebuilddb**}
+**rpmdb** {**\--initdb\|\--rebuilddb\|\--parkdb**}
**rpmdb** {**\--verifydb**}
@@ -23,7 +23,7 @@ DESCRIPTION
The general form of an rpmdb command is
-**rpm** {**\--initdb\|\--rebuilddb**} \[**-v**\] \[**\--dbpath
+**rpm** {**\--initdb\|\--rebuilddb\|\--parkdb**} \[**-v**\] \[**\--dbpath
***DIRECTORY*\] \[**\--root ***DIRECTORY*\]
Use **\--initdb** to create a new database if one doesn\'t already exist
@@ -38,6 +38,15 @@ for transfporting to another host or database type.
**\--importdb** imports a database from a header-list format as created
by **\--exportdb**.
+**\--parkdb** parks the database. This prepares and optimizes the database for
+inclusion on read-only media, such as immutable OS images. Write operations,
+such as RPM transactions, will unpark the database and continue normally,
+leaving the database unparked when finished. Thus, to unpark manually, use
+**\--rebuilddb**. Depending on the backend used, this operation may include the
+removal of auxiliary, backend-specific files from disk, such as the write-ahead
+log or shared memory index, and thus facilitate bit-for-bit reproducible OS
+images.
+
SEE ALSO
========
diff --git a/include/rpm/rpmts.h b/include/rpm/rpmts.h
index 5c168820f..d390f2ac4 100644
--- a/include/rpm/rpmts.h
+++ b/include/rpm/rpmts.h
@@ -308,6 +308,13 @@ int rpmtsSetDBMode(rpmts ts, int dbmode);
*/
int rpmtsRebuildDB(rpmts ts);
+/** \ingroup rpmts
+ * Park the database used by the transaction.
+ * @param ts transaction set
+ * @return 0 on success
+ */
+int rpmtsParkDB(rpmts ts);
+
/** \ingroup rpmts
* Verify the database used by the transaction.
* @param ts transaction set
diff --git a/lib/backend/dbi.h b/lib/backend/dbi.h
index 00ada038e..6e6226ff7 100644
--- a/lib/backend/dbi.h
+++ b/lib/backend/dbi.h
@@ -13,6 +13,7 @@ enum rpmdbFlags {
RPMDB_FLAG_REBUILD = (1 << 1),
RPMDB_FLAG_VERIFYONLY = (1 << 2),
RPMDB_FLAG_SALVAGE = (1 << 3),
+ RPMDB_FLAG_PARK = (1 << 4),
};
typedef enum dbCtrlOp_e {
diff --git a/lib/backend/sqlite.c b/lib/backend/sqlite.c
index 76e9cae72..6cedcce16 100644
--- a/lib/backend/sqlite.c
+++ b/lib/backend/sqlite.c
@@ -197,10 +197,23 @@ static int sqlite_fini(rpmdb rdb)
if (sqlite3_db_readonly(sdb, NULL) == 0) {
sqlexec(sdb, "PRAGMA optimize");
sqlexec(sdb, "PRAGMA wal_checkpoint = TRUNCATE");
+
+ /* Park the database if requested */
+ if ((rdb->db_flags & RPMDB_FLAG_PARK) != 0) {
+ int zero = 0;
+ /* Make sure any WAL and SHM files are cleaned up */
+ sqlite3_file_control(sdb, NULL, SQLITE_FCNTL_PERSIST_WAL,
+ &zero);
+ rc = sqlexec(sdb, "PRAGMA journal_mode = DELETE");
+ if (rc == 0)
+ rpmlog(RPMLOG_DEBUG, _("rpmdb sqlite parking done\n"));
+ else
+ rpmlog(RPMLOG_ERR, _("rpmdb sqlite parking failed\n"));
+ }
}
rdb->db_dbenv = NULL;
int xx = sqlite3_close(sdb);
- rc = (xx != SQLITE_OK);
+ rc += (xx != SQLITE_OK);
}
}
@@ -329,7 +342,7 @@ static int sqlite_Close(dbiIndex dbi, unsigned int flags)
int rc = 0;
if (rdb->db_flags & RPMDB_FLAG_REBUILD)
rc = init_index(dbi, rpmTagGetValue(dbi->dbi_file));
- sqlite_fini(dbi->dbi_rpmdb);
+ rc += sqlite_fini(dbi->dbi_rpmdb);
dbiFree(dbi);
return rc;
}
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index 117df46e1..39b2e723e 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -2450,7 +2450,9 @@ int rpmdbRebuild(const char * prefix, rpmts ts,
goto exit;
}
if (openDatabase(prefix, newdbpath, &newdb,
- (O_RDWR | O_CREAT), 0644, RPMDB_FLAG_REBUILD)) {
+ (O_RDWR | O_CREAT), 0644, RPMDB_FLAG_REBUILD |
+ (rebuildflags & RPMDB_REBUILD_FLAG_PARK ?
+ RPMDB_FLAG_PARK : 0))) {
rc = 1;
goto exit;
}
@@ -2498,7 +2500,8 @@ int rpmdbRebuild(const char * prefix, rpmts ts,
rpmdbClose(olddb);
dbCtrl(newdb, DB_CTRL_INDEXSYNC);
- rpmdbClose(newdb);
+ if (rpmdbClose(newdb))
+ failed = 1;
if (failed) {
rpmlog(RPMLOG_WARNING,
diff --git a/lib/rpmdb_internal.h b/lib/rpmdb_internal.h
index 0590013db..36e18b71a 100644
--- a/lib/rpmdb_internal.h
+++ b/lib/rpmdb_internal.h
@@ -22,6 +22,7 @@ extern "C" {
enum rpmdbRebuildFlags_e {
RPMDB_REBUILD_FLAG_SALVAGE = (1 << 0),
+ RPMDB_REBUILD_FLAG_PARK = (1 << 1),
};
/** \ingroup rpmdb
diff --git a/lib/rpmts.c b/lib/rpmts.c
index bc52a2f28..96dd31b0a 100644
--- a/lib/rpmts.c
+++ b/lib/rpmts.c
@@ -165,6 +165,11 @@ int rpmtsRebuildDB(rpmts ts)
return rebuildDB(ts, 0);
}
+int rpmtsParkDB(rpmts ts)
+{
+ return rebuildDB(ts, RPMDB_REBUILD_FLAG_PARK);
+}
+
int rpmtsVerifyDB(rpmts ts)
{
int rc = -1;
diff --git a/python/rpmts-py.c b/python/rpmts-py.c
index ae2eeea28..dc81d3489 100644
--- a/python/rpmts-py.c
+++ b/python/rpmts-py.c
@@ -375,6 +375,18 @@ rpmts_RebuildDB(rpmtsObject * s)
return Py_BuildValue("i", rc);
}
+static PyObject *
+rpmts_ParkDB(rpmtsObject * s)
+{
+ int rc;
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = rpmtsParkDB(s->ts);
+ Py_END_ALLOW_THREADS
+
+ return Py_BuildValue("i", rc);
+}
+
static PyObject *
rpmts_VerifyDB(rpmtsObject * s)
{
@@ -799,6 +811,9 @@ Remove all elements from the transaction set\n" },
{"rebuildDB", (PyCFunction) rpmts_RebuildDB, METH_NOARGS,
"ts.rebuildDB() -> None\n\
- Rebuild the default transaction rpmdb.\n" },
+ {"parkDB", (PyCFunction) rpmts_ParkDB, METH_NOARGS,
+"ts.parkDB() -> None\n\
+- Park the default transaction rpmdb.\n" },
{"verifyDB", (PyCFunction) rpmts_VerifyDB, METH_NOARGS,
"ts.verifyDB() -> None\n\
- Verify the default transaction rpmdb.\n" },
diff --git a/tools/rpmdb.c b/tools/rpmdb.c
index 36efff8af..3de81be26 100644
--- a/tools/rpmdb.c
+++ b/tools/rpmdb.c
@@ -13,6 +13,7 @@ enum modes {
MODE_EXPORTDB = (1 << 3),
MODE_IMPORTDB = (1 << 4),
MODE_SALVAGEDB = (1 << 5),
+ MODE_PARKDB = (1 << 6),
};
static int mode = 0;
@@ -23,6 +24,8 @@ static struct poptOption dbOptsTable[] = {
{ "rebuilddb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_REBUILDDB,
N_("rebuild database inverted lists from installed package headers"),
NULL},
+ { "parkdb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR),
+ &mode, MODE_PARKDB, N_("park database"), NULL},
{ "verifydb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR),
&mode, MODE_VERIFYDB, N_("verify database"), NULL},
{ "salvagedb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR|POPT_ARGFLAG_DOC_HIDDEN),
@@ -117,6 +120,9 @@ int main(int argc, char *argv[])
ec = rpmtsRebuildDB(ts);
rpmtsSetVSFlags(ts, ovsflags);
} break;
+ case MODE_PARKDB:
+ ec = rpmtsParkDB(ts);
+ break;
case MODE_VERIFYDB:
ec = rpmtsVerifyDB(ts);
break;
--
2.54.0
diff -up rpm-4.19.1.1/docs/man/rpmdb.8.orig rpm-4.19.1.1/docs/man/rpmdb.8
--- rpm-4.19.1.1/docs/man/rpmdb.8.orig 2026-06-18 09:27:25.469107665 +0200
+++ rpm-4.19.1.1/docs/man/rpmdb.8 2026-06-18 09:27:53.907945350 +0200
@@ -1,70 +1,60 @@
-.\" Automatically generated by Pandoc 3.1.3
+.\" Automatically generated by Pandoc 3.1.11.1
.\"
-.\" Define V font for inline verbatim, using C font in formats
-.\" that render this, and otherwise B font.
-.ie "\f[CB]x\f[]"x" \{\
-. ftr V B
-. ftr VI BI
-. ftr VB B
-. ftr VBI BI
-.\}
-.el \{\
-. ftr V CR
-. ftr VI CI
-. ftr VB CB
-. ftr VBI CBI
-.\}
.TH "RPMDB" "8" "29 June 2010" "" ""
-.hy
.SH NAME
-.PP
-rpmdb - RPM Database Tool
+rpmdb \- RPM Database Tool
.SH SYNOPSIS
+\f[B]rpmdb\f[R] {\f[B]\-\-initdb|\-\-rebuilddb|\-\-parkdb\f[R]}
.PP
-\f[B]rpmdb\f[R] {\f[B]--initdb|--rebuilddb\f[R]}
-.PP
-\f[B]rpmdb\f[R] {\f[B]--verifydb\f[R]}
+\f[B]rpmdb\f[R] {\f[B]\-\-verifydb\f[R]}
.PP
-\f[B]rpmdb\f[R] {\f[B]--exportdb|--importdb\f[R]}
+\f[B]rpmdb\f[R] {\f[B]\-\-exportdb|\-\-importdb\f[R]}
.SH DESCRIPTION
-.PP
The general form of an rpmdb command is
.PP
-\f[B]rpm\f[R] {\f[B]--initdb|--rebuilddb\f[R]} [\f[B]-v\f[R]]
-[\f[B]--dbpath \f[R]\f[I]DIRECTORY\f[R]] [\f[B]--root
-\f[R]\f[I]DIRECTORY\f[R]]
+\f[B]rpm\f[R] {\f[B]\-\-initdb|\-\-rebuilddb|\-\-parkdb\f[R]}
+[\f[B]\-v\f[R]] [\f[B]\-\-dbpath \f[R]\f[I]DIRECTORY\f[R]]
+[\f[B]\-\-root \f[R]\f[I]DIRECTORY\f[R]]
.PP
-Use \f[B]--initdb\f[R] to create a new database if one doesn\[aq]t
+Use \f[B]\-\-initdb\f[R] to create a new database if one doesn\[aq]t
already exist (existing database is not overwritten), use
-\f[B]--rebuilddb\f[R] to rebuild the database indices from the installed
-package headers.
+\f[B]\-\-rebuilddb\f[R] to rebuild the database indices from the
+installed package headers.
.PP
-\f[B]--verifydb\f[R] performs a low-level integrity check on the
+\f[B]\-\-verifydb\f[R] performs a low\-level integrity check on the
database.
.PP
-\f[B]--exportdb\f[R] exports the database in header-list format,
+\f[B]\-\-exportdb\f[R] exports the database in header\-list format,
suitable for transfporting to another host or database type.
.PP
-\f[B]--importdb\f[R] imports a database from a header-list format as
-created by \f[B]--exportdb\f[R].
-.SH SEE ALSO
+\f[B]\-\-importdb\f[R] imports a database from a header\-list format as
+created by \f[B]\-\-exportdb\f[R].
.PP
+\f[B]\-\-parkdb\f[R] parks the database.
+This prepares and optimizes the database for inclusion on read\-only
+media, such as immutable OS images.
+Write operations, such as RPM transactions, will unpark the database and
+continue normally, leaving the database unparked when finished.
+Thus, to unpark manually, use \f[B]\-\-rebuilddb\f[R].
+Depending on the backend used, this operation may include the removal of
+auxiliary, backend\-specific files from disk, such as the write\-ahead
+log or shared memory index, and thus facilitate bit\-for\-bit
+reproducible OS images.
+.SH SEE ALSO
\f[B]popt\f[R](3), \f[B]rpm\f[R](8), \f[B]rpmkeys\f[R](8),
\f[B]rpmsign\f[R](8), \f[B]rpm2cpio\f[R](8), \f[B]rpmbuild\f[R](8),
\f[B]rpmspec\f[R](8)
.PP
-\f[B]rpm --help\f[R] - as rpm supports customizing the options via popt
-aliases it\[aq]s impossible to guarantee that what\[aq]s described in
-the manual matches what\[aq]s available.
+\f[B]rpm \-\-help\f[R] \- as rpm supports customizing the options via
+popt aliases it\[aq]s impossible to guarantee that what\[aq]s described
+in the manual matches what\[aq]s available.
.PP
\f[B]http://www.rpm.org/ <URL:http://www.rpm.org/>\f[R]
.SH AUTHORS
.IP
-.nf
-\f[C]
+.EX
Marc Ewing <marc\[at]redhat.com>
Jeff Johnson <jbj\[at]redhat.com>
Erik Troan <ewt\[at]redhat.com>
Panu Matilainen <pmatilai\[at]redhat.com>
-\f[R]
-.fi
+.EE

View File

@ -0,0 +1,699 @@
From 76be5b707d1d55388bcb6bd77c8cc351152612de Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 8 Apr 2026 10:40:39 +0300
Subject: [PATCH 1/6] Fix wrong operation names used in the syslog plugin
There are more rpmte types than just TR_ADDED and TR_REMOVED these days,
but this code was never updated to match. As a result, it'll log
anything but installs (such as --restore) as erasure which can be a
little hair-raising when looking at the log.
Fixes: #4172
(cherry picked from commit bbba5b986ff468badb49a822bd70b68dcf606cef)
---
plugins/syslog.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/plugins/syslog.c b/plugins/syslog.c
index f7b1a1388..2dac9872f 100644
--- a/plugins/syslog.c
+++ b/plugins/syslog.c
@@ -74,13 +74,24 @@ static rpmRC syslog_tsm_post(rpmPlugin plugin, rpmts ts, int res)
return RPMRC_OK;
}
+static const char *getOp(rpmte te)
+{
+ switch (rpmteType(te)) {
+ case TR_ADDED: return "install";
+ case TR_REMOVED: return "erase";
+ case TR_RPMDB: return "rpmdb";
+ case TR_RESTORED: return "restore";
+ }
+ return "<unknown>";
+}
+
static rpmRC syslog_psm_post(rpmPlugin plugin, rpmte te, int res)
{
struct logstat * state = rpmPluginGetData(plugin);
if (state->logging) {
int lvl = LOG_NOTICE;
- const char *op = (rpmteType(te) == TR_ADDED) ? "install" : "erase";
+ const char *op = getOp(te);
const char *outcome = "success";
/* XXX: Permit configurable header queryformat? */
const char *pkg = rpmteNEVRA(te);
--
2.54.0
From fc5c083b06ae1b24c879c8db3e4af5d57074700a Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 15 Apr 2026 16:29:31 +0300
Subject: [PATCH 2/6] Use a sane identity string for syslog
The old "[RPM]" string is a PITA to grep for and annoying with journalctl
too. Lets just use plain "rpm" to reduce friction. And with that,
"journalctl -t rpm" is actually a pretty handy way to look at the
transaction history.
In theory, this could of course break somebody's scripts. But
considering how broken the output has been without anybody complaining,
it suggests nobody is actually using this plugin and so, changing cannot
hurt.
(cherry picked from commit 099128396c2a78cc2ca576be7c98dc269d11a457)
---
plugins/syslog.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/syslog.c b/plugins/syslog.c
index 2dac9872f..e05a9b4d1 100644
--- a/plugins/syslog.c
+++ b/plugins/syslog.c
@@ -16,7 +16,7 @@ struct logstat {
static rpmRC syslog_init(rpmPlugin plugin, rpmts ts)
{
/* XXX make this configurable? */
- const char * log_ident = "[RPM]";
+ const char * log_ident = "rpm";
struct logstat * state = rcalloc(1, sizeof(*state));
rpmPluginSetData(plugin, state);
--
2.54.0
From 91d39dbbbed2ad5537551aef5dd3bd6d65510bec Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 15 Apr 2026 13:53:57 +0300
Subject: [PATCH 3/6] Add + use an internal macro for determining script-only
install goals
No functional changes, but we'll need this info in another spot in
the next commit.
(cherry picked from commit bfefc137eb2d24c76858cc131b998a9fac99a679)
---
lib/rpmte.c | 2 +-
lib/rpmte_internal.h | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/rpmte.c b/lib/rpmte.c
index 657b4e11d..3802aeaec 100644
--- a/lib/rpmte.c
+++ b/lib/rpmte.c
@@ -815,7 +815,7 @@ int rpmteAddOp(rpmte te)
int rpmteProcess(rpmte te, pkgGoal goal, int num)
{
/* Only install/erase resets pkg file info */
- int scriptstage = (goal != PKG_INSTALL && goal != PKG_ERASE && goal != PKG_RESTORE);
+ int scriptstage = isScriptStage(goal);
int test = (rpmtsFlags(te->ts) & RPMTRANS_FLAG_TEST);
int reset_fi = (scriptstage == 0 && test == 0);
int failed = 1;
diff --git a/lib/rpmte_internal.h b/lib/rpmte_internal.h
index e616c0561..881772c95 100644
--- a/lib/rpmte_internal.h
+++ b/lib/rpmte_internal.h
@@ -22,6 +22,8 @@ typedef enum pkgGoal_e {
PKG_TRANSFILETRIGGERUN = RPMTAG_TRANSFILETRIGGERUN,
} pkgGoal;
+#define isScriptStage(_g) ((_g) != PKG_INSTALL && (_g) != PKG_ERASE && (_g) != PKG_RESTORE)
+
/** \ingroup rpmte
* Transaction element ordering chain linkage.
*/
--
2.54.0
From 38e1fedd72cb14b9bf8e0a428a79071eb0e510dc Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 15 Apr 2026 13:59:16 +0300
Subject: [PATCH 4/6] Only execute psm_pre and psm_post for the main package
operation
These hooks getting called multiple times with no means to identify
why it's getting called makes them impossible to use meaningfully.
Only run the psm hooks on non-script goals: install, erase and restore.
It is of course a change to what is now a public API semantics,
but the former behavior is really a bug that we're fixing here.
With this change, the syslog plugin no longer emits duplicates and
in a strange order at that.
Fixes: #1254
(backported from commit 0a45aefa01d1517184c41f233f4b53cebd78cf8d)
---
docs/manual/plugins.md | 2 +-
lib/psm.c | 7 ++++---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/docs/manual/plugins.md b/docs/manual/plugins.md
index e53eb9e3d..b34c182f4 100644
--- a/docs/manual/plugins.md
+++ b/docs/manual/plugins.md
@@ -44,7 +44,7 @@ Post hook is guaranteed to execute whenever pre hook was executed.
## Per transaction element hooks
-Hooks `psm_pre` and `psm_post` occur before and after the processing of single transaction element within the transaction. Both hooks can get executed multiple times for a single element as these hooks get called separately for %pretrans and %posttrans scriptlets in addition to the main package install or erase action.
+Hooks `psm_pre` and `psm_post` occur before and after the processing of single transaction element within the transaction during install, erase and restore operations.
Post hook is guaranteed to execute whenever pre hook was executed.
diff --git a/lib/psm.c b/lib/psm.c
index 39261b9f4..820704cab 100644
--- a/lib/psm.c
+++ b/lib/psm.c
@@ -1118,7 +1118,8 @@ static rpmRC runGoal(rpmpsm psm, pkgGoal goal)
rpmRC rpmpsmRun(rpmts ts, rpmte te, pkgGoal goal)
{
rpmpsm psm = NULL;
- rpmRC rc = RPMRC_FAIL;
+ rpmRC rc = RPMRC_OK;
+ int runplugins = (isScriptStage(goal) == 0);
/* Psm can't fail in test mode, just return early */
if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)
@@ -1126,7 +1127,7 @@ rpmRC rpmpsmRun(rpmts ts, rpmte te, pkgGoal goal)
psm = rpmpsmNew(ts, te, goal);
/* Run pre transaction element hook for all plugins */
- if (rpmChrootIn() == 0) {
+ if (runplugins && rpmChrootIn() == 0) {
rc = rpmpluginsCallPsmPre(rpmtsPlugins(ts), te);
rpmChrootOut();
}
@@ -1135,7 +1136,7 @@ rpmRC rpmpsmRun(rpmts ts, rpmte te, pkgGoal goal)
rc = runGoal(psm, goal);
/* Run post transaction element hook for all plugins (even on failure) */
- if (rpmChrootIn() == 0) {
+ if (runplugins && rpmChrootIn() == 0) {
rpmpluginsCallPsmPost(rpmtsPlugins(ts), te, rc);
rpmChrootOut();
}
--
2.54.0
From 4f85d8cf98e67200f82a6cef666d6bfecb084f21 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 20 May 2026 16:33:02 +0300
Subject: [PATCH 5/6] Add a configurable output target to the syslog plugin
Allow optionally redirecting the plugin output to stderr instead of
the actual syslog. We'll need this in the next commit to make testing
actually feasible.
(backported from commit fbf4d588458700da25f193770d10a3632c2c4836)
---
docs/man/rpm-plugin-syslog.8.md | 9 +++++--
plugins/syslog.c | 43 +++++++++++++++++++++++++++------
2 files changed, 43 insertions(+), 9 deletions(-)
diff --git a/docs/man/rpm-plugin-syslog.8.md b/docs/man/rpm-plugin-syslog.8.md
index e9fa48e1b..47a6bc549 100644
--- a/docs/man/rpm-plugin-syslog.8.md
+++ b/docs/man/rpm-plugin-syslog.8.md
@@ -18,8 +18,13 @@ The plugin writes basic information about rpm transactions to the syslog
Configuration
=============
-There are currently no options for this plugin in particular. See
-**rpm-plugins**(8) on how to control plugins in general.
+**%\_\_transaction\_syslog\_target**
+: Specify target output for the plugin. Supported values are:
+
+ - **syslog**: system log (default)
+ - **stderr**: standard error
+
+See **rpm-plugins**(8) on how to control plugins in general.
SEE ALSO
========
diff --git a/plugins/syslog.c b/plugins/syslog.c
index e05a9b4d1..5db295f4b 100644
--- a/plugins/syslog.c
+++ b/plugins/syslog.c
@@ -1,34 +1,63 @@
#include "system.h"
+#include <stdarg.h>
#include <stdlib.h>
#include <syslog.h>
+#include <rpm/rpmlog.h>
+#include <rpm/rpmmacro.h>
#include <rpm/rpmstring.h>
#include <rpm/rpmts.h>
#include "rpmplugin.h"
+typedef void (*loggerfunc)(int prio, const char *fmt, ...);
+
struct logstat {
int logging;
unsigned int scriptfail;
unsigned int pkgfail;
+ loggerfunc log;
};
+static void errlog(int prio, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
static rpmRC syslog_init(rpmPlugin plugin, rpmts ts)
{
/* XXX make this configurable? */
const char * log_ident = "rpm";
struct logstat * state = rcalloc(1, sizeof(*state));
+ char *target = rpmExpand("%{?__transaction_syslog_target}", NULL);
+
+ if (rstreq(target, "stderr")) {
+ state->log = errlog;
+ } else {
+ if (*target && !rstreq(target, "syslog")) {
+ rpmlog(RPMLOG_WARNING,
+ _("unknown syslog target %s, using 'syslog'\n"), target);
+ }
+ state->log = syslog;
+ openlog(log_ident, (LOG_PID), LOG_USER);
+ }
rpmPluginSetData(plugin, state);
- openlog(log_ident, (LOG_PID), LOG_USER);
+ free(target);
return RPMRC_OK;
}
static void syslog_cleanup(rpmPlugin plugin)
{
struct logstat * state = rpmPluginGetData(plugin);
+ if (state->log == syslog)
+ closelog();
free(state);
- closelog();
}
static rpmRC syslog_tsm_pre(rpmPlugin plugin, rpmts ts)
@@ -51,7 +80,7 @@ static rpmRC syslog_tsm_pre(rpmPlugin plugin, rpmts ts)
state->logging = 0;
if (state->logging) {
- syslog(LOG_NOTICE, "Transaction ID %x started", rpmtsGetTid(ts));
+ state->log(LOG_NOTICE, "Transaction ID %x started", rpmtsGetTid(ts));
}
return RPMRC_OK;
@@ -63,10 +92,10 @@ static rpmRC syslog_tsm_post(rpmPlugin plugin, rpmts ts, int res)
if (state->logging) {
if (state->pkgfail || state->scriptfail) {
- syslog(LOG_WARNING, "%u elements failed, %u scripts failed",
+ state->log(LOG_WARNING, "%u elements failed, %u scripts failed",
state->pkgfail, state->scriptfail);
}
- syslog(LOG_NOTICE, "Transaction ID %x finished: %d",
+ state->log(LOG_NOTICE, "Transaction ID %x finished: %d",
rpmtsGetTid(ts), res);
}
@@ -102,7 +131,7 @@ static rpmRC syslog_psm_post(rpmPlugin plugin, rpmte te, int res)
state->pkgfail++;
}
- syslog(lvl, "%s %s: %s", op, pkg, outcome);
+ state->log(lvl, "%s %s: %s", op, pkg, outcome);
}
return RPMRC_OK;
}
@@ -113,7 +142,7 @@ static rpmRC syslog_scriptlet_post(rpmPlugin plugin,
struct logstat * state = rpmPluginGetData(plugin);
if (state->logging && res) {
- syslog(LOG_WARNING, "scriptlet %s failure: %d\n", s_name, res);
+ state->log(LOG_WARNING, "scriptlet %s failure: %d\n", s_name, res);
state->scriptfail++;
}
return RPMRC_OK;
--
2.54.0
From eb44ea8ebb305bf13208dac5512bd6e00c3087ee Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 20 May 2026 16:37:13 +0300
Subject: [PATCH 6/6] Report meaningful operation names in syslog output
Determine and output human understandable operations, including the
related transaction elements where relevant and explain it in the
manual. Drop the comment about making things more configurable, that's
not helpful to the community (except perhaps if the default is bad,
as it originally was).
Add tests now that we can actually test it.
Related: RHEL-155272
(backported from commit 98bcdb37397c23c6689ab64824875f4021a986ed)
---
docs/man/rpm-plugin-syslog.8.md | 48 ++++++++++++++++
plugins/syslog.c | 97 +++++++++++++++++++++++++++++----
2 files changed, 134 insertions(+), 11 deletions(-)
diff --git a/docs/man/rpm-plugin-syslog.8.md b/docs/man/rpm-plugin-syslog.8.md
index 47a6bc549..08944c6b7 100644
--- a/docs/man/rpm-plugin-syslog.8.md
+++ b/docs/man/rpm-plugin-syslog.8.md
@@ -26,6 +26,54 @@ Configuration
See **rpm-plugins**(8) on how to control plugins in general.
+Output
+======
+
+The plugin uses **rpm** as its syslog identity.
+
+The package level output during transactions is as follows:
+
+_OPERATION_ _NEVRA_ [**(from:** _RELNEVRA_**)**]**:** _STATUS_
+
+_OPERATION_ is one of:
+
+- **cleanup**: cleanup of the previous version in **upgrade** or **downgrade**
+- **downgrade**: downgrade an installed package to an older version
+- **erase**: erase package from the system
+- **install**: install a new package on the system
+- **replace**: replace (obsolete) a previously installed package with another one
+- **restore**: restore permissions and similar on an installed package
+- **upgrade**: upgrade an installed package to a newer version
+
+_NEVRA_ identifies the transaction element being operated on.
+Note that operations **downgrade**, **replace** and **upgrade** consist of two
+elements: install of one package version and removal of another.
+In these cases, the related element identifier _RELNEVRA_ is indicated
+in parentheses after **from:**. _STATUS_ is one of **success** or **failure**.
+
+Examples
+========
+
+**journalctl -t rpm**
+: Inspect RPM transaction history on a systemd-based OS.
+
+**Package aaa upgrade from 1.2-1 to 2.0-1**
+```
+upgrade: aaa-2.0-1.noarch (from: aaa-1.2-1.noarch): success
+cleanup: aaa-1.2-1.noarch (from: aaa-2.0-1.noarch): success
+```
+
+**Package bbb 1.3-5 obsoleting aaa 1.2-1**
+```
+replace: bbb-1.3-5.noarch (from: aaa-1.2-1.noarch): success
+erase: aaa-1.2-1.noarch (from: bbb-1.3-5.noarch): success
+```
+
+**Package aaa 1.2-1 install failure**
+```
+install: aaa-1.2-1.noarch: failure
+```
+
SEE ALSO
========
diff --git a/plugins/syslog.c b/plugins/syslog.c
index 5db295f4b..dbcc018db 100644
--- a/plugins/syslog.c
+++ b/plugins/syslog.c
@@ -6,6 +6,7 @@
#include <rpm/rpmlog.h>
#include <rpm/rpmmacro.h>
+#include <rpm/rpmver.h>
#include <rpm/rpmstring.h>
#include <rpm/rpmts.h>
#include "rpmplugin.h"
@@ -16,6 +17,7 @@ struct logstat {
int logging;
unsigned int scriptfail;
unsigned int pkgfail;
+ rpmts ts;
loggerfunc log;
};
@@ -31,7 +33,6 @@ static void errlog(int prio, const char *fmt, ...)
static rpmRC syslog_init(rpmPlugin plugin, rpmts ts)
{
- /* XXX make this configurable? */
const char * log_ident = "rpm";
struct logstat * state = rcalloc(1, sizeof(*state));
char *target = rpmExpand("%{?__transaction_syslog_target}", NULL);
@@ -65,6 +66,7 @@ static rpmRC syslog_tsm_pre(rpmPlugin plugin, rpmts ts)
struct logstat * state = rpmPluginGetData(plugin);
/* Reset counters */
+ state->ts = ts;
state->scriptfail = 0;
state->pkgfail = 0;
@@ -103,15 +105,89 @@ static rpmRC syslog_tsm_post(rpmPlugin plugin, rpmts ts, int res)
return RPMRC_OK;
}
-static const char *getOp(rpmte te)
+static rpmte findDependent(rpmts ts, rpmte te)
{
+ rpmte dep = NULL;
+ rpmte p = NULL;
+ rpmtsi pi = rpmtsiInit(ts);
+ while ((p = rpmtsiNext(pi, 0)) != NULL) {
+ if (rpmteDependsOn(p) == te) {
+ dep = p;
+ break;
+ }
+ }
+ rpmtsiFree(pi);
+
+ return dep;
+}
+
+static int isObsolete(rpmte a, rpmte b)
+{
+ return strcmp(rpmteN(a), rpmteN(b));
+}
+
+static int isDowngrade(rpmte a, rpmte b)
+{
+ int downgrade = 0;
+ rpmver av = rpmverParse(rpmteEVR(a));
+ rpmver bv = rpmverParse(rpmteEVR(b));
+
+ if (av && bv && rpmverCmp(av, bv) < 0)
+ downgrade = 1;
+
+ rpmverFree(av);
+ rpmverFree(bv);
+ return downgrade;
+}
+
+static char *getOp(rpmts ts, rpmte te)
+{
+ char *ret = NULL;
+ const char *op = NULL;
+ rpmte dep = NULL;
+
switch (rpmteType(te)) {
- case TR_ADDED: return "install";
- case TR_REMOVED: return "erase";
- case TR_RPMDB: return "rpmdb";
- case TR_RESTORED: return "restore";
+ case TR_ADDED:
+ dep = findDependent(ts, te);
+ if (dep) {
+ if (isObsolete(te, dep)) {
+ op = "replace";
+ } else {
+ op = isDowngrade(te, dep) ? "downgrade" : "upgrade";
+ }
+ } else {
+ op = "install";
+ }
+ break;
+ case TR_REMOVED:
+ dep = rpmteDependsOn(te);
+ if (dep && !isObsolete(te, dep)) {
+ op = "cleanup";
+ } else {
+ op = "erase";
+ }
+ break;
+ case TR_RPMDB:
+ /* not an operation */
+ break;
+ case TR_RESTORED:
+ op = "restore";
+ break;
+ default:
+ op = "<unknown>";
+ break;
}
- return "<unknown>";
+
+ if (op) {
+ if (dep) {
+ rasprintf(&ret, "%s: %s (from: %s)", op,
+ rpmteNEVRA(te), rpmteNEVRA(dep));
+ } else {
+ rasprintf(&ret, "%s: %s", op, rpmteNEVRA(te));
+ }
+ }
+
+ return ret;
}
static rpmRC syslog_psm_post(rpmPlugin plugin, rpmte te, int res)
@@ -120,10 +196,8 @@ static rpmRC syslog_psm_post(rpmPlugin plugin, rpmte te, int res)
if (state->logging) {
int lvl = LOG_NOTICE;
- const char *op = getOp(te);
+ char *op = getOp(state->ts, te);
const char *outcome = "success";
- /* XXX: Permit configurable header queryformat? */
- const char *pkg = rpmteNEVRA(te);
if (res != RPMRC_OK) {
lvl = LOG_WARNING;
@@ -131,7 +205,8 @@ static rpmRC syslog_psm_post(rpmPlugin plugin, rpmte te, int res)
state->pkgfail++;
}
- state->log(lvl, "%s %s: %s", op, pkg, outcome);
+ state->log(lvl, "%s: %s", op, outcome);
+ free(op);
}
return RPMRC_OK;
}
--
2.54.0
diff -up rpm-4.19.1.1/docs/man/rpm-plugin-syslog.8.orig rpm-4.19.1.1/docs/man/rpm-plugin-syslog.8
--- rpm-4.19.1.1/docs/man/rpm-plugin-syslog.8.orig 2026-06-18 09:26:45.106337957 +0200
+++ rpm-4.19.1.1/docs/man/rpm-plugin-syslog.8 2026-06-18 09:26:48.072321034 +0200
@@ -1,32 +1,81 @@
-.\" Automatically generated by Pandoc 3.1.3
+.\" Automatically generated by Pandoc 3.1.11.1
.\"
-.\" Define V font for inline verbatim, using C font in formats
-.\" that render this, and otherwise B font.
-.ie "\f[CB]x\f[]"x" \{\
-. ftr V B
-. ftr VI BI
-. ftr VB B
-. ftr VBI BI
-.\}
-.el \{\
-. ftr V CR
-. ftr VI CI
-. ftr VB CB
-. ftr VBI CBI
-.\}
-.TH "RPM-SYSLOG" "8" "14 Apr 2016" "" ""
-.hy
+.TH "RPM\-SYSLOG" "8" "14 Apr 2016" "" ""
.SH NAME
-.PP
-rpm-plugin-syslog - Syslog plugin for the RPM Package Manager
+rpm\-plugin\-syslog \- Syslog plugin for the RPM Package Manager
.SH Description
-.PP
The plugin writes basic information about rpm transactions to the syslog
-- like transactions run and packages installed or removed.
+\- like transactions run and packages installed or removed.
.SH Configuration
+.TP
+\f[B]%__transaction_syslog_target\f[R]
+Specify target output for the plugin.
+Supported values are:
+.RS
+.IP \[bu] 2
+\f[B]syslog\f[R]: system log (default)
+.IP \[bu] 2
+\f[B]stderr\f[R]: standard error
+.RE
.PP
-There are currently no options for this plugin in particular.
-See \f[B]rpm-plugins\f[R](8) on how to control plugins in general.
-.SH SEE ALSO
+See \f[B]rpm\-plugins\f[R](8) on how to control plugins in general.
+.SH Output
+The plugin uses \f[B]rpm\f[R] as its syslog identity.
+.PP
+The package level output during transactions is as follows:
+.PP
+\f[I]OPERATION\f[R] \f[I]NEVRA\f[R] [\f[B](from:\f[R]
+\f[I]RELNEVRA\f[R]\f[B])\f[R]]\f[B]:\f[R] \f[I]STATUS\f[R]
.PP
-\f[B]rpm\f[R](8), \f[B]rpm-plugins\f[R](8)
+\f[I]OPERATION\f[R] is one of:
+.IP \[bu] 2
+\f[B]cleanup\f[R]: cleanup of the previous version in \f[B]upgrade\f[R]
+or \f[B]downgrade\f[R]
+.IP \[bu] 2
+\f[B]downgrade\f[R]: downgrade an installed package to an older version
+.IP \[bu] 2
+\f[B]erase\f[R]: erase package from the system
+.IP \[bu] 2
+\f[B]install\f[R]: install a new package on the system
+.IP \[bu] 2
+\f[B]replace\f[R]: replace (obsolete) a previously installed package
+with another one
+.IP \[bu] 2
+\f[B]restore\f[R]: restore permissions and similar on an installed
+package
+.IP \[bu] 2
+\f[B]upgrade\f[R]: upgrade an installed package to a newer version
+.PP
+\f[I]NEVRA\f[R] identifies the transaction element being operated on.
+Note that operations \f[B]downgrade\f[R], \f[B]replace\f[R] and
+\f[B]upgrade\f[R] consist of two elements: install of one package
+version and removal of another.
+In these cases, the related element identifier \f[I]RELNEVRA\f[R] is
+indicated in parentheses after \f[B]from:\f[R].
+\f[I]STATUS\f[R] is one of \f[B]success\f[R] or \f[B]failure\f[R].
+.SH Examples
+.TP
+\f[B]journalctl \-t rpm\f[R]
+Inspect RPM transaction history on a systemd\-based OS.
+.PP
+\f[B]Package aaa upgrade from 1.2\-1 to 2.0\-1\f[R]
+.IP
+.EX
+upgrade: aaa\-2.0\-1.noarch (from: aaa\-1.2\-1.noarch): success
+cleanup: aaa\-1.2\-1.noarch (from: aaa\-2.0\-1.noarch): success
+.EE
+.PP
+\f[B]Package bbb 1.3\-5 obsoleting aaa 1.2\-1\f[R]
+.IP
+.EX
+replace: bbb\-1.3\-5.noarch (from: aaa\-1.2\-1.noarch): success
+erase: aaa\-1.2\-1.noarch (from: bbb\-1.3\-5.noarch): success
+.EE
+.PP
+\f[B]Package aaa 1.2\-1 install failure\f[R]
+.IP
+.EX
+install: aaa\-1.2\-1.noarch: failure
+.EE
+.SH SEE ALSO
+\f[B]rpm\f[R](8), \f[B]rpm\-plugins\f[R](8)

View File

@ -27,7 +27,7 @@
%global rpmver 4.19.1.1
#global snapver rc1
%global baserelease 23
%global baserelease 25
%global sover 10
%global srcver %{rpmver}%{?snapver:-%{snapver}}
@ -178,6 +178,11 @@ rpm-4.19.x-multisig-verify-fixes.patch
rpm-4.19.x-nsswitch-enable.patch
0001-Fix-empty-password-field-in-passwd-group-causing-ent.patch
rpm-4.19.x-add-autosetup-C.patch
rpm-4.19.x-add-parkdb.patch
rpm-4.19.x-improve-syslog.patch
0001-Prevent-buffer-overruns-in-findPreambleTag-for-langu.patch
# These are not yet upstream
rpm-4.7.1-geode-i686.patch
@ -196,7 +201,8 @@ Requires(meta): %{name} = %{version}-%{release}
# >= 1.4.0 required for pgpVerifySignature2() and pgpPrtParams2()
Requires: rpm-sequoia%{_isa} >= 1.9.0
# Most systems should have a central package operations log
Recommends: rpm-plugin-audit
Requires(meta): (rpm-plugin-audit if audit)
Requires(meta): (rpm-plugin-syslog if syslog)
%endif
%description libs
@ -667,9 +673,19 @@ fi
%doc %{_defaultdocdir}/rpm/API/
%changelog
* Fri Feb 06 2026 Eduard Abdullin <eabdullin@almalinux.org> - 4.19.1.1-23.alma.1
* Sat Jun 20 2026 Eduard Abdullin <eabdullin@almalinux.org> - 4.19.1.1-25.alma.1
- Fix: Treat x86_64_v2 as x86_64 in architecture checks
* Fri Jun 19 2026 Michal Domonkos <mdomonko@redhat.com> - 4.19.1.1-25
- Apply forgotten patch for RHEL-169755
* Thu Jun 18 2026 Michal Domonkos <mdomonko@redhat.com> - 4.19.1.1-24
- Add support for %%autosetup -C (RHEL-141269)
- Add support for database parking (RHEL-126405)
- Make syslog plugin actually useful and also required (RHEL-155272)
- Require rpm-plugin-audit instead of just recommending (RHEL-139071)
- Fix buffer overruns with long language strings (RHEL-169755)
* Thu Feb 05 2026 Michal Domonkos <mdomonko@redhat.com> - 4.19.1.1-23
- Fix key import API to return NOTTRUSTED for disabled algorithms (RHEL-112394)