128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* 228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * Copyright (C) 2010 The Android Open Source Project 328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * 428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * Licensed under the Apache License, Version 2.0 (the "License"); 528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * you may not use this file except in compliance with the License. 628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * You may obtain a copy of the License at 728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * 828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * http://www.apache.org/licenses/LICENSE-2.0 928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * 1028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * Unless required by applicable law or agreed to in writing, software 1128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * distributed under the License is distributed on an "AS IS" BASIS, 1228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * See the License for the specific language governing permissions and 1428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * limitations under the License. 1528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross */ 1628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 1728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define _FILE_OFFSET_BITS 64 1828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define _LARGEFILE64_SOURCE 1 1928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 2028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <fcntl.h> 21ccecf1425412beb2bc3bb38d470293fdc244d6f1Elliott Hughes#include <inttypes.h> 221e17b313a6257b7b5081e178e81435c09d60378eColin Cross#include <limits.h> 2328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <stdbool.h> 24b4cd267db30c152245e6308598e0066d87c5c55dColin Cross#include <stddef.h> 2528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <stdlib.h> 2628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <string.h> 2728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sys/stat.h> 2828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sys/types.h> 2928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <unistd.h> 3028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <zlib.h> 3128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 32031a748b2a9bf6dcfd3983d8f0f616718fcddd88Mark Salyzyn#include "defs.h" 3328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "output_file.h" 3428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_crc32.h" 358116c8c37aadd83033ffea9e4f5fc86240428e43Mark Salyzyn#include "sparse_format.h" 3628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 3728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifndef USE_MINGW 3828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sys/mman.h> 3928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define O_BINARY 0 40b4cd267db30c152245e6308598e0066d87c5c55dColin Cross#else 41b4cd267db30c152245e6308598e0066d87c5c55dColin Cross#define ftruncate64 ftruncate 4228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 4328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 4428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#if defined(__APPLE__) && defined(__MACH__) 4528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define lseek64 lseek 4628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define ftruncate64 ftruncate 4728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define mmap64 mmap 4828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define off64_t off_t 4928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 5028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 51b55dceea986ab24f8b836b5116b389ed619c816eColin Cross#define min(a, b) \ 52b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ({ typeof(a) _a = (a); typeof(b) _b = (b); (_a < _b) ? _a : _b; }) 53b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 5428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define SPARSE_HEADER_MAJOR_VER 1 5528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define SPARSE_HEADER_MINOR_VER 0 5628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define SPARSE_HEADER_LEN (sizeof(sparse_header_t)) 5728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define CHUNK_HEADER_LEN (sizeof(chunk_header_t)) 5828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 59b4cd267db30c152245e6308598e0066d87c5c55dColin Cross#define container_of(inner, outer_t, elem) \ 60b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ((outer_t *)((char *)inner - offsetof(outer_t, elem))) 61b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 6228fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct output_file_ops { 63b4cd267db30c152245e6308598e0066d87c5c55dColin Cross int (*open)(struct output_file *, int fd); 64b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*skip)(struct output_file *, int64_t); 65b4cd267db30c152245e6308598e0066d87c5c55dColin Cross int (*pad)(struct output_file *, int64_t); 66b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write)(struct output_file *, void *, int); 6728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross void (*close)(struct output_file *); 6828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}; 6928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 70b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstruct sparse_file_ops { 71b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write_data_chunk)(struct output_file *out, unsigned int len, 72b55dceea986ab24f8b836b5116b389ed619c816eColin Cross void *data); 73b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write_fill_chunk)(struct output_file *out, unsigned int len, 74b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t fill_val); 75b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write_skip_chunk)(struct output_file *out, int64_t len); 76b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write_end_chunk)(struct output_file *out); 77b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}; 78b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 7928fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct output_file { 8028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int64_t cur_out_ptr; 81b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int chunk_cnt; 82b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t crc32; 8328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross struct output_file_ops *ops; 84b55dceea986ab24f8b836b5116b389ed619c816eColin Cross struct sparse_file_ops *sparse_ops; 8528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int use_crc; 8628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross unsigned int block_size; 8728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int64_t len; 88b55dceea986ab24f8b836b5116b389ed619c816eColin Cross char *zero_buf; 89b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t *fill_buf; 90b4cd267db30c152245e6308598e0066d87c5c55dColin Cross char *buf; 91b4cd267db30c152245e6308598e0066d87c5c55dColin Cross}; 92b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 93b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstruct output_file_gz { 94b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file out; 95b4cd267db30c152245e6308598e0066d87c5c55dColin Cross gzFile gz_fd; 96b4cd267db30c152245e6308598e0066d87c5c55dColin Cross}; 97b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 98b4cd267db30c152245e6308598e0066d87c5c55dColin Cross#define to_output_file_gz(_o) \ 99b4cd267db30c152245e6308598e0066d87c5c55dColin Cross container_of((_o), struct output_file_gz, out) 100b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 101b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstruct output_file_normal { 102b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file out; 103b4cd267db30c152245e6308598e0066d87c5c55dColin Cross int fd; 10428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}; 10528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 106b4cd267db30c152245e6308598e0066d87c5c55dColin Cross#define to_output_file_normal(_o) \ 107b4cd267db30c152245e6308598e0066d87c5c55dColin Cross container_of((_o), struct output_file_normal, out) 108b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 1091e17b313a6257b7b5081e178e81435c09d60378eColin Crossstruct output_file_callback { 1101e17b313a6257b7b5081e178e81435c09d60378eColin Cross struct output_file out; 1111e17b313a6257b7b5081e178e81435c09d60378eColin Cross void *priv; 1121e17b313a6257b7b5081e178e81435c09d60378eColin Cross int (*write)(void *priv, const void *buf, int len); 1131e17b313a6257b7b5081e178e81435c09d60378eColin Cross}; 1141e17b313a6257b7b5081e178e81435c09d60378eColin Cross 1151e17b313a6257b7b5081e178e81435c09d60378eColin Cross#define to_output_file_callback(_o) \ 1161e17b313a6257b7b5081e178e81435c09d60378eColin Cross container_of((_o), struct output_file_callback, out) 1171e17b313a6257b7b5081e178e81435c09d60378eColin Cross 118b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic int file_open(struct output_file *out, int fd) 119b4cd267db30c152245e6308598e0066d87c5c55dColin Cross{ 120b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_normal *outn = to_output_file_normal(out); 121b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 122b4cd267db30c152245e6308598e0066d87c5c55dColin Cross outn->fd = fd; 123b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return 0; 124b4cd267db30c152245e6308598e0066d87c5c55dColin Cross} 125b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 126b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int file_skip(struct output_file *out, int64_t cnt) 12728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 12828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross off64_t ret; 129b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_normal *outn = to_output_file_normal(out); 13028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 131b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = lseek64(outn->fd, cnt, SEEK_CUR); 13228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) { 13328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("lseek64"); 13428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 13528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 13628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 13728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 13828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 139b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic int file_pad(struct output_file *out, int64_t len) 140b4cd267db30c152245e6308598e0066d87c5c55dColin Cross{ 141b4cd267db30c152245e6308598e0066d87c5c55dColin Cross int ret; 142b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_normal *outn = to_output_file_normal(out); 143b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 144b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = ftruncate64(outn->fd, len); 145b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (ret < 0) { 146b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return -errno; 147b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 148b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 149b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return 0; 150b4cd267db30c152245e6308598e0066d87c5c55dColin Cross} 151b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 152b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int file_write(struct output_file *out, void *data, int len) 15328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 15428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 155b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_normal *outn = to_output_file_normal(out); 156b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 157b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = write(outn->fd, data, len); 15828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) { 15928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("write"); 16028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 16128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } else if (ret < len) { 16228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error("incomplete write"); 16328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 16428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 16528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 16628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 16728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 16828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 16928fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void file_close(struct output_file *out) 17028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 171b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_normal *outn = to_output_file_normal(out); 172b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 173b4cd267db30c152245e6308598e0066d87c5c55dColin Cross free(outn); 17428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 17528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 17628fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic struct output_file_ops file_ops = { 177b4cd267db30c152245e6308598e0066d87c5c55dColin Cross .open = file_open, 178b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .skip = file_skip, 179b4cd267db30c152245e6308598e0066d87c5c55dColin Cross .pad = file_pad, 18028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross .write = file_write, 18128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross .close = file_close, 18228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}; 18328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 184b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic int gz_file_open(struct output_file *out, int fd) 185b4cd267db30c152245e6308598e0066d87c5c55dColin Cross{ 186b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_gz *outgz = to_output_file_gz(out); 187b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 188b4cd267db30c152245e6308598e0066d87c5c55dColin Cross outgz->gz_fd = gzdopen(fd, "wb9"); 189b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (!outgz->gz_fd) { 190b4cd267db30c152245e6308598e0066d87c5c55dColin Cross error_errno("gzopen"); 191b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return -errno; 192b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 193b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 194b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return 0; 195b4cd267db30c152245e6308598e0066d87c5c55dColin Cross} 196b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 197b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 198b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int gz_file_skip(struct output_file *out, int64_t cnt) 19928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 20028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross off64_t ret; 201b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_gz *outgz = to_output_file_gz(out); 20228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 203b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = gzseek(outgz->gz_fd, cnt, SEEK_CUR); 20428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) { 20528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("gzseek"); 20628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 20728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 20828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 20928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 21028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 211b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic int gz_file_pad(struct output_file *out, int64_t len) 212b4cd267db30c152245e6308598e0066d87c5c55dColin Cross{ 213b4cd267db30c152245e6308598e0066d87c5c55dColin Cross off64_t ret; 214b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_gz *outgz = to_output_file_gz(out); 215b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 216b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = gztell(outgz->gz_fd); 217b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (ret < 0) { 218b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return -1; 219b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 220b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 221b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (ret >= len) { 222b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return 0; 223b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 224b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 225b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = gzseek(outgz->gz_fd, len - 1, SEEK_SET); 226b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (ret < 0) { 227b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return -1; 228b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 229b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 230b4cd267db30c152245e6308598e0066d87c5c55dColin Cross gzwrite(outgz->gz_fd, "", 1); 231b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 232b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return 0; 233b4cd267db30c152245e6308598e0066d87c5c55dColin Cross} 234b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 235b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int gz_file_write(struct output_file *out, void *data, int len) 23628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 23728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 238b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_gz *outgz = to_output_file_gz(out); 239b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 240b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = gzwrite(outgz->gz_fd, data, len); 24128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) { 24228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("gzwrite"); 24328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 24428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } else if (ret < len) { 24528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error("incomplete gzwrite"); 24628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 24728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 24828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 24928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 25028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 25128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 25228fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void gz_file_close(struct output_file *out) 25328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 254b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_gz *outgz = to_output_file_gz(out); 255b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 256b4cd267db30c152245e6308598e0066d87c5c55dColin Cross gzclose(outgz->gz_fd); 257b4cd267db30c152245e6308598e0066d87c5c55dColin Cross free(outgz); 25828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 25928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 26028fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic struct output_file_ops gz_file_ops = { 261b4cd267db30c152245e6308598e0066d87c5c55dColin Cross .open = gz_file_open, 262b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .skip = gz_file_skip, 263b4cd267db30c152245e6308598e0066d87c5c55dColin Cross .pad = gz_file_pad, 26428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross .write = gz_file_write, 26528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross .close = gz_file_close, 26628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}; 26728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 268031a748b2a9bf6dcfd3983d8f0f616718fcddd88Mark Salyzynstatic int callback_file_open(struct output_file *out __unused, int fd __unused) 2691e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 2701e17b313a6257b7b5081e178e81435c09d60378eColin Cross return 0; 2711e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 2721e17b313a6257b7b5081e178e81435c09d60378eColin Cross 2731e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic int callback_file_skip(struct output_file *out, int64_t off) 2741e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 2751e17b313a6257b7b5081e178e81435c09d60378eColin Cross struct output_file_callback *outc = to_output_file_callback(out); 2761e17b313a6257b7b5081e178e81435c09d60378eColin Cross int to_write; 2771e17b313a6257b7b5081e178e81435c09d60378eColin Cross int ret; 2781e17b313a6257b7b5081e178e81435c09d60378eColin Cross 2791e17b313a6257b7b5081e178e81435c09d60378eColin Cross while (off > 0) { 2801e17b313a6257b7b5081e178e81435c09d60378eColin Cross to_write = min(off, (int64_t)INT_MAX); 2811e17b313a6257b7b5081e178e81435c09d60378eColin Cross ret = outc->write(outc->priv, NULL, to_write); 2821e17b313a6257b7b5081e178e81435c09d60378eColin Cross if (ret < 0) { 2831e17b313a6257b7b5081e178e81435c09d60378eColin Cross return ret; 2841e17b313a6257b7b5081e178e81435c09d60378eColin Cross } 2851e17b313a6257b7b5081e178e81435c09d60378eColin Cross off -= to_write; 2861e17b313a6257b7b5081e178e81435c09d60378eColin Cross } 2871e17b313a6257b7b5081e178e81435c09d60378eColin Cross 2881e17b313a6257b7b5081e178e81435c09d60378eColin Cross return 0; 2891e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 2901e17b313a6257b7b5081e178e81435c09d60378eColin Cross 291031a748b2a9bf6dcfd3983d8f0f616718fcddd88Mark Salyzynstatic int callback_file_pad(struct output_file *out __unused, int64_t len __unused) 2921e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 2931e17b313a6257b7b5081e178e81435c09d60378eColin Cross return -1; 2941e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 2951e17b313a6257b7b5081e178e81435c09d60378eColin Cross 2961e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic int callback_file_write(struct output_file *out, void *data, int len) 2971e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 2981e17b313a6257b7b5081e178e81435c09d60378eColin Cross struct output_file_callback *outc = to_output_file_callback(out); 2991e17b313a6257b7b5081e178e81435c09d60378eColin Cross 3001e17b313a6257b7b5081e178e81435c09d60378eColin Cross return outc->write(outc->priv, data, len); 3011e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 3021e17b313a6257b7b5081e178e81435c09d60378eColin Cross 3031e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic void callback_file_close(struct output_file *out) 3041e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 3051e17b313a6257b7b5081e178e81435c09d60378eColin Cross struct output_file_callback *outc = to_output_file_callback(out); 3061e17b313a6257b7b5081e178e81435c09d60378eColin Cross 3071e17b313a6257b7b5081e178e81435c09d60378eColin Cross free(outc); 3081e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 3091e17b313a6257b7b5081e178e81435c09d60378eColin Cross 3101e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic struct output_file_ops callback_file_ops = { 3111e17b313a6257b7b5081e178e81435c09d60378eColin Cross .open = callback_file_open, 3121e17b313a6257b7b5081e178e81435c09d60378eColin Cross .skip = callback_file_skip, 3131e17b313a6257b7b5081e178e81435c09d60378eColin Cross .pad = callback_file_pad, 3141e17b313a6257b7b5081e178e81435c09d60378eColin Cross .write = callback_file_write, 3151e17b313a6257b7b5081e178e81435c09d60378eColin Cross .close = callback_file_close, 3161e17b313a6257b7b5081e178e81435c09d60378eColin Cross}; 3171e17b313a6257b7b5081e178e81435c09d60378eColin Cross 31813a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Crossint read_all(int fd, void *buf, size_t len) 31913a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross{ 32013a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross size_t total = 0; 32113a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross int ret; 32213a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross char *ptr = buf; 32313a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross 32413a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross while (total < len) { 32513a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross ret = read(fd, ptr, len - total); 32613a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross 32713a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross if (ret < 0) 32813a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross return -errno; 32913a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross 33013a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross if (ret == 0) 33113a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross return -EINVAL; 33213a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross 33313a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross ptr += ret; 33413a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross total += ret; 33513a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross } 33613a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross 33713a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross return 0; 33813a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross} 33913a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross 340b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_sparse_skip_chunk(struct output_file *out, int64_t skip_len) 34128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 34228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header_t chunk_header; 3438116c8c37aadd83033ffea9e4f5fc86240428e43Mark Salyzyn int ret; 34428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 34528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (skip_len % out->block_size) { 346ccecf1425412beb2bc3bb38d470293fdc244d6f1Elliott Hughes error("don't care size %"PRIi64" is not a multiple of the block size %u", 34728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross skip_len, out->block_size); 34828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 34928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 35028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 35128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross /* We are skipping data, so emit a don't care chunk. */ 35228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_type = CHUNK_TYPE_DONT_CARE; 35328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.reserved1 = 0; 35428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_sz = skip_len / out->block_size; 35528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.total_sz = CHUNK_HEADER_LEN; 356b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &chunk_header, sizeof(chunk_header)); 35728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 35828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 35928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 36028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->cur_out_ptr += skip_len; 36128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->chunk_cnt++; 36228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 36328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 36428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 36528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 366b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_sparse_fill_chunk(struct output_file *out, unsigned int len, 367b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t fill_val) 36828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 36928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header_t chunk_header; 3708116c8c37aadd83033ffea9e4f5fc86240428e43Mark Salyzyn int rnd_up_len, count; 37128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 37228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 373b55dceea986ab24f8b836b5116b389ed619c816eColin Cross /* Round up the fill length to a multiple of the block size */ 374b55dceea986ab24f8b836b5116b389ed619c816eColin Cross rnd_up_len = ALIGN(len, out->block_size); 37528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 37628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross /* Finally we can safely emit a chunk of data */ 37728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_type = CHUNK_TYPE_FILL; 37828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.reserved1 = 0; 37928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_sz = rnd_up_len / out->block_size; 38028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.total_sz = CHUNK_HEADER_LEN + sizeof(fill_val); 381b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &chunk_header, sizeof(chunk_header)); 38228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 38328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 38428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 385b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &fill_val, sizeof(fill_val)); 38628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 38728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 38828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 38928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (out->use_crc) { 390b55dceea986ab24f8b836b5116b389ed619c816eColin Cross count = out->block_size / sizeof(uint32_t); 391b55dceea986ab24f8b836b5116b389ed619c816eColin Cross while (count--) 392b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->crc32 = sparse_crc32(out->crc32, &fill_val, sizeof(uint32_t)); 39328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 39428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 39528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->cur_out_ptr += rnd_up_len; 39628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->chunk_cnt++; 39728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 39828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 39928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 40028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 401b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_sparse_data_chunk(struct output_file *out, unsigned int len, 402b55dceea986ab24f8b836b5116b389ed619c816eColin Cross void *data) 40328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 40428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header_t chunk_header; 40528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int rnd_up_len, zero_len; 40628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 40728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 408b55dceea986ab24f8b836b5116b389ed619c816eColin Cross /* Round up the data length to a multiple of the block size */ 409b55dceea986ab24f8b836b5116b389ed619c816eColin Cross rnd_up_len = ALIGN(len, out->block_size); 41028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross zero_len = rnd_up_len - len; 41128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 41228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross /* Finally we can safely emit a chunk of data */ 41328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_type = CHUNK_TYPE_RAW; 41428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.reserved1 = 0; 41528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_sz = rnd_up_len / out->block_size; 41628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.total_sz = CHUNK_HEADER_LEN + rnd_up_len; 417b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &chunk_header, sizeof(chunk_header)); 41828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 41928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 42028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 42128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross ret = out->ops->write(out, data, len); 42228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 42328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 42428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (zero_len) { 425b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, out->zero_buf, zero_len); 42628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 42728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 42828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 42928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 43028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (out->use_crc) { 43128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->crc32 = sparse_crc32(out->crc32, data, len); 43228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (zero_len) 433b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->crc32 = sparse_crc32(out->crc32, out->zero_buf, zero_len); 43428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 43528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 43628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->cur_out_ptr += rnd_up_len; 43728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->chunk_cnt++; 43828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 43928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 44028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 44128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 442b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_sparse_end_chunk(struct output_file *out) 44328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 44428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header_t chunk_header; 445b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int ret; 44628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 447b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (out->use_crc) { 448b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunk_header.chunk_type = CHUNK_TYPE_CRC32; 449b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunk_header.reserved1 = 0; 450b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunk_header.chunk_sz = 0; 451b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunk_header.total_sz = CHUNK_HEADER_LEN + 4; 452b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 453b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &chunk_header, sizeof(chunk_header)); 454b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 455b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 456b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 457b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->ops->write(out, &out->crc32, 4); 458b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 459b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 460b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 461b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 462b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->chunk_cnt++; 463b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 464b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 465b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return 0; 466b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 467b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 468b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic struct sparse_file_ops sparse_file_ops = { 469b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_data_chunk = write_sparse_data_chunk, 470b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_fill_chunk = write_sparse_fill_chunk, 471b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_skip_chunk = write_sparse_skip_chunk, 472b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_end_chunk = write_sparse_end_chunk, 473b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}; 474b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 475b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_normal_data_chunk(struct output_file *out, unsigned int len, 476b55dceea986ab24f8b836b5116b389ed619c816eColin Cross void *data) 477b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 478b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int ret; 479b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int rnd_up_len = ALIGN(len, out->block_size); 480b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 481b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, data, len); 482b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 483b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 484b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 485b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 486b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (rnd_up_len > len) { 487b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->skip(out, rnd_up_len - len); 488b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 48928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 490b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 491b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 492b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 493b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_normal_fill_chunk(struct output_file *out, unsigned int len, 494b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t fill_val) 495b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 496b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int ret; 497b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int i; 498b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int write_len; 49928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 500b55dceea986ab24f8b836b5116b389ed619c816eColin Cross /* Initialize fill_buf with the fill_val */ 501b55dceea986ab24f8b836b5116b389ed619c816eColin Cross for (i = 0; i < out->block_size / sizeof(uint32_t); i++) { 502b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->fill_buf[i] = fill_val; 503b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 504b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 505b55dceea986ab24f8b836b5116b389ed619c816eColin Cross while (len) { 506b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_len = min(len, out->block_size); 507b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, out->fill_buf, write_len); 508b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 509b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 51028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 51128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 512b55dceea986ab24f8b836b5116b389ed619c816eColin Cross len -= write_len; 513b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 514b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 515b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return 0; 516b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 517b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 518b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_normal_skip_chunk(struct output_file *out, int64_t len) 519b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 520b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return out->ops->skip(out, len); 521b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 522b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 523b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_normal_end_chunk(struct output_file *out) 524b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 525b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return out->ops->pad(out, out->len); 526b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 527b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 528b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic struct sparse_file_ops normal_file_ops = { 529b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_data_chunk = write_normal_data_chunk, 530b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_fill_chunk = write_normal_fill_chunk, 531b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_skip_chunk = write_normal_skip_chunk, 532b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_end_chunk = write_normal_end_chunk, 533b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}; 534b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 535b43828b247fd4f1e0373584de0504004c69eeac9Colin Crossvoid output_file_close(struct output_file *out) 536b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 537b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->sparse_ops->write_end_chunk(out); 53828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->ops->close(out); 53928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 54028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 541b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic int output_file_init(struct output_file *out, int block_size, 542b4cd267db30c152245e6308598e0066d87c5c55dColin Cross int64_t len, bool sparse, int chunks, bool crc) 54328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 54428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 545b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 546b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->len = len; 547b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->block_size = block_size; 548b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->cur_out_ptr = 0ll; 549b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->chunk_cnt = 0; 550b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->crc32 = 0; 551b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->use_crc = crc; 552b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 553b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->zero_buf = calloc(block_size, 1); 554b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (!out->zero_buf) { 55528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("malloc zero_buf"); 556b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return -ENOMEM; 557b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 558b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 559b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->fill_buf = calloc(block_size, 1); 560b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (!out->fill_buf) { 561b55dceea986ab24f8b836b5116b389ed619c816eColin Cross error_errno("malloc fill_buf"); 562b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = -ENOMEM; 563b55dceea986ab24f8b836b5116b389ed619c816eColin Cross goto err_fill_buf; 56428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 56528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 566b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (sparse) { 567b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->sparse_ops = &sparse_file_ops; 568b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } else { 569b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->sparse_ops = &normal_file_ops; 570b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 571b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 572b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (sparse) { 573b55dceea986ab24f8b836b5116b389ed619c816eColin Cross sparse_header_t sparse_header = { 574b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .magic = SPARSE_HEADER_MAGIC, 575b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .major_version = SPARSE_HEADER_MAJOR_VER, 576b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .minor_version = SPARSE_HEADER_MINOR_VER, 577b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .file_hdr_sz = SPARSE_HEADER_LEN, 578b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .chunk_hdr_sz = CHUNK_HEADER_LEN, 579b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .blk_sz = out->block_size, 580b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .total_blks = out->len / out->block_size, 581b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .total_chunks = chunks, 582b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .image_checksum = 0 583b55dceea986ab24f8b836b5116b389ed619c816eColin Cross }; 584b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 585b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (out->use_crc) { 58628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross sparse_header.total_chunks++; 587b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 58828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 589b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &sparse_header, sizeof(sparse_header)); 590b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 591b55dceea986ab24f8b836b5116b389ed619c816eColin Cross goto err_write; 592b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 59328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 59428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 595b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return 0; 596b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 597b55dceea986ab24f8b836b5116b389ed619c816eColin Crosserr_write: 598b55dceea986ab24f8b836b5116b389ed619c816eColin Cross free(out->fill_buf); 599b55dceea986ab24f8b836b5116b389ed619c816eColin Crosserr_fill_buf: 600b55dceea986ab24f8b836b5116b389ed619c816eColin Cross free(out->zero_buf); 601b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return ret; 602b4cd267db30c152245e6308598e0066d87c5c55dColin Cross} 603b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 604b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic struct output_file *output_file_new_gz(void) 605b4cd267db30c152245e6308598e0066d87c5c55dColin Cross{ 606b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_gz *outgz = calloc(1, sizeof(struct output_file_gz)); 607b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (!outgz) { 608b4cd267db30c152245e6308598e0066d87c5c55dColin Cross error_errno("malloc struct outgz"); 609b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return NULL; 610b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 611b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 612b4cd267db30c152245e6308598e0066d87c5c55dColin Cross outgz->out.ops = &gz_file_ops; 613b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 614b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return &outgz->out; 615b4cd267db30c152245e6308598e0066d87c5c55dColin Cross} 616b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 617b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic struct output_file *output_file_new_normal(void) 618b4cd267db30c152245e6308598e0066d87c5c55dColin Cross{ 619b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_normal *outn = calloc(1, sizeof(struct output_file_normal)); 620b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (!outn) { 621b4cd267db30c152245e6308598e0066d87c5c55dColin Cross error_errno("malloc struct outn"); 622b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return NULL; 623b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 624b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 625b4cd267db30c152245e6308598e0066d87c5c55dColin Cross outn->out.ops = &file_ops; 626b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 627b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return &outn->out; 62828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 62928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 630b43828b247fd4f1e0373584de0504004c69eeac9Colin Crossstruct output_file *output_file_open_callback(int (*write)(void *, const void *, int), 631031a748b2a9bf6dcfd3983d8f0f616718fcddd88Mark Salyzyn void *priv, unsigned int block_size, int64_t len, 632031a748b2a9bf6dcfd3983d8f0f616718fcddd88Mark Salyzyn int gz __unused, int sparse, int chunks, int crc) 6331e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 6341e17b313a6257b7b5081e178e81435c09d60378eColin Cross int ret; 6351e17b313a6257b7b5081e178e81435c09d60378eColin Cross struct output_file_callback *outc; 6361e17b313a6257b7b5081e178e81435c09d60378eColin Cross 6371e17b313a6257b7b5081e178e81435c09d60378eColin Cross outc = calloc(1, sizeof(struct output_file_callback)); 6381e17b313a6257b7b5081e178e81435c09d60378eColin Cross if (!outc) { 6391e17b313a6257b7b5081e178e81435c09d60378eColin Cross error_errno("malloc struct outc"); 6401e17b313a6257b7b5081e178e81435c09d60378eColin Cross return NULL; 6411e17b313a6257b7b5081e178e81435c09d60378eColin Cross } 6421e17b313a6257b7b5081e178e81435c09d60378eColin Cross 6431e17b313a6257b7b5081e178e81435c09d60378eColin Cross outc->out.ops = &callback_file_ops; 6441e17b313a6257b7b5081e178e81435c09d60378eColin Cross outc->priv = priv; 6451e17b313a6257b7b5081e178e81435c09d60378eColin Cross outc->write = write; 6461e17b313a6257b7b5081e178e81435c09d60378eColin Cross 6471e17b313a6257b7b5081e178e81435c09d60378eColin Cross ret = output_file_init(&outc->out, block_size, len, sparse, chunks, crc); 6481e17b313a6257b7b5081e178e81435c09d60378eColin Cross if (ret < 0) { 6491e17b313a6257b7b5081e178e81435c09d60378eColin Cross free(outc); 6501e17b313a6257b7b5081e178e81435c09d60378eColin Cross return NULL; 6511e17b313a6257b7b5081e178e81435c09d60378eColin Cross } 6521e17b313a6257b7b5081e178e81435c09d60378eColin Cross 6531e17b313a6257b7b5081e178e81435c09d60378eColin Cross return &outc->out; 6541e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 6551e17b313a6257b7b5081e178e81435c09d60378eColin Cross 656b43828b247fd4f1e0373584de0504004c69eeac9Colin Crossstruct output_file *output_file_open_fd(int fd, unsigned int block_size, int64_t len, 65728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int gz, int sparse, int chunks, int crc) 65828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 659b4cd267db30c152245e6308598e0066d87c5c55dColin Cross int ret; 660b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file *out; 66128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 662b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (gz) { 663b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out = output_file_new_gz(); 66428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } else { 665b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out = output_file_new_normal(); 66628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 66783a6d36d4226f82c202ffb27f89e080f95b71c30Hong-Mei Li if (!out) { 66883a6d36d4226f82c202ffb27f89e080f95b71c30Hong-Mei Li return NULL; 66983a6d36d4226f82c202ffb27f89e080f95b71c30Hong-Mei Li } 67028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 671b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->ops->open(out, fd); 672b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 673b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = output_file_init(out, block_size, len, sparse, chunks, crc); 674b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (ret < 0) { 675b4cd267db30c152245e6308598e0066d87c5c55dColin Cross free(out); 67628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return NULL; 67728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 67828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 679b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return out; 68028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 68128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 68228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* Write a contiguous region of data blocks from a memory buffer */ 683b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_data_chunk(struct output_file *out, unsigned int len, void *data) 68428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 685b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return out->sparse_ops->write_data_chunk(out, len, data); 68628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 68728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 68828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* Write a contiguous region of data blocks with a fill value */ 689b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_fill_chunk(struct output_file *out, unsigned int len, 690b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t fill_val) 69128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 692b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return out->sparse_ops->write_fill_chunk(out, len, fill_val); 69328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 69428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 6959e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Crossint write_fd_chunk(struct output_file *out, unsigned int len, 6969e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross int fd, int64_t offset) 69728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 69828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 69928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int64_t aligned_offset; 70028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int aligned_diff; 70128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int buffer_size; 70213a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross char *ptr; 70328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 70428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross aligned_offset = offset & ~(4096 - 1); 70528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross aligned_diff = offset - aligned_offset; 70628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross buffer_size = len + aligned_diff; 70728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 70828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifndef USE_MINGW 7099e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross char *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, fd, 71028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross aligned_offset); 71128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (data == MAP_FAILED) { 7129e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return -errno; 71328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 71413a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross ptr = data + aligned_diff; 71528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#else 71613a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross off64_t pos; 71713a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross char *data = malloc(len); 71828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (!data) { 7199e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return -errno; 72028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 72113a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross pos = lseek64(fd, offset, SEEK_SET); 72213a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross if (pos < 0) { 72314e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes free(data); 72413a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross return -errno; 72513a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross } 72613a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross ret = read_all(fd, data, len); 72713a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross if (ret < 0) { 72814e28d39f7f094225c1ddae8fa43bd792c621a8fElliott Hughes free(data); 72913a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross return ret; 73013a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross } 73113a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross ptr = data; 73228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 73328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 73413a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross ret = out->sparse_ops->write_data_chunk(out, len, ptr); 73528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 73628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifndef USE_MINGW 73728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross munmap(data, buffer_size); 73828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#else 73928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross free(data); 74028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 7419e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 7429e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return ret; 7439e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross} 7449e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 7459e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross/* Write a contiguous region of data blocks from a file */ 7469e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Crossint write_file_chunk(struct output_file *out, unsigned int len, 7479e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross const char *file, int64_t offset) 7489e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross{ 7499e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross int ret; 7509e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 7519e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross int file_fd = open(file, O_RDONLY | O_BINARY); 7529e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross if (file_fd < 0) { 7539e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return -errno; 7549e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross } 7559e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 7569e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross ret = write_fd_chunk(out, len, file_fd, offset); 7579e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 75828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross close(file_fd); 759b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 760b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 761b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 762b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 763b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_skip_chunk(struct output_file *out, int64_t len) 764b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 765b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return out->sparse_ops->write_skip_chunk(out, len); 76628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 767