2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define _FILE_OFFSET_BITS 64
18 #define _LARGEFILE64_SOURCE 1
20 #include <sys/types.h>
22 #include <sys/types.h>
28 #include <sparse/sparse.h>
30 #include "ext4_utils.h"
31 #include "make_ext4fs.h"
34 #if defined(__APPLE__) && defined(__MACH__)
38 #ifndef USE_MINGW /* O_BINARY is windows-specific flag */
42 extern struct fs_info info
;
44 static int verbose
= 0;
46 static void usage(char *path
)
48 fprintf(stderr
, "%s [ options ] <image or block device> <output image>\n", path
);
49 fprintf(stderr
, "\n");
50 fprintf(stderr
, " -c include CRC block\n");
51 fprintf(stderr
, " -v verbose output\n");
52 fprintf(stderr
, " -z gzip output\n");
53 fprintf(stderr
, " -S don't use sparse output format\n");
56 static int build_sparse_ext(int fd
, const char *filename
)
60 int start_contiguous_block
;
64 block_bitmap
= malloc(info
.block_size
);
66 critical_error("failed to allocate block bitmap");
68 if (aux_info
.first_data_block
> 0)
69 sparse_file_add_file(ext4_sparse_file
, filename
, 0,
70 info
.block_size
* aux_info
.first_data_block
, 0);
72 for (i
= 0; i
< aux_info
.groups
; i
++) {
73 u32 first_block
= aux_info
.first_data_block
+ i
* info
.blocks_per_group
;
74 u32 last_block
= min(info
.blocks_per_group
, aux_info
.len_blocks
- first_block
);
76 ret
= lseek64(fd
, (u64
)info
.block_size
* aux_info
.bg_desc
[i
].bg_block_bitmap
,
79 critical_error_errno("failed to seek to block group bitmap %d", i
);
81 ret
= read(fd
, block_bitmap
, info
.block_size
);
83 critical_error_errno("failed to read block group bitmap %d", i
);
84 if (ret
!= (int)info
.block_size
)
85 critical_error("failed to read all of block group bitmap %d", i
);
87 start_contiguous_block
= -1;
88 for (block
= 0; block
< last_block
; block
++) {
89 if (start_contiguous_block
>= 0) {
90 if (!bitmap_get_bit(block_bitmap
, block
)) {
91 u32 start_block
= first_block
+ start_contiguous_block
;
92 u32 len_blocks
= block
- start_contiguous_block
;
94 sparse_file_add_file(ext4_sparse_file
, filename
,
95 (u64
)info
.block_size
* start_block
,
96 info
.block_size
* len_blocks
, start_block
);
97 start_contiguous_block
= -1;
100 if (bitmap_get_bit(block_bitmap
, block
))
101 start_contiguous_block
= block
;
105 if (start_contiguous_block
>= 0) {
106 u32 start_block
= first_block
+ start_contiguous_block
;
107 u32 len_blocks
= last_block
- start_contiguous_block
;
108 sparse_file_add_file(ext4_sparse_file
, filename
,
109 (u64
)info
.block_size
* start_block
,
110 info
.block_size
* len_blocks
, start_block
);
117 int main(int argc
, char **argv
)
120 const char *in
= NULL
;
121 const char *out
= NULL
;
127 while ((opt
= getopt(argc
, argv
, "cvzS")) != -1) {
144 if (optind
>= argc
) {
145 fprintf(stderr
, "Expected image or block device after options\n");
152 if (optind
>= argc
) {
153 fprintf(stderr
, "Expected output image after input image\n");
158 out
= argv
[optind
++];
161 fprintf(stderr
, "Unexpected argument: %s\n", argv
[optind
]);
166 infd
= open(in
, O_RDONLY
);
169 critical_error_errno("failed to open input image");
171 read_ext(infd
, verbose
);
173 ext4_sparse_file
= sparse_file_new(info
.block_size
, info
.len
);
175 build_sparse_ext(infd
, in
);
179 if (strcmp(out
, "-")) {
180 outfd
= open(out
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, 0644);
186 outfd
= STDOUT_FILENO
;
189 write_ext4_image(outfd
, gzip
, sparse
, crc
);
192 sparse_file_destroy(ext4_sparse_file
);