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