blob: f59588451687c6ead4e30be767c964df006f1662 [file] [log] [blame]
Koushik K. Dutta6060e5c2010-02-11 22:27:06 -08001#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. Duttae9234872010-02-12 00:43:24 -080015#include <sys/wait.h>
16#include <sys/limits.h>
17#include <dirent.h>
Koushik K. Dutta49f56892010-02-25 14:51:05 -080018#include <sys/stat.h>
Koushik K. Duttae9234872010-02-12 00:43:24 -080019
Koushik K. Dutta33370db2010-02-25 11:39:07 -080020#include <signal.h>
21#include <sys/wait.h>
22
Koushik K. Dutta6060e5c2010-02-11 22:27:06 -080023#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. Duttaf68aaaf2010-03-07 13:39:21 -080033#include "commands.h"
34#include "amend/amend.h"
35
Koushik K. Duttaa85d7cc2010-03-12 17:00:58 -080036#include "mtdutils/dump_image.h"
37#include "../../external/yaffs2/yaffs2/utils/mkyaffs2image.h"
Koushik K. Dutta54305a82010-03-12 17:43:26 -080038#include "../../external/yaffs2/yaffs2/utils/unyaffs.h"
Koushik K. Duttaa85d7cc2010-03-12 17:00:58 -080039
Koushik K. Dutta6060e5c2010-02-11 22:27:06 -080040int signature_check_enabled = 1;
41int script_assert_enabled = 1;
Koushik K. Duttabcdd0032010-02-21 21:10:25 -080042static const char *SDCARD_PACKAGE_FILE = "SDCARD:update.zip";
Koushik K. Dutta6060e5c2010-02-11 22:27:06 -080043
44void
45toggle_signature_check()
46{
47 signature_check_enabled = !signature_check_enabled;
48 ui_print("Signature Check: %s\n", signature_check_enabled ? "Enabled" : "Disabled");
49}
50
51void toggle_script_asserts()
52{
53 script_assert_enabled = !script_assert_enabled;
Koushik K. Duttae9234872010-02-12 00:43:24 -080054 ui_print("Script Asserts: %s\n", script_assert_enabled ? "Enabled" : "Disabled");
55}
56
Koushik K. Duttaea46fe22010-03-08 02:58:04 -080057int install_zip(const char* packagefilepath)
Koushik K. Duttae9234872010-02-12 00:43:24 -080058{
Koushik K. Duttabcdd0032010-02-21 21:10:25 -080059 ui_print("\n-- Installing: %s\n", packagefilepath);
60 set_sdcard_update_bootloader_message();
61 int status = install_package(packagefilepath);
Koushik K. Dutta99fb6fe2010-03-03 00:42:58 -080062 ui_reset_progress();
Koushik K. Duttabcdd0032010-02-21 21:10:25 -080063 if (status != INSTALL_SUCCESS) {
64 ui_set_background(BACKGROUND_ICON_ERROR);
65 ui_print("Installation aborted.\n");
Koushik K. Duttaea46fe22010-03-08 02:58:04 -080066 return 1;
Koushik K. Dutta79ce82c2010-02-25 12:03:17 -080067 }
68 if (firmware_update_pending()) {
69 ui_print("\nReboot via menu to complete\ninstallation.\n");
Koushik K. Dutta001c5b52010-02-25 14:53:57 -080070 }
Koushik K. Dutta001c5b52010-02-25 14:53:57 -080071 ui_set_background(BACKGROUND_ICON_NONE);
Koushik K. Dutta99fb6fe2010-03-03 00:42:58 -080072 ui_print("\nInstall from sdcard complete.\n");
Koushik K. Duttaea46fe22010-03-08 02:58:04 -080073 return 0;
Koushik K. Duttabcdd0032010-02-21 21:10:25 -080074}
75
76char* INSTALL_MENU_ITEMS[] = { "apply sdcard:update.zip",
77 "choose zip from sdcard",
78 "toggle signature verification",
79 "toggle script asserts",
80 NULL };
81#define ITEM_APPLY_SDCARD 0
82#define ITEM_CHOOSE_ZIP 1
83#define ITEM_SIG_CHECK 2
84#define ITEM_ASSERTS 3
85
86void show_install_update_menu()
87{
88 static char* headers[] = { "Apply update from .zip file on SD card",
89 "",
90 NULL
91 };
92 for (;;)
93 {
94 int chosen_item = get_menu_selection(headers, INSTALL_MENU_ITEMS, 0);
95 switch (chosen_item)
96 {
97 case ITEM_ASSERTS:
98 toggle_script_asserts();
99 break;
100 case ITEM_SIG_CHECK:
101 toggle_signature_check();
102 break;
103 case ITEM_APPLY_SDCARD:
104 install_zip(SDCARD_PACKAGE_FILE);
105 break;
106 case ITEM_CHOOSE_ZIP:
107 show_choose_zip_menu();
108 break;
109 default:
110 return;
111 }
112
113 }
114}
115
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800116char** gather_files(const char* directory, const char* fileExtensionOrDirectory, int* numFiles)
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800117{
Koushik K. Duttae9234872010-02-12 00:43:24 -0800118 char path[PATH_MAX] = "";
119 DIR *dir;
120 struct dirent *de;
121 int total = 0;
122 int i;
123 char** files;
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800124 int pass;
125 *numFiles = 0;
126 int dirLen = strlen(directory);
Koushik K. Duttae9234872010-02-12 00:43:24 -0800127
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800128 dir = opendir(directory);
129 if (dir == NULL) {
130 ui_print("Couldn't open directory.\n");
131 return NULL;
132 }
133
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800134 int extension_length;
135 if (fileExtensionOrDirectory != NULL)
136 extension_length = strlen(fileExtensionOrDirectory);
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800137
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800138 int isCounting = 1;
139 i = 0;
140 for (pass = 0; pass < 2; pass++) {
141 while ((de=readdir(dir)) != NULL) {
142 // skip hidden files
143 if (de->d_name[0] == '.')
144 continue;
145
146 // NULL means that we are gathering directories, so skip this
147 if (fileExtensionOrDirectory != NULL)
148 {
149 // make sure that we can have the desired extension (prevent seg fault)
150 if (strlen(de->d_name) < extension_length)
151 continue;
152 // compare the extension
153 if (strcmp(de->d_name + strlen(de->d_name) - extension_length, fileExtensionOrDirectory) != 0)
154 continue;
155 }
156 else
157 {
158 struct stat info;
159 char* fullFileName = (char*)malloc(strlen(de->d_name) + dirLen + 1);
160 strcpy(fullFileName, directory);
161 strcat(fullFileName, de->d_name);
162 stat(fullFileName, &info);
163 free(fullFileName);
164 // make sure it is a directory
165 if (!(S_ISDIR(info.st_mode)))
166 continue;
167 }
168
169 if (pass == 0)
170 {
171 total++;
172 continue;
173 }
174
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800175 files[i] = (char*) malloc(dirLen + strlen(de->d_name) + 2);
176 strcpy(files[i], directory);
177 strcat(files[i], de->d_name);
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800178 if (fileExtensionOrDirectory == NULL)
179 strcat(files[i], "/");
180 i++;
181 }
182 if (pass == 1)
183 break;
184 if (total == 0)
185 break;
186 rewinddir(dir);
187 *numFiles = total;
188 files = (char**) malloc((total+1)*sizeof(char*));
189 files[total]=NULL;
190 }
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800191
192 if(closedir(dir) < 0) {
193 LOGE("Failed to close directory.");
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800194 }
195
196 if (total==0) {
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800197 return NULL;
198 }
199
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800200 return files;
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800201}
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800202
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800203void free_string_array(char** array)
204{
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800205 char* cursor = array[0];
206 int i = 0;
207 while (cursor != NULL)
208 {
209 free(cursor);
210 cursor = array[++i];
211 }
212 free(array);
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800213}
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800214
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800215// pass in NULL for fileExtensionOrDirectory and you will get a directory chooser
216char* choose_file_menu(const char* directory, const char* fileExtensionOrDirectory, const char* headers[])
217{
218 char path[PATH_MAX] = "";
219 DIR *dir;
220 struct dirent *de;
221 int numFiles = 0;
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800222 int numDirs = 0;
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800223 int i;
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800224
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800225 int dir_len = strlen(directory);
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800226
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800227 char** files = gather_files(directory, fileExtensionOrDirectory, &numFiles);
228 char** dirs;
229 if (fileExtensionOrDirectory != NULL)
230 dirs = gather_files(directory, NULL, &numDirs);
231 int total = numDirs + numFiles;
232 if (total == 0)
233 {
234 ui_print("No files found.\n");
235 return NULL;
236 }
237 char** list = (char**) malloc((total + 1) * sizeof(char*));
238 list[total] = NULL;
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800239
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800240
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800241 for (i = 0 ; i < numDirs; i++)
242 {
243 list[i] = strdup(dirs[i] + dir_len);
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800244 }
245
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800246 for (i = 0 ; i < numFiles; i++)
247 {
248 list[numDirs + i] = strdup(files[i] + dir_len);
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800249 }
250
Koushik K. Dutta981b0cd2010-02-22 08:53:34 -0800251 for (;;)
252 {
253 int chosen_item = get_menu_selection(headers, list, 0);
254 if (chosen_item == GO_BACK)
255 break;
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800256 if (chosen_item < numDirs)
257 {
258 char* subret = choose_file_menu(dirs[chosen_item], fileExtensionOrDirectory, headers);
259 if (subret != NULL)
260 return subret;
261 continue;
262 }
Koushik K. Dutta981b0cd2010-02-22 08:53:34 -0800263 static char ret[PATH_MAX];
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800264 strcpy(ret, files[chosen_item - numDirs]);
Koushik K. Dutta981b0cd2010-02-22 08:53:34 -0800265 return ret;
266 }
267 return NULL;
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800268}
269
270void show_choose_zip_menu()
271{
Koushik K. Duttae9234872010-02-12 00:43:24 -0800272 if (ensure_root_path_mounted("SDCARD:") != 0) {
273 LOGE ("Can't mount /sdcard\n");
274 return;
275 }
276
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800277 static char* headers[] = { "Choose a zip to apply",
278 "",
279 NULL
280 };
281
282 char* file = choose_file_menu("/sdcard/", ".zip", headers);
283 if (file == NULL)
284 return;
285 char sdcard_package_file[1024];
286 strcpy(sdcard_package_file, "SDCARD:");
287 strcat(sdcard_package_file, file + strlen("/sdcard/"));
288 install_zip(sdcard_package_file);
289}
290
Koushik K. Dutta33370db2010-02-25 11:39:07 -0800291// This was pulled from bionic: The default system command always looks
292// for shell in /system/bin/sh. This is bad.
293#define _PATH_BSHELL "/sbin/sh"
294#define system recovery_system
295extern char **environ;
296int
297system(const char *command)
298{
299 pid_t pid;
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800300 sig_t intsave, quitsave;
301 sigset_t mask, omask;
302 int pstat;
303 char *argp[] = {"sh", "-c", NULL, NULL};
Koushik K. Dutta33370db2010-02-25 11:39:07 -0800304
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800305 if (!command) /* just checking... */
306 return(1);
Koushik K. Dutta33370db2010-02-25 11:39:07 -0800307
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800308 argp[2] = (char *)command;
Koushik K. Dutta33370db2010-02-25 11:39:07 -0800309
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800310 sigemptyset(&mask);
311 sigaddset(&mask, SIGCHLD);
312 sigprocmask(SIG_BLOCK, &mask, &omask);
313 switch (pid = vfork()) {
314 case -1: /* error */
315 sigprocmask(SIG_SETMASK, &omask, NULL);
316 return(-1);
317 case 0: /* child */
318 sigprocmask(SIG_SETMASK, &omask, NULL);
319 execve(_PATH_BSHELL, argp, environ);
Koushik K. Dutta33370db2010-02-25 11:39:07 -0800320 _exit(127);
321 }
322
Koushik K. Dutta001c5b52010-02-25 14:53:57 -0800323 intsave = (sig_t) bsd_signal(SIGINT, SIG_IGN);
324 quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN);
325 pid = waitpid(pid, (int *)&pstat, 0);
326 sigprocmask(SIG_SETMASK, &omask, NULL);
327 (void)bsd_signal(SIGINT, intsave);
328 (void)bsd_signal(SIGQUIT, quitsave);
329 return (pid == -1 ? -1 : pstat);
Koushik K. Dutta33370db2010-02-25 11:39:07 -0800330}
331
Koushik K. Duttaa85d7cc2010-03-12 17:00:58 -0800332int print_and_error(char* message)
333{
334 ui_print(message);
335 return 1;
336}
337
Koushik K. Dutta54305a82010-03-12 17:43:26 -0800338// TODO : Separate file for Nandroid?
Koushik K. Duttaa9483082010-03-07 21:47:41 -0800339int do_nandroid_backup(char* backup_name)
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800340{
Koushik K. Dutta60d7ee02010-03-07 22:16:55 -0800341 if (ensure_root_path_mounted("SDCARD:") != 0) {
342 LOGE ("Can't mount /sdcard\n");
343 return 1;
344 }
Koushik K. Duttaa85d7cc2010-03-12 17:00:58 -0800345
346 struct timeval tp;
347 gettimeofday(&tp, NULL);
348
349 char backupdir[PATH_MAX];
350 char tmp[PATH_MAX];
351 if (NULL != backup_name)
352 sprintf(backupdir, "/sdcard/clockworkmod/backup/%s", backup_name);
353 else
354 sprintf(backupdir, "/sdcard/clockworkmod/backup/%d", tp.tv_sec);
355
356 sprintf(tmp, "mkdir -p %s", backupdir);
357 system(tmp);
358
359 int ret;
360 ui_print("Backing up boot...\n");
361 sprintf(tmp, "%s/%s", backupdir, "boot.img");
362 ret = dump_image("boot", tmp, NULL);
363 if (0 != ret)
364 return print_and_error("Error while dumping boot image!\n");
365
Koushik K. Dutta54305a82010-03-12 17:43:26 -0800366 // TODO: Wrap this up in a loop?
Koushik K. Duttaa85d7cc2010-03-12 17:00:58 -0800367 ui_print("Backing up system...\n");
368 sprintf(tmp, "%s/%s", backupdir, "system.img");
Koushik K. Dutta54305a82010-03-12 17:43:26 -0800369 if (ensure_root_path_mounted("SYSTEM:") != 0)
370 return print_and_error("Can't mount /system!\n");
Koushik K. Duttaa85d7cc2010-03-12 17:00:58 -0800371 ret = mkyaffs2image("/system", tmp, 0, NULL);
372 ensure_root_path_unmounted("SYSTEM:");
373 if (0 != ret)
374 return print_and_error("Error while making a yaffs2 image of system!\n");
375
376 ui_print("Backing up data...\n");
377 sprintf(tmp, "%s/%s", backupdir, "data.img");
Koushik K. Dutta54305a82010-03-12 17:43:26 -0800378 if (ensure_root_path_mounted("DATA:") != 0)
379 return print_and_error("Can't mount /data!\n");
Koushik K. Duttaa85d7cc2010-03-12 17:00:58 -0800380 ret = mkyaffs2image("/data", tmp, 0, NULL);
381 ensure_root_path_unmounted("DATA:");
382 if (0 != ret)
383 return print_and_error("Error while making a yaffs2 image of data!\n");
384
385 ui_print("Backing up cache...\n");
386 sprintf(tmp, "%s/%s", backupdir, "cache.img");
Koushik K. Dutta54305a82010-03-12 17:43:26 -0800387 if (ensure_root_path_mounted("CACHE:") != 0)
388 return print_and_error("Can't mount /cache!\n");
Koushik K. Duttaa85d7cc2010-03-12 17:00:58 -0800389 ret = mkyaffs2image("/cache", tmp, 0, NULL);
390 ensure_root_path_unmounted("CACHE:");
391 if (0 != ret)
392 return print_and_error("Error while making a yaffs2 image of cache!\n");
393
394 sprintf(tmp, "md5sum %s/*img > %s/nandroid.md5", backupdir, backupdir);
395 system(tmp);
396
397 return 0;
Koushik K. Duttaa9483082010-03-07 21:47:41 -0800398}
399
400int do_nandroid_restore(char* backup_path)
401{
Koushik K. Dutta60d7ee02010-03-07 22:16:55 -0800402 if (ensure_root_path_mounted("SDCARD:") != 0) {
403 LOGE ("Can't mount /sdcard\n");
404 return 1;
405 }
Koushik K. Dutta54305a82010-03-12 17:43:26 -0800406
407 char tmp[PATH_MAX];
Koushik K. Dutta60d7ee02010-03-07 22:16:55 -0800408
Koushik K. Dutta54305a82010-03-12 17:43:26 -0800409 ui_print("Checking MD5 sums...\n");
410 sprintf(tmp, "md5sum -c %s/nandroid.md5", backup_path);
411 if (0 != system(tmp))
412 return print_and_error("MD5 mismatch!\n");
413
Koushik K. Dutta928d6052010-03-12 17:47:59 -0800414 // TODO: put this in a loop?
Koushik K. Dutta54305a82010-03-12 17:43:26 -0800415 ui_print("Restoring system...\n");
416 if (0 != ensure_root_path_unmounted("SYSTEM:"))
417 return print_and_error("Can't unmount /system!\n");
418 if (0 != format_root_device("SYSTEM:"))
419 return print_and_error("Error while formatting /system!\n");
420 if (ensure_root_path_mounted("SYSTEM:") != 0)
421 return print_and_error("Can't mount /system!\n");
422 sprintf(tmp, "%s/system.img", backup_path);
423 if (0 != unyaffs(tmp, "/system", NULL))
424 return print_and_error("Error while restoring /system!\n");
425
426 ui_print("Restoring data...\n");
427 if (0 != ensure_root_path_unmounted("DATA:"))
428 return print_and_error("Can't unmount /data!\n");
429 if (0 != format_root_device("DATA:"))
430 return print_and_error("Error while formatting /data!\n");
431 if (ensure_root_path_mounted("DATA:") != 0)
432 return print_and_error("Can't mount /data!\n");
433 sprintf(tmp, "%s/data.img", backup_path);
434 if (0 != unyaffs(tmp, "/data", NULL))
435 return print_and_error("Error while restoring /data!\n");
436
437 ui_print("Restoring cache...\n");
438 if (0 != ensure_root_path_unmounted("CACHE:"))
439 return print_and_error("Can't unmount /cache!\n");
440 if (0 != format_root_device("CACHE:"))
441 return print_and_error("Error while formatting /cache!\n");
442 if (ensure_root_path_mounted("CACHE:") != 0)
443 return print_and_error("Can't mount /cache!\n");
444 sprintf(tmp, "%s/cache.img", backup_path);
445 if (0 != unyaffs(tmp, "/cache", NULL))
446 return print_and_error("Error while restoring /cache!\n");
447
448 return 0;
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800449}
450
451void show_nandroid_restore_menu()
452{
Koushik K. Dutta54305a82010-03-12 17:43:26 -0800453 if (ensure_root_path_mounted("SDCARD:") != 0) {
454 LOGE ("Can't mount /sdcard\n");
455 return 1;
456 }
457
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800458 static char* headers[] = { "Choose an image to restore",
459 "",
460 NULL
461 };
Koushik K. Duttae9234872010-02-12 00:43:24 -0800462
Koushik K. Dutta49f56892010-02-25 14:51:05 -0800463 char* file = choose_file_menu("/sdcard/clockworkmod/backup/", NULL, headers);
Koushik K. Duttabcdd0032010-02-21 21:10:25 -0800464 if (file == NULL)
465 return;
Koushik K. Duttaa9483082010-03-07 21:47:41 -0800466 do_nandroid_restore(file);
Koushik K. Dutta03173782010-02-26 14:14:23 -0800467}
468
469void do_mount_usb_storage()
470{
471 system("echo /dev/block/mmcblk0 > /sys/devices/platform/usb_mass_storage/lun0/file");
472 static char* headers[] = { "USB Mass Storage device",
473 "Leaving this menu unmount",
474 "your SD card from your PC.",
475 "",
476 NULL
477 };
478
479 static char* list[] = { "Unmount", NULL };
480
481 for (;;)
482 {
483 int chosen_item = get_menu_selection(headers, list, 0);
484 if (chosen_item == GO_BACK || chosen_item == 0)
485 break;
486 }
487
Koushik K. Duttae81cb752010-02-26 17:44:33 -0800488 system("echo '' > /sys/devices/platform/usb_mass_storage/lun0/file");
Koushik K. Dutta03173782010-02-26 14:14:23 -0800489 system("echo 0 > /sys/devices/platform/usb_mass_storage/lun0/enable");
Koushik K. Duttae81cb752010-02-26 17:44:33 -0800490}
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800491
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800492#define EXTENDEDCOMMAND_SCRIPT "/cache/recovery/extendedcommand"
493
494int extendedcommand_file_exists()
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800495{
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800496 struct stat file_info;
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800497 return 0 == stat(EXTENDEDCOMMAND_SCRIPT, &file_info);
498}
499
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800500int run_script_from_buffer(char* script_data, int script_len, char* filename)
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800501{
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800502 /* Parse the script. Note that the script and parse tree are never freed.
503 */
504 const AmCommandList *commands = parseAmendScript(script_data, script_len);
505 if (commands == NULL) {
506 printf("Syntax error in update script\n");
507 return 1;
508 } else {
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800509 printf("Parsed %.*s\n", script_len, filename);
Koushik K. Duttaf68aaaf2010-03-07 13:39:21 -0800510 }
511
512 /* Execute the script.
513 */
514 int ret = execCommandList((ExecContext *)1, commands);
515 if (ret != 0) {
516 int num = ret;
517 char *line, *next = script_data;
518 while (next != NULL && ret-- > 0) {
519 line = next;
520 next = memchr(line, '\n', script_data + script_len - line);
521 if (next != NULL) *next++ = '\0';
522 }
523 printf("Failure at line %d:\n%s\n", num, next ? line : "(not found)");
524 return 1;
525 }
526
527 return 0;
528}
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800529
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800530int run_script(char* filename, int delete_file)
531{
532 struct stat file_info;
533 if (0 != stat(filename, &file_info)) {
534 printf("Error executing stat on file: %s\n", filename);
535 return 1;
536 }
537
538 int script_len = file_info.st_size;
539 char* script_data = (char*)malloc(script_len);
540 FILE *file = fopen(filename, "rb");
541 fread(script_data, script_len, 1, file);
542 fclose(file);
543 if (delete_file)
544 remove(filename);
545
546 return run_script_from_buffer(script_data, script_len, filename);
547}
548
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800549int run_and_remove_extendedcommand()
550{
Koushik K. Dutta3a25cf52010-03-08 19:22:41 -0800551 int i = 0;
552 for (i = 20; i > 0; i--) {
553 ui_print("Waiting for SD Card to mount (%ds)\n", i);
554 if (ensure_root_path_mounted("SDCARD:") == 0) {
555 ui_print("SD Card mounted...\n");
556 break;
557 }
558 sleep(1);
559 }
560 if (i == 0) {
561 ui_print("Timed out waiting for SD card... continuing anyways.");
562 }
563
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800564 return run_script(EXTENDEDCOMMAND_SCRIPT, 1);
Koushik K. Dutta72a1db62010-03-07 14:10:26 -0800565}
566
567int amend_main(int argc, char** argv)
568{
569 if (argc != 2)
570 {
571 printf("Usage: amend <script>\n");
572 return 0;
573 }
574
575 RecoveryCommandContext ctx = { NULL };
576 if (register_update_commands(&ctx)) {
577 LOGE("Can't install update commands\n");
578 }
Koushik K. Dutta3836f722010-03-11 22:17:43 -0800579 return run_script(argv[1], 0);
Koushik K. Dutta5306db52010-03-08 14:09:35 -0800580}