changeset 9280:8e7809057f85 HEAD

settings_dup(): Copy only the settings, leave the rest of the struct zeroed out.
author Timo Sirainen <tss@iki.fi>
date Thu, 14 May 2009 18:51:17 -0400
parents 2da7dec937d4
children 11e974e40f7b
files src/lib-settings/settings-parser.c
diffstat 1 files changed, 28 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-settings/settings-parser.c	Thu May 14 17:20:51 2009 -0400
+++ b/src/lib-settings/settings-parser.c	Thu May 14 18:51:17 2009 -0400
@@ -847,6 +847,18 @@
 	return FALSE;
 }
 
+static void settings_set_parent(const struct setting_parser_info *info,
+				void *child, void *parent)
+{
+	void **ptr;
+
+	if (info->parent_offset == (size_t)-1)
+		return;
+
+	ptr = PTR_OFFSET(child, info->parent_offset);
+	*ptr = parent;
+}
+
 void *settings_dup(const struct setting_parser_info *info,
 		   const void *set, pool_t pool)
 {
@@ -855,17 +867,27 @@
 	void *dest_set, *dest, *const *children;
 	unsigned int i, count;
 
+	/* don't just copy everything from set to dest_set. it may contain
+	   some non-setting fields allocated from the original pool. */
 	dest_set = p_malloc(pool, info->struct_size);
-	memcpy(dest_set, set, info->struct_size);
 	for (def = info->defines; def->key != NULL; def++) {
 		src = CONST_PTR_OFFSET(set, def->offset);
 		dest = PTR_OFFSET(dest_set, def->offset);
 
 		switch (def->type) {
-		case SET_INTERNAL:
-		case SET_BOOL:
-		case SET_UINT:
+		case SET_BOOL: {
+			const bool *src_bool = src;
+			bool *dest_bool = dest;
+
+			*dest_bool = *src_bool;
+		}
+		case SET_UINT: {
+			const unsigned int *src_uint = src;
+			unsigned int *dest_uint = dest;
+
+			*dest_uint = *src_uint;
 			break;
+		}
 		case SET_STR_VARS:
 		case SET_STR:
 		case SET_ENUM: {
@@ -889,6 +911,8 @@
 				child_set = settings_dup(def->list_info,
 							 children[i], pool);
 				array_append(dest_arr, &child_set, 1);
+				settings_set_parent(def->list_info, child_set,
+						    dest_set);
 			}
 			break;
 		}