diff options
author | Jeremy Compostella <jeremy.compostella@intel.com> | 2015-02-22 10:47:16 +0100 |
---|---|---|
committer | Jeremy Compostella <jeremy.compostella@intel.com> | 2015-03-01 11:54:02 +0100 |
commit | 9f0d6bdd6691cbe78a3c03e531cb69ec2cc63602 (patch) | |
tree | c58308d6e62627730a875067b7e343c28a409d99 /libsparse | |
parent | be9712156bdcf8cff774a78a3afdb0c562998c73 (diff) | |
download | core-9f0d6bdd6691cbe78a3c03e531cb69ec2cc63602.tar.gz core-9f0d6bdd6691cbe78a3c03e531cb69ec2cc63602.tar.bz2 core-9f0d6bdd6691cbe78a3c03e531cb69ec2cc63602.zip |
fastboot/sparse: propagate error code
sparse_file_write_block calls functions that might failed. This patch
makes sparse_file_write_block catch the error code and propagate it.
Without this patch, fastboot crashes on a segmentation fault if
usb_write() fail during a sparse file image flashing.
Change-Id: If9c0e8dfac8fa380628a2504e13abe8cf7d62726
Signed-off-by: Jeremy Compostella <jeremy.compostella@intel.com>
Diffstat (limited to 'libsparse')
-rw-r--r-- | libsparse/sparse.c | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/libsparse/sparse.c b/libsparse/sparse.c index baa30cdc1..65c09e0d4 100644 --- a/libsparse/sparse.c +++ b/libsparse/sparse.c @@ -101,26 +101,32 @@ unsigned int sparse_count_chunks(struct sparse_file *s) return chunks; } -static void sparse_file_write_block(struct output_file *out, +static int sparse_file_write_block(struct output_file *out, struct backed_block *bb) { + int ret = -EINVAL; + switch (backed_block_type(bb)) { case BACKED_BLOCK_DATA: - write_data_chunk(out, backed_block_len(bb), backed_block_data(bb)); + ret = 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)); + ret = write_file_chunk(out, backed_block_len(bb), + backed_block_filename(bb), + backed_block_file_offset(bb)); break; case BACKED_BLOCK_FD: - write_fd_chunk(out, backed_block_len(bb), - backed_block_fd(bb), backed_block_file_offset(bb)); + ret = write_fd_chunk(out, backed_block_len(bb), + backed_block_fd(bb), + backed_block_file_offset(bb)); break; case BACKED_BLOCK_FILL: - write_fill_chunk(out, backed_block_len(bb), - backed_block_fill_val(bb)); + ret = write_fill_chunk(out, backed_block_len(bb), + backed_block_fill_val(bb)); break; } + + return ret; } static int write_all_blocks(struct sparse_file *s, struct output_file *out) @@ -128,6 +134,7 @@ static int write_all_blocks(struct sparse_file *s, struct output_file *out) struct backed_block *bb; unsigned int last_block = 0; int64_t pad; + int ret = 0; for (bb = backed_block_iter_new(s->backed_block_list); bb; bb = backed_block_iter_next(bb)) { @@ -135,7 +142,9 @@ static int write_all_blocks(struct sparse_file *s, struct output_file *out) unsigned int blocks = backed_block_block(bb) - last_block; write_skip_chunk(out, (int64_t)blocks * s->block_size); } - sparse_file_write_block(out, bb); + ret = sparse_file_write_block(out, bb); + if (ret) + return ret; last_block = backed_block_block(bb) + DIV_ROUND_UP(backed_block_len(bb), s->block_size); } @@ -230,6 +239,7 @@ static struct backed_block *move_chunks_up_to_len(struct sparse_file *from, struct backed_block *bb; struct backed_block *start; int64_t file_len = 0; + int ret; /* * overhead is sparse file header, initial skip chunk, split chunk, end @@ -249,7 +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; /* will call out_counter_write to update count */ - sparse_file_write_block(out_counter, bb); + ret = sparse_file_write_block(out_counter, bb); + if (ret) { + bb = NULL; + goto out; + } if (file_len + count > len) { /* * If the remaining available size is more than 1/8th of the @@ -260,16 +274,17 @@ static struct backed_block *move_chunks_up_to_len(struct sparse_file *from, backed_block_split(from->backed_block_list, bb, len - file_len); last_bb = bb; } - goto out; + goto move; } file_len += count; last_bb = bb; } -out: +move: backed_block_list_move(from->backed_block_list, to->backed_block_list, start, last_bb); +out: output_file_close(out_counter); return bb; |