blob: f8d63274aa058db33839eca02fcfbe46822910fe [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
537/**************************************************************************/
538/*
539 * Alternative implementation, using mmap to map all the file to memory when
540 * starting
541 */
542struct index_mm {
543 struct kmod_ctx *ctx;
544 void *mm;
545 uint32_t root_offset;
546 size_t size;
547};
548
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200549struct index_mm_node {
550 struct index_mm *idx;
551 char *prefix;
552 struct index_value *values;
553 unsigned char first;
554 unsigned char last;
555 uint32_t children[];
556};
557
558static inline uint32_t read_long_mm(void **p)
559{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200560 uint8_t *addr = *(uint8_t **)p;
561 uint32_t v;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200562
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200563 /* addr may be unalined to uint32_t */
564 memcpy(&v, addr, sizeof(uint32_t));
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200565
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200566 *p = addr + sizeof(uint32_t);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200567 return ntohl(v);
568}
569
570static inline uint8_t read_char_mm(void **p)
571{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200572 uint8_t *addr = *(uint8_t **)p;
573 uint8_t v = *addr;
574 *p = addr + sizeof(uint8_t);
575 return v;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200576}
577
578static inline char *read_alloc_chars_mm(void **p)
579{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200580 char *addr = *(char **)p;
581 size_t len = strlen(addr) + 1;
582 *p = addr + len;
583 return memdup(addr, len);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200584}
585
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200586static inline char *read_chars_mm(void **p, unsigned *rlen)
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200587{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200588 char *addr = *(char **)p;
589 size_t len = *rlen = strlen(addr);
590 *p = addr + len + 1;
591 return addr;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200592}
593
594static struct index_mm_node *index_mm_read_node(struct index_mm *idx,
595 uint32_t offset) {
596 void *p = idx->mm;
597 struct index_mm_node *node;
598 char *prefix;
599 int i, child_count = 0;
600
601
602 if ((offset & INDEX_NODE_MASK) == 0)
603 return NULL;
604
605 p = (char *)p + (offset & INDEX_NODE_MASK);
606
607 if (offset & INDEX_NODE_PREFIX)
608 prefix = read_alloc_chars_mm(&p);
609 else
610 prefix = strdup("");
611
612 if (offset & INDEX_NODE_CHILDS) {
613 char first = read_char_mm(&p);
614 char last = read_char_mm(&p);
615 child_count = last - first + 1;
616
617 node = malloc(sizeof(*node) + sizeof(uint32_t) * child_count);
618
619 node->first = first;
620 node->last = last;
621
622 for (i = 0; i < child_count; i++)
623 node->children[i] = read_long_mm(&p);
624 } else {
625 node = malloc(sizeof(*node));
626 node->first = INDEX_CHILDMAX;
627 node->last = 0;
628 }
629
630 node->values = NULL;
631
632 if (offset & INDEX_NODE_VALUES) {
633 uint32_t j;
634
635 for (j = read_long_mm(&p); j > 0; j--) {
636 unsigned int priority;
637 const char *value;
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200638 unsigned len;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200639
640 priority = read_long_mm(&p);
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200641 value = read_chars_mm(&p, &len);
642 add_value(&node->values, value, len, priority);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200643 }
644 }
645
646 node->prefix = prefix;
647 node->idx = idx;
648
649 return node;
650}
651
652static void index_mm_free_node(struct index_mm_node *node)
653{
654 free(node->prefix);
655 index_values_free(node->values);
656 free(node);
657}
658
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200659struct index_mm *index_mm_open(struct kmod_ctx *ctx, const char *filename,
660 bool populate)
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200661{
662 int fd;
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200663 int flags;
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200664 struct stat st;
665 struct index_mm *idx;
666 struct {
667 uint32_t magic;
668 uint32_t version;
669 uint32_t root_offset;
670 } hdr;
671 void *p;
672
673 DBG(ctx, "file=%s\n", filename);
674
675 if ((fd = open(filename, O_RDONLY)) < 0) {
676 ERR(ctx, "%m\n");
677 return NULL;
678 }
679
680 fstat(fd, &st);
681
682 idx = malloc(sizeof(*idx));
683 if (idx == NULL) {
684 ERR(ctx, "%m\n");
685 goto fail;
686 }
687
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200688 flags = MAP_PRIVATE;
689 if (populate)
690 flags |= MAP_POPULATE;
691
692 if ((idx->mm = mmap(0, st.st_size, PROT_READ, flags, fd, 0))
693 == MAP_FAILED) {
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200694 ERR(ctx, "%m\n");
695 goto fail;
696 }
697
698 p = idx->mm;
699 hdr.magic = read_long_mm(&p);
700 hdr.version = read_long_mm(&p);
701 hdr.root_offset = read_long_mm(&p);
702
703 if (hdr.magic != INDEX_MAGIC) {
704 ERR(ctx, "magic check fail: %x instead of %x\n", hdr.magic,
705 INDEX_MAGIC);
706 goto fail;
707 }
708
709 if (hdr.version >> 16 != INDEX_VERSION_MAJOR) {
710 ERR(ctx, "major version check fail: %u instead of %u\n",
711 hdr.version, INDEX_MAGIC);
712 goto fail;
713 }
714
715 idx->root_offset = hdr.root_offset;
716 idx->size = st.st_size;
717 idx->ctx = ctx;
718 close(fd);
719
720 return idx;
721
722fail:
723 close(fd);
724 if (idx->mm)
725 munmap(idx->mm, st.st_size);
726 free(idx);
727 return NULL;
728}
729
730void index_mm_close(struct index_mm *idx)
731{
732 munmap(idx->mm, idx->size);
733 free(idx);
734}
Lucas De Marchi77bf9362011-12-02 17:41:30 -0200735
736static struct index_mm_node *index_mm_readroot(struct index_mm *idx)
737{
738 return index_mm_read_node(idx, idx->root_offset);
739}
Lucas De Marchi91298dc2011-12-02 17:41:46 -0200740
741static struct index_mm_node *index_mm_readchild(const struct index_mm_node *parent,
742 int ch)
743{
744 if (parent->first <= ch && ch <= parent->last) {
745 return index_mm_read_node(parent->idx,
746 parent->children[ch - parent->first]);
747 }
748
749 return NULL;
750}
Lucas De Marchie33bb872011-12-02 17:45:01 -0200751
752static char *index_mm_search_node(struct index_mm_node *node, const char *key,
753 int i)
754{
755 char *value;
756 struct index_mm_node *child;
757 int ch;
758 int j;
759
760 while(node) {
761 for (j = 0; node->prefix[j]; j++) {
762 ch = node->prefix[j];
763
764 if (ch != key[i+j]) {
765 index_mm_free_node(node);
766 return NULL;
767 }
768 }
769
770 i += j;
771
772 if (key[i] == '\0') {
773 if (node->values) {
774 value = strdup(node->values[0].value);
775 index_mm_free_node(node);
776 return value;
777 } else {
778 return NULL;
779 }
780 }
781
782 child = index_mm_readchild(node, key[i]);
783 index_mm_free_node(node);
784 node = child;
785 i++;
786 }
787
788 return NULL;
789}
Lucas De Marchib797b792011-12-02 17:49:03 -0200790
791/*
792 * Search the index for a key
793 *
794 * Returns the value of the first match
795 *
796 * The recursive functions free their node argument (using index_close).
797 */
798char *index_mm_search(struct index_mm *idx, const char *key)
799{
800 struct index_mm_node *root;
801 char *value;
802
803 root = index_mm_readroot(idx);
804 value = index_mm_search_node(root, key, 0);
805
806 return value;
807}
Lucas De Marchibf89f702011-12-02 18:23:36 -0200808
809/* Level 4: add all the values from a matching node */
810static void index_mm_searchwild_allvalues(struct index_mm_node *node,
811 struct index_value **out)
812{
813 struct index_value *v;
814
815 for (v = node->values; v != NULL; v = v->next)
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200816 add_value(out, v->value, v->len, v->priority);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200817
818 index_mm_free_node(node);
819}
820
821/*
822 * Level 3: traverse a sub-keyspace which starts with a wildcard,
823 * looking for matches.
824 */
825static void index_mm_searchwild_all(struct index_mm_node *node, int j,
826 struct buffer *buf,
827 const char *subkey,
828 struct index_value **out)
829{
830 int pushed = 0;
831 int ch;
832
833 while (node->prefix[j]) {
834 ch = node->prefix[j];
835
836 buf_pushchar(buf, ch);
837 pushed++;
838 j++;
839 }
840
841 for (ch = node->first; ch <= node->last; ch++) {
842 struct index_mm_node *child = index_mm_readchild(node, ch);
843
844 if (!child)
845 continue;
846
847 buf_pushchar(buf, ch);
848 index_mm_searchwild_all(child, 0, buf, subkey, out);
849 buf_popchar(buf);
850 }
851
852 if (node->values) {
853 if (fnmatch(buf_str(buf), subkey, 0) == 0)
854 index_mm_searchwild_allvalues(node, out);
855 } else {
856 index_mm_free_node(node);
857 }
858
859 buf_popchars(buf, pushed);
860}
861
862/* Level 2: descend the tree (until we hit a wildcard) */
863static void index_mm_searchwild_node(struct index_mm_node *node,
864 struct buffer *buf,
865 const char *key, int i,
866 struct index_value **out)
867{
868 struct index_mm_node *child;
869 int j;
870 int ch;
871
872 while(node) {
873 for (j = 0; node->prefix[j]; j++) {
874 ch = node->prefix[j];
875
876 if (ch == '*' || ch == '?' || ch == '[') {
877 index_mm_searchwild_all(node, j, buf,
878 &key[i+j], out);
879 return;
880 }
881
882 if (ch != key[i+j]) {
883 index_mm_free_node(node);
884 return;
885 }
886 }
887
888 i += j;
889
890 child = index_mm_readchild(node, '*');
891 if (child) {
892 buf_pushchar(buf, '*');
893 index_mm_searchwild_all(child, 0, buf, &key[i], out);
894 buf_popchar(buf);
895 }
896
897 child = index_mm_readchild(node, '?');
898 if (child) {
899 buf_pushchar(buf, '?');
900 index_mm_searchwild_all(child, 0, buf, &key[i], out);
901 buf_popchar(buf);
902 }
903
904 child = index_mm_readchild(node, '[');
905 if (child) {
906 buf_pushchar(buf, '[');
907 index_mm_searchwild_all(child, 0, buf, &key[i], out);
908 buf_popchar(buf);
909 }
910
911 if (key[i] == '\0') {
912 index_mm_searchwild_allvalues(node, out);
913
914 return;
915 }
916
917 child = index_mm_readchild(node, key[i]);
918 index_mm_free_node(node);
919 node = child;
920 i++;
921 }
922}
923
924/*
925 * Search the index for a key. The index may contain wildcards.
926 *
927 * Returns a list of all the values of matching keys.
928 */
929struct index_value *index_mm_searchwild(struct index_mm *idx, const char *key)
930{
931 struct index_mm_node *root = index_mm_readroot(idx);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200932 struct buffer buf;
Lucas De Marchibf89f702011-12-02 18:23:36 -0200933 struct index_value *out = NULL;
934
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200935 buf_init(&buf);
936 index_mm_searchwild_node(root, &buf, key, 0, &out);
937 buf_release(&buf);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200938 return out;
939}