Home | History | Annotate | Download | only in android
      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