source: mainline/uspace/srv/devman/match.c@ 659ebd86

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 659ebd86 was 6afc9d7, checked in by Jiri Svoboda <jiri@…>, 10 years ago

UNIX-like I/O functions should use errno to return error code for many reasons.

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