source: mainline/uspace/srv/devman/match.c@ 80743a1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 80743a1 was 23a0368, checked in by Jakub Jermar <jakub@…>, 8 years ago

Rename stat() to vfs_stat_path() and fstat() to vfs_stat()

  • Property mode set to 100644
File size: 6.3 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 <fcntl.h>
35#include <io/log.h>
36#include <str.h>
37#include <str_error.h>
38#include <sys/types.h>
39#include <vfs/vfs.h>
40
41#include "devman.h"
42#include "match.h"
43
44#define COMMENT '#'
45
46/** Compute compound score of driver and device.
47 *
48 * @param driver Match id of the driver.
49 * @param device Match id of the device.
50 * @return Compound score.
51 * @retval 0 No match at all.
52 */
53static int compute_match_score(match_id_t *driver, match_id_t *device)
54{
55 if (str_cmp(driver->id, device->id) == 0) {
56 /*
57 * The strings match, return the product of their scores.
58 */
59 return driver->score * device->score;
60 } else {
61 /*
62 * Different strings, return zero.
63 */
64 return 0;
65 }
66}
67
68int get_match_score(driver_t *drv, dev_node_t *dev)
69{
70 link_t *drv_head = &drv->match_ids.ids.head;
71 link_t *dev_head = &dev->pfun->match_ids.ids.head;
72
73 if (list_empty(&drv->match_ids.ids) ||
74 list_empty(&dev->pfun->match_ids.ids)) {
75 return 0;
76 }
77
78 /*
79 * Go through all pairs, return the highest score obtained.
80 */
81 int highest_score = 0;
82
83 link_t *drv_link = drv->match_ids.ids.head.next;
84 while (drv_link != drv_head) {
85 link_t *dev_link = dev_head->next;
86 while (dev_link != dev_head) {
87 match_id_t *drv_id = list_get_instance(drv_link, match_id_t, link);
88 match_id_t *dev_id = list_get_instance(dev_link, match_id_t, link);
89
90 int score = compute_match_score(drv_id, dev_id);
91 if (score > highest_score) {
92 highest_score = score;
93 }
94
95 dev_link = dev_link->next;
96 }
97
98 drv_link = drv_link->next;
99 }
100
101 return highest_score;
102}
103
104/** Read match id at the specified position of a string and set the position in
105 * the string to the first character following the id.
106 *
107 * @param buf The position in the input string.
108 * @return The match id.
109 */
110char *read_match_id(char **buf)
111{
112 char *res = NULL;
113 size_t len = get_nonspace_len(*buf);
114
115 if (len > 0) {
116 res = malloc(len + 1);
117 if (res != NULL) {
118 str_ncpy(res, len + 1, *buf, len);
119 *buf += len;
120 }
121 }
122
123 return res;
124}
125
126/**
127 * Read match ids and associated match scores from a string.
128 *
129 * Each match score in the string is followed by its match id.
130 * The match ids and match scores are separated by whitespaces.
131 * Neither match ids nor match scores can contain whitespaces.
132 *
133 * @param buf The string from which the match ids are read.
134 * @param ids The list of match ids into which the match ids and
135 * scores are added.
136 * @return True if at least one match id and associated match score
137 * was successfully read, false otherwise.
138 */
139bool parse_match_ids(char *buf, match_id_list_t *ids)
140{
141 int score = 0;
142 char *id = NULL;
143 int ids_read = 0;
144
145 while (true) {
146 /* skip spaces */
147 if (!skip_spaces(&buf))
148 break;
149
150 if (*buf == COMMENT) {
151 skip_line(&buf);
152 continue;
153 }
154
155 /* read score */
156 score = strtoul(buf, &buf, 10);
157
158 /* skip spaces */
159 if (!skip_spaces(&buf))
160 break;
161
162 /* read id */
163 id = read_match_id(&buf);
164 if (NULL == id)
165 break;
166
167 /* create new match_id structure */
168 match_id_t *mid = create_match_id();
169 mid->id = id;
170 mid->score = score;
171
172 /* add it to the list */
173 add_match_id(ids, mid);
174
175 ids_read++;
176 }
177
178 return ids_read > 0;
179}
180
181/**
182 * Read match ids and associated match scores from a file.
183 *
184 * Each match score in the file is followed by its match id.
185 * The match ids and match scores are separated by whitespaces.
186 * Neither match ids nor match scores can contain whitespaces.
187 *
188 * @param buf The path to the file from which the match ids are read.
189 * @param ids The list of match ids into which the match ids and
190 * scores are added.
191 * @return True if at least one match id and associated match score
192 * was successfully read, false otherwise.
193 */
194bool read_match_ids(const char *conf_path, match_id_list_t *ids)
195{
196 log_msg(LOG_DEFAULT, LVL_DEBUG, "read_match_ids(conf_path=\"%s\")", conf_path);
197
198 bool suc = false;
199 char *buf = NULL;
200 bool opened = false;
201 int fd;
202 size_t len = 0;
203 struct stat st;
204
205 fd = open(conf_path, O_RDONLY);
206 if (fd < 0) {
207 log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to open `%s' for reading: %s.",
208 conf_path, str_error(errno));
209 goto cleanup;
210 }
211 opened = true;
212
213 if (vfs_stat(fd, &st) != EOK) {
214 log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to fstat %d: %s.", fd,
215 str_error(errno));
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 ssize_t read_bytes = read(fd, (aoff64_t []) {0}, buf, len);
233 if (read_bytes <= 0) {
234 log_msg(LOG_DEFAULT, LVL_ERROR, "Unable to read file '%s' (%d).", conf_path,
235 errno);
236 goto cleanup;
237 }
238 buf[read_bytes] = 0;
239
240 suc = parse_match_ids(buf, ids);
241
242cleanup:
243 free(buf);
244
245 if (opened)
246 close(fd);
247
248 return suc;
249}
250
251/** @}
252 */
Note: See TracBrowser for help on using the repository browser.