diff options
author | Colin Cross <ccross@android.com> | 2012-04-24 23:07:49 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2012-07-09 22:09:37 -0700 |
commit | b55dceea986ab24f8b836b5116b389ed619c816e (patch) | |
tree | aa4f4ed6384931ec362c70eca7b25a7cb8dab450 /libsparse/sparse.c | |
parent | 411619e921904b896eddae81c086c1f687c8304d (diff) | |
download | system_core-b55dceea986ab24f8b836b5116b389ed619c816e.tar.gz system_core-b55dceea986ab24f8b836b5116b389ed619c816e.tar.bz2 system_core-b55dceea986ab24f8b836b5116b389ed619c816e.zip |
libsparse: cleanups
Move block loops into sparse.c with iterator helpers in backed_block.c.
Simplify chunk writing by moving skip chunk calls from output_file.c to
sparse.c.
Rename variables to be consistent with new naming.
Remove use of u8, u32, u64.
Change-Id: Ic138ad58bef9f96239266ccee12ee83ea285e7eb
Diffstat (limited to 'libsparse/sparse.c')
-rw-r--r-- | libsparse/sparse.c | 137 |
1 files changed, 59 insertions, 78 deletions
diff --git a/libsparse/sparse.c b/libsparse/sparse.c index a6134c9d2..fce9dbbb6 100644 --- a/libsparse/sparse.c +++ b/libsparse/sparse.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include <assert.h> #include <stdlib.h> #include <sparse/sparse.h> @@ -24,7 +25,6 @@ #include "backed_block.h" #include "sparse_defs.h" - struct sparse_file *sparse_file_new(unsigned int block_size, int64_t len) { struct sparse_file *s = calloc(sizeof(struct sparse_file), 1); @@ -53,108 +53,89 @@ void sparse_file_destroy(struct sparse_file *s) int sparse_file_add_data(struct sparse_file *s, void *data, unsigned int len, unsigned int block) { - queue_data_block(s->backed_block_list, data, len, block); - - return 0; + return backed_block_add_data(s->backed_block_list, data, len, block); } int sparse_file_add_fill(struct sparse_file *s, uint32_t fill_val, unsigned int len, unsigned int block) { - queue_fill_block(s->backed_block_list, fill_val, len, block); - - return 0; + return backed_block_add_fill(s->backed_block_list, fill_val, len, block); } int sparse_file_add_file(struct sparse_file *s, const char *filename, int64_t file_offset, unsigned int len, unsigned int block) { - queue_data_file(s->backed_block_list, filename, file_offset, len, block); - - return 0; -} - -struct count_chunks { - unsigned int chunks; - int64_t cur_ptr; - unsigned int block_size; -}; - -static void count_data_block(void *priv, int64_t off, void *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, count_chunks->block_size); - count_chunks->chunks++; -} - -static void count_fill_block(void *priv, int64_t off, unsigned int fill_val, int len) -{ - struct count_chunks *count_chunks = priv; - if (off > count_chunks->cur_ptr) - count_chunks->chunks++; - count_chunks->cur_ptr = off + ALIGN(len, count_chunks->block_size); - count_chunks->chunks++; -} - -static void count_file_block(void *priv, int64_t off, const char *file, - int64_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, count_chunks->block_size); - count_chunks->chunks++; + return backed_block_add_file(s->backed_block_list, filename, file_offset, + len, block); } -static int count_sparse_chunks(struct backed_block_list *b, - unsigned int block_size, int64_t len) +unsigned int sparse_count_chunks(struct sparse_file *s) { - struct count_chunks count_chunks = {0, 0, block_size}; - - for_each_data_block(b, count_data_block, count_file_block, - count_fill_block, &count_chunks, block_size); - - if (count_chunks.cur_ptr != len) - count_chunks.chunks++; - - return count_chunks.chunks; -} - -static void ext4_write_data_block(void *priv, int64_t off, void *data, int len) -{ - write_data_block(priv, off, data, len); -} - -static void ext4_write_fill_block(void *priv, int64_t off, unsigned int fill_val, int len) -{ - write_fill_block(priv, off, fill_val, len); -} + struct backed_block *bb; + unsigned int last_block = 0; + unsigned int chunks = 0; + + for (bb = backed_block_iter_new(s->backed_block_list); bb; + bb = backed_block_iter_next(bb)) { + if (backed_block_block(bb) > last_block) { + /* If there is a gap between chunks, add a skip chunk */ + chunks++; + } + chunks++; + last_block = backed_block_block(bb) + + DIV_ROUND_UP(backed_block_len(bb), s->block_size); + } + if (last_block < DIV_ROUND_UP(s->len, s->block_size)) { + chunks++; + } -static void ext4_write_data_file(void *priv, int64_t off, const char *file, - int64_t offset, int len) -{ - write_data_file(priv, off, file, offset, len); + return chunks; } int sparse_file_write(struct sparse_file *s, int fd, bool gz, bool sparse, bool crc) { - int chunks = count_sparse_chunks(s->backed_block_list, s->block_size, - s->len); - struct output_file *out = open_output_fd(fd, s->block_size, s->len, - gz, sparse, chunks, crc); + struct backed_block *bb; + unsigned int last_block = 0; + int64_t pad; + int chunks; + struct output_file *out; + + chunks = sparse_count_chunks(s); + out = open_output_fd(fd, s->block_size, s->len, gz, sparse, chunks, crc); if (!out) return -ENOMEM; - for_each_data_block(s->backed_block_list, ext4_write_data_block, - ext4_write_data_file, ext4_write_fill_block, out, s->block_size); + for (bb = backed_block_iter_new(s->backed_block_list); bb; + bb = backed_block_iter_next(bb)) { + if (backed_block_block(bb) > last_block) { + unsigned int blocks = backed_block_block(bb) - last_block; + write_skip_chunk(out, (int64_t)blocks * s->block_size); + } + switch (backed_block_type(bb)) { + case BACKED_BLOCK_DATA: + write_data_chunk(out, backed_block_len(bb), backed_block_data(bb)); + break; + case BACKED_BLOCK_FILE: + write_file_chunk(out, backed_block_len(bb), + backed_block_filename(bb), backed_block_file_offset(bb)); + break; + case BACKED_BLOCK_FILL: + write_fill_chunk(out, backed_block_len(bb), + backed_block_fill_val(bb)); + break; + } + last_block = backed_block_block(bb) + + DIV_ROUND_UP(backed_block_len(bb), s->block_size); + } - if (s->len) - pad_output_file(out, s->len); + pad = s->len - last_block * s->block_size; + assert(pad >= 0); + if (pad > 0) { + write_skip_chunk(out, pad); + } close_output_file(out); |