sparse.c revision f1ec8ac84a8540b92a16f187bfa92b2f3c63917e
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
2228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_file.h"
2328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
2428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "output_file.h"
2528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "backed_block.h"
2628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_defs.h"
27bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross#include "sparse_format.h"
2828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
2928fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct sparse_file *sparse_file_new(unsigned int block_size, int64_t len)
3028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
3128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	struct sparse_file *s = calloc(sizeof(struct sparse_file), 1);
3228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (!s) {
3328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return NULL;
3428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
3528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
36be8ddcb35a459481c0bcf5bfe645c1fefe963f5cColin Cross	s->backed_block_list = backed_block_list_new(block_size);
37411619e921904b896eddae81c086c1f687c8304dColin Cross	if (!s->backed_block_list) {
38411619e921904b896eddae81c086c1f687c8304dColin Cross		free(s);
39411619e921904b896eddae81c086c1f687c8304dColin Cross		return NULL;
40411619e921904b896eddae81c086c1f687c8304dColin Cross	}
4128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
4228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	s->block_size = block_size;
4328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	s->len = len;
4428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
4528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	return s;
4628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
4728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
4828fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossvoid sparse_file_destroy(struct sparse_file *s)
4928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
50411619e921904b896eddae81c086c1f687c8304dColin Cross	backed_block_list_destroy(s->backed_block_list);
5128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	free(s);
5228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
5328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
5428fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_data(struct sparse_file *s,
5528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		void *data, unsigned int len, unsigned int block)
5628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
57b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return backed_block_add_data(s->backed_block_list, data, len, block);
5828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
5928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
6028fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_fill(struct sparse_file *s,
6128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		uint32_t fill_val, unsigned int len, unsigned int block)
6228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
63b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return backed_block_add_fill(s->backed_block_list, fill_val, len, block);
6428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
6528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
6628fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_file(struct sparse_file *s,
6728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		const char *filename, int64_t file_offset, unsigned int len,
6828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		unsigned int block)
6928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
70b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return backed_block_add_file(s->backed_block_list, filename, file_offset,
71b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			len, block);
7228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
7328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
749e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Crossint sparse_file_add_fd(struct sparse_file *s,
759e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross		int fd, int64_t file_offset, unsigned int len, unsigned int block)
769e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross{
779e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross	return backed_block_add_fd(s->backed_block_list, fd, file_offset,
789e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross			len, block);
799e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross}
80b55dceea986ab24f8b836b5116b389ed619c816eColin Crossunsigned int sparse_count_chunks(struct sparse_file *s)
8128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
82b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	struct backed_block *bb;
83b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	unsigned int last_block = 0;
84b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	unsigned int chunks = 0;
85b55dceea986ab24f8b836b5116b389ed619c816eColin Cross
86b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	for (bb = backed_block_iter_new(s->backed_block_list); bb;
87b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			bb = backed_block_iter_next(bb)) {
88b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		if (backed_block_block(bb) > last_block) {
89b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			/* If there is a gap between chunks, add a skip chunk */
90b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			chunks++;
91b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		}
92b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		chunks++;
93b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		last_block = backed_block_block(bb) +
94b55dceea986ab24f8b836b5116b389ed619c816eColin Cross				DIV_ROUND_UP(backed_block_len(bb), s->block_size);
95b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	}
96b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	if (last_block < DIV_ROUND_UP(s->len, s->block_size)) {
97b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		chunks++;
98b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	}
9928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
100b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	return chunks;
10128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
10228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
1031e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic void sparse_file_write_block(struct output_file *out,
1041e17b313a6257b7b5081e178e81435c09d60378eColin Cross		struct backed_block *bb)
1051e17b313a6257b7b5081e178e81435c09d60378eColin Cross{
1061e17b313a6257b7b5081e178e81435c09d60378eColin Cross	switch (backed_block_type(bb)) {
1071e17b313a6257b7b5081e178e81435c09d60378eColin Cross	case BACKED_BLOCK_DATA:
1081e17b313a6257b7b5081e178e81435c09d60378eColin Cross		write_data_chunk(out, backed_block_len(bb), backed_block_data(bb));
1091e17b313a6257b7b5081e178e81435c09d60378eColin Cross		break;
1101e17b313a6257b7b5081e178e81435c09d60378eColin Cross	case BACKED_BLOCK_FILE:
1111e17b313a6257b7b5081e178e81435c09d60378eColin Cross		write_file_chunk(out, backed_block_len(bb),
1121e17b313a6257b7b5081e178e81435c09d60378eColin Cross				backed_block_filename(bb), backed_block_file_offset(bb));
1131e17b313a6257b7b5081e178e81435c09d60378eColin Cross		break;
1141e17b313a6257b7b5081e178e81435c09d60378eColin Cross	case BACKED_BLOCK_FD:
1151e17b313a6257b7b5081e178e81435c09d60378eColin Cross		write_fd_chunk(out, backed_block_len(bb),
1161e17b313a6257b7b5081e178e81435c09d60378eColin Cross				backed_block_fd(bb), backed_block_file_offset(bb));
1171e17b313a6257b7b5081e178e81435c09d60378eColin Cross		break;
1181e17b313a6257b7b5081e178e81435c09d60378eColin Cross	case BACKED_BLOCK_FILL:
1191e17b313a6257b7b5081e178e81435c09d60378eColin Cross		write_fill_chunk(out, backed_block_len(bb),
1201e17b313a6257b7b5081e178e81435c09d60378eColin Cross				backed_block_fill_val(bb));
1211e17b313a6257b7b5081e178e81435c09d60378eColin Cross		break;
1221e17b313a6257b7b5081e178e81435c09d60378eColin Cross	}
1231e17b313a6257b7b5081e178e81435c09d60378eColin Cross}
1241e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1251e17b313a6257b7b5081e178e81435c09d60378eColin Crossstatic int write_all_blocks(struct sparse_file *s, struct output_file *out)
12628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
127b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	struct backed_block *bb;
128b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	unsigned int last_block = 0;
129b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	int64_t pad;
13028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
131b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	for (bb = backed_block_iter_new(s->backed_block_list); bb;
132b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			bb = backed_block_iter_next(bb)) {
133b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		if (backed_block_block(bb) > last_block) {
134b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			unsigned int blocks = backed_block_block(bb) - last_block;
135b55dceea986ab24f8b836b5116b389ed619c816eColin Cross			write_skip_chunk(out, (int64_t)blocks * s->block_size);
136b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		}
1371e17b313a6257b7b5081e178e81435c09d60378eColin Cross		sparse_file_write_block(out, bb);
138b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		last_block = backed_block_block(bb) +
139b55dceea986ab24f8b836b5116b389ed619c816eColin Cross				DIV_ROUND_UP(backed_block_len(bb), s->block_size);
140b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	}
14128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
142f1ec8ac84a8540b92a16f187bfa92b2f3c63917eColin Cross	pad = s->len - (int64_t)last_block * s->block_size;
143b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	assert(pad >= 0);
144b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	if (pad > 0) {
145b55dceea986ab24f8b836b5116b389ed619c816eColin Cross		write_skip_chunk(out, pad);
146b55dceea986ab24f8b836b5116b389ed619c816eColin Cross	}
14728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
1481e17b313a6257b7b5081e178e81435c09d60378eColin Cross	return 0;
1491e17b313a6257b7b5081e178e81435c09d60378eColin Cross}
1501e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1511e17b313a6257b7b5081e178e81435c09d60378eColin Crossint sparse_file_write(struct sparse_file *s, int fd, bool gz, bool sparse,
1521e17b313a6257b7b5081e178e81435c09d60378eColin Cross		bool crc)
1531e17b313a6257b7b5081e178e81435c09d60378eColin Cross{
1541e17b313a6257b7b5081e178e81435c09d60378eColin Cross	int ret;
1551e17b313a6257b7b5081e178e81435c09d60378eColin Cross	int chunks;
1561e17b313a6257b7b5081e178e81435c09d60378eColin Cross	struct output_file *out;
1571e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1581e17b313a6257b7b5081e178e81435c09d60378eColin Cross	chunks = sparse_count_chunks(s);
159b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	out = output_file_open_fd(fd, s->block_size, s->len, gz, sparse, chunks, crc);
1601e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1611e17b313a6257b7b5081e178e81435c09d60378eColin Cross	if (!out)
1621e17b313a6257b7b5081e178e81435c09d60378eColin Cross		return -ENOMEM;
1631e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1641e17b313a6257b7b5081e178e81435c09d60378eColin Cross	ret = write_all_blocks(s, out);
1651e17b313a6257b7b5081e178e81435c09d60378eColin Cross
166b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	output_file_close(out);
16728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
1681e17b313a6257b7b5081e178e81435c09d60378eColin Cross	return ret;
1691e17b313a6257b7b5081e178e81435c09d60378eColin Cross}
1701e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1711e17b313a6257b7b5081e178e81435c09d60378eColin Crossint sparse_file_callback(struct sparse_file *s, bool sparse, bool crc,
1721e17b313a6257b7b5081e178e81435c09d60378eColin Cross		int (*write)(void *priv, const void *data, int len), void *priv)
1731e17b313a6257b7b5081e178e81435c09d60378eColin Cross{
1741e17b313a6257b7b5081e178e81435c09d60378eColin Cross	int ret;
1751e17b313a6257b7b5081e178e81435c09d60378eColin Cross	int chunks;
1761e17b313a6257b7b5081e178e81435c09d60378eColin Cross	struct output_file *out;
1771e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1781e17b313a6257b7b5081e178e81435c09d60378eColin Cross	chunks = sparse_count_chunks(s);
179b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	out = output_file_open_callback(write, priv, s->block_size, s->len, false,
1801e17b313a6257b7b5081e178e81435c09d60378eColin Cross			sparse, chunks, crc);
1811e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1821e17b313a6257b7b5081e178e81435c09d60378eColin Cross	if (!out)
1831e17b313a6257b7b5081e178e81435c09d60378eColin Cross		return -ENOMEM;
1841e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1851e17b313a6257b7b5081e178e81435c09d60378eColin Cross	ret = write_all_blocks(s, out);
1861e17b313a6257b7b5081e178e81435c09d60378eColin Cross
187b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	output_file_close(out);
1881e17b313a6257b7b5081e178e81435c09d60378eColin Cross
1891e17b313a6257b7b5081e178e81435c09d60378eColin Cross	return ret;
19028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
191a21930b6b0dbb04a52948566d58fb48c6db58babColin Cross
192bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Crossstatic int out_counter_write(void *priv, const void *data, int len)
193bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross{
194bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	int64_t *count = priv;
195bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	*count += len;
196bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	return 0;
197bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross}
198bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
199317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Crossint64_t sparse_file_len(struct sparse_file *s, bool sparse, bool crc)
200317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross{
201317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	int ret;
202317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	int chunks = sparse_count_chunks(s);
203317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	int64_t count = 0;
204317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	struct output_file *out;
205317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross
206b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	out = output_file_open_callback(out_counter_write, &count,
207317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross			s->block_size, s->len, false, sparse, chunks, crc);
208317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	if (!out) {
209317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross		return -1;
210317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	}
211317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross
212317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	ret = write_all_blocks(s, out);
213317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross
214b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	output_file_close(out);
215317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross
216317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	if (ret < 0) {
217317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross		return -1;
218317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	}
219317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross
220317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross	return count;
221317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross}
222317a09e2d47257df5e0972c85f14c2a6ffdbbfd2Colin Cross
223bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Crossstatic struct backed_block *move_chunks_up_to_len(struct sparse_file *from,
224bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		struct sparse_file *to, unsigned int len)
225bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross{
226bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	int64_t count = 0;
227bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct output_file *out_counter;
228bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct backed_block *last_bb = NULL;
229bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct backed_block *bb;
230bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct backed_block *start;
231bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	int64_t file_len = 0;
232bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
233bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	/*
234bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	 * overhead is sparse file header, initial skip chunk, split chunk, end
235bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	 * skip chunk, and crc chunk.
236bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	 */
237bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	int overhead = sizeof(sparse_header_t) + 4 * sizeof(chunk_header_t) +
238bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			sizeof(uint32_t);
239bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	len -= overhead;
240bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
241bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	start = backed_block_iter_new(from->backed_block_list);
242b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	out_counter = output_file_open_callback(out_counter_write, &count,
243bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			to->block_size, to->len, false, true, 0, false);
244bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	if (!out_counter) {
245bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		return NULL;
246bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	}
247bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
248bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	for (bb = start; bb; bb = backed_block_iter_next(bb)) {
249bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		count = 0;
250bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		/* will call out_counter_write to update count */
251bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		sparse_file_write_block(out_counter, bb);
252bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		if (file_len + count > len) {
253bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			/*
254bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			 * If the remaining available size is more than 1/8th of the
255bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			 * requested size, split the chunk.  Results in sparse files that
256bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			 * are at least 7/8ths of the requested size
257bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			 */
258bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			if (!last_bb || (len - file_len > (len / 8))) {
259bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross				backed_block_split(from->backed_block_list, bb, len - file_len);
260bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross				last_bb = bb;
261bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			}
262bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			goto out;
263bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		}
264bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		file_len += count;
265bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		last_bb = bb;
266bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	}
267bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
268bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Crossout:
269bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	backed_block_list_move(from->backed_block_list,
270bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		to->backed_block_list, start, last_bb);
271bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
272b43828b247fd4f1e0373584de0504004c69eeac9Colin Cross	output_file_close(out_counter);
273bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
274bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	return bb;
275bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross}
276bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
277bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Crossint sparse_file_resparse(struct sparse_file *in_s, unsigned int max_len,
278bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		struct sparse_file **out_s, int out_s_count)
279bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross{
280bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct backed_block *bb;
281bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	unsigned int overhead;
282bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct sparse_file *s;
283bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	struct sparse_file *tmp;
284bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	int c = 0;
285bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
286bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	tmp = sparse_file_new(in_s->block_size, in_s->len);
287bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	if (!tmp) {
288bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		return -ENOMEM;
289bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	}
290bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
291bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	do {
292bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		s = sparse_file_new(in_s->block_size, in_s->len);
293bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
294bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		bb = move_chunks_up_to_len(in_s, s, max_len);
295bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
296bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		if (c < out_s_count) {
297bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			out_s[c] = s;
298bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		} else {
299bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			backed_block_list_move(s->backed_block_list, tmp->backed_block_list,
300bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross					NULL, NULL);
301bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			sparse_file_destroy(s);
302bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		}
303bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross		c++;
304bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	} while (bb);
305bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
306bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	backed_block_list_move(tmp->backed_block_list, in_s->backed_block_list,
307bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross			NULL, NULL);
308bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
309bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	sparse_file_destroy(tmp);
310bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
311bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross	return c;
312bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross}
313bdc6d39ed6c09199a5d806f29b71b44cbb27c5c2Colin Cross
314a21930b6b0dbb04a52948566d58fb48c6db58babColin Crossvoid sparse_file_verbose(struct sparse_file *s)
315a21930b6b0dbb04a52948566d58fb48c6db58babColin Cross{
316a21930b6b0dbb04a52948566d58fb48c6db58babColin Cross	s->verbose = true;
317a21930b6b0dbb04a52948566d58fb48c6db58babColin Cross}
318