diff options
author | Colin Cross <ccross@android.com> | 2012-07-17 23:39:43 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2012-07-17 23:39:43 -0700 |
commit | 868ea3d59ea2c500348c3843c76f6df0468b5481 (patch) | |
tree | f087777f96e07935fae0349360e810b62c0ffced | |
parent | 29b6d3325b84acc8e9a3bd12a05fef5073bbaf9d (diff) | |
parent | cab036827411791e8f197a0194f95faad6f12cec (diff) | |
download | extras-868ea3d59ea2c500348c3843c76f6df0468b5481.tar.gz |
am cab03682: Merge changes I32c33626,I93bc9cf9,I1f66f6c3
* commit 'cab036827411791e8f197a0194f95faad6f12cec':
make_ext4fs: allow sparse gzip files
libsparse: make API sane
Refactor sparse file support into libsparse
25 files changed, 687 insertions, 280 deletions
diff --git a/ext4_utils/Android.mk b/ext4_utils/Android.mk index f4f07a9b..bba74bb9 100644 --- a/ext4_utils/Android.mk +++ b/ext4_utils/Android.mk @@ -8,14 +8,11 @@ libext4_utils_src_files := \ ext4fixup.c \ ext4_utils.c \ allocate.c \ - backed_block.c \ - output_file.c \ contents.c \ extent.c \ indirect.c \ uuid.c \ sha1.c \ - sparse_crc32.c \ wipe.c # -- All host/targets including windows @@ -24,6 +21,7 @@ LOCAL_SRC_FILES := $(libext4_utils_src_files) LOCAL_MODULE := libext4_utils LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES += external/zlib +LOCAL_STATIC_LIBRARIES += libsparse ifeq ($(HAVE_SELINUX), true) LOCAL_C_INCLUDES += external/libselinux/include @@ -37,7 +35,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := make_ext4fs_main.c LOCAL_MODULE := make_ext4fs -LOCAL_STATIC_LIBRARIES += libext4_utils libz +LOCAL_STATIC_LIBRARIES += libext4_utils libsparse libz ifeq ($(HOST_OS),windows) LOCAL_LDLIBS += -lws2_32 else @@ -59,7 +57,7 @@ LOCAL_SRC_FILES := $(libext4_utils_src_files) LOCAL_MODULE := libext4_utils LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES += external/zlib -LOCAL_SHARED_LIBRARIES := libz +LOCAL_SHARED_LIBRARIES := libsparse libz ifeq ($(HAVE_SELINUX), true) LOCAL_C_INCLUDES += external/libselinux/include @@ -75,6 +73,7 @@ LOCAL_SRC_FILES := $(libext4_utils_src_files) LOCAL_MODULE := libext4_utils LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES += external/zlib +LOCAL_STATIC_LIBRARIES += libsparse ifeq ($(HAVE_SELINUX), true) LOCAL_C_INCLUDES += external/libselinux/include @@ -104,7 +103,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := ext2simg.c LOCAL_MODULE := ext2simg LOCAL_MODULE_TAGS := optional -LOCAL_SHARED_LIBRARIES += libext4_utils libz +LOCAL_SHARED_LIBRARIES += libext4_utils libsparse libz ifeq ($(HAVE_SELINUX), true) LOCAL_C_INCLUDES += external/libselinux/include @@ -119,7 +118,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := ext2simg.c LOCAL_MODULE := ext2simg LOCAL_MODULE_TAGS := optional -LOCAL_STATIC_LIBRARIES += libext4_utils libz +LOCAL_STATIC_LIBRARIES += libext4_utils libsparse libz ifeq ($(HAVE_SELINUX), true) LOCAL_C_INCLUDES += external/libselinux/include @@ -130,40 +129,6 @@ endif # HAVE_SELINUX include $(BUILD_HOST_EXECUTABLE) include $(CLEAR_VARS) - -LOCAL_SRC_FILES := simg2img.c \ - sparse_crc32.c -LOCAL_MODULE := simg2img -LOCAL_MODULE_TAGS := debug - -include $(BUILD_HOST_EXECUTABLE) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := simg2img.c \ - sparse_crc32.c -LOCAL_MODULE := simg2img -LOCAL_MODULE_TAGS := optional - -include $(BUILD_EXECUTABLE) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := img2simg.c -LOCAL_MODULE := img2simg -LOCAL_MODULE_TAGS := debug - -include $(BUILD_HOST_EXECUTABLE) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := img2simg.c -LOCAL_MODULE := img2simg -LOCAL_MODULE_TAGS := optional - -include $(BUILD_EXECUTABLE) - -include $(CLEAR_VARS) LOCAL_SRC_FILES := setup_fs.c LOCAL_MODULE := setup_fs LOCAL_MODULE_TAGS := optional @@ -175,7 +140,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := ext4fixup_main.c LOCAL_MODULE := ext4fixup LOCAL_MODULE_TAGS := optional -LOCAL_SHARED_LIBRARIES += libext4_utils libz +LOCAL_SHARED_LIBRARIES += libext4_utils libsparse libz include $(BUILD_EXECUTABLE) @@ -184,7 +149,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := ext4fixup_main.c LOCAL_MODULE := ext4fixup LOCAL_MODULE_TAGS := optional -LOCAL_STATIC_LIBRARIES += libext4_utils libz +LOCAL_STATIC_LIBRARIES += libext4_utils libsparse libz include $(BUILD_HOST_EXECUTABLE) @@ -200,14 +165,6 @@ LOCAL_IS_HOST_MODULE := true include $(BUILD_PREBUILT) -include $(CLEAR_VARS) - -LOCAL_MODULE := simg_dump.py -LOCAL_MODULE_TAGS := debug -LOCAL_SRC_FILES := simg_dump.py -LOCAL_MODULE_CLASS := EXECUTABLES -LOCAL_IS_HOST_MODULE := true - -include $(BUILD_PREBUILT) - endif + +include $(LOCAL_PATH)/libsparse/Android.mk diff --git a/ext4_utils/allocate.c b/ext4_utils/allocate.c index 0e162851..adf91baf 100644 --- a/ext4_utils/allocate.c +++ b/ext4_utils/allocate.c @@ -16,9 +16,10 @@ #include "ext4_utils.h" #include "allocate.h" -#include "backed_block.h" #include "ext4.h" +#include <sparse/sparse.h> + #include <stdio.h> #include <stdlib.h> @@ -154,8 +155,8 @@ static void allocate_bg_inode_table(struct block_group_info *bg) if (bg->inode_table == NULL) critical_error_errno("calloc"); - queue_data_block(bg->inode_table, aux_info.inode_table_blocks - * info.block_size, block); + sparse_file_add_data(info.sparse_file, bg->inode_table, + aux_info.inode_table_blocks * info.block_size, block); } void init_unused_inode_tables(void) @@ -170,9 +171,10 @@ void init_unused_inode_tables(void) block = bg->first_block + 2; if (bg->has_superblock) block += aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks + 1; - queue_fill_block(0, aux_info.inode_table_blocks * info.block_size, block); - } - } + sparse_file_add_fill(info.sparse_file, 0, + aux_info.inode_table_blocks * info.block_size, block); + } + } } static int bitmap_set_bit(u8 *bitmap, u32 bit) @@ -287,7 +289,8 @@ static void init_bg(struct block_group_info *bg, unsigned int i) u32 block = bg->first_block; if (bg->has_superblock) block += 1 + aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks; - queue_data_block(bg->bitmaps, 2 * info.block_size, block); + sparse_file_add_data(info.sparse_file, bg->bitmaps, 2 * info.block_size, + block); bg->data_blocks_used = 0; bg->free_blocks = info.blocks_per_group; diff --git a/ext4_utils/ext2simg.c b/ext4_utils/ext2simg.c index 1fe085a9..f4b6c93b 100644 --- a/ext4_utils/ext2simg.c +++ b/ext4_utils/ext2simg.c @@ -14,11 +14,8 @@ * limitations under the License. */ -#include "ext4_utils.h" -#include "make_ext4fs.h" -#include "output_file.h" -#include "backed_block.h" -#include "allocate.h" +#define _FILE_OFFSET_BITS 64 +#define _LARGEFILE64_SOURCE 1 #include <sys/types.h> #include <sys/stat.h> @@ -28,6 +25,16 @@ #include <libgen.h> #include <unistd.h> +#include <sparse/sparse.h> + +#include "ext4_utils.h" +#include "make_ext4fs.h" +#include "allocate.h" + +#if defined(__APPLE__) && defined(__MACH__) +#define off64_t off_t +#endif + #ifndef USE_MINGW /* O_BINARY is windows-specific flag */ #define O_BINARY 0 #endif @@ -120,7 +127,7 @@ static int build_sparse_ext(int fd, const char *filename) critical_error("failed to allocate block bitmap"); if (aux_info.first_data_block > 0) - queue_data_file(filename, 0, + sparse_file_add_file(info.sparse_file, filename, 0, info.block_size * aux_info.first_data_block, 0); for (i = 0; i < aux_info.groups; i++) { @@ -145,7 +152,8 @@ static int build_sparse_ext(int fd, const char *filename) u32 start_block = first_block + start_contiguous_block; u32 len_blocks = block - start_contiguous_block; - queue_data_file(filename, (u64)info.block_size * start_block, + sparse_file_add_file(info.sparse_file, filename, + (u64)info.block_size * start_block, info.block_size * len_blocks, start_block); start_contiguous_block = -1; } @@ -158,7 +166,8 @@ static int build_sparse_ext(int fd, const char *filename) if (start_contiguous_block >= 0) { u32 start_block = first_block + start_contiguous_block; u32 len_blocks = last_block - start_contiguous_block; - queue_data_file(filename, (u64)info.block_size * start_block, + sparse_file_add_file(info.sparse_file, filename, + (u64)info.block_size * start_block, info.block_size * len_blocks, start_block); } } @@ -222,6 +231,8 @@ int main(int argc, char **argv) read_ext(infd); + info.sparse_file = sparse_file_new(info.block_size, info.len); + build_sparse_ext(infd, in); close(infd); @@ -236,8 +247,10 @@ int main(int argc, char **argv) outfd = STDOUT_FILENO; } - write_ext4_image(outfd, gzip, sparse, crc, 0); + write_ext4_image(outfd, gzip, sparse, crc); close(outfd); + sparse_file_destroy(info.sparse_file); + return 0; } diff --git a/ext4_utils/ext4_utils.c b/ext4_utils/ext4_utils.c index 7f226c8b..43b44806 100644 --- a/ext4_utils/ext4_utils.c +++ b/ext4_utils/ext4_utils.c @@ -15,13 +15,13 @@ */ #include "ext4_utils.h" -#include "output_file.h" -#include "backed_block.h" #include "uuid.h" #include "allocate.h" #include "indirect.h" #include "extent.h" +#include <sparse/sparse.h> + #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> @@ -80,83 +80,10 @@ int ext4_bg_has_super_block(int bg) return 0; } -struct count_chunks { - u32 chunks; - u64 cur_ptr; -}; - -void count_data_block(void *priv, u64 off, u8 *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, info.block_size); - count_chunks->chunks++; -} - -void count_fill_block(void *priv, u64 off, u32 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, info.block_size); - count_chunks->chunks++; -} - -void count_file_block(void *priv, u64 off, const char *file, - off64_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, info.block_size); - count_chunks->chunks++; -} - -int count_sparse_chunks() -{ - struct count_chunks count_chunks = {0, 0}; - - for_each_data_block(count_data_block, count_file_block, count_fill_block, &count_chunks); - - if (count_chunks.cur_ptr != (u64) info.len) - count_chunks.chunks++; - - return count_chunks.chunks; -} - -static void ext4_write_data_block(void *priv, u64 off, u8 *data, int len) -{ - write_data_block(priv, off, data, len); -} - -static void ext4_write_fill_block(void *priv, u64 off, u32 fill_val, int len) -{ - write_fill_block(priv, off, fill_val, len); -} - -static void ext4_write_data_file(void *priv, u64 off, const char *file, - off64_t offset, int len) -{ - write_data_file(priv, off, file, offset, len); -} - /* Write the filesystem image to a file */ -void write_ext4_image(int fd, int gz, int sparse, int crc, int wipe) +void write_ext4_image(int fd, int gz, int sparse, int crc) { - int ret = 0; - - struct output_file *out = open_output_fd(fd, gz, sparse, - count_sparse_chunks(), crc, wipe); - - if (!out) - return; - - for_each_data_block(ext4_write_data_block, ext4_write_data_file, ext4_write_fill_block, out); - - pad_output_file(out, info.len); - - close_output_file(out); + sparse_file_write(info.sparse_file, fd, gz, sparse, crc); } /* Compute the rest of the parameters of the filesystem from the basic info */ @@ -299,10 +226,10 @@ void ext4_fill_in_sb() memcpy(aux_info.backup_sb[i], sb, info.block_size); /* Update the block group nr of this backup superblock */ aux_info.backup_sb[i]->s_block_group_nr = i; - queue_data_block((u8 *)aux_info.backup_sb[i], - info.block_size, group_start_block); + sparse_file_add_data(info.sparse_file, aux_info.backup_sb[i], + info.block_size, group_start_block); } - queue_data_block((u8 *)aux_info.bg_desc, + sparse_file_add_data(info.sparse_file, aux_info.bg_desc, aux_info.bg_desc_blocks * info.block_size, group_start_block + 1); header_size = 1 + aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks; @@ -328,9 +255,9 @@ void ext4_queue_sb(void) if (info.block_size > 1024) { u8 *buf = calloc(info.block_size, 1); memcpy(buf + 1024, (u8*)aux_info.sb, 1024); - queue_data_block(buf, info.block_size, 0); + sparse_file_add_data(info.sparse_file, buf, info.block_size, 0); } else { - queue_data_block((u8*)aux_info.sb, 1024, 1); + sparse_file_add_data(info.sparse_file, aux_info.sb, 1024, 1); } } diff --git a/ext4_utils/ext4_utils.h b/ext4_utils/ext4_utils.h index 1d701d0d..cad2eaea 100644 --- a/ext4_utils/ext4_utils.h +++ b/ext4_utils/ext4_utils.h @@ -25,7 +25,7 @@ extern "C" { #define _GNU_SOURCE #endif #define _FILE_OFFSET_BITS 64 -#define _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE 1 #include <sys/types.h> #include <unistd.h> @@ -119,6 +119,8 @@ struct fs_info { u32 bg_desc_reserve_blocks; const char *label; u8 no_journal; + + struct sparse_file *sparse_file; }; struct fs_aux_info { @@ -153,8 +155,7 @@ static inline int log_2(int j) } int ext4_bg_has_super_block(int bg); -void write_ext4_image(int fd, int gz, int sparse, int crc, - int wipe); +void write_ext4_image(int fd, int gz, int sparse, int crc); void ext4_create_fs_aux_info(void); void ext4_free_fs_aux_info(void); void ext4_fill_in_sb(void); diff --git a/ext4_utils/ext4fixup.c b/ext4_utils/ext4fixup.c index c664ac3a..f0124f88 100644 --- a/ext4_utils/ext4fixup.c +++ b/ext4_utils/ext4fixup.c @@ -16,11 +16,11 @@ #include "ext4_utils.h" #include "make_ext4fs.h" #include "ext4_extents.h" -#include "output_file.h" -#include "backed_block.h" #include "allocate.h" #include "ext4fixup.h" +#include <sparse/sparse.h> + #include <sys/types.h> #include <sys/stat.h> #include <sys/types.h> diff --git a/ext4_utils/extent.c b/ext4_utils/extent.c index daa25413..948bf41e 100644 --- a/ext4_utils/extent.c +++ b/ext4_utils/extent.c @@ -17,9 +17,10 @@ #include "ext4_utils.h" #include "ext4.h" #include "ext4_extents.h" -#include "backed_block.h" #include "extent.h" +#include <sparse/sparse.h> + #include <stdlib.h> #include <stdio.h> @@ -42,7 +43,7 @@ static u8 *extent_create_backing(struct block_allocation *alloc, len = min(region_len * info.block_size, backing_len); - queue_data_block(ptr, len, region_block); + sparse_file_add_data(info.sparse_file, ptr, len, region_block); ptr += len; backing_len -= len; } @@ -64,7 +65,8 @@ static void extent_create_backing_file(struct block_allocation *alloc, len = min(region_len * info.block_size, backing_len); - queue_data_file(filename, offset, len, region_block); + sparse_file_add_file(info.sparse_file, filename, offset, len, + region_block); offset += len; backing_len -= len; } @@ -123,7 +125,8 @@ static struct block_allocation *do_inode_allocate_extents( if (!data) critical_error_errno("calloc"); - queue_data_block(data, info.block_size, extent_block); + sparse_file_add_data(info.sparse_file, data, info.block_size, + extent_block); if (((int)(info.block_size - sizeof(struct ext4_extent_header) / sizeof(struct ext4_extent))) < allocation_len) { diff --git a/ext4_utils/indirect.c b/ext4_utils/indirect.c index 70f04d6e..3d97ec84 100644 --- a/ext4_utils/indirect.c +++ b/ext4_utils/indirect.c @@ -17,10 +17,11 @@ #include "ext4_utils.h" #include "ext4.h" #include "ext4_extents.h" -#include "backed_block.h" #include "indirect.h" #include "allocate.h" +#include <sparse/sparse.h> + #include <stdlib.h> #include <stdio.h> @@ -45,7 +46,7 @@ static u8 *create_backing(struct block_allocation *alloc, len = min(region_len * info.block_size, backing_len); - queue_data_block(ptr, len, region_block); + sparse_file_add_data(info.sparse_file, ptr, len, region_block); ptr += len; backing_len -= len; } @@ -122,7 +123,8 @@ static void fill_dindirect_block(u32 *dind_block, int len, struct block_allocati dind_block[i] = ind_block; u32 *ind_block_data = calloc(info.block_size, 1); - queue_data_block((u8*)ind_block_data, info.block_size, ind_block); + sparse_file_add_data(info.sparse_file, ind_block_data, info.block_size, + ind_block); int ind_block_len = min((int)aux_info.blocks_per_ind, len); fill_indirect_block(ind_block_data, ind_block_len, alloc); @@ -151,7 +153,8 @@ static void fill_tindirect_block(u32 *tind_block, int len, struct block_allocati tind_block[i] = dind_block; u32 *dind_block_data = calloc(info.block_size, 1); - queue_data_block((u8*)dind_block_data, info.block_size, dind_block); + sparse_file_add_data(info.sparse_file, dind_block_data, info.block_size, + dind_block); int dind_block_len = min((int)aux_info.blocks_per_dind, len); fill_dindirect_block(dind_block_data, dind_block_len, alloc); @@ -199,7 +202,8 @@ static int inode_attach_indirect_blocks(struct ext4_inode *inode, } u32 *ind_block_data = calloc(info.block_size, 1); - queue_data_block((u8*)ind_block_data, info.block_size, ind_block); + sparse_file_add_data(info.sparse_file, ind_block_data, info.block_size, + ind_block); fill_indirect_block(ind_block_data, len, alloc); @@ -230,7 +234,8 @@ static int inode_attach_dindirect_blocks(struct ext4_inode *inode, } u32 *dind_block_data = calloc(info.block_size, 1); - queue_data_block((u8*)dind_block_data, info.block_size, dind_block); + sparse_file_add_data(info.sparse_file, dind_block_data, info.block_size, + dind_block); fill_dindirect_block(dind_block_data, len, alloc); @@ -261,7 +266,8 @@ static int inode_attach_tindirect_blocks(struct ext4_inode *inode, } u32 *tind_block_data = calloc(info.block_size, 1); - queue_data_block((u8*)tind_block_data, info.block_size, tind_block); + sparse_file_add_data(info.sparse_file, tind_block_data, info.block_size, + tind_block); fill_tindirect_block(tind_block_data, len, alloc); @@ -440,12 +446,13 @@ void inode_attach_resize(struct ext4_inode *inode, u32 *dind_block_data = calloc(info.block_size, 1); if (!dind_block_data) critical_error_errno("calloc"); - queue_data_block((u8 *)dind_block_data, info.block_size, dind_block); + sparse_file_add_data(info.sparse_file, dind_block_data, info.block_size, + dind_block); u32 *ind_block_data = calloc(info.block_size, info.bg_desc_reserve_blocks); if (!ind_block_data) critical_error_errno("calloc"); - queue_data_block((u8 *)ind_block_data, + sparse_file_add_data(info.sparse_file, ind_block_data, info.block_size * info.bg_desc_reserve_blocks, get_block(alloc, 0)); diff --git a/ext4_utils/libsparse/Android.mk b/ext4_utils/libsparse/Android.mk new file mode 100644 index 00000000..dbe4d184 --- /dev/null +++ b/ext4_utils/libsparse/Android.mk @@ -0,0 +1,86 @@ +# Copyright 2010 The Android Open Source Project + +LOCAL_PATH:= $(call my-dir) + +libsparse_src_files := \ + backed_block.c \ + output_file.c \ + sparse.c \ + sparse_crc32.c + +include $(CLEAR_VARS) + +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_SRC_FILES := $(libsparse_src_files) +LOCAL_MODULE := libsparse +LOCAL_MODULE_TAGS := optional +LOCAL_STATIC_LIBRARIES := libz +LOCAL_C_INCLUDES += $(LOCAL_PATH)/include external/zlib + +include $(BUILD_HOST_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_SRC_FILES := $(libsparse_src_files) +LOCAL_MODULE := libsparse +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES += $(LOCAL_PATH)/include external/zlib +LOCAL_SHARED_LIBRARIES := libz + +include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_SRC_FILES := $(libsparse_src_files) +LOCAL_MODULE := libsparse +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES += $(LOCAL_PATH)/include external/zlib +LOCAL_STATIC_LIBRARIES := libz + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := simg2img.c \ + sparse_crc32.c +LOCAL_MODULE := simg2img +LOCAL_MODULE_TAGS := debug + +include $(BUILD_HOST_EXECUTABLE) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := simg2img.c \ + sparse_crc32.c +LOCAL_MODULE := simg2img +LOCAL_MODULE_TAGS := optional + +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := img2simg.c +LOCAL_MODULE := img2simg +LOCAL_MODULE_TAGS := debug + +include $(BUILD_HOST_EXECUTABLE) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := img2simg.c +LOCAL_MODULE := img2simg +LOCAL_MODULE_TAGS := optional + +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) + +LOCAL_MODULE := simg_dump.py +LOCAL_MODULE_TAGS := debug +LOCAL_SRC_FILES := simg_dump.py +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_IS_HOST_MODULE := true + +include $(BUILD_PREBUILT) diff --git a/ext4_utils/backed_block.c b/ext4_utils/libsparse/backed_block.c index c0070f1a..25481380 100644 --- a/ext4_utils/backed_block.c +++ b/ext4_utils/libsparse/backed_block.c @@ -14,17 +14,18 @@ * limitations under the License. */ -#include "ext4_utils.h" -#include "backed_block.h" - #include <stdlib.h> +#include <string.h> + +#include "backed_block.h" +#include "sparse_defs.h" struct data_block { u32 block; u32 len; - u8 *data; + void *data; const char *filename; - off64_t offset; + int64_t offset; struct data_block *next; u32 fill_val; u8 fill; @@ -71,11 +72,13 @@ static void queue_db(struct data_block *new_db) } /* Queues a fill block of memory to be written to the specified data blocks */ -void queue_fill_block(u32 fill_val, u32 len, u32 block) +void queue_fill_block(unsigned int fill_val, unsigned int len, unsigned int block) { struct data_block *db = malloc(sizeof(struct data_block)); - if (db == NULL) - critical_error_errno("malloc"); + if (db == NULL) { + error_errno("malloc"); + return; + } db->block = block; db->len = len; @@ -89,11 +92,13 @@ void queue_fill_block(u32 fill_val, u32 len, u32 block) } /* Queues a block of memory to be written to the specified data blocks */ -void queue_data_block(u8 *data, u32 len, u32 block) +void queue_data_block(void *data, unsigned int len, unsigned int block) { struct data_block *db = malloc(sizeof(struct data_block)); - if (db == NULL) - critical_error_errno("malloc"); + if (db == NULL) { + error_errno("malloc"); + return; + } db->block = block; db->len = len; @@ -106,12 +111,14 @@ void queue_data_block(u8 *data, u32 len, u32 block) } /* Queues a chunk of a file on disk to be written to the specified data blocks */ -void queue_data_file(const char *filename, off64_t offset, u32 len, - u32 block) +void queue_data_file(const char *filename, int64_t offset, unsigned int len, + unsigned int block) { struct data_block *db = malloc(sizeof(struct data_block)); - if (db == NULL) - critical_error_errno("malloc"); + if (db == NULL) { + error_errno("malloc"); + return; + } db->block = block; db->len = len; @@ -128,7 +135,7 @@ void queue_data_file(const char *filename, off64_t offset, u32 len, data block, and file_func for each contiguous file block */ void for_each_data_block(data_block_callback_t data_func, data_block_file_callback_t file_func, - data_block_fill_callback_t fill_func, void *priv) + data_block_fill_callback_t fill_func, void *priv, unsigned int block_size) { struct data_block *db; u32 last_block = 0; @@ -136,14 +143,14 @@ void for_each_data_block(data_block_callback_t data_func, for (db = data_blocks; db; db = db->next) { if (db->block < last_block) error("data blocks out of order: %u < %u", db->block, last_block); - last_block = db->block + DIV_ROUND_UP(db->len, info.block_size) - 1; + last_block = db->block + DIV_ROUND_UP(db->len, block_size) - 1; if (db->filename) - file_func(priv, (u64)db->block * info.block_size, db->filename, db->offset, db->len); + file_func(priv, (u64)db->block * block_size, db->filename, db->offset, db->len); else if (db->fill) - fill_func(priv, (u64)db->block * info.block_size, db->fill_val, db->len); + fill_func(priv, (u64)db->block * block_size, db->fill_val, db->len); else - data_func(priv, (u64)db->block * info.block_size, db->data, db->len); + data_func(priv, (u64)db->block * block_size, db->data, db->len); } } diff --git a/ext4_utils/backed_block.h b/ext4_utils/libsparse/backed_block.h index e3c4ac4a..7b7c90aa 100644 --- a/ext4_utils/backed_block.h +++ b/ext4_utils/libsparse/backed_block.h @@ -17,22 +17,23 @@ #ifndef _BACKED_BLOCK_H_ #define _BACKED_BLOCK_H_ -#include "ext4_utils.h" -#include "output_file.h" +#include <sparse/sparse.h> -typedef void (*data_block_callback_t)(void *priv, u64 off, u8 *data, int len); -typedef void (*data_block_fill_callback_t)(void *priv, u64 off, u32 fill_val, int len); -typedef void (*data_block_file_callback_t)(void *priv, u64 off, - const char *file, off64_t offset, +typedef void (*data_block_callback_t)(void *priv, int64_t off, void *data, int len); +typedef void (*data_block_fill_callback_t)(void *priv, int64_t off, unsigned int fill_val, int len); +typedef void (*data_block_file_callback_t)(void *priv, int64_t off, + const char *file, int64_t offset, int len); -void queue_data_block(u8 *data, u32 len, u32 block); -void queue_fill_block(u32 fill_val, u32 len, u32 block); -void queue_data_file(const char *filename, off64_t offset, u32 len, - u32 block); void for_each_data_block(data_block_callback_t data_func, data_block_file_callback_t file_func, - data_block_fill_callback_t fill_func, void *priv); + data_block_fill_callback_t fill_func, void *priv, unsigned int); + +void queue_data_block(void *data, unsigned int len, unsigned int block); +void queue_fill_block(unsigned int fill_val, unsigned int len, unsigned int block); +void queue_data_file(const char *filename, int64_t offset, unsigned int len, + unsigned int block); + void free_data_blocks(); #endif diff --git a/ext4_utils/img2simg.c b/ext4_utils/libsparse/img2simg.c index 3b466132..a1594df6 100644 --- a/ext4_utils/img2simg.c +++ b/ext4_utils/libsparse/img2simg.c @@ -18,7 +18,6 @@ #define DEFAULT_CHUNK_SIZE "64M" #define DEFAULT_SUFFIX "%03d" -#include "ext4_utils.h" #include "sparse_format.h" #if 0 /* endian.h is not on all platforms */ # include <endian.h> diff --git a/ext4_utils/libsparse/include/sparse/sparse.h b/ext4_utils/libsparse/include/sparse/sparse.h new file mode 100644 index 00000000..db068847 --- /dev/null +++ b/ext4_utils/libsparse/include/sparse/sparse.h @@ -0,0 +1,134 @@ +/* + * 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. + */ + +#ifndef _LIBSPARSE_SPARSE_H_ +#define _LIBSPARSE_SPARSE_H_ + +#include <stdbool.h> +#include <stdint.h> + +struct sparse_file; + +/** + * sparse_file_new - create a new sparse file cookie + * + * @block_size - minimum size of a chunk + * @len - size of the expanded sparse file. + * + * Creates a new sparse_file cookie that can be used to associate data + * blocks. Can later be written to a file with a variety of options. + * block_size specifies the minimum size of a chunk in the file. The maximum + * size of the file is 2**32 * block_size (16TB for 4k block size). + * + * Returns the sparse file cookie, or NULL on error. + */ +struct sparse_file *sparse_file_new(unsigned int block_size, int64_t len); + +/** + * sparse_file_destroy - destroy a sparse file cookie + * + * @s - sparse file cookie + * + * Destroys a sparse file cookie. After destroy, all memory passed in to + * sparse_file_add_data can be freed by the caller + */ +void sparse_file_destroy(struct sparse_file *s); + +/** + * sparse_file_add_data - associate a data chunk with a sparse file + * + * @s - sparse file cookie + * @data - pointer to data block + * @len - length of the data block + * @block - offset in blocks into the sparse file to place the data chunk + * + * Associates a data chunk with a sparse file cookie. The region + * [block * block_size : block * block_size + len) must not already be used in + * the sparse file. If len is not a multiple of the block size the data + * will be padded with zeros. + * + * The data pointer must remain valid until the sparse file is closed or the + * data block is removed from the sparse file. + * + * Returns 0 on success, negative errno on error. + */ +int sparse_file_add_data(struct sparse_file *s, + void *data, unsigned int len, unsigned int block); + +/** + * sparse_file_add_fill - associate a fill chunk with a sparse file + * + * @s - sparse file cookie + * @fill_val - 32 bit fill data + * @len - length of the fill block + * @block - offset in blocks into the sparse file to place the fill chunk + * + * Associates a chunk filled with fill_val with a sparse file cookie. + * The region [block * block_size : block * block_size + len) must not already + * be used in the sparse file. If len is not a multiple of the block size the + * data will be padded with zeros. + * + * Returns 0 on success, negative errno on error. + */ +int sparse_file_add_fill(struct sparse_file *s, + uint32_t fill_val, unsigned int len, unsigned int block); + +/** + * sparse_file_add_file - associate a chunk of a file with a sparse file + * + * @s - sparse file cookie + * @filename - filename of the file to be copied + * @file_offset - offset into the copied file + * @len - length of the copied block + * @block - offset in blocks into the sparse file to place the file chunk + * + * Associates a chunk of an existing file with a sparse file cookie. + * The region [block * block_size : block * block_size + len) must not already + * be used in the sparse file. If len is not a multiple of the block size the + * data will be padded with zeros. + * + * Allows adding large amounts of data to a sparse file without needing to keep + * it all mapped. File size is limited by available virtual address space, + * exceptionally large files may need to be added in multiple chunks. + * + * Returns 0 on success, negative errno on error. + */ +int sparse_file_add_file(struct sparse_file *s, + const char *filename, int64_t file_offset, unsigned int len, + unsigned int block); + +/** + * sparse_file_write - write a sparse file to a file + * + * @s - sparse file cookie + * @fd - file descriptor to write to + * @gz - write a gzipped file + * @sparse - write in the Android sparse file format + * @crc - append a crc chunk + * + * Writes a sparse file to a file. If gz is true, the data will be passed + * through zlib. If sparse is true, the file will be written in the Android + * sparse file format. If sparse is false, the file will be written by seeking + * over unused chunks, producing a smaller file if the filesystem supports + * sparse files. If crc is true, the crc of the expanded data will be + * calculated and appended in a crc chunk. + * + * Returns 0 on success, negative errno on error. + */ +int sparse_file_write(struct sparse_file *s, int fd, bool gz, bool sparse, + bool crc); + +#endif diff --git a/ext4_utils/output_file.c b/ext4_utils/libsparse/output_file.c index 40655a92..2c4b5573 100644 --- a/ext4_utils/output_file.c +++ b/ext4_utils/libsparse/output_file.c @@ -14,38 +14,50 @@ * limitations under the License. */ -#include "ext4_utils.h" -#include "output_file.h" -#include "sparse_format.h" -#include "sparse_crc32.h" -#include "wipe.h" +#define _FILE_OFFSET_BITS 64 +#define _LARGEFILE64_SOURCE 1 #include <fcntl.h> #include <stdbool.h> -#include <sys/types.h> +#include <stdlib.h> +#include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <zlib.h> +#include "output_file.h" +#include "sparse_format.h" +#include "sparse_crc32.h" + #ifndef USE_MINGW #include <sys/mman.h> #define O_BINARY 0 #endif - #if defined(__APPLE__) && defined(__MACH__) #define lseek64 lseek +#define ftruncate64 ftruncate +#define mmap64 mmap #define off64_t off_t #endif +#ifdef __BIONIC__ +extern void* __mmap2(void *, size_t, int, int, int, off_t); +static inline void *mmap64(void *addr, size_t length, int prot, int flags, + int fd, off64_t offset) +{ + return __mmap2(addr, length, prot, flags, fd, offset >> 12); +} +#endif + #define SPARSE_HEADER_MAJOR_VER 1 #define SPARSE_HEADER_MINOR_VER 0 #define SPARSE_HEADER_LEN (sizeof(sparse_header_t)) #define CHUNK_HEADER_LEN (sizeof(chunk_header_t)) struct output_file_ops { - int (*seek)(struct output_file *, off64_t); + int (*seek)(struct output_file *, int64_t); int (*write)(struct output_file *, u8 *, int); void (*close)(struct output_file *); }; @@ -55,14 +67,16 @@ struct output_file { gzFile gz_fd; bool close_fd; int sparse; - u64 cur_out_ptr; + int64_t cur_out_ptr; u32 chunk_cnt; u32 crc32; struct output_file_ops *ops; int use_crc; + unsigned int block_size; + int64_t len; }; -static int file_seek(struct output_file *out, off64_t off) +static int file_seek(struct output_file *out, int64_t off) { off64_t ret; @@ -103,7 +117,7 @@ static struct output_file_ops file_ops = { .close = file_close, }; -static int gz_file_seek(struct output_file *out, off64_t off) +static int gz_file_seek(struct output_file *out, int64_t off) { off64_t ret; @@ -162,16 +176,16 @@ static int emit_skip_chunk(struct output_file *out, u64 skip_len) //DBG printf("skip chunk: 0x%llx bytes\n", skip_len); - if (skip_len % info.block_size) { + if (skip_len % out->block_size) { error("don't care size %llu is not a multiple of the block size %u", - skip_len, info.block_size); + skip_len, out->block_size); return -1; } /* We are skipping data, so emit a don't care chunk. */ chunk_header.chunk_type = CHUNK_TYPE_DONT_CARE; chunk_header.reserved1 = 0; - chunk_header.chunk_sz = skip_len / info.block_size; + chunk_header.chunk_sz = skip_len / out->block_size; chunk_header.total_sz = CHUNK_HEADER_LEN; ret = out->ops->write(out, (u8 *)&chunk_header, sizeof(chunk_header)); if (ret < 0) @@ -183,7 +197,7 @@ static int emit_skip_chunk(struct output_file *out, u64 skip_len) return 0; } -static int write_chunk_fill(struct output_file *out, u64 off, u32 fill_val, int len) +static int write_chunk_fill(struct output_file *out, int64_t off, u32 fill_val, int len) { chunk_header_t chunk_header; int rnd_up_len, zero_len, count; @@ -210,9 +224,9 @@ static int write_chunk_fill(struct output_file *out, u64 off, u32 fill_val, int emit_skip_chunk(out, off - out->cur_out_ptr); } - if (off % info.block_size) { + if (off % out->block_size) { error("write chunk offset %llu is not a multiple of the block size %u", - off, info.block_size); + off, out->block_size); return -1; } @@ -222,12 +236,12 @@ static int write_chunk_fill(struct output_file *out, u64 off, u32 fill_val, int } /* Round up the file length to a multiple of the block size */ - rnd_up_len = (len + (info.block_size - 1)) & (~(info.block_size -1)); + rnd_up_len = (len + (out->block_size - 1)) & (~(out->block_size -1)); /* Finally we can safely emit a chunk of data */ chunk_header.chunk_type = CHUNK_TYPE_FILL; chunk_header.reserved1 = 0; - chunk_header.chunk_sz = rnd_up_len / info.block_size; + chunk_header.chunk_sz = rnd_up_len / out->block_size; chunk_header.total_sz = CHUNK_HEADER_LEN + sizeof(fill_val); ret = out->ops->write(out, (u8 *)&chunk_header, sizeof(chunk_header)); @@ -239,13 +253,13 @@ static int write_chunk_fill(struct output_file *out, u64 off, u32 fill_val, int if (out->use_crc) { /* Initialize fill_buf with the fill_val */ - for (i = 0; i < (info.block_size / sizeof(u32)); i++) { + for (i = 0; i < (out->block_size / sizeof(u32)); i++) { fill_buf[i] = fill_val; } count = chunk_header.chunk_sz; while (count) { - out->crc32 = sparse_crc32(out->crc32, fill_buf, info.block_size); + out->crc32 = sparse_crc32(out->crc32, fill_buf, out->block_size); count--; } } @@ -256,7 +270,7 @@ static int write_chunk_fill(struct output_file *out, u64 off, u32 fill_val, int return 0; } -static int write_chunk_raw(struct output_file *out, u64 off, u8 *data, int len) +static int write_chunk_raw(struct output_file *out, int64_t off, u8 *data, int len) { chunk_header_t chunk_header; int rnd_up_len, zero_len; @@ -281,9 +295,9 @@ static int write_chunk_raw(struct output_file *out, u64 off, u8 *data, int len) emit_skip_chunk(out, off - out->cur_out_ptr); } - if (off % info.block_size) { + if (off % out->block_size) { error("write chunk offset %llu is not a multiple of the block size %u", - off, info.block_size); + off, out->block_size); return -1; } @@ -293,13 +307,13 @@ static int write_chunk_raw(struct output_file *out, u64 off, u8 *data, int len) } /* Round up the file length to a multiple of the block size */ - rnd_up_len = (len + (info.block_size - 1)) & (~(info.block_size -1)); + rnd_up_len = (len + (out->block_size - 1)) & (~(out->block_size -1)); zero_len = rnd_up_len - len; /* Finally we can safely emit a chunk of data */ chunk_header.chunk_type = CHUNK_TYPE_RAW; chunk_header.reserved1 = 0; - chunk_header.chunk_sz = rnd_up_len / info.block_size; + chunk_header.chunk_sz = rnd_up_len / out->block_size; chunk_header.total_sz = CHUNK_HEADER_LEN + rnd_up_len; ret = out->ops->write(out, (u8 *)&chunk_header, sizeof(chunk_header)); @@ -351,8 +365,8 @@ void close_output_file(struct output_file *out) out->ops->close(out); } -struct output_file *open_output_fd(int fd, int gz, int sparse, - int chunks, int crc, int wipe) +struct output_file *open_output_fd(int fd, unsigned int block_size, int64_t len, + int gz, int sparse, int chunks, int crc) { int ret; struct output_file *out = malloc(sizeof(struct output_file)); @@ -360,13 +374,13 @@ struct output_file *open_output_fd(int fd, int gz, int sparse, error_errno("malloc struct out"); return NULL; } - zero_buf = malloc(info.block_size); + zero_buf = malloc(out->block_size); if (!zero_buf) { error_errno("malloc zero_buf"); free(out); return NULL; } - memset(zero_buf, '\0', info.block_size); + memset(zero_buf, '\0', out->block_size); if (gz) { out->ops = &gz_file_ops; @@ -389,12 +403,12 @@ struct output_file *open_output_fd(int fd, int gz, int sparse, out->crc32 = 0; out->use_crc = crc; - if (wipe) - wipe_block_device(out->fd, info.len); + out->len = len; + out->block_size = block_size; if (out->sparse) { - sparse_header.blk_sz = info.block_size, - sparse_header.total_blks = info.len / info.block_size, + sparse_header.blk_sz = out->block_size, + sparse_header.total_blks = out->len / out->block_size, sparse_header.total_chunks = chunks; if (out->use_crc) sparse_header.total_chunks++; @@ -407,9 +421,10 @@ struct output_file *open_output_fd(int fd, int gz, int sparse, return out; } -struct output_file *open_output_file(const char *filename, int gz, int sparse, - int chunks, int crc, int wipe) { - +struct output_file *open_output_file(const char *filename, + unsigned int block_size, int64_t len, + int gz, int sparse, int chunks, int crc) +{ int fd; struct output_file *file; @@ -423,7 +438,7 @@ struct output_file *open_output_file(const char *filename, int gz, int sparse, fd = STDOUT_FILENO; } - file = open_output_fd(fd, gz, sparse, chunks, crc, wipe); + file = open_output_fd(fd, block_size, len, gz, sparse, chunks, crc); if (!file) { close(fd); return NULL; @@ -434,13 +449,13 @@ struct output_file *open_output_file(const char *filename, int gz, int sparse, return file; } -void pad_output_file(struct output_file *out, u64 len) +void pad_output_file(struct output_file *out, int64_t len) { int ret; - if (len > (u64) info.len) { + if (len > out->len) { error("attempted to pad file %llu bytes past end of filesystem", - len - info.len); + len - out->len); return; } if (out->sparse) { @@ -471,13 +486,13 @@ void pad_output_file(struct output_file *out, u64 len) } /* Write a contiguous region of data blocks from a memory buffer */ -void write_data_block(struct output_file *out, u64 off, u8 *data, int len) +void write_data_block(struct output_file *out, int64_t off, void *data, int len) { int ret; - if (off + len > (u64) info.len) { + if (off + len > out->len) { error("attempted to write block %llu past end of filesystem", - off + len - info.len); + off + len - out->len); return; } @@ -495,16 +510,16 @@ void write_data_block(struct output_file *out, u64 off, u8 *data, int len) } /* Write a contiguous region of data blocks with a fill value */ -void write_fill_block(struct output_file *out, u64 off, u32 fill_val, int len) +void write_fill_block(struct output_file *out, int64_t off, unsigned int fill_val, int len) { int ret; unsigned int i; int write_len; u32 fill_buf[4096/sizeof(u32)]; /* Maximum size of a block */ - if (off + len > (u64) info.len) { + if (off + len > out->len) { error("attempted to write block %llu past end of filesystem", - off + len - info.len); + off + len - out->len); return; } @@ -533,17 +548,17 @@ void write_fill_block(struct output_file *out, u64 off, u32 fill_val, int len) } /* Write a contiguous region of data blocks from a file */ -void write_data_file(struct output_file *out, u64 off, const char *file, - off64_t offset, int len) +void write_data_file(struct output_file *out, int64_t off, const char *file, + int64_t offset, int len) { int ret; - off64_t aligned_offset; + int64_t aligned_offset; int aligned_diff; int buffer_size; - if (off + len >= (u64) info.len) { + if (off + len >= out->len) { error("attempted to write block %llu past end of filesystem", - off + len - info.len); + off + len - out->len); return; } diff --git a/ext4_utils/output_file.h b/ext4_utils/libsparse/output_file.h index a578c80f..b12194fc 100644 --- a/ext4_utils/output_file.h +++ b/ext4_utils/libsparse/output_file.h @@ -17,17 +17,20 @@ #ifndef _OUTPUT_FILE_H_ #define _OUTPUT_FILE_H_ +#include <sparse/sparse.h> + struct output_file; -struct output_file *open_output_file(const char *filename, int gz, int sparse, - int chunks, int crc, int wipe); -struct output_file *open_output_fd(int fd, int gz, int sparse, - int chunks, int crc, int wipe); -void write_data_block(struct output_file *out, u64 off, u8 *data, int len); -void write_fill_block(struct output_file *out, u64 off, u32 fill_val, int len); -void write_data_file(struct output_file *out, u64 off, const char *file, - off64_t offset, int len); -void pad_output_file(struct output_file *out, u64 len); +struct output_file *open_output_file(const char *filename, + unsigned int block_size, int64_t len, + int gz, int sparse, int chunks, int crc); +struct output_file *open_output_fd(int fd, unsigned int block_size, int64_t len, + int gz, int sparse, int chunks, int crc); +void write_data_block(struct output_file *out, int64_t off, void *data, int len); +void write_fill_block(struct output_file *out, int64_t off, unsigned int fill_val, int len); +void write_data_file(struct output_file *out, int64_t off, const char *file, + int64_t offset, int len); +void pad_output_file(struct output_file *out, int64_t len); void close_output_file(struct output_file *out); #endif diff --git a/ext4_utils/simg2img.c b/ext4_utils/libsparse/simg2img.c index 12b92eb7..486b8054 100644 --- a/ext4_utils/simg2img.c +++ b/ext4_utils/libsparse/simg2img.c @@ -14,17 +14,24 @@ * limitations under the License. */ -#include "ext4_utils.h" +#define _FILE_OFFSET_BITS 64 +#define _LARGEFILE64_SOURCE 1 +#include <sys/types.h> +#include <unistd.h> + +#include "sparse_defs.h" #include "sparse_format.h" #include "sparse_crc32.h" +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/mman.h> #include <unistd.h> -#include <fcntl.h> -#include <stdio.h> #define COPY_BUF_SIZE (1024*1024) u8 *copybuf; diff --git a/ext4_utils/simg_dump.py b/ext4_utils/libsparse/simg_dump.py index 6ece31d0..6ece31d0 100755 --- a/ext4_utils/simg_dump.py +++ b/ext4_utils/libsparse/simg_dump.py diff --git a/ext4_utils/libsparse/sparse.c b/ext4_utils/libsparse/sparse.c new file mode 100644 index 00000000..d6f55611 --- /dev/null +++ b/ext4_utils/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; +} diff --git a/ext4_utils/sparse_crc32.c b/ext4_utils/libsparse/sparse_crc32.c index 9336b1d8..38bfe4aa 100644 --- a/ext4_utils/sparse_crc32.c +++ b/ext4_utils/libsparse/sparse_crc32.c @@ -43,9 +43,9 @@ */ /* Code taken from FreeBSD 8 */ -#include "ext4_utils.h" +#include <stdint.h> -static u32 crc32_tab[] = { +static uint32_t crc32_tab[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, @@ -98,10 +98,10 @@ static u32 crc32_tab[] = { * in sys/libkern.h, where it can be inlined. */ -u32 sparse_crc32(u32 crc_in, const void *buf, int size) +uint32_t sparse_crc32(uint32_t crc_in, const void *buf, int size) { - const u8 *p = buf; - u32 crc; + const uint8_t *p = buf; + uint32_t crc; crc = crc_in ^ ~0U; while (size--) diff --git a/ext4_utils/sparse_crc32.h b/ext4_utils/libsparse/sparse_crc32.h index 21625bac..21625bac 100644 --- a/ext4_utils/sparse_crc32.h +++ b/ext4_utils/libsparse/sparse_crc32.h diff --git a/ext4_utils/libsparse/sparse_defs.h b/ext4_utils/libsparse/sparse_defs.h new file mode 100644 index 00000000..9f32d592 --- /dev/null +++ b/ext4_utils/libsparse/sparse_defs.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010 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. + */ + +#ifndef _LIBSPARSE_SPARSE_DEFS_ +#define _LIBSPARSE_SPARSE_DEFS_ + +#include <errno.h> +#include <stdio.h> + +#define __le64 u64 +#define __le32 u32 +#define __le16 u16 + +#define __be64 u64 +#define __be32 u32 +#define __be16 u16 + +#define __u64 u64 +#define __u32 u32 +#define __u16 u16 +#define __u8 u8 + +typedef unsigned long long u64; +typedef signed long long s64; +typedef unsigned int u32; +typedef unsigned short int u16; +typedef unsigned char u8; + +#define DIV_ROUND_UP(x, y) (((x) + (y) - 1)/(y)) +#define ALIGN(x, y) ((y) * DIV_ROUND_UP((x), (y))) + +#define error(fmt, args...) do { fprintf(stderr, "error: %s: " fmt "\n", __func__, ## args); } while (0) +#define error_errno(s, args...) error(s ": %s", ##args, strerror(errno)) + +#endif diff --git a/ext4_utils/libsparse/sparse_file.h b/ext4_utils/libsparse/sparse_file.h new file mode 100644 index 00000000..05a78d96 --- /dev/null +++ b/ext4_utils/libsparse/sparse_file.h @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#ifndef _LIBSPARSE_SPARSE_FILE_H_ +#define _LIBSPARSE_SPARSE_FILE_H_ + +#include <sparse/sparse.h> + +struct sparse_file { + unsigned int block_size; + int64_t len; + + struct output_file *out; +}; + + +#endif /* _LIBSPARSE_SPARSE_FILE_H_ */ diff --git a/ext4_utils/sparse_format.h b/ext4_utils/libsparse/sparse_format.h index 6c62c34c..c41f12a5 100644 --- a/ext4_utils/sparse_format.h +++ b/ext4_utils/libsparse/sparse_format.h @@ -14,6 +14,10 @@ * limitations under the License. */ +#ifndef _LIBSPARSE_SPARSE_FORMAT_H_ +#define _LIBSPARSE_SPARSE_FORMAT_H_ +#include "sparse_defs.h" + typedef struct sparse_header { __le32 magic; /* 0xed26ff3a */ __le16 major_version; /* (0x1) - reject images with higher major versions */ @@ -48,3 +52,4 @@ typedef struct chunk_header { * For a CRC32 chunk, it's 4 bytes of CRC32 */ +#endif diff --git a/ext4_utils/make_ext4fs.c b/ext4_utils/make_ext4fs.c index 6cd5adec..be63e276 100644 --- a/ext4_utils/make_ext4fs.c +++ b/ext4_utils/make_ext4fs.c @@ -15,12 +15,13 @@ */ #include "make_ext4fs.h" -#include "output_file.h" #include "ext4_utils.h" #include "allocate.h" #include "contents.h" #include "uuid.h" -#include "backed_block.h" +#include "wipe.h" + +#include <sparse/sparse.h> #include <assert.h> #include <dirent.h> @@ -293,7 +294,11 @@ void reset_ext4fs_info() { // can be called again. memset(&info, 0, sizeof(info)); memset(&aux_info, 0, sizeof(aux_info)); - free_data_blocks(); + + if (info.sparse_file) { + sparse_file_destroy(info.sparse_file); + info.sparse_file = NULL; + } } int make_ext4fs(const char *filename, s64 len, @@ -392,6 +397,8 @@ int make_ext4fs_internal(int fd, const char *directory, printf(" Block groups: %d\n", aux_info.groups); printf(" Reserved block group size: %d\n", info.bg_desc_reserve_blocks); + info.sparse_file = sparse_file_new(info.block_size, info.len); + block_allocator_init(); ext4_fill_in_sb(); @@ -456,7 +463,13 @@ int make_ext4fs_internal(int fd, const char *directory, aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo, aux_info.sb->s_blocks_count_lo); - write_ext4_image(fd, gzip, sparse, crc, wipe); + if (wipe) + wipe_block_device(fd, info.len); + + write_ext4_image(fd, gzip, sparse, crc); + + sparse_file_destroy(info.sparse_file); + info.sparse_file = NULL; return 0; } diff --git a/ext4_utils/make_ext4fs_main.c b/ext4_utils/make_ext4fs_main.c index d5454236..f7beeb5f 100644 --- a/ext4_utils/make_ext4fs_main.c +++ b/ext4_utils/make_ext4fs_main.c @@ -136,12 +136,6 @@ int main(int argc, char **argv) } } - if (gzip && sparse) { - fprintf(stderr, "Cannot specify both gzip and sparse\n"); - usage(argv[0]); - exit(EXIT_FAILURE); - } - if (wipe && sparse) { fprintf(stderr, "Cannot specifiy both wipe and sparse\n"); usage(argv[0]); |