1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define _GNU_SOURCE
18 #define _FILE_OFFSET_BITS 64
19 #define _LARGEFILE64_SOURCE 1
20 
21 #include <inttypes.h>
22 #include <fcntl.h>
23 #include <stdarg.h>
24 #include <stdbool.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 
31 #include <sparse/sparse.h>
32 
33 #include "defs.h"
34 #include "output_file.h"
35 #include "sparse_crc32.h"
36 #include "sparse_file.h"
37 #include "sparse_format.h"
38 
39 #if defined(__APPLE__) && defined(__MACH__)
40 #define lseek64 lseek
41 #define off64_t off_t
42 #endif
43 
44 #define SPARSE_HEADER_MAJOR_VER 1
45 #define SPARSE_HEADER_LEN       (sizeof(sparse_header_t))
46 #define CHUNK_HEADER_LEN (sizeof(chunk_header_t))
47 
48 #define COPY_BUF_SIZE (1024U*1024U)
49 static char *copybuf;
50 
51 #define min(a, b) \
52 	({ typeof(a) _a = (a); typeof(b) _b = (b); (_a < _b) ? _a : _b; })
53 
verbose_error(bool verbose,int err,const char * fmt,...)54 static void verbose_error(bool verbose, int err, const char *fmt, ...)
55 {
56 	char *s = "";
57 	char *at = "";
58 	if (fmt) {
59 		va_list argp;
60 		int size;
61 
62 		va_start(argp, fmt);
63 		size = vsnprintf(NULL, 0, fmt, argp);
64 		va_end(argp);
65 
66 		if (size < 0) {
67 			return;
68 		}
69 
70 		at = malloc(size + 1);
71 		if (at == NULL) {
72 			return;
73 		}
74 
75 		va_start(argp, fmt);
76 		vsnprintf(at, size, fmt, argp);
77 		va_end(argp);
78 		at[size] = 0;
79 		s = " at ";
80 	}
81 	if (verbose) {
82 #ifndef USE_MINGW
83 		if (err == -EOVERFLOW) {
84 			sparse_print_verbose("EOF while reading file%s%s\n", s, at);
85 		} else
86 #endif
87 		if (err == -EINVAL) {
88 			sparse_print_verbose("Invalid sparse file format%s%s\n", s, at);
89 		} else if (err == -ENOMEM) {
90 			sparse_print_verbose("Failed allocation while reading file%s%s\n",
91 					s, at);
92 		} else {
93 			sparse_print_verbose("Unknown error %d%s%s\n", err, s, at);
94 		}
95 	}
96 	if (fmt) {
97 		free(at);
98 	}
99 }
100 
process_raw_chunk(struct sparse_file * s,unsigned int chunk_size,int fd,int64_t offset,unsigned int blocks,unsigned int block,uint32_t * crc32)101 static int process_raw_chunk(struct sparse_file *s, unsigned int chunk_size,
102 		int fd, int64_t offset, unsigned int blocks, unsigned int block,
103 		uint32_t *crc32)
104 {
105 	int ret;
106 	int chunk;
107 	unsigned int len = blocks * s->block_size;
108 
109 	if (chunk_size % s->block_size != 0) {
110 		return -EINVAL;
111 	}
112 
113 	if (chunk_size / s->block_size != blocks) {
114 		return -EINVAL;
115 	}
116 
117 	ret = sparse_file_add_fd(s, fd, offset, len, block);
118 	if (ret < 0) {
119 		return ret;
120 	}
121 
122 	if (crc32) {
123 		while (len) {
124 			chunk = min(len, COPY_BUF_SIZE);
125 			ret = read_all(fd, copybuf, chunk);
126 			if (ret < 0) {
127 				return ret;
128 			}
129 			*crc32 = sparse_crc32(*crc32, copybuf, chunk);
130 			len -= chunk;
131 		}
132 	} else {
133 		lseek64(fd, len, SEEK_CUR);
134 	}
135 
136 	return 0;
137 }
138 
process_fill_chunk(struct sparse_file * s,unsigned int chunk_size,int fd,unsigned int blocks,unsigned int block,uint32_t * crc32)139 static int process_fill_chunk(struct sparse_file *s, unsigned int chunk_size,
140 		int fd, unsigned int blocks, unsigned int block, uint32_t *crc32)
141 {
142 	int ret;
143 	int chunk;
144 	int64_t len = (int64_t)blocks * s->block_size;
145 	uint32_t fill_val;
146 	uint32_t *fillbuf;
147 	unsigned int i;
148 
149 	if (chunk_size != sizeof(fill_val)) {
150 		return -EINVAL;
151 	}
152 
153 	ret = read_all(fd, &fill_val, sizeof(fill_val));
154 	if (ret < 0) {
155 		return ret;
156 	}
157 
158 	ret = sparse_file_add_fill(s, fill_val, len, block);
159 	if (ret < 0) {
160 		return ret;
161 	}
162 
163 	if (crc32) {
164 		/* Fill copy_buf with the fill value */
165 		fillbuf = (uint32_t *)copybuf;
166 		for (i = 0; i < (COPY_BUF_SIZE / sizeof(fill_val)); i++) {
167 			fillbuf[i] = fill_val;
168 		}
169 
170 		while (len) {
171 			chunk = min(len, COPY_BUF_SIZE);
172 			*crc32 = sparse_crc32(*crc32, copybuf, chunk);
173 			len -= chunk;
174 		}
175 	}
176 
177 	return 0;
178 }
179 
process_skip_chunk(struct sparse_file * s,unsigned int chunk_size,int fd __unused,unsigned int blocks,unsigned int block __unused,uint32_t * crc32)180 static int process_skip_chunk(struct sparse_file *s, unsigned int chunk_size,
181 		int fd __unused, unsigned int blocks,
182 		unsigned int block __unused, uint32_t *crc32)
183 {
184 	if (chunk_size != 0) {
185 		return -EINVAL;
186 	}
187 
188 	if (crc32) {
189 	        int64_t len = (int64_t)blocks * s->block_size;
190 		memset(copybuf, 0, COPY_BUF_SIZE);
191 
192 		while (len) {
193 			int chunk = min(len, COPY_BUF_SIZE);
194 			*crc32 = sparse_crc32(*crc32, copybuf, chunk);
195 			len -= chunk;
196 		}
197 	}
198 
199 	return 0;
200 }
201 
process_crc32_chunk(int fd,unsigned int chunk_size,uint32_t * crc32)202 static int process_crc32_chunk(int fd, unsigned int chunk_size, uint32_t *crc32)
203 {
204 	uint32_t file_crc32;
205 	int ret;
206 
207 	if (chunk_size != sizeof(file_crc32)) {
208 		return -EINVAL;
209 	}
210 
211 	ret = read_all(fd, &file_crc32, sizeof(file_crc32));
212 	if (ret < 0) {
213 		return ret;
214 	}
215 
216 	if (crc32 != NULL && file_crc32 != *crc32) {
217 		return -EINVAL;
218 	}
219 
220 	return 0;
221 }
222 
process_chunk(struct sparse_file * s,int fd,off64_t offset,unsigned int chunk_hdr_sz,chunk_header_t * chunk_header,unsigned int cur_block,uint32_t * crc_ptr)223 static int process_chunk(struct sparse_file *s, int fd, off64_t offset,
224 		unsigned int chunk_hdr_sz, chunk_header_t *chunk_header,
225 		unsigned int cur_block, uint32_t *crc_ptr)
226 {
227 	int ret;
228 	unsigned int chunk_data_size;
229 
230 	chunk_data_size = chunk_header->total_sz - chunk_hdr_sz;
231 
232 	switch (chunk_header->chunk_type) {
233 		case CHUNK_TYPE_RAW:
234 			ret = process_raw_chunk(s, chunk_data_size, fd, offset,
235 					chunk_header->chunk_sz, cur_block, crc_ptr);
236 			if (ret < 0) {
237 				verbose_error(s->verbose, ret, "data block at %" PRId64, offset);
238 				return ret;
239 			}
240 			return chunk_header->chunk_sz;
241 		case CHUNK_TYPE_FILL:
242 			ret = process_fill_chunk(s, chunk_data_size, fd,
243 					chunk_header->chunk_sz, cur_block, crc_ptr);
244 			if (ret < 0) {
245 				verbose_error(s->verbose, ret, "fill block at %" PRId64, offset);
246 				return ret;
247 			}
248 			return chunk_header->chunk_sz;
249 		case CHUNK_TYPE_DONT_CARE:
250 			ret = process_skip_chunk(s, chunk_data_size, fd,
251 					chunk_header->chunk_sz, cur_block, crc_ptr);
252 			if (chunk_data_size != 0) {
253 				if (ret < 0) {
254 					verbose_error(s->verbose, ret, "skip block at %" PRId64, offset);
255 					return ret;
256 				}
257 			}
258 			return chunk_header->chunk_sz;
259 		case CHUNK_TYPE_CRC32:
260 			ret = process_crc32_chunk(fd, chunk_data_size, crc_ptr);
261 			if (ret < 0) {
262 				verbose_error(s->verbose, -EINVAL, "crc block at %" PRId64,
263 						offset);
264 				return ret;
265 			}
266 			return 0;
267 		default:
268 			verbose_error(s->verbose, -EINVAL, "unknown block %04X at %" PRId64,
269 					chunk_header->chunk_type, offset);
270 	}
271 
272 	return 0;
273 }
274 
sparse_file_read_sparse(struct sparse_file * s,int fd,bool crc)275 static int sparse_file_read_sparse(struct sparse_file *s, int fd, bool crc)
276 {
277 	int ret;
278 	unsigned int i;
279 	sparse_header_t sparse_header;
280 	chunk_header_t chunk_header;
281 	uint32_t crc32 = 0;
282 	uint32_t *crc_ptr = 0;
283 	unsigned int cur_block = 0;
284 	off64_t offset;
285 
286 	if (!copybuf) {
287 		copybuf = malloc(COPY_BUF_SIZE);
288 	}
289 
290 	if (!copybuf) {
291 		return -ENOMEM;
292 	}
293 
294 	if (crc) {
295 		crc_ptr = &crc32;
296 	}
297 
298 	ret = read_all(fd, &sparse_header, sizeof(sparse_header));
299 	if (ret < 0) {
300 		return ret;
301 	}
302 
303 	if (sparse_header.magic != SPARSE_HEADER_MAGIC) {
304 		return -EINVAL;
305 	}
306 
307 	if (sparse_header.major_version != SPARSE_HEADER_MAJOR_VER) {
308 		return -EINVAL;
309 	}
310 
311 	if (sparse_header.file_hdr_sz < SPARSE_HEADER_LEN) {
312 		return -EINVAL;
313 	}
314 
315 	if (sparse_header.chunk_hdr_sz < sizeof(chunk_header)) {
316 		return -EINVAL;
317 	}
318 
319 	if (sparse_header.file_hdr_sz > SPARSE_HEADER_LEN) {
320 		/* Skip the remaining bytes in a header that is longer than
321 		 * we expected.
322 		 */
323 		lseek64(fd, sparse_header.file_hdr_sz - SPARSE_HEADER_LEN, SEEK_CUR);
324 	}
325 
326 	for (i = 0; i < sparse_header.total_chunks; i++) {
327 		ret = read_all(fd, &chunk_header, sizeof(chunk_header));
328 		if (ret < 0) {
329 			return ret;
330 		}
331 
332 		if (sparse_header.chunk_hdr_sz > CHUNK_HEADER_LEN) {
333 			/* Skip the remaining bytes in a header that is longer than
334 			 * we expected.
335 			 */
336 			lseek64(fd, sparse_header.chunk_hdr_sz - CHUNK_HEADER_LEN, SEEK_CUR);
337 		}
338 
339 		offset = lseek64(fd, 0, SEEK_CUR);
340 
341 		ret = process_chunk(s, fd, offset, sparse_header.chunk_hdr_sz, &chunk_header,
342 				cur_block, crc_ptr);
343 		if (ret < 0) {
344 			return ret;
345 		}
346 
347 		cur_block += ret;
348 	}
349 
350 	if (sparse_header.total_blks != cur_block) {
351 		return -EINVAL;
352 	}
353 
354 	return 0;
355 }
356 
sparse_file_read_normal(struct sparse_file * s,int fd)357 static int sparse_file_read_normal(struct sparse_file *s, int fd)
358 {
359 	int ret;
360 	uint32_t *buf = malloc(s->block_size);
361 	unsigned int block = 0;
362 	int64_t remain = s->len;
363 	int64_t offset = 0;
364 	unsigned int to_read;
365 	unsigned int i;
366 	bool sparse_block;
367 
368 	if (!buf) {
369 		return -ENOMEM;
370 	}
371 
372 	while (remain > 0) {
373 		to_read = min(remain, s->block_size);
374 		ret = read_all(fd, buf, to_read);
375 		if (ret < 0) {
376 			error("failed to read sparse file");
377 			free(buf);
378 			return ret;
379 		}
380 
381 		if (to_read == s->block_size) {
382 			sparse_block = true;
383 			for (i = 1; i < s->block_size / sizeof(uint32_t); i++) {
384 				if (buf[0] != buf[i]) {
385 					sparse_block = false;
386 					break;
387 				}
388 			}
389 		} else {
390 			sparse_block = false;
391 		}
392 
393 		if (sparse_block) {
394 			/* TODO: add flag to use skip instead of fill for buf[0] == 0 */
395 			sparse_file_add_fill(s, buf[0], to_read, block);
396 		} else {
397 			sparse_file_add_fd(s, fd, offset, to_read, block);
398 		}
399 
400 		remain -= to_read;
401 		offset += to_read;
402 		block++;
403 	}
404 
405 	free(buf);
406 	return 0;
407 }
408 
sparse_file_read(struct sparse_file * s,int fd,bool sparse,bool crc)409 int sparse_file_read(struct sparse_file *s, int fd, bool sparse, bool crc)
410 {
411 	if (crc && !sparse) {
412 		return -EINVAL;
413 	}
414 
415 	if (sparse) {
416 		return sparse_file_read_sparse(s, fd, crc);
417 	} else {
418 		return sparse_file_read_normal(s, fd);
419 	}
420 }
421 
sparse_file_import(int fd,bool verbose,bool crc)422 struct sparse_file *sparse_file_import(int fd, bool verbose, bool crc)
423 {
424 	int ret;
425 	sparse_header_t sparse_header;
426 	int64_t len;
427 	struct sparse_file *s;
428 
429 	ret = read_all(fd, &sparse_header, sizeof(sparse_header));
430 	if (ret < 0) {
431 		verbose_error(verbose, ret, "header");
432 		return NULL;
433 	}
434 
435 	if (sparse_header.magic != SPARSE_HEADER_MAGIC) {
436 		verbose_error(verbose, -EINVAL, "header magic");
437 		return NULL;
438 	}
439 
440 	if (sparse_header.major_version != SPARSE_HEADER_MAJOR_VER) {
441 		verbose_error(verbose, -EINVAL, "header major version");
442 		return NULL;
443 	}
444 
445 	if (sparse_header.file_hdr_sz < SPARSE_HEADER_LEN) {
446 		return NULL;
447 	}
448 
449 	if (sparse_header.chunk_hdr_sz < sizeof(chunk_header_t)) {
450 		return NULL;
451 	}
452 
453 	len = (int64_t)sparse_header.total_blks * sparse_header.blk_sz;
454 	s = sparse_file_new(sparse_header.blk_sz, len);
455 	if (!s) {
456 		verbose_error(verbose, -EINVAL, NULL);
457 		return NULL;
458 	}
459 
460 	ret = lseek64(fd, 0, SEEK_SET);
461 	if (ret < 0) {
462 		verbose_error(verbose, ret, "seeking");
463 		sparse_file_destroy(s);
464 		return NULL;
465 	}
466 
467 	s->verbose = verbose;
468 
469 	ret = sparse_file_read(s, fd, true, crc);
470 	if (ret < 0) {
471 		sparse_file_destroy(s);
472 		return NULL;
473 	}
474 
475 	return s;
476 }
477 
sparse_file_import_auto(int fd,bool crc,bool verbose)478 struct sparse_file *sparse_file_import_auto(int fd, bool crc, bool verbose)
479 {
480 	struct sparse_file *s;
481 	int64_t len;
482 	int ret;
483 
484 	s = sparse_file_import(fd, verbose, crc);
485 	if (s) {
486 		return s;
487 	}
488 
489 	len = lseek64(fd, 0, SEEK_END);
490 	if (len < 0) {
491 		return NULL;
492 	}
493 
494 	lseek64(fd, 0, SEEK_SET);
495 
496 	s = sparse_file_new(4096, len);
497 	if (!s) {
498 		return NULL;
499 	}
500 
501 	ret = sparse_file_read_normal(s, fd);
502 	if (ret < 0) {
503 		sparse_file_destroy(s);
504 		return NULL;
505 	}
506 
507 	return s;
508 }
509