#define buf_size 1024
-static const char *mountpoint;
+static const char *devpath;
static int param_is_ignored(const char *param)
{
/* if there's no space, it's only a kernel image with no params */
if (!pos) {
- opt->boot_image_file = resolve_path(config, mountpoint);
+ opt->boot_image_file = resolve_path(config, devpath);
opt->description = strdup(config);
return 1;
}
*pos = 0;
- opt->boot_image_file = resolve_path(config, mountpoint);
+ opt->boot_image_file = resolve_path(config, devpath);
cmdline = malloc(buf_size);
*cmdline = 0;
free(cmdline);
cmdline = tmp;
- opt->initrd_file = resolve_path(initrd, mountpoint);
+ opt->initrd_file = resolve_path(initrd, devpath);
}
if (root) {
}
}
-static int parse(const char *devicepath, const char *_mountpoint)
+static int parse(const char *device)
{
char *filepath, *buf;
int fd, len, rc = 0;
struct stat stat;
struct device *dev;
- mountpoint = _mountpoint;
+ devpath = device;
- filepath = join_paths(mountpoint, "/etc/kboot.conf");
+ filepath = resolve_path("/etc/kboot.conf", devpath);
fd = open(filepath, O_RDONLY);
if (fd < 0)
dev = malloc(sizeof(*dev));
memset(dev, 0, sizeof(*dev));
- dev->id = strdup(devicepath);
+ dev->id = strdup(device);
dev->icon_file = strdup(generic_icon_file(guess_device_type()));
parse_buf(dev, buf);
#include "parser.h"
#include "params.h"
+#include "paths.h"
#include <stdlib.h>
#include <stdio.h>
static struct boot_option *cur_opt;
static struct device *dev;
-static const char *mountpoint;
+static const char *devpath;
int device_added;
int check_and_add_device(struct device *dev)
opt->description = strdup(value);
else if (streq(name, "image"))
- opt->boot_image_file = join_paths(mountpoint, value);
+ opt->boot_image_file = resolve_path(value, devpath);
else if (streq(name, "icon"))
- opt->icon_file = join_paths(mountpoint, value);
+ opt->icon_file = resolve_path(value, devpath);
else if (streq(name, "initrd"))
- opt->initrd_file = join_paths(mountpoint, value);
+ opt->initrd_file =resolve_path(value, devpath);
else if (streq(name, "args"))
opt->boot_args = strdup(value);
dev->description = strdup(value);
else if (streq(name, "icon"))
- dev->icon_file = join_paths(mountpoint, value);
+ dev->icon_file = resolve_path(value, devpath);
}
static int parameter(char *param_name, char *param_value)
}
-int parse(const char *devicepath, const char *_mountpoint)
+int parse(const char *device)
{
char *filepath;
int rc;
- mountpoint = _mountpoint;
-
- filepath = join_paths(mountpoint, conf_filename);
+ filepath = resolve_path(conf_filename, device);
cur_opt = NULL;
dev = malloc(sizeof(*dev));
memset(dev, 0, sizeof(*dev));
- dev->id = strdup(devicepath);
+ dev->id = strdup(device);
rc = pm_process(filepath, section, parameter);
if (!rc)
then
rootdev=$(cat "$dir/rootdev")
fi
- ./parser-test "$dir" $rootdev 2>/dev/null |
+ ./parser-test "$dir" /dev/$rootdev 2>/dev/null |
diff -u "$dir/expected-output" -
}
-[dev 0] id: ps3da1
+[dev 0] id: /dev/ps3da1
[dev 0] name: (null)
[dev 0] description: (null)
[dev 0] boot_image: /usr/share/petitboot/artwork/hdd.png
[opt 0] name: live
[opt 0] description: /casper/vmlinux root=/dev/ram0 initrd=/casper/initrd.gz file=/cdrom/preseed/ubuntu.seed boot=casper quiet splash --
-[opt 0] boot_image: devices/parser-tests/001/ps3da1//casper/vmlinux
-[opt 0] initrd: devices/parser-tests/001/ps3da1//casper/initrd.gz
+[opt 0] boot_image: devices/parser-tests/001/ps3da1/casper/vmlinux
+[opt 0] initrd: devices/parser-tests/001/ps3da1/casper/initrd.gz
[opt 0] boot_args: root=/dev/ram0 initrd=/casper/initrd.gz file=/cdrom/preseed/ubuntu.seed boot=casper quiet splash --
[opt 1] name: live_nosplash
[opt 1] description: /casper/vmlinux root=/dev/ram0 initrd=/casper/initrd.gz file=/cdrom/preseed/ubuntu.seed boot=casper quiet --
-[opt 1] boot_image: devices/parser-tests/001/ps3da1//casper/vmlinux
-[opt 1] initrd: devices/parser-tests/001/ps3da1//casper/initrd.gz
+[opt 1] boot_image: devices/parser-tests/001/ps3da1/casper/vmlinux
+[opt 1] initrd: devices/parser-tests/001/ps3da1/casper/initrd.gz
[opt 1] boot_args: root=/dev/ram0 initrd=/casper/initrd.gz file=/cdrom/preseed/ubuntu.seed boot=casper quiet --
[opt 2] name: driverupdates
[opt 2] description: /casper/vmlinux root=/dev/ram0 initrd=/casper/initrd.gz file=/cdrom/preseed/ubuntu.seed boot=casper debian-installer/driver-update=true quiet splash --
-[opt 2] boot_image: devices/parser-tests/001/ps3da1//casper/vmlinux
-[opt 2] initrd: devices/parser-tests/001/ps3da1//casper/initrd.gz
+[opt 2] boot_image: devices/parser-tests/001/ps3da1/casper/vmlinux
+[opt 2] initrd: devices/parser-tests/001/ps3da1/casper/initrd.gz
[opt 2] boot_args: root=/dev/ram0 initrd=/casper/initrd.gz file=/cdrom/preseed/ubuntu.seed boot=casper debian-installer/driver-update=true quiet splash --
[opt 3] name: check
[opt 3] description: /casper/vmlinux root=/dev/ram0 initrd=/casper/initrd.gz boot=casper integrity-check quiet splash --
-[opt 3] boot_image: devices/parser-tests/001/ps3da1//casper/vmlinux
-[opt 3] initrd: devices/parser-tests/001/ps3da1//casper/initrd.gz
+[opt 3] boot_image: devices/parser-tests/001/ps3da1/casper/vmlinux
+[opt 3] initrd: devices/parser-tests/001/ps3da1/casper/initrd.gz
[opt 3] boot_args: root=/dev/ram0 initrd=/casper/initrd.gz boot=casper integrity-check quiet splash --
-[dev 0] id: ps3da1
+[dev 0] id: /dev/ps3da1
[dev 0] name: (null)
[dev 0] description:
[dev 0] boot_image: /usr/share/petitboot/artwork/hdd.png
[opt 0] name: linux
[opt 0] description: (null)
-[opt 0] boot_image: devices/parser-tests/002/ps3da1//ppc/ppc64/vmlinux
-[opt 0] initrd: devices/parser-tests/002/ps3da1//ppc/ppc64/ramdisk.image.gz
+[opt 0] boot_image: devices/parser-tests/002/ps3da1/ppc/ppc64/vmlinux
+[opt 0] initrd: devices/parser-tests/002/ps3da1/ppc/ppc64/ramdisk.image.gz
[opt 0] boot_args: ro
--- /dev/null
+[dev 0] id: /dev/ps3da1
+[dev 0] name: (null)
+[dev 0] description: (null)
+[dev 0] boot_image: /usr/share/petitboot/artwork/hdd.png
+[opt 0] name: test
+[opt 0] description: /dev/sda1:/vmlinux
+[opt 0] boot_image: devices/parser-tests/003/ps3da1/vmlinux
+[opt 0] initrd: (null)
+[opt 0] boot_args: (null)
--- /dev/null
+# test remapping sda to ps3da, when mounted from a ps3da device
+
+test='/dev/sda1:/vmlinux'
+
--- /dev/null
+[dev 0] id: /dev/sda1
+[dev 0] name: (null)
+[dev 0] description: (null)
+[dev 0] boot_image: /usr/share/petitboot/artwork/hdd.png
+[opt 0] name: test
+[opt 0] description: /dev/sda1:/vmlinux
+[opt 0] boot_image: devices/parser-tests/004/sda1/vmlinux
+[opt 0] initrd: (null)
+[opt 0] boot_args: (null)
--- /dev/null
+# test remapping sda to ps3da, when mounted from a plain sd device
+
+test='/dev/sda1:/vmlinux'
+
for (i = 0; parsers[i]; i++) {
pb_log("\ttrying parser '%s'\n", parsers[i]->name);
/* just use a dummy device path for now */
- if (parsers[i]->parse(devpath, mountpoint_for_device(devpath)))
+ if (parsers[i]->parse(devpath))
return;
}
pb_log("\tno boot_options found\n");
free(opt);
}
-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] != '/')
- strcat(full_path, "/");
- strcat(full_path, b);
-
- return full_path;
-}
-
const char *generic_icon_file(enum generic_icon_type type)
{
switch (type) {
struct parser {
char *name;
int priority;
- int (*parse)(const char *devicepath, const char *mountpoint);
+ int (*parse)(const char *device);
struct parser *next;
};
void free_device(struct device *dev);
void free_boot_option(struct boot_option *opt);
-char *join_paths(const char *a, const char *b);
-
const char *generic_icon_file(enum generic_icon_type type);
/* functions provided by udev-helper or the test wrapper */
int mount_device(const char *dev_path);
-char *resolve_path(const char *path, const char *default_mountpoint);
+char *resolve_path(const char *path, const char *current_dev);
const char *mountpoint_for_device(const char *dev_path);
enum generic_icon_type guess_device_type(void);
#define DEVICE_MAP_SIZE 32
static struct device_map device_map[DEVICE_MAP_SIZE];
-const char *mountpoint_for_device(const char *dev_path)
+static 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;
+}
+
#define PATHS_H
/**
- * Get the mountpoint for a device
+ * Given a string (eg /dev/sda1, sda1 or UUID=B8E53381CA9EA0E3), parse the
+ * device path (eg /dev/sda1). Any device descriptions read from config files
+ * should be parsed into the path first.
+ *
+ * The cur_dev is provided for some remapping situations. If NULL is provided,
+ * no remapping will be done.
+ *
+ * Returns a newly-allocated string.
+ */
+char *parse_device_path(const char *dev_str, const char *current_device);
+
+/**
+ * Get the mountpoint for a device.
*/
-const char *mountpoint_for_device(const char *dev_path);
+const char *mountpoint_for_device(const char *dev);
/**
* Resolve a path given in a config file, to a path in the local filesystem.
*
* Returns a newly-allocated string containing a full path to the file in path
*/
-char *resolve_path(const char *path, const char *current_mountpoint);
+char *resolve_path(const char *path, const char *current_device);
+
/**
* Set the base directory for newly-created mountpoints
*/
void set_mount_base(const char *path);
+/**
+ * Utility function for joining two paths. Adds a / between a and b if
+ * required.
+ *
+ * Returns a newly-allocated string.
+ */
+char *join_paths(const char *a, const char *b);
+
+
#endif /* PATHS_H */
#include "parser.h"
#include "params.h"
+#include "paths.h"
#include "yaboot-cfg.h"
#include <stdlib.h>
#include <sys/param.h>
static struct device *dev;
-static const char *mountpoint;
+static char *devpath;
static char *defimage;
char *
opt.name = label;
cfgopt = cfg_get_strg(label, "image");
- opt.boot_image_file = resolve_path(cfgopt, mountpoint);
+ opt.boot_image_file = resolve_path(cfgopt, devpath);
if (cfgopt == defimage)
pb_log("This one is default. What do we do about it?\n");
cfgopt = cfg_get_strg(label, "initrd");
if (cfgopt)
- opt.initrd_file = resolve_path(cfgopt, mountpoint);
+ opt.initrd_file = resolve_path(cfgopt, devpath);
opt.boot_args = make_params(label, NULL);
free(opt.initrd_file);
}
-static int yaboot_parse(const char *devicepath, const char *_mountpoint)
+static int yaboot_parse(const char *device)
{
char *filepath;
char *conf_file;
struct stat st;
char *label;
- mountpoint = _mountpoint;
+ devpath = strdup(device);
- filepath = join_paths(mountpoint, "/etc/yaboot.conf");
+ filepath = resolve_path("/etc/yaboot.conf", devpath);
fd = open(filepath, O_RDONLY);
if (fd < 0) {
free(filepath);
- filepath = join_paths(mountpoint, "/yaboot.conf");
+ filepath = resolve_path("/yaboot.conf", devpath);
fd = open(filepath, O_RDONLY);
if (fd < 0)
dev = malloc(sizeof(*dev));
memset(dev, 0, sizeof(*dev));
- dev->id = strdup(devicepath);
+ dev->id = strdup(devpath);
if (cfg_get_strg(0, "init-message")) {
char *newline;
dev->description = strdup(cfg_get_strg(0, "init-message"));
}
dev->icon_file = strdup(generic_icon_file(guess_device_type()));
- /* If we have a 'partiton=' directive, update the default mountpoint
- * to use that instead of the current mountpoint */
+ /* If we have a 'partiton=' directive, update the default devpath
+ * to use that instead of the current device */
tmpstr = cfg_get_strg(0, "partition");
if (tmpstr) {
char *endp;
int partnr = strtol(tmpstr, &endp, 10);
if (endp != tmpstr && !*endp) {
- char *new_dev = malloc(strlen(devicepath) + strlen(tmpstr) + 1);
+ char *new_dev, *tmp;
+
+ new_dev = malloc(strlen(devpath) + strlen(tmpstr) + 1);
if (!new_dev)
return 0;
- strcpy(new_dev, devicepath);
+ strcpy(new_dev, devpath);
/* Strip digits (partition number) from string */
- endp = &new_dev[strlen(devicepath) - 1];
+ endp = new_dev + strlen(devpath) - 1;
while (isdigit(*endp))
*(endp--) = 0;
/* and add our own... */
- sprintf(endp+1, "%d", partnr);
+ sprintf(endp + 1, "%d", partnr);
- mountpoint = mountpoint_for_device(new_dev);
+ tmp = devpath;
+ devpath = parse_device_path(new_dev, devpath);
+ free(tmp);
free(new_dev);
}
}