| Koushik K. Dutta | 6060e5c | 2010-02-11 22:27:06 -0800 | [diff] [blame] | 1 | #include <ctype.h> | 
|  | 2 | #include <errno.h> | 
|  | 3 | #include <fcntl.h> | 
|  | 4 | #include <getopt.h> | 
|  | 5 | #include <limits.h> | 
|  | 6 | #include <linux/input.h> | 
|  | 7 | #include <stdio.h> | 
|  | 8 | #include <stdlib.h> | 
|  | 9 | #include <string.h> | 
|  | 10 | #include <sys/reboot.h> | 
|  | 11 | #include <sys/types.h> | 
|  | 12 | #include <time.h> | 
|  | 13 | #include <unistd.h> | 
|  | 14 |  | 
| Koushik K. Dutta | e923487 | 2010-02-12 00:43:24 -0800 | [diff] [blame] | 15 | #include <sys/wait.h> | 
|  | 16 | #include <sys/limits.h> | 
|  | 17 | #include <dirent.h> | 
| Koushik K. Dutta | 49f5689 | 2010-02-25 14:51:05 -0800 | [diff] [blame] | 18 | #include <sys/stat.h> | 
| Koushik K. Dutta | e923487 | 2010-02-12 00:43:24 -0800 | [diff] [blame] | 19 |  | 
| Koushik K. Dutta | 33370db | 2010-02-25 11:39:07 -0800 | [diff] [blame] | 20 | #include <signal.h> | 
|  | 21 | #include <sys/wait.h> | 
|  | 22 |  | 
| Koushik K. Dutta | 6060e5c | 2010-02-11 22:27:06 -0800 | [diff] [blame] | 23 | #include "bootloader.h" | 
|  | 24 | #include "common.h" | 
|  | 25 | #include "cutils/properties.h" | 
|  | 26 | #include "firmware.h" | 
|  | 27 | #include "install.h" | 
|  | 28 | #include "minui/minui.h" | 
|  | 29 | #include "minzip/DirUtil.h" | 
|  | 30 | #include "roots.h" | 
|  | 31 | #include "recovery_ui.h" | 
|  | 32 |  | 
| Koushik K. Dutta | f68aaaf | 2010-03-07 13:39:21 -0800 | [diff] [blame] | 33 | #include "commands.h" | 
|  | 34 | #include "amend/amend.h" | 
|  | 35 |  | 
| Koushik K. Dutta | 6060e5c | 2010-02-11 22:27:06 -0800 | [diff] [blame] | 36 | int signature_check_enabled = 1; | 
|  | 37 | int script_assert_enabled = 1; | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 38 | static const char *SDCARD_PACKAGE_FILE = "SDCARD:update.zip"; | 
| Koushik K. Dutta | 6060e5c | 2010-02-11 22:27:06 -0800 | [diff] [blame] | 39 |  | 
|  | 40 | void | 
|  | 41 | toggle_signature_check() | 
|  | 42 | { | 
|  | 43 | signature_check_enabled = !signature_check_enabled; | 
|  | 44 | ui_print("Signature Check: %s\n", signature_check_enabled ? "Enabled" : "Disabled"); | 
|  | 45 | } | 
|  | 46 |  | 
|  | 47 | void toggle_script_asserts() | 
|  | 48 | { | 
|  | 49 | script_assert_enabled = !script_assert_enabled; | 
| Koushik K. Dutta | e923487 | 2010-02-12 00:43:24 -0800 | [diff] [blame] | 50 | ui_print("Script Asserts: %s\n", script_assert_enabled ? "Enabled" : "Disabled"); | 
|  | 51 | } | 
|  | 52 |  | 
| Koushik K. Dutta | ea46fe2 | 2010-03-08 02:58:04 -0800 | [diff] [blame^] | 53 | int install_zip(const char* packagefilepath) | 
| Koushik K. Dutta | e923487 | 2010-02-12 00:43:24 -0800 | [diff] [blame] | 54 | { | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 55 | ui_print("\n-- Installing: %s\n", packagefilepath); | 
|  | 56 | set_sdcard_update_bootloader_message(); | 
|  | 57 | int status = install_package(packagefilepath); | 
| Koushik K. Dutta | 99fb6fe | 2010-03-03 00:42:58 -0800 | [diff] [blame] | 58 | ui_reset_progress(); | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 59 | if (status != INSTALL_SUCCESS) { | 
|  | 60 | ui_set_background(BACKGROUND_ICON_ERROR); | 
|  | 61 | ui_print("Installation aborted.\n"); | 
| Koushik K. Dutta | ea46fe2 | 2010-03-08 02:58:04 -0800 | [diff] [blame^] | 62 | return 1; | 
| Koushik K. Dutta | 79ce82c | 2010-02-25 12:03:17 -0800 | [diff] [blame] | 63 | } | 
|  | 64 | if (firmware_update_pending()) { | 
|  | 65 | ui_print("\nReboot via menu to complete\ninstallation.\n"); | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 66 | } | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 67 | ui_set_background(BACKGROUND_ICON_NONE); | 
| Koushik K. Dutta | 99fb6fe | 2010-03-03 00:42:58 -0800 | [diff] [blame] | 68 | ui_print("\nInstall from sdcard complete.\n"); | 
| Koushik K. Dutta | ea46fe2 | 2010-03-08 02:58:04 -0800 | [diff] [blame^] | 69 | return 0; | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 70 | } | 
|  | 71 |  | 
|  | 72 | char* INSTALL_MENU_ITEMS[] = {  "apply sdcard:update.zip", | 
|  | 73 | "choose zip from sdcard", | 
|  | 74 | "toggle signature verification", | 
|  | 75 | "toggle script asserts", | 
|  | 76 | NULL }; | 
|  | 77 | #define ITEM_APPLY_SDCARD     0 | 
|  | 78 | #define ITEM_CHOOSE_ZIP       1 | 
|  | 79 | #define ITEM_SIG_CHECK        2 | 
|  | 80 | #define ITEM_ASSERTS          3 | 
|  | 81 |  | 
|  | 82 | void show_install_update_menu() | 
|  | 83 | { | 
|  | 84 | static char* headers[] = {  "Apply update from .zip file on SD card", | 
|  | 85 | "", | 
|  | 86 | NULL | 
|  | 87 | }; | 
|  | 88 | for (;;) | 
|  | 89 | { | 
|  | 90 | int chosen_item = get_menu_selection(headers, INSTALL_MENU_ITEMS, 0); | 
|  | 91 | switch (chosen_item) | 
|  | 92 | { | 
|  | 93 | case ITEM_ASSERTS: | 
|  | 94 | toggle_script_asserts(); | 
|  | 95 | break; | 
|  | 96 | case ITEM_SIG_CHECK: | 
|  | 97 | toggle_signature_check(); | 
|  | 98 | break; | 
|  | 99 | case ITEM_APPLY_SDCARD: | 
|  | 100 | install_zip(SDCARD_PACKAGE_FILE); | 
|  | 101 | break; | 
|  | 102 | case ITEM_CHOOSE_ZIP: | 
|  | 103 | show_choose_zip_menu(); | 
|  | 104 | break; | 
|  | 105 | default: | 
|  | 106 | return; | 
|  | 107 | } | 
|  | 108 |  | 
|  | 109 | } | 
|  | 110 | } | 
|  | 111 |  | 
| Koushik K. Dutta | 49f5689 | 2010-02-25 14:51:05 -0800 | [diff] [blame] | 112 | char** gather_files(const char* directory, const char* fileExtensionOrDirectory, int* numFiles) | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 113 | { | 
| Koushik K. Dutta | e923487 | 2010-02-12 00:43:24 -0800 | [diff] [blame] | 114 | char path[PATH_MAX] = ""; | 
|  | 115 | DIR *dir; | 
|  | 116 | struct dirent *de; | 
|  | 117 | int total = 0; | 
|  | 118 | int i; | 
|  | 119 | char** files; | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 120 | int pass; | 
|  | 121 | *numFiles = 0; | 
|  | 122 | int dirLen = strlen(directory); | 
| Koushik K. Dutta | e923487 | 2010-02-12 00:43:24 -0800 | [diff] [blame] | 123 |  | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 124 | dir = opendir(directory); | 
|  | 125 | if (dir == NULL) { | 
|  | 126 | ui_print("Couldn't open directory.\n"); | 
|  | 127 | return NULL; | 
|  | 128 | } | 
|  | 129 |  | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 130 | int extension_length; | 
|  | 131 | if (fileExtensionOrDirectory != NULL) | 
|  | 132 | extension_length = strlen(fileExtensionOrDirectory); | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 133 |  | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 134 | int isCounting = 1; | 
|  | 135 | i = 0; | 
|  | 136 | for (pass = 0; pass < 2; pass++) { | 
|  | 137 | while ((de=readdir(dir)) != NULL) { | 
|  | 138 | // skip hidden files | 
|  | 139 | if (de->d_name[0] == '.') | 
|  | 140 | continue; | 
|  | 141 |  | 
|  | 142 | // NULL means that we are gathering directories, so skip this | 
|  | 143 | if (fileExtensionOrDirectory != NULL) | 
|  | 144 | { | 
|  | 145 | // make sure that we can have the desired extension (prevent seg fault) | 
|  | 146 | if (strlen(de->d_name) < extension_length) | 
|  | 147 | continue; | 
|  | 148 | // compare the extension | 
|  | 149 | if (strcmp(de->d_name + strlen(de->d_name) - extension_length, fileExtensionOrDirectory) != 0) | 
|  | 150 | continue; | 
|  | 151 | } | 
|  | 152 | else | 
|  | 153 | { | 
|  | 154 | struct stat info; | 
|  | 155 | char* fullFileName = (char*)malloc(strlen(de->d_name) + dirLen + 1); | 
|  | 156 | strcpy(fullFileName, directory); | 
|  | 157 | strcat(fullFileName, de->d_name); | 
|  | 158 | stat(fullFileName, &info); | 
|  | 159 | free(fullFileName); | 
|  | 160 | // make sure it is a directory | 
|  | 161 | if (!(S_ISDIR(info.st_mode))) | 
|  | 162 | continue; | 
|  | 163 | } | 
|  | 164 |  | 
|  | 165 | if (pass == 0) | 
|  | 166 | { | 
|  | 167 | total++; | 
|  | 168 | continue; | 
|  | 169 | } | 
|  | 170 |  | 
| Koushik K. Dutta | 49f5689 | 2010-02-25 14:51:05 -0800 | [diff] [blame] | 171 | files[i] = (char*) malloc(dirLen + strlen(de->d_name) + 2); | 
|  | 172 | strcpy(files[i], directory); | 
|  | 173 | strcat(files[i], de->d_name); | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 174 | if (fileExtensionOrDirectory == NULL) | 
|  | 175 | strcat(files[i], "/"); | 
|  | 176 | i++; | 
|  | 177 | } | 
|  | 178 | if (pass == 1) | 
|  | 179 | break; | 
|  | 180 | if (total == 0) | 
|  | 181 | break; | 
|  | 182 | rewinddir(dir); | 
|  | 183 | *numFiles = total; | 
|  | 184 | files = (char**) malloc((total+1)*sizeof(char*)); | 
|  | 185 | files[total]=NULL; | 
|  | 186 | } | 
| Koushik K. Dutta | 49f5689 | 2010-02-25 14:51:05 -0800 | [diff] [blame] | 187 |  | 
|  | 188 | if(closedir(dir) < 0) { | 
|  | 189 | LOGE("Failed to close directory."); | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 190 | } | 
|  | 191 |  | 
|  | 192 | if (total==0) { | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 193 | return NULL; | 
|  | 194 | } | 
|  | 195 |  | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 196 | return files; | 
| Koushik K. Dutta | 49f5689 | 2010-02-25 14:51:05 -0800 | [diff] [blame] | 197 | } | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 198 |  | 
| Koushik K. Dutta | 49f5689 | 2010-02-25 14:51:05 -0800 | [diff] [blame] | 199 | void free_string_array(char** array) | 
|  | 200 | { | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 201 | char* cursor = array[0]; | 
|  | 202 | int i = 0; | 
|  | 203 | while (cursor != NULL) | 
|  | 204 | { | 
|  | 205 | free(cursor); | 
|  | 206 | cursor = array[++i]; | 
|  | 207 | } | 
|  | 208 | free(array); | 
| Koushik K. Dutta | 49f5689 | 2010-02-25 14:51:05 -0800 | [diff] [blame] | 209 | } | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 210 |  | 
| Koushik K. Dutta | 49f5689 | 2010-02-25 14:51:05 -0800 | [diff] [blame] | 211 | // pass in NULL for fileExtensionOrDirectory and you will get a directory chooser | 
|  | 212 | char* choose_file_menu(const char* directory, const char* fileExtensionOrDirectory, const char* headers[]) | 
|  | 213 | { | 
|  | 214 | char path[PATH_MAX] = ""; | 
|  | 215 | DIR *dir; | 
|  | 216 | struct dirent *de; | 
|  | 217 | int numFiles = 0; | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 218 | int numDirs = 0; | 
| Koushik K. Dutta | 49f5689 | 2010-02-25 14:51:05 -0800 | [diff] [blame] | 219 | int i; | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 220 |  | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 221 | int dir_len = strlen(directory); | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 222 |  | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 223 | char** files = gather_files(directory, fileExtensionOrDirectory, &numFiles); | 
|  | 224 | char** dirs; | 
|  | 225 | if (fileExtensionOrDirectory != NULL) | 
|  | 226 | dirs = gather_files(directory, NULL, &numDirs); | 
|  | 227 | int total = numDirs + numFiles; | 
|  | 228 | if (total == 0) | 
|  | 229 | { | 
|  | 230 | ui_print("No files found.\n"); | 
|  | 231 | return NULL; | 
|  | 232 | } | 
|  | 233 | char** list = (char**) malloc((total + 1) * sizeof(char*)); | 
|  | 234 | list[total] = NULL; | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 235 |  | 
| Koushik K. Dutta | 49f5689 | 2010-02-25 14:51:05 -0800 | [diff] [blame] | 236 |  | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 237 | for (i = 0 ; i < numDirs; i++) | 
|  | 238 | { | 
|  | 239 | list[i] = strdup(dirs[i] + dir_len); | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 240 | } | 
|  | 241 |  | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 242 | for (i = 0 ; i < numFiles; i++) | 
|  | 243 | { | 
|  | 244 | list[numDirs + i] = strdup(files[i] + dir_len); | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 245 | } | 
|  | 246 |  | 
| Koushik K. Dutta | 981b0cd | 2010-02-22 08:53:34 -0800 | [diff] [blame] | 247 | for (;;) | 
|  | 248 | { | 
|  | 249 | int chosen_item = get_menu_selection(headers, list, 0); | 
|  | 250 | if (chosen_item == GO_BACK) | 
|  | 251 | break; | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 252 | if (chosen_item < numDirs) | 
|  | 253 | { | 
|  | 254 | char* subret = choose_file_menu(dirs[chosen_item], fileExtensionOrDirectory, headers); | 
|  | 255 | if (subret != NULL) | 
|  | 256 | return subret; | 
|  | 257 | continue; | 
|  | 258 | } | 
| Koushik K. Dutta | 981b0cd | 2010-02-22 08:53:34 -0800 | [diff] [blame] | 259 | static char ret[PATH_MAX]; | 
| Koushik K. Dutta | 49f5689 | 2010-02-25 14:51:05 -0800 | [diff] [blame] | 260 | strcpy(ret, files[chosen_item - numDirs]); | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 261 | ui_print("File chosen: %s\n", ret); | 
| Koushik K. Dutta | 981b0cd | 2010-02-22 08:53:34 -0800 | [diff] [blame] | 262 | return ret; | 
|  | 263 | } | 
|  | 264 | return NULL; | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 265 | } | 
|  | 266 |  | 
|  | 267 | void show_choose_zip_menu() | 
|  | 268 | { | 
| Koushik K. Dutta | e923487 | 2010-02-12 00:43:24 -0800 | [diff] [blame] | 269 | if (ensure_root_path_mounted("SDCARD:") != 0) { | 
|  | 270 | LOGE ("Can't mount /sdcard\n"); | 
|  | 271 | return; | 
|  | 272 | } | 
|  | 273 |  | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 274 | static char* headers[] = {  "Choose a zip to apply", | 
|  | 275 | "", | 
|  | 276 | NULL | 
|  | 277 | }; | 
|  | 278 |  | 
|  | 279 | char* file = choose_file_menu("/sdcard/", ".zip", headers); | 
|  | 280 | if (file == NULL) | 
|  | 281 | return; | 
|  | 282 | char sdcard_package_file[1024]; | 
|  | 283 | strcpy(sdcard_package_file, "SDCARD:"); | 
|  | 284 | strcat(sdcard_package_file,  file + strlen("/sdcard/")); | 
|  | 285 | install_zip(sdcard_package_file); | 
|  | 286 | } | 
|  | 287 |  | 
| Koushik K. Dutta | 33370db | 2010-02-25 11:39:07 -0800 | [diff] [blame] | 288 | // This was pulled from bionic: The default system command always looks | 
|  | 289 | // for shell in /system/bin/sh. This is bad. | 
|  | 290 | #define _PATH_BSHELL "/sbin/sh" | 
|  | 291 | #define system recovery_system | 
|  | 292 | extern char **environ; | 
|  | 293 | int | 
|  | 294 | system(const char *command) | 
|  | 295 | { | 
|  | 296 | pid_t pid; | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 297 | sig_t intsave, quitsave; | 
|  | 298 | sigset_t mask, omask; | 
|  | 299 | int pstat; | 
|  | 300 | char *argp[] = {"sh", "-c", NULL, NULL}; | 
| Koushik K. Dutta | 33370db | 2010-02-25 11:39:07 -0800 | [diff] [blame] | 301 |  | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 302 | if (!command)        /* just checking... */ | 
|  | 303 | return(1); | 
| Koushik K. Dutta | 33370db | 2010-02-25 11:39:07 -0800 | [diff] [blame] | 304 |  | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 305 | argp[2] = (char *)command; | 
| Koushik K. Dutta | 33370db | 2010-02-25 11:39:07 -0800 | [diff] [blame] | 306 |  | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 307 | sigemptyset(&mask); | 
|  | 308 | sigaddset(&mask, SIGCHLD); | 
|  | 309 | sigprocmask(SIG_BLOCK, &mask, &omask); | 
|  | 310 | switch (pid = vfork()) { | 
|  | 311 | case -1:            /* error */ | 
|  | 312 | sigprocmask(SIG_SETMASK, &omask, NULL); | 
|  | 313 | return(-1); | 
|  | 314 | case 0:                /* child */ | 
|  | 315 | sigprocmask(SIG_SETMASK, &omask, NULL); | 
|  | 316 | execve(_PATH_BSHELL, argp, environ); | 
| Koushik K. Dutta | 33370db | 2010-02-25 11:39:07 -0800 | [diff] [blame] | 317 | _exit(127); | 
|  | 318 | } | 
|  | 319 |  | 
| Koushik K. Dutta | 001c5b5 | 2010-02-25 14:53:57 -0800 | [diff] [blame] | 320 | intsave = (sig_t)  bsd_signal(SIGINT, SIG_IGN); | 
|  | 321 | quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN); | 
|  | 322 | pid = waitpid(pid, (int *)&pstat, 0); | 
|  | 323 | sigprocmask(SIG_SETMASK, &omask, NULL); | 
|  | 324 | (void)bsd_signal(SIGINT, intsave); | 
|  | 325 | (void)bsd_signal(SIGQUIT, quitsave); | 
|  | 326 | return (pid == -1 ? -1 : pstat); | 
| Koushik K. Dutta | 33370db | 2010-02-25 11:39:07 -0800 | [diff] [blame] | 327 | } | 
|  | 328 |  | 
| Koushik K. Dutta | a948308 | 2010-03-07 21:47:41 -0800 | [diff] [blame] | 329 | int do_nandroid_backup(char* backup_name) | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 330 | { | 
| Koushik K. Dutta | 60d7ee0 | 2010-03-07 22:16:55 -0800 | [diff] [blame] | 331 | if (ensure_root_path_mounted("SDCARD:") != 0) { | 
|  | 332 | LOGE ("Can't mount /sdcard\n"); | 
|  | 333 | return 1; | 
|  | 334 | } | 
|  | 335 |  | 
| Koushik K. Dutta | a948308 | 2010-03-07 21:47:41 -0800 | [diff] [blame] | 336 | char cmd[PATH_MAX]; | 
|  | 337 | if (NULL == backup_name) | 
|  | 338 | backup_name = ""; | 
|  | 339 | sprintf(cmd, "/sbin/nandroid-mobile.sh backup /sdcard/clockworkmod/backup/ %s", backup_name); | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 340 | ui_print("Performing backup...\n"); | 
| Koushik K. Dutta | a948308 | 2010-03-07 21:47:41 -0800 | [diff] [blame] | 341 | int ret = system(cmd); | 
| Koushik K. Dutta | 33370db | 2010-02-25 11:39:07 -0800 | [diff] [blame] | 342 | if (ret != 0) | 
| Koushik K. Dutta | 225c6b4 | 2010-02-21 22:02:24 -0800 | [diff] [blame] | 343 | { | 
| Koushik K. Dutta | 33370db | 2010-02-25 11:39:07 -0800 | [diff] [blame] | 344 | ui_print("Error while backing up! Error code: %d\n", ret); | 
| Koushik K. Dutta | a948308 | 2010-03-07 21:47:41 -0800 | [diff] [blame] | 345 | return ret; | 
| Koushik K. Dutta | 225c6b4 | 2010-02-21 22:02:24 -0800 | [diff] [blame] | 346 | } | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 347 | ui_print("Backup complete.\n"); | 
| Koushik K. Dutta | a948308 | 2010-03-07 21:47:41 -0800 | [diff] [blame] | 348 | return ret; | 
|  | 349 | } | 
|  | 350 |  | 
|  | 351 | int do_nandroid_restore(char* backup_path) | 
|  | 352 | { | 
| Koushik K. Dutta | 60d7ee0 | 2010-03-07 22:16:55 -0800 | [diff] [blame] | 353 | if (ensure_root_path_mounted("SDCARD:") != 0) { | 
|  | 354 | LOGE ("Can't mount /sdcard\n"); | 
|  | 355 | return 1; | 
|  | 356 | } | 
|  | 357 |  | 
| Koushik K. Dutta | a948308 | 2010-03-07 21:47:41 -0800 | [diff] [blame] | 358 | char* command[PATH_MAX]; | 
|  | 359 | sprintf(command, "nandroid-mobile.sh restore %s", backup_path); | 
|  | 360 | ui_print("Performing restore...\n"); | 
|  | 361 | int ret = system(command); | 
|  | 362 | if (ret != 0) | 
|  | 363 | { | 
|  | 364 | ui_print("Error while restoring!\n"); | 
|  | 365 | return ret; | 
|  | 366 | } | 
|  | 367 | ui_print("Restore complete.\n"); | 
|  | 368 | return ret; | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 369 | } | 
|  | 370 |  | 
|  | 371 | void show_nandroid_restore_menu() | 
|  | 372 | { | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 373 | static char* headers[] = {  "Choose an image to restore", | 
|  | 374 | "", | 
|  | 375 | NULL | 
|  | 376 | }; | 
| Koushik K. Dutta | e923487 | 2010-02-12 00:43:24 -0800 | [diff] [blame] | 377 |  | 
| Koushik K. Dutta | 49f5689 | 2010-02-25 14:51:05 -0800 | [diff] [blame] | 378 | char* file = choose_file_menu("/sdcard/clockworkmod/backup/", NULL, headers); | 
| Koushik K. Dutta | bcdd003 | 2010-02-21 21:10:25 -0800 | [diff] [blame] | 379 | if (file == NULL) | 
|  | 380 | return; | 
| Koushik K. Dutta | a948308 | 2010-03-07 21:47:41 -0800 | [diff] [blame] | 381 | do_nandroid_restore(file); | 
| Koushik K. Dutta | 0317378 | 2010-02-26 14:14:23 -0800 | [diff] [blame] | 382 | } | 
|  | 383 |  | 
|  | 384 | void do_mount_usb_storage() | 
|  | 385 | { | 
|  | 386 | system("echo /dev/block/mmcblk0 > /sys/devices/platform/usb_mass_storage/lun0/file"); | 
|  | 387 | static char* headers[] = {  "USB Mass Storage device", | 
|  | 388 | "Leaving this menu unmount", | 
|  | 389 | "your SD card from your PC.", | 
|  | 390 | "", | 
|  | 391 | NULL | 
|  | 392 | }; | 
|  | 393 |  | 
|  | 394 | static char* list[] = { "Unmount", NULL }; | 
|  | 395 |  | 
|  | 396 | for (;;) | 
|  | 397 | { | 
|  | 398 | int chosen_item = get_menu_selection(headers, list, 0); | 
|  | 399 | if (chosen_item == GO_BACK || chosen_item == 0) | 
|  | 400 | break; | 
|  | 401 | } | 
|  | 402 |  | 
| Koushik K. Dutta | e81cb75 | 2010-02-26 17:44:33 -0800 | [diff] [blame] | 403 | system("echo '' > /sys/devices/platform/usb_mass_storage/lun0/file"); | 
| Koushik K. Dutta | 0317378 | 2010-02-26 14:14:23 -0800 | [diff] [blame] | 404 | system("echo 0 > /sys/devices/platform/usb_mass_storage/lun0/enable"); | 
| Koushik K. Dutta | e81cb75 | 2010-02-26 17:44:33 -0800 | [diff] [blame] | 405 | } | 
| Koushik K. Dutta | f68aaaf | 2010-03-07 13:39:21 -0800 | [diff] [blame] | 406 |  | 
| Koushik K. Dutta | 72a1db6 | 2010-03-07 14:10:26 -0800 | [diff] [blame] | 407 | #define EXTENDEDCOMMAND_SCRIPT "/cache/recovery/extendedcommand" | 
|  | 408 |  | 
|  | 409 | int extendedcommand_file_exists() | 
| Koushik K. Dutta | f68aaaf | 2010-03-07 13:39:21 -0800 | [diff] [blame] | 410 | { | 
| Koushik K. Dutta | f68aaaf | 2010-03-07 13:39:21 -0800 | [diff] [blame] | 411 | struct stat file_info; | 
| Koushik K. Dutta | 72a1db6 | 2010-03-07 14:10:26 -0800 | [diff] [blame] | 412 | return 0 == stat(EXTENDEDCOMMAND_SCRIPT, &file_info); | 
|  | 413 | } | 
|  | 414 |  | 
|  | 415 | int run_script(char* filename) | 
|  | 416 | { | 
|  | 417 | struct stat file_info; | 
|  | 418 | if (0 != stat(filename, &file_info)) { | 
|  | 419 | printf("Error executing stat on file: %s\n", filename); | 
| Koushik K. Dutta | f68aaaf | 2010-03-07 13:39:21 -0800 | [diff] [blame] | 420 | return 1; | 
|  | 421 | } | 
|  | 422 |  | 
|  | 423 | int script_len = file_info.st_size; | 
|  | 424 | char* script_data = (char*)malloc(script_len); | 
| Koushik K. Dutta | 72a1db6 | 2010-03-07 14:10:26 -0800 | [diff] [blame] | 425 | FILE *file = fopen(filename, "rb"); | 
| Koushik K. Dutta | f68aaaf | 2010-03-07 13:39:21 -0800 | [diff] [blame] | 426 | fread(script_data, script_len, 1, file); | 
|  | 427 | fclose(file); | 
|  | 428 |  | 
|  | 429 | /* Parse the script.  Note that the script and parse tree are never freed. | 
|  | 430 | */ | 
|  | 431 | const AmCommandList *commands = parseAmendScript(script_data, script_len); | 
|  | 432 | if (commands == NULL) { | 
|  | 433 | printf("Syntax error in update script\n"); | 
|  | 434 | return 1; | 
|  | 435 | } else { | 
| Koushik K. Dutta | 72a1db6 | 2010-03-07 14:10:26 -0800 | [diff] [blame] | 436 | printf("Parsed %.*s\n", script_len, filename); | 
| Koushik K. Dutta | f68aaaf | 2010-03-07 13:39:21 -0800 | [diff] [blame] | 437 | } | 
|  | 438 |  | 
|  | 439 | /* Execute the script. | 
|  | 440 | */ | 
|  | 441 | int ret = execCommandList((ExecContext *)1, commands); | 
|  | 442 | if (ret != 0) { | 
|  | 443 | int num = ret; | 
|  | 444 | char *line, *next = script_data; | 
|  | 445 | while (next != NULL && ret-- > 0) { | 
|  | 446 | line = next; | 
|  | 447 | next = memchr(line, '\n', script_data + script_len - line); | 
|  | 448 | if (next != NULL) *next++ = '\0'; | 
|  | 449 | } | 
|  | 450 | printf("Failure at line %d:\n%s\n", num, next ? line : "(not found)"); | 
|  | 451 | return 1; | 
|  | 452 | } | 
|  | 453 |  | 
|  | 454 | return 0; | 
|  | 455 | } | 
| Koushik K. Dutta | 72a1db6 | 2010-03-07 14:10:26 -0800 | [diff] [blame] | 456 |  | 
|  | 457 | int run_and_remove_extendedcommand() | 
|  | 458 | { | 
|  | 459 | int ret = run_script(EXTENDEDCOMMAND_SCRIPT); | 
|  | 460 | remove(EXTENDEDCOMMAND_SCRIPT); | 
|  | 461 | return ret; | 
|  | 462 | } | 
|  | 463 |  | 
|  | 464 | int amend_main(int argc, char** argv) | 
|  | 465 | { | 
|  | 466 | if (argc != 2) | 
|  | 467 | { | 
|  | 468 | printf("Usage: amend <script>\n"); | 
|  | 469 | return 0; | 
|  | 470 | } | 
|  | 471 |  | 
|  | 472 | RecoveryCommandContext ctx = { NULL }; | 
|  | 473 | if (register_update_commands(&ctx)) { | 
|  | 474 | LOGE("Can't install update commands\n"); | 
|  | 475 | } | 
| Koushik K. Dutta | a948308 | 2010-03-07 21:47:41 -0800 | [diff] [blame] | 476 | return run_script(argv[1]); | 
|  | 477 | } |