#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;
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;
+}
+