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)
49static char *copybuf;
50
51#define min(a, b) \
52	({ typeof(a) _a = (a); typeof(b) _b = (b); (_a < _b) ? _a : _b; })
53
54static 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 _WIN32
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
101static 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
139static 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
180static 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
202static 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
223static 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
275static 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
357static 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
409int 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
422struct 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
478struct 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