summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Compostella2015-02-22 03:47:16 -0600
committerJeremy Compostella2015-03-01 04:54:02 -0600
commit9f0d6bdd6691cbe78a3c03e531cb69ec2cc63602 (patch)
treec58308d6e62627730a875067b7e343c28a409d99 /libsparse
parentbe9712156bdcf8cff774a78a3afdb0c562998c73 (diff)
downloadplatform-system-core-9f0d6bdd6691cbe78a3c03e531cb69ec2cc63602.tar.gz
platform-system-core-9f0d6bdd6691cbe78a3c03e531cb69ec2cc63602.tar.xz
platform-system-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)
101 return chunks; 101 return chunks;
102} 102}
103 103
104static void sparse_file_write_block(struct output_file *out, 104static int sparse_file_write_block(struct output_file *out,
105 struct backed_block *bb) 105 struct backed_block *bb)
106{ 106{
107 int ret = -EINVAL;
108
107 switch (backed_block_type(bb)) { 109 switch (backed_block_type(bb)) {
108 case BACKED_BLOCK_DATA: 110 case BACKED_BLOCK_DATA:
109 write_data_chunk(out, backed_block_len(bb), backed_block_data(bb)); 111 ret = write_data_chunk(out, backed_block_len(bb), backed_block_data(bb));
110 break; 112 break;
111 case BACKED_BLOCK_FILE: 113 case BACKED_BLOCK_FILE:
112 write_file_chunk(out, backed_block_len(bb), 114 ret = write_file_chunk(out, backed_block_len(bb),
113 backed_block_filename(bb), backed_block_file_offset(bb)); 115 backed_block_filename(bb),
116 backed_block_file_offset(bb));
114 break; 117 break;
115 case BACKED_BLOCK_FD: 118 case BACKED_BLOCK_FD:
116 write_fd_chunk(out, backed_block_len(bb), 119 ret = write_fd_chunk(out, backed_block_len(bb),
117 backed_block_fd(bb), backed_block_file_offset(bb)); 120 backed_block_fd(bb),
121 backed_block_file_offset(bb));
118 break; 122 break;
119 case BACKED_BLOCK_FILL: 123 case BACKED_BLOCK_FILL:
120 write_fill_chunk(out, backed_block_len(bb), 124 ret = write_fill_chunk(out, backed_block_len(bb),
121 backed_block_fill_val(bb)); 125 backed_block_fill_val(bb));
122 break; 126 break;
123 } 127 }
128
129 return ret;
124} 130}
125 131
126static int write_all_blocks(struct sparse_file *s, struct output_file *out) 132static 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)
128 struct backed_block *bb; 134 struct backed_block *bb;
129 unsigned int last_block = 0; 135 unsigned int last_block = 0;
130 int64_t pad; 136 int64_t pad;
137 int ret = 0;
131 138
132 for (bb = backed_block_iter_new(s->backed_block_list); bb; 139 for (bb = backed_block_iter_new(s->backed_block_list); bb;
133 bb = backed_block_iter_next(bb)) { 140 bb = backed_block_iter_next(bb)) {
@@ -135,7 +142,9 @@ static int write_all_blocks(struct sparse_file *s, struct output_file *out)
135 unsigned int blocks = backed_block_block(bb) - last_block; 142 unsigned int blocks = backed_block_block(bb) - last_block;
136 write_skip_chunk(out, (int64_t)blocks * s->block_size); 143 write_skip_chunk(out, (int64_t)blocks * s->block_size);
137 } 144 }
138 sparse_file_write_block(out, bb); 145 ret = sparse_file_write_block(out, bb);
146 if (ret)
147 return ret;
139 last_block = backed_block_block(bb) + 148 last_block = backed_block_block(bb) +
140 DIV_ROUND_UP(backed_block_len(bb), s->block_size); 149 DIV_ROUND_UP(backed_block_len(bb), s->block_size);
141 } 150 }
@@ -230,6 +239,7 @@ static struct backed_block *move_chunks_up_to_len(struct sparse_file *from,
230 struct backed_block *bb; 239 struct backed_block *bb;
231 struct backed_block *start; 240 struct backed_block *start;
232 int64_t file_len = 0; 241 int64_t file_len = 0;
242 int ret;
233 243
234 /* 244 /*
235 * overhead is sparse file header, initial skip chunk, split chunk, end 245 * 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,
249 for (bb = start; bb; bb = backed_block_iter_next(bb)) { 259 for (bb = start; bb; bb = backed_block_iter_next(bb)) {
250 count = 0; 260 count = 0;
251 /* will call out_counter_write to update count */ 261 /* will call out_counter_write to update count */
252 sparse_file_write_block(out_counter, bb); 262 ret = sparse_file_write_block(out_counter, bb);
263 if (ret) {
264 bb = NULL;
265 goto out;
266 }
253 if (file_len + count > len) { 267 if (file_len + count > len) {
254 /* 268 /*
255 * If the remaining available size is more than 1/8th of the 269 * 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,
260 backed_block_split(from->backed_block_list, bb, len - file_len); 274 backed_block_split(from->backed_block_list, bb, len - file_len);
261 last_bb = bb; 275 last_bb = bb;
262 } 276 }
263 goto out; 277 goto move;
264 } 278 }
265 file_len += count; 279 file_len += count;
266 last_bb = bb; 280 last_bb = bb;
267 } 281 }
268 282
269out: 283move:
270 backed_block_list_move(from->backed_block_list, 284 backed_block_list_move(from->backed_block_list,
271 to->backed_block_list, start, last_bb); 285 to->backed_block_list, start, last_bb);
272 286
287out:
273 output_file_close(out_counter); 288 output_file_close(out_counter);
274 289
275 return bb; 290 return bb;