ext2simg.c revision 782879ab61fe825835a9c6a701f91aa7d305acef
1a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross/* 2a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross * Copyright (C) 2010 The Android Open Source Project 3a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross * 4a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross * Licensed under the Apache License, Version 2.0 (the "License"); 5a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross * you may not use this file except in compliance with the License. 6a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross * You may obtain a copy of the License at 7a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross * 8a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross * http://www.apache.org/licenses/LICENSE-2.0 9a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross * 10a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross * Unless required by applicable law or agreed to in writing, software 11a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross * distributed under the License is distributed on an "AS IS" BASIS, 12a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross * See the License for the specific language governing permissions and 14a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross * limitations under the License. 15a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross */ 16a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 17f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross#define _FILE_OFFSET_BITS 64 18f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross#define _LARGEFILE64_SOURCE 1 19a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 20a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross#include <sys/types.h> 21a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross#include <sys/stat.h> 22a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross#include <sys/types.h> 23a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross#include <sys/mman.h> 24a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross#include <fcntl.h> 25a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross#include <libgen.h> 26a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross#include <unistd.h> 27a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 28f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross#include <sparse/sparse.h> 29f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross 30f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross#include "ext4_utils.h" 31f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross#include "make_ext4fs.h" 32f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross#include "allocate.h" 33f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross 34f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross#if defined(__APPLE__) && defined(__MACH__) 35f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross#define off64_t off_t 36f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross#endif 37f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross 380349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau#ifndef USE_MINGW /* O_BINARY is windows-specific flag */ 390349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau#define O_BINARY 0 400349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau#endif 410349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau 42a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Crossextern struct fs_info info; 43a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 44a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Crossstatic int verbose = 0; 45a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 46a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Crossstatic void usage(char *path) 47a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross{ 48a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, "%s [ options ] <image or block device> <output image>\n", path); 49a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, "\n"); 50a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, " -c include CRC block\n"); 51a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, " -v verbose output\n"); 52a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, " -z gzip output\n"); 53a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, " -S don't use sparse output format\n"); 54a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross} 55a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 56a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Crossstatic int read_ext(int fd) 57a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross{ 58a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross off64_t ret; 59a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross struct ext4_super_block sb; 60a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 61a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = lseek64(fd, 1024, SEEK_SET); 62a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 63a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to seek to superblock"); 64a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 65a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = read(fd, &sb, sizeof(sb)); 66a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 67a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to read superblock"); 68a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret != sizeof(sb)) 69a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error("failed to read all of superblock"); 70a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 71a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ext4_parse_sb(&sb); 72a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 73a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = lseek64(fd, info.len, SEEK_SET); 74a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 75a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to seek to end of input image"); 76a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 77a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = lseek64(fd, info.block_size * (aux_info.first_data_block + 1), SEEK_SET); 78a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 79a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to seek to block group descriptors"); 80a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 81a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = read(fd, aux_info.bg_desc, info.block_size * aux_info.bg_desc_blocks); 82a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 83a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to read block group descriptors"); 84a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret != (int)info.block_size * (int)aux_info.bg_desc_blocks) 85a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error("failed to read all of block group descriptors"); 86a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 87a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (verbose) { 88a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf("Found filesystem with parameters:\n"); 89a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Size: %llu\n", info.len); 90a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Block size: %d\n", info.block_size); 91a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Blocks per group: %d\n", info.blocks_per_group); 92a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Inodes per group: %d\n", info.inodes_per_group); 93a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Inode size: %d\n", info.inode_size); 94a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Label: %s\n", info.label); 95a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Blocks: %llu\n", aux_info.len_blocks); 96a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Block groups: %d\n", aux_info.groups); 97a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Reserved block group size: %d\n", info.bg_desc_reserve_blocks); 98a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Used %d/%d inodes and %d/%d blocks\n", 99a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross aux_info.sb->s_inodes_count - aux_info.sb->s_free_inodes_count, 100a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross aux_info.sb->s_inodes_count, 101a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo, 102a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross aux_info.sb->s_blocks_count_lo); 103a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 104a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 105a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross return 0; 106a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross} 107a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 108a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Crossstatic int bitmap_get_bit(u8 *bitmap, u32 bit) 109a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross{ 110a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (bitmap[bit / 8] & 1 << (bit % 8)) 111a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross return 1; 112a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 113a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross return 0; 114a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross} 115a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 116a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Crossstatic int build_sparse_ext(int fd, const char *filename) 117a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross{ 118a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross unsigned int i; 119a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross unsigned int block; 120a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int start_contiguous_block; 121a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u8 *block_bitmap; 122a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross off64_t ret; 123a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 124a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross block_bitmap = malloc(info.block_size); 125a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (!block_bitmap) 126a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error("failed to allocate block bitmap"); 127a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 128a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (aux_info.first_data_block > 0) 129782879ab61fe825835a9c6a701f91aa7d305acefColin Cross sparse_file_add_file(ext4_sparse_file, filename, 0, 130a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross info.block_size * aux_info.first_data_block, 0); 131a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 132a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross for (i = 0; i < aux_info.groups; i++) { 133a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 first_block = aux_info.first_data_block + i * info.blocks_per_group; 134a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 last_block = min(info.blocks_per_group, aux_info.len_blocks - first_block); 135a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 136a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = lseek64(fd, (u64)info.block_size * aux_info.bg_desc[i].bg_block_bitmap, 137a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross SEEK_SET); 138a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 139a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to seek to block group bitmap %d", i); 140a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 141a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = read(fd, block_bitmap, info.block_size); 142a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 143a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to read block group bitmap %d", i); 144a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret != (int)info.block_size) 145a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error("failed to read all of block group bitmap %d", i); 146a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 147a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross start_contiguous_block = -1; 148a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross for (block = 0; block < last_block; block++) { 149a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (start_contiguous_block >= 0) { 150a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (!bitmap_get_bit(block_bitmap, block)) { 151a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 start_block = first_block + start_contiguous_block; 152a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 len_blocks = block - start_contiguous_block; 153a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 154782879ab61fe825835a9c6a701f91aa7d305acefColin Cross sparse_file_add_file(ext4_sparse_file, filename, 155f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross (u64)info.block_size * start_block, 156a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross info.block_size * len_blocks, start_block); 157a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross start_contiguous_block = -1; 158a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 159a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } else { 160a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (bitmap_get_bit(block_bitmap, block)) 161a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross start_contiguous_block = block; 162a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 163a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 164a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 165a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (start_contiguous_block >= 0) { 166a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 start_block = first_block + start_contiguous_block; 167a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 len_blocks = last_block - start_contiguous_block; 168782879ab61fe825835a9c6a701f91aa7d305acefColin Cross sparse_file_add_file(ext4_sparse_file, filename, 169f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross (u64)info.block_size * start_block, 170a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross info.block_size * len_blocks, start_block); 171a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 172a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 173a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 174a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross return 0; 175a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross} 176a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 177a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Crossint main(int argc, char **argv) 178a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross{ 179a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int opt; 180a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross const char *in = NULL; 181a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross const char *out = NULL; 182a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int gzip = 0; 183a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int sparse = 1; 1840349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau int infd, outfd; 185a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int crc = 0; 186a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 187a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross while ((opt = getopt(argc, argv, "cvzS")) != -1) { 188a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross switch (opt) { 189a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross case 'c': 190a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross crc = 1; 191a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross break; 192a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross case 'v': 193a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross verbose = 1; 194a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross break; 195a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross case 'z': 196a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross gzip = 1; 197a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross break; 198a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross case 'S': 199a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross sparse = 0; 200a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross break; 201a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 202a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 203a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 204a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (optind >= argc) { 205a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, "Expected image or block device after options\n"); 206a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross usage(argv[0]); 207a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross exit(EXIT_FAILURE); 208a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 209a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 210a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross in = argv[optind++]; 211a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 212a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (optind >= argc) { 213a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, "Expected output image after input image\n"); 214a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross usage(argv[0]); 215a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross exit(EXIT_FAILURE); 216a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 217a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 218a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross out = argv[optind++]; 219a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 220a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (optind < argc) { 221a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, "Unexpected argument: %s\n", argv[optind]); 222a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross usage(argv[0]); 223a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross exit(EXIT_FAILURE); 224a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 225a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 2260349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau infd = open(in, O_RDONLY); 227a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 2280349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau if (infd < 0) 229a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to open input image"); 230a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 2310349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau read_ext(infd); 2320349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau 233782879ab61fe825835a9c6a701f91aa7d305acefColin Cross ext4_sparse_file = sparse_file_new(info.block_size, info.len); 234f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross 2350349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau build_sparse_ext(infd, in); 236a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 2370349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau close(infd); 238a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 2390349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau if (strcmp(out, "-")) { 2400349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau outfd = open(out, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); 2410349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau if (outfd < 0) { 2420349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau error_errno("open"); 2430349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau return EXIT_FAILURE; 2440349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau } 2450349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau } else { 2460349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau outfd = STDOUT_FILENO; 2470349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau } 248a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 249dc5abeee1e6fc4827ee0d5ece12aaed2dd56f4c7Colin Cross write_ext4_image(outfd, gzip, sparse, crc); 2500349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau close(outfd); 251a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 252782879ab61fe825835a9c6a701f91aa7d305acefColin Cross sparse_file_destroy(ext4_sparse_file); 253f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross 254a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross return 0; 255a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross} 256