• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <getopt.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <limits.h>
6 #include <ext2fs/ext2fs.h>
7 
8 #include "perms.h"
9 #include "base_fs.h"
10 #include "block_list.h"
11 #include "basefs_allocator.h"
12 #include "create_inode.h"
13 
14 static char *prog_name = "e2fsdroid";
15 static char *in_file;
16 static char *block_list;
17 static char *basefs_out;
18 static char *basefs_in;
19 static char *mountpoint = "";
20 static time_t fixed_time = -1;
21 static char *fs_config_file;
22 static char *file_contexts;
23 static char *product_out;
24 static char *src_dir;
25 static int android_configure;
26 static int android_sparse_file = 1;
27 
usage(int ret)28 static void usage(int ret)
29 {
30 	fprintf(stderr, "%s [-B block_list] [-D basefs_out] [-T timestamp]\n"
31 			"\t[-C fs_config] [-S file_contexts] [-p product_out]\n"
32 			"\t[-a mountpoint] [-d basefs_in] [-f src_dir] [-e] image\n",
33                 prog_name);
34 	exit(ret);
35 }
36 
absolute_path(const char * file)37 static char *absolute_path(const char *file)
38 {
39 	char *ret;
40 	char cwd[PATH_MAX];
41 
42 	if (file[0] != '/') {
43 		getcwd(cwd, PATH_MAX);
44 		ret = malloc(strlen(cwd) + 1 + strlen(file) + 1);
45 		if (ret)
46 			sprintf(ret, "%s/%s", cwd, file);
47 	} else
48 		ret = strdup(file);
49 	return ret;
50 }
51 
main(int argc,char * argv[])52 int main(int argc, char *argv[])
53 {
54 	int c;
55 	char *p;
56 	int flags = EXT2_FLAG_RW;
57 	errcode_t retval;
58 	io_manager io_mgr;
59 	ext2_filsys fs = NULL;
60 	struct fs_ops_callbacks fs_callbacks = { NULL, NULL };
61 
62 	add_error_table(&et_ext2_error_table);
63 
64 	while ((c = getopt (argc, argv, "T:C:S:p:a:D:d:B:f:e")) != EOF) {
65 		switch (c) {
66 		case 'T':
67 			fixed_time = strtoul(optarg, &p, 0);
68 			android_configure = 1;
69 			break;
70 		case 'C':
71 			fs_config_file = absolute_path(optarg);
72 			android_configure = 1;
73 			break;
74 		case 'S':
75 			file_contexts = absolute_path(optarg);
76 			android_configure = 1;
77 			break;
78 		case 'p':
79 			product_out = absolute_path(optarg);
80 			break;
81 		case 'a':
82 			mountpoint = strdup(optarg);
83 			break;
84 		case 'D':
85 			basefs_out = absolute_path(optarg);
86 			break;
87 		case 'd':
88 			basefs_in = absolute_path(optarg);
89 			break;
90 		case 'B':
91 			block_list = absolute_path(optarg);
92 			break;
93 		case 'f':
94 			src_dir = absolute_path(optarg);
95 			break;
96 		case 'e':
97 			android_sparse_file = 0;
98 			break;
99 		default:
100 			usage(EXIT_FAILURE);
101 		}
102 	}
103 	if (optind >= argc) {
104 		fprintf(stderr, "Expected filename after options\n");
105 		exit(EXIT_FAILURE);
106 	}
107 	in_file = strdup(argv[optind]);
108 
109 	io_mgr = android_sparse_file ? sparse_io_manager: unix_io_manager;
110 	retval = ext2fs_open(in_file, flags, 0, 0, io_mgr, &fs);
111 	if (retval) {
112 		com_err(prog_name, retval, "while opening file %s\n", in_file);
113 		return retval;
114 	}
115 
116 	if (src_dir) {
117 		ext2fs_read_bitmaps(fs);
118 		if (basefs_in) {
119 			retval = base_fs_alloc_load(fs, basefs_in, mountpoint);
120 			if (retval) {
121 				com_err(prog_name, retval, "%s",
122 				"while reading base_fs file");
123 			    exit(1);
124 			}
125 			fs_callbacks.create_new_inode =
126 				base_fs_alloc_set_target;
127 			fs_callbacks.end_create_new_inode =
128 				base_fs_alloc_unset_target;
129 		}
130 		retval = populate_fs2(fs, EXT2_ROOT_INO, src_dir,
131 				      EXT2_ROOT_INO, &fs_callbacks);
132 		if (retval) {
133 			com_err(prog_name, retval, "%s",
134 			"while populating file system");
135 		    exit(1);
136 		}
137 		if (basefs_in)
138 			base_fs_alloc_cleanup(fs);
139 	}
140 
141 	if (android_configure) {
142 		retval = android_configure_fs(fs, src_dir, product_out, mountpoint,
143 			file_contexts, fs_config_file, fixed_time);
144 		if (retval) {
145 			com_err(prog_name, retval, "%s",
146 				"while configuring the file system");
147 			exit(1);
148 		}
149 	}
150 
151 	if (block_list) {
152 		retval = fsmap_iter_filsys(fs, &block_list_format, block_list,
153 					   mountpoint);
154 		if (retval) {
155 			com_err(prog_name, retval, "%s",
156 				"while creating the block_list");
157 			exit(1);
158 		}
159 	}
160 
161 	if (basefs_out) {
162 		retval = fsmap_iter_filsys(fs, &base_fs_format,
163 					   basefs_out, mountpoint);
164 		if (retval) {
165 			com_err(prog_name, retval, "%s",
166 				"while creating the basefs file");
167 			exit(1);
168 		}
169 	}
170 
171 	retval = ext2fs_close_free(&fs);
172 	if (retval) {
173 		com_err(prog_name, retval, "%s",
174 				"while writing superblocks");
175 		exit(1);
176 	}
177 
178 	remove_error_table(&et_ext2_error_table);
179 	return 0;
180 }
181