/*
* libkmod - interface to kernel module operations
*
- * Copyright (C) 2011 ProFUSION embedded systems
+ * Copyright (C) 2011-2012 ProFUSION embedded systems
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
return true;
}
+static unsigned buf_pushchars(struct buffer *buf, const char *str)
+{
+ unsigned i = 0;
+ int ch;
+
+ while ((ch = str[i])) {
+ buf_pushchar(buf, ch);
+ i++;
+ }
+
+ return i;
+}
+
static unsigned buf_freadchars(struct buffer *buf, FILE *in)
{
unsigned i = 0;
uint32_t magic, version;
struct index_file *new;
- file = fopen(filename, "r");
+ file = fopen(filename, "re");
if (!file)
return NULL;
errno = EINVAL;
magic = read_long(file);
- if (magic != INDEX_MAGIC)
+ if (magic != INDEX_MAGIC) {
+ fclose(file);
return NULL;
+ }
version = read_long(file);
- if (version >> 16 != INDEX_VERSION_MAJOR)
+ if (version >> 16 != INDEX_VERSION_MAJOR) {
+ fclose(file);
return NULL;
+ }
new = NOFAIL(malloc(sizeof(struct index_file)));
new->file = file;
return NULL;
}
+static void index_dump_node(struct index_node_f *node, struct buffer *buf,
+ int fd)
+{
+ struct index_value *v;
+ int ch, pushed;
+
+ pushed = buf_pushchars(buf, node->prefix);
+
+ for (v = node->values; v != NULL; v = v->next) {
+ write_str_safe(fd, buf->bytes, buf->used);
+ write_str_safe(fd, " ", 1);
+ write_str_safe(fd, v->value, strlen(v->value));
+ write_str_safe(fd, "\n", 1);
+ }
+
+ for (ch = node->first; ch <= node->last; ch++) {
+ struct index_node_f *child = index_readchild(node, ch);
+
+ if (!child)
+ continue;
+
+ buf_pushchar(buf, ch);
+ index_dump_node(child, buf, fd);
+ buf_popchar(buf);
+ }
+
+ buf_popchars(buf, pushed);
+ index_close(node);
+}
+
+void index_dump(struct index_file *in, int fd, const char *prefix)
+{
+ struct index_node_f *root;
+ struct buffer buf;
+
+ buf_init(&buf);
+ buf_pushchars(&buf, prefix);
+ root = index_readroot(in);
+ index_dump_node(root, &buf, fd);
+ buf_release(&buf);
+}
+
static char *index_search__node(struct index_node_f *node, const char *key, int i)
{
char *value;
child_count = 0;
}
- children_padding = (offsetof(struct index_mm_node, children) +
+ children_padding = (sizeof(struct index_mm_node) +
(sizeof(uint32_t) * child_count)) % sizeof(void *);
if (offset & INDEX_NODE_VALUES)
}
struct index_mm *index_mm_open(struct kmod_ctx *ctx, const char *filename,
- bool populate)
+ bool populate, unsigned long long *stamp)
{
int fd;
int flags;
DBG(ctx, "file=%s\n", filename);
- if ((fd = open(filename, O_RDONLY)) < 0) {
- ERR(ctx, "%m\n");
+ idx = malloc(sizeof(*idx));
+ if (idx == NULL) {
+ ERR(ctx, "malloc: %m\n");
return NULL;
}
- fstat(fd, &st);
-
- idx = malloc(sizeof(*idx));
- if (idx == NULL) {
- ERR(ctx, "%m\n");
- goto fail;
+ if ((fd = open(filename, O_RDONLY|O_CLOEXEC)) < 0) {
+ ERR(ctx, "open(%s, O_RDONLY|O_CLOEXEC): %m\n", filename);
+ goto fail_open;
}
+ fstat(fd, &st);
flags = MAP_PRIVATE;
if (populate)
flags |= MAP_POPULATE;
if ((idx->mm = mmap(0, st.st_size, PROT_READ, flags, fd, 0))
== MAP_FAILED) {
- ERR(ctx, "%m\n");
+ ERR(ctx, "mmap(0, %zd, PROT_READ, %d, %d, 0): %m\n",
+ (size_t)st.st_size, flags, fd);
goto fail;
}
idx->ctx = ctx;
close(fd);
+ *stamp = stat_mstamp(&st);
+
return idx;
fail:
close(fd);
- if (idx->mm)
+ if (idx->mm != MAP_FAILED)
munmap(idx->mm, st.st_size);
+fail_open:
free(idx);
return NULL;
}
return NULL;
}
+static void index_mm_dump_node(struct index_mm_node *node, struct buffer *buf,
+ int fd)
+{
+ struct index_mm_value *itr, *itr_end;
+ int ch, pushed;
+
+ pushed = buf_pushchars(buf, node->prefix);
+
+ itr = node->values.values;
+ itr_end = itr + node->values.len;
+ for (; itr < itr_end; itr++) {
+ write_str_safe(fd, buf->bytes, buf->used);
+ write_str_safe(fd, " ", 1);
+ write_str_safe(fd, itr->value, itr->len);
+ write_str_safe(fd, "\n", 1);
+ }
+
+ for (ch = node->first; ch <= node->last; ch++) {
+ struct index_mm_node *child = index_mm_readchild(node, ch);
+
+ if (child == NULL)
+ continue;
+
+ buf_pushchar(buf, ch);
+ index_mm_dump_node(child, buf, fd);
+ buf_popchar(buf);
+ }
+
+ buf_popchars(buf, pushed);
+ index_mm_free_node(node);
+}
+
+void index_mm_dump(struct index_mm *idx, int fd, const char *prefix)
+{
+ struct index_mm_node *root;
+ struct buffer buf;
+
+ buf_init(&buf);
+ buf_pushchars(&buf, prefix);
+ root = index_mm_readroot(idx);
+ index_mm_dump_node(root, &buf, fd);
+ buf_release(&buf);
+}
+
static char *index_mm_search_node(struct index_mm_node *node, const char *key,
int i)
{