2 * libkmod - interface to kernel module operations
4 * Copyright (C) 2011-2013 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>
30 #include <shared/macro.h>
31 #include <shared/util.h>
33 #include "libkmod-internal.h"
34 #include "libkmod-index.h"
36 /* index.c: module index file shared functions for modprobe and depmod */
38 #define INDEX_CHILDMAX 128
42 uint32_t magic = INDEX_MAGIC;
43 uint32_t version = INDEX_VERSION;
46 (node_offset & INDEX_NODE_MASK) specifies the file offset of nodes:
48 char[] prefix; // nul terminated
52 uint32_t children[last - first + 1];
57 char[] value; // nul terminated
58 } values[value_count];
60 (node_offset & INDEX_NODE_FLAGS) indicates which fields are present.
61 Empty prefixes are omitted, leaf nodes omit the three child-related fields.
63 This could be optimised further by adding a sparse child format
64 (indicated using a new flag).
67 /* Format of node offsets within index file */
69 INDEX_NODE_FLAGS
= 0xF0000000, /* Flags in high nibble */
70 INDEX_NODE_PREFIX
= 0x80000000,
71 INDEX_NODE_VALUES
= 0x40000000,
72 INDEX_NODE_CHILDS
= 0x20000000,
74 INDEX_NODE_MASK
= 0x0FFFFFFF, /* Offset value */
77 void index_values_free(struct index_value
*values
)
80 struct index_value
*value
= values
;
87 static int add_value(struct index_value
**values
,
88 const char *value
, unsigned len
, unsigned int priority
)
90 struct index_value
*v
;
92 /* find position to insert value */
93 while (*values
&& (*values
)->priority
< priority
)
94 values
= &(*values
)->next
;
96 v
= malloc(sizeof(struct index_value
) + len
+ 1);
100 v
->priority
= priority
;
102 memcpy(v
->value
, value
, len
);
103 v
->value
[len
] = '\0';
109 static void read_error(void)
111 fatal("Module index: unexpected error: %s\n"
112 "Try re-running depmod\n", errno
? strerror(errno
) : "EOF");
115 static int read_char(FILE *in
)
120 ch
= getc_unlocked(in
);
126 static uint32_t read_long(FILE *in
)
131 if (fread(&l
, sizeof(uint32_t), 1, in
) != sizeof(uint32_t))
137 * Buffer abstract data type
139 * Used internally to store the current path during tree traversal.
140 * They help build wildcard key strings to pass to fnmatch(),
141 * as well as building values of matching keys.
149 #define BUF_STEP (2048)
150 static bool buf_grow(struct buffer
*buf
, size_t newsize
)
155 if (newsize
% BUF_STEP
== 0)
158 sz
= ((newsize
/ BUF_STEP
) + 1) * BUF_STEP
;
163 tmp
= realloc(buf
->bytes
, sz
);
164 if (sz
> 0 && tmp
== NULL
)
171 static void buf_init(struct buffer
*buf
)
178 static void buf_release(struct buffer
*buf
)
183 /* Destroy buffer and return a copy as a C string */
184 static char *buf_steal(struct buffer
*buf
)
188 bytes
= realloc(buf
->bytes
, buf
->used
+ 1);
193 bytes
[buf
->used
] = '\0';
197 /* Return a C string owned by the buffer
198 (invalidated if the buffer is changed).
200 static const char *buf_str(struct buffer
*buf
)
202 if (!buf_grow(buf
, buf
->used
+ 1))
204 buf
->bytes
[buf
->used
] = '\0';
208 static bool buf_pushchar(struct buffer
*buf
, char ch
)
210 if (!buf_grow(buf
, buf
->used
+ 1))
212 buf
->bytes
[buf
->used
] = ch
;
217 static unsigned buf_pushchars(struct buffer
*buf
, const char *str
)
222 while ((ch
= str
[i
])) {
223 buf_pushchar(buf
, ch
);
230 static unsigned buf_freadchars(struct buffer
*buf
, FILE *in
)
235 while ((ch
= read_char(in
))) {
236 if (!buf_pushchar(buf
, ch
))
244 static void buf_popchar(struct buffer
*buf
)
246 assert(buf
->used
> 0);
250 static void buf_popchars(struct buffer
*buf
, unsigned n
)
252 assert(buf
->used
>= n
);
256 static void buf_clear(struct buffer
*buf
)
262 * Index file searching
264 struct index_node_f
{
266 char *prefix
; /* path compression */
267 struct index_value
*values
;
268 unsigned char first
; /* range of child nodes */
270 uint32_t children
[0];
273 static struct index_node_f
*index_read(FILE *in
, uint32_t offset
)
275 struct index_node_f
*node
;
277 int i
, child_count
= 0;
279 if ((offset
& INDEX_NODE_MASK
) == 0)
282 fseek(in
, offset
& INDEX_NODE_MASK
, SEEK_SET
);
284 if (offset
& INDEX_NODE_PREFIX
) {
287 buf_freadchars(&buf
, in
);
288 prefix
= buf_steal(&buf
);
290 prefix
= NOFAIL(strdup(""));
292 if (offset
& INDEX_NODE_CHILDS
) {
293 char first
= read_char(in
);
294 char last
= read_char(in
);
295 child_count
= last
- first
+ 1;
297 node
= NOFAIL(malloc(sizeof(struct index_node_f
) +
298 sizeof(uint32_t) * child_count
));
303 for (i
= 0; i
< child_count
; i
++)
304 node
->children
[i
] = read_long(in
);
306 node
= NOFAIL(malloc(sizeof(struct index_node_f
)));
307 node
->first
= INDEX_CHILDMAX
;
312 if (offset
& INDEX_NODE_VALUES
) {
316 unsigned int priority
;
318 value_count
= read_long(in
);
321 while (value_count
--) {
322 priority
= read_long(in
);
323 buf_freadchars(&buf
, in
);
324 value
= buf_str(&buf
);
325 add_value(&node
->values
, value
, buf
.used
, priority
);
331 node
->prefix
= prefix
;
336 static void index_close(struct index_node_f
*node
)
339 index_values_free(node
->values
);
345 uint32_t root_offset
;
348 /* Failures are silent; modprobe will fall back to text files */
349 struct index_file
*index_file_open(const char *filename
)
352 uint32_t magic
, version
;
353 struct index_file
*new;
355 file
= fopen(filename
, "re");
360 magic
= read_long(file
);
361 if (magic
!= INDEX_MAGIC
) {
366 version
= read_long(file
);
367 if (version
>> 16 != INDEX_VERSION_MAJOR
) {
372 new = NOFAIL(malloc(sizeof(struct index_file
)));
374 new->root_offset
= read_long(new->file
);
380 void index_file_close(struct index_file
*idx
)
386 static struct index_node_f
*index_readroot(struct index_file
*in
)
388 return index_read(in
->file
, in
->root_offset
);
391 static struct index_node_f
*index_readchild(const struct index_node_f
*parent
,
394 if (parent
->first
<= ch
&& ch
<= parent
->last
) {
395 return index_read(parent
->file
,
396 parent
->children
[ch
- parent
->first
]);
402 static void index_dump_node(struct index_node_f
*node
, struct buffer
*buf
,
405 struct index_value
*v
;
408 pushed
= buf_pushchars(buf
, node
->prefix
);
410 for (v
= node
->values
; v
!= NULL
; v
= v
->next
) {
411 write_str_safe(fd
, buf
->bytes
, buf
->used
);
412 write_str_safe(fd
, " ", 1);
413 write_str_safe(fd
, v
->value
, strlen(v
->value
));
414 write_str_safe(fd
, "\n", 1);
417 for (ch
= node
->first
; ch
<= node
->last
; ch
++) {
418 struct index_node_f
*child
= index_readchild(node
, ch
);
423 buf_pushchar(buf
, ch
);
424 index_dump_node(child
, buf
, fd
);
428 buf_popchars(buf
, pushed
);
432 void index_dump(struct index_file
*in
, int fd
, const char *prefix
)
434 struct index_node_f
*root
;
437 root
= index_readroot(in
);
442 buf_pushchars(&buf
, prefix
);
443 index_dump_node(root
, &buf
, fd
);
447 static char *index_search__node(struct index_node_f
*node
, const char *key
, int i
)
450 struct index_node_f
*child
;
455 for (j
= 0; node
->prefix
[j
]; j
++) {
456 ch
= node
->prefix
[j
];
458 if (ch
!= key
[i
+j
]) {
466 if (key
[i
] == '\0') {
467 value
= node
->values
!= NULL
468 ? strdup(node
->values
[0].value
)
475 child
= index_readchild(node
, key
[i
]);
485 * Search the index for a key
487 * Returns the value of the first match
489 * The recursive functions free their node argument (using index_close).
491 char *index_search(struct index_file
*in
, const char *key
)
493 // FIXME: return value by reference instead of strdup
494 struct index_node_f
*root
;
497 root
= index_readroot(in
);
498 value
= index_search__node(root
, key
, 0);
505 /* Level 4: add all the values from a matching node */
506 static void index_searchwild__allvalues(struct index_node_f
*node
,
507 struct index_value
**out
)
509 struct index_value
*v
;
511 for (v
= node
->values
; v
!= NULL
; v
= v
->next
)
512 add_value(out
, v
->value
, v
->len
, v
->priority
);
518 * Level 3: traverse a sub-keyspace which starts with a wildcard,
519 * looking for matches.
521 static void index_searchwild__all(struct index_node_f
*node
, int j
,
524 struct index_value
**out
)
529 while (node
->prefix
[j
]) {
530 ch
= node
->prefix
[j
];
532 buf_pushchar(buf
, ch
);
537 for (ch
= node
->first
; ch
<= node
->last
; ch
++) {
538 struct index_node_f
*child
= index_readchild(node
, ch
);
543 buf_pushchar(buf
, ch
);
544 index_searchwild__all(child
, 0, buf
, subkey
, out
);
549 if (fnmatch(buf_str(buf
), subkey
, 0) == 0)
550 index_searchwild__allvalues(node
, out
);
557 buf_popchars(buf
, pushed
);
560 /* Level 2: descend the tree (until we hit a wildcard) */
561 static void index_searchwild__node(struct index_node_f
*node
,
563 const char *key
, int i
,
564 struct index_value
**out
)
566 struct index_node_f
*child
;
571 for (j
= 0; node
->prefix
[j
]; j
++) {
572 ch
= node
->prefix
[j
];
574 if (ch
== '*' || ch
== '?' || ch
== '[') {
575 index_searchwild__all(node
, j
, buf
,
580 if (ch
!= key
[i
+j
]) {
588 child
= index_readchild(node
, '*');
590 buf_pushchar(buf
, '*');
591 index_searchwild__all(child
, 0, buf
, &key
[i
], out
);
595 child
= index_readchild(node
, '?');
597 buf_pushchar(buf
, '?');
598 index_searchwild__all(child
, 0, buf
, &key
[i
], out
);
602 child
= index_readchild(node
, '[');
604 buf_pushchar(buf
, '[');
605 index_searchwild__all(child
, 0, buf
, &key
[i
], out
);
609 if (key
[i
] == '\0') {
610 index_searchwild__allvalues(node
, out
);
615 child
= index_readchild(node
, key
[i
]);
623 * Search the index for a key. The index may contain wildcards.
625 * Returns a list of all the values of matching keys.
627 struct index_value
*index_searchwild(struct index_file
*in
, const char *key
)
629 struct index_node_f
*root
= index_readroot(in
);
631 struct index_value
*out
= NULL
;
634 index_searchwild__node(root
, &buf
, key
, 0, &out
);
639 #include <sys/mman.h>
640 #include <sys/stat.h>
643 static const char _idx_empty_str
[] = "";
645 /**************************************************************************/
647 * Alternative implementation, using mmap to map all the file to memory when
651 struct kmod_ctx
*ctx
;
653 uint32_t root_offset
;
657 struct index_mm_value
{
658 unsigned int priority
;
663 struct index_mm_value_array
{
664 struct index_mm_value
*values
;
668 struct index_mm_node
{
669 struct index_mm
*idx
;
670 const char *prefix
; /* mmape'd value */
671 struct index_mm_value_array values
;
677 static inline uint32_t read_long_mm(void **p
)
679 uint8_t *addr
= *(uint8_t **)p
;
682 /* addr may be unalined to uint32_t */
683 v
= get_unaligned((uint32_t *) addr
);
685 *p
= addr
+ sizeof(uint32_t);
689 static inline uint8_t read_char_mm(void **p
)
691 uint8_t *addr
= *(uint8_t **)p
;
693 *p
= addr
+ sizeof(uint8_t);
697 static inline char *read_chars_mm(void **p
, unsigned *rlen
)
699 char *addr
= *(char **)p
;
700 size_t len
= *rlen
= strlen(addr
);
705 static struct index_mm_node
*index_mm_read_node(struct index_mm
*idx
,
708 struct index_mm_node
*node
;
710 int i
, child_count
, value_count
, children_padding
;
711 uint32_t children
[INDEX_CHILDMAX
];
714 if ((offset
& INDEX_NODE_MASK
) == 0)
717 p
= (char *)p
+ (offset
& INDEX_NODE_MASK
);
719 if (offset
& INDEX_NODE_PREFIX
) {
721 prefix
= read_chars_mm(&p
, &len
);
723 prefix
= _idx_empty_str
;
725 if (offset
& INDEX_NODE_CHILDS
) {
726 first
= read_char_mm(&p
);
727 last
= read_char_mm(&p
);
728 child_count
= last
- first
+ 1;
729 for (i
= 0; i
< child_count
; i
++)
730 children
[i
] = read_long_mm(&p
);
732 first
= INDEX_CHILDMAX
;
737 children_padding
= (sizeof(struct index_mm_node
) +
738 (sizeof(uint32_t) * child_count
)) % sizeof(void *);
740 if (offset
& INDEX_NODE_VALUES
)
741 value_count
= read_long_mm(&p
);
745 node
= malloc(sizeof(struct index_mm_node
)
746 + sizeof(uint32_t) * child_count
+ children_padding
747 + sizeof(struct index_mm_value
) * value_count
);
752 node
->prefix
= prefix
;
753 if (value_count
== 0)
754 node
->values
.values
= NULL
;
756 node
->values
.values
= (struct index_mm_value
*)
757 ((char *)node
+ sizeof(struct index_mm_node
) +
758 sizeof(uint32_t) * child_count
+ children_padding
);
760 node
->values
.len
= value_count
;
763 memcpy(node
->children
, children
, sizeof(uint32_t) * child_count
);
765 for (i
= 0; i
< value_count
; i
++) {
766 struct index_mm_value
*v
= node
->values
.values
+ i
;
767 v
->priority
= read_long_mm(&p
);
768 v
->value
= read_chars_mm(&p
, &v
->len
);
774 static void index_mm_free_node(struct index_mm_node
*node
)
779 struct index_mm
*index_mm_open(struct kmod_ctx
*ctx
, const char *filename
,
780 unsigned long long *stamp
)
784 struct index_mm
*idx
;
788 uint32_t root_offset
;
792 DBG(ctx
, "file=%s\n", filename
);
794 idx
= malloc(sizeof(*idx
));
796 ERR(ctx
, "malloc: %m\n");
800 if ((fd
= open(filename
, O_RDONLY
|O_CLOEXEC
)) < 0) {
801 DBG(ctx
, "open(%s, O_RDONLY|O_CLOEXEC): %m\n", filename
);
805 if (fstat(fd
, &st
) < 0)
807 if ((size_t) st
.st_size
< sizeof(hdr
))
810 if ((idx
->mm
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0))
812 ERR(ctx
, "mmap(NULL, %"PRIu64
", PROT_READ, %d, MAP_PRIVATE, 0): %m\n",
818 hdr
.magic
= read_long_mm(&p
);
819 hdr
.version
= read_long_mm(&p
);
820 hdr
.root_offset
= read_long_mm(&p
);
822 if (hdr
.magic
!= INDEX_MAGIC
) {
823 ERR(ctx
, "magic check fail: %x instead of %x\n", hdr
.magic
,
828 if (hdr
.version
>> 16 != INDEX_VERSION_MAJOR
) {
829 ERR(ctx
, "major version check fail: %u instead of %u\n",
830 hdr
.version
>> 16, INDEX_VERSION_MAJOR
);
834 idx
->root_offset
= hdr
.root_offset
;
835 idx
->size
= st
.st_size
;
839 *stamp
= stat_mstamp(&st
);
844 munmap(idx
->mm
, st
.st_size
);
852 void index_mm_close(struct index_mm
*idx
)
854 munmap(idx
->mm
, idx
->size
);
858 static struct index_mm_node
*index_mm_readroot(struct index_mm
*idx
)
860 return index_mm_read_node(idx
, idx
->root_offset
);
863 static struct index_mm_node
*index_mm_readchild(const struct index_mm_node
*parent
,
866 if (parent
->first
<= ch
&& ch
<= parent
->last
) {
867 return index_mm_read_node(parent
->idx
,
868 parent
->children
[ch
- parent
->first
]);
874 static void index_mm_dump_node(struct index_mm_node
*node
, struct buffer
*buf
,
877 struct index_mm_value
*itr
, *itr_end
;
880 pushed
= buf_pushchars(buf
, node
->prefix
);
882 itr
= node
->values
.values
;
883 itr_end
= itr
+ node
->values
.len
;
884 for (; itr
< itr_end
; itr
++) {
885 write_str_safe(fd
, buf
->bytes
, buf
->used
);
886 write_str_safe(fd
, " ", 1);
887 write_str_safe(fd
, itr
->value
, itr
->len
);
888 write_str_safe(fd
, "\n", 1);
891 for (ch
= node
->first
; ch
<= node
->last
; ch
++) {
892 struct index_mm_node
*child
= index_mm_readchild(node
, ch
);
897 buf_pushchar(buf
, ch
);
898 index_mm_dump_node(child
, buf
, fd
);
902 buf_popchars(buf
, pushed
);
903 index_mm_free_node(node
);
906 void index_mm_dump(struct index_mm
*idx
, int fd
, const char *prefix
)
908 struct index_mm_node
*root
;
911 root
= index_mm_readroot(idx
);
916 buf_pushchars(&buf
, prefix
);
917 index_mm_dump_node(root
, &buf
, fd
);
921 static char *index_mm_search_node(struct index_mm_node
*node
, const char *key
,
925 struct index_mm_node
*child
;
930 for (j
= 0; node
->prefix
[j
]; j
++) {
931 ch
= node
->prefix
[j
];
933 if (ch
!= key
[i
+j
]) {
934 index_mm_free_node(node
);
941 if (key
[i
] == '\0') {
942 value
= node
->values
.len
> 0
943 ? strdup(node
->values
.values
[0].value
)
946 index_mm_free_node(node
);
950 child
= index_mm_readchild(node
, key
[i
]);
951 index_mm_free_node(node
);
960 * Search the index for a key
962 * Returns the value of the first match
964 * The recursive functions free their node argument (using index_close).
966 char *index_mm_search(struct index_mm
*idx
, const char *key
)
968 // FIXME: return value by reference instead of strdup
969 struct index_mm_node
*root
;
972 root
= index_mm_readroot(idx
);
973 value
= index_mm_search_node(root
, key
, 0);
978 /* Level 4: add all the values from a matching node */
979 static void index_mm_searchwild_allvalues(struct index_mm_node
*node
,
980 struct index_value
**out
)
982 struct index_mm_value
*itr
, *itr_end
;
984 itr
= node
->values
.values
;
985 itr_end
= itr
+ node
->values
.len
;
986 for (; itr
< itr_end
; itr
++)
987 add_value(out
, itr
->value
, itr
->len
, itr
->priority
);
989 index_mm_free_node(node
);
993 * Level 3: traverse a sub-keyspace which starts with a wildcard,
994 * looking for matches.
996 static void index_mm_searchwild_all(struct index_mm_node
*node
, int j
,
999 struct index_value
**out
)
1004 while (node
->prefix
[j
]) {
1005 ch
= node
->prefix
[j
];
1007 buf_pushchar(buf
, ch
);
1012 for (ch
= node
->first
; ch
<= node
->last
; ch
++) {
1013 struct index_mm_node
*child
= index_mm_readchild(node
, ch
);
1018 buf_pushchar(buf
, ch
);
1019 index_mm_searchwild_all(child
, 0, buf
, subkey
, out
);
1023 if (node
->values
.len
> 0) {
1024 if (fnmatch(buf_str(buf
), subkey
, 0) == 0)
1025 index_mm_searchwild_allvalues(node
, out
);
1027 index_mm_free_node(node
);
1029 index_mm_free_node(node
);
1032 buf_popchars(buf
, pushed
);
1035 /* Level 2: descend the tree (until we hit a wildcard) */
1036 static void index_mm_searchwild_node(struct index_mm_node
*node
,
1038 const char *key
, int i
,
1039 struct index_value
**out
)
1041 struct index_mm_node
*child
;
1046 for (j
= 0; node
->prefix
[j
]; j
++) {
1047 ch
= node
->prefix
[j
];
1049 if (ch
== '*' || ch
== '?' || ch
== '[') {
1050 index_mm_searchwild_all(node
, j
, buf
,
1055 if (ch
!= key
[i
+j
]) {
1056 index_mm_free_node(node
);
1063 child
= index_mm_readchild(node
, '*');
1065 buf_pushchar(buf
, '*');
1066 index_mm_searchwild_all(child
, 0, buf
, &key
[i
], out
);
1070 child
= index_mm_readchild(node
, '?');
1072 buf_pushchar(buf
, '?');
1073 index_mm_searchwild_all(child
, 0, buf
, &key
[i
], out
);
1077 child
= index_mm_readchild(node
, '[');
1079 buf_pushchar(buf
, '[');
1080 index_mm_searchwild_all(child
, 0, buf
, &key
[i
], out
);
1084 if (key
[i
] == '\0') {
1085 index_mm_searchwild_allvalues(node
, out
);
1090 child
= index_mm_readchild(node
, key
[i
]);
1091 index_mm_free_node(node
);
1098 * Search the index for a key. The index may contain wildcards.
1100 * Returns a list of all the values of matching keys.
1102 struct index_value
*index_mm_searchwild(struct index_mm
*idx
, const char *key
)
1104 struct index_mm_node
*root
= index_mm_readroot(idx
);
1106 struct index_value
*out
= NULL
;
1109 index_mm_searchwild_node(root
, &buf
, key
, 0, &out
);