mirror of
https://github.com/systemd/systemd.git
synced 2024-12-23 21:35:11 +03:00
[PATCH] D-BUS patch for udev-008
Attached is a patch against udev-008 to send out a D-BUS message when a device node is added or removed. Using D-BUS lingo, udev acquires the org.kernel.udev service and sends out a NodeCreated or NodeDeleted signal on the org.kernel.udev.NodeMonitor interface. Each signal carries two parameters: the node in question and the corresponding sysfs path. [Note: the D-BUS concepts of service, interface, object can be a bit confusing at first glance] An example program listening for these messages looks like this #!/usr/bin/python import dbus import gtk def udev_signal_received(dbus_iface, member, service, object_path, message): [filename, sysfs_path] = message.get_args_list() if member=='NodeCreated': print 'Node %s created for %s'%(filename, sysfs_path) elif member=='NodeDeleted': print 'Node %s deleted for %s'%(filename, sysfs_path) def main(): bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) bus.add_signal_receiver(udev_signal_received, 'org.kernel.udev.NodeMonitor', # interface 'org.kernel.udev', # service '/org/kernel/udev/NodeMonitor') # object gtk.mainloop() if __name__ == '__main__': main() and this is the output when hot-plugging some usb-storage. [david@laptop udev-008]$ ~/node_monitor.py Node /udev/sda created for /block/sda Node /udev/sda1 created for /block/sda/sda1 Node /udev/sda1 deleted for /block/sda/sda1 Node /udev/sda deleted for /block/sda The patch requires D-BUS 0.20 or later while the python example program requires D-BUS from CVS as I only recently applied a patch against the python bindings.
This commit is contained in:
parent
3d150dfb28
commit
5aebfbcb62
29
Makefile
29
Makefile
@ -20,6 +20,10 @@
|
||||
# Leave this set to `false' for production use.
|
||||
DEBUG = false
|
||||
|
||||
# Set the following to `true' to make udev emit a D-BUS signal when a
|
||||
# new node is created.
|
||||
USE_DBUS = true
|
||||
|
||||
|
||||
ROOT = udev
|
||||
VERSION = 008_bk
|
||||
@ -34,6 +38,7 @@ etcdir = ${prefix}/etc
|
||||
sbindir = ${exec_prefix}/sbin
|
||||
mandir = ${prefix}/usr/share/man
|
||||
hotplugdir = ${etcdir}/hotplug.d/default
|
||||
dbusdir = ${etcdir}/dbus-1/system.d
|
||||
configdir = ${etcdir}/udev/
|
||||
srcdir = .
|
||||
|
||||
@ -138,6 +143,13 @@ endif
|
||||
|
||||
CFLAGS += -I$(PWD)/libsysfs
|
||||
|
||||
ifeq ($(USE_DBUS), true)
|
||||
CFLAGS += -DUSE_DBUS
|
||||
CFLAGS += $(shell pkg-config --cflags dbus-1)
|
||||
LIB_OBJS += $(shell pkg-config --libs-only-l dbus-1)
|
||||
endif
|
||||
|
||||
|
||||
all: $(ROOT)
|
||||
@for target in $(EXTRAS) ; do \
|
||||
echo $$target ; \
|
||||
@ -240,7 +252,20 @@ small_release: $(DISTFILES) clean
|
||||
@echo "Built $(RELEASE_NAME).tar.gz"
|
||||
|
||||
|
||||
install: all
|
||||
ifeq ($(USE_DBUS), true)
|
||||
install-dbus-policy:
|
||||
$(INSTALL) -d $(DESTDIR)$(dbusdir)
|
||||
$(INSTALL_DATA) udev_sysbus_policy.conf $(DESTDIR)$(dbusdir)
|
||||
uninstall-dbus-policy:
|
||||
- rm $(DESTDIR)$(dbusdir)/udev_sysbus_policy.conf
|
||||
else
|
||||
install-dbus-policy:
|
||||
-
|
||||
uninstall-dbus-policy:
|
||||
-
|
||||
endif
|
||||
|
||||
install: install-dbus-policy all
|
||||
$(INSTALL) -d $(DESTDIR)$(udevdir)
|
||||
$(INSTALL) -d $(DESTDIR)$(configdir)
|
||||
$(INSTALL) -d $(DESTDIR)$(hotplugdir)
|
||||
@ -257,7 +282,7 @@ install: all
|
||||
-C $$target $@ ; \
|
||||
done ; \
|
||||
|
||||
uninstall:
|
||||
uninstall: uninstall-dbus-policy
|
||||
- rm $(hotplugdir)/udev.hotplug
|
||||
- rm $(configdir)/udev.permissions
|
||||
- rm $(configdir)/udev.rules
|
||||
|
1
TODO
1
TODO
@ -21,7 +21,6 @@ greg@kroah.com
|
||||
will have an upgrade path.
|
||||
- do early boot logic (putting udev into initramfs, handle pivot-root,
|
||||
etc.)
|
||||
- add hooks to call D-BUS when new node is created or removed
|
||||
- lots of other stuff...
|
||||
- actually use the BUS= value to determine where the LABEL rule should look
|
||||
(right now it's ignored, and we only look in the current sysfs directory.)
|
||||
|
42
udev-add.c
42
udev-add.c
@ -100,6 +100,42 @@ static int create_path(char *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_DBUS
|
||||
/** Send out a signal that a device node is created
|
||||
*
|
||||
* @param dev udevice object
|
||||
* @param path Sysfs path of device
|
||||
*/
|
||||
static 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);
|
||||
}
|
||||
#endif /* USE_DBUS */
|
||||
|
||||
/*
|
||||
* we possibly want to add some symlinks here
|
||||
* only numeric owner/group id's are supported
|
||||
@ -323,6 +359,12 @@ int udev_add_device(char *path, char *subsystem)
|
||||
dbg("name='%s'", dev.name);
|
||||
retval = create_node(&dev);
|
||||
|
||||
#ifdef USE_DBUS
|
||||
if (retval == 0) {
|
||||
sysbus_send_create(&dev, path);
|
||||
}
|
||||
#endif /* USE_DBUS */
|
||||
|
||||
exit:
|
||||
if (class_dev)
|
||||
sysfs_close_class_device(class_dev);
|
||||
|
@ -100,6 +100,42 @@ static int delete_node(struct udevice *dev)
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef USE_DBUS
|
||||
/** 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
|
||||
*/
|
||||
static 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);
|
||||
}
|
||||
#endif /* USE_DBUS */
|
||||
|
||||
/*
|
||||
* Look up the sysfs path in the database to see if we have named this device
|
||||
* something different from the kernel name. If we have, us it. If not, use
|
||||
@ -122,5 +158,10 @@ int udev_remove_device(char *path, char *subsystem)
|
||||
|
||||
dbg("name is '%s'", dev->name);
|
||||
udevdb_delete_dev(path);
|
||||
|
||||
#ifdef USE_DBUS
|
||||
sysbus_send_remove(name, device);
|
||||
#endif /* USE_DBUS */
|
||||
|
||||
return delete_node(dev);
|
||||
}
|
||||
|
64
udev.c
64
udev.c
@ -63,6 +63,60 @@ static inline char *get_seqnum(void)
|
||||
return seqnum;
|
||||
}
|
||||
|
||||
#ifdef USE_DBUS
|
||||
|
||||
/** Global variable for the connection the to system message bus or #NULL
|
||||
* if we cannot connect or acquire the org.kernel.udev service
|
||||
*/
|
||||
DBusConnection* sysbus_connection;
|
||||
|
||||
/** Disconnect from the system message bus */
|
||||
static void sysbus_disconnect()
|
||||
{
|
||||
if (sysbus_connection == NULL)
|
||||
return;
|
||||
|
||||
dbus_connection_disconnect(sysbus_connection);
|
||||
sysbus_connection = NULL;
|
||||
}
|
||||
|
||||
/** Connect to the system message bus */
|
||||
static void sysbus_connect()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* USE_DBUS */
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
char *action;
|
||||
@ -111,6 +165,11 @@ int main(int argc, char **argv, char **envp)
|
||||
/* initialize our configuration */
|
||||
udev_init_config();
|
||||
|
||||
#ifdef USE_DBUS
|
||||
/* connect to the system message bus */
|
||||
sysbus_connect();
|
||||
#endif /* USE_DBUS */
|
||||
|
||||
/* initialize udev database */
|
||||
retval = udevdb_init(UDEVDB_DEFAULT);
|
||||
if (retval != 0) {
|
||||
@ -133,6 +192,11 @@ int main(int argc, char **argv, char **envp)
|
||||
}
|
||||
udevdb_exit();
|
||||
|
||||
#ifdef USE_DBUS
|
||||
/* disconnect from the system message bus */
|
||||
sysbus_disconnect();
|
||||
#endif /* USE_DBUS */
|
||||
|
||||
exit:
|
||||
return retval;
|
||||
}
|
||||
|
9
udev.h
9
udev.h
@ -93,4 +93,13 @@ extern char udev_config_filename[PATH_MAX+NAME_MAX];
|
||||
extern char udev_rules_filename[PATH_MAX+NAME_MAX];
|
||||
extern char default_mode_str[NAME_MAX];
|
||||
|
||||
#ifdef USE_DBUS
|
||||
|
||||
#define DBUS_API_SUBJECT_TO_CHANGE
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
extern DBusConnection* sysbus_connection;
|
||||
|
||||
#endif /* USE_DBUS */
|
||||
|
||||
#endif
|
||||
|
23
udev_sysbus_policy.conf
Normal file
23
udev_sysbus_policy.conf
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE busconfig PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<busconfig>
|
||||
|
||||
<!-- This configuration file specifies the required security policies
|
||||
for udev to work. -->
|
||||
|
||||
<!-- Only root can own the udev service and only root can use the
|
||||
org.kernel.udev.NodeMonitor interface to send signals -->
|
||||
<policy user="root">
|
||||
<allow own="org.kernel.udev"/>
|
||||
|
||||
<allow send_interface="org.kernel.udev.NodeMonitor"/>
|
||||
</policy>
|
||||
|
||||
<!-- Allow anyone to listen to the org.kernel.udev.NodeMonitor interface
|
||||
for messages send from the owner of the org.kernel.udev service -->
|
||||
<policy context="default">
|
||||
<allow receive_interface="org.kernel.udev.NodeMonitor"/>
|
||||
</policy>
|
||||
</busconfig>
|
||||
|
Loading…
Reference in New Issue
Block a user