From b8fe46e27d53b5a03b5d27b59bae40a6445e9b8d Mon Sep 17 00:00:00 2001 From: Chip Black Date: Wed, 2 Jul 2014 21:36:46 -0500 Subject: [PATCH] Fix a lot of dumb bugs in stringbucket --- common/stringbucket.c | 92 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 15 deletions(-) diff --git a/common/stringbucket.c b/common/stringbucket.c index 7fd0bfa..86efff3 100644 --- a/common/stringbucket.c +++ b/common/stringbucket.c @@ -25,38 +25,76 @@ const char * strnchr(const char *s, int c, int n) { return NULL; } -struct stringbucket * stringbucket_open(const char *filename) { +int stringbucket_remap(struct stringbucket *sb) { struct stat st; + + if (sb->list != NULL) { + munmap(sb->list, sb->size); + } + + flock(sb->fd, LOCK_SH); + fstat(sb->fd, &st); + flock(sb->fd, LOCK_UN); + sb->size = st.st_size; + if (sb->size > 0) { + sb->list = mmap(NULL, sb->size, PROT_READ | PROT_WRITE, MAP_SHARED, sb->fd, 0); + if (sb->list == MAP_FAILED) { + perror("stringbucket mmap"); + return 0; + } + } else { + /* Don't map anything for now. */ + sb->list = NULL; + } + + return 1; +} + +struct stringbucket * stringbucket_open(const char *filename) { struct stringbucket *obj = malloc(sizeof(struct stringbucket)); + obj->list = NULL; + obj->size = 0; if (obj == NULL) { perror("stringbucket allocate"); - return NULL; + goto stringbucket_open__malloc_fail; } obj->fd = open(filename, O_RDWR | O_APPEND | O_CREAT, 0600); - flock(obj->fd, LOCK_SH); - fstat(obj->fd, &st); - flock(obj->fd, LOCK_UN); - obj->size = st.st_size; - obj->list = mmap(NULL, obj->size, PROT_READ | PROT_WRITE, MAP_SHARED, obj->fd, 0); - if (obj->list == MAP_FAILED) { - perror("stringbucket mmap"); - close(obj->fd); - free(obj); - return 0; + if (obj->fd == -1) { + perror("stringbucket open"); + goto stringbucket_open__open_fail; + } + + if (stringbucket_remap(obj) == 0) { + goto stringbucket_open__mmap_fail; } return obj; + +stringbucket_open__mmap_fail: + close(obj->fd); +stringbucket_open__open_fail: + free(obj); +stringbucket_open__malloc_fail: + return NULL; } void stringbucket_close(struct stringbucket *sb) { - munmap(sb->list, sb->size); + if (sb == NULL) + return; + + if (sb->list != NULL) + munmap(sb->list, sb->size); + close(sb->fd); free(sb); } int stringbucket_find(struct stringbucket *sb, const char *string) { + if (sb->list == NULL) + return -1; + char * end = sb->list + sb->size; int string_len = strlen(string); @@ -79,11 +117,32 @@ int stringbucket_find(struct stringbucket *sb, const char *string) { int stringbucket_add(struct stringbucket *sb, const char *string) { if (stringbucket_find(sb, string) != -1) return 0; + int str_len = strlen(string); + int len; + flock(sb->fd, LOCK_EX); - write(sb->fd, string, strlen(string)); - write(sb->fd, "\n", 1); + len = write(sb->fd, string, str_len); + if (len < 0) + perror("stringbucket add"); + if (len < str_len) + goto stringbucket_add__fail; + len = write(sb->fd, "\n", 1); + if (len < 0) + perror("stringbucket add"); + if (len == 0) + goto stringbucket_add__fail; flock(sb->fd, LOCK_UN); + + /* remap the data to include added content */ + if (stringbucket_remap(sb) == 0) + return 0; + return 1; + +stringbucket_add__fail: + ftruncate(sb->fd, sb->size); + flock(sb->fd, LOCK_UN); + return 0; } int stringbucket_delete(struct stringbucket *sb, const char *string) { @@ -96,6 +155,9 @@ int stringbucket_delete(struct stringbucket *sb, const char *string) { } void stringbucket_iterate(struct stringbucket *sb, void (*iter)(char *, void *), void *stuff) { + if (sb->list == NULL) + return; + char string[STRINGBUCKET_STRINGSIZE + 1]; char * ptr = sb->list; char * end = sb->list + sb->size; -- 2.25.1