summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/rib.c67
-rw-r--r--src/lib/tests/rib_test.c24
2 files changed, 91 insertions, 0 deletions
diff --git a/src/lib/rib.c b/src/lib/rib.c
index 4d1ae884..6b27ad27 100644
--- a/src/lib/rib.c
+++ b/src/lib/rib.c
@@ -95,6 +95,7 @@ struct rnode {
struct rnode * parent;
+ size_t chlen;
struct list_head children;
struct list_head subs;
@@ -248,6 +249,8 @@ static int rnode_add_child(struct rnode * node,
c->node = child;
list_add(&c->next, &node->children);
+ ++node->chlen;
+
return 0;
}
@@ -265,6 +268,7 @@ static void rnode_remove_child(struct rnode * node,
if (c->node == child) {
list_del(&c->next);
free(c);
+ --node->chlen;
return;
}
}
@@ -321,6 +325,8 @@ static struct rnode * rnode_create(struct rnode * parent,
node->parent = parent;
+ node->chlen = 0;
+
branch_hash(node);
rnode_throw_event(node, RO_CREATE);
@@ -606,6 +612,13 @@ ssize_t rib_read(const char * path,
return -EFBIG;
}
+ if (node->data == NULL) {
+ pthread_rwlock_unlock(&rib.lock);
+ return 0;
+ }
+
+ assert(node->len > 0);
+
memcpy(data, node->data, node->len);
rlen = node->len;
@@ -681,6 +694,60 @@ bool rib_has(const char * path)
return node != NULL;
}
+ssize_t rib_children(const char * path,
+ char *** children)
+{
+ struct list_head * p;
+
+ struct rnode * node;
+
+ ssize_t i = 0;
+
+ assert(path);
+ assert(children);
+
+ pthread_rwlock_rdlock(&rib.lock);
+
+ node = find_rnode_by_path(path);
+ if (node == NULL) {
+ pthread_rwlock_unlock(&rib.lock);
+ return -EPERM;
+ }
+
+ if (node->chlen == 0) {
+ pthread_rwlock_unlock(&rib.lock);
+ *children = NULL;
+ return 0;
+ }
+
+ *children = malloc(sizeof(**children) * node->chlen);
+ if (*children == NULL) {
+ pthread_rwlock_unlock(&rib.lock);
+ return -ENOMEM;
+ }
+
+ list_for_each(p, &node->children) {
+ struct child * c = list_entry(p, struct child, next);
+ (*children)[i] = strdup(c->node->name);
+ if ((*children)[i] == NULL) {
+ ssize_t j;
+ pthread_rwlock_unlock(&rib.lock);
+ for (j = 0; j < i; ++j)
+ free((*children)[j]);
+ free(*children);
+ return -ENOMEM;
+ }
+ ++i;
+ }
+
+ assert(i > 0);
+ assert((size_t) i == node->chlen);
+
+ pthread_rwlock_unlock(&rib.lock);
+
+ return i;
+}
+
static struct rib_sub * rib_get_sub(uint32_t sid)
{
struct list_head * p;
diff --git a/src/lib/tests/rib_test.c b/src/lib/tests/rib_test.c
index 37503941..bad01083 100644
--- a/src/lib/tests/rib_test.c
+++ b/src/lib/tests/rib_test.c
@@ -46,6 +46,9 @@ int rib_test(int argc,
char tmp[RIB_MAX_PATH_LEN];
+ char ** kids;
+ ssize_t ch;
+
struct timespec t = {0, 100 * BILLION};
(void) argc;
@@ -73,6 +76,16 @@ int rib_test(int argc,
return -1;
}
+ ch = rib_children("/static_info", &kids);
+ if (ch != 0) {
+ printf("Wrong number of children returned.\n");
+ rib_fini();
+ while (ch > 0)
+ free(kids[--ch]);
+ free(kids);
+ return -1;
+ }
+
if (!rib_has("/static_info")) {
printf("Failed to find added element.\n");
rib_fini();
@@ -118,6 +131,17 @@ int rib_test(int argc,
return -1;
}
+ ch = rib_children("/static_info", &kids);
+ if (ch != 2) {
+ printf("Wrong number of children returned.\n");
+ rib_fini();
+ return -1;
+ }
+
+ while (ch > 0)
+ free(kids[--ch]);
+ free(kids);
+
if (addr_chk != addr_size) {
printf("Failed to verify added element contents.\n");
rib_fini();