9 #include <talloc/talloc.h>
10 #include <pb-protocol/pb-protocol.h>
12 #include "device-handler.h"
17 #define MOUNT_BIN "/bin/mount"
19 struct device_handler {
20 struct discover_server *server;
22 struct device *devices;
26 struct discover_context {
29 struct udev_event *event;
30 struct device *device;
41 static struct boot_option options[] = {
45 .description = "meep description one",
46 .icon_file = "meep.one.png",
47 .boot_args = "root=/dev/sda1",
51 static struct device device = {
54 .description = "meep description",
55 .icon_file = "meep.png",
60 int device_handler_get_current_devices(struct device_handler *handler,
61 struct device **devices)
68 static int mkdir_recursive(const char *dir)
77 if (!stat(dir, &statbuf)) {
78 if (!S_ISDIR(statbuf.st_mode)) {
79 pb_log("%s: %s exists, but isn't a directory\n",
86 str = talloc_strdup(NULL, dir);
87 sep = strchr(*str == '/' ? str + 1 : str, '/');
91 /* terminate the path at sep */
95 if (mkdir(str, mode) && errno != EEXIST) {
96 pb_log("mkdir(%s): %s\n", str, strerror(errno));
103 /* reset dir to the full path */
105 sep = strchr(sep + 1, '/');
113 static void setup_device_links(struct discover_context *ctx)
120 .dir = "disk/by-uuid"
123 .env = "ID_FS_LABEL",
124 .dir = "disk/by-label"
131 for (link = links; link->env; link++) {
132 char *enc, *dir, *path;
135 value = udev_event_param(ctx->event, link->env);
139 enc = encode_label(ctx, value);
140 dir = join_paths(ctx, mount_base(), link->dir);
141 path = join_paths(ctx, dir, value);
143 if (!mkdir_recursive(dir)) {
145 if (symlink(ctx->mount_path, path)) {
146 pb_log("symlink(%s,%s): %s\n",
147 ctx->mount_path, path,
151 int i = ctx->n_links++;
152 ctx->links = talloc_realloc(ctx,
155 ctx->links[i] = path;
165 static int mount_device(struct discover_context *ctx)
167 const char *mountpoint;
172 if (!ctx->mount_path) {
173 mountpoint = mountpoint_for_device(ctx->device_path);
174 ctx->mount_path = talloc_strdup(ctx, mountpoint);
177 if (stat(ctx->mount_path, &statbuf)) {
178 if (mkdir(ctx->mount_path, 0755)) {
179 pb_log("couldn't create mount directory %s: %s\n",
180 ctx->mount_path, strerror(errno));
184 if (!S_ISDIR(statbuf.st_mode)) {
185 pb_log("mountpoint %s exists, but isn't a directory\n",
193 pb_log("%s: fork failed: %s\n", __func__, strerror(errno));
198 execl(MOUNT_BIN, MOUNT_BIN, ctx->device_path, ctx->mount_path,
203 if (waitpid(pid, &status, 0) == -1) {
204 pb_log("%s: waitpid failed: %s\n", __func__,
209 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
212 setup_device_links(ctx);
216 static int handle_add_event(struct device_handler *handler,
217 struct udev_event *event)
219 struct discover_context *ctx;
223 /* create our context */
224 ctx = talloc(NULL, struct discover_context);
226 ctx->mount_path = NULL;
230 devname = udev_event_param(ctx->event, "DEVNAME");
232 pb_log("no devname for %s?\n", event->device);
236 ctx->device_path = talloc_strdup(ctx, devname);
238 rc = mount_device(ctx);
240 pb_log("mount_device failed for %s\n", event->device);
250 static int handle_remove_event(struct device_handler *handler,
251 struct udev_event *event)
256 int device_handler_event(struct device_handler *handler,
257 struct udev_event *event)
261 switch (event->action) {
262 case UDEV_ACTION_ADD:
263 rc = handle_add_event(handler, event);
266 case UDEV_ACTION_REMOVE:
267 rc = handle_remove_event(handler, event);
274 struct device_handler *device_handler_init(struct discover_server *server)
276 struct device_handler *handler;
278 handler = talloc(NULL, struct device_handler);
279 handler->devices = NULL;
280 handler->n_devices = 0;
282 /* set up our mount point base */
283 mkdir_recursive(mount_base());
288 void device_handler_destroy(struct device_handler *devices)
290 talloc_free(devices);