9 #include <sys/socket.h>
10 #include <sys/types.h>
14 #include <talloc/talloc.h>
15 #include <waiter/waiter.h>
16 #include <system/system.h>
20 #include "pb-discover.h"
21 #include "device-handler.h"
23 #define PBOOT_DEVICE_SOCKET "/tmp/petitboot.udev"
25 #define max(a, b) ((a) > (b) ? (a) : (b))
28 struct device_handler *handler;
32 static void udev_print_event(struct event *event)
34 const char *action, *params[] = {
45 action = event->action == EVENT_ACTION_ADD ? "add" : "remove";
47 pb_log("udev %s event:\n", action);
48 pb_log("\tdevice: %s\n", event->device);
50 for (i = 0; params[i]; i++)
51 pb_log("\t%-12s => %s\n",
52 params[i], event_get_param(event, params[i]));
55 static void udev_handle_message(struct udev *udev, char *buf, int len)
61 event = talloc(udev, struct event);
62 event->type = EVENT_TYPE_UDEV;
66 result = event_parse_ad_message(event, buf, len);
71 udev_print_event(event);
73 /* Ignore ram, loop, and devices with no DEVNAME. */
75 devpath = event_get_param(event, "DEVPATH");
77 if (event_get_param(event, "DEVNAME")
78 && !strstr(devpath, "virtual/block/loop")
79 && !strstr(devpath, "virtual/block/ram")) {
80 device_handler_event(udev->handler, event);
88 static int udev_process(void *arg)
90 struct udev *udev = arg;
94 len = recvfrom(udev->socket, buf, sizeof(buf), 0, NULL, NULL);
97 pb_log("udev socket read failed: %s", strerror(errno));
104 udev_handle_message(udev, buf, len);
109 static int udev_destructor(void *p)
111 struct udev *udev = p;
113 if (udev->socket >= 0)
119 struct udev *udev_init(struct waitset *waitset, struct device_handler *handler)
121 struct sockaddr_un addr;
124 unlink(PBOOT_DEVICE_SOCKET);
126 udev = talloc(NULL, struct udev);
128 udev->handler = handler;
130 udev->socket = socket(PF_UNIX, SOCK_DGRAM, 0);
131 if (udev->socket < 0) {
132 pb_log("Error creating udev socket: %s\n", strerror(errno));
136 talloc_set_destructor(udev, udev_destructor);
138 memset(&addr, 0, sizeof addr);
139 addr.sun_family = AF_UNIX;
140 strcpy(addr.sun_path, PBOOT_DEVICE_SOCKET);
142 if (bind(udev->socket, (struct sockaddr *)&addr, sizeof(addr))) {
143 pb_log("Error binding udev socket: %s\n", strerror(errno));
147 waiter_register(waitset, udev->socket, WAIT_IN, udev_process, udev);
149 pb_log("%s: waiting on %s\n", __func__, PBOOT_DEVICE_SOCKET);
158 int udev_trigger(struct udev __attribute__((unused)) *udev)
160 const char *cmd[] = {
161 pb_system_apps.udevadm,
163 "--subsystem-match=block",
169 rc = pb_run_cmd(cmd, 1, 0);
172 pb_log("udev trigger failed: %d (%d)\n", rc, WEXITSTATUS(rc));
174 return WEXITSTATUS(rc);
177 void udev_destroy(struct udev *udev)