blob: 13199a25ecafdd9f1b773efc68b3106374fff852 [file] [log] [blame]
Lucas De Marchi8f923be2011-12-03 04:28:49 -02001/*
2 * libkmod - interface to kernel module operations
3 *
Lucas De Marchie6b0e492013-01-16 11:27:21 -02004 * Copyright (C) 2011-2013 ProFUSION embedded systems
Lucas De Marchi8f923be2011-12-03 04:28:49 -02005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
Lucas De Marchicb451f32011-12-12 18:24:35 -02008 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
Lucas De Marchi8f923be2011-12-03 04:28:49 -020010 *
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 Marchibfcd31d2012-03-02 21:28:11 -030028#include <inttypes.h>
Lucas De Marchie8847fd2011-11-30 15:23:28 -020029
Lucas De Marchi83b855a2013-07-04 16:13:11 -030030#include "libkmod-internal.h"
Lucas De Marchie8847fd2011-11-30 15:23:28 -020031#include "libkmod-index.h"
32#include "macro.h"
33
Lucas De Marchi8f923be2011-12-03 04:28:49 -020034/* index.c: module index file shared functions for modprobe and depmod */
35
Gustavo Sverzut Barbieri148226e2011-12-10 11:53:51 -020036#define INDEX_CHILDMAX 128
37
38/* Disk format:
39
40 uint32_t magic = INDEX_MAGIC;
41 uint32_t version = INDEX_VERSION;
42 uint32_t root_offset;
43
44 (node_offset & INDEX_NODE_MASK) specifies the file offset of nodes:
45
46 char[] prefix; // nul terminated
47
48 char first;
49 char last;
50 uint32_t children[last - first + 1];
51
52 uint32_t value_count;
53 struct {
54 uint32_t priority;
55 char[] value; // nul terminated
56 } values[value_count];
57
58 (node_offset & INDEX_NODE_FLAGS) indicates which fields are present.
59 Empty prefixes are omitted, leaf nodes omit the three child-related fields.
60
61 This could be optimised further by adding a sparse child format
62 (indicated using a new flag).
63 */
64
65/* Format of node offsets within index file */
66enum node_offset {
67 INDEX_NODE_FLAGS = 0xF0000000, /* Flags in high nibble */
68 INDEX_NODE_PREFIX = 0x80000000,
69 INDEX_NODE_VALUES = 0x40000000,
70 INDEX_NODE_CHILDS = 0x20000000,
71
72 INDEX_NODE_MASK = 0x0FFFFFFF, /* Offset value */
73};
74
Lucas De Marchie8847fd2011-11-30 15:23:28 -020075void index_values_free(struct index_value *values)
76{
77 while (values) {
78 struct index_value *value = values;
79
80 values = value->next;
81 free(value);
82 }
83}
84
Lucas De Marchie8847fd2011-11-30 15:23:28 -020085static int add_value(struct index_value **values,
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -020086 const char *value, unsigned len, unsigned int priority)
Lucas De Marchie8847fd2011-11-30 15:23:28 -020087{
88 struct index_value *v;
Lucas De Marchie8847fd2011-11-30 15:23:28 -020089
90 /* find position to insert value */
91 while (*values && (*values)->priority < priority)
92 values = &(*values)->next;
93
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -020094 v = malloc(sizeof(struct index_value) + len + 1);
95 if (!v)
96 return -1;
Lucas De Marchie8847fd2011-11-30 15:23:28 -020097 v->next = *values;
98 v->priority = priority;
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -020099 v->len = len;
100 memcpy(v->value, value, len);
101 v->value[len] = '\0';
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200102 *values = v;
103
Gustavo Sverzut Barbieri558b0202011-12-08 16:36:48 -0200104 return 0;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200105}
106
Lucas De Marchi93688882011-12-02 10:05:31 -0200107static void read_error(void)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200108{
109 fatal("Module index: unexpected error: %s\n"
110 "Try re-running depmod\n", errno ? strerror(errno) : "EOF");
111}
112
113static int read_char(FILE *in)
114{
115 int ch;
116
117 errno = 0;
118 ch = getc_unlocked(in);
119 if (ch == EOF)
120 read_error();
121 return ch;
122}
123
124static uint32_t read_long(FILE *in)
125{
126 uint32_t l;
127
128 errno = 0;
Leandro Pereirab6d985c2014-04-28 20:47:49 -0300129 if (fread(&l, sizeof(uint32_t), 1, in) != sizeof(uint32_t))
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200130 read_error();
131 return ntohl(l);
132}
133
134/*
135 * Buffer abstract data type
136 *
137 * Used internally to store the current path during tree traversal.
138 * They help build wildcard key strings to pass to fnmatch(),
139 * as well as building values of matching keys.
140 */
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200141struct buffer {
142 char *bytes;
143 unsigned size;
144 unsigned used;
145};
146
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200147#define BUF_STEP (2048)
148static bool buf_grow(struct buffer *buf, size_t newsize)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200149{
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200150 void *tmp;
151 size_t sz;
152
153 if (newsize % BUF_STEP == 0)
154 sz = newsize;
155 else
156 sz = ((newsize / BUF_STEP) + 1) * BUF_STEP;
157
Gustavo Sverzut Barbieri435ad782011-12-08 16:35:08 -0200158 if (buf->size == sz)
159 return true;
160
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200161 tmp = realloc(buf->bytes, sz);
162 if (sz > 0 && tmp == NULL)
163 return false;
164 buf->bytes = tmp;
165 buf->size = sz;
166 return true;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200167}
168
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200169static void buf_init(struct buffer *buf)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200170{
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200171 buf->bytes = NULL;
172 buf->size = 0;
173 buf->used = 0;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200174}
175
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200176static void buf_release(struct buffer *buf)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200177{
178 free(buf->bytes);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200179}
180
181/* Destroy buffer and return a copy as a C string */
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200182static char *buf_steal(struct buffer *buf)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200183{
184 char *bytes;
185
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200186 bytes = realloc(buf->bytes, buf->used + 1);
187 if (!bytes) {
188 free(buf->bytes);
189 return NULL;
190 }
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200191 bytes[buf->used] = '\0';
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200192 return bytes;
193}
194
195/* Return a C string owned by the buffer
196 (invalidated if the buffer is changed).
197 */
198static const char *buf_str(struct buffer *buf)
199{
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200200 if (!buf_grow(buf, buf->used + 1))
201 return NULL;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200202 buf->bytes[buf->used] = '\0';
203 return buf->bytes;
204}
205
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200206static bool buf_pushchar(struct buffer *buf, char ch)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200207{
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200208 if (!buf_grow(buf, buf->used + 1))
209 return false;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200210 buf->bytes[buf->used] = ch;
211 buf->used++;
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200212 return true;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200213}
214
Lucas De Marchi758428a2012-01-16 15:56:17 -0200215static unsigned buf_pushchars(struct buffer *buf, const char *str)
216{
217 unsigned i = 0;
218 int ch;
219
220 while ((ch = str[i])) {
221 buf_pushchar(buf, ch);
222 i++;
223 }
224
225 return i;
226}
227
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200228static unsigned buf_freadchars(struct buffer *buf, FILE *in)
229{
230 unsigned i = 0;
231 int ch;
232
233 while ((ch = read_char(in))) {
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200234 if (!buf_pushchar(buf, ch))
235 break;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200236 i++;
237 }
238
239 return i;
240}
241
242static void buf_popchar(struct buffer *buf)
243{
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200244 assert(buf->used > 0);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200245 buf->used--;
246}
247
248static void buf_popchars(struct buffer *buf, unsigned n)
249{
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200250 assert(buf->used >= n);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200251 buf->used -= n;
252}
253
254static void buf_clear(struct buffer *buf)
255{
256 buf->used = 0;
257}
258
259/*
Lucas De Marchieb8bb322011-12-02 10:23:02 -0200260 * Index file searching
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200261 */
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200262struct index_node_f {
263 FILE *file;
264 char *prefix; /* path compression */
265 struct index_value *values;
266 unsigned char first; /* range of child nodes */
267 unsigned char last;
268 uint32_t children[0];
269};
270
271static struct index_node_f *index_read(FILE *in, uint32_t offset)
272{
273 struct index_node_f *node;
274 char *prefix;
275 int i, child_count = 0;
276
277 if ((offset & INDEX_NODE_MASK) == 0)
278 return NULL;
279
280 fseek(in, offset & INDEX_NODE_MASK, SEEK_SET);
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200281
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200282 if (offset & INDEX_NODE_PREFIX) {
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200283 struct buffer buf;
284 buf_init(&buf);
285 buf_freadchars(&buf, in);
286 prefix = buf_steal(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200287 } else
288 prefix = NOFAIL(strdup(""));
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200289
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200290 if (offset & INDEX_NODE_CHILDS) {
291 char first = read_char(in);
292 char last = read_char(in);
293 child_count = last - first + 1;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200294
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200295 node = NOFAIL(malloc(sizeof(struct index_node_f) +
296 sizeof(uint32_t) * child_count));
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200297
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200298 node->first = first;
299 node->last = last;
300
301 for (i = 0; i < child_count; i++)
302 node->children[i] = read_long(in);
303 } else {
304 node = NOFAIL(malloc(sizeof(struct index_node_f)));
305 node->first = INDEX_CHILDMAX;
306 node->last = 0;
307 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200308
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200309 node->values = NULL;
310 if (offset & INDEX_NODE_VALUES) {
311 int value_count;
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200312 struct buffer buf;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200313 const char *value;
314 unsigned int priority;
315
316 value_count = read_long(in);
317
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200318 buf_init(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200319 while (value_count--) {
320 priority = read_long(in);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200321 buf_freadchars(&buf, in);
322 value = buf_str(&buf);
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200323 add_value(&node->values, value, buf.used, priority);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200324 buf_clear(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200325 }
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200326 buf_release(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200327 }
328
329 node->prefix = prefix;
330 node->file = in;
331 return node;
332}
333
334static void index_close(struct index_node_f *node)
335{
336 free(node->prefix);
337 index_values_free(node->values);
338 free(node);
339}
340
341struct index_file {
342 FILE *file;
343 uint32_t root_offset;
344};
345
346/* Failures are silent; modprobe will fall back to text files */
347struct index_file *index_file_open(const char *filename)
348{
349 FILE *file;
350 uint32_t magic, version;
351 struct index_file *new;
352
Cristian Rodríguez79e5ea92011-12-16 02:49:54 -0300353 file = fopen(filename, "re");
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200354 if (!file)
355 return NULL;
356 errno = EINVAL;
357
358 magic = read_long(file);
Cristian Rodríguez67d94ad2011-12-23 03:06:56 -0200359 if (magic != INDEX_MAGIC) {
360 fclose(file);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200361 return NULL;
Cristian Rodríguez67d94ad2011-12-23 03:06:56 -0200362 }
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200363
364 version = read_long(file);
Cristian Rodríguez4088b272011-12-26 01:38:04 -0300365 if (version >> 16 != INDEX_VERSION_MAJOR) {
366 fclose(file);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200367 return NULL;
Cristian Rodríguez4088b272011-12-26 01:38:04 -0300368 }
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200369
370 new = NOFAIL(malloc(sizeof(struct index_file)));
371 new->file = file;
372 new->root_offset = read_long(new->file);
373
374 errno = 0;
375 return new;
376}
377
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200378void index_file_close(struct index_file *idx)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200379{
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200380 fclose(idx->file);
381 free(idx);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200382}
383
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200384static struct index_node_f *index_readroot(struct index_file *in)
385{
386 return index_read(in->file, in->root_offset);
387}
388
389static struct index_node_f *index_readchild(const struct index_node_f *parent,
390 int ch)
391{
Lucas De Marchie71970a2011-12-02 10:27:15 -0200392 if (parent->first <= ch && ch <= parent->last) {
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200393 return index_read(parent->file,
394 parent->children[ch - parent->first]);
Lucas De Marchie71970a2011-12-02 10:27:15 -0200395 }
396
397 return NULL;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200398}
399
Lucas De Marchi758428a2012-01-16 15:56:17 -0200400static void index_dump_node(struct index_node_f *node, struct buffer *buf,
401 int fd)
402{
403 struct index_value *v;
404 int ch, pushed;
405
406 pushed = buf_pushchars(buf, node->prefix);
407
408 for (v = node->values; v != NULL; v = v->next) {
409 write_str_safe(fd, buf->bytes, buf->used);
410 write_str_safe(fd, " ", 1);
411 write_str_safe(fd, v->value, strlen(v->value));
412 write_str_safe(fd, "\n", 1);
413 }
414
415 for (ch = node->first; ch <= node->last; ch++) {
416 struct index_node_f *child = index_readchild(node, ch);
417
418 if (!child)
419 continue;
420
421 buf_pushchar(buf, ch);
422 index_dump_node(child, buf, fd);
423 buf_popchar(buf);
424 }
425
426 buf_popchars(buf, pushed);
427 index_close(node);
428}
429
430void index_dump(struct index_file *in, int fd, const char *prefix)
431{
432 struct index_node_f *root;
433 struct buffer buf;
434
Lucas De Marchi681bf892013-04-23 21:21:00 -0300435 root = index_readroot(in);
436 if (root == NULL)
437 return;
438
Lucas De Marchi758428a2012-01-16 15:56:17 -0200439 buf_init(&buf);
440 buf_pushchars(&buf, prefix);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200441 index_dump_node(root, &buf, fd);
442 buf_release(&buf);
443}
444
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200445static char *index_search__node(struct index_node_f *node, const char *key, int i)
446{
447 char *value;
448 struct index_node_f *child;
449 int ch;
450 int j;
451
452 while(node) {
453 for (j = 0; node->prefix[j]; j++) {
454 ch = node->prefix[j];
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200455
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200456 if (ch != key[i+j]) {
457 index_close(node);
458 return NULL;
459 }
460 }
Lucas De Marchie71970a2011-12-02 10:27:15 -0200461
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200462 i += j;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200463
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200464 if (key[i] == '\0') {
Lucas De Marchi817f4e32012-02-27 19:54:33 -0300465 value = node->values != NULL
466 ? strdup(node->values[0].value)
467 : NULL;
468
469 index_close(node);
470 return value;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200471 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200472
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200473 child = index_readchild(node, key[i]);
474 index_close(node);
475 node = child;
476 i++;
477 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200478
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200479 return NULL;
480}
481
482/*
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200483 * Search the index for a key
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200484 *
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200485 * Returns the value of the first match
486 *
487 * The recursive functions free their node argument (using index_close).
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200488 */
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200489char *index_search(struct index_file *in, const char *key)
490{
Lucas De Marchiee1d1882012-02-27 18:48:02 -0300491// FIXME: return value by reference instead of strdup
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200492 struct index_node_f *root;
493 char *value;
494
495 root = index_readroot(in);
496 value = index_search__node(root, key, 0);
497
498 return value;
499}
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200500
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200501
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200502
503/* Level 4: add all the values from a matching node */
504static void index_searchwild__allvalues(struct index_node_f *node,
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200505 struct index_value **out)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200506{
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200507 struct index_value *v;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200508
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200509 for (v = node->values; v != NULL; v = v->next)
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200510 add_value(out, v->value, v->len, v->priority);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200511
512 index_close(node);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200513}
514
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200515/*
516 * Level 3: traverse a sub-keyspace which starts with a wildcard,
517 * looking for matches.
518 */
519static void index_searchwild__all(struct index_node_f *node, int j,
520 struct buffer *buf,
521 const char *subkey,
522 struct index_value **out)
523{
524 int pushed = 0;
525 int ch;
526
527 while (node->prefix[j]) {
528 ch = node->prefix[j];
529
530 buf_pushchar(buf, ch);
531 pushed++;
532 j++;
533 }
534
535 for (ch = node->first; ch <= node->last; ch++) {
536 struct index_node_f *child = index_readchild(node, ch);
537
538 if (!child)
539 continue;
540
541 buf_pushchar(buf, ch);
542 index_searchwild__all(child, 0, buf, subkey, out);
543 buf_popchar(buf);
544 }
545
546 if (node->values) {
547 if (fnmatch(buf_str(buf), subkey, 0) == 0)
548 index_searchwild__allvalues(node, out);
Gustavo Sverzut Barbieri27fdf632011-12-10 13:28:18 -0200549 else
550 index_close(node);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200551 } else {
552 index_close(node);
553 }
554
555 buf_popchars(buf, pushed);
556}
557
558/* Level 2: descend the tree (until we hit a wildcard) */
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200559static void index_searchwild__node(struct index_node_f *node,
560 struct buffer *buf,
561 const char *key, int i,
562 struct index_value **out)
563{
564 struct index_node_f *child;
565 int j;
566 int ch;
567
568 while(node) {
569 for (j = 0; node->prefix[j]; j++) {
570 ch = node->prefix[j];
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200571
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200572 if (ch == '*' || ch == '?' || ch == '[') {
573 index_searchwild__all(node, j, buf,
574 &key[i+j], out);
575 return;
576 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200577
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200578 if (ch != key[i+j]) {
579 index_close(node);
580 return;
581 }
582 }
Lucas De Marchie71970a2011-12-02 10:27:15 -0200583
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200584 i += j;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200585
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200586 child = index_readchild(node, '*');
587 if (child) {
588 buf_pushchar(buf, '*');
589 index_searchwild__all(child, 0, buf, &key[i], out);
590 buf_popchar(buf);
591 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200592
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200593 child = index_readchild(node, '?');
594 if (child) {
595 buf_pushchar(buf, '?');
596 index_searchwild__all(child, 0, buf, &key[i], out);
597 buf_popchar(buf);
598 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200599
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200600 child = index_readchild(node, '[');
601 if (child) {
602 buf_pushchar(buf, '[');
603 index_searchwild__all(child, 0, buf, &key[i], out);
604 buf_popchar(buf);
605 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200606
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200607 if (key[i] == '\0') {
608 index_searchwild__allvalues(node, out);
609
610 return;
611 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200612
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200613 child = index_readchild(node, key[i]);
614 index_close(node);
615 node = child;
616 i++;
617 }
618}
619
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200620/*
621 * Search the index for a key. The index may contain wildcards.
622 *
623 * Returns a list of all the values of matching keys.
624 */
625struct index_value *index_searchwild(struct index_file *in, const char *key)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200626{
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200627 struct index_node_f *root = index_readroot(in);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200628 struct buffer buf;
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200629 struct index_value *out = NULL;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200630
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200631 buf_init(&buf);
632 index_searchwild__node(root, &buf, key, 0, &out);
633 buf_release(&buf);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200634 return out;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200635}
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200636
637#include <sys/mman.h>
638#include <sys/stat.h>
639#include <unistd.h>
640
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200641static const char _idx_empty_str[] = "";
642
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200643/**************************************************************************/
644/*
645 * Alternative implementation, using mmap to map all the file to memory when
646 * starting
647 */
648struct index_mm {
649 struct kmod_ctx *ctx;
650 void *mm;
651 uint32_t root_offset;
652 size_t size;
653};
654
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200655struct index_mm_value {
656 unsigned int priority;
657 unsigned int len;
658 const char *value;
659};
660
661struct index_mm_value_array {
662 struct index_mm_value *values;
663 unsigned int len;
664};
665
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200666struct index_mm_node {
667 struct index_mm *idx;
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200668 const char *prefix; /* mmape'd value */
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200669 struct index_mm_value_array values;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200670 unsigned char first;
671 unsigned char last;
672 uint32_t children[];
673};
674
675static inline uint32_t read_long_mm(void **p)
676{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200677 uint8_t *addr = *(uint8_t **)p;
678 uint32_t v;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200679
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200680 /* addr may be unalined to uint32_t */
Lucas De Marchi5bbec8c2012-05-23 19:32:58 -0300681 v = get_unaligned((uint32_t *) addr);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200682
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200683 *p = addr + sizeof(uint32_t);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200684 return ntohl(v);
685}
686
687static inline uint8_t read_char_mm(void **p)
688{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200689 uint8_t *addr = *(uint8_t **)p;
690 uint8_t v = *addr;
691 *p = addr + sizeof(uint8_t);
692 return v;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200693}
694
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200695static inline char *read_chars_mm(void **p, unsigned *rlen)
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200696{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200697 char *addr = *(char **)p;
698 size_t len = *rlen = strlen(addr);
699 *p = addr + len + 1;
700 return addr;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200701}
702
703static struct index_mm_node *index_mm_read_node(struct index_mm *idx,
704 uint32_t offset) {
705 void *p = idx->mm;
706 struct index_mm_node *node;
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200707 const char *prefix;
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200708 int i, child_count, value_count, children_padding;
709 uint32_t children[INDEX_CHILDMAX];
710 char first, last;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200711
712 if ((offset & INDEX_NODE_MASK) == 0)
713 return NULL;
714
715 p = (char *)p + (offset & INDEX_NODE_MASK);
716
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200717 if (offset & INDEX_NODE_PREFIX) {
718 unsigned len;
719 prefix = read_chars_mm(&p, &len);
720 } else
721 prefix = _idx_empty_str;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200722
723 if (offset & INDEX_NODE_CHILDS) {
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200724 first = read_char_mm(&p);
725 last = read_char_mm(&p);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200726 child_count = last - first + 1;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200727 for (i = 0; i < child_count; i++)
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200728 children[i] = read_long_mm(&p);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200729 } else {
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200730 first = INDEX_CHILDMAX;
731 last = 0;
732 child_count = 0;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200733 }
734
Gustavo Sverzut Barbieric6824b62011-12-21 18:23:58 -0200735 children_padding = (sizeof(struct index_mm_node) +
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200736 (sizeof(uint32_t) * child_count)) % sizeof(void *);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200737
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200738 if (offset & INDEX_NODE_VALUES)
739 value_count = read_long_mm(&p);
740 else
741 value_count = 0;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200742
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200743 node = malloc(sizeof(struct index_mm_node)
744 + sizeof(uint32_t) * child_count + children_padding
745 + sizeof(struct index_mm_value) * value_count);
746 if (node == NULL)
747 return NULL;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200748
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200749 node->idx = idx;
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200750 node->prefix = prefix;
751 if (value_count == 0)
752 node->values.values = NULL;
753 else {
754 node->values.values = (struct index_mm_value *)
755 ((char *)node + sizeof(struct index_mm_node) +
756 sizeof(uint32_t) * child_count + children_padding);
757 }
758 node->values.len = value_count;
759 node->first = first;
760 node->last = last;
761 memcpy(node->children, children, sizeof(uint32_t) * child_count);
762
763 for (i = 0; i < value_count; i++) {
764 struct index_mm_value *v = node->values.values + i;
765 v->priority = read_long_mm(&p);
766 v->value = read_chars_mm(&p, &v->len);
767 }
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200768
769 return node;
770}
771
772static void index_mm_free_node(struct index_mm_node *node)
773{
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200774 free(node);
775}
776
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200777struct index_mm *index_mm_open(struct kmod_ctx *ctx, const char *filename,
Lucas De Marchi2e2e2522012-03-02 20:33:26 -0300778 unsigned long long *stamp)
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200779{
780 int fd;
781 struct stat st;
782 struct index_mm *idx;
783 struct {
784 uint32_t magic;
785 uint32_t version;
786 uint32_t root_offset;
787 } hdr;
788 void *p;
789
790 DBG(ctx, "file=%s\n", filename);
791
Lucas De Marchi7d51d8b2011-12-12 18:41:57 -0200792 idx = malloc(sizeof(*idx));
793 if (idx == NULL) {
Gustavo Sverzut Barbieridfa96f12012-01-07 19:37:37 -0200794 ERR(ctx, "malloc: %m\n");
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200795 return NULL;
796 }
797
Cristian Rodríguez79e5ea92011-12-16 02:49:54 -0300798 if ((fd = open(filename, O_RDONLY|O_CLOEXEC)) < 0) {
Lucas De Marchi73298172012-02-13 21:58:36 -0200799 DBG(ctx, "open(%s, O_RDONLY|O_CLOEXEC): %m\n", filename);
Lucas De Marchi7d51d8b2011-12-12 18:41:57 -0200800 goto fail_open;
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200801 }
802
Leandro Pereirad36c8862014-04-28 20:44:14 -0300803 if (fstat(fd, &st) < 0)
804 goto fail_nommap;
Lucas De Marchi5b05c322012-06-06 09:36:29 -0300805 if ((size_t) st.st_size < sizeof(hdr))
806 goto fail_nommap;
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200807
Kees Cookc3e8d262013-02-18 12:02:34 -0800808 if ((idx->mm = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0))
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200809 == MAP_FAILED) {
Kees Cookc3e8d262013-02-18 12:02:34 -0800810 ERR(ctx, "mmap(NULL, %"PRIu64", PROT_READ, %d, MAP_PRIVATE, 0): %m\n",
Lucas De Marchi2e2e2522012-03-02 20:33:26 -0300811 st.st_size, fd);
Lucas De Marchi5b05c322012-06-06 09:36:29 -0300812 goto fail_nommap;
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200813 }
814
815 p = idx->mm;
816 hdr.magic = read_long_mm(&p);
817 hdr.version = read_long_mm(&p);
818 hdr.root_offset = read_long_mm(&p);
819
820 if (hdr.magic != INDEX_MAGIC) {
821 ERR(ctx, "magic check fail: %x instead of %x\n", hdr.magic,
822 INDEX_MAGIC);
823 goto fail;
824 }
825
826 if (hdr.version >> 16 != INDEX_VERSION_MAJOR) {
827 ERR(ctx, "major version check fail: %u instead of %u\n",
Holger Obermaier1a4aa7e2014-09-04 14:38:16 +0200828 hdr.version >> 16, INDEX_VERSION_MAJOR);
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200829 goto fail;
830 }
831
832 idx->root_offset = hdr.root_offset;
833 idx->size = st.st_size;
834 idx->ctx = ctx;
835 close(fd);
836
Lucas De Marchi6068aaa2012-01-17 12:10:42 -0200837 *stamp = stat_mstamp(&st);
Lucas De Marchi9fd58f32011-12-31 18:53:24 -0200838
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200839 return idx;
840
841fail:
Lucas De Marchi5b05c322012-06-06 09:36:29 -0300842 munmap(idx->mm, st.st_size);
843fail_nommap:
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200844 close(fd);
Gustavo Sverzut Barbieria5a92a62011-12-16 16:17:50 -0200845fail_open:
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200846 free(idx);
847 return NULL;
848}
849
850void index_mm_close(struct index_mm *idx)
851{
852 munmap(idx->mm, idx->size);
853 free(idx);
854}
Lucas De Marchi77bf9362011-12-02 17:41:30 -0200855
856static struct index_mm_node *index_mm_readroot(struct index_mm *idx)
857{
858 return index_mm_read_node(idx, idx->root_offset);
859}
Lucas De Marchi91298dc2011-12-02 17:41:46 -0200860
861static struct index_mm_node *index_mm_readchild(const struct index_mm_node *parent,
862 int ch)
863{
864 if (parent->first <= ch && ch <= parent->last) {
865 return index_mm_read_node(parent->idx,
866 parent->children[ch - parent->first]);
867 }
868
869 return NULL;
870}
Lucas De Marchie33bb872011-12-02 17:45:01 -0200871
Lucas De Marchi758428a2012-01-16 15:56:17 -0200872static void index_mm_dump_node(struct index_mm_node *node, struct buffer *buf,
873 int fd)
874{
875 struct index_mm_value *itr, *itr_end;
876 int ch, pushed;
877
878 pushed = buf_pushchars(buf, node->prefix);
879
880 itr = node->values.values;
881 itr_end = itr + node->values.len;
882 for (; itr < itr_end; itr++) {
883 write_str_safe(fd, buf->bytes, buf->used);
884 write_str_safe(fd, " ", 1);
885 write_str_safe(fd, itr->value, itr->len);
886 write_str_safe(fd, "\n", 1);
887 }
888
889 for (ch = node->first; ch <= node->last; ch++) {
890 struct index_mm_node *child = index_mm_readchild(node, ch);
891
892 if (child == NULL)
893 continue;
894
895 buf_pushchar(buf, ch);
896 index_mm_dump_node(child, buf, fd);
897 buf_popchar(buf);
898 }
899
900 buf_popchars(buf, pushed);
901 index_mm_free_node(node);
902}
903
904void index_mm_dump(struct index_mm *idx, int fd, const char *prefix)
905{
906 struct index_mm_node *root;
907 struct buffer buf;
908
Lucas De Marchi681bf892013-04-23 21:21:00 -0300909 root = index_mm_readroot(idx);
910 if (root == NULL)
911 return;
912
Lucas De Marchi758428a2012-01-16 15:56:17 -0200913 buf_init(&buf);
914 buf_pushchars(&buf, prefix);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200915 index_mm_dump_node(root, &buf, fd);
916 buf_release(&buf);
917}
918
Lucas De Marchie33bb872011-12-02 17:45:01 -0200919static char *index_mm_search_node(struct index_mm_node *node, const char *key,
920 int i)
921{
922 char *value;
923 struct index_mm_node *child;
924 int ch;
925 int j;
926
927 while(node) {
928 for (j = 0; node->prefix[j]; j++) {
929 ch = node->prefix[j];
930
931 if (ch != key[i+j]) {
932 index_mm_free_node(node);
933 return NULL;
934 }
935 }
936
937 i += j;
938
939 if (key[i] == '\0') {
Lucas De Marchi817f4e32012-02-27 19:54:33 -0300940 value = node->values.len > 0
941 ? strdup(node->values.values[0].value)
942 : NULL;
943
944 index_mm_free_node(node);
945 return value;
Lucas De Marchie33bb872011-12-02 17:45:01 -0200946 }
947
948 child = index_mm_readchild(node, key[i]);
949 index_mm_free_node(node);
950 node = child;
951 i++;
952 }
953
954 return NULL;
955}
Lucas De Marchib797b792011-12-02 17:49:03 -0200956
957/*
958 * Search the index for a key
959 *
960 * Returns the value of the first match
961 *
962 * The recursive functions free their node argument (using index_close).
963 */
964char *index_mm_search(struct index_mm *idx, const char *key)
965{
Lucas De Marchiee1d1882012-02-27 18:48:02 -0300966// FIXME: return value by reference instead of strdup
Lucas De Marchib797b792011-12-02 17:49:03 -0200967 struct index_mm_node *root;
968 char *value;
969
970 root = index_mm_readroot(idx);
971 value = index_mm_search_node(root, key, 0);
972
973 return value;
974}
Lucas De Marchibf89f702011-12-02 18:23:36 -0200975
976/* Level 4: add all the values from a matching node */
977static void index_mm_searchwild_allvalues(struct index_mm_node *node,
978 struct index_value **out)
979{
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200980 struct index_mm_value *itr, *itr_end;
Lucas De Marchibf89f702011-12-02 18:23:36 -0200981
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200982 itr = node->values.values;
983 itr_end = itr + node->values.len;
984 for (; itr < itr_end; itr++)
985 add_value(out, itr->value, itr->len, itr->priority);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200986
987 index_mm_free_node(node);
988}
989
990/*
991 * Level 3: traverse a sub-keyspace which starts with a wildcard,
992 * looking for matches.
993 */
994static void index_mm_searchwild_all(struct index_mm_node *node, int j,
995 struct buffer *buf,
996 const char *subkey,
997 struct index_value **out)
998{
999 int pushed = 0;
1000 int ch;
1001
1002 while (node->prefix[j]) {
1003 ch = node->prefix[j];
1004
1005 buf_pushchar(buf, ch);
1006 pushed++;
1007 j++;
1008 }
1009
1010 for (ch = node->first; ch <= node->last; ch++) {
1011 struct index_mm_node *child = index_mm_readchild(node, ch);
1012
1013 if (!child)
1014 continue;
1015
1016 buf_pushchar(buf, ch);
1017 index_mm_searchwild_all(child, 0, buf, subkey, out);
1018 buf_popchar(buf);
1019 }
1020
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -02001021 if (node->values.len > 0) {
Lucas De Marchibf89f702011-12-02 18:23:36 -02001022 if (fnmatch(buf_str(buf), subkey, 0) == 0)
1023 index_mm_searchwild_allvalues(node, out);
Gustavo Sverzut Barbieri27fdf632011-12-10 13:28:18 -02001024 else
1025 index_mm_free_node(node);
Lucas De Marchibf89f702011-12-02 18:23:36 -02001026 } else {
1027 index_mm_free_node(node);
1028 }
1029
1030 buf_popchars(buf, pushed);
1031}
1032
1033/* Level 2: descend the tree (until we hit a wildcard) */
1034static void index_mm_searchwild_node(struct index_mm_node *node,
1035 struct buffer *buf,
1036 const char *key, int i,
1037 struct index_value **out)
1038{
1039 struct index_mm_node *child;
1040 int j;
1041 int ch;
1042
1043 while(node) {
1044 for (j = 0; node->prefix[j]; j++) {
1045 ch = node->prefix[j];
1046
1047 if (ch == '*' || ch == '?' || ch == '[') {
1048 index_mm_searchwild_all(node, j, buf,
1049 &key[i+j], out);
1050 return;
1051 }
1052
1053 if (ch != key[i+j]) {
1054 index_mm_free_node(node);
1055 return;
1056 }
1057 }
1058
1059 i += j;
1060
1061 child = index_mm_readchild(node, '*');
1062 if (child) {
1063 buf_pushchar(buf, '*');
1064 index_mm_searchwild_all(child, 0, buf, &key[i], out);
1065 buf_popchar(buf);
1066 }
1067
1068 child = index_mm_readchild(node, '?');
1069 if (child) {
1070 buf_pushchar(buf, '?');
1071 index_mm_searchwild_all(child, 0, buf, &key[i], out);
1072 buf_popchar(buf);
1073 }
1074
1075 child = index_mm_readchild(node, '[');
1076 if (child) {
1077 buf_pushchar(buf, '[');
1078 index_mm_searchwild_all(child, 0, buf, &key[i], out);
1079 buf_popchar(buf);
1080 }
1081
1082 if (key[i] == '\0') {
1083 index_mm_searchwild_allvalues(node, out);
1084
1085 return;
1086 }
1087
1088 child = index_mm_readchild(node, key[i]);
1089 index_mm_free_node(node);
1090 node = child;
1091 i++;
1092 }
1093}
1094
1095/*
1096 * Search the index for a key. The index may contain wildcards.
1097 *
1098 * Returns a list of all the values of matching keys.
1099 */
1100struct index_value *index_mm_searchwild(struct index_mm *idx, const char *key)
1101{
1102 struct index_mm_node *root = index_mm_readroot(idx);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -02001103 struct buffer buf;
Lucas De Marchibf89f702011-12-02 18:23:36 -02001104 struct index_value *out = NULL;
1105
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -02001106 buf_init(&buf);
1107 index_mm_searchwild_node(root, &buf, key, 0, &out);
1108 buf_release(&buf);
Lucas De Marchibf89f702011-12-02 18:23:36 -02001109 return out;
1110}