OSDN Git Service

ext4_utils: Export headers for libext4_utils* libs.
[android-x86/system-extras.git] / ext4_utils / ext2simg.c
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef _FILE_OFFSET_BITS
18 #define _FILE_OFFSET_BITS 64
19 #endif
20
21 #ifndef _LARGEFILE64_SOURCE
22 #define _LARGEFILE64_SOURCE 1
23 #endif
24
25 #include <fcntl.h>
26 #include <libgen.h>
27 #include <sys/mman.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31
32 #include <sparse/sparse.h>
33
34 #include "allocate.h"
35 #include "ext4_utils/ext4_utils.h"
36 #include "ext4_utils/make_ext4fs.h"
37
38 #if defined(__APPLE__) && defined(__MACH__)
39 #define off64_t off_t
40 #endif
41
42 #ifndef _WIN32 /* O_BINARY is windows-specific flag */
43 #define O_BINARY 0
44 #endif
45
46 extern struct fs_info info;
47
48 static int verbose = 0;
49
50 static void usage(char *path)
51 {
52         fprintf(stderr, "%s [ options ] <image or block device> <output image>\n", path);
53         fprintf(stderr, "\n");
54         fprintf(stderr, "  -c include CRC block\n");
55         fprintf(stderr, "  -v verbose output\n");
56         fprintf(stderr, "  -z gzip output\n");
57         fprintf(stderr, "  -S don't use sparse output format\n");
58 }
59
60 static int build_sparse_ext(int fd, const char *filename)
61 {
62         unsigned int i;
63         unsigned int block;
64         int start_contiguous_block;
65         u8 *block_bitmap;
66         off64_t ret;
67
68         block_bitmap = malloc(info.block_size);
69         if (!block_bitmap)
70                 critical_error("failed to allocate block bitmap");
71
72         if (aux_info.first_data_block > 0)
73                 sparse_file_add_file(ext4_sparse_file, filename, 0,
74                                 info.block_size * aux_info.first_data_block, 0);
75
76         for (i = 0; i < aux_info.groups; i++) {
77                 u32 first_block = aux_info.first_data_block + i * info.blocks_per_group;
78                 u32 last_block = min(info.blocks_per_group, aux_info.len_blocks - first_block);
79
80                 ret = lseek64(fd, (u64)info.block_size * aux_info.bg_desc[i].bg_block_bitmap,
81                                 SEEK_SET);
82                 if (ret < 0)
83                         critical_error_errno("failed to seek to block group bitmap %d", i);
84
85                 ret = read(fd, block_bitmap, info.block_size);
86                 if (ret < 0)
87                         critical_error_errno("failed to read block group bitmap %d", i);
88                 if (ret != (int)info.block_size)
89                         critical_error("failed to read all of block group bitmap %d", i);
90
91                 start_contiguous_block = -1;
92                 for (block = 0; block < last_block; block++) {
93                         if (start_contiguous_block >= 0) {
94                                 if (!bitmap_get_bit(block_bitmap, block)) {
95                                         u32 start_block = first_block + start_contiguous_block;
96                                         u32 len_blocks = block - start_contiguous_block;
97
98                                         sparse_file_add_file(ext4_sparse_file, filename,
99                                                         (u64)info.block_size * start_block,
100                                                         info.block_size * len_blocks, start_block);
101                                         start_contiguous_block = -1;
102                                 }
103                         } else {
104                                 if (bitmap_get_bit(block_bitmap, block))
105                                         start_contiguous_block = block;
106                         }
107                 }
108
109                 if (start_contiguous_block >= 0) {
110                         u32 start_block = first_block + start_contiguous_block;
111                         u32 len_blocks = last_block - start_contiguous_block;
112                         sparse_file_add_file(ext4_sparse_file, filename,
113                                         (u64)info.block_size * start_block,
114                                         info.block_size * len_blocks, start_block);
115                 }
116         }
117
118         return 0;
119 }
120
121 int main(int argc, char **argv)
122 {
123         int opt;
124         const char *in = NULL;
125         const char *out = NULL;
126         int gzip = 0;
127         int sparse = 1;
128         int infd, outfd;
129         int crc = 0;
130
131         while ((opt = getopt(argc, argv, "cvzS")) != -1) {
132                 switch (opt) {
133                 case 'c':
134                         crc = 1;
135                         break;
136                 case 'v':
137                         verbose = 1;
138                         break;
139                 case 'z':
140                         gzip = 1;
141                         break;
142                 case 'S':
143                         sparse = 0;
144                         break;
145                 }
146         }
147
148         if (optind >= argc) {
149                 fprintf(stderr, "Expected image or block device after options\n");
150                 usage(argv[0]);
151                 exit(EXIT_FAILURE);
152         }
153
154         in = argv[optind++];
155
156         if (optind >= argc) {
157                 fprintf(stderr, "Expected output image after input image\n");
158                 usage(argv[0]);
159                 exit(EXIT_FAILURE);
160         }
161
162         out = argv[optind++];
163
164         if (optind < argc) {
165                 fprintf(stderr, "Unexpected argument: %s\n", argv[optind]);
166                 usage(argv[0]);
167                 exit(EXIT_FAILURE);
168         }
169
170         infd = open(in, O_RDONLY);
171
172         if (infd < 0)
173                 critical_error_errno("failed to open input image");
174
175         read_ext(infd, verbose);
176
177         ext4_sparse_file = sparse_file_new(info.block_size, info.len);
178
179         build_sparse_ext(infd, in);
180
181         close(infd);
182
183         if (strcmp(out, "-")) {
184                 outfd = open(out, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
185                 if (outfd < 0) {
186                         error_errno("open");
187                         return EXIT_FAILURE;
188                 }
189         } else {
190                 outfd = STDOUT_FILENO;
191         }
192
193         write_ext4_image(outfd, gzip, sparse, crc);
194         close(outfd);
195
196         sparse_file_destroy(ext4_sparse_file);
197
198         return 0;
199 }