1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17 #include <fcntl.h> 18 #include <libgen.h> 19 #include <stdio.h> 20 #include <unistd.h> 21 22 #if defined(__linux__) 23 #include <linux/fs.h> 24 #elif defined(__APPLE__) && defined(__MACH__) 25 #include <sys/disk.h> 26 #endif 27 28 #ifdef ANDROID 29 #include <private/android_filesystem_config.h> 30 #endif 31 32 #ifndef USE_MINGW 33 #include <selinux/selinux.h> 34 #include <selinux/label.h> 35 #include <selinux/android.h> 36 #else 37 struct selabel_handle; 38 #endif 39 40 #include "make_ext4fs.h" 41 #include "ext4_utils.h" 42 43 #ifndef USE_MINGW /* O_BINARY is windows-specific flag */ 44 #define O_BINARY 0 45 #endif 46 47 extern struct fs_info info; 48 49 50 static void usage(char *path) 51 { 52 fprintf(stderr, "%s [ -l <len> ] [ -j <journal size> ] [ -b <block_size> ]\n", basename(path)); 53 fprintf(stderr, " [ -g <blocks per group> ] [ -i <inodes> ] [ -I <inode size> ]\n"); 54 fprintf(stderr, " [ -L <label> ] [ -f ] [ -a <android mountpoint> ]\n"); 55 fprintf(stderr, " [ -S file_contexts ]\n"); 56 fprintf(stderr, " [ -z | -s ] [ -w ] [ -c ] [ -J ] [ -v ]\n"); 57 fprintf(stderr, " <filename> [<directory>]\n"); 58 } 59 60 int main(int argc, char **argv) 61 { 62 int opt; 63 const char *filename = NULL; 64 const char *directory = NULL; 65 char *mountpoint = NULL; 66 fs_config_func_t fs_config_func = NULL; 67 int gzip = 0; 68 int sparse = 0; 69 int crc = 0; 70 int wipe = 0; 71 int fd; 72 int exitcode; 73 int verbose = 0; 74 struct selabel_handle *sehnd = NULL; 75 #ifndef USE_MINGW 76 struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "" } }; 77 #endif 78 79 while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:S:fwzJsctv")) != -1) { 80 switch (opt) { 81 case 'l': 82 info.len = parse_num(optarg); 83 break; 84 case 'j': 85 info.journal_blocks = parse_num(optarg); 86 break; 87 case 'b': 88 info.block_size = parse_num(optarg); 89 break; 90 case 'g': 91 info.blocks_per_group = parse_num(optarg); 92 break; 93 case 'i': 94 info.inodes = parse_num(optarg); 95 break; 96 case 'I': 97 info.inode_size = parse_num(optarg); 98 break; 99 case 'L': 100 info.label = optarg; 101 break; 102 case 'f': 103 force = 1; 104 break; 105 case 'a': 106 #ifdef ANDROID 107 fs_config_func = fs_config; 108 mountpoint = optarg; 109 #else 110 fprintf(stderr, "can't set android permissions - built without android support\n"); 111 usage(argv[0]); 112 exit(EXIT_FAILURE); 113 #endif 114 break; 115 case 'w': 116 wipe = 1; 117 break; 118 case 'z': 119 gzip = 1; 120 break; 121 case 'J': 122 info.no_journal = 1; 123 break; 124 case 'c': 125 crc = 1; 126 break; 127 case 's': 128 sparse = 1; 129 break; 130 case 't': 131 fprintf(stderr, "Warning: -t (initialize inode tables) is deprecated\n"); 132 break; 133 case 'S': 134 #ifndef USE_MINGW 135 seopts[0].value = optarg; 136 sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1); 137 if (!sehnd) { 138 perror(optarg); 139 exit(EXIT_FAILURE); 140 } 141 #endif 142 break; 143 case 'v': 144 verbose = 1; 145 break; 146 default: /* '?' */ 147 usage(argv[0]); 148 exit(EXIT_FAILURE); 149 } 150 } 151 152 #if !defined(HOST) 153 // Use only if -S option not requested 154 if (!sehnd && mountpoint) { 155 sehnd = selinux_android_file_context_handle(); 156 157 if (!sehnd) { 158 perror(optarg); 159 exit(EXIT_FAILURE); 160 } 161 } 162 #endif 163 164 if (wipe && sparse) { 165 fprintf(stderr, "Cannot specifiy both wipe and sparse\n"); 166 usage(argv[0]); 167 exit(EXIT_FAILURE); 168 } 169 170 if (wipe && gzip) { 171 fprintf(stderr, "Cannot specifiy both wipe and gzip\n"); 172 usage(argv[0]); 173 exit(EXIT_FAILURE); 174 } 175 176 if (optind >= argc) { 177 fprintf(stderr, "Expected filename after options\n"); 178 usage(argv[0]); 179 exit(EXIT_FAILURE); 180 } 181 182 filename = argv[optind++]; 183 184 if (optind < argc) 185 directory = argv[optind++]; 186 187 if (optind < argc) { 188 fprintf(stderr, "Unexpected argument: %s\n", argv[optind]); 189 usage(argv[0]); 190 exit(EXIT_FAILURE); 191 } 192 193 if (strcmp(filename, "-")) { 194 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); 195 if (fd < 0) { 196 perror("open"); 197 return EXIT_FAILURE; 198 } 199 } else { 200 fd = STDOUT_FILENO; 201 } 202 203 exitcode = make_ext4fs_internal(fd, directory, mountpoint, fs_config_func, gzip, 204 sparse, crc, wipe, sehnd, verbose); 205 close(fd); 206 if (exitcode && strcmp(filename, "-")) 207 unlink(filename); 208 return exitcode; 209 } 210