diff options
author | Colin Cross <ccross@android.com> | 2010-12-22 18:41:13 -0800 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2011-01-05 15:36:06 -0800 |
commit | b781330b1acae2e5706bbda8d81e5f7575f40e2a (patch) | |
tree | b9ac20e47a0e913563b61741e4c544680cbe3600 /ext4_utils/ext4_utils.c | |
parent | 33f96c66e9a1f2e266a75e5e84c091dffa6ef118 (diff) | |
download | extras-b781330b1acae2e5706bbda8d81e5f7575f40e2a.tar.gz |
ext4_utils: Get rid of CRC in sparse file header
Also removes the need to seek in the output file, allowing
stdin and stdout to be used for input and output.
Change-Id: I93cbe335d9cc83a6d21daa696af2cb54952dcc9f
Diffstat (limited to 'ext4_utils/ext4_utils.c')
-rw-r--r-- | ext4_utils/ext4_utils.c | 94 |
1 files changed, 69 insertions, 25 deletions
diff --git a/ext4_utils/ext4_utils.c b/ext4_utils/ext4_utils.c index 1551633f..9d8a9b0f 100644 --- a/ext4_utils/ext4_utils.c +++ b/ext4_utils/ext4_utils.c @@ -73,34 +73,63 @@ int ext4_bg_has_super_block(int bg) return 0; } +struct count_chunks { + u32 chunks; + u64 cur_ptr; +}; + +void count_data_block(void *priv, u64 off, u8 *data, int len) +{ + struct count_chunks *count_chunks = priv; + if (off > count_chunks->cur_ptr) + count_chunks->chunks++; + count_chunks->cur_ptr = off + ALIGN(len, info.block_size); + count_chunks->chunks++; +} + +void count_file_block(void *priv, u64 off, const char *file, + off64_t offset, int len) +{ + struct count_chunks *count_chunks = priv; + if (off > count_chunks->cur_ptr) + count_chunks->chunks++; + count_chunks->cur_ptr = off + ALIGN(len, info.block_size); + count_chunks->chunks++; +} + +int count_sparse_chunks() +{ + struct count_chunks count_chunks = {0, 0}; + + for_each_data_block(count_data_block, count_file_block, &count_chunks); + + if (count_chunks.cur_ptr != info.len) + count_chunks.chunks++; + + return count_chunks.chunks; +} + +static void ext4_write_data_block(void *priv, u64 off, u8 *data, int len) +{ + write_data_block(priv, off, data, len); +} +static void ext4_write_data_file(void *priv, u64 off, const char *file, + off64_t offset, int len) +{ + write_data_file(priv, off, file, offset, len); +} + /* Write the filesystem image to a file */ void write_ext4_image(const char *filename, int gz, int sparse) { int ret = 0; - struct output_file *out = open_output_file(filename, gz, sparse); + struct output_file *out = open_output_file(filename, gz, sparse, + count_sparse_chunks()); if (!out) return; - /* The write_data* functions expect only block aligned calls. - * This is not an issue, except when we write out the super - * block on a system with a block size > 1K. So, we need to - * deal with that here. - */ - if (info.block_size > 1024) { - u8 buf[4096] = { 0 }; /* The larget supported ext4 block size */ - memcpy(buf + 1024, (u8*)aux_info.sb, 1024); - write_data_block(out, 0, buf, info.block_size); - - } else { - write_data_block(out, 1024, (u8*)aux_info.sb, 1024); - } - - write_data_block(out, (u64)(aux_info.first_data_block + 1) * info.block_size, - (u8*)aux_info.bg_desc, - aux_info.bg_desc_blocks * info.block_size); - - for_each_data_block(write_data_block, write_data_file, out); + for_each_data_block(ext4_write_data_block, ext4_write_data_file, out); pad_output_file(out, info.len); @@ -233,12 +262,11 @@ void ext4_fill_in_sb() info.blocks_per_group; u32 header_size = 0; if (ext4_bg_has_super_block(i)) { - if (i != 0) { + if (i != 0) queue_data_block((u8 *)sb, info.block_size, group_start_block); - queue_data_block((u8 *)aux_info.bg_desc, - aux_info.bg_desc_blocks * info.block_size, - group_start_block + 1); - } + queue_data_block((u8 *)aux_info.bg_desc, + aux_info.bg_desc_blocks * info.block_size, + group_start_block + 1); header_size = 1 + aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks; } @@ -252,6 +280,22 @@ void ext4_fill_in_sb() } } +void ext4_queue_sb(void) +{ + /* The write_data* functions expect only block aligned calls. + * This is not an issue, except when we write out the super + * block on a system with a block size > 1K. So, we need to + * deal with that here. + */ + if (info.block_size > 1024) { + u8 *buf = calloc(info.block_size, 1); + memcpy(buf + 1024, (u8*)aux_info.sb, 1024); + queue_data_block(buf, info.block_size, 0); + } else { + queue_data_block((u8*)aux_info.sb, 1024, 1); + } +} + void ext4_create_resize_inode() { struct block_allocation *reserve_inode_alloc = create_allocation(); |