chris41g

i9003 /extendedcommands.c

Jul 5th, 2011
370
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 35.76 KB | None | 0 0
  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 <reboot/reboot.h>
  12. #include <sys/types.h>
  13. #include <time.h>
  14. #include <unistd.h>
  15.  
  16. #include <sys/wait.h>
  17. #include <sys/limits.h>
  18. #include <dirent.h>
  19. #include <sys/stat.h>
  20.  
  21. #include <signal.h>
  22. #include <sys/wait.h>
  23.  
  24. #include "bootloader.h"
  25. #include "common.h"
  26. #include "cutils/properties.h"
  27. #include "firmware.h"
  28. #include "install.h"
  29. #include "minui/minui.h"
  30. #include "minzip/DirUtil.h"
  31. #include "roots.h"
  32. #include "recovery_ui.h"
  33.  
  34. #include "../../external/yaffs2/yaffs2/utils/mkyaffs2image.h"
  35. #include "../../external/yaffs2/yaffs2/utils/unyaffs.h"
  36.  
  37. #include "extendedcommands.h"
  38. #include "nandroid.h"
  39. #include "mounts.h"
  40. #include "flashutils/flashutils.h"
  41. #include "edify/expr.h"
  42. #include <libgen.h>
  43.  
  44.  
  45. int signature_check_enabled = 1;
  46. int script_assert_enabled = 1;
  47. static const char *SDCARD_UPDATE_FILE = "/sdcard/update.zip";
  48.  
  49. void
  50. toggle_signature_check()
  51. {
  52.     signature_check_enabled = !signature_check_enabled;
  53.     ui_print("Signature Check: %s\n", signature_check_enabled ? "Enabled" : "Disabled");
  54. }
  55.  
  56. void toggle_script_asserts()
  57. {
  58.     script_assert_enabled = !script_assert_enabled;
  59.     ui_print("Script Asserts: %s\n", script_assert_enabled ? "Enabled" : "Disabled");
  60. }
  61.  
  62. int install_zip(const char* packagefilepath)
  63. {
  64.     ui_print("\n-- Installing: %s\n", packagefilepath);
  65.     if (device_flash_type() == MTD) {
  66.         set_sdcard_update_bootloader_message();
  67.     }
  68.     int status = install_package(packagefilepath);
  69.     ui_reset_progress();
  70.     if (status != INSTALL_SUCCESS) {
  71.         ui_set_background(BACKGROUND_ICON_ERROR);
  72.         ui_print("Installation aborted.\n");
  73.         return 1;
  74.     }
  75.     ui_set_background(BACKGROUND_ICON_NONE);
  76.     ui_print("\nInstall from sdcard complete.\n");
  77.     return 0;
  78. }
  79.  
  80. char* INSTALL_MENU_ITEMS[] = {  "apply /sdcard/update.zip",
  81.                                 "choose zip from sdcard",
  82.                                 "toggle signature verification",
  83.                                 "toggle script asserts",
  84.                                 NULL };
  85. #define ITEM_APPLY_SDCARD     0
  86. #define ITEM_CHOOSE_ZIP       1
  87. #define ITEM_SIG_CHECK        2
  88. #define ITEM_ASSERTS          3
  89.  
  90. void show_install_update_menu()
  91. {
  92.     static char* headers[] = {  "Apply update from .zip file on SD card",
  93.                                 "",
  94.                                 NULL
  95.     };
  96.     for (;;)
  97.     {
  98.         int chosen_item = get_menu_selection(headers, INSTALL_MENU_ITEMS, 0, 0);
  99.         switch (chosen_item)
  100.         {
  101.             case ITEM_ASSERTS:
  102.                 toggle_script_asserts();
  103.                 break;
  104.             case ITEM_SIG_CHECK:
  105.                 toggle_signature_check();
  106.                 break;
  107.             case ITEM_APPLY_SDCARD:
  108.             {
  109.                 if (confirm_selection("Confirm install?", "Yes - Install /sdcard/update.zip"))
  110.                     install_zip(SDCARD_UPDATE_FILE);
  111.                 break;
  112.             }
  113.             case ITEM_CHOOSE_ZIP:
  114.                 show_choose_zip_menu();
  115.                 break;
  116.             default:
  117.                 return;
  118.         }
  119.  
  120.     }
  121. }
  122.  
  123. void free_string_array(char** array)
  124. {
  125.     if (array == NULL)
  126.         return;
  127.     char* cursor = array[0];
  128.     int i = 0;
  129.     while (cursor != NULL)
  130.     {
  131.         free(cursor);
  132.         cursor = array[++i];
  133.     }
  134.     free(array);
  135. }
  136.  
  137. char** gather_files(const char* directory, const char* fileExtensionOrDirectory, int* numFiles)
  138. {
  139.     char path[PATH_MAX] = "";
  140.     DIR *dir;
  141.     struct dirent *de;
  142.     int total = 0;
  143.     int i;
  144.     char** files = NULL;
  145.     int pass;
  146.     *numFiles = 0;
  147.     int dirLen = strlen(directory);
  148.  
  149.     dir = opendir(directory);
  150.     if (dir == NULL) {
  151.         ui_print("Couldn't open directory.\n");
  152.         return NULL;
  153.     }
  154.  
  155.     int extension_length = 0;
  156.     if (fileExtensionOrDirectory != NULL)
  157.         extension_length = strlen(fileExtensionOrDirectory);
  158.  
  159.     int isCounting = 1;
  160.     i = 0;
  161.     for (pass = 0; pass < 2; pass++) {
  162.         while ((de=readdir(dir)) != NULL) {
  163.             // skip hidden files
  164.             if (de->d_name[0] == '.')
  165.                 continue;
  166.  
  167.             // NULL means that we are gathering directories, so skip this
  168.             if (fileExtensionOrDirectory != NULL)
  169.             {
  170.                 // make sure that we can have the desired extension (prevent seg fault)
  171.                 if (strlen(de->d_name) < extension_length)
  172.                     continue;
  173.                 // compare the extension
  174.                 if (strcmp(de->d_name + strlen(de->d_name) - extension_length, fileExtensionOrDirectory) != 0)
  175.                     continue;
  176.             }
  177.             else
  178.             {
  179.                 struct stat info;
  180.                 char fullFileName[PATH_MAX];
  181.                 strcpy(fullFileName, directory);
  182.                 strcat(fullFileName, de->d_name);
  183.                 stat(fullFileName, &info);
  184.                 // make sure it is a directory
  185.                 if (!(S_ISDIR(info.st_mode)))
  186.                     continue;
  187.             }
  188.  
  189.             if (pass == 0)
  190.             {
  191.                 total++;
  192.                 continue;
  193.             }
  194.  
  195.             files[i] = (char*) malloc(dirLen + strlen(de->d_name) + 2);
  196.             strcpy(files[i], directory);
  197.             strcat(files[i], de->d_name);
  198.             if (fileExtensionOrDirectory == NULL)
  199.                 strcat(files[i], "/");
  200.             i++;
  201.         }
  202.         if (pass == 1)
  203.             break;
  204.         if (total == 0)
  205.             break;
  206.         rewinddir(dir);
  207.         *numFiles = total;
  208.         files = (char**) malloc((total+1)*sizeof(char*));
  209.         files[total]=NULL;
  210.     }
  211.  
  212.     if(closedir(dir) < 0) {
  213.         LOGE("Failed to close directory.");
  214.     }
  215.  
  216.     if (total==0) {
  217.         return NULL;
  218.     }
  219.  
  220.     // sort the result
  221.     if (files != NULL) {
  222.         for (i = 0; i < total; i++) {
  223.             int curMax = -1;
  224.             int j;
  225.             for (j = 0; j < total - i; j++) {
  226.                 if (curMax == -1 || strcmp(files[curMax], files[j]) < 0)
  227.                     curMax = j;
  228.             }
  229.             char* temp = files[curMax];
  230.             files[curMax] = files[total - i - 1];
  231.             files[total - i - 1] = temp;
  232.         }
  233.     }
  234.  
  235.     return files;
  236. }
  237.  
  238. // pass in NULL for fileExtensionOrDirectory and you will get a directory chooser
  239. char* choose_file_menu(const char* directory, const char* fileExtensionOrDirectory, const char* headers[])
  240. {
  241.     char path[PATH_MAX] = "";
  242.     DIR *dir;
  243.     struct dirent *de;
  244.     int numFiles = 0;
  245.     int numDirs = 0;
  246.     int i;
  247.     char* return_value = NULL;
  248.     int dir_len = strlen(directory);
  249.  
  250.     char** files = gather_files(directory, fileExtensionOrDirectory, &numFiles);
  251.     char** dirs = NULL;
  252.     if (fileExtensionOrDirectory != NULL)
  253.         dirs = gather_files(directory, NULL, &numDirs);
  254.     int total = numDirs + numFiles;
  255.     if (total == 0)
  256.     {
  257.         ui_print("No files found.\n");
  258.     }
  259.     else
  260.     {
  261.         char** list = (char**) malloc((total + 1) * sizeof(char*));
  262.         list[total] = NULL;
  263.  
  264.  
  265.         for (i = 0 ; i < numDirs; i++)
  266.         {
  267.             list[i] = strdup(dirs[i] + dir_len);
  268.         }
  269.  
  270.         for (i = 0 ; i < numFiles; i++)
  271.         {
  272.             list[numDirs + i] = strdup(files[i] + dir_len);
  273.         }
  274.  
  275.         for (;;)
  276.         {
  277.             int chosen_item = get_menu_selection(headers, list, 0, 0);
  278.             if (chosen_item == GO_BACK)
  279.                 break;
  280.             static char ret[PATH_MAX];
  281.             if (chosen_item < numDirs)
  282.             {
  283.                 char* subret = choose_file_menu(dirs[chosen_item], fileExtensionOrDirectory, headers);
  284.                 if (subret != NULL)
  285.                 {
  286.                     strcpy(ret, subret);
  287.                     return_value = ret;
  288.                     break;
  289.                 }
  290.                 continue;
  291.             }
  292.             strcpy(ret, files[chosen_item - numDirs]);
  293.             return_value = ret;
  294.             break;
  295.         }
  296.         free_string_array(list);
  297.     }
  298.  
  299.     free_string_array(files);
  300.     free_string_array(dirs);
  301.     return return_value;
  302. }
  303.  
  304. void show_choose_zip_menu()
  305. {
  306.     if (ensure_path_mounted("/sdcard") != 0) {
  307.         LOGE ("Can't mount /sdcard\n");
  308.         return;
  309.     }
  310.  
  311.     static char* headers[] = {  "Choose a zip to apply",
  312.                                 "",
  313.                                 NULL
  314.     };
  315.  
  316.     char* file = choose_file_menu("/sdcard/", ".zip", headers);
  317.     if (file == NULL)
  318.         return;
  319.     static char* confirm_install  = "Confirm install?";
  320.     static char confirm[PATH_MAX];
  321.     sprintf(confirm, "Yes - Install %s", basename(file));
  322.     if (confirm_selection(confirm_install, confirm))
  323.         install_zip(file);
  324. }
  325.  
  326. void show_nandroid_restore_menu()
  327. {
  328.     if (ensure_path_mounted("/sdcard") != 0) {
  329.         LOGE ("Can't mount /sdcard\n");
  330.         return;
  331.     }
  332.  
  333.     static char* headers[] = {  "Choose an image to restore",
  334.                                 "",
  335.                                 NULL
  336.     };
  337.  
  338.     char* file = choose_file_menu("/sdcard/clockworkmod/backup/", NULL, headers);
  339.     if (file == NULL)
  340.         return;
  341.  
  342.     if (confirm_selection("Confirm restore?", "Yes - Restore"))
  343.         nandroid_restore(file, 1, 1, 1, 1, 1, 0);
  344. }
  345.  
  346. #ifndef BOARD_UMS_LUNFILE
  347. #define BOARD_UMS_LUNFILE   "/sys/devices/platform/usb_mass_storage/lun0/file"
  348. #endif
  349.  
  350. void show_mount_usb_storage_menu()
  351. {
  352.     int fd;
  353.     Volume *vol = volume_for_path("/sdcard");
  354.     if ((fd = open(BOARD_UMS_LUNFILE, O_WRONLY)) < 0) {
  355.         LOGE("Unable to open ums lunfile (%s)", strerror(errno));
  356.         return -1;
  357.     }
  358.  
  359.     if ((write(fd, vol->device, strlen(vol->device)) < 0) &&
  360.         (!vol->device2 || (write(fd, vol->device, strlen(vol->device2)) < 0))) {
  361.         LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
  362.         close(fd);
  363.         return -1;
  364.     }
  365.     static char* headers[] = {  "USB Mass Storage device",
  366.                                 "Leaving this menu unmount",
  367.                                 "your SD card from your PC.",
  368.                                 "",
  369.                                 NULL
  370.     };
  371.  
  372.     static char* list[] = { "Unmount", NULL };
  373.  
  374.     for (;;)
  375.     {
  376.         int chosen_item = get_menu_selection(headers, list, 0, 0);
  377.         if (chosen_item == GO_BACK || chosen_item == 0)
  378.             break;
  379.     }
  380.  
  381.     if ((fd = open(BOARD_UMS_LUNFILE, O_WRONLY)) < 0) {
  382.         LOGE("Unable to open ums lunfile (%s)", strerror(errno));
  383.         return -1;
  384.     }
  385.  
  386.     char ch = 0;
  387.     if (write(fd, &ch, 1) < 0) {
  388.         LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
  389.         close(fd);
  390.         return -1;
  391.     }
  392. }
  393.  
  394. int confirm_selection(const char* title, const char* confirm)
  395. {
  396.     struct stat info;
  397.     if (0 == stat("/sdcard/clockworkmod/.no_confirm", &info))
  398.         return 1;
  399.  
  400.     char* confirm_headers[]  = {  title, "  THIS CAN NOT BE UNDONE.", "", NULL };
  401.     char* items[] = { "No",
  402.                       "No",
  403.                       "No",
  404.                       "No",
  405.                       "No",
  406.                       "No",
  407.                       "No",
  408.                       confirm, //" Yes -- wipe partition",   // [7
  409.                       "No",
  410.                       "No",
  411.                       "No",
  412.                       NULL };
  413.  
  414.     int chosen_item = get_menu_selection(confirm_headers, items, 0, 0);
  415.     return chosen_item == 7;
  416. }
  417.  
  418. #define MKE2FS_BIN      "/sbin/mke2fs"
  419. #define TUNE2FS_BIN     "/sbin/tune2fs"
  420. #define E2FSCK_BIN      "/sbin/e2fsck"
  421.  
  422. int format_unknown_device(const char *device, const char* path, const char *fs_type)
  423. {
  424.     LOGI("Formatting unknown device.\n");
  425.  
  426.     if (fs_type != NULL && get_flash_type(fs_type) != UNSUPPORTED)
  427.         return erase_raw_partition(fs_type, device);
  428.  
  429.     // if this is SDEXT:, don't worry about it if it does not exist.
  430.     if (0 == strcmp(path, "/sd-ext"))
  431.     {
  432.         struct stat st;
  433.         Volume *vol = volume_for_path("/sd-ext");
  434.         if (vol == NULL || 0 != stat(vol->device, &st))
  435.         {
  436.             ui_print("No app2sd partition found. Skipping format of /sd-ext.\n");
  437.             return 0;
  438.         }
  439.     }
  440.  
  441.     if (NULL != fs_type) {
  442.         if (strcmp("ext3", fs_type) == 0) {
  443.             LOGI("Formatting ext3 device.\n");
  444.             if (0 != ensure_path_unmounted(path)) {
  445.                 LOGE("Error while unmounting %s.\n", path);
  446.                 return -12;
  447.             }
  448.             return format_ext3_device(device);
  449.         }
  450.  
  451.         if (strcmp("ext2", fs_type) == 0) {
  452.             LOGI("Formatting ext2 device.\n");
  453.             if (0 != ensure_path_unmounted(path)) {
  454.                 LOGE("Error while unmounting %s.\n", path);
  455.                 return -12;
  456.             }
  457.             return format_ext2_device(device);
  458.         }
  459.     }
  460.  
  461.     if (0 != ensure_path_mounted(path))
  462.     {
  463.         ui_print("Error mounting %s!\n", path);
  464.         ui_print("Skipping format...\n");
  465.         return 0;
  466.     }
  467.  
  468.     static char tmp[PATH_MAX];
  469.     if (strcmp(path, "/data") == 0) {
  470.         sprintf(tmp, "cd /data ; for f in $(ls -a | grep -v ^media$); do rm -rf $f; done");
  471.         __system(tmp);
  472.     }
  473.     else {
  474.         sprintf(tmp, "rm -rf %s/*", path);
  475.         __system(tmp);
  476.         sprintf(tmp, "rm -rf %s/.*", path);
  477.         __system(tmp);
  478.     }
  479.  
  480.     ensure_path_unmounted(path);
  481.     return 0;
  482. }
  483.  
  484. //#define MOUNTABLE_COUNT 5
  485. //#define DEVICE_COUNT 4
  486. //#define MMC_COUNT 2
  487.  
  488. typedef struct {
  489.     char mount[255];
  490.     char unmount[255];
  491.     Volume* v;
  492. } MountMenuEntry;
  493.  
  494. typedef struct {
  495.     char txt[255];
  496.     Volume* v;
  497. } FormatMenuEntry;
  498.  
  499. int is_safe_to_format(char* name)
  500. {
  501.     char str[255];
  502.     char* partition;
  503.     property_get("ro.cwm.forbid_format", str, "/misc,/radio,/bootloader,/recovery,/efs");
  504.  
  505.     partition = strtok(str, ", ");
  506.     while (partition != NULL) {
  507.         if (strcmp(name, partition) == 0) {
  508.             return 0;
  509.         }
  510.         partition = strtok(NULL, ", ");
  511.     }
  512.  
  513.     return 1;
  514. }
  515.  
  516. void show_partition_menu()
  517. {
  518.     static char* headers[] = {  "Mounts and Storage Menu",
  519.                                 "",
  520.                                 NULL
  521.     };
  522.  
  523.     static MountMenuEntry* mount_menue = NULL;
  524.     static FormatMenuEntry* format_menue = NULL;
  525.  
  526.     typedef char* string;
  527.  
  528.     int i, mountable_volumes, formatable_volumes;
  529.     int num_volumes;
  530.     Volume* device_volumes;
  531.  
  532.     num_volumes = get_num_volumes();
  533.     device_volumes = get_device_volumes();
  534.  
  535.     string options[255];
  536.  
  537.     if(!device_volumes)
  538.         return;
  539.  
  540.         mountable_volumes = 0;
  541.         formatable_volumes = 0;
  542.  
  543.         mount_menue = malloc(num_volumes * sizeof(MountMenuEntry));
  544.         format_menue = malloc(num_volumes * sizeof(FormatMenuEntry));
  545.  
  546.         for (i = 0; i < num_volumes; ++i) {
  547.             Volume* v = &device_volumes[i];
  548.             if(strcmp("ramdisk", v->fs_type) != 0 && strcmp("mtd", v->fs_type) != 0 && strcmp("emmc", v->fs_type) != 0 && strcmp("bml", v->fs_type) != 0)
  549.             {
  550.                 sprintf(&mount_menue[mountable_volumes].mount, "mount %s", v->mount_point);
  551.                 sprintf(&mount_menue[mountable_volumes].unmount, "unmount %s", v->mount_point);
  552.                 mount_menue[mountable_volumes].v = &device_volumes[i];
  553.                 ++mountable_volumes;
  554.                 if (is_safe_to_format(v->mount_point)) {
  555.                     sprintf(&format_menue[formatable_volumes].txt, "format %s", v->mount_point);
  556.                     format_menue[formatable_volumes].v = &device_volumes[i];
  557.                     ++formatable_volumes;
  558.                 }
  559.             }
  560.             else if (strcmp("ramdisk", v->fs_type) != 0 && strcmp("mtd", v->fs_type) == 0 && is_safe_to_format(v->mount_point))
  561.             {
  562.                 sprintf(&format_menue[formatable_volumes].txt, "format %s", v->mount_point);
  563.                 format_menue[formatable_volumes].v = &device_volumes[i];
  564.                 ++formatable_volumes;
  565.             }
  566.         }
  567.  
  568.  
  569.     static char* confirm_format  = "Confirm format?";
  570.     static char* confirm = "Yes - Format";
  571.     char confirm_string[255];
  572.  
  573.     for (;;)
  574.     {
  575.  
  576.         for (i = 0; i < mountable_volumes; i++)
  577.         {
  578.             MountMenuEntry* e = &mount_menue[i];
  579.             Volume* v = e->v;
  580.             if(is_path_mounted(v->mount_point))
  581.                 options[i] = e->unmount;
  582.             else
  583.                 options[i] = e->mount;
  584.         }
  585.  
  586.         for (i = 0; i < formatable_volumes; i++)
  587.         {
  588.             FormatMenuEntry* e = &format_menue[i];
  589.  
  590.             options[mountable_volumes+i] = e->txt;
  591.         }
  592.  
  593.         options[mountable_volumes+formatable_volumes] = "mount USB storage";
  594.         options[mountable_volumes+formatable_volumes + 1] = NULL;
  595.  
  596.         int chosen_item = get_menu_selection(headers, &options, 0, 0);
  597.         if (chosen_item == GO_BACK)
  598.             break;
  599.         if (chosen_item == (mountable_volumes+formatable_volumes))
  600.         {
  601.             show_mount_usb_storage_menu();
  602.         }
  603.         else if (chosen_item < mountable_volumes)
  604.         {
  605.             MountMenuEntry* e = &mount_menue[chosen_item];
  606.             Volume* v = e->v;
  607.  
  608.             if (is_path_mounted(v->mount_point))
  609.             {
  610.                 if (0 != ensure_path_unmounted(v->mount_point))
  611.                     ui_print("Error unmounting %s!\n", v->mount_point);
  612.             }
  613.             else
  614.             {
  615.                 if (0 != ensure_path_mounted(v->mount_point))
  616.                     ui_print("Error mounting %s!\n",  v->mount_point);
  617.             }
  618.         }
  619.         else if (chosen_item < (mountable_volumes + formatable_volumes))
  620.         {
  621.             chosen_item = chosen_item - mountable_volumes;
  622.             FormatMenuEntry* e = &format_menue[chosen_item];
  623.             Volume* v = e->v;
  624.  
  625.             sprintf(confirm_string, "%s - %s", v->mount_point, confirm_format);
  626.  
  627.             if (!confirm_selection(confirm_string, confirm))
  628.                 continue;
  629.             ui_print("Formatting %s...\n", v->mount_point);
  630.             if (0 != format_volume(v->mount_point))
  631.                 ui_print("Error formatting %s!\n", v->mount_point);
  632.             else
  633.                 ui_print("Done.\n");
  634.         }
  635.     }
  636.  
  637.     free(mount_menue);
  638.     free(format_menue);
  639.  
  640. }
  641.  
  642. #define EXTENDEDCOMMAND_SCRIPT "/cache/recovery/extendedcommand"
  643.  
  644. int extendedcommand_file_exists()
  645. {
  646.     struct stat file_info;
  647.     return 0 == stat(EXTENDEDCOMMAND_SCRIPT, &file_info);
  648. }
  649.  
  650. int edify_main(int argc, char** argv) {
  651.     load_volume_table();
  652.     process_volumes();
  653.     RegisterBuiltins();
  654.     RegisterRecoveryHooks();
  655.     FinishRegistration();
  656.  
  657.     if (argc != 2) {
  658.         printf("edify <filename>\n");
  659.         return 1;
  660.     }
  661.  
  662.     FILE* f = fopen(argv[1], "r");
  663.     if (f == NULL) {
  664.         printf("%s: %s: No such file or directory\n", argv[0], argv[1]);
  665.         return 1;
  666.     }
  667.     char buffer[8192];
  668.     int size = fread(buffer, 1, 8191, f);
  669.     fclose(f);
  670.     buffer[size] = '\0';
  671.  
  672.     Expr* root;
  673.     int error_count = 0;
  674.     yy_scan_bytes(buffer, size);
  675.     int error = yyparse(&root, &error_count);
  676.     printf("parse returned %d; %d errors encountered\n", error, error_count);
  677.     if (error == 0 || error_count > 0) {
  678.  
  679.         //ExprDump(0, root, buffer);
  680.  
  681.         State state;
  682.         state.cookie = NULL;
  683.         state.script = buffer;
  684.         state.errmsg = NULL;
  685.  
  686.         char* result = Evaluate(&state, root);
  687.         if (result == NULL) {
  688.             printf("result was NULL, message is: %s\n",
  689.                    (state.errmsg == NULL ? "(NULL)" : state.errmsg));
  690.             free(state.errmsg);
  691.         } else {
  692.             printf("result is [%s]\n", result);
  693.         }
  694.     }
  695.     return 0;
  696. }
  697.  
  698. int run_script(char* filename)
  699. {
  700.     struct stat file_info;
  701.     if (0 != stat(filename, &file_info)) {
  702.         printf("Error executing stat on file: %s\n", filename);
  703.         return 1;
  704.     }
  705.  
  706.     int script_len = file_info.st_size;
  707.     char* script_data = (char*)malloc(script_len + 1);
  708.     FILE *file = fopen(filename, "rb");
  709.     fread(script_data, script_len, 1, file);
  710.     // supposedly not necessary, but let's be safe.
  711.     script_data[script_len] = '\0';
  712.     fclose(file);
  713.     LOGI("Running script:\n");
  714.     LOGI("\n%s\n", script_data);
  715.  
  716.     int ret = run_script_from_buffer(script_data, script_len, filename);
  717.     free(script_data);
  718.     return ret;
  719. }
  720.  
  721. int run_and_remove_extendedcommand()
  722. {
  723.     char tmp[PATH_MAX];
  724.     sprintf(tmp, "cp %s /tmp/%s", EXTENDEDCOMMAND_SCRIPT, basename(EXTENDEDCOMMAND_SCRIPT));
  725.     __system(tmp);
  726.     remove(EXTENDEDCOMMAND_SCRIPT);
  727.     int i = 0;
  728.     for (i = 20; i > 0; i--) {
  729.         ui_print("Waiting for SD Card to mount (%ds)\n", i);
  730.         if (ensure_path_mounted("/sdcard") == 0) {
  731.             ui_print("SD Card mounted...\n");
  732.             break;
  733.         }
  734.         sleep(1);
  735.     }
  736.     remove("/sdcard/clockworkmod/.recoverycheckpoint");
  737.     if (i == 0) {
  738.         ui_print("Timed out waiting for SD card... continuing anyways.");
  739.     }
  740.  
  741.     sprintf(tmp, "/tmp/%s", basename(EXTENDEDCOMMAND_SCRIPT));
  742.     return run_script(tmp);
  743. }
  744.  
  745. void show_nandroid_advanced_restore_menu()
  746. {
  747.     if (ensure_path_mounted("/sdcard") != 0) {
  748.         LOGE ("Can't mount /sdcard\n");
  749.         return;
  750.     }
  751.  
  752.     static char* advancedheaders[] = {  "Choose an image to restore",
  753.                                 "",
  754.                                 "Choose an image to restore",
  755.                                 "first. The next menu will",
  756.                                 "you more options.",
  757.                                 "",
  758.                                 NULL
  759.     };
  760.  
  761.     char* file = choose_file_menu("/sdcard/clockworkmod/backup/", NULL, advancedheaders);
  762.     if (file == NULL)
  763.         return;
  764.  
  765.     static char* headers[] = {  "Nandroid Advanced Restore",
  766.                                 "",
  767.                                 NULL
  768.     };
  769.  
  770.     static char* list[] = { "Restore boot",
  771.                             "Restore system",
  772.                             "Restore data",
  773.                             "Restore cache",
  774.                             "Restore sd-ext",
  775.                             "Restore wimax",
  776.                             NULL
  777.     };
  778.    
  779.     char tmp[PATH_MAX];
  780.     if (0 != get_partition_device("wimax", tmp)) {
  781.         // disable wimax restore option
  782.         list[5] = NULL;
  783.     }
  784.  
  785.     static char* confirm_restore  = "Confirm restore?";
  786.  
  787.     int chosen_item = get_menu_selection(headers, list, 0, 0);
  788.     switch (chosen_item)
  789.     {
  790.         case 0:
  791.             if (confirm_selection(confirm_restore, "Yes - Restore boot"))
  792.                 nandroid_restore(file, 1, 0, 0, 0, 0, 0);
  793.             break;
  794.         case 1:
  795.             if (confirm_selection(confirm_restore, "Yes - Restore system"))
  796.                 nandroid_restore(file, 0, 1, 0, 0, 0, 0);
  797.             break;
  798.         case 2:
  799.             if (confirm_selection(confirm_restore, "Yes - Restore data"))
  800.                 nandroid_restore(file, 0, 0, 1, 0, 0, 0);
  801.             break;
  802.         case 3:
  803.             if (confirm_selection(confirm_restore, "Yes - Restore cache"))
  804.                 nandroid_restore(file, 0, 0, 0, 1, 0, 0);
  805.             break;
  806.         case 4:
  807.             if (confirm_selection(confirm_restore, "Yes - Restore sd-ext"))
  808.                 nandroid_restore(file, 0, 0, 0, 0, 1, 0);
  809.             break;
  810.         case 5:
  811.             if (confirm_selection(confirm_restore, "Yes - Restore wimax"))
  812.                 nandroid_restore(file, 0, 0, 0, 0, 0, 1);
  813.             break;
  814.     }
  815. }
  816.  
  817. void show_nandroid_menu()
  818. {
  819.     static char* headers[] = {  "Nandroid",
  820.                                 "",
  821.                                 NULL
  822.     };
  823.  
  824.     static char* list[] = { "Backup",
  825.                             "Restore",
  826.                             "Advanced Restore",
  827.                             NULL
  828.     };
  829.  
  830.     int chosen_item = get_menu_selection(headers, list, 0, 0);
  831.     switch (chosen_item)
  832.     {
  833.         case 0:
  834.             {
  835.                 char backup_path[PATH_MAX];
  836.                 time_t t = time(NULL);
  837.                 struct tm *tmp = localtime(&t);
  838.                 if (tmp == NULL)
  839.                 {
  840.                     struct timeval tp;
  841.                     gettimeofday(&tp, NULL);
  842.                     sprintf(backup_path, "/sdcard/clockworkmod/backup/%d", tp.tv_sec);
  843.                 }
  844.                 else
  845.                 {
  846.                     strftime(backup_path, sizeof(backup_path), "/sdcard/clockworkmod/backup/%F.%H.%M.%S", tmp);
  847.                 }
  848.                 nandroid_backup(backup_path);
  849.             }
  850.             break;
  851.         case 1:
  852.             show_nandroid_restore_menu();
  853.             break;
  854.         case 2:
  855.             show_nandroid_advanced_restore_menu();
  856.             break;
  857.     }
  858. }
  859.  
  860. void wipe_battery_stats()
  861. {
  862.     ensure_path_mounted("/data");
  863.     remove("/data/system/batterystats.bin");
  864.     ensure_path_unmounted("/data");
  865. }
  866.  
  867. void show_advanced_menu()
  868. {
  869.     static char* headers[] = {  "Advanced and Debugging Menu",
  870.                                 "",
  871.                                 NULL
  872.     };
  873.  
  874.     static char* list[] = { "Reboot Recovery",
  875.                             "Wipe Dalvik Cache",
  876.                             "Wipe Battery Stats",
  877.                             "Report Error",
  878.                             "Key Test",
  879. #ifndef BOARD_HAS_SMALL_RECOVERY
  880.                             "Partition SD Card",
  881.                             "Fix Permissions",
  882. #ifdef BOARD_HAS_SDCARD_INTERNAL
  883.                             "Partition Internal SD Card",
  884. #endif
  885. #endif
  886.                             NULL
  887.     };
  888.  
  889.     for (;;)
  890.     {
  891.         int chosen_item = get_menu_selection(headers, list, 0, 0);
  892.         if (chosen_item == GO_BACK)
  893.             break;
  894.         switch (chosen_item)
  895.         {
  896.             case 0:
  897.                 reboot_wrapper("recovery");
  898.                 break;
  899.             case 1:
  900.             {
  901.                 if (0 != ensure_path_mounted("/data"))
  902.                     break;
  903.                 ensure_path_mounted("/sd-ext");
  904.                 ensure_path_mounted("/cache");
  905.                 if (confirm_selection( "Confirm wipe?", "Yes - Wipe Dalvik Cache")) {
  906.                     __system("rm -r /data/dalvik-cache");
  907.                     __system("rm -r /cache/dalvik-cache");
  908.                     __system("rm -r /sd-ext/dalvik-cache");
  909.                 }
  910.                 ensure_path_unmounted("/data");
  911.                 ui_print("Dalvik Cache wiped.\n");
  912.                 break;
  913.             }
  914.             case 2:
  915.             {
  916.                 if (confirm_selection( "Confirm wipe?", "Yes - Wipe Battery Stats"))
  917.                     wipe_battery_stats();
  918.                 break;
  919.             }
  920.             case 3:
  921.                 handle_failure(1);
  922.                 break;
  923.             case 4:
  924.             {
  925.                 ui_print("Outputting key codes.\n");
  926.                 ui_print("Go back to end debugging.\n");
  927.                 int key;
  928.                 int action;
  929.                 do
  930.                 {
  931.                     key = ui_wait_key();
  932.                     action = device_handle_key(key, 1);
  933.                     ui_print("Key: %d\n", key);
  934.                 }
  935.                 while (action != GO_BACK);
  936.                 break;
  937.             }
  938.             case 5:
  939.             {
  940.                 static char* ext_sizes[] = { "128M",
  941.                                              "256M",
  942.                                              "512M",
  943.                                              "1024M",
  944.                                              "2048M",
  945.                                              "4096M",
  946.                                              NULL };
  947.  
  948.                 static char* swap_sizes[] = { "0M",
  949.                                               "32M",
  950.                                               "64M",
  951.                                               "128M",
  952.                                               "256M",
  953.                                               NULL };
  954.  
  955.                 static char* ext_headers[] = { "Ext Size", "", NULL };
  956.                 static char* swap_headers[] = { "Swap Size", "", NULL };
  957.  
  958.                 int ext_size = get_menu_selection(ext_headers, ext_sizes, 0, 0);
  959.                 if (ext_size == GO_BACK)
  960.                     continue;
  961.  
  962.                 int swap_size = get_menu_selection(swap_headers, swap_sizes, 0, 0);
  963.                 if (swap_size == GO_BACK)
  964.                     continue;
  965.  
  966.                 char sddevice[256];
  967.                 Volume *vol = volume_for_path("/sdcard");
  968.                 strcpy(sddevice, vol->device);
  969.                 // we only want the mmcblk, not the partition
  970.                 sddevice[strlen("/dev/block/mmcblkX")] = NULL;
  971.                 char cmd[PATH_MAX];
  972.                 setenv("SDPATH", sddevice, 1);
  973.                 sprintf(cmd, "sdparted -es %s -ss %s -efs ext3 -s", ext_sizes[ext_size], swap_sizes[swap_size]);
  974.                 ui_print("Partitioning SD Card... please wait...\n");
  975.                 if (0 == __system(cmd))
  976.                     ui_print("Done!\n");
  977.                 else
  978.                     ui_print("An error occured while partitioning your SD Card. Please see /tmp/recovery.log for more details.\n");
  979.                 break;
  980.             }
  981.             case 6:
  982.             {
  983.                 ensure_path_mounted("/system");
  984.                 ensure_path_mounted("/data");
  985.                 ui_print("Fixing permissions...\n");
  986.                 __system("fix_permissions");
  987.                 ui_print("Done!\n");
  988.                 break;
  989.             }
  990.             case 7:
  991.             {
  992.                 static char* ext_sizes[] = { "128M",
  993.                                              "256M",
  994.                                              "512M",
  995.                                              "1024M",
  996.                                              "2048M",
  997.                                              "4096M",
  998.                                              NULL };
  999.  
  1000.                 static char* swap_sizes[] = { "0M",
  1001.                                               "32M",
  1002.                                               "64M",
  1003.                                               "128M",
  1004.                                               "256M",
  1005.                                               NULL };
  1006.  
  1007.                 static char* ext_headers[] = { "Data Size", "", NULL };
  1008.                 static char* swap_headers[] = { "Swap Size", "", NULL };
  1009.  
  1010.                 int ext_size = get_menu_selection(ext_headers, ext_sizes, 0, 0);
  1011.                 if (ext_size == GO_BACK)
  1012.                     continue;
  1013.  
  1014.                 int swap_size = 0;
  1015.                 if (swap_size == GO_BACK)
  1016.                     continue;
  1017.  
  1018.                 char sddevice[256];
  1019.                 Volume *vol = volume_for_path("/emmc");
  1020.                 strcpy(sddevice, vol->device);
  1021.                 // we only want the mmcblk, not the partition
  1022.                 sddevice[strlen("/dev/block/mmcblkX")] = NULL;
  1023.                 char cmd[PATH_MAX];
  1024.                 setenv("SDPATH", sddevice, 1);
  1025.                 sprintf(cmd, "sdparted -es %s -ss %s -efs ext3 -s", ext_sizes[ext_size], swap_sizes[swap_size]);
  1026.                 ui_print("Partitioning Internal SD Card... please wait...\n");
  1027.                 if (0 == __system(cmd))
  1028.                     ui_print("Done!\n");
  1029.                 else
  1030.                     ui_print("An error occured while partitioning your Internal SD Card. Please see /tmp/recovery.log for more details.\n");
  1031.                 break;
  1032.             }
  1033.         }
  1034.     }
  1035. }
  1036.  
  1037. void write_fstab_root(char *path, FILE *file)
  1038. {
  1039.     Volume *vol = volume_for_path(path);
  1040.     if (vol == NULL) {
  1041.         LOGW("Unable to get recovery.fstab info for %s during fstab generation!\n", path);
  1042.         return;
  1043.     }
  1044.  
  1045.     char device[200];
  1046.     if (vol->device[0] != '/')
  1047.         get_partition_device(vol->device, device);
  1048.     else
  1049.         strcpy(device, vol->device);
  1050.  
  1051.     fprintf(file, "%s ", device);
  1052.     fprintf(file, "%s ", path);
  1053.     // special case rfs cause auto will mount it as vfat on samsung.
  1054.     fprintf(file, "%s rw\n", vol->fs_type2 != NULL && strcmp(vol->fs_type, "rfs") != 0 ? "auto" : vol->fs_type);
  1055. }
  1056.  
  1057. void create_fstab()
  1058. {
  1059.     struct stat info;
  1060.     __system("touch /etc/mtab");
  1061.     FILE *file = fopen("/etc/fstab", "w");
  1062.     if (file == NULL) {
  1063.         LOGW("Unable to create /etc/fstab!\n");
  1064.         return;
  1065.     }
  1066.     Volume *vol = volume_for_path("/boot");
  1067.     if (NULL != vol && strcmp(vol->fs_type, "mtd") != 0 && strcmp(vol->fs_type, "emmc") != 0 && strcmp(vol->fs_type, "bml") != 0)
  1068.          write_fstab_root("/boot", file);
  1069.     write_fstab_root("/cache", file);
  1070.     write_fstab_root("/data", file);
  1071.     if (has_datadata()) {
  1072.         write_fstab_root("/datadata", file);
  1073.     }
  1074.     write_fstab_root("/system", file);
  1075.     write_fstab_root("/sdcard", file);
  1076.     write_fstab_root("/sd-ext", file);
  1077.     fclose(file);
  1078.     LOGI("Completed outputting fstab.\n");
  1079. }
  1080.  
  1081. int bml_check_volume(const char *path) {
  1082.     ui_print("Checking %s...\n", path);
  1083.     ensure_path_unmounted(path);
  1084.     if (0 == ensure_path_mounted(path)) {
  1085.         ensure_path_unmounted(path);
  1086.         return 0;
  1087.     }
  1088.    
  1089.     Volume *vol = volume_for_path(path);
  1090.     if (vol == NULL) {
  1091.         LOGE("Unable process volume! Skipping...\n");
  1092.         return 0;
  1093.     }
  1094.    
  1095.     ui_print("%s may be rfs. Checking...\n", path);
  1096.     char tmp[PATH_MAX];
  1097.     sprintf(tmp, "mount -t rfs %s %s", vol->device, path);
  1098.     int ret = __system(tmp);
  1099.     printf("%d\n", ret);
  1100.     return ret == 0 ? 1 : 0;
  1101. }
  1102.  
  1103. void process_volumes() {
  1104.     create_fstab();
  1105.  
  1106.     if (is_data_media()) {
  1107.         setup_data_media();
  1108.     }
  1109.  
  1110.     return;
  1111.  
  1112.     // dead code.
  1113.     if (device_flash_type() != BML)
  1114.         return;
  1115.  
  1116.     ui_print("Checking for ext4 partitions...\n");
  1117.     int ret = 0;
  1118.     ret = bml_check_volume("/system");
  1119.     ret |= bml_check_volume("/data");
  1120.     if (has_datadata())
  1121.         ret |= bml_check_volume("/datadata");
  1122.     ret |= bml_check_volume("/cache");
  1123.    
  1124.     if (ret == 0) {
  1125.         ui_print("Done!\n");
  1126.         return;
  1127.     }
  1128.    
  1129.     char backup_path[PATH_MAX];
  1130.     time_t t = time(NULL);
  1131.     char backup_name[PATH_MAX];
  1132.     struct timeval tp;
  1133.     gettimeofday(&tp, NULL);
  1134.     sprintf(backup_name, "before-ext4-convert-%d", tp.tv_sec);
  1135.     sprintf(backup_path, "/sdcard/clockworkmod/backup/%s", backup_name);
  1136.  
  1137.     ui_set_show_text(1);
  1138.     ui_print("Filesystems need to be converted to ext4.\n");
  1139.     ui_print("A backup and restore will now take place.\n");
  1140.     ui_print("If anything goes wrong, your backup will be\n");
  1141.     ui_print("named %s. Try restoring it\n", backup_name);
  1142.     ui_print("in case of error.\n");
  1143.  
  1144.     nandroid_backup(backup_path);
  1145.     nandroid_restore(backup_path, 1, 1, 1, 1, 1, 0);
  1146.     ui_set_show_text(0);
  1147. }
  1148.  
  1149. void handle_failure(int ret)
  1150. {
  1151.     if (ret == 0)
  1152.         return;
  1153.     if (0 != ensure_path_mounted("/sdcard"))
  1154.         return;
  1155.     mkdir("/sdcard/clockworkmod", S_IRWXU);
  1156.     __system("cp /tmp/recovery.log /sdcard/clockworkmod/recovery.log");
  1157.     ui_print("/tmp/recovery.log was copied to /sdcard/clockworkmod/recovery.log. Please open ROM Manager to report the issue.\n");
  1158. }
  1159.  
  1160. int is_path_mounted(const char* path) {
  1161.     Volume* v = volume_for_path(path);
  1162.     if (v == NULL) {
  1163.         return 0;
  1164.     }
  1165.     if (strcmp(v->fs_type, "ramdisk") == 0) {
  1166.         // the ramdisk is always mounted.
  1167.         return 1;
  1168.     }
  1169.  
  1170.     int result;
  1171.     result = scan_mounted_volumes();
  1172.     if (result < 0) {
  1173.         LOGE("failed to scan mounted volumes\n");
  1174.         return 0;
  1175.     }
  1176.  
  1177.     const MountedVolume* mv =
  1178.         find_mounted_volume_by_mount_point(v->mount_point);
  1179.     if (mv) {
  1180.         // volume is already mounted
  1181.         return 1;
  1182.     }
  1183.     return 0;
  1184. }
  1185.  
  1186. int has_datadata() {
  1187.     Volume *vol = volume_for_path("/datadata");
  1188.     return vol != NULL;
  1189. }
  1190.  
  1191. int volume_main(int argc, char **argv) {
  1192.     load_volume_table();
  1193.     return 0;
  1194. }
Advertisement
Add Comment
Please, Sign In to add comment