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