diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/rib.c | 67 | ||||
-rw-r--r-- | src/lib/tests/rib_test.c | 24 |
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(); |