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