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