1*6a54128fSAndroid Build Coastguard Worker #define _GNU_SOURCE
2*6a54128fSAndroid Build Coastguard Worker
3*6a54128fSAndroid Build Coastguard Worker #include "config.h"
4*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
5*6a54128fSAndroid Build Coastguard Worker #include <getopt.h>
6*6a54128fSAndroid Build Coastguard Worker #include <string.h>
7*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
8*6a54128fSAndroid Build Coastguard Worker #include <limits.h>
9*6a54128fSAndroid Build Coastguard Worker
10*6a54128fSAndroid Build Coastguard Worker #include "perms.h"
11*6a54128fSAndroid Build Coastguard Worker #include "base_fs.h"
12*6a54128fSAndroid Build Coastguard Worker #include "block_list.h"
13*6a54128fSAndroid Build Coastguard Worker #include "basefs_allocator.h"
14*6a54128fSAndroid Build Coastguard Worker #include "create_inode.h"
15*6a54128fSAndroid Build Coastguard Worker
16*6a54128fSAndroid Build Coastguard Worker #ifndef UID_GID_MAP_MAX_EXTENTS
17*6a54128fSAndroid Build Coastguard Worker /*
18*6a54128fSAndroid Build Coastguard Worker * The value is defined in linux/user_namspace.h.
19*6a54128fSAndroid Build Coastguard Worker * The value is (arbitrarily) 5 in 4.14 and earlier, or 340 in 4.15 and later.
20*6a54128fSAndroid Build Coastguard Worker * Here, the bigger value is taken. See also man user_namespace(7).
21*6a54128fSAndroid Build Coastguard Worker */
22*6a54128fSAndroid Build Coastguard Worker #define UID_GID_MAP_MAX_EXTENTS 340
23*6a54128fSAndroid Build Coastguard Worker #endif
24*6a54128fSAndroid Build Coastguard Worker
25*6a54128fSAndroid Build Coastguard Worker // disable leak detection, breaks host asan build
__asan_default_options()26*6a54128fSAndroid Build Coastguard Worker const char *__asan_default_options() {
27*6a54128fSAndroid Build Coastguard Worker return "detect_leaks=0";
28*6a54128fSAndroid Build Coastguard Worker }
29*6a54128fSAndroid Build Coastguard Worker
30*6a54128fSAndroid Build Coastguard Worker static char *prog_name = "e2fsdroid";
31*6a54128fSAndroid Build Coastguard Worker static char *in_file;
32*6a54128fSAndroid Build Coastguard Worker static char *block_list;
33*6a54128fSAndroid Build Coastguard Worker static char *basefs_out;
34*6a54128fSAndroid Build Coastguard Worker static char *basefs_in;
35*6a54128fSAndroid Build Coastguard Worker static char *mountpoint = "";
36*6a54128fSAndroid Build Coastguard Worker static time_t fixed_time = -1;
37*6a54128fSAndroid Build Coastguard Worker static char *fs_config_file;
38*6a54128fSAndroid Build Coastguard Worker static struct selinux_opt seopt_file[8];
39*6a54128fSAndroid Build Coastguard Worker static int max_nr_opt = (int)sizeof(seopt_file) / sizeof(seopt_file[0]);
40*6a54128fSAndroid Build Coastguard Worker static char *product_out;
41*6a54128fSAndroid Build Coastguard Worker static char *src_dir;
42*6a54128fSAndroid Build Coastguard Worker static int android_configure;
43*6a54128fSAndroid Build Coastguard Worker static int android_sparse_file = 1;
44*6a54128fSAndroid Build Coastguard Worker
usage(int ret)45*6a54128fSAndroid Build Coastguard Worker static void usage(int ret)
46*6a54128fSAndroid Build Coastguard Worker {
47*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "%s [-B block_list] [-D basefs_out] [-T timestamp]\n"
48*6a54128fSAndroid Build Coastguard Worker "\t[-C fs_config] [-S file_contexts] [-p product_out]\n"
49*6a54128fSAndroid Build Coastguard Worker "\t[-a mountpoint] [-d basefs_in] [-f src_dir] [-e] [-s]\n"
50*6a54128fSAndroid Build Coastguard Worker "\t[-u uid-mapping] [-g gid-mapping] image\n",
51*6a54128fSAndroid Build Coastguard Worker prog_name);
52*6a54128fSAndroid Build Coastguard Worker exit(ret);
53*6a54128fSAndroid Build Coastguard Worker }
54*6a54128fSAndroid Build Coastguard Worker
absolute_path(const char * file)55*6a54128fSAndroid Build Coastguard Worker static char *absolute_path(const char *file)
56*6a54128fSAndroid Build Coastguard Worker {
57*6a54128fSAndroid Build Coastguard Worker char *ret;
58*6a54128fSAndroid Build Coastguard Worker char cwd[PATH_MAX];
59*6a54128fSAndroid Build Coastguard Worker
60*6a54128fSAndroid Build Coastguard Worker if (file[0] != '/') {
61*6a54128fSAndroid Build Coastguard Worker if (getcwd(cwd, PATH_MAX) == NULL) {
62*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "Failed to getcwd\n");
63*6a54128fSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
64*6a54128fSAndroid Build Coastguard Worker }
65*6a54128fSAndroid Build Coastguard Worker ret = malloc(strlen(cwd) + 1 + strlen(file) + 1);
66*6a54128fSAndroid Build Coastguard Worker if (ret)
67*6a54128fSAndroid Build Coastguard Worker sprintf(ret, "%s/%s", cwd, file);
68*6a54128fSAndroid Build Coastguard Worker } else
69*6a54128fSAndroid Build Coastguard Worker ret = strdup(file);
70*6a54128fSAndroid Build Coastguard Worker return ret;
71*6a54128fSAndroid Build Coastguard Worker }
72*6a54128fSAndroid Build Coastguard Worker
parse_ugid_map_entry(char * line,struct ugid_map_entry * result)73*6a54128fSAndroid Build Coastguard Worker static int parse_ugid_map_entry(char* line, struct ugid_map_entry* result)
74*6a54128fSAndroid Build Coastguard Worker {
75*6a54128fSAndroid Build Coastguard Worker char *token, *token_saveptr;
76*6a54128fSAndroid Build Coastguard Worker size_t num_tokens;
77*6a54128fSAndroid Build Coastguard Worker unsigned int *parsed[] = {&result->child_id,
78*6a54128fSAndroid Build Coastguard Worker &result->parent_id,
79*6a54128fSAndroid Build Coastguard Worker &result->length};
80*6a54128fSAndroid Build Coastguard Worker for (token = strtok_r(line, " ", &token_saveptr), num_tokens = 0;
81*6a54128fSAndroid Build Coastguard Worker token && num_tokens < 3;
82*6a54128fSAndroid Build Coastguard Worker token = strtok_r(NULL, " ", &token_saveptr), ++num_tokens) {
83*6a54128fSAndroid Build Coastguard Worker char* endptr = NULL;
84*6a54128fSAndroid Build Coastguard Worker unsigned long t = strtoul(token, &endptr, 10);
85*6a54128fSAndroid Build Coastguard Worker if ((t == ULONG_MAX && errno) || (t > UINT_MAX) || *endptr) {
86*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "Malformed u/gid mapping line\n");
87*6a54128fSAndroid Build Coastguard Worker return 0;
88*6a54128fSAndroid Build Coastguard Worker }
89*6a54128fSAndroid Build Coastguard Worker *parsed[num_tokens] = (unsigned int) t;
90*6a54128fSAndroid Build Coastguard Worker }
91*6a54128fSAndroid Build Coastguard Worker if (num_tokens < 3 || strtok_r(NULL, " ", &token_saveptr) != NULL) {
92*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "Malformed u/gid mapping line\n");
93*6a54128fSAndroid Build Coastguard Worker return 0;
94*6a54128fSAndroid Build Coastguard Worker }
95*6a54128fSAndroid Build Coastguard Worker if (result->child_id + result->length < result->child_id ||
96*6a54128fSAndroid Build Coastguard Worker result->parent_id + result->length < result->parent_id) {
97*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "u/gid mapping overflow\n");
98*6a54128fSAndroid Build Coastguard Worker return 0;
99*6a54128fSAndroid Build Coastguard Worker }
100*6a54128fSAndroid Build Coastguard Worker return 1;
101*6a54128fSAndroid Build Coastguard Worker }
102*6a54128fSAndroid Build Coastguard Worker
103*6a54128fSAndroid Build Coastguard Worker /*
104*6a54128fSAndroid Build Coastguard Worker * Returns 1 if [begin1, begin1+length1) and [begin2, begin2+length2) have
105*6a54128fSAndroid Build Coastguard Worker * overlapping range. Otherwise 0.
106*6a54128fSAndroid Build Coastguard Worker */
is_overlapping(unsigned int begin1,unsigned int length1,unsigned int begin2,unsigned int length2)107*6a54128fSAndroid Build Coastguard Worker static int is_overlapping(unsigned int begin1, unsigned int length1,
108*6a54128fSAndroid Build Coastguard Worker unsigned int begin2, unsigned int length2)
109*6a54128fSAndroid Build Coastguard Worker {
110*6a54128fSAndroid Build Coastguard Worker unsigned int end1 = begin1 + length1;
111*6a54128fSAndroid Build Coastguard Worker unsigned int end2 = begin2 + length2;
112*6a54128fSAndroid Build Coastguard Worker return !(end1 <= begin2 || end2 <= begin1);
113*6a54128fSAndroid Build Coastguard Worker }
114*6a54128fSAndroid Build Coastguard Worker
115*6a54128fSAndroid Build Coastguard Worker /*
116*6a54128fSAndroid Build Coastguard Worker * Verifies if the given mapping works.
117*6a54128fSAndroid Build Coastguard Worker * - Checks if the number of entries is less than or equals to
118*6a54128fSAndroid Build Coastguard Worker * UID_GID_MAP_MAX_EXTENTS.
119*6a54128fSAndroid Build Coastguard Worker * - Checks if there is no overlapped ranges.
120*6a54128fSAndroid Build Coastguard Worker * Returns 1 if valid, otherwise 0.
121*6a54128fSAndroid Build Coastguard Worker */
is_valid_ugid_map(const struct ugid_map * mapping)122*6a54128fSAndroid Build Coastguard Worker static int is_valid_ugid_map(const struct ugid_map* mapping)
123*6a54128fSAndroid Build Coastguard Worker {
124*6a54128fSAndroid Build Coastguard Worker size_t i, j;
125*6a54128fSAndroid Build Coastguard Worker
126*6a54128fSAndroid Build Coastguard Worker if (mapping->size > UID_GID_MAP_MAX_EXTENTS) {
127*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "too many u/gid mapping entries\n");
128*6a54128fSAndroid Build Coastguard Worker return 0;
129*6a54128fSAndroid Build Coastguard Worker }
130*6a54128fSAndroid Build Coastguard Worker
131*6a54128fSAndroid Build Coastguard Worker for (i = 0; i < mapping->size; ++i) {
132*6a54128fSAndroid Build Coastguard Worker const struct ugid_map_entry *entry1 = &mapping->entries[i];
133*6a54128fSAndroid Build Coastguard Worker for (j = i + 1; j < mapping->size; ++j) {
134*6a54128fSAndroid Build Coastguard Worker const struct ugid_map_entry *entry2 =
135*6a54128fSAndroid Build Coastguard Worker &mapping->entries[j];
136*6a54128fSAndroid Build Coastguard Worker if (is_overlapping(entry1->child_id, entry1->length,
137*6a54128fSAndroid Build Coastguard Worker entry2->child_id, entry2->length)) {
138*6a54128fSAndroid Build Coastguard Worker fprintf(stderr,
139*6a54128fSAndroid Build Coastguard Worker "Overlapping child u/gid: [%d %d %d],"
140*6a54128fSAndroid Build Coastguard Worker " [%d %d %d]\n",
141*6a54128fSAndroid Build Coastguard Worker entry1->child_id, entry1->parent_id,
142*6a54128fSAndroid Build Coastguard Worker entry1->length, entry2->child_id,
143*6a54128fSAndroid Build Coastguard Worker entry2->parent_id, entry2->length);
144*6a54128fSAndroid Build Coastguard Worker return 0;
145*6a54128fSAndroid Build Coastguard Worker }
146*6a54128fSAndroid Build Coastguard Worker if (is_overlapping(entry1->parent_id, entry1->length,
147*6a54128fSAndroid Build Coastguard Worker entry2->parent_id, entry2->length)) {
148*6a54128fSAndroid Build Coastguard Worker fprintf(stderr,
149*6a54128fSAndroid Build Coastguard Worker "Overlapping parent u/gid: [%d %d %d],"
150*6a54128fSAndroid Build Coastguard Worker " [%d %d %d]\n",
151*6a54128fSAndroid Build Coastguard Worker entry1->child_id, entry1->parent_id,
152*6a54128fSAndroid Build Coastguard Worker entry1->length, entry2->child_id,
153*6a54128fSAndroid Build Coastguard Worker entry2->parent_id, entry2->length);
154*6a54128fSAndroid Build Coastguard Worker return 0;
155*6a54128fSAndroid Build Coastguard Worker }
156*6a54128fSAndroid Build Coastguard Worker }
157*6a54128fSAndroid Build Coastguard Worker }
158*6a54128fSAndroid Build Coastguard Worker return 1;
159*6a54128fSAndroid Build Coastguard Worker }
160*6a54128fSAndroid Build Coastguard Worker
161*6a54128fSAndroid Build Coastguard Worker /*
162*6a54128fSAndroid Build Coastguard Worker * Parses the UID/GID mapping argument. The argument could be a multi-line
163*6a54128fSAndroid Build Coastguard Worker * string (separated by '\n', no trailing '\n' is allowed). Each line must
164*6a54128fSAndroid Build Coastguard Worker * contain exact three integer tokens; the first token is |child_id|,
165*6a54128fSAndroid Build Coastguard Worker * the second is |parent_id|, and the last is |length| of the mapping range.
166*6a54128fSAndroid Build Coastguard Worker * See also user_namespace(7) man page.
167*6a54128fSAndroid Build Coastguard Worker * On success, the parsed entries are stored in |result|, and it returns 1.
168*6a54128fSAndroid Build Coastguard Worker * Otherwise, returns 0.
169*6a54128fSAndroid Build Coastguard Worker */
parse_ugid_map(char * arg,struct ugid_map * result)170*6a54128fSAndroid Build Coastguard Worker static int parse_ugid_map(char* arg, struct ugid_map* result)
171*6a54128fSAndroid Build Coastguard Worker {
172*6a54128fSAndroid Build Coastguard Worker int i;
173*6a54128fSAndroid Build Coastguard Worker char *line, *line_saveptr;
174*6a54128fSAndroid Build Coastguard Worker size_t current_index;
175*6a54128fSAndroid Build Coastguard Worker
176*6a54128fSAndroid Build Coastguard Worker /* Count the number of lines. */
177*6a54128fSAndroid Build Coastguard Worker result->size = 1;
178*6a54128fSAndroid Build Coastguard Worker for (i = 0; arg[i]; ++i) {
179*6a54128fSAndroid Build Coastguard Worker if (arg[i] == '\n')
180*6a54128fSAndroid Build Coastguard Worker ++result->size;
181*6a54128fSAndroid Build Coastguard Worker }
182*6a54128fSAndroid Build Coastguard Worker
183*6a54128fSAndroid Build Coastguard Worker /* Allocate memory for entries. */
184*6a54128fSAndroid Build Coastguard Worker result->entries = malloc(sizeof(struct ugid_map_entry) * result->size);
185*6a54128fSAndroid Build Coastguard Worker if (!result->entries) {
186*6a54128fSAndroid Build Coastguard Worker result->size = 0;
187*6a54128fSAndroid Build Coastguard Worker return 0;
188*6a54128fSAndroid Build Coastguard Worker }
189*6a54128fSAndroid Build Coastguard Worker
190*6a54128fSAndroid Build Coastguard Worker /* Parse each line */
191*6a54128fSAndroid Build Coastguard Worker for (line = strtok_r(arg, "\n", &line_saveptr), current_index = 0;
192*6a54128fSAndroid Build Coastguard Worker line;
193*6a54128fSAndroid Build Coastguard Worker line = strtok_r(NULL, "\n", &line_saveptr), ++current_index) {
194*6a54128fSAndroid Build Coastguard Worker if (!parse_ugid_map_entry(
195*6a54128fSAndroid Build Coastguard Worker line, &result->entries[current_index])) {
196*6a54128fSAndroid Build Coastguard Worker return 0;
197*6a54128fSAndroid Build Coastguard Worker }
198*6a54128fSAndroid Build Coastguard Worker }
199*6a54128fSAndroid Build Coastguard Worker
200*6a54128fSAndroid Build Coastguard Worker return is_valid_ugid_map(result);
201*6a54128fSAndroid Build Coastguard Worker }
202*6a54128fSAndroid Build Coastguard Worker
main(int argc,char * argv[])203*6a54128fSAndroid Build Coastguard Worker int main(int argc, char *argv[])
204*6a54128fSAndroid Build Coastguard Worker {
205*6a54128fSAndroid Build Coastguard Worker int c;
206*6a54128fSAndroid Build Coastguard Worker char *p;
207*6a54128fSAndroid Build Coastguard Worker int flags = EXT2_FLAG_RW;
208*6a54128fSAndroid Build Coastguard Worker errcode_t retval;
209*6a54128fSAndroid Build Coastguard Worker io_manager io_mgr;
210*6a54128fSAndroid Build Coastguard Worker ext2_filsys fs = NULL;
211*6a54128fSAndroid Build Coastguard Worker struct fs_ops_callbacks fs_callbacks = { NULL, NULL };
212*6a54128fSAndroid Build Coastguard Worker char *token;
213*6a54128fSAndroid Build Coastguard Worker int nr_opt = 0;
214*6a54128fSAndroid Build Coastguard Worker ext2_ino_t inodes_count;
215*6a54128fSAndroid Build Coastguard Worker ext2_ino_t free_inodes_count;
216*6a54128fSAndroid Build Coastguard Worker blk64_t blocks_count;
217*6a54128fSAndroid Build Coastguard Worker blk64_t free_blocks_count;
218*6a54128fSAndroid Build Coastguard Worker struct ugid_map uid_map = { 0, NULL }, gid_map = { 0, NULL };
219*6a54128fSAndroid Build Coastguard Worker
220*6a54128fSAndroid Build Coastguard Worker add_error_table(&et_ext2_error_table);
221*6a54128fSAndroid Build Coastguard Worker
222*6a54128fSAndroid Build Coastguard Worker while ((c = getopt (argc, argv, "T:C:S:p:a:D:d:B:f:esu:g:")) != EOF) {
223*6a54128fSAndroid Build Coastguard Worker switch (c) {
224*6a54128fSAndroid Build Coastguard Worker case 'T':
225*6a54128fSAndroid Build Coastguard Worker fixed_time = strtoul(optarg, &p, 0);
226*6a54128fSAndroid Build Coastguard Worker android_configure = 1;
227*6a54128fSAndroid Build Coastguard Worker break;
228*6a54128fSAndroid Build Coastguard Worker case 'C':
229*6a54128fSAndroid Build Coastguard Worker fs_config_file = absolute_path(optarg);
230*6a54128fSAndroid Build Coastguard Worker android_configure = 1;
231*6a54128fSAndroid Build Coastguard Worker break;
232*6a54128fSAndroid Build Coastguard Worker case 'S':
233*6a54128fSAndroid Build Coastguard Worker token = strtok(optarg, ",");
234*6a54128fSAndroid Build Coastguard Worker while (token) {
235*6a54128fSAndroid Build Coastguard Worker if (nr_opt == max_nr_opt) {
236*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "Expected at most %d selinux opts\n",
237*6a54128fSAndroid Build Coastguard Worker max_nr_opt);
238*6a54128fSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
239*6a54128fSAndroid Build Coastguard Worker }
240*6a54128fSAndroid Build Coastguard Worker seopt_file[nr_opt].type = SELABEL_OPT_PATH;
241*6a54128fSAndroid Build Coastguard Worker seopt_file[nr_opt].value = absolute_path(token);
242*6a54128fSAndroid Build Coastguard Worker nr_opt++;
243*6a54128fSAndroid Build Coastguard Worker token = strtok(NULL, ",");
244*6a54128fSAndroid Build Coastguard Worker }
245*6a54128fSAndroid Build Coastguard Worker android_configure = 1;
246*6a54128fSAndroid Build Coastguard Worker break;
247*6a54128fSAndroid Build Coastguard Worker case 'p':
248*6a54128fSAndroid Build Coastguard Worker product_out = absolute_path(optarg);
249*6a54128fSAndroid Build Coastguard Worker android_configure = 1;
250*6a54128fSAndroid Build Coastguard Worker break;
251*6a54128fSAndroid Build Coastguard Worker case 'a':
252*6a54128fSAndroid Build Coastguard Worker mountpoint = strdup(optarg);
253*6a54128fSAndroid Build Coastguard Worker break;
254*6a54128fSAndroid Build Coastguard Worker case 'D':
255*6a54128fSAndroid Build Coastguard Worker basefs_out = absolute_path(optarg);
256*6a54128fSAndroid Build Coastguard Worker break;
257*6a54128fSAndroid Build Coastguard Worker case 'd':
258*6a54128fSAndroid Build Coastguard Worker basefs_in = absolute_path(optarg);
259*6a54128fSAndroid Build Coastguard Worker break;
260*6a54128fSAndroid Build Coastguard Worker case 'B':
261*6a54128fSAndroid Build Coastguard Worker block_list = absolute_path(optarg);
262*6a54128fSAndroid Build Coastguard Worker break;
263*6a54128fSAndroid Build Coastguard Worker case 'f':
264*6a54128fSAndroid Build Coastguard Worker src_dir = absolute_path(optarg);
265*6a54128fSAndroid Build Coastguard Worker break;
266*6a54128fSAndroid Build Coastguard Worker case 'e':
267*6a54128fSAndroid Build Coastguard Worker android_sparse_file = 0;
268*6a54128fSAndroid Build Coastguard Worker break;
269*6a54128fSAndroid Build Coastguard Worker case 's':
270*6a54128fSAndroid Build Coastguard Worker flags |= EXT2_FLAG_SHARE_DUP;
271*6a54128fSAndroid Build Coastguard Worker break;
272*6a54128fSAndroid Build Coastguard Worker case 'u':
273*6a54128fSAndroid Build Coastguard Worker if (!parse_ugid_map(optarg, &uid_map))
274*6a54128fSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
275*6a54128fSAndroid Build Coastguard Worker android_configure = 1;
276*6a54128fSAndroid Build Coastguard Worker break;
277*6a54128fSAndroid Build Coastguard Worker case 'g':
278*6a54128fSAndroid Build Coastguard Worker if (!parse_ugid_map(optarg, &gid_map))
279*6a54128fSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
280*6a54128fSAndroid Build Coastguard Worker android_configure = 1;
281*6a54128fSAndroid Build Coastguard Worker break;
282*6a54128fSAndroid Build Coastguard Worker default:
283*6a54128fSAndroid Build Coastguard Worker usage(EXIT_FAILURE);
284*6a54128fSAndroid Build Coastguard Worker }
285*6a54128fSAndroid Build Coastguard Worker }
286*6a54128fSAndroid Build Coastguard Worker if (optind >= argc) {
287*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "Expected filename after options\n");
288*6a54128fSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
289*6a54128fSAndroid Build Coastguard Worker }
290*6a54128fSAndroid Build Coastguard Worker
291*6a54128fSAndroid Build Coastguard Worker if (android_sparse_file) {
292*6a54128fSAndroid Build Coastguard Worker io_mgr = sparse_io_manager;
293*6a54128fSAndroid Build Coastguard Worker if (asprintf(&in_file, "(%s)", argv[optind]) == -1) {
294*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "Failed to allocate file name\n");
295*6a54128fSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
296*6a54128fSAndroid Build Coastguard Worker }
297*6a54128fSAndroid Build Coastguard Worker } else {
298*6a54128fSAndroid Build Coastguard Worker io_mgr = unix_io_manager;
299*6a54128fSAndroid Build Coastguard Worker in_file = strdup(argv[optind]);
300*6a54128fSAndroid Build Coastguard Worker }
301*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_open(in_file, flags, 0, 0, io_mgr, &fs);
302*6a54128fSAndroid Build Coastguard Worker if (retval) {
303*6a54128fSAndroid Build Coastguard Worker com_err(prog_name, retval, "while opening file %s\n", in_file);
304*6a54128fSAndroid Build Coastguard Worker return retval;
305*6a54128fSAndroid Build Coastguard Worker }
306*6a54128fSAndroid Build Coastguard Worker
307*6a54128fSAndroid Build Coastguard Worker if (src_dir) {
308*6a54128fSAndroid Build Coastguard Worker ext2fs_read_bitmaps(fs);
309*6a54128fSAndroid Build Coastguard Worker if (basefs_in) {
310*6a54128fSAndroid Build Coastguard Worker retval = base_fs_alloc_load(fs, basefs_in, mountpoint,
311*6a54128fSAndroid Build Coastguard Worker src_dir);
312*6a54128fSAndroid Build Coastguard Worker if (retval) {
313*6a54128fSAndroid Build Coastguard Worker com_err(prog_name, retval, "%s",
314*6a54128fSAndroid Build Coastguard Worker "while reading base_fs file");
315*6a54128fSAndroid Build Coastguard Worker exit(1);
316*6a54128fSAndroid Build Coastguard Worker }
317*6a54128fSAndroid Build Coastguard Worker fs_callbacks.create_new_inode =
318*6a54128fSAndroid Build Coastguard Worker base_fs_alloc_set_target;
319*6a54128fSAndroid Build Coastguard Worker fs_callbacks.end_create_new_inode =
320*6a54128fSAndroid Build Coastguard Worker base_fs_alloc_unset_target;
321*6a54128fSAndroid Build Coastguard Worker }
322*6a54128fSAndroid Build Coastguard Worker retval = populate_fs2(fs, EXT2_ROOT_INO, src_dir,
323*6a54128fSAndroid Build Coastguard Worker EXT2_ROOT_INO, &fs_callbacks);
324*6a54128fSAndroid Build Coastguard Worker if (retval) {
325*6a54128fSAndroid Build Coastguard Worker com_err(prog_name, retval, "%s",
326*6a54128fSAndroid Build Coastguard Worker "while populating file system");
327*6a54128fSAndroid Build Coastguard Worker exit(1);
328*6a54128fSAndroid Build Coastguard Worker }
329*6a54128fSAndroid Build Coastguard Worker if (basefs_in)
330*6a54128fSAndroid Build Coastguard Worker base_fs_alloc_cleanup(fs);
331*6a54128fSAndroid Build Coastguard Worker }
332*6a54128fSAndroid Build Coastguard Worker
333*6a54128fSAndroid Build Coastguard Worker if (android_configure) {
334*6a54128fSAndroid Build Coastguard Worker retval = android_configure_fs(
335*6a54128fSAndroid Build Coastguard Worker fs, src_dir, product_out, mountpoint, seopt_file,
336*6a54128fSAndroid Build Coastguard Worker nr_opt, fs_config_file, fixed_time, &uid_map, &gid_map);
337*6a54128fSAndroid Build Coastguard Worker if (retval) {
338*6a54128fSAndroid Build Coastguard Worker com_err(prog_name, retval, "%s",
339*6a54128fSAndroid Build Coastguard Worker "while configuring the file system");
340*6a54128fSAndroid Build Coastguard Worker exit(1);
341*6a54128fSAndroid Build Coastguard Worker }
342*6a54128fSAndroid Build Coastguard Worker }
343*6a54128fSAndroid Build Coastguard Worker
344*6a54128fSAndroid Build Coastguard Worker if (block_list) {
345*6a54128fSAndroid Build Coastguard Worker retval = fsmap_iter_filsys(fs, &block_list_format, block_list,
346*6a54128fSAndroid Build Coastguard Worker mountpoint);
347*6a54128fSAndroid Build Coastguard Worker if (retval) {
348*6a54128fSAndroid Build Coastguard Worker com_err(prog_name, retval, "%s",
349*6a54128fSAndroid Build Coastguard Worker "while creating the block_list");
350*6a54128fSAndroid Build Coastguard Worker exit(1);
351*6a54128fSAndroid Build Coastguard Worker }
352*6a54128fSAndroid Build Coastguard Worker }
353*6a54128fSAndroid Build Coastguard Worker
354*6a54128fSAndroid Build Coastguard Worker if (basefs_out) {
355*6a54128fSAndroid Build Coastguard Worker retval = fsmap_iter_filsys(fs, &base_fs_format,
356*6a54128fSAndroid Build Coastguard Worker basefs_out, mountpoint);
357*6a54128fSAndroid Build Coastguard Worker if (retval) {
358*6a54128fSAndroid Build Coastguard Worker com_err(prog_name, retval, "%s",
359*6a54128fSAndroid Build Coastguard Worker "while creating the basefs file");
360*6a54128fSAndroid Build Coastguard Worker exit(1);
361*6a54128fSAndroid Build Coastguard Worker }
362*6a54128fSAndroid Build Coastguard Worker }
363*6a54128fSAndroid Build Coastguard Worker
364*6a54128fSAndroid Build Coastguard Worker inodes_count = fs->super->s_inodes_count;
365*6a54128fSAndroid Build Coastguard Worker free_inodes_count = fs->super->s_free_inodes_count;
366*6a54128fSAndroid Build Coastguard Worker blocks_count = ext2fs_blocks_count(fs->super);
367*6a54128fSAndroid Build Coastguard Worker free_blocks_count = ext2fs_free_blocks_count(fs->super);
368*6a54128fSAndroid Build Coastguard Worker
369*6a54128fSAndroid Build Coastguard Worker retval = ext2fs_close_free(&fs);
370*6a54128fSAndroid Build Coastguard Worker if (retval) {
371*6a54128fSAndroid Build Coastguard Worker com_err(prog_name, retval, "%s",
372*6a54128fSAndroid Build Coastguard Worker "while writing superblocks");
373*6a54128fSAndroid Build Coastguard Worker exit(1);
374*6a54128fSAndroid Build Coastguard Worker }
375*6a54128fSAndroid Build Coastguard Worker
376*6a54128fSAndroid Build Coastguard Worker printf("Created filesystem with %u/%u inodes and %llu/%llu blocks\n",
377*6a54128fSAndroid Build Coastguard Worker inodes_count - free_inodes_count, inodes_count,
378*6a54128fSAndroid Build Coastguard Worker blocks_count - free_blocks_count, blocks_count);
379*6a54128fSAndroid Build Coastguard Worker
380*6a54128fSAndroid Build Coastguard Worker remove_error_table(&et_ext2_error_table);
381*6a54128fSAndroid Build Coastguard Worker return 0;
382*6a54128fSAndroid Build Coastguard Worker }
383