]> git.ozlabs.org Git - petitboot/blob - discover/event.c
discover/udev: Setup event params from udev properties
[petitboot] / discover / event.c
1 #if defined(HAVE_CONFIG_H)
2 #include "config.h"
3 #endif
4
5 #define _GNU_SOURCE
6 #include <string.h>
7
8 #include <log/log.h>
9 #include <talloc/talloc.h>
10
11 #include "event.h"
12
13 #define streq(a, b) (!strcasecmp((a), (b)))
14
15 /**
16  * event_parse_ad_header - Parse an <action>@<device> event header.
17  *
18  * The buffer is modified in place.
19  * Returns zero on success.
20  */
21
22 static int event_parse_ad_header(char *buf, int len, enum event_action *action,
23         char **device)
24 {
25         char *sep;
26
27         *action = 0;
28         *device = NULL;
29
30         /* we should see an <action>@<device>\0 at the head of the buffer */
31         sep = strchr(buf, '@');
32         if (!sep) {
33                 pb_log("%s: bad header: %s\n", __func__, buf);
34                 return -1;
35         }
36
37         /* terminate the action string */
38         *sep = '\0';
39         len -= sep - buf + 1;
40
41         if (streq(buf, "add"))
42                 *action = EVENT_ACTION_ADD;
43         else if (streq(buf, "remove"))
44                 *action = EVENT_ACTION_REMOVE;
45         else if (streq(buf, "conf"))
46                 *action = EVENT_ACTION_CONF;
47         else {
48                 pb_log("%s: unknown action: %s\n", __func__, buf);
49                 return -1;
50         }
51
52         if (!*(sep + 1)) {
53                 pb_log("%s: bad device: %s\n", __func__, buf);
54                 return -1;
55         }
56
57         *device = sep + 1;
58         return 0;
59 }
60
61 /**
62  * event_parse_params - Parse a <name>=<value> buffer.
63  *
64  * The buffer is not modified.
65  */
66
67 static void event_parse_params(struct event *event, const char *buf, int len)
68 {
69         int param_len, name_len, value_len;
70         struct param *param;
71         char *sep;
72
73         for (; len > 0; len -= param_len + 1, buf += param_len + 1) {
74
75                 /* find the length of the whole parameter */
76                 param_len = strnlen(buf, len);
77                 if (!param_len) {
78                         /* multiple NULs? skip over */
79                         param_len = 1;
80                         continue;
81                 }
82
83                 /* find the separator */
84                 sep = memchr(buf, '=', param_len);
85                 if (!sep)
86                         continue;
87
88                 name_len = sep - buf;
89                 value_len = param_len - name_len - 1;
90
91                 /* update the params array */
92                 event->params = talloc_realloc(event, event->params,
93                                         struct param, ++event->n_params);
94                 param = &event->params[event->n_params - 1];
95
96                 param->name = talloc_strndup(event, buf, name_len);
97                 param->value = talloc_strndup(event, sep + 1, value_len);
98         }
99 }
100
101 int event_parse_ad_message(struct event *event, char *buf, int len)
102 {
103         int result;
104         char *device;
105         enum event_action action;
106         int device_len;
107
108         result = event_parse_ad_header(buf, len, &action, &device);
109
110         if (result)
111                 return -1;
112
113         device_len = strlen(device);
114
115         /* now we have an action and a device, we can construct the event */
116         event->action = action;
117         event->device = talloc_strndup(event, device, device_len);
118         event->n_params = 0;
119         event->params = NULL;
120
121         len -= device_len + 1;
122         event_parse_params(event, device + device_len + 1, len);
123
124         return 0;
125 }
126
127 const char *event_get_param(const struct event *event, const char *name)
128 {
129         int i;
130
131         for (i = 0; i < event->n_params; i++)
132                 if (!strcasecmp(event->params[i].name, name))
133                         return event->params[i].value;
134
135         return NULL;
136 }
137
138 void event_set_param(struct event *event, const char *name, const char *value)
139 {
140         struct param *param;
141         int i;
142
143         /* if it's already present, replace the value of the old param */
144         for (i = 0; i < event->n_params; i++) {
145                 param = &event->params[i];
146                 if (!strcasecmp(param->name, name)) {
147                         talloc_free(param->value);
148                         param->value = talloc_strdup(event, value);
149                         return;
150                 }
151         }
152
153         /* not found - create a new param */
154         event->params = talloc_realloc(event, event->params,
155                                 struct param, ++event->n_params);
156         param = &event->params[event->n_params - 1];
157
158         param->name = talloc_strdup(event, name);
159         param->value = talloc_strdup(event, value);
160 }