memcpy(dest, src, sizeof(struct struct_ext2_filsys));
dest->inode_map = NULL;
dest->block_map = NULL;
+ dest->badblocks = NULL;
if (dest->dblist)
dest->dblist->fs = dest;
if (src->block_map) {
}
if (src->badblocks) {
- retval = ext2fs_badblocks_copy(src->badblocks, &dest->badblocks);
+ retval = ext2fs_badblocks_copy(src->badblocks,
+ &dest->badblocks);
if (retval)
return retval;
}
io_channel dest_image_io;
ext2fs_inode_bitmap inode_map;
ext2fs_block_bitmap block_map;
+ ext2_badblocks_list badblocks;
dest_io = dest->io;
dest_image_io = dest->image_io;
inode_map = dest->inode_map;
block_map = dest->block_map;
+ badblocks = dest->badblocks;
memcpy(dest, src, sizeof(struct struct_ext2_filsys));
dest->io = dest_io;
dest->icache = icache;
dest->inode_map = inode_map;
dest->block_map = block_map;
+ dest->badblocks = badblocks;
if (dest->dblist)
dest->dblist->fs = dest;
goto out;
if (src->badblocks) {
- retval = ext2fs_badblocks_copy(src->badblocks, &dest->badblocks);
-
- ext2fs_badblocks_list_free(src->badblocks);
- src->badblocks = NULL;
+ if (dest->badblocks == NULL)
+ retval = ext2fs_badblocks_copy(src->badblocks,
+ &dest->badblocks);
+ else
+ retval = ext2fs_badblocks_merge(src->badblocks,
+ dest->badblocks);
}
out:
io_channel_close(src->io);
ext2fs_free_generic_bmap(src->inode_map);
if (src->block_map)
ext2fs_free_generic_bmap(src->block_map);
+ if (src->badblocks)
+ ext2fs_badblocks_list_free(src->badblocks);
return retval;
}
#include "config.h"
#include <stdio.h>
+#include <assert.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
return 0;
}
+static inline int insert_ok(blk_t *array, int cnt, blk_t new)
+{
+ return (cnt == 0 || array[cnt - 1] != new);
+}
+
+/*
+ * Merge list from src to dest
+ */
+static errcode_t merge_u32_list(ext2_u32_list src, ext2_u32_list dest)
+{
+ errcode_t retval;
+ int src_count = src->num;
+ int dest_count = dest->num;
+ int size = src_count + dest_count;
+ int size_entry = sizeof(blk_t);
+ blk_t *array;
+ blk_t *src_array = src->list;
+ blk_t *dest_array = dest->list;
+ int src_index = 0;
+ int dest_index = 0;
+ int uniq_cnt = 0;
+
+ if (src->num == 0)
+ return 0;
+
+ retval = ext2fs_get_array(size, size_entry, &array);
+ if (retval)
+ return retval;
+
+ /*
+ * It is possible that src list and dest list could be
+ * duplicated when merging badblocks.
+ */
+ while (src_index < src_count || dest_index < dest_count) {
+ if (src_index >= src_count) {
+ for (; dest_index < dest_count; dest_index++)
+ if (insert_ok(array, uniq_cnt, dest_array[dest_index]))
+ array[uniq_cnt++] = dest_array[dest_index];
+ break;
+ }
+ if (dest_index >= dest_count) {
+ for (; src_index < src_count; src_index++)
+ if (insert_ok(array, uniq_cnt, src_array[src_index]))
+ array[uniq_cnt++] = src_array[src_index];
+ break;
+ }
+ if (src_array[src_index] < dest_array[dest_index]) {
+ if (insert_ok(array, uniq_cnt, src_array[src_index]))
+ array[uniq_cnt++] = src_array[src_index];
+ src_index++;
+ } else if (src_array[src_index] > dest_array[dest_index]) {
+ if (insert_ok(array, uniq_cnt, dest_array[dest_index]))
+ array[uniq_cnt++] = dest_array[dest_index];
+ dest_index++;
+ } else {
+ if (insert_ok(array, uniq_cnt, dest_array[dest_index]))
+ array[uniq_cnt++] = dest_array[dest_index];
+ src_index++;
+ dest_index++;
+ }
+ }
+
+ ext2fs_free_mem(&dest->list);
+ dest->list = array;
+ dest->num = uniq_cnt;
+ dest->size = size;
+ return 0;
+}
+
/*
* This procedure creates an empty u32 list.
*/
errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest)
{
- errcode_t retval;
-
- retval = make_u32_list(src->size, src->num, src->list, dest);
- if (retval)
- return retval;
- (*dest)->badblocks_flags = src->badblocks_flags;
- return 0;
+ return make_u32_list(src->size, src->num, src->list, dest);
}
errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
(ext2_u32_list *) dest);
}
+errcode_t ext2fs_badblocks_merge(ext2_badblocks_list src,
+ ext2_badblocks_list dest)
+{
+ return merge_u32_list((ext2_u32_list) src,
+ (ext2_u32_list) dest);
+}
+
/*
* This procedure frees a badblocks list.
*