2 * libkmod - interface to kernel module operations
4 * Copyright (C) 2011-2012 ProFUSION embedded systems
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
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.
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
21 #include <arpa/inet.h> /* htonl */
29 #include "libkmod-private.h"
30 #include "libkmod-index.h"
33 /* index.c: module index file shared functions for modprobe and depmod */
35 #define INDEX_CHILDMAX 128
39 uint32_t magic = INDEX_MAGIC;
40 uint32_t version = INDEX_VERSION;
43 (node_offset & INDEX_NODE_MASK) specifies the file offset of nodes:
45 char[] prefix; // nul terminated
49 uint32_t children[last - first + 1];
54 char[] value; // nul terminated
55 } values[value_count];
57 (node_offset & INDEX_NODE_FLAGS) indicates which fields are present.
58 Empty prefixes are omitted, leaf nodes omit the three child-related fields.
60 This could be optimised further by adding a sparse child format
61 (indicated using a new flag).
64 /* Format of node offsets within index file */
66 INDEX_NODE_FLAGS
= 0xF0000000, /* Flags in high nibble */
67 INDEX_NODE_PREFIX
= 0x80000000,
68 INDEX_NODE_VALUES
= 0x40000000,
69 INDEX_NODE_CHILDS
= 0x20000000,
71 INDEX_NODE_MASK
= 0x0FFFFFFF, /* Offset value */
74 void index_values_free(struct index_value
*values
)
77 struct index_value
*value
= values
;
84 static int add_value(struct index_value
**values
,
85 const char *value
, unsigned len
, unsigned int priority
)
87 struct index_value
*v
;
89 /* find position to insert value */
90 while (*values
&& (*values
)->priority
< priority
)
91 values
= &(*values
)->next
;
93 v
= malloc(sizeof(struct index_value
) + len
+ 1);
97 v
->priority
= priority
;
99 memcpy(v
->value
, value
, len
);
100 v
->value
[len
] = '\0';
106 static void read_error(void)
108 fatal("Module index: unexpected error: %s\n"
109 "Try re-running depmod\n", errno
? strerror(errno
) : "EOF");
112 static int read_char(FILE *in
)
117 ch
= getc_unlocked(in
);
123 static uint32_t read_long(FILE *in
)
128 if (fread(&l
, sizeof(uint32_t), 1, in
) <= 0)
134 * Buffer abstract data type
136 * Used internally to store the current path during tree traversal.
137 * They help build wildcard key strings to pass to fnmatch(),
138 * as well as building values of matching keys.
146 #define BUF_STEP (2048)
147 static bool buf_grow(struct buffer
*buf
, size_t newsize
)
152 if (newsize
% BUF_STEP
== 0)
155 sz
= ((newsize
/ BUF_STEP
) + 1) * BUF_STEP
;
160 tmp
= realloc(buf
->bytes
, sz
);
161 if (sz
> 0 && tmp
== NULL
)
168 static void buf_init(struct buffer
*buf
)
175 static void buf_release(struct buffer
*buf
)
180 /* Destroy buffer and return a copy as a C string */
181 static char *buf_steal(struct buffer
*buf
)
185 bytes
= realloc(buf
->bytes
, buf
->used
+ 1);
190 bytes
[buf
->used
] = '\0';
194 /* Return a C string owned by the buffer
195 (invalidated if the buffer is changed).
197 static const char *buf_str(struct buffer
*buf
)
199 if (!buf_grow(buf
, buf
->used
+ 1))
201 buf
->bytes
[buf
->used
] = '\0';
205 static bool buf_pushchar(struct buffer
*buf
, char ch
)
207 if (!buf_grow(buf
, buf
->used
+ 1))
209 buf
->bytes
[buf
->used
] = ch
;
214 static unsigned buf_pushchars(struct buffer
*buf
, const char *str
)
219 while ((ch
= str
[i
])) {
220 buf_pushchar(buf
, ch
);
227 static unsigned buf_freadchars(struct buffer
*buf
, FILE *in
)
232 while ((ch
= read_char(in
))) {
233 if (!buf_pushchar(buf
, ch
))
241 static void buf_popchar(struct buffer
*buf
)
243 assert(buf
->used
> 0);
247 static void buf_popchars(struct buffer
*buf
, unsigned n
)
249 assert(buf
->used
>= n
);
253 static void buf_clear(struct buffer
*buf
)
259 * Index file searching
261 struct index_node_f
{
263 char *prefix
; /* path compression */
264 struct index_value
*values
;
265 unsigned char first
; /* range of child nodes */
267 uint32_t children
[0];
270 static struct index_node_f
*index_read(FILE *in
, uint32_t offset
)
272 struct index_node_f
*node
;
274 int i
, child_count
= 0;
276 if ((offset
& INDEX_NODE_MASK
) == 0)
279 fseek(in
, offset
& INDEX_NODE_MASK
, SEEK_SET
);
281 if (offset
& INDEX_NODE_PREFIX
) {
284 buf_freadchars(&buf
, in
);
285 prefix
= buf_steal(&buf
);
287 prefix
= NOFAIL(strdup(""));
289 if (offset
& INDEX_NODE_CHILDS
) {
290 char first
= read_char(in
);
291 char last
= read_char(in
);
292 child_count
= last
- first
+ 1;
294 node
= NOFAIL(malloc(sizeof(struct index_node_f
) +
295 sizeof(uint32_t) * child_count
));
300 for (i
= 0; i
< child_count
; i
++)
301 node
->children
[i
] = read_long(in
);
303 node
= NOFAIL(malloc(sizeof(struct index_node_f
)));
304 node
->first
= INDEX_CHILDMAX
;
309 if (offset
& INDEX_NODE_VALUES
) {
313 unsigned int priority
;
315 value_count
= read_long(in
);
318 while (value_count
--) {
319 priority
= read_long(in
);
320 buf_freadchars(&buf
, in
);
321 value
= buf_str(&buf
);
322 add_value(&node
->values
, value
, buf
.used
, priority
);
328 node
->prefix
= prefix
;
333 static void index_close(struct index_node_f
*node
)
336 index_values_free(node
->values
);
342 uint32_t root_offset
;
345 /* Failures are silent; modprobe will fall back to text files */
346 struct index_file
*index_file_open(const char *filename
)
349 uint32_t magic
, version
;
350 struct index_file
*new;
352 file
= fopen(filename
, "re");
357 magic
= read_long(file
);
358 if (magic
!= INDEX_MAGIC
) {
363 version
= read_long(file
);
364 if (version
>> 16 != INDEX_VERSION_MAJOR
) {
369 new = NOFAIL(malloc(sizeof(struct index_file
)));
371 new->root_offset
= read_long(new->file
);
377 void index_file_close(struct index_file
*idx
)
383 static struct index_node_f
*index_readroot(struct index_file
*in
)
385 return index_read(in
->file
, in
->root_offset
);
388 static struct index_node_f
*index_readchild(const struct index_node_f
*parent
,
391 if (parent
->first
<= ch
&& ch
<= parent
->last
) {
392 return index_read(parent
->file
,
393 parent
->children
[ch
- parent
->first
]);
399 static void index_dump_node(struct index_node_f
*node
, struct buffer
*buf
,
402 struct index_value
*v
;
405 pushed
= buf_pushchars(buf
, node
->prefix
);
407 for (v
= node
->values
; v
!= NULL
; v
= v
->next
) {
408 write_str_safe(fd
, buf
->bytes
, buf
->used
);
409 write_str_safe(fd
, " ", 1);
410 write_str_safe(fd
, v
->value
, strlen(v
->value
));
411 write_str_safe(fd
, "\n", 1);
414 for (ch
= node
->first
; ch
<= node
->last
; ch
++) {
415 struct index_node_f
*child
= index_readchild(node
, ch
);
420 buf_pushchar(buf
, ch
);
421 index_dump_node(child
, buf
, fd
);
425 buf_popchars(buf
, pushed
);
429 void index_dump(struct index_file
*in
, int fd
, const char *prefix
)
431 struct index_node_f
*root
;
435 buf_pushchars(&buf
, prefix
);
436 root
= index_readroot(in
);
437 index_dump_node(root
, &buf
, fd
);
441 static char *index_search__node(struct index_node_f
*node
, const char *key
, int i
)
444 struct index_node_f
*child
;
449 for (j
= 0; node
->prefix
[j
]; j
++) {
450 ch
= node
->prefix
[j
];
452 if (ch
!= key
[i
+j
]) {
460 if (key
[i
] == '\0') {
461 value
= node
->values
!= NULL
462 ? strdup(node
->values
[0].value
)
469 child
= index_readchild(node
, key
[i
]);
479 * Search the index for a key
481 * Returns the value of the first match
483 * The recursive functions free their node argument (using index_close).
485 char *index_search(struct index_file
*in
, const char *key
)
487 // FIXME: return value by reference instead of strdup
488 struct index_node_f
*root
;
491 root
= index_readroot(in
);
492 value
= index_search__node(root
, key
, 0);
499 /* Level 4: add all the values from a matching node */
500 static void index_searchwild__allvalues(struct index_node_f
*node
,
501 struct index_value
**out
)
503 struct index_value
*v
;
505 for (v
= node
->values
; v
!= NULL
; v
= v
->next
)
506 add_value(out
, v
->value
, v
->len
, v
->priority
);
512 * Level 3: traverse a sub-keyspace which starts with a wildcard,
513 * looking for matches.
515 static void index_searchwild__all(struct index_node_f
*node
, int j
,
518 struct index_value
**out
)
523 while (node
->prefix
[j
]) {
524 ch
= node
->prefix
[j
];
526 buf_pushchar(buf
, ch
);
531 for (ch
= node
->first
; ch
<= node
->last
; ch
++) {
532 struct index_node_f
*child
= index_readchild(node
, ch
);
537 buf_pushchar(buf
, ch
);
538 index_searchwild__all(child
, 0, buf
, subkey
, out
);
543 if (fnmatch(buf_str(buf
), subkey
, 0) == 0)
544 index_searchwild__allvalues(node
, out
);
551 buf_popchars(buf
, pushed
);
554 /* Level 2: descend the tree (until we hit a wildcard) */
555 static void index_searchwild__node(struct index_node_f
*node
,
557 const char *key
, int i
,
558 struct index_value
**out
)
560 struct index_node_f
*child
;
565 for (j
= 0; node
->prefix
[j
]; j
++) {
566 ch
= node
->prefix
[j
];
568 if (ch
== '*' || ch
== '?' || ch
== '[') {
569 index_searchwild__all(node
, j
, buf
,
574 if (ch
!= key
[i
+j
]) {
582 child
= index_readchild(node
, '*');
584 buf_pushchar(buf
, '*');
585 index_searchwild__all(child
, 0, buf
, &key
[i
], out
);
589 child
= index_readchild(node
, '?');
591 buf_pushchar(buf
, '?');
592 index_searchwild__all(child
, 0, buf
, &key
[i
], out
);
596 child
= index_readchild(node
, '[');
598 buf_pushchar(buf
, '[');
599 index_searchwild__all(child
, 0, buf
, &key
[i
], out
);
603 if (key
[i
] == '\0') {
604 index_searchwild__allvalues(node
, out
);
609 child
= index_readchild(node
, key
[i
]);
617 * Search the index for a key. The index may contain wildcards.
619 * Returns a list of all the values of matching keys.
621 struct index_value
*index_searchwild(struct index_file
*in
, const char *key
)
623 struct index_node_f
*root
= index_readroot(in
);
625 struct index_value
*out
= NULL
;
628 index_searchwild__node(root
, &buf
, key
, 0, &out
);
633 #include <sys/mman.h>
634 #include <sys/stat.h>
637 static const char _idx_empty_str
[] = "";
639 /**************************************************************************/
641 * Alternative implementation, using mmap to map all the file to memory when
645 struct kmod_ctx
*ctx
;
647 uint32_t root_offset
;
651 struct index_mm_value
{
652 unsigned int priority
;
657 struct index_mm_value_array
{
658 struct index_mm_value
*values
;
662 struct index_mm_node
{
663 struct index_mm
*idx
;
664 const char *prefix
; /* mmape'd value */
665 struct index_mm_value_array values
;
671 static inline uint32_t read_long_mm(void **p
)
673 uint8_t *addr
= *(uint8_t **)p
;
676 /* addr may be unalined to uint32_t */
677 memcpy(&v
, addr
, sizeof(uint32_t));
679 *p
= addr
+ sizeof(uint32_t);
683 static inline uint8_t read_char_mm(void **p
)
685 uint8_t *addr
= *(uint8_t **)p
;
687 *p
= addr
+ sizeof(uint8_t);
691 static inline char *read_chars_mm(void **p
, unsigned *rlen
)
693 char *addr
= *(char **)p
;
694 size_t len
= *rlen
= strlen(addr
);
699 static struct index_mm_node
*index_mm_read_node(struct index_mm
*idx
,
702 struct index_mm_node
*node
;
704 int i
, child_count
, value_count
, children_padding
;
705 uint32_t children
[INDEX_CHILDMAX
];
708 if ((offset
& INDEX_NODE_MASK
) == 0)
711 p
= (char *)p
+ (offset
& INDEX_NODE_MASK
);
713 if (offset
& INDEX_NODE_PREFIX
) {
715 prefix
= read_chars_mm(&p
, &len
);
717 prefix
= _idx_empty_str
;
719 if (offset
& INDEX_NODE_CHILDS
) {
720 first
= read_char_mm(&p
);
721 last
= read_char_mm(&p
);
722 child_count
= last
- first
+ 1;
723 for (i
= 0; i
< child_count
; i
++)
724 children
[i
] = read_long_mm(&p
);
726 first
= INDEX_CHILDMAX
;
731 children_padding
= (sizeof(struct index_mm_node
) +
732 (sizeof(uint32_t) * child_count
)) % sizeof(void *);
734 if (offset
& INDEX_NODE_VALUES
)
735 value_count
= read_long_mm(&p
);
739 node
= malloc(sizeof(struct index_mm_node
)
740 + sizeof(uint32_t) * child_count
+ children_padding
741 + sizeof(struct index_mm_value
) * value_count
);
746 node
->prefix
= prefix
;
747 if (value_count
== 0)
748 node
->values
.values
= NULL
;
750 node
->values
.values
= (struct index_mm_value
*)
751 ((char *)node
+ sizeof(struct index_mm_node
) +
752 sizeof(uint32_t) * child_count
+ children_padding
);
754 node
->values
.len
= value_count
;
757 memcpy(node
->children
, children
, sizeof(uint32_t) * child_count
);
759 for (i
= 0; i
< value_count
; i
++) {
760 struct index_mm_value
*v
= node
->values
.values
+ i
;
761 v
->priority
= read_long_mm(&p
);
762 v
->value
= read_chars_mm(&p
, &v
->len
);
768 static void index_mm_free_node(struct index_mm_node
*node
)
773 struct index_mm
*index_mm_open(struct kmod_ctx
*ctx
, const char *filename
,
774 unsigned long long *stamp
)
778 struct index_mm
*idx
;
782 uint32_t root_offset
;
786 DBG(ctx
, "file=%s\n", filename
);
788 idx
= malloc(sizeof(*idx
));
790 ERR(ctx
, "malloc: %m\n");
794 if ((fd
= open(filename
, O_RDONLY
|O_CLOEXEC
)) < 0) {
795 DBG(ctx
, "open(%s, O_RDONLY|O_CLOEXEC): %m\n", filename
);
801 if ((idx
->mm
= mmap(0, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0))
803 ERR(ctx
, "mmap(0, %zd, PROT_READ, %d, MAP_PRIVATE, 0): %m\n",
809 hdr
.magic
= read_long_mm(&p
);
810 hdr
.version
= read_long_mm(&p
);
811 hdr
.root_offset
= read_long_mm(&p
);
813 if (hdr
.magic
!= INDEX_MAGIC
) {
814 ERR(ctx
, "magic check fail: %x instead of %x\n", hdr
.magic
,
819 if (hdr
.version
>> 16 != INDEX_VERSION_MAJOR
) {
820 ERR(ctx
, "major version check fail: %u instead of %u\n",
821 hdr
.version
, INDEX_MAGIC
);
825 idx
->root_offset
= hdr
.root_offset
;
826 idx
->size
= st
.st_size
;
830 *stamp
= stat_mstamp(&st
);
836 if (idx
->mm
!= MAP_FAILED
)
837 munmap(idx
->mm
, st
.st_size
);
843 void index_mm_close(struct index_mm
*idx
)
845 munmap(idx
->mm
, idx
->size
);
849 static struct index_mm_node
*index_mm_readroot(struct index_mm
*idx
)
851 return index_mm_read_node(idx
, idx
->root_offset
);
854 static struct index_mm_node
*index_mm_readchild(const struct index_mm_node
*parent
,
857 if (parent
->first
<= ch
&& ch
<= parent
->last
) {
858 return index_mm_read_node(parent
->idx
,
859 parent
->children
[ch
- parent
->first
]);
865 static void index_mm_dump_node(struct index_mm_node
*node
, struct buffer
*buf
,
868 struct index_mm_value
*itr
, *itr_end
;
871 pushed
= buf_pushchars(buf
, node
->prefix
);
873 itr
= node
->values
.values
;
874 itr_end
= itr
+ node
->values
.len
;
875 for (; itr
< itr_end
; itr
++) {
876 write_str_safe(fd
, buf
->bytes
, buf
->used
);
877 write_str_safe(fd
, " ", 1);
878 write_str_safe(fd
, itr
->value
, itr
->len
);
879 write_str_safe(fd
, "\n", 1);
882 for (ch
= node
->first
; ch
<= node
->last
; ch
++) {
883 struct index_mm_node
*child
= index_mm_readchild(node
, ch
);
888 buf_pushchar(buf
, ch
);
889 index_mm_dump_node(child
, buf
, fd
);
893 buf_popchars(buf
, pushed
);
894 index_mm_free_node(node
);
897 void index_mm_dump(struct index_mm
*idx
, int fd
, const char *prefix
)
899 struct index_mm_node
*root
;
903 buf_pushchars(&buf
, prefix
);
904 root
= index_mm_readroot(idx
);
905 index_mm_dump_node(root
, &buf
, fd
);
909 static char *index_mm_search_node(struct index_mm_node
*node
, const char *key
,
913 struct index_mm_node
*child
;
918 for (j
= 0; node
->prefix
[j
]; j
++) {
919 ch
= node
->prefix
[j
];
921 if (ch
!= key
[i
+j
]) {
922 index_mm_free_node(node
);
929 if (key
[i
] == '\0') {
930 value
= node
->values
.len
> 0
931 ? strdup(node
->values
.values
[0].value
)
934 index_mm_free_node(node
);
938 child
= index_mm_readchild(node
, key
[i
]);
939 index_mm_free_node(node
);
948 * Search the index for a key
950 * Returns the value of the first match
952 * The recursive functions free their node argument (using index_close).
954 char *index_mm_search(struct index_mm
*idx
, const char *key
)
956 // FIXME: return value by reference instead of strdup
957 struct index_mm_node
*root
;
960 root
= index_mm_readroot(idx
);
961 value
= index_mm_search_node(root
, key
, 0);
966 /* Level 4: add all the values from a matching node */
967 static void index_mm_searchwild_allvalues(struct index_mm_node
*node
,
968 struct index_value
**out
)
970 struct index_mm_value
*itr
, *itr_end
;
972 itr
= node
->values
.values
;
973 itr_end
= itr
+ node
->values
.len
;
974 for (; itr
< itr_end
; itr
++)
975 add_value(out
, itr
->value
, itr
->len
, itr
->priority
);
977 index_mm_free_node(node
);
981 * Level 3: traverse a sub-keyspace which starts with a wildcard,
982 * looking for matches.
984 static void index_mm_searchwild_all(struct index_mm_node
*node
, int j
,
987 struct index_value
**out
)
992 while (node
->prefix
[j
]) {
993 ch
= node
->prefix
[j
];
995 buf_pushchar(buf
, ch
);
1000 for (ch
= node
->first
; ch
<= node
->last
; ch
++) {
1001 struct index_mm_node
*child
= index_mm_readchild(node
, ch
);
1006 buf_pushchar(buf
, ch
);
1007 index_mm_searchwild_all(child
, 0, buf
, subkey
, out
);
1011 if (node
->values
.len
> 0) {
1012 if (fnmatch(buf_str(buf
), subkey
, 0) == 0)
1013 index_mm_searchwild_allvalues(node
, out
);
1015 index_mm_free_node(node
);
1017 index_mm_free_node(node
);
1020 buf_popchars(buf
, pushed
);
1023 /* Level 2: descend the tree (until we hit a wildcard) */
1024 static void index_mm_searchwild_node(struct index_mm_node
*node
,
1026 const char *key
, int i
,
1027 struct index_value
**out
)
1029 struct index_mm_node
*child
;
1034 for (j
= 0; node
->prefix
[j
]; j
++) {
1035 ch
= node
->prefix
[j
];
1037 if (ch
== '*' || ch
== '?' || ch
== '[') {
1038 index_mm_searchwild_all(node
, j
, buf
,
1043 if (ch
!= key
[i
+j
]) {
1044 index_mm_free_node(node
);
1051 child
= index_mm_readchild(node
, '*');
1053 buf_pushchar(buf
, '*');
1054 index_mm_searchwild_all(child
, 0, buf
, &key
[i
], out
);
1058 child
= index_mm_readchild(node
, '?');
1060 buf_pushchar(buf
, '?');
1061 index_mm_searchwild_all(child
, 0, buf
, &key
[i
], out
);
1065 child
= index_mm_readchild(node
, '[');
1067 buf_pushchar(buf
, '[');
1068 index_mm_searchwild_all(child
, 0, buf
, &key
[i
], out
);
1072 if (key
[i
] == '\0') {
1073 index_mm_searchwild_allvalues(node
, out
);
1078 child
= index_mm_readchild(node
, key
[i
]);
1079 index_mm_free_node(node
);
1086 * Search the index for a key. The index may contain wildcards.
1088 * Returns a list of all the values of matching keys.
1090 struct index_value
*index_mm_searchwild(struct index_mm
*idx
, const char *key
)
1092 struct index_mm_node
*root
= index_mm_readroot(idx
);
1094 struct index_value
*out
= NULL
;
1097 index_mm_searchwild_node(root
, &buf
, key
, 0, &out
);