blob: 6eddf3c315f9afcebcc612d740823de2b3d9cd26 [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
Lucas De Marchic2e42862014-10-03 01:41:42 -030021#include <arpa/inet.h>
22#include <assert.h>
Lucas De Marchie8847fd2011-11-30 15:23:28 -020023#include <errno.h>
24#include <fnmatch.h>
Lucas De Marchibfcd31d2012-03-02 21:28:11 -030025#include <inttypes.h>
Lucas De Marchic2e42862014-10-03 01:41:42 -030026#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
Lucas De Marchie8847fd2011-11-30 15:23:28 -020029
Lucas De Marchi576dd432014-10-02 22:03:19 -030030#include <shared/macro.h>
Lucas De Marchib4d1f442014-10-11 13:03:21 -030031#include <shared/strbuf.h>
Lucas De Marchi96573a02014-10-03 00:01:35 -030032#include <shared/util.h>
Lucas De Marchi576dd432014-10-02 22:03:19 -030033
Lucas De Marchi83b855a2013-07-04 16:13:11 -030034#include "libkmod-internal.h"
Lucas De Marchie8847fd2011-11-30 15:23:28 -020035#include "libkmod-index.h"
Lucas De Marchie8847fd2011-11-30 15:23:28 -020036
Lucas De Marchi8f923be2011-12-03 04:28:49 -020037/* index.c: module index file shared functions for modprobe and depmod */
38
Gustavo Sverzut Barbieri148226e2011-12-10 11:53:51 -020039#define INDEX_CHILDMAX 128
40
41/* Disk format:
42
43 uint32_t magic = INDEX_MAGIC;
44 uint32_t version = INDEX_VERSION;
45 uint32_t root_offset;
46
47 (node_offset & INDEX_NODE_MASK) specifies the file offset of nodes:
48
49 char[] prefix; // nul terminated
50
51 char first;
52 char last;
53 uint32_t children[last - first + 1];
54
55 uint32_t value_count;
56 struct {
57 uint32_t priority;
58 char[] value; // nul terminated
59 } values[value_count];
60
61 (node_offset & INDEX_NODE_FLAGS) indicates which fields are present.
62 Empty prefixes are omitted, leaf nodes omit the three child-related fields.
63
64 This could be optimised further by adding a sparse child format
65 (indicated using a new flag).
66 */
67
68/* Format of node offsets within index file */
69enum node_offset {
70 INDEX_NODE_FLAGS = 0xF0000000, /* Flags in high nibble */
71 INDEX_NODE_PREFIX = 0x80000000,
72 INDEX_NODE_VALUES = 0x40000000,
73 INDEX_NODE_CHILDS = 0x20000000,
74
75 INDEX_NODE_MASK = 0x0FFFFFFF, /* Offset value */
76};
77
Lucas De Marchie8847fd2011-11-30 15:23:28 -020078void index_values_free(struct index_value *values)
79{
80 while (values) {
81 struct index_value *value = values;
82
83 values = value->next;
84 free(value);
85 }
86}
87
Lucas De Marchie8847fd2011-11-30 15:23:28 -020088static int add_value(struct index_value **values,
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -020089 const char *value, unsigned len, unsigned int priority)
Lucas De Marchie8847fd2011-11-30 15:23:28 -020090{
91 struct index_value *v;
Lucas De Marchie8847fd2011-11-30 15:23:28 -020092
93 /* find position to insert value */
94 while (*values && (*values)->priority < priority)
95 values = &(*values)->next;
96
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -020097 v = malloc(sizeof(struct index_value) + len + 1);
98 if (!v)
99 return -1;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200100 v->next = *values;
101 v->priority = priority;
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200102 v->len = len;
103 memcpy(v->value, value, len);
104 v->value[len] = '\0';
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200105 *values = v;
106
Gustavo Sverzut Barbieri558b0202011-12-08 16:36:48 -0200107 return 0;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200108}
109
Lucas De Marchi93688882011-12-02 10:05:31 -0200110static void read_error(void)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200111{
112 fatal("Module index: unexpected error: %s\n"
113 "Try re-running depmod\n", errno ? strerror(errno) : "EOF");
114}
115
116static int read_char(FILE *in)
117{
118 int ch;
119
120 errno = 0;
121 ch = getc_unlocked(in);
122 if (ch == EOF)
123 read_error();
124 return ch;
125}
126
127static uint32_t read_long(FILE *in)
128{
129 uint32_t l;
130
131 errno = 0;
Leandro Pereirab6d985c2014-04-28 20:47:49 -0300132 if (fread(&l, sizeof(uint32_t), 1, in) != sizeof(uint32_t))
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200133 read_error();
134 return ntohl(l);
135}
136
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300137static unsigned buf_freadchars(struct strbuf *buf, FILE *in)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200138{
139 unsigned i = 0;
140 int ch;
141
142 while ((ch = read_char(in))) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300143 if (!strbuf_pushchar(buf, ch))
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200144 break;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200145 i++;
146 }
147
148 return i;
149}
150
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200151/*
Lucas De Marchieb8bb322011-12-02 10:23:02 -0200152 * Index file searching
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200153 */
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200154struct index_node_f {
155 FILE *file;
156 char *prefix; /* path compression */
157 struct index_value *values;
158 unsigned char first; /* range of child nodes */
159 unsigned char last;
160 uint32_t children[0];
161};
162
163static struct index_node_f *index_read(FILE *in, uint32_t offset)
164{
165 struct index_node_f *node;
166 char *prefix;
167 int i, child_count = 0;
168
169 if ((offset & INDEX_NODE_MASK) == 0)
170 return NULL;
171
172 fseek(in, offset & INDEX_NODE_MASK, SEEK_SET);
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200173
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200174 if (offset & INDEX_NODE_PREFIX) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300175 struct strbuf buf;
176 strbuf_init(&buf);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200177 buf_freadchars(&buf, in);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300178 prefix = strbuf_steal(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200179 } else
180 prefix = NOFAIL(strdup(""));
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200181
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200182 if (offset & INDEX_NODE_CHILDS) {
183 char first = read_char(in);
184 char last = read_char(in);
185 child_count = last - first + 1;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200186
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200187 node = NOFAIL(malloc(sizeof(struct index_node_f) +
188 sizeof(uint32_t) * child_count));
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200189
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200190 node->first = first;
191 node->last = last;
192
193 for (i = 0; i < child_count; i++)
194 node->children[i] = read_long(in);
195 } else {
196 node = NOFAIL(malloc(sizeof(struct index_node_f)));
197 node->first = INDEX_CHILDMAX;
198 node->last = 0;
199 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200200
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200201 node->values = NULL;
202 if (offset & INDEX_NODE_VALUES) {
203 int value_count;
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300204 struct strbuf buf;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200205 const char *value;
206 unsigned int priority;
207
208 value_count = read_long(in);
209
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300210 strbuf_init(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200211 while (value_count--) {
212 priority = read_long(in);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200213 buf_freadchars(&buf, in);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300214 value = strbuf_str(&buf);
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200215 add_value(&node->values, value, buf.used, priority);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300216 strbuf_clear(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200217 }
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300218 strbuf_release(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200219 }
220
221 node->prefix = prefix;
222 node->file = in;
223 return node;
224}
225
226static void index_close(struct index_node_f *node)
227{
228 free(node->prefix);
229 index_values_free(node->values);
230 free(node);
231}
232
233struct index_file {
234 FILE *file;
235 uint32_t root_offset;
236};
237
238/* Failures are silent; modprobe will fall back to text files */
239struct index_file *index_file_open(const char *filename)
240{
241 FILE *file;
242 uint32_t magic, version;
243 struct index_file *new;
244
Cristian Rodríguez79e5ea92011-12-16 02:49:54 -0300245 file = fopen(filename, "re");
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200246 if (!file)
247 return NULL;
248 errno = EINVAL;
249
250 magic = read_long(file);
Cristian Rodríguez67d94ad2011-12-23 03:06:56 -0200251 if (magic != INDEX_MAGIC) {
252 fclose(file);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200253 return NULL;
Cristian Rodríguez67d94ad2011-12-23 03:06:56 -0200254 }
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200255
256 version = read_long(file);
Cristian Rodríguez4088b272011-12-26 01:38:04 -0300257 if (version >> 16 != INDEX_VERSION_MAJOR) {
258 fclose(file);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200259 return NULL;
Cristian Rodríguez4088b272011-12-26 01:38:04 -0300260 }
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200261
262 new = NOFAIL(malloc(sizeof(struct index_file)));
263 new->file = file;
264 new->root_offset = read_long(new->file);
265
266 errno = 0;
267 return new;
268}
269
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200270void index_file_close(struct index_file *idx)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200271{
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200272 fclose(idx->file);
273 free(idx);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200274}
275
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200276static struct index_node_f *index_readroot(struct index_file *in)
277{
278 return index_read(in->file, in->root_offset);
279}
280
281static struct index_node_f *index_readchild(const struct index_node_f *parent,
282 int ch)
283{
Lucas De Marchie71970a2011-12-02 10:27:15 -0200284 if (parent->first <= ch && ch <= parent->last) {
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200285 return index_read(parent->file,
286 parent->children[ch - parent->first]);
Lucas De Marchie71970a2011-12-02 10:27:15 -0200287 }
288
289 return NULL;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200290}
291
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300292static void index_dump_node(struct index_node_f *node, struct strbuf *buf,
Lucas De Marchi758428a2012-01-16 15:56:17 -0200293 int fd)
294{
295 struct index_value *v;
296 int ch, pushed;
297
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300298 pushed = strbuf_pushchars(buf, node->prefix);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200299
300 for (v = node->values; v != NULL; v = v->next) {
301 write_str_safe(fd, buf->bytes, buf->used);
302 write_str_safe(fd, " ", 1);
303 write_str_safe(fd, v->value, strlen(v->value));
304 write_str_safe(fd, "\n", 1);
305 }
306
307 for (ch = node->first; ch <= node->last; ch++) {
308 struct index_node_f *child = index_readchild(node, ch);
309
310 if (!child)
311 continue;
312
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300313 strbuf_pushchar(buf, ch);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200314 index_dump_node(child, buf, fd);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300315 strbuf_popchar(buf);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200316 }
317
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300318 strbuf_popchars(buf, pushed);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200319 index_close(node);
320}
321
322void index_dump(struct index_file *in, int fd, const char *prefix)
323{
324 struct index_node_f *root;
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300325 struct strbuf buf;
Lucas De Marchi758428a2012-01-16 15:56:17 -0200326
Lucas De Marchi681bf892013-04-23 21:21:00 -0300327 root = index_readroot(in);
328 if (root == NULL)
329 return;
330
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300331 strbuf_init(&buf);
332 strbuf_pushchars(&buf, prefix);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200333 index_dump_node(root, &buf, fd);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300334 strbuf_release(&buf);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200335}
336
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200337static char *index_search__node(struct index_node_f *node, const char *key, int i)
338{
339 char *value;
340 struct index_node_f *child;
341 int ch;
342 int j;
343
344 while(node) {
345 for (j = 0; node->prefix[j]; j++) {
346 ch = node->prefix[j];
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200347
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200348 if (ch != key[i+j]) {
349 index_close(node);
350 return NULL;
351 }
352 }
Lucas De Marchie71970a2011-12-02 10:27:15 -0200353
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200354 i += j;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200355
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200356 if (key[i] == '\0') {
Lucas De Marchi817f4e32012-02-27 19:54:33 -0300357 value = node->values != NULL
358 ? strdup(node->values[0].value)
359 : NULL;
360
361 index_close(node);
362 return value;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200363 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200364
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200365 child = index_readchild(node, key[i]);
366 index_close(node);
367 node = child;
368 i++;
369 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200370
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200371 return NULL;
372}
373
374/*
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200375 * Search the index for a key
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200376 *
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200377 * Returns the value of the first match
378 *
379 * The recursive functions free their node argument (using index_close).
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200380 */
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200381char *index_search(struct index_file *in, const char *key)
382{
Lucas De Marchiee1d1882012-02-27 18:48:02 -0300383// FIXME: return value by reference instead of strdup
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200384 struct index_node_f *root;
385 char *value;
386
387 root = index_readroot(in);
388 value = index_search__node(root, key, 0);
389
390 return value;
391}
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200392
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200393
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200394
395/* Level 4: add all the values from a matching node */
396static void index_searchwild__allvalues(struct index_node_f *node,
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200397 struct index_value **out)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200398{
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200399 struct index_value *v;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200400
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200401 for (v = node->values; v != NULL; v = v->next)
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200402 add_value(out, v->value, v->len, v->priority);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200403
404 index_close(node);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200405}
406
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200407/*
408 * Level 3: traverse a sub-keyspace which starts with a wildcard,
409 * looking for matches.
410 */
411static void index_searchwild__all(struct index_node_f *node, int j,
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300412 struct strbuf *buf,
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200413 const char *subkey,
414 struct index_value **out)
415{
416 int pushed = 0;
417 int ch;
418
419 while (node->prefix[j]) {
420 ch = node->prefix[j];
421
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300422 strbuf_pushchar(buf, ch);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200423 pushed++;
424 j++;
425 }
426
427 for (ch = node->first; ch <= node->last; ch++) {
428 struct index_node_f *child = index_readchild(node, ch);
429
430 if (!child)
431 continue;
432
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300433 strbuf_pushchar(buf, ch);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200434 index_searchwild__all(child, 0, buf, subkey, out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300435 strbuf_popchar(buf);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200436 }
437
438 if (node->values) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300439 if (fnmatch(strbuf_str(buf), subkey, 0) == 0)
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200440 index_searchwild__allvalues(node, out);
Gustavo Sverzut Barbieri27fdf632011-12-10 13:28:18 -0200441 else
442 index_close(node);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200443 } else {
444 index_close(node);
445 }
446
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300447 strbuf_popchars(buf, pushed);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200448}
449
450/* Level 2: descend the tree (until we hit a wildcard) */
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200451static void index_searchwild__node(struct index_node_f *node,
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300452 struct strbuf *buf,
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200453 const char *key, int i,
454 struct index_value **out)
455{
456 struct index_node_f *child;
457 int j;
458 int ch;
459
460 while(node) {
461 for (j = 0; node->prefix[j]; j++) {
462 ch = node->prefix[j];
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200463
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200464 if (ch == '*' || ch == '?' || ch == '[') {
465 index_searchwild__all(node, j, buf,
466 &key[i+j], out);
467 return;
468 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200469
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200470 if (ch != key[i+j]) {
471 index_close(node);
472 return;
473 }
474 }
Lucas De Marchie71970a2011-12-02 10:27:15 -0200475
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200476 i += j;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200477
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200478 child = index_readchild(node, '*');
479 if (child) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300480 strbuf_pushchar(buf, '*');
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200481 index_searchwild__all(child, 0, buf, &key[i], out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300482 strbuf_popchar(buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200483 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200484
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200485 child = index_readchild(node, '?');
486 if (child) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300487 strbuf_pushchar(buf, '?');
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200488 index_searchwild__all(child, 0, buf, &key[i], out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300489 strbuf_popchar(buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200490 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200491
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200492 child = index_readchild(node, '[');
493 if (child) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300494 strbuf_pushchar(buf, '[');
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200495 index_searchwild__all(child, 0, buf, &key[i], out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300496 strbuf_popchar(buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200497 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200498
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200499 if (key[i] == '\0') {
500 index_searchwild__allvalues(node, out);
501
502 return;
503 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200504
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200505 child = index_readchild(node, key[i]);
506 index_close(node);
507 node = child;
508 i++;
509 }
510}
511
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200512/*
513 * Search the index for a key. The index may contain wildcards.
514 *
515 * Returns a list of all the values of matching keys.
516 */
517struct index_value *index_searchwild(struct index_file *in, const char *key)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200518{
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200519 struct index_node_f *root = index_readroot(in);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300520 struct strbuf buf;
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200521 struct index_value *out = NULL;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200522
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300523 strbuf_init(&buf);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200524 index_searchwild__node(root, &buf, key, 0, &out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300525 strbuf_release(&buf);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200526 return out;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200527}
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200528
529#include <sys/mman.h>
530#include <sys/stat.h>
531#include <unistd.h>
532
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200533static const char _idx_empty_str[] = "";
534
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200535/**************************************************************************/
536/*
537 * Alternative implementation, using mmap to map all the file to memory when
538 * starting
539 */
540struct index_mm {
541 struct kmod_ctx *ctx;
542 void *mm;
543 uint32_t root_offset;
544 size_t size;
545};
546
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200547struct index_mm_value {
548 unsigned int priority;
549 unsigned int len;
550 const char *value;
551};
552
553struct index_mm_value_array {
554 struct index_mm_value *values;
555 unsigned int len;
556};
557
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200558struct index_mm_node {
559 struct index_mm *idx;
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200560 const char *prefix; /* mmape'd value */
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200561 struct index_mm_value_array values;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200562 unsigned char first;
563 unsigned char last;
564 uint32_t children[];
565};
566
567static inline uint32_t read_long_mm(void **p)
568{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200569 uint8_t *addr = *(uint8_t **)p;
570 uint32_t v;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200571
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200572 /* addr may be unalined to uint32_t */
Lucas De Marchi5bbec8c2012-05-23 19:32:58 -0300573 v = get_unaligned((uint32_t *) addr);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200574
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200575 *p = addr + sizeof(uint32_t);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200576 return ntohl(v);
577}
578
579static inline uint8_t read_char_mm(void **p)
580{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200581 uint8_t *addr = *(uint8_t **)p;
582 uint8_t v = *addr;
583 *p = addr + sizeof(uint8_t);
584 return v;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200585}
586
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200587static inline char *read_chars_mm(void **p, unsigned *rlen)
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200588{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200589 char *addr = *(char **)p;
590 size_t len = *rlen = strlen(addr);
591 *p = addr + len + 1;
592 return addr;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200593}
594
595static struct index_mm_node *index_mm_read_node(struct index_mm *idx,
596 uint32_t offset) {
597 void *p = idx->mm;
598 struct index_mm_node *node;
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200599 const char *prefix;
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200600 int i, child_count, value_count, children_padding;
601 uint32_t children[INDEX_CHILDMAX];
602 char first, last;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200603
604 if ((offset & INDEX_NODE_MASK) == 0)
605 return NULL;
606
607 p = (char *)p + (offset & INDEX_NODE_MASK);
608
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200609 if (offset & INDEX_NODE_PREFIX) {
610 unsigned len;
611 prefix = read_chars_mm(&p, &len);
612 } else
613 prefix = _idx_empty_str;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200614
615 if (offset & INDEX_NODE_CHILDS) {
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200616 first = read_char_mm(&p);
617 last = read_char_mm(&p);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200618 child_count = last - first + 1;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200619 for (i = 0; i < child_count; i++)
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200620 children[i] = read_long_mm(&p);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200621 } else {
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200622 first = INDEX_CHILDMAX;
623 last = 0;
624 child_count = 0;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200625 }
626
Gustavo Sverzut Barbieric6824b62011-12-21 18:23:58 -0200627 children_padding = (sizeof(struct index_mm_node) +
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200628 (sizeof(uint32_t) * child_count)) % sizeof(void *);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200629
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200630 if (offset & INDEX_NODE_VALUES)
631 value_count = read_long_mm(&p);
632 else
633 value_count = 0;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200634
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200635 node = malloc(sizeof(struct index_mm_node)
636 + sizeof(uint32_t) * child_count + children_padding
637 + sizeof(struct index_mm_value) * value_count);
638 if (node == NULL)
639 return NULL;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200640
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200641 node->idx = idx;
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200642 node->prefix = prefix;
643 if (value_count == 0)
644 node->values.values = NULL;
645 else {
646 node->values.values = (struct index_mm_value *)
647 ((char *)node + sizeof(struct index_mm_node) +
648 sizeof(uint32_t) * child_count + children_padding);
649 }
650 node->values.len = value_count;
651 node->first = first;
652 node->last = last;
653 memcpy(node->children, children, sizeof(uint32_t) * child_count);
654
655 for (i = 0; i < value_count; i++) {
656 struct index_mm_value *v = node->values.values + i;
657 v->priority = read_long_mm(&p);
658 v->value = read_chars_mm(&p, &v->len);
659 }
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200660
661 return node;
662}
663
664static void index_mm_free_node(struct index_mm_node *node)
665{
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200666 free(node);
667}
668
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200669struct index_mm *index_mm_open(struct kmod_ctx *ctx, const char *filename,
Lucas De Marchi2e2e2522012-03-02 20:33:26 -0300670 unsigned long long *stamp)
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200671{
672 int fd;
673 struct stat st;
674 struct index_mm *idx;
675 struct {
676 uint32_t magic;
677 uint32_t version;
678 uint32_t root_offset;
679 } hdr;
680 void *p;
681
682 DBG(ctx, "file=%s\n", filename);
683
Lucas De Marchi7d51d8b2011-12-12 18:41:57 -0200684 idx = malloc(sizeof(*idx));
685 if (idx == NULL) {
Gustavo Sverzut Barbieridfa96f12012-01-07 19:37:37 -0200686 ERR(ctx, "malloc: %m\n");
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200687 return NULL;
688 }
689
Cristian Rodríguez79e5ea92011-12-16 02:49:54 -0300690 if ((fd = open(filename, O_RDONLY|O_CLOEXEC)) < 0) {
Lucas De Marchi73298172012-02-13 21:58:36 -0200691 DBG(ctx, "open(%s, O_RDONLY|O_CLOEXEC): %m\n", filename);
Lucas De Marchi7d51d8b2011-12-12 18:41:57 -0200692 goto fail_open;
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200693 }
694
Leandro Pereirad36c8862014-04-28 20:44:14 -0300695 if (fstat(fd, &st) < 0)
696 goto fail_nommap;
Lucas De Marchi5b05c322012-06-06 09:36:29 -0300697 if ((size_t) st.st_size < sizeof(hdr))
698 goto fail_nommap;
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200699
Kees Cookc3e8d262013-02-18 12:02:34 -0800700 if ((idx->mm = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0))
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200701 == MAP_FAILED) {
Kees Cookc3e8d262013-02-18 12:02:34 -0800702 ERR(ctx, "mmap(NULL, %"PRIu64", PROT_READ, %d, MAP_PRIVATE, 0): %m\n",
Lucas De Marchi2e2e2522012-03-02 20:33:26 -0300703 st.st_size, fd);
Lucas De Marchi5b05c322012-06-06 09:36:29 -0300704 goto fail_nommap;
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200705 }
706
707 p = idx->mm;
708 hdr.magic = read_long_mm(&p);
709 hdr.version = read_long_mm(&p);
710 hdr.root_offset = read_long_mm(&p);
711
712 if (hdr.magic != INDEX_MAGIC) {
713 ERR(ctx, "magic check fail: %x instead of %x\n", hdr.magic,
714 INDEX_MAGIC);
715 goto fail;
716 }
717
718 if (hdr.version >> 16 != INDEX_VERSION_MAJOR) {
719 ERR(ctx, "major version check fail: %u instead of %u\n",
Holger Obermaier1a4aa7e2014-09-04 14:38:16 +0200720 hdr.version >> 16, INDEX_VERSION_MAJOR);
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200721 goto fail;
722 }
723
724 idx->root_offset = hdr.root_offset;
725 idx->size = st.st_size;
726 idx->ctx = ctx;
727 close(fd);
728
Lucas De Marchi6068aaa2012-01-17 12:10:42 -0200729 *stamp = stat_mstamp(&st);
Lucas De Marchi9fd58f32011-12-31 18:53:24 -0200730
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200731 return idx;
732
733fail:
Lucas De Marchi5b05c322012-06-06 09:36:29 -0300734 munmap(idx->mm, st.st_size);
735fail_nommap:
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200736 close(fd);
Gustavo Sverzut Barbieria5a92a62011-12-16 16:17:50 -0200737fail_open:
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200738 free(idx);
739 return NULL;
740}
741
742void index_mm_close(struct index_mm *idx)
743{
744 munmap(idx->mm, idx->size);
745 free(idx);
746}
Lucas De Marchi77bf9362011-12-02 17:41:30 -0200747
748static struct index_mm_node *index_mm_readroot(struct index_mm *idx)
749{
750 return index_mm_read_node(idx, idx->root_offset);
751}
Lucas De Marchi91298dc2011-12-02 17:41:46 -0200752
753static struct index_mm_node *index_mm_readchild(const struct index_mm_node *parent,
754 int ch)
755{
756 if (parent->first <= ch && ch <= parent->last) {
757 return index_mm_read_node(parent->idx,
758 parent->children[ch - parent->first]);
759 }
760
761 return NULL;
762}
Lucas De Marchie33bb872011-12-02 17:45:01 -0200763
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300764static void index_mm_dump_node(struct index_mm_node *node, struct strbuf *buf,
Lucas De Marchi758428a2012-01-16 15:56:17 -0200765 int fd)
766{
767 struct index_mm_value *itr, *itr_end;
768 int ch, pushed;
769
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300770 pushed = strbuf_pushchars(buf, node->prefix);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200771
772 itr = node->values.values;
773 itr_end = itr + node->values.len;
774 for (; itr < itr_end; itr++) {
775 write_str_safe(fd, buf->bytes, buf->used);
776 write_str_safe(fd, " ", 1);
777 write_str_safe(fd, itr->value, itr->len);
778 write_str_safe(fd, "\n", 1);
779 }
780
781 for (ch = node->first; ch <= node->last; ch++) {
782 struct index_mm_node *child = index_mm_readchild(node, ch);
783
784 if (child == NULL)
785 continue;
786
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300787 strbuf_pushchar(buf, ch);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200788 index_mm_dump_node(child, buf, fd);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300789 strbuf_popchar(buf);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200790 }
791
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300792 strbuf_popchars(buf, pushed);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200793 index_mm_free_node(node);
794}
795
796void index_mm_dump(struct index_mm *idx, int fd, const char *prefix)
797{
798 struct index_mm_node *root;
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300799 struct strbuf buf;
Lucas De Marchi758428a2012-01-16 15:56:17 -0200800
Lucas De Marchi681bf892013-04-23 21:21:00 -0300801 root = index_mm_readroot(idx);
802 if (root == NULL)
803 return;
804
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300805 strbuf_init(&buf);
806 strbuf_pushchars(&buf, prefix);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200807 index_mm_dump_node(root, &buf, fd);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300808 strbuf_release(&buf);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200809}
810
Lucas De Marchie33bb872011-12-02 17:45:01 -0200811static char *index_mm_search_node(struct index_mm_node *node, const char *key,
812 int i)
813{
814 char *value;
815 struct index_mm_node *child;
816 int ch;
817 int j;
818
819 while(node) {
820 for (j = 0; node->prefix[j]; j++) {
821 ch = node->prefix[j];
822
823 if (ch != key[i+j]) {
824 index_mm_free_node(node);
825 return NULL;
826 }
827 }
828
829 i += j;
830
831 if (key[i] == '\0') {
Lucas De Marchi817f4e32012-02-27 19:54:33 -0300832 value = node->values.len > 0
833 ? strdup(node->values.values[0].value)
834 : NULL;
835
836 index_mm_free_node(node);
837 return value;
Lucas De Marchie33bb872011-12-02 17:45:01 -0200838 }
839
840 child = index_mm_readchild(node, key[i]);
841 index_mm_free_node(node);
842 node = child;
843 i++;
844 }
845
846 return NULL;
847}
Lucas De Marchib797b792011-12-02 17:49:03 -0200848
849/*
850 * Search the index for a key
851 *
852 * Returns the value of the first match
853 *
854 * The recursive functions free their node argument (using index_close).
855 */
856char *index_mm_search(struct index_mm *idx, const char *key)
857{
Lucas De Marchiee1d1882012-02-27 18:48:02 -0300858// FIXME: return value by reference instead of strdup
Lucas De Marchib797b792011-12-02 17:49:03 -0200859 struct index_mm_node *root;
860 char *value;
861
862 root = index_mm_readroot(idx);
863 value = index_mm_search_node(root, key, 0);
864
865 return value;
866}
Lucas De Marchibf89f702011-12-02 18:23:36 -0200867
868/* Level 4: add all the values from a matching node */
869static void index_mm_searchwild_allvalues(struct index_mm_node *node,
870 struct index_value **out)
871{
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200872 struct index_mm_value *itr, *itr_end;
Lucas De Marchibf89f702011-12-02 18:23:36 -0200873
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200874 itr = node->values.values;
875 itr_end = itr + node->values.len;
876 for (; itr < itr_end; itr++)
877 add_value(out, itr->value, itr->len, itr->priority);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200878
879 index_mm_free_node(node);
880}
881
882/*
883 * Level 3: traverse a sub-keyspace which starts with a wildcard,
884 * looking for matches.
885 */
886static void index_mm_searchwild_all(struct index_mm_node *node, int j,
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300887 struct strbuf *buf,
Lucas De Marchibf89f702011-12-02 18:23:36 -0200888 const char *subkey,
889 struct index_value **out)
890{
891 int pushed = 0;
892 int ch;
893
894 while (node->prefix[j]) {
895 ch = node->prefix[j];
896
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300897 strbuf_pushchar(buf, ch);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200898 pushed++;
899 j++;
900 }
901
902 for (ch = node->first; ch <= node->last; ch++) {
903 struct index_mm_node *child = index_mm_readchild(node, ch);
904
905 if (!child)
906 continue;
907
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300908 strbuf_pushchar(buf, ch);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200909 index_mm_searchwild_all(child, 0, buf, subkey, out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300910 strbuf_popchar(buf);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200911 }
912
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200913 if (node->values.len > 0) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300914 if (fnmatch(strbuf_str(buf), subkey, 0) == 0)
Lucas De Marchibf89f702011-12-02 18:23:36 -0200915 index_mm_searchwild_allvalues(node, out);
Gustavo Sverzut Barbieri27fdf632011-12-10 13:28:18 -0200916 else
917 index_mm_free_node(node);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200918 } else {
919 index_mm_free_node(node);
920 }
921
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300922 strbuf_popchars(buf, pushed);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200923}
924
925/* Level 2: descend the tree (until we hit a wildcard) */
926static void index_mm_searchwild_node(struct index_mm_node *node,
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300927 struct strbuf *buf,
Lucas De Marchibf89f702011-12-02 18:23:36 -0200928 const char *key, int i,
929 struct index_value **out)
930{
931 struct index_mm_node *child;
932 int j;
933 int ch;
934
935 while(node) {
936 for (j = 0; node->prefix[j]; j++) {
937 ch = node->prefix[j];
938
939 if (ch == '*' || ch == '?' || ch == '[') {
940 index_mm_searchwild_all(node, j, buf,
941 &key[i+j], out);
942 return;
943 }
944
945 if (ch != key[i+j]) {
946 index_mm_free_node(node);
947 return;
948 }
949 }
950
951 i += j;
952
953 child = index_mm_readchild(node, '*');
954 if (child) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300955 strbuf_pushchar(buf, '*');
Lucas De Marchibf89f702011-12-02 18:23:36 -0200956 index_mm_searchwild_all(child, 0, buf, &key[i], out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300957 strbuf_popchar(buf);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200958 }
959
960 child = index_mm_readchild(node, '?');
961 if (child) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300962 strbuf_pushchar(buf, '?');
Lucas De Marchibf89f702011-12-02 18:23:36 -0200963 index_mm_searchwild_all(child, 0, buf, &key[i], out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300964 strbuf_popchar(buf);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200965 }
966
967 child = index_mm_readchild(node, '[');
968 if (child) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300969 strbuf_pushchar(buf, '[');
Lucas De Marchibf89f702011-12-02 18:23:36 -0200970 index_mm_searchwild_all(child, 0, buf, &key[i], out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300971 strbuf_popchar(buf);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200972 }
973
974 if (key[i] == '\0') {
975 index_mm_searchwild_allvalues(node, out);
976
977 return;
978 }
979
980 child = index_mm_readchild(node, key[i]);
981 index_mm_free_node(node);
982 node = child;
983 i++;
984 }
985}
986
987/*
988 * Search the index for a key. The index may contain wildcards.
989 *
990 * Returns a list of all the values of matching keys.
991 */
992struct index_value *index_mm_searchwild(struct index_mm *idx, const char *key)
993{
994 struct index_mm_node *root = index_mm_readroot(idx);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300995 struct strbuf buf;
Lucas De Marchibf89f702011-12-02 18:23:36 -0200996 struct index_value *out = NULL;
997
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300998 strbuf_init(&buf);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200999 index_mm_searchwild_node(root, &buf, key, 0, &out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -03001000 strbuf_release(&buf);
Lucas De Marchibf89f702011-12-02 18:23:36 -02001001 return out;
1002}