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