128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/*
228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * Copyright (C) 2012 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
17b55dceea986ab24f8b836b5116b389ed619c816eColin Cross#include <assert.h>
1828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <stdlib.h>
1928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
2028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sparse/sparse.h>
2128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
22031a748b2a9bf6dcfd3983d8f0f616718fcddd88Mark Salyzyn#include "defs.h"
2328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_file.h"
2428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
2528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "output_file.h"
2628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "backed_block.h"
2728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_defs.h"
28bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross#include "sparse_format.h"
2928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
3028fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct sparse_file *sparse_file_new(unsigned int block_size, int64_t len)
3128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
3228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	struct sparse_file *s = calloc(sizeof(struct sparse_file), 1);
3328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (!s) {
3428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return NULL;
3528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
3628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
37be8ddcb35a459481c0bcf5bfe645c1fefe963f5cColin Cross	s->backed_block_list = backed_block_list_new(block_size);
38411619e921904b896eddae81c086c1f687c8304dColin Cross	if (!s->backed_block_list) {
39411619e921904b896eddae81c086c1f687c8304dColin Cross		free(s);
40411619e921904b896eddae81c086c1f687c8304dColin Cross		return NULL;
41411619e921904b896eddae81c086c1f687c8304dColin Cross	}
4228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
4328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	s->block_size = block_size;
4428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	s->len = len;
4528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
4628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	return s;
4728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
4828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
4928fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossvoid sparse_file_destroy(struct sparse_file *s)
5028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
51411619e921904b896eddae81c086c1f687c8304dColin Cross	backed_block_list_destroy(s->backed_block_list);
5228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	free(s);
5328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
5428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
5528fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_data(struct sparse_file *s,
5628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		void *data, unsigned int len, unsigned int block)
5728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
58b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return backed_block_add_data(s->backed_block_list, data, len, block);
5928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
6028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
6128fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_fill(struct sparse_file *s,
6228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		uint32_t fill_val, unsigned int len, unsigned int block)
6328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
64b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return backed_block_add_fill(s->backed_block_list, fill_val, len, block);
6528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
6628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
6728fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_file(struct sparse_file *s,
6828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		const char *filename, int64_t file_offset, unsigned int len,
6928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		unsigned int block)
7028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
71b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return backed_block_add_file(s->backed_block_list, filename, file_offset,
72b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			len, block);
7328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
7428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
759e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Crossint sparse_file_add_fd(struct sparse_file *s,
769e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross		int fd, int64_t file_offset, unsigned int len, unsigned int block)
779e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross{
789e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	return backed_block_add_fd(s->backed_block_list, fd, file_offset,
799e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross			len, block);
809e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross}
81b55dceea986ab24f8b836b5116b389ed619c816eColin Crossunsigned int sparse_count_chunks(struct sparse_file *s)
8228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
83b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	struct backed_block *bb;
84b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	unsigned int last_block = 0;
85b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	unsigned int chunks = 0;
86b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
87b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	for (bb = backed_block_iter_new(s->backed_block_list); bb;
88b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			bb = backed_block_iter_next(bb)) {
89b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		if (backed_block_block(bb) > last_block) {
90b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			/* If there is a gap between chunks, add a skip chunk */
91b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			chunks++;
92b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		}
93b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		chunks++;
94b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		last_block = backed_block_block(bb) +
95b55dceea986ab24f8b836b5116b389ed619c816eColin Cross				DIV_ROUND_UP(backed_block_len(bb), s->block_size);
96b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	}
97b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	if (last_block < DIV_ROUND_UP(s->len, s->block_size)) {
98b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		chunks++;
99b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	}
10028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
101b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return chunks;
10228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
10328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
1049f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostellastatic int sparse_file_write_block(struct output_file *out,
1051e17b313a6257b7b5081e178e81435c09d60378eColin Cross		struct backed_block *bb)
1061e17b313a6257b7b5081e178e81435c09d60378eColin Cross{
1079f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella	int ret = -EINVAL;
1089f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella
1091e17b313a6257b7b5081e178e81435c09d60378eColin Cross	switch (backed_block_type(bb)) {
1101e17b313a6257b7b5081e178e81435c09d60378eColin Cross	case BACKED_BLOCK_DATA:
1119f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella		ret = write_data_chunk(out, backed_block_len(bb), backed_block_data(bb));
1121e17b313a6257b7b5081e178e81435c09d60378eColin Cross		break;
1131e17b313a6257b7b5081e178e81435c09d60378eColin Cross	case BACKED_BLOCK_FILE:
1149f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella		ret = write_file_chunk(out, backed_block_len(bb),
1159f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella				       backed_block_filename(bb),
1169f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella				       backed_block_file_offset(bb));
1171e17b313a6257b7b5081e178e81435c09d60378eColin Cross		break;
1181e17b313a6257b7b5081e178e81435c09d60378eColin Cross	case BACKED_BLOCK_FD:
1199f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella		ret = write_fd_chunk(out, backed_block_len(bb),
1209f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella				     backed_block_fd(bb),
1219f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella				     backed_block_file_offset(bb));
1221e17b313a6257b7b5081e178e81435c09d60378eColin Cross		break;
1231e17b313a6257b7b5081e178e81435c09d60378eColin Cross	case BACKED_BLOCK_FILL:
1249f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella		ret = write_fill_chunk(out, backed_block_len(bb),
1259f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella				       backed_block_fill_val(bb));
1261e17b313a6257b7b5081e178e81435c09d60378eColin Cross		break;
1271e17b313a6257b7b5081e178e81435c09d60378eColin Cross	}
1289f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella
1299f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella	return ret;
1301e17b313a6257b7b5081e178e81435c09d60378eColin Cross}
1311e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1321e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic int write_all_blocks(struct sparse_file *s, struct output_file *out)
13328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
134b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	struct backed_block *bb;
135b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	unsigned int last_block = 0;
136b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	int64_t pad;
1379f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella	int ret = 0;
13828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
139b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	for (bb = backed_block_iter_new(s->backed_block_list); bb;
140b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			bb = backed_block_iter_next(bb)) {
141b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		if (backed_block_block(bb) > last_block) {
142b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			unsigned int blocks = backed_block_block(bb) - last_block;
143b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			write_skip_chunk(out, (int64_t)blocks * s->block_size);
144b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		}
1459f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella		ret = sparse_file_write_block(out, bb);
1469f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella		if (ret)
1479f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella			return ret;
148b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		last_block = backed_block_block(bb) +
149b55dceea986ab24f8b836b5116b389ed619c816eColin Cross				DIV_ROUND_UP(backed_block_len(bb), s->block_size);
150b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	}
15128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
152f1ec8ac84a8540b92a16f187bfa92b2f3c63917eColin Cross	pad = s->len - (int64_t)last_block * s->block_size;
153b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	assert(pad >= 0);
154b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	if (pad > 0) {
155b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		write_skip_chunk(out, pad);
156b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	}
15728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
1581e17b313a6257b7b5081e178e81435c09d60378eColin Cross	return 0;
1591e17b313a6257b7b5081e178e81435c09d60378eColin Cross}
1601e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1611e17b313a6257b7b5081e178e81435c09d60378eColin Crossint sparse_file_write(struct sparse_file *s, int fd, bool gz, bool sparse,
1621e17b313a6257b7b5081e178e81435c09d60378eColin Cross		bool crc)
1631e17b313a6257b7b5081e178e81435c09d60378eColin Cross{
1641e17b313a6257b7b5081e178e81435c09d60378eColin Cross	int ret;
1651e17b313a6257b7b5081e178e81435c09d60378eColin Cross	int chunks;
1661e17b313a6257b7b5081e178e81435c09d60378eColin Cross	struct output_file *out;
1671e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1681e17b313a6257b7b5081e178e81435c09d60378eColin Cross	chunks = sparse_count_chunks(s);
169b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	out = output_file_open_fd(fd, s->block_size, s->len, gz, sparse, chunks, crc);
1701e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1711e17b313a6257b7b5081e178e81435c09d60378eColin Cross	if (!out)
1721e17b313a6257b7b5081e178e81435c09d60378eColin Cross		return -ENOMEM;
1731e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1741e17b313a6257b7b5081e178e81435c09d60378eColin Cross	ret = write_all_blocks(s, out);
1751e17b313a6257b7b5081e178e81435c09d60378eColin Cross
176b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	output_file_close(out);
17728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
1781e17b313a6257b7b5081e178e81435c09d60378eColin Cross	return ret;
1791e17b313a6257b7b5081e178e81435c09d60378eColin Cross}
1801e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1811e17b313a6257b7b5081e178e81435c09d60378eColin Crossint sparse_file_callback(struct sparse_file *s, bool sparse, bool crc,
1821e17b313a6257b7b5081e178e81435c09d60378eColin Cross		int (*write)(void *priv, const void *data, int len), void *priv)
1831e17b313a6257b7b5081e178e81435c09d60378eColin Cross{
1841e17b313a6257b7b5081e178e81435c09d60378eColin Cross	int ret;
1851e17b313a6257b7b5081e178e81435c09d60378eColin Cross	int chunks;
1861e17b313a6257b7b5081e178e81435c09d60378eColin Cross	struct output_file *out;
1871e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1881e17b313a6257b7b5081e178e81435c09d60378eColin Cross	chunks = sparse_count_chunks(s);
189b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	out = output_file_open_callback(write, priv, s->block_size, s->len, false,
1901e17b313a6257b7b5081e178e81435c09d60378eColin Cross			sparse, chunks, crc);
1911e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1921e17b313a6257b7b5081e178e81435c09d60378eColin Cross	if (!out)
1931e17b313a6257b7b5081e178e81435c09d60378eColin Cross		return -ENOMEM;
1941e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1951e17b313a6257b7b5081e178e81435c09d60378eColin Cross	ret = write_all_blocks(s, out);
1961e17b313a6257b7b5081e178e81435c09d60378eColin Cross
197b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	output_file_close(out);
1981e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1991e17b313a6257b7b5081e178e81435c09d60378eColin Cross	return ret;
20028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
201a21930b6b0dbb04a52948566d58fb48c6db58babColin Cross
202031a748b2a9bf6dcfd3983d8f0f616718fcddd88Mark Salyzynstatic int out_counter_write(void *priv, const void *data __unused, int len)
203bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross{
204bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	int64_t *count = priv;
205bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	*count += len;
206bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	return 0;
207bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross}
208bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
209317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Crossint64_t sparse_file_len(struct sparse_file *s, bool sparse, bool crc)
210317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross{
211317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	int ret;
212317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	int chunks = sparse_count_chunks(s);
213317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	int64_t count = 0;
214317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	struct output_file *out;
215317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross
216b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	out = output_file_open_callback(out_counter_write, &count,
217317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross			s->block_size, s->len, false, sparse, chunks, crc);
218317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	if (!out) {
219317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross		return -1;
220317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	}
221317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross
222317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	ret = write_all_blocks(s, out);
223317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross
224b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	output_file_close(out);
225317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross
226317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	if (ret < 0) {
227317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross		return -1;
228317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	}
229317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross
230317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	return count;
231317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross}
232317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross
233bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Crossstatic struct backed_block *move_chunks_up_to_len(struct sparse_file *from,
234bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		struct sparse_file *to, unsigned int len)
235bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross{
236bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	int64_t count = 0;
237bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct output_file *out_counter;
238bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct backed_block *last_bb = NULL;
239bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct backed_block *bb;
240bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct backed_block *start;
241cfd3a03d3d147fca7a33d6f583b7047c5351fc32Jeremy Compostella	unsigned int last_block = 0;
242bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	int64_t file_len = 0;
2439f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella	int ret;
244bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
245bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	/*
246cfd3a03d3d147fca7a33d6f583b7047c5351fc32Jeremy Compostella	 * overhead is sparse file header, the potential end skip
247cfd3a03d3d147fca7a33d6f583b7047c5351fc32Jeremy Compostella	 * chunk and crc chunk.
248bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	 */
249cfd3a03d3d147fca7a33d6f583b7047c5351fc32Jeremy Compostella	int overhead = sizeof(sparse_header_t) + 2 * sizeof(chunk_header_t) +
250bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			sizeof(uint32_t);
251bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	len -= overhead;
252bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
253bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	start = backed_block_iter_new(from->backed_block_list);
254b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	out_counter = output_file_open_callback(out_counter_write, &count,
255bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			to->block_size, to->len, false, true, 0, false);
256bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	if (!out_counter) {
257bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		return NULL;
258bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	}
259bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
260bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	for (bb = start; bb; bb = backed_block_iter_next(bb)) {
261bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		count = 0;
262cfd3a03d3d147fca7a33d6f583b7047c5351fc32Jeremy Compostella		if (backed_block_block(bb) > last_block)
263cfd3a03d3d147fca7a33d6f583b7047c5351fc32Jeremy Compostella			count += sizeof(chunk_header_t);
264cfd3a03d3d147fca7a33d6f583b7047c5351fc32Jeremy Compostella		last_block = backed_block_block(bb) +
265cfd3a03d3d147fca7a33d6f583b7047c5351fc32Jeremy Compostella				DIV_ROUND_UP(backed_block_len(bb), to->block_size);
266cfd3a03d3d147fca7a33d6f583b7047c5351fc32Jeremy Compostella
267bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		/* will call out_counter_write to update count */
2689f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella		ret = sparse_file_write_block(out_counter, bb);
2699f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella		if (ret) {
2709f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella			bb = NULL;
2719f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella			goto out;
2729f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella		}
273bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		if (file_len + count > len) {
274bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			/*
275bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			 * If the remaining available size is more than 1/8th of the
276bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			 * requested size, split the chunk.  Results in sparse files that
277bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			 * are at least 7/8ths of the requested size
278bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			 */
279cfd3a03d3d147fca7a33d6f583b7047c5351fc32Jeremy Compostella			file_len += sizeof(chunk_header_t);
280bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			if (!last_bb || (len - file_len > (len / 8))) {
281bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross				backed_block_split(from->backed_block_list, bb, len - file_len);
282bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross				last_bb = bb;
283bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			}
2849f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostella			goto move;
285bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		}
286bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		file_len += count;
287bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		last_bb = bb;
288bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	}
289bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
2909f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostellamove:
291bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	backed_block_list_move(from->backed_block_list,
292bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		to->backed_block_list, start, last_bb);
293bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
2949f0d6bdd6691cbe78a3c03e531cb69ec2cc63602Jeremy Compostellaout:
295b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	output_file_close(out_counter);
296bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
297bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	return bb;
298bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross}
299bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
300bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Crossint sparse_file_resparse(struct sparse_file *in_s, unsigned int max_len,
301bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		struct sparse_file **out_s, int out_s_count)
302bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross{
303bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct backed_block *bb;
304bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct sparse_file *s;
305bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct sparse_file *tmp;
306bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	int c = 0;
307bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
308bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	tmp = sparse_file_new(in_s->block_size, in_s->len);
309bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	if (!tmp) {
310bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		return -ENOMEM;
311bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	}
312bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
313bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	do {
314bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		s = sparse_file_new(in_s->block_size, in_s->len);
315bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
316bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		bb = move_chunks_up_to_len(in_s, s, max_len);
317bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
318bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		if (c < out_s_count) {
319bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			out_s[c] = s;
320bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		} else {
321bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			backed_block_list_move(s->backed_block_list, tmp->backed_block_list,
322bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross					NULL, NULL);
323bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			sparse_file_destroy(s);
324bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		}
325bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		c++;
326bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	} while (bb);
327bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
328bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	backed_block_list_move(tmp->backed_block_list, in_s->backed_block_list,
329bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			NULL, NULL);
330bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
331bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	sparse_file_destroy(tmp);
332bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
333bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	return c;
334bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross}
335bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
336a21930b6b0dbb04a52948566d58fb48c6db58babColin Crossvoid sparse_file_verbose(struct sparse_file *s)
337a21930b6b0dbb04a52948566d58fb48c6db58babColin Cross{
338a21930b6b0dbb04a52948566d58fb48c6db58babColin Cross	s->verbose = true;
339a21930b6b0dbb04a52948566d58fb48c6db58babColin Cross}
340