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 build_sparse_ext(int fd, const char *filename) 57a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross{ 58a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross unsigned int i; 59a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross unsigned int block; 60a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int start_contiguous_block; 61a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u8 *block_bitmap; 62a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross off64_t ret; 63a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 64a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross block_bitmap = malloc(info.block_size); 65a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (!block_bitmap) 66a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error("failed to allocate block bitmap"); 67a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 68a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (aux_info.first_data_block > 0) 69782879ab61fe825835a9c6a701f91aa7d305acefColin Cross sparse_file_add_file(ext4_sparse_file, filename, 0, 70a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross info.block_size * aux_info.first_data_block, 0); 71a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 72a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross for (i = 0; i < aux_info.groups; i++) { 73a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 first_block = aux_info.first_data_block + i * info.blocks_per_group; 74a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 last_block = min(info.blocks_per_group, aux_info.len_blocks - first_block); 75a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 76a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = lseek64(fd, (u64)info.block_size * aux_info.bg_desc[i].bg_block_bitmap, 77a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross SEEK_SET); 78a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 79a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to seek to block group bitmap %d", i); 80a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 81a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross ret = read(fd, block_bitmap, info.block_size); 82a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret < 0) 83a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to read block group bitmap %d", i); 84a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (ret != (int)info.block_size) 85a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error("failed to read all of block group bitmap %d", i); 86a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 87a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross start_contiguous_block = -1; 88a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross for (block = 0; block < last_block; block++) { 89a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (start_contiguous_block >= 0) { 90a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (!bitmap_get_bit(block_bitmap, block)) { 91a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 start_block = first_block + start_contiguous_block; 92a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 len_blocks = block - start_contiguous_block; 93a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 94782879ab61fe825835a9c6a701f91aa7d305acefColin Cross sparse_file_add_file(ext4_sparse_file, filename, 95f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross (u64)info.block_size * start_block, 96a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross info.block_size * len_blocks, start_block); 97a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross start_contiguous_block = -1; 98a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 99a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } else { 100a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (bitmap_get_bit(block_bitmap, block)) 101a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross start_contiguous_block = block; 102a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 103a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 104a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 105a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (start_contiguous_block >= 0) { 106a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 start_block = first_block + start_contiguous_block; 107a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross u32 len_blocks = last_block - start_contiguous_block; 108782879ab61fe825835a9c6a701f91aa7d305acefColin Cross sparse_file_add_file(ext4_sparse_file, filename, 109f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross (u64)info.block_size * start_block, 110a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross info.block_size * len_blocks, start_block); 111a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 112a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 113a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 114a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross return 0; 115a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross} 116a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 117a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Crossint main(int argc, char **argv) 118a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross{ 119a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int opt; 120a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross const char *in = NULL; 121a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross const char *out = NULL; 122a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int gzip = 0; 123a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int sparse = 1; 1240349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau int infd, outfd; 125a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross int crc = 0; 126a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 127a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross while ((opt = getopt(argc, argv, "cvzS")) != -1) { 128a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross switch (opt) { 129a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross case 'c': 130a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross crc = 1; 131a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross break; 132a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross case 'v': 133a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross verbose = 1; 134a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross break; 135a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross case 'z': 136a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross gzip = 1; 137a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross break; 138a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross case 'S': 139a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross sparse = 0; 140a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross break; 141a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 142a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 143a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 144a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (optind >= argc) { 145a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, "Expected image or block device after options\n"); 146a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross usage(argv[0]); 147a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross exit(EXIT_FAILURE); 148a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 149a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 150a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross in = argv[optind++]; 151a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 152a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (optind >= argc) { 153a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, "Expected output image after input image\n"); 154a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross usage(argv[0]); 155a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross exit(EXIT_FAILURE); 156a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 157a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 158a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross out = argv[optind++]; 159a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 160a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross if (optind < argc) { 161a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross fprintf(stderr, "Unexpected argument: %s\n", argv[optind]); 162a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross usage(argv[0]); 163a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross exit(EXIT_FAILURE); 164a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross } 165a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 1660349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau infd = open(in, O_RDONLY); 167a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 1680349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau if (infd < 0) 169a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross critical_error_errno("failed to open input image"); 170a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 171ee2bba62529ce544a60d141ca10a37407c03ab1ePaul Lawrence read_ext(infd, verbose); 1720349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau 173782879ab61fe825835a9c6a701f91aa7d305acefColin Cross ext4_sparse_file = sparse_file_new(info.block_size, info.len); 174f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross 1750349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau build_sparse_ext(infd, in); 176a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 1770349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau close(infd); 178a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 1790349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau if (strcmp(out, "-")) { 1800349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau outfd = open(out, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); 1810349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau if (outfd < 0) { 1820349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau error_errno("open"); 1830349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau return EXIT_FAILURE; 1840349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau } 1850349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau } else { 1860349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau outfd = STDOUT_FILENO; 1870349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau } 188a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 189dc5abeee1e6fc4827ee0d5ece12aaed2dd56f4c7Colin Cross write_ext4_image(outfd, gzip, sparse, crc); 1900349bd9f14d252673a7a25767da4a80121aaaaf2Anatol Pomazau close(outfd); 191a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross 192782879ab61fe825835a9c6a701f91aa7d305acefColin Cross sparse_file_destroy(ext4_sparse_file); 193f0ee37ffded79afdb03e15ae3a69969d2b7e6079Colin Cross 194a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross return 0; 195a7ed433f2dc0116627a93b18fbb260f0665ca0cbColin Cross} 196