From cfd3a03d3d147fca7a33d6f583b7047c5351fc32 Mon Sep 17 00:00:00 2001 From: Jeremy Compostella Date: Fri, 3 Apr 2015 14:31:19 +0200 Subject: libsparse: move_chunks_up_to_len() does not account skip chunks I caught the fastboot host command sending more data than the fastboot device can accept. Fastboot host command was sending 36 surplus bytes because of 3 skip chunks that were not taken into account in move_chunks_up_to_len() algorithm. Change-Id: I39a4a033c9b15893bd70e553f17116735ee4a48e --- libsparse/sparse.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'libsparse') diff --git a/libsparse/sparse.c b/libsparse/sparse.c index 65c09e0..311678a 100644 --- a/libsparse/sparse.c +++ b/libsparse/sparse.c @@ -238,14 +238,15 @@ static struct backed_block *move_chunks_up_to_len(struct sparse_file *from, struct backed_block *last_bb = NULL; struct backed_block *bb; struct backed_block *start; + unsigned int last_block = 0; int64_t file_len = 0; int ret; /* - * overhead is sparse file header, initial skip chunk, split chunk, end - * skip chunk, and crc chunk. + * overhead is sparse file header, the potential end skip + * chunk and crc chunk. */ - int overhead = sizeof(sparse_header_t) + 4 * sizeof(chunk_header_t) + + int overhead = sizeof(sparse_header_t) + 2 * sizeof(chunk_header_t) + sizeof(uint32_t); len -= overhead; @@ -258,6 +259,11 @@ static struct backed_block *move_chunks_up_to_len(struct sparse_file *from, for (bb = start; bb; bb = backed_block_iter_next(bb)) { count = 0; + if (backed_block_block(bb) > last_block) + count += sizeof(chunk_header_t); + last_block = backed_block_block(bb) + + DIV_ROUND_UP(backed_block_len(bb), to->block_size); + /* will call out_counter_write to update count */ ret = sparse_file_write_block(out_counter, bb); if (ret) { @@ -270,6 +276,7 @@ static struct backed_block *move_chunks_up_to_len(struct sparse_file *from, * requested size, split the chunk. Results in sparse files that * are at least 7/8ths of the requested size */ + file_len += sizeof(chunk_header_t); if (!last_bb || (len - file_len > (len / 8))) { backed_block_split(from->backed_block_list, bb, len - file_len); last_bb = bb; -- cgit v1.1