Blame plugins/systemd_inhibit.c

2ff057
#include "system.h"
2ff057
2ff057
#include <dbus/dbus.h>
2ff057
#include <sys/types.h>
2ff057
#include <sys/stat.h>
2ff057
#include <unistd.h>
2ff057
#include <rpm/rpmlog.h>
2ff057
#include <rpm/rpmts.h>
2ff057
#include "lib/rpmplugin.h"
2ff057
2ff057
static int lock_fd = -1;
2ff057
2ff057
static int inhibit(void)
2ff057
{
2ff057
    DBusError err;
2ff057
    DBusConnection *bus = NULL;
2ff057
    DBusMessage *msg = NULL;
2ff057
    DBusMessage *reply = NULL;
2ff057
    int fd = -1;
2ff057
2ff057
    dbus_error_init(&err;;
2ff057
    bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err;;
2ff057
2ff057
    if (bus) {
2ff057
	msg = dbus_message_new_method_call("org.freedesktop.login1",
2ff057
					   "/org/freedesktop/login1",
2ff057
					   "org.freedesktop.login1.Manager",
2ff057
					   "Inhibit");
2ff057
    }
2ff057
2ff057
    if (msg) {
2ff057
	const char *what = "idle:sleep:shutdown";
2ff057
	const char *mode = "block";
2ff057
	const char *who = "RPM";
2ff057
	const char *reason = "Transaction running";
2ff057
2ff057
	dbus_message_append_args(msg,
2ff057
				 DBUS_TYPE_STRING, &what,
2ff057
				 DBUS_TYPE_STRING, &who,
2ff057
				 DBUS_TYPE_STRING, &reason,
2ff057
				 DBUS_TYPE_STRING, &mode,
2ff057
				 DBUS_TYPE_INVALID);
2ff057
2ff057
	reply = dbus_connection_send_with_reply_and_block(bus, msg, -1, &err;;
2ff057
	dbus_message_unref(msg);
2ff057
    }
2ff057
2ff057
    if (reply) {
2ff057
	dbus_message_get_args(reply, &err,
2ff057
			      DBUS_TYPE_UNIX_FD, &fd,
2ff057
			      DBUS_TYPE_INVALID);
2ff057
	dbus_message_unref(reply);
2ff057
    }
2ff057
    
2ff057
    if (dbus_error_is_set(&err)) {
2ff057
	rpmlog(RPMLOG_WARNING,
2ff057
	       "Unable to get systemd shutdown inhibition lock: %s\n",
2ff057
		err.message);
2ff057
	dbus_error_free(&err;;
2ff057
    }
2ff057
2ff057
    if (bus) {
2ff057
	dbus_connection_close(bus);
2ff057
	dbus_connection_unref(bus);
2ff057
    }
2ff057
2ff057
    return fd;
2ff057
}
2ff057
2ff057
static rpmRC systemd_inhibit_init(rpmPlugin plugin, rpmts ts)
2ff057
{
2ff057
    struct stat st;
2ff057
2ff057
    if (lstat("/run/systemd/system/", &st) == 0) {
2ff057
        if (S_ISDIR(st.st_mode)) {
2ff057
            return RPMRC_OK;
2ff057
        }
2ff057
    }
2ff057
2ff057
    return RPMRC_NOTFOUND;
2ff057
}
2ff057
2ff057
static rpmRC systemd_inhibit_tsm_pre(rpmPlugin plugin, rpmts ts)
2ff057
{
2ff057
    if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
2ff057
	return RPMRC_OK;
2ff057
2ff057
    lock_fd = inhibit();
2ff057
2ff057
    if (lock_fd >= 0) {
2ff057
	rpmlog(RPMLOG_DEBUG, "System shutdown blocked (fd %d)\n", lock_fd);
2ff057
    }
2ff057
2ff057
    return RPMRC_OK;
2ff057
}
2ff057
2ff057
static rpmRC systemd_inhibit_tsm_post(rpmPlugin plugin, rpmts ts, int res)
2ff057
{
2ff057
    if (lock_fd >= 0) {
2ff057
	close(lock_fd);
2ff057
	lock_fd = -1;
2ff057
	rpmlog(RPMLOG_DEBUG, "System shutdown unblocked\n");
2ff057
    }
2ff057
    return RPMRC_OK;
2ff057
}
2ff057
2ff057
struct rpmPluginHooks_s systemd_inhibit_hooks = {
2ff057
    .init = systemd_inhibit_init,
2ff057
    .tsm_pre = systemd_inhibit_tsm_pre,
2ff057
    .tsm_post = systemd_inhibit_tsm_post,
2ff057
};