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