summaryrefslogtreecommitdiffstats
path: root/discover/resource.c
blob: 25fff650db7fabc6bfe805525c38c379a3ce7708 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

#define _GNU_SOURCE

#include <assert.h>
#include <stdbool.h>
#include <string.h>

#include <url/url.h>
#include <log/log.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);
}

void resolve_resource_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(struct discover_boot_option *opt,
	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(opt, 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_resource_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_resource_against_device(res, orig_device, devpath);
		return res;
	}

	devstr = talloc_strndup(res, devpath, pos - devpath);
	path = talloc_strdup(res, pos + 1);

	pb_log("%s: resource depends on device %s\n", __func__, devstr);

	/* 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_resource_against_device(res, dev, info->path);
	talloc_free(info);

	return true;
}

struct resource *create_url_resource(struct discover_boot_option *opt,
		struct pb_url *url)
{
	struct resource *res;

	res = talloc(opt, struct resource);
	res->url = url;
	res->resolved = true;

	return res;
}
OpenPOWER on IntegriCloud