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