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