summaryrefslogtreecommitdiff
path: root/udev_dbus.c
blob: 57685163c537c832616978ed5bd478f8ab3e8c49 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>

#include "udev_dbus.h"


/** variable for the connection the to system message bus or #NULL
 *  if we cannot connect or acquire the org.kernel.udev service
 */
static DBusConnection* sysbus_connection;

/** Disconnect from the system message bus */
void sysbus_disconnect(void)
{
        if (sysbus_connection == NULL)
                return;

        dbus_connection_disconnect(sysbus_connection);
        sysbus_connection = NULL;
}

/** Connect to the system message bus */
void sysbus_connect(void)
{
        DBusError error;

        /* Connect to a well-known bus instance, the system bus */
        dbus_error_init(&error);
        sysbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
        if (sysbus_connection == NULL) {
                dbg("cannot connect to system message bus, error %s: %s", 
                    error.name, error.message);
                dbus_error_free(&error);
                return;
        }

        /*  Acquire the org.kernel.udev service such that listeners
         *  know that the message is really from us and not from a
         *  random attacker. See the file udev_sysbus_policy.conf for
         *  details.
         *
         *  Note that a service can have multiple owners (though there
         *  is a concept of a primary owner for reception of messages)
         *  so no race is introduced if two copies of udev is running
         *  at the same time.
         */
        dbus_bus_acquire_service(sysbus_connection, "org.kernel.udev", 0, 
                                 &error);
        if (dbus_error_is_set(&error)) {
                printf("cannot acquire org.kernel.udev service, error %s: %s'",
                       error.name, error.message);
                sysbus_disconnect();
                return;
        }
}


/** Send out a signal that a device node is created
 *
 *  @param  dev                 udevice object
 *  @param  path                Sysfs path of device
 */
void sysbus_send_create(struct udevice *dev, const char *path)
{
        char filename[255];
        DBusMessage* message;
        DBusMessageIter iter;

        if (sysbus_connection == NULL)
                return;

        strncpy(filename, udev_root, sizeof(filename));
        strncat(filename, dev->name, sizeof(filename));

        /* object, interface, member */
        message = dbus_message_new_signal("/org/kernel/udev/NodeMonitor", 
                                          "org.kernel.udev.NodeMonitor",
                                          "NodeCreated");
        
        dbus_message_iter_init(message, &iter);
        dbus_message_iter_append_string(&iter, filename);
        dbus_message_iter_append_string(&iter, path);

        if ( !dbus_connection_send(sysbus_connection, message, NULL) )
                dbg("error sending d-bus signal");

        dbus_message_unref(message);
        
        dbus_connection_flush(sysbus_connection);
}

/** Send out a signal that a device node is deleted
 *
 *  @param  name                Name of the device node, e.g. /udev/sda1
 *  @param  path                Sysfs path of device
 */
void sysbus_send_remove(const char* name, const char *path)
{
        char filename[255];
        DBusMessage* message;
        DBusMessageIter iter;

        if (sysbus_connection == NULL)
                return;

        strncpy(filename, udev_root, sizeof(filename));
        strncat(filename, name, sizeof(filename));

        /* object, interface, member */
        message = dbus_message_new_signal("/org/kernel/udev/NodeMonitor", 
                                          "org.kernel.udev.NodeMonitor",
                                          "NodeDeleted");
        
        dbus_message_iter_init(message, &iter);
        dbus_message_iter_append_string(&iter, filename);
        dbus_message_iter_append_string(&iter, path);
        
        if ( !dbus_connection_send(sysbus_connection, message, NULL) )
                dbg("error sending d-bus signal");
        
        dbus_message_unref(message);

        dbus_connection_flush(sysbus_connection);
}