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