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 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 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 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