diff --git a/doc/Makefile.am b/doc/Makefile.am index 09a77ef06f..cad361fde5 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -21,6 +21,7 @@ man_man8_DATA += rpm-plugin-audit.8 endif if DBUS man_man8_DATA += rpm-plugin-systemd-inhibit.8 +man_man8_DATA += rpm-plugin-dbus-announce.8 endif if IMA man_man8_DATA += rpm-plugin-ima.8 diff --git a/doc/rpm-plugin-dbus-announce.8 b/doc/rpm-plugin-dbus-announce.8 new file mode 100644 index 0000000000..5d6c419101 --- /dev/null +++ b/doc/rpm-plugin-dbus-announce.8 @@ -0,0 +1,26 @@ +'\" t +.TH "RPM-DBUS-ANNOUNCE" "8" "03 Jun 2020" "Red Hat, Inc." +.SH NAME +rpm-plugin-dbus-announce \- DBus plugin for the RPM Package Manager + +.SH Description + +The plugin writes basic information about rpm transactions to the +system dbus - like packages installed or removed. Other programms can +subscribe to the signals to be notified of the packages on the system +change. + +.SH DBus Signals + +Sends \fBStartTransaction\fP and \fBEndTransaction\fP messages from the +\fB/org/rpm/Transaction\fP object with the \fBorg.rpm.Transaction\fP interface. + +.SH Configuration + +There are currently no options for this plugin in particular. See +.BR rpm-plugins (8) +on how to control plugins in general. + +.SH SEE ALSO +.IR dbus-monitor (1) +.IR rpm-plugins (8) diff --git a/macros.in b/macros.in index 5778a1f585..9bd123c029 100644 --- a/macros.in +++ b/macros.in @@ -1183,6 +1183,7 @@ package or when debugging this package.\ %__transaction_fsverity %{__plugindir}/fsverity.so %__transaction_prioreset %{__plugindir}/prioreset.so %__transaction_audit %{__plugindir}/audit.so +%__transaction_dbus_announce %{__plugindir}/dbus_announce.so #------------------------------------------------------------------------------ # Macros for further automated spec %setup and patch application diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 963d53db48..c0c0daa607 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -27,6 +27,14 @@ systemd_inhibit_la_SOURCES = systemd_inhibit.c systemd_inhibit_la_CPPFLAGS = $(AM_CPPFLAGS) @DBUS_CFLAGS@ systemd_inhibit_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la @DBUS_LIBS@ plugins_LTLIBRARIES += systemd_inhibit.la + +dbus_announce_la_SOURCES = dbus_announce.c +dbus_announce_la_CPPFLAGS = $(AM_CPPFLAGS) @DBUS_CFLAGS@ +dbus_announce_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la @DBUS_LIBS@ +plugins_LTLIBRARIES += dbus_announce.la + +dbus_confdir=$(sysconfdir)/dbus-1/system.d/ +dbus_conf_DATA = org.rpm.conf endif prioreset_la_SOURCES = prioreset.c diff --git a/plugins/dbus_announce.c b/plugins/dbus_announce.c new file mode 100644 index 0000000000..1fa8c76a4b --- /dev/null +++ b/plugins/dbus_announce.c @@ -0,0 +1,143 @@ +#include "system.h" + +#include +#include +#include +#include +#include +#include +#include +#include "lib/rpmplugin.h" + +struct dbus_announce_data { + DBusConnection * bus; + int logging; + int old_dboffset; +}; + +static rpmRC dbus_announce_init(rpmPlugin plugin, rpmts ts) +{ + struct dbus_announce_data * state = rcalloc(1, sizeof(*state)); + rpmPluginSetData(plugin, state); + return RPMRC_OK; +} + +static rpmRC open_dbus(rpmPlugin plugin, rpmts ts) +{ + struct stat st; + DBusError err; + int rc = 0; + struct dbus_announce_data * state = rpmPluginGetData(plugin); + + /* Assume we are logging but... */ + state->logging = 1; + + /* ...don't log test transactions */ + if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS)) + state->logging = 0; + + /* ...don't log chroot transactions */ + if (!rstreq(rpmtsRootDir(ts), "/")) + state->logging = 0; + + /* Don't open */ + if (!state->logging || state->bus) + return RPMRC_OK; + + if (lstat("/run/systemd/system/", &st) == 0) { + if (S_ISDIR(st.st_mode)) { + // initialise the error value + dbus_error_init(&err); + + state->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err); + if (dbus_error_is_set(&err)) { + fprintf(stderr, "Connection Error (%s)\n", err.message); + dbus_error_free(&err); + } + if (state->bus) { + rc = dbus_bus_request_name(state->bus, "org.rpm.announce", + DBUS_NAME_FLAG_REPLACE_EXISTING , &err); + } + if (dbus_error_is_set(&err)) { + //fprintf(stderr, "Name Error (%s)\n", err.message); + dbus_error_free(&err); + } + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != rc) { + dbus_connection_close(state->bus); + dbus_connection_unref(state->bus); + state->bus = NULL; + state->logging = 0; + return RPMRC_NOTFOUND; + } + return RPMRC_OK; + } + } + + return RPMRC_NOTFOUND; +} + +static void dbus_announce_cleanup(rpmPlugin plugin) +{ + struct dbus_announce_data * state = rpmPluginGetData(plugin); + if (state->bus) { + dbus_connection_close(state->bus); + dbus_connection_unref(state->bus); + } + free(state); +} + +static rpmRC send_ts_message(rpmPlugin plugin, + const char * name, + rpmts ts, + int res) +{ + struct dbus_announce_data * state = rpmPluginGetData(plugin); + DBusMessage* msg; + dbus_uint32_t serial = 0; + char * dbcookie; + + if (!state->logging) { + return RPMRC_OK; + } + + msg = dbus_message_new_signal("/org/rpm/Transaction", // object name + "org.rpm.Transaction", // interface name + name); // name of the signal + if (NULL == msg) { + return RPMRC_FAIL; + } + + dbcookie = rpmdbCookie(rpmtsGetRdb(ts)); + if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &dbcookie)) { + return RPMRC_FAIL; + } + dbcookie = _free(dbcookie); + + if (!dbus_connection_send(state->bus, msg, &serial)) { + return RPMRC_FAIL; + } + dbus_connection_flush(state->bus); + return RPMRC_OK; +} + +static rpmRC dbus_announce_tsm_pre(rpmPlugin plugin, rpmts ts) +{ + int rc; + + rc = open_dbus(plugin, ts); + if (rc != RPMRC_OK) + return rc; + return send_ts_message(plugin, "StartTransaction", ts, RPMRC_OK); +} + +static rpmRC dbus_announce_tsm_post(rpmPlugin plugin, rpmts ts, int res) +{ + return send_ts_message(plugin, "EndTransaction", ts, res); +} + +struct rpmPluginHooks_s dbus_announce_hooks = { + .init = dbus_announce_init, + .cleanup = dbus_announce_cleanup, + .tsm_pre = dbus_announce_tsm_pre, + .tsm_post = dbus_announce_tsm_post, +}; diff --git a/plugins/org.rpm.conf b/plugins/org.rpm.conf new file mode 100644 index 0000000000..7def6d506a --- /dev/null +++ b/plugins/org.rpm.conf @@ -0,0 +1,10 @@ + + + + + + + +