sparse.c revision 9e1f17e926fa20255c5f4b4d2f68aa98a964253a
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" 2728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 2828fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct sparse_file *sparse_file_new(unsigned int block_size, int64_t len) 2928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 3028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross struct sparse_file *s = calloc(sizeof(struct sparse_file), 1); 3128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (!s) { 3228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return NULL; 3328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross } 3428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 35411619e921904b896eddae81c086c1f687c8304dColin Cross s->backed_block_list = backed_block_list_new(); 36411619e921904b896eddae81c086c1f687c8304dColin Cross if (!s->backed_block_list) { 37411619e921904b896eddae81c086c1f687c8304dColin Cross free(s); 38411619e921904b896eddae81c086c1f687c8304dColin Cross return NULL; 39411619e921904b896eddae81c086c1f687c8304dColin Cross } 4028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 4128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross s->block_size = block_size; 4228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross s->len = len; 4328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 4428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return s; 4528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 4628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 4728fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossvoid sparse_file_destroy(struct sparse_file *s) 4828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 49411619e921904b896eddae81c086c1f687c8304dColin Cross backed_block_list_destroy(s->backed_block_list); 5028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross free(s); 5128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 5228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 5328fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_data(struct sparse_file *s, 5428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross void *data, unsigned int len, unsigned int block) 5528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 56b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return backed_block_add_data(s->backed_block_list, data, len, block); 5728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 5828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 5928fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_fill(struct sparse_file *s, 6028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross uint32_t fill_val, unsigned int len, unsigned int block) 6128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 62b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return backed_block_add_fill(s->backed_block_list, fill_val, len, block); 6328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 6428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 6528fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_file(struct sparse_file *s, 6628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross const char *filename, int64_t file_offset, unsigned int len, 6728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross unsigned int block) 6828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 69b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return backed_block_add_file(s->backed_block_list, filename, file_offset, 70b55dceea986ab24f8b836b5116b389ed619c816eColin Cross len, block); 7128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 7228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 739e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Crossint sparse_file_add_fd(struct sparse_file *s, 749e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross int fd, int64_t file_offset, unsigned int len, unsigned int block) 759e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross{ 769e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross return backed_block_add_fd(s->backed_block_list, fd, file_offset, 779e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross len, block); 789e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross} 79b55dceea986ab24f8b836b5116b389ed619c816eColin Crossunsigned int sparse_count_chunks(struct sparse_file *s) 8028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 81b55dceea986ab24f8b836b5116b389ed619c816eColin Cross struct backed_block *bb; 82b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int last_block = 0; 83b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int chunks = 0; 84b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 85b55dceea986ab24f8b836b5116b389ed619c816eColin Cross for (bb = backed_block_iter_new(s->backed_block_list); bb; 86b55dceea986ab24f8b836b5116b389ed619c816eColin Cross bb = backed_block_iter_next(bb)) { 87b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (backed_block_block(bb) > last_block) { 88b55dceea986ab24f8b836b5116b389ed619c816eColin Cross /* If there is a gap between chunks, add a skip chunk */ 89b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunks++; 90b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 91b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunks++; 92b55dceea986ab24f8b836b5116b389ed619c816eColin Cross last_block = backed_block_block(bb) + 93b55dceea986ab24f8b836b5116b389ed619c816eColin Cross DIV_ROUND_UP(backed_block_len(bb), s->block_size); 94b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 95b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (last_block < DIV_ROUND_UP(s->len, s->block_size)) { 96b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunks++; 97b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 9828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 99b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return chunks; 10028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 10128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 10228fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_write(struct sparse_file *s, int fd, bool gz, bool sparse, 10328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross bool crc) 10428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 105b55dceea986ab24f8b836b5116b389ed619c816eColin Cross struct backed_block *bb; 106b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int last_block = 0; 107b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int64_t pad; 108b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int chunks; 109b55dceea986ab24f8b836b5116b389ed619c816eColin Cross struct output_file *out; 110b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 111b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunks = sparse_count_chunks(s); 112b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out = open_output_fd(fd, s->block_size, s->len, gz, sparse, chunks, crc); 11328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 11428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (!out) 11528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -ENOMEM; 11628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 117b55dceea986ab24f8b836b5116b389ed619c816eColin Cross for (bb = backed_block_iter_new(s->backed_block_list); bb; 118b55dceea986ab24f8b836b5116b389ed619c816eColin Cross bb = backed_block_iter_next(bb)) { 119b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (backed_block_block(bb) > last_block) { 120b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int blocks = backed_block_block(bb) - last_block; 121b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_skip_chunk(out, (int64_t)blocks * s->block_size); 122b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 123b55dceea986ab24f8b836b5116b389ed619c816eColin Cross switch (backed_block_type(bb)) { 124b55dceea986ab24f8b836b5116b389ed619c816eColin Cross case BACKED_BLOCK_DATA: 125b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_data_chunk(out, backed_block_len(bb), backed_block_data(bb)); 126b55dceea986ab24f8b836b5116b389ed619c816eColin Cross break; 127b55dceea986ab24f8b836b5116b389ed619c816eColin Cross case BACKED_BLOCK_FILE: 128b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_file_chunk(out, backed_block_len(bb), 129b55dceea986ab24f8b836b5116b389ed619c816eColin Cross backed_block_filename(bb), backed_block_file_offset(bb)); 130b55dceea986ab24f8b836b5116b389ed619c816eColin Cross break; 1319e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross case BACKED_BLOCK_FD: 1329e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross write_fd_chunk(out, backed_block_len(bb), 1339e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross backed_block_fd(bb), backed_block_file_offset(bb)); 1349e1f17e926fa20255c5f4b4d2f68aa98a964253aColin Cross break; 135b55dceea986ab24f8b836b5116b389ed619c816eColin Cross case BACKED_BLOCK_FILL: 136b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_fill_chunk(out, backed_block_len(bb), 137b55dceea986ab24f8b836b5116b389ed619c816eColin Cross backed_block_fill_val(bb)); 138b55dceea986ab24f8b836b5116b389ed619c816eColin Cross break; 139b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 140b55dceea986ab24f8b836b5116b389ed619c816eColin Cross last_block = backed_block_block(bb) + 141b55dceea986ab24f8b836b5116b389ed619c816eColin Cross DIV_ROUND_UP(backed_block_len(bb), s->block_size); 142b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 14328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 144b55dceea986ab24f8b836b5116b389ed619c816eColin Cross pad = s->len - last_block * s->block_size; 145b55dceea986ab24f8b836b5116b389ed619c816eColin Cross assert(pad >= 0); 146b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (pad > 0) { 147b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_skip_chunk(out, pad); 148b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 14928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 15028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross close_output_file(out); 15128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 15228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 15328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 154