diff options
author | Colin Cross <ccross@android.com> | 2012-05-20 13:28:05 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2012-07-09 22:09:36 -0700 |
commit | 28fa5bc347390480fe190294c6c385b6a9f0d68b (patch) | |
tree | 59189cf41baf263befeba392fc5bab814740eab1 /libsparse/sparse.c | |
parent | 2177c79bddc66e295599d87007d4cbec549e1cac (diff) |
system/core: move libsparse into system/core
This moves an exact copy of libsparse from
system/extras/ext4_utils/libsparse to system/core/libsparse in
preparation for linking tools in system/core against it.
Change-Id: If664e4fcfd6612844ac745589beb1517e7f9fe58
Diffstat (limited to 'libsparse/sparse.c')
-rw-r--r-- | libsparse/sparse.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/libsparse/sparse.c b/libsparse/sparse.c new file mode 100644 index 000000000..d6f556114 --- /dev/null +++ b/libsparse/sparse.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> + +#include <sparse/sparse.h> + +#include "sparse_file.h" + +#include "output_file.h" +#include "backed_block.h" +#include "sparse_defs.h" + + +struct sparse_file *sparse_file_new(unsigned int block_size, int64_t len) +{ + struct sparse_file *s = calloc(sizeof(struct sparse_file), 1); + if (!s) { + return NULL; + } + + /* TODO: allocate backed block list */ + + s->block_size = block_size; + s->len = len; + + return s; +} + +void sparse_file_destroy(struct sparse_file *s) +{ + free_data_blocks(); + free(s); +} + +int sparse_file_add_data(struct sparse_file *s, + void *data, unsigned int len, unsigned int block) +{ + queue_data_block(data, len, block); + + return 0; +} + +int sparse_file_add_fill(struct sparse_file *s, + uint32_t fill_val, unsigned int len, unsigned int block) +{ + queue_fill_block(fill_val, len, block); + + return 0; +} + +int sparse_file_add_file(struct sparse_file *s, + const char *filename, int64_t file_offset, unsigned int len, + unsigned int block) +{ + queue_data_file(filename, file_offset, len, block); + + return 0; +} + +struct count_chunks { + unsigned int chunks; + int64_t cur_ptr; + unsigned int block_size; +}; + +static void count_data_block(void *priv, int64_t off, void *data, int len) +{ + struct count_chunks *count_chunks = priv; + if (off > count_chunks->cur_ptr) + count_chunks->chunks++; + count_chunks->cur_ptr = off + ALIGN(len, count_chunks->block_size); + count_chunks->chunks++; +} + +static void count_fill_block(void *priv, int64_t off, unsigned int fill_val, int len) +{ + struct count_chunks *count_chunks = priv; + if (off > count_chunks->cur_ptr) + count_chunks->chunks++; + count_chunks->cur_ptr = off + ALIGN(len, count_chunks->block_size); + count_chunks->chunks++; +} + +static void count_file_block(void *priv, int64_t off, const char *file, + int64_t offset, int len) +{ + struct count_chunks *count_chunks = priv; + if (off > count_chunks->cur_ptr) + count_chunks->chunks++; + count_chunks->cur_ptr = off + ALIGN(len, count_chunks->block_size); + count_chunks->chunks++; +} + +static int count_sparse_chunks(unsigned int block_size, int64_t len) +{ + struct count_chunks count_chunks = {0, 0, block_size}; + + for_each_data_block(count_data_block, count_file_block, count_fill_block, &count_chunks, block_size); + + if (count_chunks.cur_ptr != len) + count_chunks.chunks++; + + return count_chunks.chunks; +} + +static void ext4_write_data_block(void *priv, int64_t off, void *data, int len) +{ + write_data_block(priv, off, data, len); +} + +static void ext4_write_fill_block(void *priv, int64_t off, unsigned int fill_val, int len) +{ + write_fill_block(priv, off, fill_val, len); +} + +static void ext4_write_data_file(void *priv, int64_t off, const char *file, + int64_t offset, int len) +{ + write_data_file(priv, off, file, offset, len); +} + +int sparse_file_write(struct sparse_file *s, int fd, bool gz, bool sparse, + bool crc) +{ + int chunks = count_sparse_chunks(s->block_size, s->len); + struct output_file *out = open_output_fd(fd, s->block_size, s->len, + gz, sparse, chunks, crc); + + if (!out) + return -ENOMEM; + + for_each_data_block(ext4_write_data_block, ext4_write_data_file, ext4_write_fill_block, out, s->block_size); + + if (s->len) + pad_output_file(out, s->len); + + close_output_file(out); + + return 0; +} |