From 32e6a41f33e5576716b351bd473a27939fe94fa1 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Mon, 15 Dec 2008 15:22:34 +1100 Subject: Initial support for multiple UIs Move the device discovery code from separate udev helpers to a single process to listen on two sockets: one SOCK_DGRAM for incoming udev events, and one SOCK_STREAM for UIs to connect. Initial support for client/server infrastructure, still need to wire-up the udev messages. Signed-off-by: Jeremy Kerr --- discover/paths.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 discover/paths.c (limited to 'discover/paths.c') diff --git a/discover/paths.c b/discover/paths.c new file mode 100644 index 0000000..2373c28 --- /dev/null +++ b/discover/paths.c @@ -0,0 +1,141 @@ +#define _GNU_SOURCE + +#include +#include +#include + +#include "paths.h" + +static char *mount_base; + +struct device_map { + char *dev, *mnt; +}; + +#define DEVICE_MAP_SIZE 32 +static struct device_map device_map[DEVICE_MAP_SIZE]; + +char *encode_label(const char *label) +{ + char *str, *c; + int i; + + /* the label can be expanded by up to four times */ + str = malloc(strlen(label) * 4 + 1); + c = str; + + for (i = 0; i < strlen(label); i++) { + + if (label[i] == '/' || label[i] == '\\') { + sprintf(c, "\\x%02x", label[i]); + c += 4; + continue; + } + + *(c++) = label[i]; + } + + *c = '\0'; + + return str; +} + +char *parse_device_path(const char *dev_str, const char *cur_dev) +{ + char *dev, tmp[256], *enc; + + if (!strncasecmp(dev_str, "uuid=", 5)) { + asprintf(&dev, "/dev/disk/by-uuid/%s", dev_str + 5); + return dev; + } + + if (!strncasecmp(dev_str, "label=", 6)) { + enc = encode_label(dev_str + 6); + asprintf(&dev, "/dev/disk/by-label/%s", enc); + free(enc); + return dev; + } + + /* normalise '/dev/foo' to 'foo' for easy comparisons, we'll expand + * back before returning. + */ + if (!strncmp(dev_str, "/dev/", 5)) + dev_str += 5; + + /* PS3 hack: if we're reading from a ps3dx device, and we refer to + * a sdx device, remap to ps3dx */ + if (cur_dev && !strncmp(cur_dev, "/dev/ps3d", 9) + && !strncmp(dev_str, "sd", 2)) { + snprintf(tmp, 255, "ps3d%s", dev_str + 2); + dev_str = tmp; + } + + return join_paths("/dev", dev_str); +} + +const char *mountpoint_for_device(const char *dev) +{ + int i; + + if (!strncmp(dev, "/dev/", 5)) + dev += 5; + + /* check existing entries in the map */ + for (i = 0; (i < DEVICE_MAP_SIZE) && device_map[i].dev; i++) + if (!strcmp(device_map[i].dev, dev)) + return device_map[i].mnt; + + if (i == DEVICE_MAP_SIZE) + return NULL; + + device_map[i].dev = strdup(dev); + device_map[i].mnt = join_paths(mount_base, dev); + return device_map[i].mnt; +} + +char *resolve_path(const char *path, const char *current_dev) +{ + char *ret; + const char *devpath, *sep; + + sep = strchr(path, ':'); + if (!sep) { + devpath = mountpoint_for_device(current_dev); + ret = join_paths(devpath, path); + } else { + /* parse just the device name into dev */ + char *tmp, *dev; + tmp = strndup(path, sep - path); + dev = parse_device_path(tmp, current_dev); + + devpath = mountpoint_for_device(dev); + ret = join_paths(devpath, sep + 1); + + free(dev); + free(tmp); + } + + return ret; +} + +void set_mount_base(const char *path) +{ + if (mount_base) + free(mount_base); + mount_base = strdup(path); +} + +char *join_paths(const char *a, const char *b) +{ + char *full_path; + + full_path = malloc(strlen(a) + strlen(b) + 2); + + strcpy(full_path, a); + if (b[0] != '/' && a[strlen(a) - 1] != '/') + strcat(full_path, "/"); + strcat(full_path, b); + + return full_path; +} + -- cgit v1.2.1