diff --git a/src/common/rbtree.c b/src/common/rbtree.c index 54697ba..bc45b3e 100644 --- a/src/common/rbtree.c +++ b/src/common/rbtree.c @@ -11,23 +11,20 @@ * http://www.eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx */ -#include - +#include "xalloc.h" #include "debug.h" #include "rbtree.h" #define is_red(n) ((n) != NULL && (n)->color == RB_RED) #define swap(n,d,q) ((n)->child[(n)->child[d] == (q)]) -static rbnode* node_alloc(uint key, void *ptr) { +static rbnode* node_alloc(uint key, void *ptr, size_t len) { - rbnode *n = malloc(sizeof(rbnode)); - - if (n == NULL) - return NULL; + rbnode *n = xmalloc(sizeof(rbnode)); n->key = key; n->data = ptr; + n->len = len; n->color = RB_RED; n->child[0] = NULL; n->child[1] = NULL; @@ -46,14 +43,14 @@ static void node_dealloc(rbnode *n, void (*action)(rbnode *)) { if (action != NULL) { action(n); } else if (n->data != NULL) { - free(n->data); + xfree(n->data); n->data = NULL; } node_dealloc(n->child[0], action); node_dealloc(n->child[1], action); - free(n); + xfree(n); } /* @@ -185,7 +182,7 @@ void rbtree_free(rbtree *tree, void (*action)(rbnode *)) { * * the function now returns -1 in that situation // H Hautakoski */ -int rbtree_insert(rbtree *tree, uint key, void *data) { +int rbtree_insert(rbtree *tree, uint key, void *data, size_t len) { rbnode head = {0}; @@ -198,7 +195,7 @@ int rbtree_insert(rbtree *tree, uint key, void *data) { unsigned char dir = 0, dir2, last, inserted = 0; if (tree->root == NULL) { - tree->root = node_alloc(key, data); + tree->root = node_alloc(key, data, len); if (tree->root == NULL) return 0; goto done; @@ -212,7 +209,7 @@ int rbtree_insert(rbtree *tree, uint key, void *data) { for(;;) { if (q == NULL) { - p->child[dir] = q = node_alloc(key, data); + p->child[dir] = q = node_alloc(key, data, len); if (q == NULL) return 0; inserted = 1; @@ -325,18 +322,15 @@ void* rbtree_delete(rbtree *tree, uint key) { tree->root->color = RB_BLACK; /* remove if found */ - if (f != NULL) { - ret = q->data; - if (q == tree->root) { - tree->root = NULL; - } else { - if (f != q) { - f->key = q->key; - f->data = q->data; - } - swap(p, 1, q) = swap(q, 0, NULL); - } - free(q); + if (f) { + ret = f->data; + if (f != q) { + f->key = q->key; + f->data = xmemdup(q->data, q->len); + f->len = q->len; + } + swap(p, 1, q) = swap(q, 0, NULL); + xfree(q); } return ret; diff --git a/src/common/rbtree.h b/src/common/rbtree.h index 15f16a1..7771cd4 100644 --- a/src/common/rbtree.h +++ b/src/common/rbtree.h @@ -42,7 +42,7 @@ void rbtree_walk(rbtree *tree, void (*action)(rbnode *)); void rbtree_free(rbtree *tree, void (*action)(rbnode *)); -int rbtree_insert(rbtree *tree, uint key, void *data); +int rbtree_insert(rbtree *tree, uint key, void *data, size_t len); void* rbtree_delete(rbtree *tree, uint key); diff --git a/src/common/xalloc.c b/src/common/xalloc.c index 88531f9..c2302b8 100644 --- a/src/common/xalloc.c +++ b/src/common/xalloc.c @@ -75,6 +75,17 @@ bail: die_errno("xstrdup"); } +void* xmemdup(const void *src, size_t size) { + + CHECK_INPUT(src); + + void *dest = xmalloc(size); + memcpy(dest, src, size); + return dest; +bail: + die_errno("xmemdup"); +} + void xfree(void *ptr) { CHECK_INPUT(ptr); diff --git a/src/common/xalloc.h b/src/common/xalloc.h index f77b862..8e726a3 100644 --- a/src/common/xalloc.h +++ b/src/common/xalloc.h @@ -21,6 +21,8 @@ void* xrealloc(void *, size_t); char* xstrdup(const char *); +void* xmemdup(const void *, size_t); + void xfree(void *); #endif /* __COMMON_XALLOC_H */ diff --git a/src/notify/inotify.c b/src/notify/inotify.c index b9be358..f09da78 100644 --- a/src/notify/inotify.c +++ b/src/notify/inotify.c @@ -42,16 +42,17 @@ static queue_t event_queue; static int addwatch(const char *path, const char *name) { rbnode *node; - char *cpath; + char *npath; int wd; - cpath = path_normalize(path, name, 1); + npath = path_normalize(path, name, 1); - wd = inotify_add_watch(fd, cpath, WATCH_MASK); + wd = inotify_add_watch(fd, npath, WATCH_MASK); if (wd < 0) { perror("NOTIFY ADD"); - dprint("%i path %s\n", errno == EBADF, cpath); + dprint("%i path %s\n", errno == EBADF, npath); + free(npath); return -errno; } @@ -59,12 +60,13 @@ static int addwatch(const char *path, const char *name) { node = rbtree_search(&tree, wd); if (node == NULL) { - dprint("added wd = %i on %s\n", wd, cpath); - rbtree_insert(&tree, wd, (void*)cpath); + dprint("added wd = %i on %s\n", wd, npath); + rbtree_insert(&tree, wd, (void*)npath, strlen(npath)+1); } else { - dprint("updated wd = %i from %s to %s\n", wd, (char*)node->data, cpath); + dprint("updated wd = %i from %s to %s\n", wd, (char*)node->data, npath); free(node->data); - node->data = (void*) cpath; + node->data = (void*) npath; + node->len = strlen(npath)+1; } return wd; diff --git a/test/Makefile b/test/Makefile index 6d3eb84..1642a50 100644 --- a/test/Makefile +++ b/test/Makefile @@ -28,6 +28,7 @@ rbtree : $(CC) $(CFLAGS) \ unit.c \ ../src/common/die.c \ + ../src/common/xalloc.c \ ../src/common/rbtree.c \ t_rbtree.c -o test_rbtree diff --git a/test/t_rbtree.c b/test/t_rbtree.c index 5f146a3..d3ed31e 100644 --- a/test/t_rbtree.c +++ b/test/t_rbtree.c @@ -60,7 +60,8 @@ static int rb_assert(rbnode *node) { /* data */ static rbtree tree; -static uint keyref[NODES]; +static uint keyref[NODES]; +static char *dataref[NODES]; static uint search_key = -1; static char search_data[32]; @@ -79,7 +80,7 @@ void test_insert() { data = utest_ran_string(32); /* insert into rbtree and assert it */ - ret = rbtree_insert(&tree, ckey, data); + ret = rbtree_insert(&tree, ckey, data, 32); rb_assert(tree.root); dprint("INSERT: %i %s\n", ckey, data); @@ -89,6 +90,7 @@ void test_insert() { continue; keyref[i] = ckey; + dataref[i] = data; if (i == ((NODES/2))) { search_key = ckey; @@ -99,7 +101,7 @@ void test_insert() { } /* insert duplicate key */ - assert(rbtree_insert(&tree, search_key, "duplicate") == -1); + assert(rbtree_insert(&tree, search_key, "duplicate", 10) == -1); rb_assert(tree.root); } @@ -107,13 +109,16 @@ void test_delete() { int i; uint key; + char *data, *dref; /* remove some values */ for(i=0; i < 10; i++) { key = keyref[(NODES/2)+i]; + dref = dataref[(NODES/2)+i]; - rbtree_delete(&tree, key); + data = rbtree_delete(&tree, key); + assert_string(data, dref); rb_assert(tree.root); } }