source: mainline/uspace/srv/devman/match.c@ f77c1c9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f77c1c9 was f77c1c9, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

Return VFS handles separately from error codes.

  • Property mode set to 100644
File size: 6.4 KB
Line 
1/*
2 * Copyright (c) 2010 Lenka Trochtova
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup devman
30 * @{
31 */
32
33#include <errno.h>
34#include <io/log.h>
35#include <str.h>
36#include <str_error.h>
37#include <stddef.h>
38#include <vfs/vfs.h>
39
40#include "devman.h"
41#include "match.h"
42
43#define COMMENT '#'
44
45/** Compute compound score of driver and device.
46 *
47 * @param driver Match id of the driver.
48 * @param device Match id of the device.
49 * @return Compound score.
50 * @retval 0 No match at all.
51 */
52static int compute_match_score(match_id_t *driver, match_id_t *device)
53{
54 if (str_cmp(driver->id, device->id) == 0) {
55 /*
56 * The strings match, return the product of their scores.
57 */
58 return driver->score * device->score;
59 } else {
60 /*
61 * Different strings, return zero.
62 */
63 return 0;
64 }
65}
66
67int get_match_score(driver_t *drv, dev_node_t *dev)
68{
69 link_t *drv_head = &drv->match_ids.ids.head;
70 link_t *dev_head = &dev->pfun->match_ids.ids.head;
71
72 if (list_empty(&drv->match_ids.ids) ||
73 list_empty(&dev->pfun->match_ids.ids)) {
74 return 0;
75 }
76
77 /*
78 * Go through all pairs, return the highest score obtained.
79 */
80 int highest_score = 0;
81
82 link_t *drv_link = drv->match_ids.ids.head.next;
83 while (drv_link != drv_head) {
84 link_t *dev_link = dev_head->next;
85 while (dev_link != dev_head) {
86 match_id_t *drv_id = list_get_instance(drv_link, match_id_t, link);
87 match_id_t *dev_id = list_get_instance(dev_link, match_id_t, link);
88
89 int score = compute_match_score(drv_id, dev_id);
90 if (score > highest_score) {
91 highest_score = score;
92 }
93
94 dev_link = dev_link->next;
95 }
96
97 drv_link = drv_link->next;
98 }
99
100 return highest_score;
101}
102
103/** Read match id at the specified position of a string and set the position in
104 * the string to the first character following the id.
105 *
106 * @param buf The position in the input string.
107 * @return The match id.
108 */
109char *read_match_id(char **buf)
110{
111 char *res = NULL;
112 size_t len = get_nonspace_len(*buf);
113
114 if (len > 0) {
115 res = malloc(len + 1);
116 if (res != NULL) {
117 str_ncpy(res, len + 1, *buf, len);
118 *buf += len;
119 }
120 }
121
122 return res;
123}
124
125/**
126 * Read match ids and associated match scores from a string.
127 *
128 * Each match score in the string is followed by its match id.
129 * The match ids and match scores are separated by whitespaces.
130 * Neither match ids nor match scores can contain whitespaces.
131 *
132 * @param buf The string from which the match ids are read.
133 * @param ids The list of match ids into which the match ids and
134 * scores are added.
135 * @return True if at least one match id and associated match score
136 * was successfully read, false otherwise.
137 */
138bool parse_match_ids(char *buf, match_id_list_t *ids)
139{
140 int score = 0;
141 char *id = NULL;
142 int ids_read = 0;
143
144 while (true) {
145 /* skip spaces */
146 if (!skip_spaces(&buf))
147 break;
148
149 if (*buf == COMMENT) {
150 skip_line(&buf);
151 continue;
152 }
153
154 /* read score */
155 score = strtoul(buf, &buf, 10);
156
157 /* skip spaces */
158 if (!skip_spaces(&buf))
159 break;
160
161 /* read id */
162 id = read_match_id(&buf);
163 if (NULL == id)
164 break;
165
166 /* create new match_id structure */
167 match_id_t *mid = create_match_id();
168 mid->id = id;
169 mid->score = score;
170
171 /* add it to the list */
172 add_match_id(ids, mid);
173
174 ids_read++;
175 }
176
177 return ids_read > 0;
178}
179
180/**
181 * Read match ids and associated match scores from a file.
182 *
183 * Each match score in the file is followed by its match id.
184 * The match ids and match scores are separated by whitespaces.
185 * Neither match ids nor match scores can contain whitespaces.
186 *
187 * @param buf The path to the file from which the match ids are read.
188 * @param ids The list of match ids into which the match ids and
189 * scores are added.
190 * @return True if at least one match id and associated match score
191 * was successfully read, false otherwise.
192 */
193bool read_match_ids(const char *conf_path, match_id_list_t *ids)
194{
195 log_msg(LOG_DEFAULT, LVL_DEBUG, "read_match_ids(conf_path=\"%s\")", conf_path);
196
197 bool suc = false;
198 char *buf = NULL;
199 bool opened = false;
200 int fd;
201 size_t len = 0;
202 struct stat st;
203
204 int rc = vfs_lookup_open(conf_path, WALK_REGULAR, MODE_READ, &fd);
205 if (rc != EOK) {
206 log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to open `%s' for reading: %s.",
207 conf_path, str_error(rc));
208 goto cleanup;
209 }
210 opened = true;
211
212 rc = vfs_stat(fd, &st);
213 if (rc != EOK) {
214 log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to fstat %d: %s.", fd,
215 str_error(rc));
216 goto cleanup;
217 }
218 len = st.size;
219 if (len == 0) {
220 log_msg(LOG_DEFAULT, LVL_ERROR, "Configuration file '%s' is empty.",
221 conf_path);
222 goto cleanup;
223 }
224
225 buf = malloc(len + 1);
226 if (buf == NULL) {
227 log_msg(LOG_DEFAULT, LVL_ERROR, "Memory allocation failed when parsing file "
228 "'%s'.", conf_path);
229 goto cleanup;
230 }
231
232 size_t read_bytes;
233 rc = vfs_read(fd, (aoff64_t []) {0}, buf, len, &read_bytes);
234 if (rc != EOK) {
235 log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to read file '%s': %s.", conf_path,
236 str_error(rc));
237 goto cleanup;
238 }
239 buf[read_bytes] = 0;
240
241 suc = parse_match_ids(buf, ids);
242
243cleanup:
244 free(buf);
245
246 if (opened)
247 vfs_put(fd);
248
249 return suc;
250}
251
252/** @}
253 */
Note: See TracBrowser for help on using the repository browser.