From c6a36fdf2fc2e7a1c2bc4c8d16f2a3bb575b5a2f Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Tue, 16 Apr 2013 15:54:13 +0800 Subject: discover: Add devpath resources Add a generic resource type, to handle "dev:path"-style file references. This creates a duplicate of is_prefix_ignorecase, which we'll switch over to later. Signed-off-by: Jeremy Kerr --- discover/Makefile.am | 1 + discover/resource.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++ discover/resource.h | 24 +++++++++++ 3 files changed, 138 insertions(+) create mode 100644 discover/resource.c diff --git a/discover/Makefile.am b/discover/Makefile.am index a858855..a8d07b2 100644 --- a/discover/Makefile.am +++ b/discover/Makefile.am @@ -54,6 +54,7 @@ pb_discover_SOURCES = \ params.h \ pb-discover.c \ pb-discover.h \ + resource.c \ resource.h \ udev.c \ udev.h \ diff --git a/discover/resource.c b/discover/resource.c new file mode 100644 index 0000000..917a6dc --- /dev/null +++ b/discover/resource.c @@ -0,0 +1,113 @@ + +#define _GNU_SOURCE + +#include +#include +#include + +#include +#include + +#include "device-handler.h" +#include "resource.h" +#include "paths.h" + +static int is_prefix_ignorecase(const char *str, const char *prefix) +{ + return !strncasecmp(str, prefix, strlen(prefix)); +} + +struct devpath_resource_info { + char *dev, *path; +}; + +static struct discover_device *parse_device_string( + struct device_handler *handler, const char *devstr) +{ + if (is_prefix_ignorecase(devstr, "uuid=")) + return device_lookup_by_uuid(handler, devstr + strlen("uuid")); + + if (is_prefix_ignorecase(devstr, "label=")) + return device_lookup_by_label(handler, + devstr + strlen("label=")); + + return device_lookup_by_name(handler, devstr); +} +static void resolve_devpath_against_device(struct resource *res, + struct discover_device *dev, const char *path) +{ + char *resolved_path = join_paths(res, dev->mount_path, path); + res->url = pb_url_parse(res, resolved_path); + res->resolved = true; +} + +struct resource *create_devpath_resource(void *ctx, + struct discover_device *orig_device, + const char *devpath) +{ + struct devpath_resource_info *info; + char *pos, *devstr, *path; + struct resource *res; + struct pb_url *url; + + res = talloc(ctx, struct resource); + + pos = strchr(devpath, ':'); + + /* do we have a "://" scheme separator? */ + if (pos && pos[1] && pos[1] == '/' && pos[2] && pos[2] == '/') { + url = pb_url_parse(res, devpath); + + if (url->scheme != pb_url_file) { + /* not a file? we're ready to go */ + res->resolved = true; + res->url = url; + } else { + /* we've been passed a file:// URL, which has no device + * specifier. We can resolve against the original + * device */ + resolve_devpath_against_device(res, orig_device, + url->path); + talloc_free(url); + } + return res; + } + + /* if there was no device specified, we can resolve now */ + if (!pos) { + resolve_devpath_against_device(res, orig_device, devpath); + return res; + } + + devstr = talloc_strndup(res, devpath, pos - devpath); + path = talloc_strdup(res, pos + 1); + + /* defer resolution until we can find a suitable matching device */ + info = talloc(res, struct devpath_resource_info); + info->dev = devstr; + info->path = path; + + res->resolved = false; + res->info = info; + + return res; +} + +bool resolve_devpath_resource(struct device_handler *handler, + struct resource *res) +{ + struct devpath_resource_info *info = res->info; + struct discover_device *dev; + + assert(!res->resolved); + + dev = parse_device_string(handler, info->dev); + + if (!dev) + return false; + + resolve_devpath_against_device(res, dev, info->path); + talloc_free(info); + + return true; +} diff --git a/discover/resource.h b/discover/resource.h index b7e1a46..2debe3c 100644 --- a/discover/resource.h +++ b/discover/resource.h @@ -19,5 +19,29 @@ struct resource { }; }; +/** + * devpath resources. + * + * Most resources in config files will be in one of the following formats: + * - URLs + * - device-local filenames (ie, filenames on the currently-discovered dev) + * - other-device filenames (which speficy the device by a string format, + * using a dev:path format). + * + * The following definitions are a generic resource handler for these types + * of resources. By creating resources with create_devpath_resource, + * parsers can use resolve_devpath_resource as their resolve_resouce + * callback. + */ + +struct resource *create_devpath_resource(void *ctx, + struct discover_device *orig_device, + const char *devpath); + +bool resolve_devpath_resource(struct device_handler *dev, + struct resource *res); + + + #endif /* RESOURCE_H */ -- cgit v1.2.1