149 lines
3.5 KiB
C
149 lines
3.5 KiB
C
#include "system.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <dbus/dbus.h>
|
|
#include <rpm/rpmlog.h>
|
|
#include <rpm/rpmstring.h>
|
|
#include <rpm/rpmts.h>
|
|
#include <rpm/rpmdb.h>
|
|
#include <rpm/rpmplugin.h>
|
|
|
|
struct dbus_announce_data {
|
|
DBusConnection * bus;
|
|
};
|
|
|
|
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 void dbus_announce_close_bus(struct dbus_announce_data * state)
|
|
{
|
|
if (state->bus) {
|
|
dbus_connection_close(state->bus);
|
|
dbus_connection_unref(state->bus);
|
|
state->bus = NULL;
|
|
}
|
|
}
|
|
|
|
static rpmRC open_dbus(rpmPlugin plugin, rpmts ts)
|
|
{
|
|
DBusError err;
|
|
int rc = 0;
|
|
int ignore = 0;
|
|
struct dbus_announce_data * state = rpmPluginGetData(plugin);
|
|
|
|
/* Already open */
|
|
if (state->bus)
|
|
return RPMRC_OK;
|
|
|
|
/* ...don't notify on test transactions */
|
|
if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
|
|
return RPMRC_OK;
|
|
|
|
/* ...don't notify on chroot transactions */
|
|
if (!rstreq(rpmtsRootDir(ts), "/"))
|
|
return RPMRC_OK;
|
|
|
|
dbus_error_init(&err);
|
|
|
|
state->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
|
|
if (dbus_error_is_set(&err))
|
|
goto 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))
|
|
goto err;
|
|
|
|
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != rc) {
|
|
dbus_announce_close_bus(state);
|
|
goto err;
|
|
}
|
|
return RPMRC_OK;
|
|
err:
|
|
ignore = dbus_error_has_name(&err, DBUS_ERROR_NO_SERVER) ||
|
|
dbus_error_has_name(&err, DBUS_ERROR_FILE_NOT_FOUND);
|
|
rpmlog(ignore ? RPMLOG_DEBUG : RPMLOG_WARNING,
|
|
"dbus_announce plugin: Error connecting to dbus (%s)\n",
|
|
err.message);
|
|
dbus_error_free(&err);
|
|
return RPMRC_OK;
|
|
}
|
|
|
|
static void dbus_announce_cleanup(rpmPlugin plugin)
|
|
{
|
|
struct dbus_announce_data * state = rpmPluginGetData(plugin);
|
|
dbus_announce_close_bus(state);
|
|
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;
|
|
char * dbcookie = NULL;
|
|
|
|
if (!state->bus)
|
|
return RPMRC_OK;
|
|
|
|
msg = dbus_message_new_signal("/org/rpm/Transaction", /* object name */
|
|
"org.rpm.Transaction", /* interface name */
|
|
name); /* signal name */
|
|
if (msg == NULL)
|
|
goto err;
|
|
|
|
dbcookie = rpmdbCookie(rpmtsGetRdb(ts));
|
|
rpm_tid_t tid = rpmtsGetTid(ts);
|
|
if (!dbus_message_append_args(msg,
|
|
DBUS_TYPE_STRING, &dbcookie,
|
|
DBUS_TYPE_UINT32, &tid,
|
|
DBUS_TYPE_INVALID))
|
|
goto err;
|
|
|
|
if (!dbus_connection_send(state->bus, msg, NULL))
|
|
goto err;
|
|
|
|
dbus_connection_flush(state->bus);
|
|
dbcookie = _free(dbcookie);
|
|
|
|
return RPMRC_OK;
|
|
|
|
err:
|
|
rpmlog(RPMLOG_WARNING,
|
|
"dbus_announce plugin: Error sending message (%s)\n",
|
|
name);
|
|
dbcookie = _free(dbcookie);
|
|
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,
|
|
};
|