bump release to v3.6
[mit.git] / index.c
blob5af1a124aba793fd48d5fb9dfd425bec4a42a56b
1 /* index.c: module index file shared functions for modprobe and depmod
2 Copyright (C) 2008 Alan Jenkins <alan-jenkins@tuffmail.co.uk>.
4 These programs are free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with these programs. If not, see <http://www.gnu.org/licenses/>.
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <fnmatch.h>
24 #include "logging.h"
25 #include "index.h"
28 * Index abstract data type (used only by depmod)
31 struct index_node *index_create()
33 struct index_node *node;
35 node = NOFAIL(calloc(sizeof(struct index_node), 1));
36 node->prefix = NOFAIL(strdup(""));
37 node->first = INDEX_CHILDMAX;
39 return node;
42 void index_destroy(struct index_node *node)
44 int c;
46 for (c = node->first; c <= node->last; c++) {
47 struct index_node *child = node->children[c];
49 if (child)
50 index_destroy(child);
52 free(node->prefix);
53 free(node);
56 static void index__checkstring(const char *str)
58 int spaces = 0;
59 int i;
61 for (i = 0; str[i]; i++) {
62 int ch = str[i];
64 if (ch >= INDEX_CHILDMAX)
65 fatal("Module index: bad character '%c'=0x%x - only 7-bit ASCII is supported:"
66 "\n%s\n", (char) ch, (int) ch, str);
68 if (ch == ' ')
69 spaces++;
72 if (!spaces)
73 fatal("Module index: internal error - missing space (key/value separator)"
74 "\n%s\n", str);
77 int index_insert(struct index_node *node, const char *str)
79 int i = 0; /* index within str */
80 int ch;
81 int duplicate = 0;
83 index__checkstring(str);
85 while(1) {
86 int j; /* index within node->prefix */
88 /* Ensure node->prefix is a prefix of &str[i].
89 If it is not already, then we must split node. */
90 for (j = 0; node->prefix[j]; j++) {
91 ch = node->prefix[j];
93 if (ch != str[i+j]) {
94 char *prefix = node->prefix;
95 struct index_node *n;
97 /* New child is copy of node with prefix[j+1..N] */
98 n = NOFAIL(calloc(sizeof(struct index_node), 1));
99 memcpy(n, node, sizeof(struct index_node));
100 n->prefix = NOFAIL(strdup(&prefix[j+1]));
102 /* Parent has prefix[0..j], child at prefix[j] */
103 memset(node, 0, sizeof(struct index_node));
104 prefix[j] = '\0';
105 node->prefix = prefix;
106 node->first = ch;
107 node->last = ch;
108 node->children[ch] = n;
110 break;
113 /* j is now length of node->prefix */
114 i += j;
116 ch = str[i];
117 if(ch == '\0') {
118 if (node->isendpoint)
119 duplicate = 1;
121 node->isendpoint = 1;
122 return duplicate;
125 if (!node->children[ch]) {
126 struct index_node *child;
128 if (ch < node->first)
129 node->first = ch;
130 if (ch > node->last)
131 node->last = ch;
132 node->children[ch] = NOFAIL(calloc(sizeof(struct index_node), 1));
134 child = node->children[ch];
135 child->prefix = NOFAIL(strdup(&str[i+1]));
136 child->isendpoint = 1;
137 child->first = INDEX_CHILDMAX;
139 return duplicate;
142 /* Descend into child node and continue */
143 node = node->children[ch];
144 i++;
148 static int index__haschildren(const struct index_node *node)
150 return node->first < INDEX_CHILDMAX;
153 /* Recursive post-order traversal
155 Pre-order would make for better read-side buffering / readahead / caching.
156 (post-order means you go backwards in the file as you descend the tree).
157 However, index reading is already fast enough.
158 Pre-order is simpler for writing, and depmod is already slow.
160 static uint32_t index_write__node(const struct index_node *node, FILE *out)
162 uint32_t *child_offs = NULL;
163 int child_count = 0;
164 long offset;
166 if (!node)
167 return 0;
169 /* Write children and save their offsets */
170 if (index__haschildren(node)) {
171 const struct index_node *child;
172 int i;
174 child_count = node->last - node->first + 1;
175 child_offs = NOFAIL(malloc(child_count * sizeof(uint32_t)));
177 for (i = 0; i < child_count; i++) {
178 child = node->children[node->first + i];
179 child_offs[i] = htonl(index_write__node(child, out));
183 /* Now write this node */
184 offset = ftell(out);
186 if (node->prefix[0]) {
187 fputs(node->prefix, out);
188 fputc('\0', out);
189 offset |= INDEX_NODE_PREFIX;
192 if (child_count) {
193 fputc(node->first, out);
194 fputc(node->last, out);
195 fwrite(child_offs, sizeof(uint32_t), child_count, out);
196 free(child_offs);
197 offset |= INDEX_NODE_CHILDS;
200 if (node->isendpoint)
201 offset |= INDEX_NODE_ENDPOINT;
203 return offset;
206 void index_write(const struct index_node *node, FILE *out)
208 long initial_offset, final_offset;
209 uint32_t u;
211 u = htonl(INDEX_MAGIC);
212 fwrite(&u, sizeof(u), 1, out);
213 u = htonl(INDEX_VERSION);
214 fwrite(&u, sizeof(u), 1, out);
216 /* Second word is reserved for the offset of the root node */
217 initial_offset = ftell(out);
218 u = 0;
219 fwrite(&u, sizeof(uint32_t), 1, out);
221 /* Dump trie */
222 u = htonl(index_write__node(node, out));
224 /* Update first word */
225 final_offset = ftell(out);
226 fseek(out, initial_offset, SEEK_SET);
227 fwrite(&u, sizeof(uint32_t), 1, out);
228 fseek(out, final_offset, SEEK_SET);
233 static void read_error()
235 fatal("Module index: unexpected error: %s\n"
236 "Try re-running depmod\n", errno ? strerror(errno) : "EOF");
239 static int read_char(FILE *in)
241 int ch;
243 errno = 0;
244 ch = getc_unlocked(in);
245 if (ch == EOF)
246 read_error();
247 return ch;
250 static uint32_t read_long(FILE *in)
252 uint32_t l;
254 errno = 0;
255 if (fread(&l, sizeof(uint32_t), 1, in) <= 0)
256 read_error();
257 return ntohl(l);
261 * Buffer abstract data type
263 * Used internally to store the current path during tree traversal.
264 * They help build wildcard key strings to pass to fnmatch(),
265 * as well as building values of matching keys.
268 struct buffer {
269 char *bytes;
270 unsigned size;
271 unsigned used;
274 static void buf__realloc(struct buffer *buf, unsigned size)
276 if (size > buf->size) {
277 buf->bytes = NOFAIL(realloc(buf->bytes, size));
278 buf->size = size;
282 static struct buffer *buf_create()
284 struct buffer *buf;
286 buf = NOFAIL(calloc(sizeof(struct buffer), 1));
287 buf__realloc(buf, 256);
288 return buf;
291 static void buf_destroy(struct buffer *buf)
293 free(buf->bytes);
294 free(buf);
297 /* Destroy buffer and return a copy as a C string */
298 static char *buf_detach(struct buffer *buf)
300 char *bytes;
302 bytes = NOFAIL(realloc(buf->bytes, buf->used + 1));
303 bytes[buf->used] = '\0';
305 free(buf);
306 return bytes;
309 /* Return a C string owned by the buffer
310 (invalidated if the buffer is changed).
312 static const char *buf_str(struct buffer *buf)
314 buf__realloc(buf, buf->used + 1);
315 buf->bytes[buf->used] = '\0';
316 return buf->bytes;
319 static int buf_fwrite(struct buffer *buf, FILE *out)
321 return fwrite(buf->bytes, 1, buf->used, out);
324 static struct index_value *add_value(struct buffer *buf,
325 struct index_value *values)
327 struct index_value *n = malloc(sizeof(struct index_value) + buf->used + 1);
329 memcpy(n->value, buf->bytes, buf->used);
330 n->value[buf->used] = '\0';
331 n->next = values;
333 return n;
336 static void buf_popchars(struct buffer *buf, unsigned n)
338 buf->used -= n;
341 static void buf_pushchar(struct buffer *buf, char ch)
343 buf__realloc(buf, buf->used + 1);
344 buf->bytes[buf->used] = ch;
345 buf->used++;
348 static unsigned buf_pushchars(struct buffer *buf, const char *str)
350 unsigned i = 0;
351 int ch;
353 while ((ch = str[i])) {
354 buf_pushchar(buf, ch);
355 i++;
357 return i;
360 /* like buf_pushchars(), but the string comes from a file */
361 static unsigned buf_freadchars(struct buffer *buf, FILE *in)
363 unsigned i = 0;
364 int ch;
366 while ((ch = read_char(in))) {
367 buf_pushchar(buf, ch);
368 i++;
371 return i;
374 static void buf_popchar(struct buffer *buf)
376 buf->used--;
380 * Index file searching (used only by modprobe)
383 struct index_node_f {
384 FILE *file;
385 char *prefix; /* path compression */
386 char isendpoint; /* does this node represent a string? */
387 unsigned char first; /* range of child nodes */
388 unsigned char last;
389 uint32_t children[0];
392 static void index_fatal(const char *why)
394 fatal("Module index corrupt: %s\n"
395 "Try re-running depmod\n", why);
398 static struct index_node_f *index_read(FILE *in, uint32_t offset)
400 struct index_node_f *node;
401 char *prefix;
402 int i, child_count = 0;
404 if ((offset & INDEX_NODE_MASK) == 0)
405 return NULL;
407 fseek(in, offset & INDEX_NODE_MASK, SEEK_SET);
409 if (offset & INDEX_NODE_PREFIX) {
410 struct buffer *buf = buf_create();
411 buf_freadchars(buf, in);
412 prefix = buf_detach(buf);
413 } else
414 prefix = NOFAIL(strdup(""));
416 if (offset & INDEX_NODE_CHILDS) {
417 char first = read_char(in);
418 char last = read_char(in);
419 child_count = last - first + 1;
421 node = NOFAIL(malloc(sizeof(struct index_node_f) +
422 sizeof(uint32_t) * child_count));
424 node->first = first;
425 node->last = last;
427 for (i = 0; i < child_count; i++)
428 node->children[i] = read_long(in);
429 } else {
430 node = NOFAIL(malloc(sizeof(struct index_node_f)));
431 node->first = INDEX_CHILDMAX;
432 node->last = 0;
435 node->prefix = prefix;
436 node->isendpoint = !!(offset & INDEX_NODE_ENDPOINT);
437 node->file = in;
438 return node;
441 static void index_close(struct index_node_f *node)
443 free(node->prefix);
444 free(node);
447 static struct index_node_f *index_readchild(const struct index_node_f *parent,
448 int ch)
450 if (parent->first <= ch && ch <= parent->last)
451 return index_read(parent->file,
452 parent->children[ch - parent->first]);
453 else
454 return NULL;
457 static struct index_node_f *index_readroot(FILE *in)
459 uint32_t magic, offset, version;
461 fseek(in, 0, SEEK_SET);
463 magic = read_long(in);
465 if (INDEX_MAGIC == magic)
466 version = read_long(in);
467 else if (INDEX_MAGIC_OLD == magic)
468 version = 0x00000000;
469 else
470 index_fatal("Bad magic number");
472 offset = read_long(in);
473 return index_read(in, offset);
477 * Dump all strings as lines in a plain text file.
480 static void index_dump_node(struct index_node_f *node,
481 struct buffer *buf,
482 FILE *out,
483 const char *prefix)
485 int ch, pushed;
487 pushed = buf_pushchars(buf, node->prefix);
489 if (node->isendpoint) {
490 fputs(prefix, out);
491 buf_fwrite(buf, out);
492 fputc('\n', out);
495 for (ch = node->first; ch <= node->last; ch++) {
496 struct index_node_f *child = index_readchild(node, ch);
498 if (!child)
499 continue;
501 buf_pushchar(buf, ch);
502 index_dump_node(child, buf, out, prefix);
503 buf_popchar(buf);
506 buf_popchars(buf, pushed);
507 index_close(node);
510 void index_dump(FILE *in, FILE *out, const char *prefix)
512 struct index_node_f *root;
513 struct buffer *buf;
515 buf = buf_create();
516 root = index_readroot(in);
517 index_dump_node(root, buf, out, prefix);
518 buf_destroy(buf);
522 * Search the index for a key
524 * Returns the value of the first match
526 * The calling convention for the inner functions
527 * is for the callee to free the node argument (using index_close).
530 /* Level 1: interface function */
531 char *index_search(FILE *in, const char *key);
533 /* Level 2: descend the tree */
534 static char *index_search__node(struct index_node_f *node, const char *key, int i);
536 /* Level 3: return the first value in the subtree.
537 The first character of the value is node->prefix[j] */
538 static char *index_search__firstvalue(struct index_node_f *node, int j);
540 char *index_search(FILE *in, const char *key)
542 struct index_node_f *root;
543 char *value;
545 root = index_readroot(in);
546 value = index_search__node(root, key, 0);
548 return value;
551 static char *index_search__node(struct index_node_f *node, const char *key, int i)
553 struct index_node_f *child;
554 int ch;
555 int j;
557 while(node) {
558 for (j = 0; node->prefix[j]; j++) {
559 ch = node->prefix[j];
561 if (ch == ' ' && key[i+j] == '\0')
562 return index_search__firstvalue(node, j+1);
564 if (ch != key[i+j]) {
565 index_close(node);
566 return NULL;
569 i += j;
571 if (key[i] == '\0') {
572 child = index_readchild(node, ' ');
573 index_close(node);
574 if (child)
575 return index_search__firstvalue(child, 0);
576 else
577 return NULL;
580 child = index_readchild(node, key[i]);
581 index_close(node);
582 node = child;
583 i++;
586 return NULL;
589 static char *index_search__firstvalue(struct index_node_f *node, int j)
591 struct index_node_f *child;
592 struct buffer *buf;
594 buf = buf_create();
595 buf_pushchars(buf, &node->prefix[j]);
597 while (!node->isendpoint) {
598 if (node->first == INDEX_CHILDMAX)
599 index_fatal("Index node is neither parent nor endpoint");
601 buf_pushchar(buf, node->first);
602 child = index_readchild(node, node->first);
603 index_close(node);
604 node = child;
605 if (!node)
606 index_fatal("Index node has non-existent first child");
608 buf_pushchars(buf, node->prefix);
611 index_close(node);
612 return buf_detach(buf);
616 * Search the index for a key. The index may contain wildcards.
618 * Returns a list of all the values of matching keys.
621 /* Level 1: interface function */
622 struct index_value *index_searchwild(FILE *in, const char *key);
624 /* Level 2: descend the tree (until we hit a wildcard) */
625 static void index_searchwild__node(struct index_node_f *node,
626 struct buffer *buf,
627 const char *key, int i,
628 struct index_value **out);
630 /* Level 3: traverse a sub-keyspace which starts with a wildcard,
631 generating all subkeys.
633 static void index_searchwild__all(struct index_node_f *node, int j,
634 struct buffer *buf,
635 const char *subkey,
636 struct index_value **out);
638 /* Level 4: check for a subkey match */
639 static void index_searchwild__match(struct index_node_f *node, int j,
640 struct buffer *buf,
641 const char *subkey,
642 struct index_value **out);
644 /* Level 5: add all values for a matching subkey */
645 static void index_searchwild__allvalues(struct index_node_f *node, int j,
646 struct buffer *value_buf,
647 struct index_value **out);
650 struct index_value *index_searchwild(FILE *in, const char *key)
652 struct index_node_f *root = index_readroot(in);
653 struct buffer *buf = buf_create();
654 struct index_value *out = NULL;
656 index_searchwild__node(root, buf, key, 0, &out);
657 buf_destroy(buf);
658 return out;
661 static void index_searchwild__node(struct index_node_f *node,
662 struct buffer *buf,
663 const char *key, int i,
664 struct index_value **out)
666 struct index_node_f *child;
667 int j;
668 int ch;
670 while(node) {
671 for (j = 0; node->prefix[j]; j++) {
672 ch = node->prefix[j];
674 if (ch == '*' || ch == '?' || ch == '[') {
675 index_searchwild__all(node, j, buf,
676 &key[i+j], out);
677 return;
680 if (ch == ' ' && key[i+j] == '\0') {
681 /* Note: buf matches &key[i+j] - both are empty */
682 index_searchwild__match(node, j+1, buf,
683 &key[i+j], out);
684 return;
687 if (ch != key[i+j]) {
688 index_close(node);
689 return;
692 i += j;
694 child = index_readchild(node, '*');
695 if (child) {
696 buf_pushchar(buf, '*');
697 index_searchwild__all(child, 0, buf, &key[i], out);
698 buf_popchar(buf);
701 child = index_readchild(node, '?');
702 if (child) {
703 buf_pushchar(buf, '*');
704 index_searchwild__all(child, 0, buf, &key[i], out);
705 buf_popchar(buf);
708 child = index_readchild(node, '[');
709 if (child) {
710 buf_pushchar(buf, '[');
711 index_searchwild__all(child, 0, buf, &key[i], out);
712 buf_popchar(buf);
715 if (key[i] == '\0') {
716 child = index_readchild(node, ' ');
717 index_close(node);
718 /* Note: buf matches &key[i] - both are empty */
719 if(child)
720 index_searchwild__match(child, 0,
721 buf, &key[i], out);
722 return;
725 child = index_readchild(node, key[i]);
726 index_close(node);
727 node = child;
728 i++;
732 static void index_searchwild__all(struct index_node_f *node, int j,
733 struct buffer *buf,
734 const char *subkey,
735 struct index_value **out)
737 int pushed = 0;
738 int ch;
740 while (node->prefix[j]) {
741 ch = node->prefix[j];
743 if (ch == ' ') {
744 index_searchwild__match(node, j+1, buf, subkey, out);
745 goto out_popchars;
747 buf_pushchar(buf, ch);
748 pushed++;
749 j++;
752 for (ch = node->first; ch <= node->last; ch++) {
753 struct index_node_f *child = index_readchild(node, ch);
755 if (!child)
756 continue;
758 if (ch == ' ') {
759 index_searchwild__match(child, 0, buf, subkey, out);
760 } else {
761 buf_pushchar(buf, ch);
762 index_searchwild__all(child, 0, buf, subkey, out);
763 buf_popchar(buf);
767 index_close(node);
769 out_popchars:
770 buf_popchars(buf, pushed);
773 static void index_searchwild__match(struct index_node_f *node, int j,
774 struct buffer *buf,
775 const char *subkey,
776 struct index_value **out)
778 struct buffer *value_buf;
779 const char *pattern;
781 pattern = buf_str(buf);
782 if (fnmatch(pattern, subkey, 0) == 0) {
783 value_buf = buf_create();
784 index_searchwild__allvalues(node, j, value_buf, out);
785 buf_destroy(value_buf);
786 } else
787 index_close(node);
790 static void index_searchwild__allvalues(struct index_node_f *node, int j,
791 struct buffer *value_buf,
792 struct index_value **out)
794 int pushed = 0;
795 int ch;
797 pushed = buf_pushchars(value_buf, &node->prefix[j]);
799 if (node->isendpoint)
800 *out = add_value(value_buf, *out);
802 for (ch = node->first; ch <= node->last; ch++) {
803 struct index_node_f *child = index_readchild(node, ch);
805 if (!child)
806 continue;
808 buf_pushchar(value_buf, ch);
809 index_searchwild__allvalues(child, 0, value_buf, out);
810 buf_popchar(value_buf);
813 index_close(node);
814 buf_popchars(value_buf, pushed);