void prompt_and_wait() { char** headers = prepend_title((const char**)MENU_HEADERS); for (;;) { finish_recovery(NULL); ui_reset_progress(); int chosen_item = get_menu_selection(headers, MENU_ITEMS, 0, 0); // device-specific code may take some action here. It may // return one of the core actions handled in the switch // statement below. chosen_item = device_perform_action(chosen_item); switch (chosen_item) { case ITEM_REBOOT: return; case ITEM_WIPE_DATA: wipe_data(ui_text_visible()); if (!ui_text_visible()) return; break; case ITEM_WIPE_CACHE: printf("\n-- Wiping cache...\n"); erase_volume("/cache"); printf("Cache wipe complete.\n"); if (!ui_text_visible()) return; break; case ITEM_APPLY_SDCARD: ; int status = sdcard_directory(SDCARD_ROOT); if (status >= 0) { if (status != INSTALL_SUCCESS) { ui_set_background(BACKGROUND_ICON_ERROR); printf("Installation aborted.\n"); } else if (!ui_text_visible()) { return; // reboot if logs aren't visible } else { printf("\nInstall from sdcard complete.\n"); } } break; } } }
int sdcard_directory(const char* path) { ensure_path_mounted(SDCARD_ROOT); const char* MENU_HEADERS[] = { "Choose a package to install:", path, NULL }; DIR* d; struct dirent* de; d = opendir(path); if (d == NULL) { LOGE("error opening %s: %s\n", path, strerror(errno)); ensure_path_unmounted(SDCARD_ROOT); return 0; } char** headers = prepend_title(MENU_HEADERS); int s_size = 0; int s_alloc = 10; char** sele = malloc(s_alloc * sizeof(char*)); int d_size = 0; int d_alloc = 10; char** dirs = malloc(d_alloc * sizeof(char*)); int z_size = 0; int z_alloc = 10; char** zips = malloc(z_alloc * sizeof(char*)); if (get_new_zip_dir == 1) { sele[0] = strdup("[SELECT CURRENT FOLDER]"); s_size++; } sele[s_size] = strdup("../"); inc_menu_loc(s_size); s_size++; while ((de = readdir(d)) != NULL) { int name_len = strlen(de->d_name); if (de->d_type == DT_DIR) { // skip "." and ".." entries if (name_len == 1 && de->d_name[0] == '.') continue; if (name_len == 2 && de->d_name[0] == '.' && de->d_name[1] == '.') continue; if (d_size >= d_alloc) { d_alloc *= 2; dirs = realloc(dirs, d_alloc * sizeof(char*)); } dirs[d_size] = malloc(name_len + 2); strcpy(dirs[d_size], de->d_name); dirs[d_size][name_len] = '/'; dirs[d_size][name_len+1] = '\0'; ++d_size; } else if (de->d_type == DT_REG && name_len >= 4 && strncasecmp(de->d_name + (name_len-4), ".zip", 4) == 0) { if (z_size >= z_alloc) { z_alloc *= 2; zips = realloc(zips, z_alloc * sizeof(char*)); } zips[z_size++] = strdup(de->d_name); } } closedir(d); notError = 0; qsort(dirs, d_size, sizeof(char*), compare_string); qsort(zips, z_size, sizeof(char*), compare_string); // append dirs to the zips list if (d_size + z_size + 1 > z_alloc) { z_alloc = d_size + z_size + 1; zips = realloc(zips, z_alloc * sizeof(char*)); } memcpy(zips + z_size, dirs, d_size * sizeof(char*)); free(dirs); z_size += d_size; zips[z_size] = NULL; if (z_size + s_size + 1 > s_alloc) { s_alloc = z_size + s_size + 1; sele = realloc(sele, s_alloc * sizeof(char*)); } memcpy(sele + s_size, zips, z_size * sizeof(char*)); s_size += z_size; sele[s_size] = NULL; int result; int chosen_item = 0; do { chosen_item = get_menu_selection(headers, sele, 1, chosen_item); char* item = sele[chosen_item]; int item_len = strlen(item); if (chosen_item == 0) { // item 0 is always "../" // go up but continue browsing (if the caller is sdcard_directory) if (get_new_zip_dir == 1) { strcpy(tw_zip_location_val,path); write_s_file(); return 1; } else { dec_menu_loc(); result = -1; break; } } else if (chosen_item == 1 && get_new_zip_dir == 1) { dec_menu_loc(); result = -1; break; } else if (item[item_len-1] == '/') { // recurse down into a subdirectory char new_path[PATH_MAX]; strlcpy(new_path, path, PATH_MAX); strlcat(new_path, "/", PATH_MAX); strlcat(new_path, item, PATH_MAX); new_path[strlen(new_path)-1] = '\0'; // truncate the trailing '/' result = sdcard_directory(new_path); if (go_home) { notError = 1; dec_menu_loc(); if (get_new_zip_dir == 1) { return 1; } else { return 0; } } if (result >= 0) break; } else { if (get_new_zip_dir != 1) { // selected a zip file: attempt to install it, and return // the status to the caller. char new_path[PATH_MAX]; strlcpy(new_path, path, PATH_MAX); strlcat(new_path, "/", PATH_MAX); strlcat(new_path, item, PATH_MAX); ui_print("\n-- Install %s ...\n", path); set_sdcard_update_bootloader_message(); char* copy = copy_sideloaded_package(new_path); ensure_path_unmounted(SDCARD_ROOT); if (copy) { result = install_package(copy); free(copy); } else { result = INSTALL_ERROR; } break; } } } while (true); free(zips); free(sele); free(headers); //ensure_path_unmounted(SDCARD_ROOT); return result; }