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/>.
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
;
42 void index_destroy(struct index_node
*node
)
46 for (c
= node
->first
; c
<= node
->last
; c
++) {
47 struct index_node
*child
= node
->children
[c
];
56 static void index__checkstring(const char *str
)
61 for (i
= 0; str
[i
]; 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
);
73 fatal("Module index: internal error - missing space (key/value separator)"
77 int index_insert(struct index_node
*node
, const char *str
)
79 int i
= 0; /* index within str */
83 index__checkstring(str
);
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
++) {
94 char *prefix
= node
->prefix
;
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
));
105 node
->prefix
= prefix
;
108 node
->children
[ch
] = n
;
113 /* j is now length of node->prefix */
118 if (node
->isendpoint
)
121 node
->isendpoint
= 1;
125 if (!node
->children
[ch
]) {
126 struct index_node
*child
;
128 if (ch
< node
->first
)
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
;
142 /* Descend into child node and continue */
143 node
= node
->children
[ch
];
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
;
169 /* Write children and save their offsets */
170 if (index__haschildren(node
)) {
171 const struct index_node
*child
;
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 */
186 if (node
->prefix
[0]) {
187 fputs(node
->prefix
, out
);
189 offset
|= INDEX_NODE_PREFIX
;
193 fputc(node
->first
, out
);
194 fputc(node
->last
, out
);
195 fwrite(child_offs
, sizeof(uint32_t), child_count
, out
);
197 offset
|= INDEX_NODE_CHILDS
;
200 if (node
->isendpoint
)
201 offset
|= INDEX_NODE_ENDPOINT
;
206 void index_write(const struct index_node
*node
, FILE *out
)
208 long initial_offset
, final_offset
;
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
);
219 fwrite(&u
, sizeof(uint32_t), 1, out
);
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
)
244 ch
= getc_unlocked(in
);
250 static uint32_t read_long(FILE *in
)
255 if (fread(&l
, sizeof(uint32_t), 1, in
) <= 0)
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.
274 static void buf__realloc(struct buffer
*buf
, unsigned size
)
276 if (size
> buf
->size
) {
277 buf
->bytes
= NOFAIL(realloc(buf
->bytes
, size
));
282 static struct buffer
*buf_create()
286 buf
= NOFAIL(calloc(sizeof(struct buffer
), 1));
287 buf__realloc(buf
, 256);
291 static void buf_destroy(struct buffer
*buf
)
297 /* Destroy buffer and return a copy as a C string */
298 static char *buf_detach(struct buffer
*buf
)
302 bytes
= NOFAIL(realloc(buf
->bytes
, buf
->used
+ 1));
303 bytes
[buf
->used
] = '\0';
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';
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';
336 static void buf_popchars(struct buffer
*buf
, unsigned n
)
341 static void buf_pushchar(struct buffer
*buf
, char ch
)
343 buf__realloc(buf
, buf
->used
+ 1);
344 buf
->bytes
[buf
->used
] = ch
;
348 static unsigned buf_pushchars(struct buffer
*buf
, const char *str
)
353 while ((ch
= str
[i
])) {
354 buf_pushchar(buf
, ch
);
360 /* like buf_pushchars(), but the string comes from a file */
361 static unsigned buf_freadchars(struct buffer
*buf
, FILE *in
)
366 while ((ch
= read_char(in
))) {
367 buf_pushchar(buf
, ch
);
374 static void buf_popchar(struct buffer
*buf
)
380 * Index file searching (used only by modprobe)
383 struct index_node_f
{
385 char *prefix
; /* path compression */
386 char isendpoint
; /* does this node represent a string? */
387 unsigned char first
; /* range of child nodes */
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
;
402 int i
, child_count
= 0;
404 if ((offset
& INDEX_NODE_MASK
) == 0)
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
);
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
));
427 for (i
= 0; i
< child_count
; i
++)
428 node
->children
[i
] = read_long(in
);
430 node
= NOFAIL(malloc(sizeof(struct index_node_f
)));
431 node
->first
= INDEX_CHILDMAX
;
435 node
->prefix
= prefix
;
436 node
->isendpoint
= !!(offset
& INDEX_NODE_ENDPOINT
);
441 static void index_close(struct index_node_f
*node
)
447 static struct index_node_f
*index_readchild(const struct index_node_f
*parent
,
450 if (parent
->first
<= ch
&& ch
<= parent
->last
)
451 return index_read(parent
->file
,
452 parent
->children
[ch
- parent
->first
]);
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;
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
,
487 pushed
= buf_pushchars(buf
, node
->prefix
);
489 if (node
->isendpoint
) {
491 buf_fwrite(buf
, out
);
495 for (ch
= node
->first
; ch
<= node
->last
; ch
++) {
496 struct index_node_f
*child
= index_readchild(node
, ch
);
501 buf_pushchar(buf
, ch
);
502 index_dump_node(child
, buf
, out
, prefix
);
506 buf_popchars(buf
, pushed
);
510 void index_dump(FILE *in
, FILE *out
, const char *prefix
)
512 struct index_node_f
*root
;
516 root
= index_readroot(in
);
517 index_dump_node(root
, buf
, out
, prefix
);
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
;
545 root
= index_readroot(in
);
546 value
= index_search__node(root
, key
, 0);
551 static char *index_search__node(struct index_node_f
*node
, const char *key
, int i
)
553 struct index_node_f
*child
;
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
]) {
571 if (key
[i
] == '\0') {
572 child
= index_readchild(node
, ' ');
575 return index_search__firstvalue(child
, 0);
580 child
= index_readchild(node
, key
[i
]);
589 static char *index_search__firstvalue(struct index_node_f
*node
, int j
)
591 struct index_node_f
*child
;
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
);
606 index_fatal("Index node has non-existent first child");
608 buf_pushchars(buf
, node
->prefix
);
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
,
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
,
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
,
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
);
661 static void index_searchwild__node(struct index_node_f
*node
,
663 const char *key
, int i
,
664 struct index_value
**out
)
666 struct index_node_f
*child
;
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
,
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
,
687 if (ch
!= key
[i
+j
]) {
694 child
= index_readchild(node
, '*');
696 buf_pushchar(buf
, '*');
697 index_searchwild__all(child
, 0, buf
, &key
[i
], out
);
701 child
= index_readchild(node
, '?');
703 buf_pushchar(buf
, '*');
704 index_searchwild__all(child
, 0, buf
, &key
[i
], out
);
708 child
= index_readchild(node
, '[');
710 buf_pushchar(buf
, '[');
711 index_searchwild__all(child
, 0, buf
, &key
[i
], out
);
715 if (key
[i
] == '\0') {
716 child
= index_readchild(node
, ' ');
718 /* Note: buf matches &key[i] - both are empty */
720 index_searchwild__match(child
, 0,
725 child
= index_readchild(node
, key
[i
]);
732 static void index_searchwild__all(struct index_node_f
*node
, int j
,
735 struct index_value
**out
)
740 while (node
->prefix
[j
]) {
741 ch
= node
->prefix
[j
];
744 index_searchwild__match(node
, j
+1, buf
, subkey
, out
);
747 buf_pushchar(buf
, ch
);
752 for (ch
= node
->first
; ch
<= node
->last
; ch
++) {
753 struct index_node_f
*child
= index_readchild(node
, ch
);
759 index_searchwild__match(child
, 0, buf
, subkey
, out
);
761 buf_pushchar(buf
, ch
);
762 index_searchwild__all(child
, 0, buf
, subkey
, out
);
770 buf_popchars(buf
, pushed
);
773 static void index_searchwild__match(struct index_node_f
*node
, int j
,
776 struct index_value
**out
)
778 struct buffer
*value_buf
;
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
);
790 static void index_searchwild__allvalues(struct index_node_f
*node
, int j
,
791 struct buffer
*value_buf
,
792 struct index_value
**out
)
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
);
808 buf_pushchar(value_buf
, ch
);
809 index_searchwild__allvalues(child
, 0, value_buf
, out
);
810 buf_popchar(value_buf
);
814 buf_popchars(value_buf
, pushed
);