commit:b8fe46e27d53b5a03b5d27b59bae40a6445e9b8d
author:Chip Black
committer:Chip Black
date:Wed Jul 2 21:36:46 2014 -0500
parents:7361ed553c5ed2943ab0f84e33e4ee536b6296a0
Fix a lot of dumb bugs in stringbucket
diff --git a/common/stringbucket.c b/common/stringbucket.c
line changes: +77/-15
index 7fd0bfa..86efff3
--- 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;