]> git.ozlabs.org Git - petitboot/commitdiff
discover: Add devpath resources
authorJeremy Kerr <jk@ozlabs.org>
Tue, 16 Apr 2013 07:54:13 +0000 (15:54 +0800)
committerJeremy Kerr <jk@ozlabs.org>
Mon, 29 Apr 2013 04:31:20 +0000 (14:31 +1000)
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 <jk@ozlabs.org>
discover/Makefile.am
discover/resource.c [new file with mode: 0644]
discover/resource.h

index a85885554eb7b099a8a9c24d93b757b1cf6e4d87..a8d07b21fab1c8f08614531da4fe45d447d32876 100644 (file)
@@ -54,6 +54,7 @@ pb_discover_SOURCES = \
        params.h \
        pb-discover.c \
        pb-discover.h \
        params.h \
        pb-discover.c \
        pb-discover.h \
+       resource.c \
        resource.h \
        udev.c \
        udev.h \
        resource.h \
        udev.c \
        udev.h \
diff --git a/discover/resource.c b/discover/resource.c
new file mode 100644 (file)
index 0000000..917a6dc
--- /dev/null
@@ -0,0 +1,113 @@
+
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <url/url.h>
+#include <talloc/talloc.h>
+
+#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;
+}
index b7e1a4649dfc7d699faa0aa816f3e3c8e4e9004c..2debe3cd24970e5c429c3fed950d1f40ca018deb 100644 (file)
@@ -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 */
 
 #endif /* RESOURCE_H */