output_file.c revision 9e1f17e926fa20255c5f4b4d2f68aa98a964253a
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> 2128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <stdbool.h> 2228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <stdlib.h> 2328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <string.h> 2428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sys/stat.h> 2528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sys/types.h> 2628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <unistd.h> 2728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <zlib.h> 2828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 2928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "output_file.h" 3028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_format.h" 3128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_crc32.h" 3228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 3328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifndef USE_MINGW 3428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sys/mman.h> 3528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define O_BINARY 0 3628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 3728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 3828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#if defined(__APPLE__) && defined(__MACH__) 3928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define lseek64 lseek 4028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define ftruncate64 ftruncate 4128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define mmap64 mmap 4228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define off64_t off_t 4328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 4428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 4528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifdef __BIONIC__ 4628fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossextern void* __mmap2(void *, size_t, int, int, int, off_t); 4728fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic inline void *mmap64(void *addr, size_t length, int prot, int flags, 4828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int fd, off64_t offset) 4928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 5028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return __mmap2(addr, length, prot, flags, fd, offset >> 12); 5128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 5228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 5328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 54b55dceea986ab24f8b836b5116b389ed619c816eColin Cross#define min(a, b) \ 55b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ({ typeof(a) _a = (a); typeof(b) _b = (b); (_a < _b) ? _a : _b; }) 56b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 5728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define SPARSE_HEADER_MAJOR_VER 1 5828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define SPARSE_HEADER_MINOR_VER 0 5928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define SPARSE_HEADER_LEN (sizeof(sparse_header_t)) 6028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define CHUNK_HEADER_LEN (sizeof(chunk_header_t)) 6128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 6228fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct output_file_ops { 63b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*skip)(struct output_file *, int64_t); 64b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write)(struct output_file *, void *, int); 6528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross void (*close)(struct output_file *); 6628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}; 6728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 68b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstruct sparse_file_ops { 69b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write_data_chunk)(struct output_file *out, unsigned int len, 70b55dceea986ab24f8b836b5116b389ed619c816eColin Cross void *data); 71b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write_fill_chunk)(struct output_file *out, unsigned int len, 72b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t fill_val); 73b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write_skip_chunk)(struct output_file *out, int64_t len); 74b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int (*write_end_chunk)(struct output_file *out); 75b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}; 76b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 7728fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct output_file { 7828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int fd; 7928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross gzFile gz_fd; 8028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross bool close_fd; 8128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int64_t cur_out_ptr; 82b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int chunk_cnt; 83b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t crc32; 8428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross struct output_file_ops *ops; 85b55dceea986ab24f8b836b5116b389ed619c816eColin Cross struct sparse_file_ops *sparse_ops; 8628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int use_crc; 8728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross unsigned int block_size; 8828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int64_t len; 89b55dceea986ab24f8b836b5116b389ed619c816eColin Cross char *zero_buf; 90b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t *fill_buf; 9128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}; 9228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 93b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int file_skip(struct output_file *out, int64_t cnt) 9428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 9528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross off64_t ret; 9628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 97b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = lseek64(out->fd, cnt, SEEK_CUR); 9828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) { 9928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("lseek64"); 10028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 10128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 10228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 10328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 10428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 105b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int file_write(struct output_file *out, void *data, int len) 10628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 10728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 10828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross ret = write(out->fd, data, len); 10928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) { 11028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("write"); 11128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 11228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } else if (ret < len) { 11328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error("incomplete write"); 11428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 11528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 11628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 11728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 11828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 11928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 12028fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void file_close(struct output_file *out) 12128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 12228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (out->close_fd) { 12328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross close(out->fd); 12428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 12528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 12628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 12728fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic struct output_file_ops file_ops = { 128b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .skip = file_skip, 12928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross .write = file_write, 13028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross .close = file_close, 13128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}; 13228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 133b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int gz_file_skip(struct output_file *out, int64_t cnt) 13428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 13528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross off64_t ret; 13628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 137b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = gzseek(out->gz_fd, cnt, SEEK_CUR); 13828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) { 13928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("gzseek"); 14028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 14128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 14228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 14328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 14428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 145b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int gz_file_write(struct output_file *out, void *data, int len) 14628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 14728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 14828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross ret = gzwrite(out->gz_fd, data, len); 14928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) { 15028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("gzwrite"); 15128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 15228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } else if (ret < len) { 15328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error("incomplete gzwrite"); 15428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 15528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 15628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 15728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 15828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 15928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 16028fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void gz_file_close(struct output_file *out) 16128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 16228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross gzclose(out->gz_fd); 16328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 16428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 16528fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic struct output_file_ops gz_file_ops = { 166b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .skip = gz_file_skip, 16728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross .write = gz_file_write, 16828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross .close = gz_file_close, 16928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}; 17028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 171b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_sparse_skip_chunk(struct output_file *out, int64_t skip_len) 17228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 17328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header_t chunk_header; 17428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret, chunk; 17528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 17628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (skip_len % out->block_size) { 17728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error("don't care size %llu is not a multiple of the block size %u", 17828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross skip_len, out->block_size); 17928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 18028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 18128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 18228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross /* We are skipping data, so emit a don't care chunk. */ 18328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_type = CHUNK_TYPE_DONT_CARE; 18428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.reserved1 = 0; 18528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_sz = skip_len / out->block_size; 18628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.total_sz = CHUNK_HEADER_LEN; 187b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &chunk_header, sizeof(chunk_header)); 18828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 18928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 19028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 19128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->cur_out_ptr += skip_len; 19228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->chunk_cnt++; 19328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 19428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 19528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 19628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 197b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_sparse_fill_chunk(struct output_file *out, unsigned int len, 198b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t fill_val) 19928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 20028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header_t chunk_header; 20128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int rnd_up_len, zero_len, count; 20228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 20328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross unsigned int i; 20428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 205b55dceea986ab24f8b836b5116b389ed619c816eColin Cross /* Round up the fill length to a multiple of the block size */ 206b55dceea986ab24f8b836b5116b389ed619c816eColin Cross rnd_up_len = ALIGN(len, out->block_size); 20728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 20828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross /* Finally we can safely emit a chunk of data */ 20928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_type = CHUNK_TYPE_FILL; 21028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.reserved1 = 0; 21128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_sz = rnd_up_len / out->block_size; 21228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.total_sz = CHUNK_HEADER_LEN + sizeof(fill_val); 213b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &chunk_header, sizeof(chunk_header)); 21428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 21528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 21628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 217b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &fill_val, sizeof(fill_val)); 21828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 21928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 22028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 22128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (out->use_crc) { 222b55dceea986ab24f8b836b5116b389ed619c816eColin Cross count = out->block_size / sizeof(uint32_t); 223b55dceea986ab24f8b836b5116b389ed619c816eColin Cross while (count--) 224b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->crc32 = sparse_crc32(out->crc32, &fill_val, sizeof(uint32_t)); 22528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 22628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 22728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->cur_out_ptr += rnd_up_len; 22828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->chunk_cnt++; 22928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 23028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 23128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 23228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 233b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_sparse_data_chunk(struct output_file *out, unsigned int len, 234b55dceea986ab24f8b836b5116b389ed619c816eColin Cross void *data) 23528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 23628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header_t chunk_header; 23728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int rnd_up_len, zero_len; 23828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 23928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 240b55dceea986ab24f8b836b5116b389ed619c816eColin Cross /* Round up the data length to a multiple of the block size */ 241b55dceea986ab24f8b836b5116b389ed619c816eColin Cross rnd_up_len = ALIGN(len, out->block_size); 24228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross zero_len = rnd_up_len - len; 24328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 24428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross /* Finally we can safely emit a chunk of data */ 24528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_type = CHUNK_TYPE_RAW; 24628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.reserved1 = 0; 24728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.chunk_sz = rnd_up_len / out->block_size; 24828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header.total_sz = CHUNK_HEADER_LEN + rnd_up_len; 249b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &chunk_header, sizeof(chunk_header)); 25028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 25128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 25228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 25328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross ret = out->ops->write(out, data, len); 25428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 25528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 25628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (zero_len) { 257b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, out->zero_buf, zero_len); 25828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (ret < 0) 25928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -1; 26028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 26128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 26228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (out->use_crc) { 26328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->crc32 = sparse_crc32(out->crc32, data, len); 26428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (zero_len) 265b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->crc32 = sparse_crc32(out->crc32, out->zero_buf, zero_len); 26628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 26728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 26828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->cur_out_ptr += rnd_up_len; 26928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->chunk_cnt++; 27028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 27128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 27228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 27328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 274b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_sparse_end_chunk(struct output_file *out) 27528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 27628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross chunk_header_t chunk_header; 277b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int ret; 27828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 279b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (out->use_crc) { 280b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunk_header.chunk_type = CHUNK_TYPE_CRC32; 281b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunk_header.reserved1 = 0; 282b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunk_header.chunk_sz = 0; 283b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunk_header.total_sz = CHUNK_HEADER_LEN + 4; 284b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 285b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &chunk_header, sizeof(chunk_header)); 286b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 287b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 288b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 289b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->ops->write(out, &out->crc32, 4); 290b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 291b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 292b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 293b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 294b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->chunk_cnt++; 295b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 296b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 297b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return 0; 298b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 299b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 300b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic struct sparse_file_ops sparse_file_ops = { 301b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_data_chunk = write_sparse_data_chunk, 302b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_fill_chunk = write_sparse_fill_chunk, 303b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_skip_chunk = write_sparse_skip_chunk, 304b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_end_chunk = write_sparse_end_chunk, 305b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}; 306b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 307b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_normal_data_chunk(struct output_file *out, unsigned int len, 308b55dceea986ab24f8b836b5116b389ed619c816eColin Cross void *data) 309b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 310b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int ret; 311b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int rnd_up_len = ALIGN(len, out->block_size); 312b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 313b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, data, len); 314b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 315b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 316b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 317b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 318b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (rnd_up_len > len) { 319b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->skip(out, rnd_up_len - len); 320b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 32128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 322b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 323b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 324b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 325b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_normal_fill_chunk(struct output_file *out, unsigned int len, 326b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t fill_val) 327b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 328b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int ret; 329b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int i; 330b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int write_len; 33128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 332b55dceea986ab24f8b836b5116b389ed619c816eColin Cross /* Initialize fill_buf with the fill_val */ 333b55dceea986ab24f8b836b5116b389ed619c816eColin Cross for (i = 0; i < out->block_size / sizeof(uint32_t); i++) { 334b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->fill_buf[i] = fill_val; 335b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 336b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 337b55dceea986ab24f8b836b5116b389ed619c816eColin Cross while (len) { 338b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_len = min(len, out->block_size); 339b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, out->fill_buf, write_len); 340b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 341b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 34228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 34328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 344b55dceea986ab24f8b836b5116b389ed619c816eColin Cross len -= write_len; 345b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 346b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 347b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return 0; 348b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 349b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 350b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic int write_normal_skip_chunk(struct output_file *out, int64_t len) 351b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 352b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int ret; 353b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 354b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return out->ops->skip(out, len); 355b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 356b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 357b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_normal_end_chunk(struct output_file *out) 358b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 359b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int ret; 360b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 361b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = ftruncate64(out->fd, out->len); 362b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 363b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return -errno; 36428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 365b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 366b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return 0; 367b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 368b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 369b55dceea986ab24f8b836b5116b389ed619c816eColin Crossstatic struct sparse_file_ops normal_file_ops = { 370b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_data_chunk = write_normal_data_chunk, 371b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_fill_chunk = write_normal_fill_chunk, 372b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_skip_chunk = write_normal_skip_chunk, 373b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .write_end_chunk = write_normal_end_chunk, 374b55dceea986ab24f8b836b5116b389ed619c816eColin Cross}; 375b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 376b55dceea986ab24f8b836b5116b389ed619c816eColin Crossvoid close_output_file(struct output_file *out) 377b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 378b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int ret; 379b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 380b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->sparse_ops->write_end_chunk(out); 38128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->ops->close(out); 382b55dceea986ab24f8b836b5116b389ed619c816eColin Cross free(out); 38328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 38428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 38528fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct output_file *open_output_fd(int fd, unsigned int block_size, int64_t len, 38628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int gz, int sparse, int chunks, int crc) 38728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 38828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 38928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross struct output_file *out = malloc(sizeof(struct output_file)); 39028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (!out) { 39128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("malloc struct out"); 39228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return NULL; 39328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 394b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->zero_buf = calloc(block_size, 1); 395b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (!out->zero_buf) { 39628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("malloc zero_buf"); 397b55dceea986ab24f8b836b5116b389ed619c816eColin Cross goto err_zero_buf; 398b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 399b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 400b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->fill_buf = calloc(block_size, 1); 401b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (!out->fill_buf) { 402b55dceea986ab24f8b836b5116b389ed619c816eColin Cross error_errno("malloc fill_buf"); 403b55dceea986ab24f8b836b5116b389ed619c816eColin Cross goto err_fill_buf; 40428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 40528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 40628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (gz) { 40728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->ops = &gz_file_ops; 40828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->gz_fd = gzdopen(fd, "wb9"); 40928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (!out->gz_fd) { 41028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("gzopen"); 411b55dceea986ab24f8b836b5116b389ed619c816eColin Cross goto err_gzopen; 41228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 41328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } else { 41428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->fd = fd; 41528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->ops = &file_ops; 41628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 417b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 418b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (sparse) { 419b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->sparse_ops = &sparse_file_ops; 420b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } else { 421b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out->sparse_ops = &normal_file_ops; 422b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 423b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 42428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->close_fd = false; 42528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->cur_out_ptr = 0ll; 42628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->chunk_cnt = 0; 42728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 42828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross /* Initialize the crc32 value */ 42928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->crc32 = 0; 43028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->use_crc = crc; 43128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 43228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->len = len; 43328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross out->block_size = block_size; 43428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 435b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (sparse) { 436b55dceea986ab24f8b836b5116b389ed619c816eColin Cross sparse_header_t sparse_header = { 437b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .magic = SPARSE_HEADER_MAGIC, 438b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .major_version = SPARSE_HEADER_MAJOR_VER, 439b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .minor_version = SPARSE_HEADER_MINOR_VER, 440b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .file_hdr_sz = SPARSE_HEADER_LEN, 441b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .chunk_hdr_sz = CHUNK_HEADER_LEN, 442b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .blk_sz = out->block_size, 443b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .total_blks = out->len / out->block_size, 444b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .total_chunks = chunks, 445b55dceea986ab24f8b836b5116b389ed619c816eColin Cross .image_checksum = 0 446b55dceea986ab24f8b836b5116b389ed619c816eColin Cross }; 447b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 448b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (out->use_crc) { 44928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross sparse_header.total_chunks++; 450b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 45128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 452b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->ops->write(out, &sparse_header, sizeof(sparse_header)); 453b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (ret < 0) { 454b55dceea986ab24f8b836b5116b389ed619c816eColin Cross goto err_write; 455b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 45628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 45728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 45828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return out; 459b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 460b55dceea986ab24f8b836b5116b389ed619c816eColin Crosserr_write: 461b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (gz) { 462b55dceea986ab24f8b836b5116b389ed619c816eColin Cross gzclose(out->gz_fd); 463b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 464b55dceea986ab24f8b836b5116b389ed619c816eColin Crosserr_gzopen: 465b55dceea986ab24f8b836b5116b389ed619c816eColin Cross free(out->fill_buf); 466b55dceea986ab24f8b836b5116b389ed619c816eColin Crosserr_fill_buf: 467b55dceea986ab24f8b836b5116b389ed619c816eColin Cross free(out->zero_buf); 468b55dceea986ab24f8b836b5116b389ed619c816eColin Crosserr_zero_buf: 469b55dceea986ab24f8b836b5116b389ed619c816eColin Cross free(out); 470b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return NULL; 47128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 47228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 47328fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct output_file *open_output_file(const char *filename, 47428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross unsigned int block_size, int64_t len, 47528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int gz, int sparse, int chunks, int crc) 47628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 47728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int fd; 47828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross struct output_file *file; 47928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 48028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (strcmp(filename, "-")) { 48128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); 48228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (fd < 0) { 48328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross error_errno("open"); 48428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return NULL; 48528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 48628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } else { 48728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross fd = STDOUT_FILENO; 48828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 48928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 49028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross file = open_output_fd(fd, block_size, len, gz, sparse, chunks, crc); 49128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (!file) { 49228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross close(fd); 49328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return NULL; 49428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 49528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 49628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross file->close_fd = true; // we opened descriptor thus we responsible for closing it 49728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 49828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return file; 49928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 50028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 50128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* Write a contiguous region of data blocks from a memory buffer */ 502b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_data_chunk(struct output_file *out, unsigned int len, void *data) 50328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 504b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return out->sparse_ops->write_data_chunk(out, len, data); 50528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 50628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 50728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* Write a contiguous region of data blocks with a fill value */ 508b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_fill_chunk(struct output_file *out, unsigned int len, 509b55dceea986ab24f8b836b5116b389ed619c816eColin Cross uint32_t fill_val) 51028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 511b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return out->sparse_ops->write_fill_chunk(out, len, fill_val); 51228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 51328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 5149e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Crossint write_fd_chunk(struct output_file *out, unsigned int len, 5159e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross int fd, int64_t offset) 51628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 51728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int ret; 51828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int64_t aligned_offset; 51928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int aligned_diff; 52028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int buffer_size; 52128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 52228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross aligned_offset = offset & ~(4096 - 1); 52328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross aligned_diff = offset - aligned_offset; 52428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross buffer_size = len + aligned_diff; 52528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 52628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifndef USE_MINGW 5279e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross char *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, fd, 52828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross aligned_offset); 52928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (data == MAP_FAILED) { 5309e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return -errno; 53128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 53228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#else 533b55dceea986ab24f8b836b5116b389ed619c816eColin Cross char *data = malloc(buffer_size); 53428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (!data) { 5359e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return -errno; 53628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 53728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross memset(data, 0, buffer_size); 53828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 53928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 540b55dceea986ab24f8b836b5116b389ed619c816eColin Cross ret = out->sparse_ops->write_data_chunk(out, len, data + aligned_diff); 54128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 54228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifndef USE_MINGW 54328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross munmap(data, buffer_size); 54428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#else 54528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross free(data); 54628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif 5479e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 5489e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return ret; 5499e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross} 5509e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 5519e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross/* Write a contiguous region of data blocks from a file */ 5529e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Crossint write_file_chunk(struct output_file *out, unsigned int len, 5539e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross const char *file, int64_t offset) 5549e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross{ 5559e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross int ret; 5569e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 5579e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross int file_fd = open(file, O_RDONLY | O_BINARY); 5589e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross if (file_fd < 0) { 5599e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return -errno; 5609e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross } 5619e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 5629e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross ret = write_fd_chunk(out, len, file_fd, offset); 5639e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross 56428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross close(file_fd); 565b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 566b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return ret; 567b55dceea986ab24f8b836b5116b389ed619c816eColin Cross} 568b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 569b55dceea986ab24f8b836b5116b389ed619c816eColin Crossint write_skip_chunk(struct output_file *out, int64_t len) 570b55dceea986ab24f8b836b5116b389ed619c816eColin Cross{ 571b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return out->sparse_ops->write_skip_chunk(out, len); 57228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 573