summaryrefslogtreecommitdiffstats
path: root/libsparse
diff options
context:
space:
mode:
authorJeremy Compostella <jeremy.compostella@intel.com>2015-02-22 10:47:16 +0100
committerJeremy Compostella <jeremy.compostella@intel.com>2015-03-01 11:54:02 +0100
commit9f0d6bdd6691cbe78a3c03e531cb69ec2cc63602 (patch)
treec58308d6e62627730a875067b7e343c28a409d99 /libsparse
parentbe9712156bdcf8cff774a78a3afdb0c562998c73 (diff)
downloadcore-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.c39
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;