10c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross/*
20c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross * Copyright (C) 2012 The Android Open Source Project
30c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross *
40c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross * Licensed under the Apache License, Version 2.0 (the "License");
50c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross * you may not use this file except in compliance with the License.
60c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross * You may obtain a copy of the License at
70c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross *
80c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross *      http://www.apache.org/licenses/LICENSE-2.0
90c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross *
100c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross * Unless required by applicable law or agreed to in writing, software
110c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross * distributed under the License is distributed on an "AS IS" BASIS,
120c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross * See the License for the specific language governing permissions and
140c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross * limitations under the License.
150c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross */
160c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
170c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#define _GNU_SOURCE
180c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#define _FILE_OFFSET_BITS 64
190c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#define _LARGEFILE64_SOURCE 1
200c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
21af090a6ea897f90c02ffde8a1b49f76c426d9d31Daniel Micay#include <inttypes.h>
220c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#include <fcntl.h>
230c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#include <stdarg.h>
240c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#include <stdbool.h>
250c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#include <stdint.h>
260c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#include <stdio.h>
270c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#include <stdlib.h>
280c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#include <string.h>
290c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#include <unistd.h>
300c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
310c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#include <sparse/sparse.h>
320c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
33031a748b2a9bf6dcfd3983d8f0f616718fcddd88Mark Salyzyn#include "defs.h"
34031a748b2a9bf6dcfd3983d8f0f616718fcddd88Mark Salyzyn#include "output_file.h"
350c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#include "sparse_crc32.h"
360c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#include "sparse_file.h"
370c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#include "sparse_format.h"
380c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
390c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#if defined(__APPLE__) && defined(__MACH__)
400c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#define lseek64 lseek
410c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#define off64_t off_t
420c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#endif
430c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
440c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#define SPARSE_HEADER_MAJOR_VER 1
450c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#define SPARSE_HEADER_LEN       (sizeof(sparse_header_t))
460c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#define CHUNK_HEADER_LEN (sizeof(chunk_header_t))
470c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
480c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#define COPY_BUF_SIZE (1024U*1024U)
490c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Crossstatic char *copybuf;
500c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
510c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#define min(a, b) \
520c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	({ typeof(a) _a = (a); typeof(b) _b = (b); (_a < _b) ? _a : _b; })
530c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
540c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Crossstatic void verbose_error(bool verbose, int err, const char *fmt, ...)
550c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross{
560c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	char *s = "";
570c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	char *at = "";
580c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (fmt) {
590c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		va_list argp;
600c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		int size;
610c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
620c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		va_start(argp, fmt);
630c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		size = vsnprintf(NULL, 0, fmt, argp);
640c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		va_end(argp);
650c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
660c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		if (size < 0) {
670c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			return;
680c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		}
690c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
700c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		at = malloc(size + 1);
710c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		if (at == NULL) {
720c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			return;
730c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		}
740c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
750c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		va_start(argp, fmt);
760c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		vsnprintf(at, size, fmt, argp);
770c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		va_end(argp);
780c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		at[size] = 0;
790c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		s = " at ";
800c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
810c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (verbose) {
820c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#ifndef USE_MINGW
830c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		if (err == -EOVERFLOW) {
840c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			sparse_print_verbose("EOF while reading file%s%s\n", s, at);
850c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		} else
860c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross#endif
870c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		if (err == -EINVAL) {
880c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			sparse_print_verbose("Invalid sparse file format%s%s\n", s, at);
890c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		} else if (err == -ENOMEM) {
900c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			sparse_print_verbose("Failed allocation while reading file%s%s\n",
910c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross					s, at);
920c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		} else {
930c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			sparse_print_verbose("Unknown error %d%s%s\n", err, s, at);
940c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		}
950c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
960c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (fmt) {
970c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		free(at);
980c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
990c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross}
1000c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1010c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Crossstatic int process_raw_chunk(struct sparse_file *s, unsigned int chunk_size,
1020c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		int fd, int64_t offset, unsigned int blocks, unsigned int block,
1030c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		uint32_t *crc32)
1040c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross{
1050c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int ret;
1060c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int chunk;
1070c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	unsigned int len = blocks * s->block_size;
1080c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1090c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (chunk_size % s->block_size != 0) {
1100c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -EINVAL;
1110c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
1120c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1130c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (chunk_size / s->block_size != blocks) {
1140c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -EINVAL;
1150c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
1160c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1170c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	ret = sparse_file_add_fd(s, fd, offset, len, block);
1180c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (ret < 0) {
1190c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return ret;
1200c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
1210c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1220c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (crc32) {
1230c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		while (len) {
1240c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			chunk = min(len, COPY_BUF_SIZE);
1250c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			ret = read_all(fd, copybuf, chunk);
1260c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			if (ret < 0) {
1270c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross				return ret;
1280c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			}
1290c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			*crc32 = sparse_crc32(*crc32, copybuf, chunk);
1300c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			len -= chunk;
1310c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		}
1320c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	} else {
1330c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		lseek64(fd, len, SEEK_CUR);
1340c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
1350c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1360c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	return 0;
1370c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross}
1380c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1390c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Crossstatic int process_fill_chunk(struct sparse_file *s, unsigned int chunk_size,
1400c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		int fd, unsigned int blocks, unsigned int block, uint32_t *crc32)
1410c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross{
1420c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int ret;
1430c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int chunk;
1440c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int64_t len = (int64_t)blocks * s->block_size;
1450c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	uint32_t fill_val;
1460c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	uint32_t *fillbuf;
1470c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	unsigned int i;
1480c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1490c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (chunk_size != sizeof(fill_val)) {
1500c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -EINVAL;
1510c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
1520c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1530c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	ret = read_all(fd, &fill_val, sizeof(fill_val));
1540c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (ret < 0) {
1550c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return ret;
1560c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
1570c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1580c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	ret = sparse_file_add_fill(s, fill_val, len, block);
1590c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (ret < 0) {
1600c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return ret;
1610c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
1620c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1630c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (crc32) {
1640c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		/* Fill copy_buf with the fill value */
1650c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		fillbuf = (uint32_t *)copybuf;
1660c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		for (i = 0; i < (COPY_BUF_SIZE / sizeof(fill_val)); i++) {
1670c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			fillbuf[i] = fill_val;
1680c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		}
1690c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1700c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		while (len) {
1710c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			chunk = min(len, COPY_BUF_SIZE);
1720c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			*crc32 = sparse_crc32(*crc32, copybuf, chunk);
1730c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			len -= chunk;
1740c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		}
1750c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
1760c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1770c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	return 0;
1780c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross}
1790c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1800c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Crossstatic int process_skip_chunk(struct sparse_file *s, unsigned int chunk_size,
181031a748b2a9bf6dcfd3983d8f0f616718fcddd88Mark Salyzyn		int fd __unused, unsigned int blocks,
182031a748b2a9bf6dcfd3983d8f0f616718fcddd88Mark Salyzyn		unsigned int block __unused, uint32_t *crc32)
1830c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross{
1840c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (chunk_size != 0) {
1850c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -EINVAL;
1860c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
1870c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1880c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (crc32) {
1898116c8c37aadd83033ffea9e4f5fc86240428e43Mark Salyzyn	        int64_t len = (int64_t)blocks * s->block_size;
1900c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		memset(copybuf, 0, COPY_BUF_SIZE);
1910c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1920c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		while (len) {
1938116c8c37aadd83033ffea9e4f5fc86240428e43Mark Salyzyn			int chunk = min(len, COPY_BUF_SIZE);
1940c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			*crc32 = sparse_crc32(*crc32, copybuf, chunk);
1950c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			len -= chunk;
1960c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		}
1970c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
1980c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
1990c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	return 0;
2000c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross}
2010c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2021eb743ba8b63daf773ed4628504a3bb95ee2c156Colin Crossstatic int process_crc32_chunk(int fd, unsigned int chunk_size, uint32_t *crc32)
2030c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross{
2040c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	uint32_t file_crc32;
2050c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int ret;
2060c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2070c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (chunk_size != sizeof(file_crc32)) {
2080c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -EINVAL;
2090c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
2100c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2110c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	ret = read_all(fd, &file_crc32, sizeof(file_crc32));
2120c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (ret < 0) {
2130c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return ret;
2140c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
2150c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2161eb743ba8b63daf773ed4628504a3bb95ee2c156Colin Cross	if (crc32 != NULL && file_crc32 != *crc32) {
2170c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -EINVAL;
2180c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
2190c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2200c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	return 0;
2210c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross}
2220c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2230c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Crossstatic int process_chunk(struct sparse_file *s, int fd, off64_t offset,
2240c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		unsigned int chunk_hdr_sz, chunk_header_t *chunk_header,
2250c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		unsigned int cur_block, uint32_t *crc_ptr)
2260c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross{
2270c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int ret;
2280c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	unsigned int chunk_data_size;
2290c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2300c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	chunk_data_size = chunk_header->total_sz - chunk_hdr_sz;
2310c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2320c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	switch (chunk_header->chunk_type) {
2330c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		case CHUNK_TYPE_RAW:
2340c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			ret = process_raw_chunk(s, chunk_data_size, fd, offset,
2350c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross					chunk_header->chunk_sz, cur_block, crc_ptr);
2360c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			if (ret < 0) {
237af090a6ea897f90c02ffde8a1b49f76c426d9d31Daniel Micay				verbose_error(s->verbose, ret, "data block at %" PRId64, offset);
2380c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross				return ret;
2390c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			}
2400c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			return chunk_header->chunk_sz;
2410c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		case CHUNK_TYPE_FILL:
2420c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			ret = process_fill_chunk(s, chunk_data_size, fd,
2430c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross					chunk_header->chunk_sz, cur_block, crc_ptr);
2440c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			if (ret < 0) {
245af090a6ea897f90c02ffde8a1b49f76c426d9d31Daniel Micay				verbose_error(s->verbose, ret, "fill block at %" PRId64, offset);
2460c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross				return ret;
2470c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			}
2480c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			return chunk_header->chunk_sz;
2490c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		case CHUNK_TYPE_DONT_CARE:
2500c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			ret = process_skip_chunk(s, chunk_data_size, fd,
2510c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross					chunk_header->chunk_sz, cur_block, crc_ptr);
2520c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			if (chunk_data_size != 0) {
2530c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross				if (ret < 0) {
254af090a6ea897f90c02ffde8a1b49f76c426d9d31Daniel Micay					verbose_error(s->verbose, ret, "skip block at %" PRId64, offset);
2550c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross					return ret;
2560c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross				}
2570c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			}
2580c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			return chunk_header->chunk_sz;
2590c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		case CHUNK_TYPE_CRC32:
2601eb743ba8b63daf773ed4628504a3bb95ee2c156Colin Cross			ret = process_crc32_chunk(fd, chunk_data_size, crc_ptr);
2610c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			if (ret < 0) {
262af090a6ea897f90c02ffde8a1b49f76c426d9d31Daniel Micay				verbose_error(s->verbose, -EINVAL, "crc block at %" PRId64,
2630c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross						offset);
2640c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross				return ret;
2650c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			}
2660c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			return 0;
2670c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		default:
268af090a6ea897f90c02ffde8a1b49f76c426d9d31Daniel Micay			verbose_error(s->verbose, -EINVAL, "unknown block %04X at %" PRId64,
2690c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross					chunk_header->chunk_type, offset);
2700c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
2710c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2720c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	return 0;
2730c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross}
2740c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2750c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Crossstatic int sparse_file_read_sparse(struct sparse_file *s, int fd, bool crc)
2760c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross{
2770c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int ret;
2780c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	unsigned int i;
2790c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	sparse_header_t sparse_header;
2800c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	chunk_header_t chunk_header;
2810c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	uint32_t crc32 = 0;
2820c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	uint32_t *crc_ptr = 0;
2830c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	unsigned int cur_block = 0;
2840c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	off64_t offset;
2850c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2860c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (!copybuf) {
2870c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		copybuf = malloc(COPY_BUF_SIZE);
2880c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
2890c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2900c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (!copybuf) {
2910c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -ENOMEM;
2920c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
2930c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2940c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (crc) {
2950c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		crc_ptr = &crc32;
2960c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
2970c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
2980c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	ret = read_all(fd, &sparse_header, sizeof(sparse_header));
2990c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (ret < 0) {
3000c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return ret;
3010c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
3020c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3030c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (sparse_header.magic != SPARSE_HEADER_MAGIC) {
3040c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -EINVAL;
3050c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
3060c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3070c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (sparse_header.major_version != SPARSE_HEADER_MAJOR_VER) {
3080c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -EINVAL;
3090c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
3100c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3110c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (sparse_header.file_hdr_sz < SPARSE_HEADER_LEN) {
3120c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -EINVAL;
3130c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
3140c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3150c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (sparse_header.chunk_hdr_sz < sizeof(chunk_header)) {
3160c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -EINVAL;
3170c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
3180c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3190c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (sparse_header.file_hdr_sz > SPARSE_HEADER_LEN) {
3200c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		/* Skip the remaining bytes in a header that is longer than
3210c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		 * we expected.
3220c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		 */
3230c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		lseek64(fd, sparse_header.file_hdr_sz - SPARSE_HEADER_LEN, SEEK_CUR);
3240c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
3250c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3260c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	for (i = 0; i < sparse_header.total_chunks; i++) {
3270c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		ret = read_all(fd, &chunk_header, sizeof(chunk_header));
3280c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		if (ret < 0) {
3290c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			return ret;
3300c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		}
3310c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3320c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		if (sparse_header.chunk_hdr_sz > CHUNK_HEADER_LEN) {
3330c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			/* Skip the remaining bytes in a header that is longer than
3340c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			 * we expected.
3350c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			 */
3360c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			lseek64(fd, sparse_header.chunk_hdr_sz - CHUNK_HEADER_LEN, SEEK_CUR);
3370c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		}
3380c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3390c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		offset = lseek64(fd, 0, SEEK_CUR);
3400c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3410c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		ret = process_chunk(s, fd, offset, sparse_header.chunk_hdr_sz, &chunk_header,
3420c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross				cur_block, crc_ptr);
3430c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		if (ret < 0) {
3440c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			return ret;
3450c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		}
3460c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3470c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		cur_block += ret;
3480c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
3490c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3500c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (sparse_header.total_blks != cur_block) {
3510c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -EINVAL;
3520c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
3530c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3540c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	return 0;
3550c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross}
3560c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3570c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Crossstatic int sparse_file_read_normal(struct sparse_file *s, int fd)
3580c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross{
3590c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int ret;
3600c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	uint32_t *buf = malloc(s->block_size);
3610c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	unsigned int block = 0;
3620c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int64_t remain = s->len;
3630c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int64_t offset = 0;
3640c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	unsigned int to_read;
3650c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	unsigned int i;
3660c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	bool sparse_block;
3670c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3680c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (!buf) {
3690c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -ENOMEM;
3700c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
3710c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3720c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	while (remain > 0) {
3730c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		to_read = min(remain, s->block_size);
3740c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		ret = read_all(fd, buf, to_read);
3750c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		if (ret < 0) {
3760c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			error("failed to read sparse file");
3771eb743ba8b63daf773ed4628504a3bb95ee2c156Colin Cross			free(buf);
3780c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			return ret;
3790c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		}
3800c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3810c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		if (to_read == s->block_size) {
3820c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			sparse_block = true;
3830c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			for (i = 1; i < s->block_size / sizeof(uint32_t); i++) {
3840c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross				if (buf[0] != buf[i]) {
3850c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross					sparse_block = false;
3860c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross					break;
3870c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross				}
3880c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			}
3890c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		} else {
3900c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			sparse_block = false;
3910c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		}
3920c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
3930c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		if (sparse_block) {
3940c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			/* TODO: add flag to use skip instead of fill for buf[0] == 0 */
3950c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			sparse_file_add_fill(s, buf[0], to_read, block);
3960c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		} else {
3970c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross			sparse_file_add_fd(s, fd, offset, to_read, block);
3980c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		}
3990c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4000c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		remain -= to_read;
4010c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		offset += to_read;
4020c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		block++;
4030c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
4040c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4051eb743ba8b63daf773ed4628504a3bb95ee2c156Colin Cross	free(buf);
4060c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	return 0;
4070c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross}
4080c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4090c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Crossint sparse_file_read(struct sparse_file *s, int fd, bool sparse, bool crc)
4100c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross{
4110c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (crc && !sparse) {
4120c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return -EINVAL;
4130c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
4140c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4150c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (sparse) {
4160c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return sparse_file_read_sparse(s, fd, crc);
4170c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	} else {
4180c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return sparse_file_read_normal(s, fd);
4190c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
4200c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross}
4210c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4220c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Crossstruct sparse_file *sparse_file_import(int fd, bool verbose, bool crc)
4230c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross{
4240c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int ret;
4250c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	sparse_header_t sparse_header;
4260c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int64_t len;
4270c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	struct sparse_file *s;
4280c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4290c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	ret = read_all(fd, &sparse_header, sizeof(sparse_header));
4300c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (ret < 0) {
4310c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		verbose_error(verbose, ret, "header");
4320c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return NULL;
4330c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
4340c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4350c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (sparse_header.magic != SPARSE_HEADER_MAGIC) {
4360c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		verbose_error(verbose, -EINVAL, "header magic");
4370c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return NULL;
4380c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
4390c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4400c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (sparse_header.major_version != SPARSE_HEADER_MAJOR_VER) {
4410c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		verbose_error(verbose, -EINVAL, "header major version");
4420c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return NULL;
4430c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
4440c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4450c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (sparse_header.file_hdr_sz < SPARSE_HEADER_LEN) {
4460c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return NULL;
4470c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
4480c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4490c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (sparse_header.chunk_hdr_sz < sizeof(chunk_header_t)) {
4500c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return NULL;
4510c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
4520c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4530c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	len = (int64_t)sparse_header.total_blks * sparse_header.blk_sz;
4540c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	s = sparse_file_new(sparse_header.blk_sz, len);
4550c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (!s) {
4560c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		verbose_error(verbose, -EINVAL, NULL);
4570c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return NULL;
4580c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
4590c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4600c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	ret = lseek64(fd, 0, SEEK_SET);
4610c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (ret < 0) {
4620c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		verbose_error(verbose, ret, "seeking");
4630c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		sparse_file_destroy(s);
4640c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return NULL;
4650c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
4660c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4670c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	s->verbose = verbose;
4680c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4690c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	ret = sparse_file_read(s, fd, true, crc);
4700c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (ret < 0) {
4710c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		sparse_file_destroy(s);
4720c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return NULL;
4730c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
4740c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4750c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	return s;
4760c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross}
4770c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
47880cc1f6864288f166b786a61ad57f12081114225Mohamad Ayyashstruct sparse_file *sparse_file_import_auto(int fd, bool crc, bool verbose)
4790c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross{
4800c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	struct sparse_file *s;
4810c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int64_t len;
4820c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	int ret;
4830c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
48480cc1f6864288f166b786a61ad57f12081114225Mohamad Ayyash	s = sparse_file_import(fd, verbose, crc);
4850c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (s) {
4860c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return s;
4870c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
4880c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4890c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	len = lseek64(fd, 0, SEEK_END);
4900c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (len < 0) {
4910c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return NULL;
4920c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
4930c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4940c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	lseek64(fd, 0, SEEK_SET);
4950c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
4960c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	s = sparse_file_new(4096, len);
4970c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (!s) {
4980c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return NULL;
4990c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
5000c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
5010c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	ret = sparse_file_read_normal(s, fd);
5020c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	if (ret < 0) {
5030c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		sparse_file_destroy(s);
5040c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross		return NULL;
5050c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	}
5060c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross
5070c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross	return s;
5080c4c47f88dfc15cada154a1cf9b4db88b49890f0Colin Cross}
509