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 unsigned int i; 61a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 62a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = lseek64(fd, 1024, SEEK_SET); 63a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 64a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to seek to superblock"); 65a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 66a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = read(fd, &sb, sizeof(sb)); 67a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 68a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to read superblock"); 69a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret != sizeof(sb)) 70a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error("failed to read all of superblock"); 71a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 72a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ext4_parse_sb(&sb); 73a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 74a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = lseek64(fd, info.len, SEEK_SET); 75a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 76a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to seek to end of input image"); 77a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 78a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = lseek64(fd, info.block_size * (aux_info.first_data_block + 1), SEEK_SET); 79a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 80a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to seek to block group descriptors"); 81a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 82a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = read(fd, aux_info.bg_desc, info.block_size * aux_info.bg_desc_blocks); 83a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 84a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to read block group descriptors"); 85a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret != (int)info.block_size * (int)aux_info.bg_desc_blocks) 86a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error("failed to read all of block group descriptors"); 87a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 88a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (verbose) { 89a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf("Found filesystem with parameters:\n"); 90a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Size: %llu\n", info.len); 91a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Block size: %d\n", info.block_size); 92a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Blocks per group: %d\n", info.blocks_per_group); 93a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Inodes per group: %d\n", info.inodes_per_group); 94a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Inode size: %d\n", info.inode_size); 95a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Label: %s\n", info.label); 96a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Blocks: %llu\n", aux_info.len_blocks); 97a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Block groups: %d\n", aux_info.groups); 98a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Reserved block group size: %d\n", info.bg_desc_reserve_blocks); 99a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross printf(" Used %d/%d inodes and %d/%d blocks\n", 100a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross aux_info.sb->s_inodes_count - aux_info.sb->s_free_inodes_count, 101a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross aux_info.sb->s_inodes_count, 102a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo, 103a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross aux_info.sb->s_blocks_count_lo); 104a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 105a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 106a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross return 0; 107a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross} 108a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 109a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Crossstatic int bitmap_get_bit(u8 *bitmap, u32 bit) 110a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross{ 111a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (bitmap[bit / 8] & 1 << (bit % 8)) 112a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross return 1; 113a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 114a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross return 0; 115a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross} 116a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 117a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Crossstatic int build_sparse_ext(int fd, const char *filename) 118a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross{ 119a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross unsigned int i; 120a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross unsigned int block; 121a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int start_contiguous_block; 122a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u8 *block_bitmap; 123a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross off64_t ret; 124a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 125a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross block_bitmap = malloc(info.block_size); 126a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (!block_bitmap) 127a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error("failed to allocate block bitmap"); 128a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 129a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (aux_info.first_data_block > 0) 130f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross sparse_file_add_file(info.sparse_file, filename, 0, 131a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross info.block_size * aux_info.first_data_block, 0); 132a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 133a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross for (i = 0; i < aux_info.groups; i++) { 134a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 first_block = aux_info.first_data_block + i * info.blocks_per_group; 135a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 last_block = min(info.blocks_per_group, aux_info.len_blocks - first_block); 136a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 137a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = lseek64(fd, (u64)info.block_size * aux_info.bg_desc[i].bg_block_bitmap, 138a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross SEEK_SET); 139a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 140a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to seek to block group bitmap %d", i); 141a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 142a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = read(fd, block_bitmap, info.block_size); 143a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 144a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to read block group bitmap %d", i); 145a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret != (int)info.block_size) 146a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error("failed to read all of block group bitmap %d", i); 147a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 148a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross start_contiguous_block = -1; 149a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross for (block = 0; block < last_block; block++) { 150a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (start_contiguous_block >= 0) { 151a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (!bitmap_get_bit(block_bitmap, block)) { 152a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 start_block = first_block + start_contiguous_block; 153a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 len_blocks = block - start_contiguous_block; 154a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 155f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross sparse_file_add_file(info.sparse_file, filename, 156f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross (u64)info.block_size * start_block, 157a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross info.block_size * len_blocks, start_block); 158a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross start_contiguous_block = -1; 159a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 160a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } else { 161a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (bitmap_get_bit(block_bitmap, block)) 162a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross start_contiguous_block = block; 163a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 164a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 165a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 166a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (start_contiguous_block >= 0) { 167a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 start_block = first_block + start_contiguous_block; 168a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 len_blocks = last_block - start_contiguous_block; 169f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross sparse_file_add_file(info.sparse_file, filename, 170f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross (u64)info.block_size * start_block, 171a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross info.block_size * len_blocks, start_block); 172a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 173a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 174a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 175a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross return 0; 176a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross} 177a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 178a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Crossint main(int argc, char **argv) 179a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross{ 180a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int opt; 181a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross const char *in = NULL; 182a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross const char *out = NULL; 183a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int gzip = 0; 184a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int sparse = 1; 1850349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau int infd, outfd; 186a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int crc = 0; 187a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 188a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross while ((opt = getopt(argc, argv, "cvzS")) != -1) { 189a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross switch (opt) { 190a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross case 'c': 191a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross crc = 1; 192a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross break; 193a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross case 'v': 194a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross verbose = 1; 195a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross break; 196a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross case 'z': 197a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross gzip = 1; 198a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross break; 199a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross case 'S': 200a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross sparse = 0; 201a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross break; 202a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 203a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 204a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 205a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (optind >= argc) { 206a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, "Expected image or block device after options\n"); 207a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross usage(argv[0]); 208a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross exit(EXIT_FAILURE); 209a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 210a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 211a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross in = argv[optind++]; 212a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 213a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (optind >= argc) { 214a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, "Expected output image after input image\n"); 215a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross usage(argv[0]); 216a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross exit(EXIT_FAILURE); 217a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 218a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 219a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross out = argv[optind++]; 220a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 221a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (optind < argc) { 222a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, "Unexpected argument: %s\n", argv[optind]); 223a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross usage(argv[0]); 224a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross exit(EXIT_FAILURE); 225a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 226a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 2270349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau infd = open(in, O_RDONLY); 228a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 2290349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau if (infd < 0) 230a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to open input image"); 231a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 2320349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau read_ext(infd); 2330349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau 234f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross info.sparse_file = sparse_file_new(info.block_size, info.len); 235f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross 2360349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau build_sparse_ext(infd, in); 237a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 2380349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau close(infd); 239a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 2400349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau if (strcmp(out, "-")) { 2410349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau outfd = open(out, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); 2420349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau if (outfd < 0) { 2430349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau error_errno("open"); 2440349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau return EXIT_FAILURE; 2450349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau } 2460349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau } else { 2470349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau outfd = STDOUT_FILENO; 2480349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau } 249a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 250dc5abeee1e6fc4827ee0d5ece12aaed2dd56f4c7Colin Cross write_ext4_image(outfd, gzip, sparse, crc); 2510349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau close(outfd); 252a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 253f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross sparse_file_destroy(info.sparse_file); 254f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross 255a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross return 0; 256a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross} 257