X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=devices%2Fpaths.c;h=2373c28f560555025d7b522733551b5cb3dffe22;hp=a1df5d27a452e6fb3ed522e79605d84cd86cc599;hb=2ce51d1e70aaf667be126b88a35b6210a45fb314;hpb=dbacb44c0ebb587b5cfcbbf84c770502c217473a diff --git a/devices/paths.c b/devices/paths.c index a1df5d2..2373c28 100644 --- a/devices/paths.c +++ b/devices/paths.c @@ -15,46 +15,104 @@ struct device_map { #define DEVICE_MAP_SIZE 32 static struct device_map device_map[DEVICE_MAP_SIZE]; -const char *mountpoint_for_device(const char *dev_path) +char *encode_label(const char *label) { + char *str, *c; int i; - const char *basename; - /* shorten '/dev/foo' to 'foo' */ - basename = strrchr(dev_path, '/'); - if (basename) - basename++; - else - basename = dev_path; + /* 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, basename)) + 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_path); - asprintf(&device_map[i].mnt, "%s/%s", mount_base, basename); + 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_mountpoint) +char *resolve_path(const char *path, const char *current_dev) { char *ret; const char *devpath, *sep; sep = strchr(path, ':'); if (!sep) { - devpath = current_mountpoint; - asprintf(&ret, "%s/%s", devpath, path); + devpath = mountpoint_for_device(current_dev); + ret = join_paths(devpath, path); } else { - /* copy just the device name into tmp */ - char *dev = strndup(path, sep - path); + /* 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); - asprintf(&ret, "%s/%s", devpath, sep + 1); + ret = join_paths(devpath, sep + 1); + free(dev); + free(tmp); } return ret; @@ -67,3 +125,17 @@ void set_mount_base(const char *path) 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; +} +