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