aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--device.h3
-rw-r--r--recovery.cpp108
2 files changed, 47 insertions, 64 deletions
diff --git a/device.h b/device.h
index df71377c..57ec3fc3 100644
--- a/device.h
+++ b/device.h
@@ -65,7 +65,8 @@ class Device {
65 // - invoke a specific action (a menu position: any non-negative number) 65 // - invoke a specific action (a menu position: any non-negative number)
66 virtual int HandleMenuKey(int key, int visible) = 0; 66 virtual int HandleMenuKey(int key, int visible) = 0;
67 67
68 enum BuiltinAction { NO_ACTION, REBOOT, APPLY_EXT, APPLY_CACHE, 68 enum BuiltinAction { NO_ACTION, REBOOT, APPLY_EXT,
69 APPLY_CACHE, // APPLY_CACHE is deprecated; has no effect
69 APPLY_ADB_SIDELOAD, WIPE_DATA, WIPE_CACHE, 70 APPLY_ADB_SIDELOAD, WIPE_DATA, WIPE_CACHE,
70 REBOOT_BOOTLOADER, SHUTDOWN }; 71 REBOOT_BOOTLOADER, SHUTDOWN };
71 72
diff --git a/recovery.cpp b/recovery.cpp
index 5a2715cb..1c7c0d6a 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -604,9 +604,9 @@ static int compare_string(const void* a, const void* b) {
604 return strcmp(*(const char**)a, *(const char**)b); 604 return strcmp(*(const char**)a, *(const char**)b);
605} 605}
606 606
607static int 607// Returns a malloc'd path, or NULL.
608update_directory(const char* path, const char* unmount_when_done, 608static char*
609 int* wipe_cache, Device* device) { 609browse_directory(const char* path, Device* device) {
610 ensure_path_mounted(path); 610 ensure_path_mounted(path);
611 611
612 const char* MENU_HEADERS[] = { "Choose a package to install:", 612 const char* MENU_HEADERS[] = { "Choose a package to install:",
@@ -618,10 +618,7 @@ update_directory(const char* path, const char* unmount_when_done,
618 d = opendir(path); 618 d = opendir(path);
619 if (d == NULL) { 619 if (d == NULL) {
620 LOGE("error opening %s: %s\n", path, strerror(errno)); 620 LOGE("error opening %s: %s\n", path, strerror(errno));
621 if (unmount_when_done != NULL) { 621 return NULL;
622 ensure_path_unmounted(unmount_when_done);
623 }
624 return 0;
625 } 622 }
626 623
627 const char** headers = prepend_title(MENU_HEADERS); 624 const char** headers = prepend_title(MENU_HEADERS);
@@ -677,58 +674,41 @@ update_directory(const char* path, const char* unmount_when_done,
677 z_size += d_size; 674 z_size += d_size;
678 zips[z_size] = NULL; 675 zips[z_size] = NULL;
679 676
680 int result; 677 char* result;
681 int chosen_item = 0; 678 int chosen_item = 0;
682 do { 679 while (true) {
683 chosen_item = get_menu_selection(headers, zips, 1, chosen_item, device); 680 chosen_item = get_menu_selection(headers, zips, 1, chosen_item, device);
684 681
685 char* item = zips[chosen_item]; 682 char* item = zips[chosen_item];
686 int item_len = strlen(item); 683 int item_len = strlen(item);
687 if (chosen_item == 0) { // item 0 is always "../" 684 if (chosen_item == 0) { // item 0 is always "../"
688 // go up but continue browsing (if the caller is update_directory) 685 // go up but continue browsing (if the caller is update_directory)
689 result = -1; 686 result = NULL;
690 break; 687 break;
691 } else if (item[item_len-1] == '/') { 688 }
689
690 char new_path[PATH_MAX];
691 strlcpy(new_path, path, PATH_MAX);
692 strlcat(new_path, "/", PATH_MAX);
693 strlcat(new_path, item, PATH_MAX);
694
695 if (item[item_len-1] == '/') {
692 // recurse down into a subdirectory 696 // recurse down into a subdirectory
693 char new_path[PATH_MAX];
694 strlcpy(new_path, path, PATH_MAX);
695 strlcat(new_path, "/", PATH_MAX);
696 strlcat(new_path, item, PATH_MAX);
697 new_path[strlen(new_path)-1] = '\0'; // truncate the trailing '/' 697 new_path[strlen(new_path)-1] = '\0'; // truncate the trailing '/'
698 result = update_directory(new_path, unmount_when_done, wipe_cache, device); 698 result = browse_directory(new_path, device);
699 if (result >= 0) break; 699 if (result) break;
700 } else { 700 } else {
701 // selected a zip file: attempt to install it, and return 701 // selected a zip file: return the malloc'd path to the caller.
702 // the status to the caller. 702 result = strdup(new_path);
703 char new_path[PATH_MAX];
704 strlcpy(new_path, path, PATH_MAX);
705 strlcat(new_path, "/", PATH_MAX);
706 strlcat(new_path, item, PATH_MAX);
707
708 ui->Print("\n-- Install %s ...\n", path);
709 set_sdcard_update_bootloader_message();
710 char* copy = copy_sideloaded_package(new_path);
711 if (unmount_when_done != NULL) {
712 ensure_path_unmounted(unmount_when_done);
713 }
714 if (copy) {
715 result = install_package(copy, wipe_cache, TEMPORARY_INSTALL_FILE, true);
716 free(copy);
717 } else {
718 result = INSTALL_ERROR;
719 }
720 break; 703 break;
721 } 704 }
722 } while (true); 705 }
723 706
724 int i; 707 int i;
725 for (i = 0; i < z_size; ++i) free(zips[i]); 708 for (i = 0; i < z_size; ++i) free(zips[i]);
726 free(zips); 709 free(zips);
727 free(headers); 710 free(headers);
728 711
729 if (unmount_when_done != NULL) {
730 ensure_path_unmounted(unmount_when_done);
731 }
732 return result; 712 return result;
733} 713}
734 714
@@ -800,7 +780,7 @@ prompt_and_wait(Device* device, int status) {
800 // statement below. 780 // statement below.
801 Device::BuiltinAction chosen_action = device->InvokeMenuItem(chosen_item); 781 Device::BuiltinAction chosen_action = device->InvokeMenuItem(chosen_item);
802 782
803 int wipe_cache; 783 int wipe_cache = 0;
804 switch (chosen_action) { 784 switch (chosen_action) {
805 case Device::NO_ACTION: 785 case Device::NO_ACTION:
806 break; 786 break;
@@ -822,8 +802,28 @@ prompt_and_wait(Device* device, int status) {
822 if (!ui->IsTextVisible()) return Device::NO_ACTION; 802 if (!ui->IsTextVisible()) return Device::NO_ACTION;
823 break; 803 break;
824 804
825 case Device::APPLY_EXT: 805 case Device::APPLY_EXT: {
826 status = update_directory(SDCARD_ROOT, SDCARD_ROOT, &wipe_cache, device); 806 ensure_path_mounted(SDCARD_ROOT);
807 char* path = browse_directory(SDCARD_ROOT, device);
808 if (path == NULL) {
809 ui->Print("\n-- No package file selected.\n", path);
810 break;
811 }
812
813 ui->Print("\n-- Install %s ...\n", path);
814 set_sdcard_update_bootloader_message();
815 char* copy = copy_sideloaded_package(path);
816 free(path);
817 ensure_path_unmounted(SDCARD_ROOT);
818
819 int status;
820 if (copy) {
821 status = install_package(copy, &wipe_cache, TEMPORARY_INSTALL_FILE, true);
822 free(copy);
823 } else {
824 status = INSTALL_ERROR;
825 }
826
827 if (status == INSTALL_SUCCESS && wipe_cache) { 827 if (status == INSTALL_SUCCESS && wipe_cache) {
828 ui->Print("\n-- Wiping cache (at package request)...\n"); 828 ui->Print("\n-- Wiping cache (at package request)...\n");
829 if (erase_volume("/cache")) { 829 if (erase_volume("/cache")) {
@@ -843,28 +843,10 @@ prompt_and_wait(Device* device, int status) {
843 } 843 }
844 } 844 }
845 break; 845 break;
846 }
846 847
847 case Device::APPLY_CACHE: 848 case Device::APPLY_CACHE:
848 // Don't unmount cache at the end of this. 849 ui->Print("\nAPPLY_CACHE is deprecated.\n");
849 status = update_directory(CACHE_ROOT, NULL, &wipe_cache, device);
850 if (status == INSTALL_SUCCESS && wipe_cache) {
851 ui->Print("\n-- Wiping cache (at package request)...\n");
852 if (erase_volume("/cache")) {
853 ui->Print("Cache wipe failed.\n");
854 } else {
855 ui->Print("Cache wipe complete.\n");
856 }
857 }
858 if (status >= 0) {
859 if (status != INSTALL_SUCCESS) {
860 ui->SetBackground(RecoveryUI::ERROR);
861 ui->Print("Installation aborted.\n");
862 } else if (!ui->IsTextVisible()) {
863 return Device::NO_ACTION; // reboot if logs aren't visible
864 } else {
865 ui->Print("\nInstall from cache complete.\n");
866 }
867 }
868 break; 850 break;
869 851
870 case Device::APPLY_ADB_SIDELOAD: 852 case Device::APPLY_ADB_SIDELOAD: