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> 211e17b313a6257b7b5081e178e81435c09d60378eColin Cross#include <limits.h> 2228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <stdbool.h> 23b4cd267db30c152245e6308598e0066d87c5c55dColin Cross#include <stddef.h> 2428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <stdlib.h> 2528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <string.h> 2628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sys/stat.h> 2728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sys/types.h> 2828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <unistd.h> 2928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <zlib.h> 3028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 3128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "output_file.h" 3228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_format.h" 3328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_crc32.h" 3428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 3528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifndef USE_MINGW 3628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sys/mman.h> 3728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define O_BINARY 0 38b4cd267db30c152245e6308598e0066d87c5c55dColin Cross#else 39b4cd267db30c152245e6308598e0066d87c5c55dColin Cross#define ftruncate64 ftruncate 4028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 4128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 4228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#if defined(__APPLE__) && defined(__MACH__) 4328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define lseek64 lseek 4428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define ftruncate64 ftruncate 4528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define mmap64 mmap 4628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define off64_t off_t 4728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 4828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 4928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifdef __BIONIC__ 5028fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossextern void* __mmap2(void *, size_t, int, int, int, off_t); 5128fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic inline void *mmap64(void *addr, size_t length, int prot, int flags, 5228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int fd, off64_t offset) 5328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 5428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return __mmap2(addr, length, prot, flags, fd, offset >> 12); 5528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 5628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 5728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 58b55dceea986ab24f8b836b5116b389ed619c816eColin Cross#define min(a, b) \ 59b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ({ typeof(a) _a = (a); typeof(b) _b = (b); (_a < _b) ? _a : _b; }) 60b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 6128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define SPARSE_HEADER_MAJOR_VER 1 6228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define SPARSE_HEADER_MINOR_VER 0 6328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define SPARSE_HEADER_LEN (sizeof(sparse_header_t)) 6428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define CHUNK_HEADER_LEN (sizeof(chunk_header_t)) 6528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 66b4cd267db30c152245e6308598e0066d87c5c55dColin Cross#define container_of(inner, outer_t, elem) \ 67b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ((outer_t *)((char *)inner - offsetof(outer_t, elem))) 68b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 6928fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct output_file_ops { 70b4cd267db30c152245e6308598e0066d87c5c55dColin Cross int (*open)(struct output_file *, int fd); 71b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*skip)(struct output_file *, int64_t); 72b4cd267db30c152245e6308598e0066d87c5c55dColin Cross int (*pad)(struct output_file *, int64_t); 73b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write)(struct output_file *, void *, int); 7428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross void (*close)(struct output_file *); 7528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}; 7628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 77b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstruct sparse_file_ops { 78b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write_data_chunk)(struct output_file *out, unsigned int len, 79b55dceea986ab24f8b836b5116b389ed619c816eColin Cross void *data); 80b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write_fill_chunk)(struct output_file *out, unsigned int len, 81b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t fill_val); 82b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write_skip_chunk)(struct output_file *out, int64_t len); 83b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write_end_chunk)(struct output_file *out); 84b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}; 85b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 8628fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct output_file { 8728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int64_t cur_out_ptr; 88b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int chunk_cnt; 89b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t crc32; 9028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross struct output_file_ops *ops; 91b55dceea986ab24f8b836b5116b389ed619c816eColin Cross struct sparse_file_ops *sparse_ops; 9228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int use_crc; 9328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross unsigned int block_size; 9428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int64_t len; 95b55dceea986ab24f8b836b5116b389ed619c816eColin Cross char *zero_buf; 96b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t *fill_buf; 97b4cd267db30c152245e6308598e0066d87c5c55dColin Cross char *buf; 98b4cd267db30c152245e6308598e0066d87c5c55dColin Cross}; 99b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 100b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstruct output_file_gz { 101b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file out; 102b4cd267db30c152245e6308598e0066d87c5c55dColin Cross gzFile gz_fd; 103b4cd267db30c152245e6308598e0066d87c5c55dColin Cross}; 104b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 105b4cd267db30c152245e6308598e0066d87c5c55dColin Cross#define to_output_file_gz(_o) \ 106b4cd267db30c152245e6308598e0066d87c5c55dColin Cross container_of((_o), struct output_file_gz, out) 107b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 108b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstruct output_file_normal { 109b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file out; 110b4cd267db30c152245e6308598e0066d87c5c55dColin Cross int fd; 11128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}; 11228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 113b4cd267db30c152245e6308598e0066d87c5c55dColin Cross#define to_output_file_normal(_o) \ 114b4cd267db30c152245e6308598e0066d87c5c55dColin Cross container_of((_o), struct output_file_normal, out) 115b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 1161e17b313a6257b7b5081e178e81435c09d60378eColin Crossstruct output_file_callback { 1171e17b313a6257b7b5081e178e81435c09d60378eColin Cross struct output_file out; 1181e17b313a6257b7b5081e178e81435c09d60378eColin Cross void *priv; 1191e17b313a6257b7b5081e178e81435c09d60378eColin Cross int (*write)(void *priv, const void *buf, int len); 1201e17b313a6257b7b5081e178e81435c09d60378eColin Cross}; 1211e17b313a6257b7b5081e178e81435c09d60378eColin Cross 1221e17b313a6257b7b5081e178e81435c09d60378eColin Cross#define to_output_file_callback(_o) \ 1231e17b313a6257b7b5081e178e81435c09d60378eColin Cross container_of((_o), struct output_file_callback, out) 1241e17b313a6257b7b5081e178e81435c09d60378eColin Cross 125b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic int file_open(struct output_file *out, int fd) 126b4cd267db30c152245e6308598e0066d87c5c55dColin Cross{ 127b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_normal *outn = to_output_file_normal(out); 128b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 129b4cd267db30c152245e6308598e0066d87c5c55dColin Cross outn->fd = fd; 130b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return 0; 131b4cd267db30c152245e6308598e0066d87c5c55dColin Cross} 132b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 133b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int file_skip(struct output_file *out, int64_t cnt) 13428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 13528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross off64_t ret; 136b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_normal *outn = to_output_file_normal(out); 13728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 138b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = lseek64(outn->fd, cnt, SEEK_CUR); 13928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) { 14028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("lseek64"); 14128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 14228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 14328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 14428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 14528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 146b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic int file_pad(struct output_file *out, int64_t len) 147b4cd267db30c152245e6308598e0066d87c5c55dColin Cross{ 148b4cd267db30c152245e6308598e0066d87c5c55dColin Cross int ret; 149b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_normal *outn = to_output_file_normal(out); 150b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 151b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = ftruncate64(outn->fd, len); 152b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (ret < 0) { 153b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return -errno; 154b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 155b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 156b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return 0; 157b4cd267db30c152245e6308598e0066d87c5c55dColin Cross} 158b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 159b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int file_write(struct output_file *out, void *data, int len) 16028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 16128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 162b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_normal *outn = to_output_file_normal(out); 163b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 164b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = write(outn->fd, data, len); 16528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) { 16628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("write"); 16728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 16828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } else if (ret < len) { 16928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error("incomplete write"); 17028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 17128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 17228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 17328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 17428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 17528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 17628fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void file_close(struct output_file *out) 17728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 178b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_normal *outn = to_output_file_normal(out); 179b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 180b4cd267db30c152245e6308598e0066d87c5c55dColin Cross free(outn); 18128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 18228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 18328fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic struct output_file_ops file_ops = { 184b4cd267db30c152245e6308598e0066d87c5c55dColin Cross .open = file_open, 185b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .skip = file_skip, 186b4cd267db30c152245e6308598e0066d87c5c55dColin Cross .pad = file_pad, 18728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross .write = file_write, 18828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross .close = file_close, 18928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}; 19028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 191b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic int gz_file_open(struct output_file *out, int fd) 192b4cd267db30c152245e6308598e0066d87c5c55dColin Cross{ 193b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_gz *outgz = to_output_file_gz(out); 194b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 195b4cd267db30c152245e6308598e0066d87c5c55dColin Cross outgz->gz_fd = gzdopen(fd, "wb9"); 196b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (!outgz->gz_fd) { 197b4cd267db30c152245e6308598e0066d87c5c55dColin Cross error_errno("gzopen"); 198b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return -errno; 199b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 200b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 201b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return 0; 202b4cd267db30c152245e6308598e0066d87c5c55dColin Cross} 203b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 204b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 205b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int gz_file_skip(struct output_file *out, int64_t cnt) 20628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 20728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross off64_t ret; 208b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_gz *outgz = to_output_file_gz(out); 20928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 210b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = gzseek(outgz->gz_fd, cnt, SEEK_CUR); 21128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) { 21228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("gzseek"); 21328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 21428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 21528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 21628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 21728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 218b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic int gz_file_pad(struct output_file *out, int64_t len) 219b4cd267db30c152245e6308598e0066d87c5c55dColin Cross{ 220b4cd267db30c152245e6308598e0066d87c5c55dColin Cross off64_t ret; 221b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_gz *outgz = to_output_file_gz(out); 222b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 223b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = gztell(outgz->gz_fd); 224b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (ret < 0) { 225b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return -1; 226b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 227b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 228b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (ret >= len) { 229b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return 0; 230b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 231b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 232b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = gzseek(outgz->gz_fd, len - 1, SEEK_SET); 233b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (ret < 0) { 234b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return -1; 235b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 236b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 237b4cd267db30c152245e6308598e0066d87c5c55dColin Cross gzwrite(outgz->gz_fd, "", 1); 238b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 239b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return 0; 240b4cd267db30c152245e6308598e0066d87c5c55dColin Cross} 241b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 242b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int gz_file_write(struct output_file *out, void *data, int len) 24328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 24428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 245b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_gz *outgz = to_output_file_gz(out); 246b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 247b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = gzwrite(outgz->gz_fd, data, len); 24828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) { 24928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("gzwrite"); 25028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 25128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } else if (ret < len) { 25228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error("incomplete gzwrite"); 25328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 25428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 25528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 25628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 25728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 25828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 25928fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void gz_file_close(struct output_file *out) 26028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 261b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_gz *outgz = to_output_file_gz(out); 262b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 263b4cd267db30c152245e6308598e0066d87c5c55dColin Cross gzclose(outgz->gz_fd); 264b4cd267db30c152245e6308598e0066d87c5c55dColin Cross free(outgz); 26528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 26628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 26728fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic struct output_file_ops gz_file_ops = { 268b4cd267db30c152245e6308598e0066d87c5c55dColin Cross .open = gz_file_open, 269b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .skip = gz_file_skip, 270b4cd267db30c152245e6308598e0066d87c5c55dColin Cross .pad = gz_file_pad, 27128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross .write = gz_file_write, 27228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross .close = gz_file_close, 27328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}; 27428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 2751e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic int callback_file_open(struct output_file *out, int fd) 2761e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 2771e17b313a6257b7b5081e178e81435c09d60378eColin Cross return 0; 2781e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 2791e17b313a6257b7b5081e178e81435c09d60378eColin Cross 2801e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic int callback_file_skip(struct output_file *out, int64_t off) 2811e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 2821e17b313a6257b7b5081e178e81435c09d60378eColin Cross struct output_file_callback *outc = to_output_file_callback(out); 2831e17b313a6257b7b5081e178e81435c09d60378eColin Cross int to_write; 2841e17b313a6257b7b5081e178e81435c09d60378eColin Cross int ret; 2851e17b313a6257b7b5081e178e81435c09d60378eColin Cross 2861e17b313a6257b7b5081e178e81435c09d60378eColin Cross while (off > 0) { 2871e17b313a6257b7b5081e178e81435c09d60378eColin Cross to_write = min(off, (int64_t)INT_MAX); 2881e17b313a6257b7b5081e178e81435c09d60378eColin Cross ret = outc->write(outc->priv, NULL, to_write); 2891e17b313a6257b7b5081e178e81435c09d60378eColin Cross if (ret < 0) { 2901e17b313a6257b7b5081e178e81435c09d60378eColin Cross return ret; 2911e17b313a6257b7b5081e178e81435c09d60378eColin Cross } 2921e17b313a6257b7b5081e178e81435c09d60378eColin Cross off -= to_write; 2931e17b313a6257b7b5081e178e81435c09d60378eColin Cross } 2941e17b313a6257b7b5081e178e81435c09d60378eColin Cross 2951e17b313a6257b7b5081e178e81435c09d60378eColin Cross return 0; 2961e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 2971e17b313a6257b7b5081e178e81435c09d60378eColin Cross 2981e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic int callback_file_pad(struct output_file *out, int64_t len) 2991e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 3001e17b313a6257b7b5081e178e81435c09d60378eColin Cross return -1; 3011e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 3021e17b313a6257b7b5081e178e81435c09d60378eColin Cross 3031e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic int callback_file_write(struct output_file *out, void *data, int len) 3041e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 3051e17b313a6257b7b5081e178e81435c09d60378eColin Cross int ret; 3061e17b313a6257b7b5081e178e81435c09d60378eColin Cross struct output_file_callback *outc = to_output_file_callback(out); 3071e17b313a6257b7b5081e178e81435c09d60378eColin Cross 3081e17b313a6257b7b5081e178e81435c09d60378eColin Cross return outc->write(outc->priv, data, len); 3091e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 3101e17b313a6257b7b5081e178e81435c09d60378eColin Cross 3111e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic void callback_file_close(struct output_file *out) 3121e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 3131e17b313a6257b7b5081e178e81435c09d60378eColin Cross struct output_file_callback *outc = to_output_file_callback(out); 3141e17b313a6257b7b5081e178e81435c09d60378eColin Cross 3151e17b313a6257b7b5081e178e81435c09d60378eColin Cross free(outc); 3161e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 3171e17b313a6257b7b5081e178e81435c09d60378eColin Cross 3181e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic struct output_file_ops callback_file_ops = { 3191e17b313a6257b7b5081e178e81435c09d60378eColin Cross .open = callback_file_open, 3201e17b313a6257b7b5081e178e81435c09d60378eColin Cross .skip = callback_file_skip, 3211e17b313a6257b7b5081e178e81435c09d60378eColin Cross .pad = callback_file_pad, 3221e17b313a6257b7b5081e178e81435c09d60378eColin Cross .write = callback_file_write, 3231e17b313a6257b7b5081e178e81435c09d60378eColin Cross .close = callback_file_close, 3241e17b313a6257b7b5081e178e81435c09d60378eColin Cross}; 3251e17b313a6257b7b5081e178e81435c09d60378eColin Cross 32613a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Crossint read_all(int fd, void *buf, size_t len) 32713a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross{ 32813a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross size_t total = 0; 32913a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross int ret; 33013a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross char *ptr = buf; 33113a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross 33213a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross while (total < len) { 33313a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross ret = read(fd, ptr, len - total); 33413a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross 33513a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross if (ret < 0) 33613a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross return -errno; 33713a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross 33813a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross if (ret == 0) 33913a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross return -EINVAL; 34013a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross 34113a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross ptr += ret; 34213a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross total += ret; 34313a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross } 34413a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross 34513a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross return 0; 34613a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross} 34713a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross 348b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_sparse_skip_chunk(struct output_file *out, int64_t skip_len) 34928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 35028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header_t chunk_header; 35128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret, chunk; 35228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 35328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (skip_len % out->block_size) { 35428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error("don't care size %llu is not a multiple of the block size %u", 35528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross skip_len, out->block_size); 35628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 35728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 35828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 35928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross /* We are skipping data, so emit a don't care chunk. */ 36028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_type = CHUNK_TYPE_DONT_CARE; 36128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.reserved1 = 0; 36228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_sz = skip_len / out->block_size; 36328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.total_sz = CHUNK_HEADER_LEN; 364b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &chunk_header, sizeof(chunk_header)); 36528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 36628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 36728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 36828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->cur_out_ptr += skip_len; 36928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->chunk_cnt++; 37028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 37128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 37228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 37328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 374b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_sparse_fill_chunk(struct output_file *out, unsigned int len, 375b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t fill_val) 37628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 37728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header_t chunk_header; 37828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int rnd_up_len, zero_len, count; 37928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 38028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross unsigned int i; 38128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 382b55dceea986ab24f8b836b5116b389ed619c816eColin Cross /* Round up the fill length to a multiple of the block size */ 383b55dceea986ab24f8b836b5116b389ed619c816eColin Cross rnd_up_len = ALIGN(len, out->block_size); 38428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 38528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross /* Finally we can safely emit a chunk of data */ 38628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_type = CHUNK_TYPE_FILL; 38728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.reserved1 = 0; 38828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_sz = rnd_up_len / out->block_size; 38928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.total_sz = CHUNK_HEADER_LEN + sizeof(fill_val); 390b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &chunk_header, sizeof(chunk_header)); 39128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 39228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 39328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 394b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &fill_val, sizeof(fill_val)); 39528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 39628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 39728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 39828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (out->use_crc) { 399b55dceea986ab24f8b836b5116b389ed619c816eColin Cross count = out->block_size / sizeof(uint32_t); 400b55dceea986ab24f8b836b5116b389ed619c816eColin Cross while (count--) 401b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->crc32 = sparse_crc32(out->crc32, &fill_val, sizeof(uint32_t)); 40228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 40328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 40428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->cur_out_ptr += rnd_up_len; 40528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->chunk_cnt++; 40628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 40728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 40828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 40928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 410b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_sparse_data_chunk(struct output_file *out, unsigned int len, 411b55dceea986ab24f8b836b5116b389ed619c816eColin Cross void *data) 41228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 41328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header_t chunk_header; 41428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int rnd_up_len, zero_len; 41528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 41628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 417b55dceea986ab24f8b836b5116b389ed619c816eColin Cross /* Round up the data length to a multiple of the block size */ 418b55dceea986ab24f8b836b5116b389ed619c816eColin Cross rnd_up_len = ALIGN(len, out->block_size); 41928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross zero_len = rnd_up_len - len; 42028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 42128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross /* Finally we can safely emit a chunk of data */ 42228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_type = CHUNK_TYPE_RAW; 42328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.reserved1 = 0; 42428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_sz = rnd_up_len / out->block_size; 42528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.total_sz = CHUNK_HEADER_LEN + rnd_up_len; 426b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &chunk_header, sizeof(chunk_header)); 42728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 42828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 42928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 43028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross ret = out->ops->write(out, data, len); 43128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 43228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 43328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (zero_len) { 434b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, out->zero_buf, zero_len); 43528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 43628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 43728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 43828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 43928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (out->use_crc) { 44028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->crc32 = sparse_crc32(out->crc32, data, len); 44128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (zero_len) 442b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->crc32 = sparse_crc32(out->crc32, out->zero_buf, zero_len); 44328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 44428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 44528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->cur_out_ptr += rnd_up_len; 44628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->chunk_cnt++; 44728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 44828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 44928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 45028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 451b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_sparse_end_chunk(struct output_file *out) 45228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 45328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header_t chunk_header; 454b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int ret; 45528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 456b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (out->use_crc) { 457b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunk_header.chunk_type = CHUNK_TYPE_CRC32; 458b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunk_header.reserved1 = 0; 459b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunk_header.chunk_sz = 0; 460b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunk_header.total_sz = CHUNK_HEADER_LEN + 4; 461b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 462b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &chunk_header, sizeof(chunk_header)); 463b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 464b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 465b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 466b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->ops->write(out, &out->crc32, 4); 467b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 468b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 469b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 470b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 471b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->chunk_cnt++; 472b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 473b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 474b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return 0; 475b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 476b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 477b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic struct sparse_file_ops sparse_file_ops = { 478b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_data_chunk = write_sparse_data_chunk, 479b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_fill_chunk = write_sparse_fill_chunk, 480b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_skip_chunk = write_sparse_skip_chunk, 481b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_end_chunk = write_sparse_end_chunk, 482b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}; 483b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 484b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_normal_data_chunk(struct output_file *out, unsigned int len, 485b55dceea986ab24f8b836b5116b389ed619c816eColin Cross void *data) 486b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 487b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int ret; 488b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int rnd_up_len = ALIGN(len, out->block_size); 489b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 490b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, data, len); 491b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 492b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 493b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 494b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 495b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (rnd_up_len > len) { 496b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->skip(out, rnd_up_len - len); 497b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 49828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 499b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 500b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 501b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 502b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_normal_fill_chunk(struct output_file *out, unsigned int len, 503b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t fill_val) 504b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 505b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int ret; 506b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int i; 507b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int write_len; 50828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 509b55dceea986ab24f8b836b5116b389ed619c816eColin Cross /* Initialize fill_buf with the fill_val */ 510b55dceea986ab24f8b836b5116b389ed619c816eColin Cross for (i = 0; i < out->block_size / sizeof(uint32_t); i++) { 511b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->fill_buf[i] = fill_val; 512b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 513b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 514b55dceea986ab24f8b836b5116b389ed619c816eColin Cross while (len) { 515b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_len = min(len, out->block_size); 516b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, out->fill_buf, write_len); 517b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 518b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 51928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 52028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 521b55dceea986ab24f8b836b5116b389ed619c816eColin Cross len -= write_len; 522b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 523b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 524b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return 0; 525b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 526b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 527b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_normal_skip_chunk(struct output_file *out, int64_t len) 528b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 529b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return out->ops->skip(out, len); 530b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 531b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 532b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_normal_end_chunk(struct output_file *out) 533b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 534b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return out->ops->pad(out, out->len); 535b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 536b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 537b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic struct sparse_file_ops normal_file_ops = { 538b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_data_chunk = write_normal_data_chunk, 539b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_fill_chunk = write_normal_fill_chunk, 540b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_skip_chunk = write_normal_skip_chunk, 541b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_end_chunk = write_normal_end_chunk, 542b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}; 543b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 544b43828b247fd4f1e0373584de0504004c69eeac9Colin Crossvoid output_file_close(struct output_file *out) 545b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 546b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int ret; 547b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 548b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->sparse_ops->write_end_chunk(out); 54928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->ops->close(out); 55028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 55128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 552b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic int output_file_init(struct output_file *out, int block_size, 553b4cd267db30c152245e6308598e0066d87c5c55dColin Cross int64_t len, bool sparse, int chunks, bool crc) 55428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 55528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 556b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 557b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->len = len; 558b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->block_size = block_size; 559b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->cur_out_ptr = 0ll; 560b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->chunk_cnt = 0; 561b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->crc32 = 0; 562b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->use_crc = crc; 563b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 564b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->zero_buf = calloc(block_size, 1); 565b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (!out->zero_buf) { 56628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("malloc zero_buf"); 567b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return -ENOMEM; 568b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 569b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 570b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->fill_buf = calloc(block_size, 1); 571b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (!out->fill_buf) { 572b55dceea986ab24f8b836b5116b389ed619c816eColin Cross error_errno("malloc fill_buf"); 573b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = -ENOMEM; 574b55dceea986ab24f8b836b5116b389ed619c816eColin Cross goto err_fill_buf; 57528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 57628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 577b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (sparse) { 578b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->sparse_ops = &sparse_file_ops; 579b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } else { 580b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->sparse_ops = &normal_file_ops; 581b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 582b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 583b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (sparse) { 584b55dceea986ab24f8b836b5116b389ed619c816eColin Cross sparse_header_t sparse_header = { 585b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .magic = SPARSE_HEADER_MAGIC, 586b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .major_version = SPARSE_HEADER_MAJOR_VER, 587b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .minor_version = SPARSE_HEADER_MINOR_VER, 588b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .file_hdr_sz = SPARSE_HEADER_LEN, 589b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .chunk_hdr_sz = CHUNK_HEADER_LEN, 590b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .blk_sz = out->block_size, 591b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .total_blks = out->len / out->block_size, 592b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .total_chunks = chunks, 593b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .image_checksum = 0 594b55dceea986ab24f8b836b5116b389ed619c816eColin Cross }; 595b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 596b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (out->use_crc) { 59728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross sparse_header.total_chunks++; 598b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 59928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 600b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &sparse_header, sizeof(sparse_header)); 601b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 602b55dceea986ab24f8b836b5116b389ed619c816eColin Cross goto err_write; 603b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 60428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 60528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 606b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return 0; 607b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 608b55dceea986ab24f8b836b5116b389ed619c816eColin Crosserr_write: 609b55dceea986ab24f8b836b5116b389ed619c816eColin Cross free(out->fill_buf); 610b55dceea986ab24f8b836b5116b389ed619c816eColin Crosserr_fill_buf: 611b55dceea986ab24f8b836b5116b389ed619c816eColin Cross free(out->zero_buf); 612b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return ret; 613b4cd267db30c152245e6308598e0066d87c5c55dColin Cross} 614b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 615b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic struct output_file *output_file_new_gz(void) 616b4cd267db30c152245e6308598e0066d87c5c55dColin Cross{ 617b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_gz *outgz = calloc(1, sizeof(struct output_file_gz)); 618b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (!outgz) { 619b4cd267db30c152245e6308598e0066d87c5c55dColin Cross error_errno("malloc struct outgz"); 620b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return NULL; 621b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 622b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 623b4cd267db30c152245e6308598e0066d87c5c55dColin Cross outgz->out.ops = &gz_file_ops; 624b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 625b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return &outgz->out; 626b4cd267db30c152245e6308598e0066d87c5c55dColin Cross} 627b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 628b4cd267db30c152245e6308598e0066d87c5c55dColin Crossstatic struct output_file *output_file_new_normal(void) 629b4cd267db30c152245e6308598e0066d87c5c55dColin Cross{ 630b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file_normal *outn = calloc(1, sizeof(struct output_file_normal)); 631b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (!outn) { 632b4cd267db30c152245e6308598e0066d87c5c55dColin Cross error_errno("malloc struct outn"); 633b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return NULL; 634b4cd267db30c152245e6308598e0066d87c5c55dColin Cross } 635b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 636b4cd267db30c152245e6308598e0066d87c5c55dColin Cross outn->out.ops = &file_ops; 637b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 638b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return &outn->out; 63928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 64028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 641b43828b247fd4f1e0373584de0504004c69eeac9Colin Crossstruct output_file *output_file_open_callback(int (*write)(void *, const void *, int), 6421e17b313a6257b7b5081e178e81435c09d60378eColin Cross void *priv, unsigned int block_size, int64_t len, int gz, int sparse, 6431e17b313a6257b7b5081e178e81435c09d60378eColin Cross int chunks, int crc) 6441e17b313a6257b7b5081e178e81435c09d60378eColin Cross{ 6451e17b313a6257b7b5081e178e81435c09d60378eColin Cross int ret; 6461e17b313a6257b7b5081e178e81435c09d60378eColin Cross struct output_file_callback *outc; 6471e17b313a6257b7b5081e178e81435c09d60378eColin Cross 6481e17b313a6257b7b5081e178e81435c09d60378eColin Cross outc = calloc(1, sizeof(struct output_file_callback)); 6491e17b313a6257b7b5081e178e81435c09d60378eColin Cross if (!outc) { 6501e17b313a6257b7b5081e178e81435c09d60378eColin Cross error_errno("malloc struct outc"); 6511e17b313a6257b7b5081e178e81435c09d60378eColin Cross return NULL; 6521e17b313a6257b7b5081e178e81435c09d60378eColin Cross } 6531e17b313a6257b7b5081e178e81435c09d60378eColin Cross 6541e17b313a6257b7b5081e178e81435c09d60378eColin Cross outc->out.ops = &callback_file_ops; 6551e17b313a6257b7b5081e178e81435c09d60378eColin Cross outc->priv = priv; 6561e17b313a6257b7b5081e178e81435c09d60378eColin Cross outc->write = write; 6571e17b313a6257b7b5081e178e81435c09d60378eColin Cross 6581e17b313a6257b7b5081e178e81435c09d60378eColin Cross ret = output_file_init(&outc->out, block_size, len, sparse, chunks, crc); 6591e17b313a6257b7b5081e178e81435c09d60378eColin Cross if (ret < 0) { 6601e17b313a6257b7b5081e178e81435c09d60378eColin Cross free(outc); 6611e17b313a6257b7b5081e178e81435c09d60378eColin Cross return NULL; 6621e17b313a6257b7b5081e178e81435c09d60378eColin Cross } 6631e17b313a6257b7b5081e178e81435c09d60378eColin Cross 6641e17b313a6257b7b5081e178e81435c09d60378eColin Cross return &outc->out; 6651e17b313a6257b7b5081e178e81435c09d60378eColin Cross} 6661e17b313a6257b7b5081e178e81435c09d60378eColin Cross 667b43828b247fd4f1e0373584de0504004c69eeac9Colin Crossstruct output_file *output_file_open_fd(int fd, unsigned int block_size, int64_t len, 66828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int gz, int sparse, int chunks, int crc) 66928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 670b4cd267db30c152245e6308598e0066d87c5c55dColin Cross int ret; 671b4cd267db30c152245e6308598e0066d87c5c55dColin Cross struct output_file *out; 67228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 673b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (gz) { 674b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out = output_file_new_gz(); 67528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } else { 676b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out = output_file_new_normal(); 67728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 67828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 679b4cd267db30c152245e6308598e0066d87c5c55dColin Cross out->ops->open(out, fd); 680b4cd267db30c152245e6308598e0066d87c5c55dColin Cross 681b4cd267db30c152245e6308598e0066d87c5c55dColin Cross ret = output_file_init(out, block_size, len, sparse, chunks, crc); 682b4cd267db30c152245e6308598e0066d87c5c55dColin Cross if (ret < 0) { 683b4cd267db30c152245e6308598e0066d87c5c55dColin Cross free(out); 68428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return NULL; 68528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 68628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 687b4cd267db30c152245e6308598e0066d87c5c55dColin Cross return out; 68828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 68928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 69028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* Write a contiguous region of data blocks from a memory buffer */ 691b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_data_chunk(struct output_file *out, unsigned int len, void *data) 69228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 693b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return out->sparse_ops->write_data_chunk(out, len, data); 69428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 69528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 69628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* Write a contiguous region of data blocks with a fill value */ 697b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_fill_chunk(struct output_file *out, unsigned int len, 698b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t fill_val) 69928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 700b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return out->sparse_ops->write_fill_chunk(out, len, fill_val); 70128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 70228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 7039e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Crossint write_fd_chunk(struct output_file *out, unsigned int len, 7049e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross int fd, int64_t offset) 70528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 70628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 70728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int64_t aligned_offset; 70828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int aligned_diff; 70928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int buffer_size; 71013a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross char *ptr; 71128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 71228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross aligned_offset = offset & ~(4096 - 1); 71328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross aligned_diff = offset - aligned_offset; 71428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross buffer_size = len + aligned_diff; 71528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 71628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifndef USE_MINGW 7179e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross char *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, fd, 71828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross aligned_offset); 71928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (data == MAP_FAILED) { 7209e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return -errno; 72128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 72213a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross ptr = data + aligned_diff; 72328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#else 72413a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross off64_t pos; 72513a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross char *data = malloc(len); 72628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (!data) { 7279e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return -errno; 72828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 72913a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross pos = lseek64(fd, offset, SEEK_SET); 73013a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross if (pos < 0) { 73113a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross return -errno; 73213a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross } 73313a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross ret = read_all(fd, data, len); 73413a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross if (ret < 0) { 73513a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross return ret; 73613a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross } 73713a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross ptr = data; 73828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 73928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 74013a560659381b34ce3edbfa8dbe6c0aa6c076f20Colin Cross ret = out->sparse_ops->write_data_chunk(out, len, ptr); 74128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 74228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifndef USE_MINGW 74328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross munmap(data, buffer_size); 74428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#else 74528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross free(data); 74628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 7479e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 7489e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return ret; 7499e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross} 7509e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 7519e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross/* Write a contiguous region of data blocks from a file */ 7529e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Crossint write_file_chunk(struct output_file *out, unsigned int len, 7539e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross const char *file, int64_t offset) 7549e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross{ 7559e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross int ret; 7569e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 7579e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross int file_fd = open(file, O_RDONLY | O_BINARY); 7589e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross if (file_fd < 0) { 7599e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return -errno; 7609e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross } 7619e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 7629e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross ret = write_fd_chunk(out, len, file_fd, offset); 7639e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 76428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross close(file_fd); 765b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 766b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 767b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 768b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 769b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_skip_chunk(struct output_file *out, int64_t len) 770b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 771b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return out->sparse_ops->write_skip_chunk(out, len); 77228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 773