sparse.c revision 28fa5bc347390480fe190294c6c385b6a9f0d68b
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 1728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <stdlib.h> 1828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 1928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sparse/sparse.h> 2028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 2128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_file.h" 2228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 2328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "output_file.h" 2428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "backed_block.h" 2528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_defs.h" 2628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 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 3528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross /* TODO: allocate backed block list */ 3628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 3728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross s->block_size = block_size; 3828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross s->len = len; 3928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 4028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return s; 4128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 4228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 4328fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossvoid sparse_file_destroy(struct sparse_file *s) 4428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 4528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross free_data_blocks(); 4628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross free(s); 4728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 4828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 4928fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_data(struct sparse_file *s, 5028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross void *data, unsigned int len, unsigned int block) 5128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 5228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross queue_data_block(data, len, block); 5328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 5428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 5528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 5628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 5728fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_add_fill(struct sparse_file *s, 5828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross uint32_t fill_val, unsigned int len, unsigned int block) 5928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 6028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross queue_fill_block(fill_val, len, block); 6128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 6228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 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{ 6928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross queue_data_file(filename, file_offset, len, block); 7028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 7128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 7228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 7328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 7428fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct count_chunks { 7528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross unsigned int chunks; 7628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int64_t cur_ptr; 7728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross unsigned int block_size; 7828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}; 7928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 8028fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void count_data_block(void *priv, int64_t off, void *data, int len) 8128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 8228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross struct count_chunks *count_chunks = priv; 8328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (off > count_chunks->cur_ptr) 8428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross count_chunks->chunks++; 8528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross count_chunks->cur_ptr = off + ALIGN(len, count_chunks->block_size); 8628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross count_chunks->chunks++; 8728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 8828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 8928fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void count_fill_block(void *priv, int64_t off, unsigned int fill_val, int len) 9028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 9128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross struct count_chunks *count_chunks = priv; 9228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (off > count_chunks->cur_ptr) 9328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross count_chunks->chunks++; 9428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross count_chunks->cur_ptr = off + ALIGN(len, count_chunks->block_size); 9528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross count_chunks->chunks++; 9628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 9728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 9828fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void count_file_block(void *priv, int64_t off, const char *file, 9928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int64_t offset, int len) 10028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 10128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross struct count_chunks *count_chunks = priv; 10228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (off > count_chunks->cur_ptr) 10328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross count_chunks->chunks++; 10428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross count_chunks->cur_ptr = off + ALIGN(len, count_chunks->block_size); 10528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross count_chunks->chunks++; 10628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 10728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 10828fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic int count_sparse_chunks(unsigned int block_size, int64_t len) 10928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 11028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross struct count_chunks count_chunks = {0, 0, block_size}; 11128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 11228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross for_each_data_block(count_data_block, count_file_block, count_fill_block, &count_chunks, block_size); 11328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 11428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (count_chunks.cur_ptr != len) 11528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross count_chunks.chunks++; 11628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 11728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return count_chunks.chunks; 11828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 11928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 12028fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void ext4_write_data_block(void *priv, int64_t off, void *data, int len) 12128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 12228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross write_data_block(priv, off, data, len); 12328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 12428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 12528fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void ext4_write_fill_block(void *priv, int64_t off, unsigned int fill_val, int len) 12628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 12728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross write_fill_block(priv, off, fill_val, len); 12828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 12928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 13028fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void ext4_write_data_file(void *priv, int64_t off, const char *file, 13128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int64_t offset, int len) 13228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 13328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross write_data_file(priv, off, file, offset, len); 13428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 13528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 13628fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossint sparse_file_write(struct sparse_file *s, int fd, bool gz, bool sparse, 13728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross bool crc) 13828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{ 13928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross int chunks = count_sparse_chunks(s->block_size, s->len); 14028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross struct output_file *out = open_output_fd(fd, s->block_size, s->len, 14128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross gz, sparse, chunks, crc); 14228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 14328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (!out) 14428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return -ENOMEM; 14528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 14628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross for_each_data_block(ext4_write_data_block, ext4_write_data_file, ext4_write_fill_block, out, s->block_size); 14728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 14828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross if (s->len) 14928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross pad_output_file(out, s->len); 15028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 15128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross close_output_file(out); 15228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross 15328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross return 0; 15428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross} 155