blob: d97a03c7571317dc0ce3d8ed60de1e89514bc034 [file] [log] [blame]
Lucas De Marchi8f923be2011-12-03 04:28:49 -02001/*
2 * libkmod - interface to kernel module operations
3 *
4 * Copyright (C) 2008 Alan Jenkins <alan.christopher.jenkins@googlemail.com>
5 * Copyright (C) 2011 ProFUSION embedded systems
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation version 2.1.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
Lucas De Marchie8847fd2011-11-30 15:23:28 -020020
21#include <arpa/inet.h> /* htonl */
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <errno.h>
26#include <fnmatch.h>
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -020027#include <assert.h>
Lucas De Marchie8847fd2011-11-30 15:23:28 -020028
29#include "libkmod-private.h"
30#include "libkmod-index.h"
31#include "macro.h"
32
Lucas De Marchi8f923be2011-12-03 04:28:49 -020033/* index.c: module index file shared functions for modprobe and depmod */
34
Lucas De Marchie8847fd2011-11-30 15:23:28 -020035void index_values_free(struct index_value *values)
36{
37 while (values) {
38 struct index_value *value = values;
39
40 values = value->next;
41 free(value);
42 }
43}
44
Lucas De Marchie8847fd2011-11-30 15:23:28 -020045static int add_value(struct index_value **values,
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -020046 const char *value, unsigned len, unsigned int priority)
Lucas De Marchie8847fd2011-11-30 15:23:28 -020047{
48 struct index_value *v;
Lucas De Marchie8847fd2011-11-30 15:23:28 -020049
50 /* find position to insert value */
51 while (*values && (*values)->priority < priority)
52 values = &(*values)->next;
53
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -020054 v = malloc(sizeof(struct index_value) + len + 1);
55 if (!v)
56 return -1;
Lucas De Marchie8847fd2011-11-30 15:23:28 -020057 v->next = *values;
58 v->priority = priority;
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -020059 v->len = len;
60 memcpy(v->value, value, len);
61 v->value[len] = '\0';
Lucas De Marchie8847fd2011-11-30 15:23:28 -020062 *values = v;
63
Gustavo Sverzut Barbieri558b0202011-12-08 16:36:48 -020064 return 0;
Lucas De Marchie8847fd2011-11-30 15:23:28 -020065}
66
Lucas De Marchi93688882011-12-02 10:05:31 -020067static void read_error(void)
Lucas De Marchie8847fd2011-11-30 15:23:28 -020068{
69 fatal("Module index: unexpected error: %s\n"
70 "Try re-running depmod\n", errno ? strerror(errno) : "EOF");
71}
72
73static int read_char(FILE *in)
74{
75 int ch;
76
77 errno = 0;
78 ch = getc_unlocked(in);
79 if (ch == EOF)
80 read_error();
81 return ch;
82}
83
84static uint32_t read_long(FILE *in)
85{
86 uint32_t l;
87
88 errno = 0;
89 if (fread(&l, sizeof(uint32_t), 1, in) <= 0)
90 read_error();
91 return ntohl(l);
92}
93
94/*
95 * Buffer abstract data type
96 *
97 * Used internally to store the current path during tree traversal.
98 * They help build wildcard key strings to pass to fnmatch(),
99 * as well as building values of matching keys.
100 */
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200101struct buffer {
102 char *bytes;
103 unsigned size;
104 unsigned used;
105};
106
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200107#define BUF_STEP (2048)
108static bool buf_grow(struct buffer *buf, size_t newsize)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200109{
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200110 void *tmp;
111 size_t sz;
112
113 if (newsize % BUF_STEP == 0)
114 sz = newsize;
115 else
116 sz = ((newsize / BUF_STEP) + 1) * BUF_STEP;
117
Gustavo Sverzut Barbieri435ad782011-12-08 16:35:08 -0200118 if (buf->size == sz)
119 return true;
120
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200121 tmp = realloc(buf->bytes, sz);
122 if (sz > 0 && tmp == NULL)
123 return false;
124 buf->bytes = tmp;
125 buf->size = sz;
126 return true;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200127}
128
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200129static void buf_init(struct buffer *buf)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200130{
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200131 buf->bytes = NULL;
132 buf->size = 0;
133 buf->used = 0;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200134}
135
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200136static void buf_release(struct buffer *buf)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200137{
138 free(buf->bytes);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200139}
140
141/* Destroy buffer and return a copy as a C string */
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200142static char *buf_steal(struct buffer *buf)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200143{
144 char *bytes;
145
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200146 bytes = realloc(buf->bytes, buf->used + 1);
147 if (!bytes) {
148 free(buf->bytes);
149 return NULL;
150 }
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200151 bytes[buf->used] = '\0';
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200152 return bytes;
153}
154
155/* Return a C string owned by the buffer
156 (invalidated if the buffer is changed).
157 */
158static const char *buf_str(struct buffer *buf)
159{
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200160 if (!buf_grow(buf, buf->used + 1))
161 return NULL;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200162 buf->bytes[buf->used] = '\0';
163 return buf->bytes;
164}
165
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200166static bool buf_pushchar(struct buffer *buf, char ch)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200167{
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200168 if (!buf_grow(buf, buf->used + 1))
169 return false;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200170 buf->bytes[buf->used] = ch;
171 buf->used++;
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200172 return true;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200173}
174
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200175static unsigned buf_freadchars(struct buffer *buf, FILE *in)
176{
177 unsigned i = 0;
178 int ch;
179
180 while ((ch = read_char(in))) {
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200181 if (!buf_pushchar(buf, ch))
182 break;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200183 i++;
184 }
185
186 return i;
187}
188
189static void buf_popchar(struct buffer *buf)
190{
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200191 assert(buf->used > 0);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200192 buf->used--;
193}
194
195static void buf_popchars(struct buffer *buf, unsigned n)
196{
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200197 assert(buf->used >= n);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200198 buf->used -= n;
199}
200
201static void buf_clear(struct buffer *buf)
202{
203 buf->used = 0;
204}
205
206/*
Lucas De Marchieb8bb322011-12-02 10:23:02 -0200207 * Index file searching
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200208 */
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200209struct index_node_f {
210 FILE *file;
211 char *prefix; /* path compression */
212 struct index_value *values;
213 unsigned char first; /* range of child nodes */
214 unsigned char last;
215 uint32_t children[0];
216};
217
218static struct index_node_f *index_read(FILE *in, uint32_t offset)
219{
220 struct index_node_f *node;
221 char *prefix;
222 int i, child_count = 0;
223
224 if ((offset & INDEX_NODE_MASK) == 0)
225 return NULL;
226
227 fseek(in, offset & INDEX_NODE_MASK, SEEK_SET);
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200228
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200229 if (offset & INDEX_NODE_PREFIX) {
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200230 struct buffer buf;
231 buf_init(&buf);
232 buf_freadchars(&buf, in);
233 prefix = buf_steal(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200234 } else
235 prefix = NOFAIL(strdup(""));
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200236
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200237 if (offset & INDEX_NODE_CHILDS) {
238 char first = read_char(in);
239 char last = read_char(in);
240 child_count = last - first + 1;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200241
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200242 node = NOFAIL(malloc(sizeof(struct index_node_f) +
243 sizeof(uint32_t) * child_count));
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200244
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200245 node->first = first;
246 node->last = last;
247
248 for (i = 0; i < child_count; i++)
249 node->children[i] = read_long(in);
250 } else {
251 node = NOFAIL(malloc(sizeof(struct index_node_f)));
252 node->first = INDEX_CHILDMAX;
253 node->last = 0;
254 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200255
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200256 node->values = NULL;
257 if (offset & INDEX_NODE_VALUES) {
258 int value_count;
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200259 struct buffer buf;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200260 const char *value;
261 unsigned int priority;
262
263 value_count = read_long(in);
264
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200265 buf_init(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200266 while (value_count--) {
267 priority = read_long(in);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200268 buf_freadchars(&buf, in);
269 value = buf_str(&buf);
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200270 add_value(&node->values, value, buf.used, priority);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200271 buf_clear(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200272 }
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200273 buf_release(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200274 }
275
276 node->prefix = prefix;
277 node->file = in;
278 return node;
279}
280
281static void index_close(struct index_node_f *node)
282{
283 free(node->prefix);
284 index_values_free(node->values);
285 free(node);
286}
287
288struct index_file {
289 FILE *file;
290 uint32_t root_offset;
291};
292
293/* Failures are silent; modprobe will fall back to text files */
294struct index_file *index_file_open(const char *filename)
295{
296 FILE *file;
297 uint32_t magic, version;
298 struct index_file *new;
299
300 file = fopen(filename, "r");
301 if (!file)
302 return NULL;
303 errno = EINVAL;
304
305 magic = read_long(file);
306 if (magic != INDEX_MAGIC)
307 return NULL;
308
309 version = read_long(file);
310 if (version >> 16 != INDEX_VERSION_MAJOR)
311 return NULL;
312
313 new = NOFAIL(malloc(sizeof(struct index_file)));
314 new->file = file;
315 new->root_offset = read_long(new->file);
316
317 errno = 0;
318 return new;
319}
320
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200321void index_file_close(struct index_file *idx)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200322{
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200323 fclose(idx->file);
324 free(idx);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200325}
326
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200327static struct index_node_f *index_readroot(struct index_file *in)
328{
329 return index_read(in->file, in->root_offset);
330}
331
332static struct index_node_f *index_readchild(const struct index_node_f *parent,
333 int ch)
334{
Lucas De Marchie71970a2011-12-02 10:27:15 -0200335 if (parent->first <= ch && ch <= parent->last) {
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200336 return index_read(parent->file,
337 parent->children[ch - parent->first]);
Lucas De Marchie71970a2011-12-02 10:27:15 -0200338 }
339
340 return NULL;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200341}
342
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200343static char *index_search__node(struct index_node_f *node, const char *key, int i)
344{
345 char *value;
346 struct index_node_f *child;
347 int ch;
348 int j;
349
350 while(node) {
351 for (j = 0; node->prefix[j]; j++) {
352 ch = node->prefix[j];
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200353
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200354 if (ch != key[i+j]) {
355 index_close(node);
356 return NULL;
357 }
358 }
Lucas De Marchie71970a2011-12-02 10:27:15 -0200359
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200360 i += j;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200361
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200362 if (key[i] == '\0') {
363 if (node->values) {
364 value = strdup(node->values[0].value);
365 index_close(node);
366 return value;
367 } else {
368 return NULL;
369 }
370 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200371
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200372 child = index_readchild(node, key[i]);
373 index_close(node);
374 node = child;
375 i++;
376 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200377
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200378 return NULL;
379}
380
381/*
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200382 * Search the index for a key
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200383 *
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200384 * Returns the value of the first match
385 *
386 * The recursive functions free their node argument (using index_close).
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200387 */
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200388char *index_search(struct index_file *in, const char *key)
389{
390 struct index_node_f *root;
391 char *value;
392
393 root = index_readroot(in);
394 value = index_search__node(root, key, 0);
395
396 return value;
397}
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200398
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200399
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200400
401/* Level 4: add all the values from a matching node */
402static void index_searchwild__allvalues(struct index_node_f *node,
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200403 struct index_value **out)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200404{
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200405 struct index_value *v;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200406
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200407 for (v = node->values; v != NULL; v = v->next)
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200408 add_value(out, v->value, v->len, v->priority);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200409
410 index_close(node);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200411}
412
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200413/*
414 * Level 3: traverse a sub-keyspace which starts with a wildcard,
415 * looking for matches.
416 */
417static void index_searchwild__all(struct index_node_f *node, int j,
418 struct buffer *buf,
419 const char *subkey,
420 struct index_value **out)
421{
422 int pushed = 0;
423 int ch;
424
425 while (node->prefix[j]) {
426 ch = node->prefix[j];
427
428 buf_pushchar(buf, ch);
429 pushed++;
430 j++;
431 }
432
433 for (ch = node->first; ch <= node->last; ch++) {
434 struct index_node_f *child = index_readchild(node, ch);
435
436 if (!child)
437 continue;
438
439 buf_pushchar(buf, ch);
440 index_searchwild__all(child, 0, buf, subkey, out);
441 buf_popchar(buf);
442 }
443
444 if (node->values) {
445 if (fnmatch(buf_str(buf), subkey, 0) == 0)
446 index_searchwild__allvalues(node, out);
447 } else {
448 index_close(node);
449 }
450
451 buf_popchars(buf, pushed);
452}
453
454/* Level 2: descend the tree (until we hit a wildcard) */
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200455static void index_searchwild__node(struct index_node_f *node,
456 struct buffer *buf,
457 const char *key, int i,
458 struct index_value **out)
459{
460 struct index_node_f *child;
461 int j;
462 int ch;
463
464 while(node) {
465 for (j = 0; node->prefix[j]; j++) {
466 ch = node->prefix[j];
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200467
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200468 if (ch == '*' || ch == '?' || ch == '[') {
469 index_searchwild__all(node, j, buf,
470 &key[i+j], out);
471 return;
472 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200473
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200474 if (ch != key[i+j]) {
475 index_close(node);
476 return;
477 }
478 }
Lucas De Marchie71970a2011-12-02 10:27:15 -0200479
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200480 i += j;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200481
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200482 child = index_readchild(node, '*');
483 if (child) {
484 buf_pushchar(buf, '*');
485 index_searchwild__all(child, 0, buf, &key[i], out);
486 buf_popchar(buf);
487 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200488
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200489 child = index_readchild(node, '?');
490 if (child) {
491 buf_pushchar(buf, '?');
492 index_searchwild__all(child, 0, buf, &key[i], out);
493 buf_popchar(buf);
494 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200495
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200496 child = index_readchild(node, '[');
497 if (child) {
498 buf_pushchar(buf, '[');
499 index_searchwild__all(child, 0, buf, &key[i], out);
500 buf_popchar(buf);
501 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200502
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200503 if (key[i] == '\0') {
504 index_searchwild__allvalues(node, out);
505
506 return;
507 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200508
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200509 child = index_readchild(node, key[i]);
510 index_close(node);
511 node = child;
512 i++;
513 }
514}
515
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200516/*
517 * Search the index for a key. The index may contain wildcards.
518 *
519 * Returns a list of all the values of matching keys.
520 */
521struct index_value *index_searchwild(struct index_file *in, const char *key)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200522{
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200523 struct index_node_f *root = index_readroot(in);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200524 struct buffer buf;
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200525 struct index_value *out = NULL;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200526
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200527 buf_init(&buf);
528 index_searchwild__node(root, &buf, key, 0, &out);
529 buf_release(&buf);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200530 return out;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200531}
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200532
533#include <sys/mman.h>
534#include <sys/stat.h>
535#include <unistd.h>
536
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200537static const char _idx_empty_str[] = "";
538
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200539/**************************************************************************/
540/*
541 * Alternative implementation, using mmap to map all the file to memory when
542 * starting
543 */
544struct index_mm {
545 struct kmod_ctx *ctx;
546 void *mm;
547 uint32_t root_offset;
548 size_t size;
549};
550
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200551struct index_mm_node {
552 struct index_mm *idx;
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200553 const char *prefix; /* mmape'd value */
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200554 struct index_value *values;
555 unsigned char first;
556 unsigned char last;
557 uint32_t children[];
558};
559
560static inline uint32_t read_long_mm(void **p)
561{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200562 uint8_t *addr = *(uint8_t **)p;
563 uint32_t v;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200564
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200565 /* addr may be unalined to uint32_t */
566 memcpy(&v, addr, sizeof(uint32_t));
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200567
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200568 *p = addr + sizeof(uint32_t);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200569 return ntohl(v);
570}
571
572static inline uint8_t read_char_mm(void **p)
573{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200574 uint8_t *addr = *(uint8_t **)p;
575 uint8_t v = *addr;
576 *p = addr + sizeof(uint8_t);
577 return v;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200578}
579
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200580static inline char *read_chars_mm(void **p, unsigned *rlen)
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200581{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200582 char *addr = *(char **)p;
583 size_t len = *rlen = strlen(addr);
584 *p = addr + len + 1;
585 return addr;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200586}
587
588static struct index_mm_node *index_mm_read_node(struct index_mm *idx,
589 uint32_t offset) {
590 void *p = idx->mm;
591 struct index_mm_node *node;
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200592 const char *prefix;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200593 int i, child_count = 0;
594
595
596 if ((offset & INDEX_NODE_MASK) == 0)
597 return NULL;
598
599 p = (char *)p + (offset & INDEX_NODE_MASK);
600
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200601 if (offset & INDEX_NODE_PREFIX) {
602 unsigned len;
603 prefix = read_chars_mm(&p, &len);
604 } else
605 prefix = _idx_empty_str;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200606
607 if (offset & INDEX_NODE_CHILDS) {
608 char first = read_char_mm(&p);
609 char last = read_char_mm(&p);
610 child_count = last - first + 1;
611
612 node = malloc(sizeof(*node) + sizeof(uint32_t) * child_count);
613
614 node->first = first;
615 node->last = last;
616
617 for (i = 0; i < child_count; i++)
618 node->children[i] = read_long_mm(&p);
619 } else {
620 node = malloc(sizeof(*node));
621 node->first = INDEX_CHILDMAX;
622 node->last = 0;
623 }
624
625 node->values = NULL;
626
627 if (offset & INDEX_NODE_VALUES) {
628 uint32_t j;
629
630 for (j = read_long_mm(&p); j > 0; j--) {
631 unsigned int priority;
632 const char *value;
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200633 unsigned len;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200634
635 priority = read_long_mm(&p);
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200636 value = read_chars_mm(&p, &len);
637 add_value(&node->values, value, len, priority);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200638 }
639 }
640
641 node->prefix = prefix;
642 node->idx = idx;
643
644 return node;
645}
646
647static void index_mm_free_node(struct index_mm_node *node)
648{
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200649 index_values_free(node->values);
650 free(node);
651}
652
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200653struct index_mm *index_mm_open(struct kmod_ctx *ctx, const char *filename,
654 bool populate)
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200655{
656 int fd;
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200657 int flags;
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200658 struct stat st;
659 struct index_mm *idx;
660 struct {
661 uint32_t magic;
662 uint32_t version;
663 uint32_t root_offset;
664 } hdr;
665 void *p;
666
667 DBG(ctx, "file=%s\n", filename);
668
669 if ((fd = open(filename, O_RDONLY)) < 0) {
670 ERR(ctx, "%m\n");
671 return NULL;
672 }
673
674 fstat(fd, &st);
675
676 idx = malloc(sizeof(*idx));
677 if (idx == NULL) {
678 ERR(ctx, "%m\n");
679 goto fail;
680 }
681
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200682 flags = MAP_PRIVATE;
683 if (populate)
684 flags |= MAP_POPULATE;
685
686 if ((idx->mm = mmap(0, st.st_size, PROT_READ, flags, fd, 0))
687 == MAP_FAILED) {
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200688 ERR(ctx, "%m\n");
689 goto fail;
690 }
691
692 p = idx->mm;
693 hdr.magic = read_long_mm(&p);
694 hdr.version = read_long_mm(&p);
695 hdr.root_offset = read_long_mm(&p);
696
697 if (hdr.magic != INDEX_MAGIC) {
698 ERR(ctx, "magic check fail: %x instead of %x\n", hdr.magic,
699 INDEX_MAGIC);
700 goto fail;
701 }
702
703 if (hdr.version >> 16 != INDEX_VERSION_MAJOR) {
704 ERR(ctx, "major version check fail: %u instead of %u\n",
705 hdr.version, INDEX_MAGIC);
706 goto fail;
707 }
708
709 idx->root_offset = hdr.root_offset;
710 idx->size = st.st_size;
711 idx->ctx = ctx;
712 close(fd);
713
714 return idx;
715
716fail:
717 close(fd);
718 if (idx->mm)
719 munmap(idx->mm, st.st_size);
720 free(idx);
721 return NULL;
722}
723
724void index_mm_close(struct index_mm *idx)
725{
726 munmap(idx->mm, idx->size);
727 free(idx);
728}
Lucas De Marchi77bf9362011-12-02 17:41:30 -0200729
730static struct index_mm_node *index_mm_readroot(struct index_mm *idx)
731{
732 return index_mm_read_node(idx, idx->root_offset);
733}
Lucas De Marchi91298dc2011-12-02 17:41:46 -0200734
735static struct index_mm_node *index_mm_readchild(const struct index_mm_node *parent,
736 int ch)
737{
738 if (parent->first <= ch && ch <= parent->last) {
739 return index_mm_read_node(parent->idx,
740 parent->children[ch - parent->first]);
741 }
742
743 return NULL;
744}
Lucas De Marchie33bb872011-12-02 17:45:01 -0200745
746static char *index_mm_search_node(struct index_mm_node *node, const char *key,
747 int i)
748{
749 char *value;
750 struct index_mm_node *child;
751 int ch;
752 int j;
753
754 while(node) {
755 for (j = 0; node->prefix[j]; j++) {
756 ch = node->prefix[j];
757
758 if (ch != key[i+j]) {
759 index_mm_free_node(node);
760 return NULL;
761 }
762 }
763
764 i += j;
765
766 if (key[i] == '\0') {
767 if (node->values) {
768 value = strdup(node->values[0].value);
769 index_mm_free_node(node);
770 return value;
771 } else {
772 return NULL;
773 }
774 }
775
776 child = index_mm_readchild(node, key[i]);
777 index_mm_free_node(node);
778 node = child;
779 i++;
780 }
781
782 return NULL;
783}
Lucas De Marchib797b792011-12-02 17:49:03 -0200784
785/*
786 * Search the index for a key
787 *
788 * Returns the value of the first match
789 *
790 * The recursive functions free their node argument (using index_close).
791 */
792char *index_mm_search(struct index_mm *idx, const char *key)
793{
794 struct index_mm_node *root;
795 char *value;
796
797 root = index_mm_readroot(idx);
798 value = index_mm_search_node(root, key, 0);
799
800 return value;
801}
Lucas De Marchibf89f702011-12-02 18:23:36 -0200802
803/* Level 4: add all the values from a matching node */
804static void index_mm_searchwild_allvalues(struct index_mm_node *node,
805 struct index_value **out)
806{
807 struct index_value *v;
808
809 for (v = node->values; v != NULL; v = v->next)
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200810 add_value(out, v->value, v->len, v->priority);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200811
812 index_mm_free_node(node);
813}
814
815/*
816 * Level 3: traverse a sub-keyspace which starts with a wildcard,
817 * looking for matches.
818 */
819static void index_mm_searchwild_all(struct index_mm_node *node, int j,
820 struct buffer *buf,
821 const char *subkey,
822 struct index_value **out)
823{
824 int pushed = 0;
825 int ch;
826
827 while (node->prefix[j]) {
828 ch = node->prefix[j];
829
830 buf_pushchar(buf, ch);
831 pushed++;
832 j++;
833 }
834
835 for (ch = node->first; ch <= node->last; ch++) {
836 struct index_mm_node *child = index_mm_readchild(node, ch);
837
838 if (!child)
839 continue;
840
841 buf_pushchar(buf, ch);
842 index_mm_searchwild_all(child, 0, buf, subkey, out);
843 buf_popchar(buf);
844 }
845
846 if (node->values) {
847 if (fnmatch(buf_str(buf), subkey, 0) == 0)
848 index_mm_searchwild_allvalues(node, out);
849 } else {
850 index_mm_free_node(node);
851 }
852
853 buf_popchars(buf, pushed);
854}
855
856/* Level 2: descend the tree (until we hit a wildcard) */
857static void index_mm_searchwild_node(struct index_mm_node *node,
858 struct buffer *buf,
859 const char *key, int i,
860 struct index_value **out)
861{
862 struct index_mm_node *child;
863 int j;
864 int ch;
865
866 while(node) {
867 for (j = 0; node->prefix[j]; j++) {
868 ch = node->prefix[j];
869
870 if (ch == '*' || ch == '?' || ch == '[') {
871 index_mm_searchwild_all(node, j, buf,
872 &key[i+j], out);
873 return;
874 }
875
876 if (ch != key[i+j]) {
877 index_mm_free_node(node);
878 return;
879 }
880 }
881
882 i += j;
883
884 child = index_mm_readchild(node, '*');
885 if (child) {
886 buf_pushchar(buf, '*');
887 index_mm_searchwild_all(child, 0, buf, &key[i], out);
888 buf_popchar(buf);
889 }
890
891 child = index_mm_readchild(node, '?');
892 if (child) {
893 buf_pushchar(buf, '?');
894 index_mm_searchwild_all(child, 0, buf, &key[i], out);
895 buf_popchar(buf);
896 }
897
898 child = index_mm_readchild(node, '[');
899 if (child) {
900 buf_pushchar(buf, '[');
901 index_mm_searchwild_all(child, 0, buf, &key[i], out);
902 buf_popchar(buf);
903 }
904
905 if (key[i] == '\0') {
906 index_mm_searchwild_allvalues(node, out);
907
908 return;
909 }
910
911 child = index_mm_readchild(node, key[i]);
912 index_mm_free_node(node);
913 node = child;
914 i++;
915 }
916}
917
918/*
919 * Search the index for a key. The index may contain wildcards.
920 *
921 * Returns a list of all the values of matching keys.
922 */
923struct index_value *index_mm_searchwild(struct index_mm *idx, const char *key)
924{
925 struct index_mm_node *root = index_mm_readroot(idx);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200926 struct buffer buf;
Lucas De Marchibf89f702011-12-02 18:23:36 -0200927 struct index_value *out = NULL;
928
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200929 buf_init(&buf);
930 index_mm_searchwild_node(root, &buf, key, 0, &out);
931 buf_release(&buf);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200932 return out;
933}