sparse.c revision b55dceea986ab24f8b836b5116b389ed619c816e
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 73b55dceea986ab24f8b836b5116b389ed619c816eColin Crossunsigned int sparse_count_chunks(struct sparse_file *s) 7428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 75b55dceea986ab24f8b836b5116b389ed619c816eColin Cross struct backed_block *bb; 76b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int last_block = 0; 77b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int chunks = 0; 78b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 79b55dceea986ab24f8b836b5116b389ed619c816eColin Cross for (bb = backed_block_iter_new(s->backed_block_list); bb; 80b55dceea986ab24f8b836b5116b389ed619c816eColin Cross bb = backed_block_iter_next(bb)) { 81b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (backed_block_block(bb) > last_block) { 82b55dceea986ab24f8b836b5116b389ed619c816eColin Cross /* If there is a gap between chunks, add a skip chunk */ 83b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunks++; 84b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 85b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunks++; 86b55dceea986ab24f8b836b5116b389ed619c816eColin Cross last_block = backed_block_block(bb) + 87b55dceea986ab24f8b836b5116b389ed619c816eColin Cross DIV_ROUND_UP(backed_block_len(bb), s->block_size); 88b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 89b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (last_block < DIV_ROUND_UP(s->len, s->block_size)) { 90b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunks++; 91b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 9228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 93b55dceea986ab24f8b836b5116b389ed619c816eColin Cross return chunks; 9428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 9528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 9628fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_write(struct sparse_file *s, int fd, bool gz, bool sparse, 9728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross bool crc) 9828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 99b55dceea986ab24f8b836b5116b389ed619c816eColin Cross struct backed_block *bb; 100b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int last_block = 0; 101b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int64_t pad; 102b55dceea986ab24f8b836b5116b389ed619c816eColin Cross int chunks; 103b55dceea986ab24f8b836b5116b389ed619c816eColin Cross struct output_file *out; 104b55dceea986ab24f8b836b5116b389ed619c816eColin Cross 105b55dceea986ab24f8b836b5116b389ed619c816eColin Cross chunks = sparse_count_chunks(s); 106b55dceea986ab24f8b836b5116b389ed619c816eColin Cross out = open_output_fd(fd, s->block_size, s->len, gz, sparse, chunks, crc); 10728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 10828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (!out) 10928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -ENOMEM; 11028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 111b55dceea986ab24f8b836b5116b389ed619c816eColin Cross for (bb = backed_block_iter_new(s->backed_block_list); bb; 112b55dceea986ab24f8b836b5116b389ed619c816eColin Cross bb = backed_block_iter_next(bb)) { 113b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (backed_block_block(bb) > last_block) { 114b55dceea986ab24f8b836b5116b389ed619c816eColin Cross unsigned int blocks = backed_block_block(bb) - last_block; 115b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_skip_chunk(out, (int64_t)blocks * s->block_size); 116b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 117b55dceea986ab24f8b836b5116b389ed619c816eColin Cross switch (backed_block_type(bb)) { 118b55dceea986ab24f8b836b5116b389ed619c816eColin Cross case BACKED_BLOCK_DATA: 119b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_data_chunk(out, backed_block_len(bb), backed_block_data(bb)); 120b55dceea986ab24f8b836b5116b389ed619c816eColin Cross break; 121b55dceea986ab24f8b836b5116b389ed619c816eColin Cross case BACKED_BLOCK_FILE: 122b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_file_chunk(out, backed_block_len(bb), 123b55dceea986ab24f8b836b5116b389ed619c816eColin Cross backed_block_filename(bb), backed_block_file_offset(bb)); 124b55dceea986ab24f8b836b5116b389ed619c816eColin Cross break; 125b55dceea986ab24f8b836b5116b389ed619c816eColin Cross case BACKED_BLOCK_FILL: 126b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_fill_chunk(out, backed_block_len(bb), 127b55dceea986ab24f8b836b5116b389ed619c816eColin Cross backed_block_fill_val(bb)); 128b55dceea986ab24f8b836b5116b389ed619c816eColin Cross break; 129b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 130b55dceea986ab24f8b836b5116b389ed619c816eColin Cross last_block = backed_block_block(bb) + 131b55dceea986ab24f8b836b5116b389ed619c816eColin Cross DIV_ROUND_UP(backed_block_len(bb), s->block_size); 132b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 13328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 134b55dceea986ab24f8b836b5116b389ed619c816eColin Cross pad = s->len - last_block * s->block_size; 135b55dceea986ab24f8b836b5116b389ed619c816eColin Cross assert(pad >= 0); 136b55dceea986ab24f8b836b5116b389ed619c816eColin Cross if (pad > 0) { 137b55dceea986ab24f8b836b5116b389ed619c816eColin Cross write_skip_chunk(out, pad); 138b55dceea986ab24f8b836b5116b389ed619c816eColin Cross } 13928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 14028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross close_output_file(out); 14128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 14228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 14328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 144