blob: aa17c2f0234a9c54ebbda82d59fe51d73a14f55e [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
Lucas De Marchidea2dfe2014-12-25 23:32:03 -020017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
Lucas De Marchi8f923be2011-12-03 04:28:49 -020018 */
Lucas De Marchie8847fd2011-11-30 15:23:28 -020019
Lucas De Marchic2e42862014-10-03 01:41:42 -030020#include <arpa/inet.h>
21#include <assert.h>
Lucas De Marchie8847fd2011-11-30 15:23:28 -020022#include <errno.h>
23#include <fnmatch.h>
Lucas De Marchibfcd31d2012-03-02 21:28:11 -030024#include <inttypes.h>
Lucas De Marchic2e42862014-10-03 01:41:42 -030025#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
Lucas De Marchie8847fd2011-11-30 15:23:28 -020028
Lucas De Marchi576dd432014-10-02 22:03:19 -030029#include <shared/macro.h>
Lucas De Marchib4d1f442014-10-11 13:03:21 -030030#include <shared/strbuf.h>
Lucas De Marchi96573a02014-10-03 00:01:35 -030031#include <shared/util.h>
Lucas De Marchi576dd432014-10-02 22:03:19 -030032
Lucas De Marchi83b855a2013-07-04 16:13:11 -030033#include "libkmod-internal.h"
Lucas De Marchie8847fd2011-11-30 15:23:28 -020034#include "libkmod-index.h"
Lucas De Marchie8847fd2011-11-30 15:23:28 -020035
Lucas De Marchic4cbdf82014-10-28 01:47:50 -020036/* libkmod-index.c: module index file implementation
37 *
38 * Integers are stored as 32 bit unsigned in "network" order, i.e. MSB first.
39 * All files start with a magic number.
40 *
41 * Magic spells "BOOTFAST". Second one used on newer versioned binary files.
42 * #define INDEX_MAGIC_OLD 0xB007FA57
43 *
44 * We use a version string to keep track of changes to the binary format
45 * This is stored in the form: INDEX_MAJOR (hi) INDEX_MINOR (lo) just in
46 * case we ever decide to have minor changes that are not incompatible.
47 */
48#define INDEX_MAGIC 0xB007F457
49#define INDEX_VERSION_MAJOR 0x0002
50#define INDEX_VERSION_MINOR 0x0001
51#define INDEX_VERSION ((INDEX_VERSION_MAJOR<<16)|INDEX_VERSION_MINOR)
Lucas De Marchi8f923be2011-12-03 04:28:49 -020052
Lucas De Marchic4cbdf82014-10-28 01:47:50 -020053/* The index file maps keys to values. Both keys and values are ASCII strings.
54 * Each key can have multiple values. Values are sorted by an integer priority.
55 *
56 * The reader also implements a wildcard search (including range expressions)
57 * where the keys in the index are treated as patterns.
58 * This feature is required for module aliases.
59 */
Gustavo Sverzut Barbieri148226e2011-12-10 11:53:51 -020060#define INDEX_CHILDMAX 128
61
62/* Disk format:
Lucas De Marchic4cbdf82014-10-28 01:47:50 -020063 *
64 * uint32_t magic = INDEX_MAGIC;
65 * uint32_t version = INDEX_VERSION;
66 * uint32_t root_offset;
67 *
68 * (node_offset & INDEX_NODE_MASK) specifies the file offset of nodes:
69 *
70 * char[] prefix; // nul terminated
71 *
72 * char first;
73 * char last;
74 * uint32_t children[last - first + 1];
75 *
76 * uint32_t value_count;
77 * struct {
78 * uint32_t priority;
79 * char[] value; // nul terminated
80 * } values[value_count];
81 *
82 * (node_offset & INDEX_NODE_FLAGS) indicates which fields are present.
83 * Empty prefixes are omitted, leaf nodes omit the three child-related fields.
84 *
85 * This could be optimised further by adding a sparse child format
86 * (indicated using a new flag).
87 *
88 *
89 * Implementation is based on a radix tree, or "trie".
90 * Each arc from parent to child is labelled with a character.
91 * Each path from the root represents a string.
92 *
93 * == Example strings ==
94 *
95 * ask
96 * ate
97 * on
98 * once
99 * one
100 *
101 * == Key ==
102 * + Normal node
103 * * Marked node, representing a key and it's values.
104 *
105 * +
106 * |-a-+-s-+-k-*
107 * | |
108 * | `-t-+-e-*
109 * |
110 * `-o-+-n-*-c-+-e-*
111 * |
112 * `-e-*
113 *
114 * Naive implementations tend to be very space inefficient; child pointers
115 * are stored in arrays indexed by character, but most child pointers are null.
116 *
117 * Our implementation uses a scheme described by Wikipedia as a Patrica trie,
118 *
119 * "easiest to understand as a space-optimized trie where
120 * each node with only one child is merged with its child"
121 *
122 * +
123 * |-a-+-sk-*
124 * | |
125 * | `-te-*
126 * |
127 * `-on-*-ce-*
128 * |
129 * `-e-*
130 *
131 * We still use arrays of child pointers indexed by a single character;
132 * the remaining characters of the label are stored as a "prefix" in the child.
133 *
134 * The paper describing the original Patrica trie works on individiual bits -
135 * each node has a maximum of two children, which increases space efficiency.
136 * However for this application it is simpler to use the ASCII character set.
137 * Since the index file is read-only, it can be compressed by omitting null
138 * child pointers at the start and end of arrays.
Gustavo Sverzut Barbieri148226e2011-12-10 11:53:51 -0200139 */
140
141/* Format of node offsets within index file */
142enum node_offset {
143 INDEX_NODE_FLAGS = 0xF0000000, /* Flags in high nibble */
144 INDEX_NODE_PREFIX = 0x80000000,
145 INDEX_NODE_VALUES = 0x40000000,
146 INDEX_NODE_CHILDS = 0x20000000,
147
148 INDEX_NODE_MASK = 0x0FFFFFFF, /* Offset value */
149};
150
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200151void index_values_free(struct index_value *values)
152{
153 while (values) {
154 struct index_value *value = values;
155
156 values = value->next;
157 free(value);
158 }
159}
160
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200161static int add_value(struct index_value **values,
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200162 const char *value, unsigned len, unsigned int priority)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200163{
164 struct index_value *v;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200165
166 /* find position to insert value */
167 while (*values && (*values)->priority < priority)
168 values = &(*values)->next;
169
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200170 v = malloc(sizeof(struct index_value) + len + 1);
171 if (!v)
172 return -1;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200173 v->next = *values;
174 v->priority = priority;
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200175 v->len = len;
176 memcpy(v->value, value, len);
177 v->value[len] = '\0';
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200178 *values = v;
179
Gustavo Sverzut Barbieri558b0202011-12-08 16:36:48 -0200180 return 0;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200181}
182
Lucas De Marchi93688882011-12-02 10:05:31 -0200183static void read_error(void)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200184{
185 fatal("Module index: unexpected error: %s\n"
186 "Try re-running depmod\n", errno ? strerror(errno) : "EOF");
187}
188
189static int read_char(FILE *in)
190{
191 int ch;
192
193 errno = 0;
194 ch = getc_unlocked(in);
195 if (ch == EOF)
196 read_error();
197 return ch;
198}
199
200static uint32_t read_long(FILE *in)
201{
202 uint32_t l;
203
204 errno = 0;
Leandro Pereirab6d985c2014-04-28 20:47:49 -0300205 if (fread(&l, sizeof(uint32_t), 1, in) != sizeof(uint32_t))
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200206 read_error();
207 return ntohl(l);
208}
209
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300210static unsigned buf_freadchars(struct strbuf *buf, FILE *in)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200211{
212 unsigned i = 0;
213 int ch;
214
215 while ((ch = read_char(in))) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300216 if (!strbuf_pushchar(buf, ch))
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200217 break;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200218 i++;
219 }
220
221 return i;
222}
223
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200224/*
Lucas De Marchieb8bb322011-12-02 10:23:02 -0200225 * Index file searching
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200226 */
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200227struct index_node_f {
228 FILE *file;
229 char *prefix; /* path compression */
230 struct index_value *values;
231 unsigned char first; /* range of child nodes */
232 unsigned char last;
233 uint32_t children[0];
234};
235
236static struct index_node_f *index_read(FILE *in, uint32_t offset)
237{
238 struct index_node_f *node;
239 char *prefix;
240 int i, child_count = 0;
241
242 if ((offset & INDEX_NODE_MASK) == 0)
243 return NULL;
244
245 fseek(in, offset & INDEX_NODE_MASK, SEEK_SET);
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200246
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200247 if (offset & INDEX_NODE_PREFIX) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300248 struct strbuf buf;
249 strbuf_init(&buf);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200250 buf_freadchars(&buf, in);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300251 prefix = strbuf_steal(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200252 } else
253 prefix = NOFAIL(strdup(""));
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200254
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200255 if (offset & INDEX_NODE_CHILDS) {
256 char first = read_char(in);
257 char last = read_char(in);
258 child_count = last - first + 1;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200259
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200260 node = NOFAIL(malloc(sizeof(struct index_node_f) +
261 sizeof(uint32_t) * child_count));
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200262
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200263 node->first = first;
264 node->last = last;
265
266 for (i = 0; i < child_count; i++)
267 node->children[i] = read_long(in);
268 } else {
269 node = NOFAIL(malloc(sizeof(struct index_node_f)));
270 node->first = INDEX_CHILDMAX;
271 node->last = 0;
272 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200273
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200274 node->values = NULL;
275 if (offset & INDEX_NODE_VALUES) {
276 int value_count;
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300277 struct strbuf buf;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200278 const char *value;
279 unsigned int priority;
280
281 value_count = read_long(in);
282
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300283 strbuf_init(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200284 while (value_count--) {
285 priority = read_long(in);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200286 buf_freadchars(&buf, in);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300287 value = strbuf_str(&buf);
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200288 add_value(&node->values, value, buf.used, priority);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300289 strbuf_clear(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200290 }
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300291 strbuf_release(&buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200292 }
293
294 node->prefix = prefix;
295 node->file = in;
296 return node;
297}
298
299static void index_close(struct index_node_f *node)
300{
301 free(node->prefix);
302 index_values_free(node->values);
303 free(node);
304}
305
306struct index_file {
307 FILE *file;
308 uint32_t root_offset;
309};
310
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200311struct index_file *index_file_open(const char *filename)
312{
313 FILE *file;
314 uint32_t magic, version;
315 struct index_file *new;
316
Cristian Rodríguez79e5ea92011-12-16 02:49:54 -0300317 file = fopen(filename, "re");
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200318 if (!file)
319 return NULL;
320 errno = EINVAL;
321
322 magic = read_long(file);
Cristian Rodríguez67d94ad2011-12-23 03:06:56 -0200323 if (magic != INDEX_MAGIC) {
324 fclose(file);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200325 return NULL;
Cristian Rodríguez67d94ad2011-12-23 03:06:56 -0200326 }
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200327
328 version = read_long(file);
Cristian Rodríguez4088b272011-12-26 01:38:04 -0300329 if (version >> 16 != INDEX_VERSION_MAJOR) {
330 fclose(file);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200331 return NULL;
Cristian Rodríguez4088b272011-12-26 01:38:04 -0300332 }
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200333
334 new = NOFAIL(malloc(sizeof(struct index_file)));
335 new->file = file;
336 new->root_offset = read_long(new->file);
337
338 errno = 0;
339 return new;
340}
341
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200342void index_file_close(struct index_file *idx)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200343{
Lucas De Marchi0fbdfef2011-12-02 09:56:22 -0200344 fclose(idx->file);
345 free(idx);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200346}
347
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200348static struct index_node_f *index_readroot(struct index_file *in)
349{
350 return index_read(in->file, in->root_offset);
351}
352
353static struct index_node_f *index_readchild(const struct index_node_f *parent,
354 int ch)
355{
Lucas De Marchie71970a2011-12-02 10:27:15 -0200356 if (parent->first <= ch && ch <= parent->last) {
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200357 return index_read(parent->file,
358 parent->children[ch - parent->first]);
Lucas De Marchie71970a2011-12-02 10:27:15 -0200359 }
360
361 return NULL;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200362}
363
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300364static void index_dump_node(struct index_node_f *node, struct strbuf *buf,
Lucas De Marchi758428a2012-01-16 15:56:17 -0200365 int fd)
366{
367 struct index_value *v;
368 int ch, pushed;
369
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300370 pushed = strbuf_pushchars(buf, node->prefix);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200371
372 for (v = node->values; v != NULL; v = v->next) {
373 write_str_safe(fd, buf->bytes, buf->used);
374 write_str_safe(fd, " ", 1);
375 write_str_safe(fd, v->value, strlen(v->value));
376 write_str_safe(fd, "\n", 1);
377 }
378
379 for (ch = node->first; ch <= node->last; ch++) {
380 struct index_node_f *child = index_readchild(node, ch);
381
382 if (!child)
383 continue;
384
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300385 strbuf_pushchar(buf, ch);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200386 index_dump_node(child, buf, fd);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300387 strbuf_popchar(buf);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200388 }
389
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300390 strbuf_popchars(buf, pushed);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200391 index_close(node);
392}
393
394void index_dump(struct index_file *in, int fd, const char *prefix)
395{
396 struct index_node_f *root;
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300397 struct strbuf buf;
Lucas De Marchi758428a2012-01-16 15:56:17 -0200398
Lucas De Marchi681bf892013-04-23 21:21:00 -0300399 root = index_readroot(in);
400 if (root == NULL)
401 return;
402
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300403 strbuf_init(&buf);
404 strbuf_pushchars(&buf, prefix);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200405 index_dump_node(root, &buf, fd);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300406 strbuf_release(&buf);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200407}
408
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200409static char *index_search__node(struct index_node_f *node, const char *key, int i)
410{
411 char *value;
412 struct index_node_f *child;
413 int ch;
414 int j;
415
416 while(node) {
417 for (j = 0; node->prefix[j]; j++) {
418 ch = node->prefix[j];
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200419
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200420 if (ch != key[i+j]) {
421 index_close(node);
422 return NULL;
423 }
424 }
Lucas De Marchie71970a2011-12-02 10:27:15 -0200425
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200426 i += j;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200427
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200428 if (key[i] == '\0') {
Lucas De Marchi817f4e32012-02-27 19:54:33 -0300429 value = node->values != NULL
430 ? strdup(node->values[0].value)
431 : NULL;
432
433 index_close(node);
434 return value;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200435 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200436
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200437 child = index_readchild(node, key[i]);
438 index_close(node);
439 node = child;
440 i++;
441 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200442
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200443 return NULL;
444}
445
446/*
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200447 * Search the index for a key
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200448 *
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200449 * Returns the value of the first match
450 *
451 * The recursive functions free their node argument (using index_close).
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200452 */
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200453char *index_search(struct index_file *in, const char *key)
454{
Lucas De Marchiee1d1882012-02-27 18:48:02 -0300455// FIXME: return value by reference instead of strdup
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200456 struct index_node_f *root;
457 char *value;
458
459 root = index_readroot(in);
460 value = index_search__node(root, key, 0);
461
462 return value;
463}
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200464
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200465
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200466
467/* Level 4: add all the values from a matching node */
468static void index_searchwild__allvalues(struct index_node_f *node,
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200469 struct index_value **out)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200470{
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200471 struct index_value *v;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200472
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200473 for (v = node->values; v != NULL; v = v->next)
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200474 add_value(out, v->value, v->len, v->priority);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200475
476 index_close(node);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200477}
478
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200479/*
480 * Level 3: traverse a sub-keyspace which starts with a wildcard,
481 * looking for matches.
482 */
483static void index_searchwild__all(struct index_node_f *node, int j,
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300484 struct strbuf *buf,
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200485 const char *subkey,
486 struct index_value **out)
487{
488 int pushed = 0;
489 int ch;
490
491 while (node->prefix[j]) {
492 ch = node->prefix[j];
493
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300494 strbuf_pushchar(buf, ch);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200495 pushed++;
496 j++;
497 }
498
499 for (ch = node->first; ch <= node->last; ch++) {
500 struct index_node_f *child = index_readchild(node, ch);
501
502 if (!child)
503 continue;
504
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300505 strbuf_pushchar(buf, ch);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200506 index_searchwild__all(child, 0, buf, subkey, out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300507 strbuf_popchar(buf);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200508 }
509
510 if (node->values) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300511 if (fnmatch(strbuf_str(buf), subkey, 0) == 0)
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200512 index_searchwild__allvalues(node, out);
Gustavo Sverzut Barbieri27fdf632011-12-10 13:28:18 -0200513 else
514 index_close(node);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200515 } else {
516 index_close(node);
517 }
518
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300519 strbuf_popchars(buf, pushed);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200520}
521
522/* Level 2: descend the tree (until we hit a wildcard) */
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200523static void index_searchwild__node(struct index_node_f *node,
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300524 struct strbuf *buf,
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200525 const char *key, int i,
526 struct index_value **out)
527{
528 struct index_node_f *child;
529 int j;
530 int ch;
531
532 while(node) {
533 for (j = 0; node->prefix[j]; j++) {
534 ch = node->prefix[j];
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200535
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200536 if (ch == '*' || ch == '?' || ch == '[') {
537 index_searchwild__all(node, j, buf,
538 &key[i+j], out);
539 return;
540 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200541
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200542 if (ch != key[i+j]) {
543 index_close(node);
544 return;
545 }
546 }
Lucas De Marchie71970a2011-12-02 10:27:15 -0200547
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200548 i += j;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200549
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200550 child = index_readchild(node, '*');
551 if (child) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300552 strbuf_pushchar(buf, '*');
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200553 index_searchwild__all(child, 0, buf, &key[i], out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300554 strbuf_popchar(buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200555 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200556
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200557 child = index_readchild(node, '?');
558 if (child) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300559 strbuf_pushchar(buf, '?');
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200560 index_searchwild__all(child, 0, buf, &key[i], out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300561 strbuf_popchar(buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200562 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200563
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200564 child = index_readchild(node, '[');
565 if (child) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300566 strbuf_pushchar(buf, '[');
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200567 index_searchwild__all(child, 0, buf, &key[i], out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300568 strbuf_popchar(buf);
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200569 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200570
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200571 if (key[i] == '\0') {
572 index_searchwild__allvalues(node, out);
573
574 return;
575 }
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200576
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200577 child = index_readchild(node, key[i]);
578 index_close(node);
579 node = child;
580 i++;
581 }
582}
583
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200584/*
585 * Search the index for a key. The index may contain wildcards.
586 *
587 * Returns a list of all the values of matching keys.
588 */
589struct index_value *index_searchwild(struct index_file *in, const char *key)
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200590{
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200591 struct index_node_f *root = index_readroot(in);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300592 struct strbuf buf;
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200593 struct index_value *out = NULL;
Lucas De Marchia7be73b2011-11-30 15:59:36 -0200594
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300595 strbuf_init(&buf);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -0200596 index_searchwild__node(root, &buf, key, 0, &out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300597 strbuf_release(&buf);
Lucas De Marchi1d152ac2011-12-02 10:15:00 -0200598 return out;
Lucas De Marchie8847fd2011-11-30 15:23:28 -0200599}
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200600
Lucas De Marchibb721532014-10-28 01:58:11 -0200601/**************************************************************************/
602/*
603 * Alternative implementation, using mmap to map all the file to memory when
604 * starting
605 */
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200606#include <sys/mman.h>
607#include <sys/stat.h>
608#include <unistd.h>
609
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200610static const char _idx_empty_str[] = "";
611
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200612struct index_mm {
613 struct kmod_ctx *ctx;
614 void *mm;
615 uint32_t root_offset;
616 size_t size;
617};
618
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200619struct index_mm_value {
620 unsigned int priority;
621 unsigned int len;
622 const char *value;
623};
624
625struct index_mm_value_array {
626 struct index_mm_value *values;
627 unsigned int len;
628};
629
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200630struct index_mm_node {
631 struct index_mm *idx;
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200632 const char *prefix; /* mmape'd value */
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200633 struct index_mm_value_array values;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200634 unsigned char first;
635 unsigned char last;
636 uint32_t children[];
637};
638
639static inline uint32_t read_long_mm(void **p)
640{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200641 uint8_t *addr = *(uint8_t **)p;
642 uint32_t v;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200643
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200644 /* addr may be unalined to uint32_t */
Lucas De Marchi5bbec8c2012-05-23 19:32:58 -0300645 v = get_unaligned((uint32_t *) addr);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200646
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200647 *p = addr + sizeof(uint32_t);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200648 return ntohl(v);
649}
650
651static inline uint8_t read_char_mm(void **p)
652{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200653 uint8_t *addr = *(uint8_t **)p;
654 uint8_t v = *addr;
655 *p = addr + sizeof(uint8_t);
656 return v;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200657}
658
Gustavo Sverzut Barbieri1433ba92011-12-08 14:50:29 -0200659static inline char *read_chars_mm(void **p, unsigned *rlen)
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200660{
Gustavo Sverzut Barbierifc2d8352011-12-10 11:36:35 -0200661 char *addr = *(char **)p;
662 size_t len = *rlen = strlen(addr);
663 *p = addr + len + 1;
664 return addr;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200665}
666
667static struct index_mm_node *index_mm_read_node(struct index_mm *idx,
668 uint32_t offset) {
669 void *p = idx->mm;
670 struct index_mm_node *node;
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200671 const char *prefix;
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200672 int i, child_count, value_count, children_padding;
673 uint32_t children[INDEX_CHILDMAX];
674 char first, last;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200675
676 if ((offset & INDEX_NODE_MASK) == 0)
677 return NULL;
678
679 p = (char *)p + (offset & INDEX_NODE_MASK);
680
Gustavo Sverzut Barbieri15c1c142011-12-10 11:44:31 -0200681 if (offset & INDEX_NODE_PREFIX) {
682 unsigned len;
683 prefix = read_chars_mm(&p, &len);
684 } else
685 prefix = _idx_empty_str;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200686
687 if (offset & INDEX_NODE_CHILDS) {
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200688 first = read_char_mm(&p);
689 last = read_char_mm(&p);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200690 child_count = last - first + 1;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200691 for (i = 0; i < child_count; i++)
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200692 children[i] = read_long_mm(&p);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200693 } else {
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200694 first = INDEX_CHILDMAX;
695 last = 0;
696 child_count = 0;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200697 }
698
Gustavo Sverzut Barbieric6824b62011-12-21 18:23:58 -0200699 children_padding = (sizeof(struct index_mm_node) +
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200700 (sizeof(uint32_t) * child_count)) % sizeof(void *);
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200701
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200702 if (offset & INDEX_NODE_VALUES)
703 value_count = read_long_mm(&p);
704 else
705 value_count = 0;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200706
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200707 node = malloc(sizeof(struct index_mm_node)
708 + sizeof(uint32_t) * child_count + children_padding
709 + sizeof(struct index_mm_value) * value_count);
710 if (node == NULL)
711 return NULL;
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200712
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200713 node->idx = idx;
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200714 node->prefix = prefix;
715 if (value_count == 0)
716 node->values.values = NULL;
717 else {
718 node->values.values = (struct index_mm_value *)
719 ((char *)node + sizeof(struct index_mm_node) +
720 sizeof(uint32_t) * child_count + children_padding);
721 }
722 node->values.len = value_count;
723 node->first = first;
724 node->last = last;
725 memcpy(node->children, children, sizeof(uint32_t) * child_count);
726
727 for (i = 0; i < value_count; i++) {
728 struct index_mm_value *v = node->values.values + i;
729 v->priority = read_long_mm(&p);
730 v->value = read_chars_mm(&p, &v->len);
731 }
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200732
733 return node;
734}
735
736static void index_mm_free_node(struct index_mm_node *node)
737{
Lucas De Marchi836be9a2011-12-02 17:27:52 -0200738 free(node);
739}
740
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200741struct index_mm *index_mm_open(struct kmod_ctx *ctx, const char *filename,
Lucas De Marchi2e2e2522012-03-02 20:33:26 -0300742 unsigned long long *stamp)
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200743{
744 int fd;
745 struct stat st;
746 struct index_mm *idx;
747 struct {
748 uint32_t magic;
749 uint32_t version;
750 uint32_t root_offset;
751 } hdr;
752 void *p;
753
754 DBG(ctx, "file=%s\n", filename);
755
Lucas De Marchi7d51d8b2011-12-12 18:41:57 -0200756 idx = malloc(sizeof(*idx));
757 if (idx == NULL) {
Gustavo Sverzut Barbieridfa96f12012-01-07 19:37:37 -0200758 ERR(ctx, "malloc: %m\n");
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200759 return NULL;
760 }
761
Cristian Rodríguez79e5ea92011-12-16 02:49:54 -0300762 if ((fd = open(filename, O_RDONLY|O_CLOEXEC)) < 0) {
Lucas De Marchi73298172012-02-13 21:58:36 -0200763 DBG(ctx, "open(%s, O_RDONLY|O_CLOEXEC): %m\n", filename);
Lucas De Marchi7d51d8b2011-12-12 18:41:57 -0200764 goto fail_open;
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200765 }
766
Leandro Pereirad36c8862014-04-28 20:44:14 -0300767 if (fstat(fd, &st) < 0)
768 goto fail_nommap;
Lucas De Marchi5b05c322012-06-06 09:36:29 -0300769 if ((size_t) st.st_size < sizeof(hdr))
770 goto fail_nommap;
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200771
Kees Cookc3e8d262013-02-18 12:02:34 -0800772 if ((idx->mm = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0))
Lucas De Marchi5109f2b2011-12-08 15:10:55 -0200773 == MAP_FAILED) {
Kees Cookc3e8d262013-02-18 12:02:34 -0800774 ERR(ctx, "mmap(NULL, %"PRIu64", PROT_READ, %d, MAP_PRIVATE, 0): %m\n",
Lucas De Marchi2e2e2522012-03-02 20:33:26 -0300775 st.st_size, fd);
Lucas De Marchi5b05c322012-06-06 09:36:29 -0300776 goto fail_nommap;
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200777 }
778
779 p = idx->mm;
780 hdr.magic = read_long_mm(&p);
781 hdr.version = read_long_mm(&p);
782 hdr.root_offset = read_long_mm(&p);
783
784 if (hdr.magic != INDEX_MAGIC) {
785 ERR(ctx, "magic check fail: %x instead of %x\n", hdr.magic,
786 INDEX_MAGIC);
787 goto fail;
788 }
789
790 if (hdr.version >> 16 != INDEX_VERSION_MAJOR) {
791 ERR(ctx, "major version check fail: %u instead of %u\n",
Holger Obermaier1a4aa7e2014-09-04 14:38:16 +0200792 hdr.version >> 16, INDEX_VERSION_MAJOR);
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200793 goto fail;
794 }
795
796 idx->root_offset = hdr.root_offset;
797 idx->size = st.st_size;
798 idx->ctx = ctx;
799 close(fd);
800
Lucas De Marchi6068aaa2012-01-17 12:10:42 -0200801 *stamp = stat_mstamp(&st);
Lucas De Marchi9fd58f32011-12-31 18:53:24 -0200802
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200803 return idx;
804
805fail:
Lucas De Marchi5b05c322012-06-06 09:36:29 -0300806 munmap(idx->mm, st.st_size);
807fail_nommap:
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200808 close(fd);
Gustavo Sverzut Barbieria5a92a62011-12-16 16:17:50 -0200809fail_open:
Lucas De Marchib471a6b2011-12-01 23:14:20 -0200810 free(idx);
811 return NULL;
812}
813
814void index_mm_close(struct index_mm *idx)
815{
816 munmap(idx->mm, idx->size);
817 free(idx);
818}
Lucas De Marchi77bf9362011-12-02 17:41:30 -0200819
820static struct index_mm_node *index_mm_readroot(struct index_mm *idx)
821{
822 return index_mm_read_node(idx, idx->root_offset);
823}
Lucas De Marchi91298dc2011-12-02 17:41:46 -0200824
825static struct index_mm_node *index_mm_readchild(const struct index_mm_node *parent,
826 int ch)
827{
828 if (parent->first <= ch && ch <= parent->last) {
829 return index_mm_read_node(parent->idx,
830 parent->children[ch - parent->first]);
831 }
832
833 return NULL;
834}
Lucas De Marchie33bb872011-12-02 17:45:01 -0200835
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300836static void index_mm_dump_node(struct index_mm_node *node, struct strbuf *buf,
Lucas De Marchi758428a2012-01-16 15:56:17 -0200837 int fd)
838{
839 struct index_mm_value *itr, *itr_end;
840 int ch, pushed;
841
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300842 pushed = strbuf_pushchars(buf, node->prefix);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200843
844 itr = node->values.values;
845 itr_end = itr + node->values.len;
846 for (; itr < itr_end; itr++) {
847 write_str_safe(fd, buf->bytes, buf->used);
848 write_str_safe(fd, " ", 1);
849 write_str_safe(fd, itr->value, itr->len);
850 write_str_safe(fd, "\n", 1);
851 }
852
853 for (ch = node->first; ch <= node->last; ch++) {
854 struct index_mm_node *child = index_mm_readchild(node, ch);
855
856 if (child == NULL)
857 continue;
858
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300859 strbuf_pushchar(buf, ch);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200860 index_mm_dump_node(child, buf, fd);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300861 strbuf_popchar(buf);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200862 }
863
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300864 strbuf_popchars(buf, pushed);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200865 index_mm_free_node(node);
866}
867
868void index_mm_dump(struct index_mm *idx, int fd, const char *prefix)
869{
870 struct index_mm_node *root;
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300871 struct strbuf buf;
Lucas De Marchi758428a2012-01-16 15:56:17 -0200872
Lucas De Marchi681bf892013-04-23 21:21:00 -0300873 root = index_mm_readroot(idx);
874 if (root == NULL)
875 return;
876
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300877 strbuf_init(&buf);
878 strbuf_pushchars(&buf, prefix);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200879 index_mm_dump_node(root, &buf, fd);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300880 strbuf_release(&buf);
Lucas De Marchi758428a2012-01-16 15:56:17 -0200881}
882
Lucas De Marchie33bb872011-12-02 17:45:01 -0200883static char *index_mm_search_node(struct index_mm_node *node, const char *key,
884 int i)
885{
886 char *value;
887 struct index_mm_node *child;
888 int ch;
889 int j;
890
891 while(node) {
892 for (j = 0; node->prefix[j]; j++) {
893 ch = node->prefix[j];
894
895 if (ch != key[i+j]) {
896 index_mm_free_node(node);
897 return NULL;
898 }
899 }
900
901 i += j;
902
903 if (key[i] == '\0') {
Lucas De Marchi817f4e32012-02-27 19:54:33 -0300904 value = node->values.len > 0
905 ? strdup(node->values.values[0].value)
906 : NULL;
907
908 index_mm_free_node(node);
909 return value;
Lucas De Marchie33bb872011-12-02 17:45:01 -0200910 }
911
912 child = index_mm_readchild(node, key[i]);
913 index_mm_free_node(node);
914 node = child;
915 i++;
916 }
917
918 return NULL;
919}
Lucas De Marchib797b792011-12-02 17:49:03 -0200920
921/*
922 * Search the index for a key
923 *
924 * Returns the value of the first match
925 *
926 * The recursive functions free their node argument (using index_close).
927 */
928char *index_mm_search(struct index_mm *idx, const char *key)
929{
Lucas De Marchiee1d1882012-02-27 18:48:02 -0300930// FIXME: return value by reference instead of strdup
Lucas De Marchib797b792011-12-02 17:49:03 -0200931 struct index_mm_node *root;
932 char *value;
933
934 root = index_mm_readroot(idx);
935 value = index_mm_search_node(root, key, 0);
936
937 return value;
938}
Lucas De Marchibf89f702011-12-02 18:23:36 -0200939
940/* Level 4: add all the values from a matching node */
941static void index_mm_searchwild_allvalues(struct index_mm_node *node,
942 struct index_value **out)
943{
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200944 struct index_mm_value *itr, *itr_end;
Lucas De Marchibf89f702011-12-02 18:23:36 -0200945
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200946 itr = node->values.values;
947 itr_end = itr + node->values.len;
948 for (; itr < itr_end; itr++)
949 add_value(out, itr->value, itr->len, itr->priority);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200950
951 index_mm_free_node(node);
952}
953
954/*
955 * Level 3: traverse a sub-keyspace which starts with a wildcard,
956 * looking for matches.
957 */
958static void index_mm_searchwild_all(struct index_mm_node *node, int j,
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300959 struct strbuf *buf,
Lucas De Marchibf89f702011-12-02 18:23:36 -0200960 const char *subkey,
961 struct index_value **out)
962{
963 int pushed = 0;
964 int ch;
965
966 while (node->prefix[j]) {
967 ch = node->prefix[j];
968
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300969 strbuf_pushchar(buf, ch);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200970 pushed++;
971 j++;
972 }
973
974 for (ch = node->first; ch <= node->last; ch++) {
975 struct index_mm_node *child = index_mm_readchild(node, ch);
976
977 if (!child)
978 continue;
979
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300980 strbuf_pushchar(buf, ch);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200981 index_mm_searchwild_all(child, 0, buf, subkey, out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300982 strbuf_popchar(buf);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200983 }
984
Gustavo Sverzut Barbierid0915462011-12-10 13:04:43 -0200985 if (node->values.len > 0) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300986 if (fnmatch(strbuf_str(buf), subkey, 0) == 0)
Lucas De Marchibf89f702011-12-02 18:23:36 -0200987 index_mm_searchwild_allvalues(node, out);
Gustavo Sverzut Barbieri27fdf632011-12-10 13:28:18 -0200988 else
989 index_mm_free_node(node);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200990 } else {
991 index_mm_free_node(node);
992 }
993
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300994 strbuf_popchars(buf, pushed);
Lucas De Marchibf89f702011-12-02 18:23:36 -0200995}
996
997/* Level 2: descend the tree (until we hit a wildcard) */
998static void index_mm_searchwild_node(struct index_mm_node *node,
Lucas De Marchi15a7ae32014-10-11 13:25:51 -0300999 struct strbuf *buf,
Lucas De Marchibf89f702011-12-02 18:23:36 -02001000 const char *key, int i,
1001 struct index_value **out)
1002{
1003 struct index_mm_node *child;
1004 int j;
1005 int ch;
1006
1007 while(node) {
1008 for (j = 0; node->prefix[j]; j++) {
1009 ch = node->prefix[j];
1010
1011 if (ch == '*' || ch == '?' || ch == '[') {
1012 index_mm_searchwild_all(node, j, buf,
1013 &key[i+j], out);
1014 return;
1015 }
1016
1017 if (ch != key[i+j]) {
1018 index_mm_free_node(node);
1019 return;
1020 }
1021 }
1022
1023 i += j;
1024
1025 child = index_mm_readchild(node, '*');
1026 if (child) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -03001027 strbuf_pushchar(buf, '*');
Lucas De Marchibf89f702011-12-02 18:23:36 -02001028 index_mm_searchwild_all(child, 0, buf, &key[i], out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -03001029 strbuf_popchar(buf);
Lucas De Marchibf89f702011-12-02 18:23:36 -02001030 }
1031
1032 child = index_mm_readchild(node, '?');
1033 if (child) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -03001034 strbuf_pushchar(buf, '?');
Lucas De Marchibf89f702011-12-02 18:23:36 -02001035 index_mm_searchwild_all(child, 0, buf, &key[i], out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -03001036 strbuf_popchar(buf);
Lucas De Marchibf89f702011-12-02 18:23:36 -02001037 }
1038
1039 child = index_mm_readchild(node, '[');
1040 if (child) {
Lucas De Marchi15a7ae32014-10-11 13:25:51 -03001041 strbuf_pushchar(buf, '[');
Lucas De Marchibf89f702011-12-02 18:23:36 -02001042 index_mm_searchwild_all(child, 0, buf, &key[i], out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -03001043 strbuf_popchar(buf);
Lucas De Marchibf89f702011-12-02 18:23:36 -02001044 }
1045
1046 if (key[i] == '\0') {
1047 index_mm_searchwild_allvalues(node, out);
1048
1049 return;
1050 }
1051
1052 child = index_mm_readchild(node, key[i]);
1053 index_mm_free_node(node);
1054 node = child;
1055 i++;
1056 }
1057}
1058
1059/*
1060 * Search the index for a key. The index may contain wildcards.
1061 *
1062 * Returns a list of all the values of matching keys.
1063 */
1064struct index_value *index_mm_searchwild(struct index_mm *idx, const char *key)
1065{
1066 struct index_mm_node *root = index_mm_readroot(idx);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -03001067 struct strbuf buf;
Lucas De Marchibf89f702011-12-02 18:23:36 -02001068 struct index_value *out = NULL;
1069
Lucas De Marchi15a7ae32014-10-11 13:25:51 -03001070 strbuf_init(&buf);
Gustavo Sverzut Barbieri405f6142011-12-08 14:36:30 -02001071 index_mm_searchwild_node(root, &buf, key, 0, &out);
Lucas De Marchi15a7ae32014-10-11 13:25:51 -03001072 strbuf_release(&buf);
Lucas De Marchibf89f702011-12-02 18:23:36 -02001073 return out;
1074}