void show_nandroid_restore_menu()
{
    const char* sdcard_path;
    char* backup_path[PATH_MAX];

    if (target_sdcard == TARGET_INTERNAL_SDCARD) {
        sdcard_path = INTERNAL_SDCARD_PATH;
    } else {
        sdcard_path = EXTERNAL_SDCARD_PATH;
    }

    if (ensure_path_mounted(sdcard_path) != 0) {
        LOGE ("Can't mount %s\n", sdcard_path);
        return;
    }

    static char* headers[] = {  "Choose an image to restore",
                                "",
                                NULL
    };

    sprintf(backup_path, "%s/clockworkmod/backup/", sdcard_path);
    char* file = choose_file_menu(backup_path, NULL, headers);
    if (file == NULL)
        return;

    if (confirm_selection("Confirm restore?", "Yes - Restore"))
        nandroid_restore(file, 1, 1, 1, 1, 1, 0);
}
Beispiel #2
0
static int
cmd_restore_rom(const char *name, void *cookie, int argc, const char *argv[],
        PermissionRequestList *permissions)
{
    UNUSED(cookie);
    CHECK_WORDS();

    int restoreboot = 1;
    int restoresystem = 1;
    int restoredata = 1;
    int restorecache = 1;
    int restoresdext = 1;
    int i;
    for (i = 0; i < argc; i++)
    {
        if (strcmp(argv[i], "noboot") == 0)
            restoreboot = 0;
        else if (strcmp(argv[i], "nosystem") == 0)
            restoresystem = 0;
        else if (strcmp(argv[i], "nodata") == 0)
            restoredata = 0;
        else if (strcmp(argv[i], "nocache") == 0)
            restorecache = 0;
        else if (strcmp(argv[i], "nosd-ext") == 0)
            restorecache = 0;
    }

    return nandroid_restore(argv[0], restoreboot, restoresystem, restoredata, restorecache, restoresdext);
}
Beispiel #3
0
int nandroid_main(int argc, char** argv) {
    load_volume_table();
    char backup_path[PATH_MAX];

    if (argc > 3 || argc < 2)
        return nandroid_usage();

    if (strcmp("backup", argv[1]) == 0) {
        if (argc != 2)
            return nandroid_usage();

        nandroid_generate_timestamp_path(backup_path);
        return nandroid_backup(backup_path);
    }

    if (strcmp("restore", argv[1]) == 0) {
        if (argc != 3)
            return nandroid_usage();
        return nandroid_restore(argv[2], 1, 1, 1, 1, 1, 0);
    }

    if (strcmp("dump", argv[1]) == 0) {
        if (argc != 3)
            return nandroid_usage();
        return nandroid_dump(argv[2]);
    }

    if (strcmp("undump", argv[1]) == 0) {
        if (argc != 3)
            return nandroid_usage();
        return nandroid_undump(argv[2]);
    }

    return nandroid_usage();
}
/*package nandroid_restore(const char* backup_path, restore_boot, restore_system, restore_data,
 *                         restore_cache, restore_sdext, restore_wimax);
 *INTENT_RESTORE
 *intent_restore(argc, argv[0],...,argv[6])
 */
static intentResult* intent_restore(int argc, char* argv[])
{
    return_intent_result_if_fail(argc == 7);
    return_intent_result_if_fail(argv != NULL);
    int result = nandroid_restore(argv[0], atoi(argv[1]), atoi(argv[2]), atoi(argv[3]),
                                  atoi(argv[4]), atoi(argv[5]), atoi(argv[6]));
    assert_ui_if_fail(result == 0);
    return miuiIntent_result_set(result, NULL);
}
Value* RestoreFn(const char* name, State* state, int argc, Expr* argv[]) {
    if (argc < 1) {
        return ErrorAbort(state, "%s() expects at least 1 arg", name);
    }
    char** args = ReadVarArgs(state, argc, argv);
    if (args == NULL) {
        return NULL;
    }

    char** args2 = malloc(sizeof(char*) * (argc+1));
    memcpy(args2, args, sizeof(char*) * argc);
    args2[argc] = NULL;
    
    char* path = strdup(args2[0]);
    int restoreboot = 1;
    int restoresystem = 1;
    int restoredata = 1;
    int restorecache = 1;
    int restoresdext = 1;
    int restorewebtop = 1;
    int i;
    for (i = 1; i < argc; i++)
    {
        if (args2[i] == NULL)
            continue;
        if (strcmp(args2[i], "noboot") == 0)
            restoreboot = 0;
        else if (strcmp(args2[i], "nosystem") == 0)
            restoresystem = 0;
        else if (strcmp(args2[i], "nodata") == 0)
            restoredata = 0;
        else if (strcmp(args2[i], "nocache") == 0)
            restorecache = 0;
        else if (strcmp(args2[i], "nosd-ext") == 0)
            restoresdext = 0;
        else if (strcmp(args2[i], "nowebtop") == 0)
            restorewebtop = 0;
    }
    
    for (i = 0; i < argc; ++i) {
        free(args[i]);
    }
    free(args);
    free(args2);

    if (0 != nandroid_restore(path, restoreboot, restoresystem, restoredata, restorecache, restoresdext, 0, restorewebtop, 0)) {
        free(path);
        return StringValue(strdup(""));
    }
    
    return StringValue(path);
}
void process_volumes() {
    create_fstab();

    if (is_data_media()) {
        setup_data_media();
    }

    return;

    // dead code.
    if (device_flash_type() != BML)
        return;

    ui_print("Checking for ext4 partitions...\n");
    int ret = 0;
    ret = bml_check_volume("/system");
    ret |= bml_check_volume("/data");
    if (has_datadata())
        ret |= bml_check_volume("/datadata");
    ret |= bml_check_volume("/cache");
    
    if (ret == 0) {
        ui_print("Done!\n");
        return;
    }
    
    char backup_path[PATH_MAX];
    //time_t t = time(NULL);
    char backup_name[PATH_MAX];
    struct timeval tp;
    gettimeofday(&tp, NULL);
    sprintf(backup_name, "before-ext4-convert-%d", tp.tv_sec);
    if (target_sdcard == TARGET_INTERNAL_SDCARD) {
        sprintf(backup_path, INTERNAL_SDCARD_PATH "/clockworkmod/backup/%s", backup_name);
    } else {
        sprintf(backup_path, EXTERNAL_SDCARD_PATH "/clockworkmod/backup/%s", backup_name);
    }

    ui_set_show_text(1);
    ui_print("Filesystems need to be converted to ext4.\n");
    ui_print("A backup and restore will now take place.\n");
    ui_print("If anything goes wrong, your backup will be\n");
    ui_print("named %s. Try restoring it\n", backup_name);
    ui_print("in case of error.\n");

    nandroid_backup(backup_path);
    nandroid_restore(backup_path, 1, 1, 1, 1, 1, 0);
    ui_set_show_text(0);
}
void show_nandroid_restore_menu(const char* volume)
{
    if (ensure_path_mounted(volume) != 0) {
        LOGE ("Can't mount %s\n", volume);
        return;
    }

    int restore_webtop = 1;
    static char* headers[] = {  "Choose an image to restore",
                                "",
                                NULL
    };

    char backup_path[PATH_MAX];
    sprintf(backup_path, "%s/clockworkmod/backup/", volume);
    char* file = choose_file_menu(backup_path, NULL, headers);
    if (file == NULL)
        return;

#ifdef BOARD_HAS_WEBTOP
    static char* header[] = {  "Include webtop in restore?",
                               "",
                               NULL
    };

    static char* list[] = {  "Yes",
                             "No",
                             NULL
    };

    switch (get_menu_selection(header, list, 0, 0))
    {
        case 0:
            restore_webtop = 1;
            break;
        case 1:
            restore_webtop = 0;
            break;
        default:
            return;
    }
#endif

    if (confirm_selection("Confirm restore?", "Yes - Restore"))
        nandroid_restore(file, 1, 1, 1, 1, restore_webtop, 0, restore_webtop, 0);
}
void process_volumes() {
    create_fstab();

    if (is_data_media()) {
        setup_data_media();
    }

    return;

    // dead code.
    if (device_flash_type() != BML)
        return;

    ui_print("正在校验 EXT4 分区...\n");
    int ret = 0;
    ret = bml_check_volume("/system");
    ret |= bml_check_volume("/data");
    if (has_datadata())
        ret |= bml_check_volume("/datadata");
    ret |= bml_check_volume("/cache");
    
    if (ret == 0) {
        ui_print("校验完成!\n");
        return;
    }
    
    char backup_path[PATH_MAX];
    time_t t = time(NULL);
    char backup_name[PATH_MAX];
    struct timeval tp;
    gettimeofday(&tp, NULL);
    sprintf(backup_name, "before-ext4-convert-%d", tp.tv_sec);
    sprintf(backup_path, "/sdcard/clockworkmod/backup/%s", backup_name);

    ui_set_show_text(1);
    ui_print("文件系统将会被转换为 EXT4格式.\n");
    ui_print("将会进行备份和恢复操作.\n");
    ui_print("如果出现错误你可以恢复\n");
    ui_print("文件名为%s的备份\n", backup_name);
    ui_print("在错误的情况下.\n");

    nandroid_backup(backup_path);
    nandroid_restore(backup_path, 1, 1, 1, 1, 1, 0);
    ui_set_show_text(0);
}
void show_nandroid_restore_menu()
{
    if (ensure_path_mounted("/sdcard") != 0) {
        LOGE ("Can't mount /sdcard\n");
        return;
    }

    static char* headers[] = {  "Choose an image to restore",
                                "",
                                NULL
    };

    char* file = choose_file_menu("/sdcard/clockworkmod/backup/", NULL, headers);
    if (file == NULL)
        return;

    if (confirm_selection("Confirm restore?", "Yes - Restore"))
        nandroid_restore(file, 1, 1, 1, 1, 1, 0);
}
void show_nandroid_restore_menu(const char* path)
{
    if (ensure_path_mounted(path) != 0) {
        LOGE("无法挂载 %s\n", path);
        return;
    }

    static char* headers[] = {  "选择恢复镜像",
                                "",
                                NULL
    };

    char tmp[PATH_MAX];
    sprintf(tmp, "%s/clockworkmod/backup/", path);
    char* file = choose_file_menu(tmp, NULL, headers);
    if (file == NULL)
        return;

    if (confirm_selection("确认恢复?", "是 - 恢复"))
        nandroid_restore(file, 1, 1, 1, 1, 1, 0);
}
void show_nandroid_restore_menu(const char* path)
{
    if (ensure_path_mounted(path) != 0) {
        LOGE("Can't mount %s\n", path);
        return;
    }

    static char* headers[] = {  "Choose an image to restore",
                                "",
                                NULL
    };

    char tmp[PATH_MAX];
    sprintf(tmp, "%s/clockworkmod/backup/", path);
    char* file = choose_file_menu(tmp, NULL, headers);
    if (file == NULL)
        return;

    if (confirm_selection("Confirm restore?", "Yes - Restore"))
        nandroid_restore(file, 1, 1, 1, 1, 1, 0);
}
void show_nandroid_advanced_restore_menu(const char* volume)
{
    if (ensure_path_mounted(volume) != 0) {
        LOGE ("Can't mount %s\n", volume);
        return;
    }

    static char* advancedheaders[] = {  "Choose an image to restore",
                                "",
                                "Choose an image to restore",
                                "first. The next menu will",
                                "give you more options.",
                                "",
                                NULL
    };

    char backup_path[PATH_MAX];
    sprintf(backup_path, "%s/clockworkmod/backup/", volume);
    char* file = choose_file_menu(backup_path, NULL, advancedheaders);
    if (file == NULL)
        return;

    static char* headers[] = {  "Nandroid Advanced Restore",
                                "",
                                NULL
    };

    char* list[] = { "Restore boot",
                     "Restore system",
                     "Restore data",
                     "Restore cache",
                     "Restore sd-ext",
                     "Restore wimax",
                     "Restore webtop",
                     "Restore PDS",
                     NULL
    };
    int num_menu_items = 8;
    int webtop = 6, pds = 7;
    int webtop_offset = 0, pds_offset = 0;
    int i;

    char tmp[PATH_MAX];
    if (0 != get_partition_device("wimax", tmp)) {
        // disable wimax restore option
        list[5] = NULL;
        webtop_offset--;
        pds_offset--;
    }
    if (volume_for_path("/osh") == NULL) {
        // disable webtop restore option
        list[6] = NULL;
        pds_offset--;
    }
    if (volume_for_path("/pds") == NULL) {
        // disable PDS restore option
        list[7] = NULL;
    }
    for (i = 5; i < num_menu_items; i++)
        if ((list[i] == NULL) && (list[i+1] != NULL)) {
            list[i] = list[i+1];
            list[i+1] = NULL;
        }

    static char* confirm_restore  = "Confirm restore?";

    int chosen_item = get_menu_selection(headers, list, 0, 0);
    if ((chosen_item >= 0) && (chosen_item <= 4)) {
        switch (chosen_item)
        {
            case 0:
                if (confirm_selection(confirm_restore, "Yes - Restore boot"))
                    nandroid_restore(file, 1, 0, 0, 0, 0, 0, 0, 0);
                break;
            case 1:
                if (confirm_selection(confirm_restore, "Yes - Restore system"))
                    nandroid_restore(file, 0, 1, 0, 0, 0, 0, 0, 0);
                break;
            case 2:
                if (confirm_selection(confirm_restore, "Yes - Restore data"))
                    nandroid_restore(file, 0, 0, 1, 0, 0, 0, 0, 0);
                break;
            case 3:
                if (confirm_selection(confirm_restore, "Yes - Restore cache"))
                    nandroid_restore(file, 0, 0, 0, 1, 0, 0, 0, 0);
                break;
            case 4:
                if (confirm_selection(confirm_restore, "Yes - Restore sd-ext"))
                    nandroid_restore(file, 0, 0, 0, 0, 1, 0, 0, 0);
                break;
        }
    } else if ((webtop_offset == 0) && (pds_offset == 0) && (chosen_item >= 5) && (chosen_item <= 7)) {
        switch (chosen_item)
        {
            case 5:
                if (confirm_selection(confirm_restore, "Yes - Restore wimax"))
                    nandroid_restore(file, 0, 0, 0, 0, 0, 1, 0, 0);
                break;
            case 6:
                if (confirm_selection(confirm_restore, "Yes - Restore webtop"))
                    nandroid_restore(file, 0, 0, 0, 0, 0, 0, 1, 0);
                break;
            case 7:
                if (confirm_selection(confirm_restore, "Yes - Restore PDS"))
                    nandroid_restore(file, 0, 0, 0, 0, 0, 0, 0, 1);
                break;
        }
     } else if ((chosen_item >= 5) && (chosen_item < 7)) {
        if (chosen_item == (pds + pds_offset)) {
            if (confirm_selection(confirm_restore, "Yes - Restore PDS"))
                nandroid_restore(file, 0, 0, 0, 0, 0, 0, 0, 1);
        } else if (chosen_item == (webtop + webtop_offset)) {
            if (confirm_selection(confirm_restore, "Yes - Restore webtop"))
                nandroid_restore(file, 0, 0, 0, 0, 0, 0, 1, 0);
        }
    }
}
void show_nandroid_advanced_restore_menu(int f_nandroid)
{
    if (ensure_root_path_mounted("SDCARD:") != 0) {
        LOGE ("Can't mount /sdcard\n");
        return;
    }

    static char* advancedheaders[] = {  "Choose an image to restore",
                                "",
                                "Choose an image to restore",
                                "first. The next menu will",
                                "you more options.",
                                "",
                                NULL
    };

    char* file = choose_file_menu(f_nandroid?"/sdcard/ebrecovery/backup/":"/sdcard/ebrecovery/backup/", NULL, advancedheaders);
    if (file == NULL)
        return;

    static char* headers[] = {  "Nandroid Advanced Restore",
                                "",
                                NULL
    };

    static char* list[] = { "Restore system",
                            "Restore data",
                            "Restore cache",
                            "Restore sd-ext",
                            NULL
    };


    static char* confirm_restore  = "Confirm restore?";

    int chosen_item = get_menu_selection(headers, list, 0);
    switch (chosen_item)
    {
        case 0:
            if (confirm_selection(confirm_restore, "Yes - Restore system")) {
                if (f_nandroid)
                	nandroid_restore(file, 0, 1, 0, 0, 0);
                else
                	tarbackup_restore(file, 1, 0, 0, 0);
            }
            break;
        case 1:
            if (confirm_selection(confirm_restore, "Yes - Restore data")) {
                if (f_nandroid)
                	nandroid_restore(file, 0, 0, 1, 0, 0);
                else
                	tarbackup_restore(file, 0, 1, 0, 0);
            }
            break;
        case 2:
            if (confirm_selection(confirm_restore, "Yes - Restore cache")) {
                if (f_nandroid)
                	nandroid_restore(file, 0, 0, 0, 1, 0);
                else
                	tarbackup_restore(file, 0, 0, 1, 0);
            }
            break;
        case 3:
            if (confirm_selection(confirm_restore, "Yes - Restore sd-ext")) {
                if (f_nandroid)
                	nandroid_restore(file, 0, 0, 0, 0, 1);
                else
                	tarbackup_restore(file, 0, 0, 0, 1);
            }
            break;
    }
}
void show_nandroid_advanced_restore_menu(const char* path)
{
    if (ensure_path_mounted(path) != 0) {
        LOGE ("无法挂载 sdcard\n");
        return;
    }

    static char* advancedheaders[] = {  "选择恢复镜像",
                                "",
                                "先选择一个需要恢复的镜像",
                                "下级菜单",
                                "将会显示更多选项",
                                "",
                                NULL
    };

    char tmp[PATH_MAX];
    sprintf(tmp, "%s/clockworkmod/backup/", path);
    char* file = choose_file_menu(tmp, NULL, advancedheaders);
    if (file == NULL)
        return;

    static char* headers[] = {  "高级恢复",
                                "",
                                NULL
    };

    static char* list[] = { "恢复 boot",
                            "恢复 system",
                            "恢复 data",
                            "恢复 cache",
                            "恢复 sd-ext",
                            "恢复 wimax",
                            NULL
    };
    
    if (0 != get_partition_device("wimax", tmp)) {
        // disable wimax restore option
        list[5] = NULL;
    }

    static char* confirm_restore  = "确认恢复?";

    int chosen_item = get_menu_selection(headers, list, 0, 0);
    switch (chosen_item)
    {
        case 0:
            if (confirm_selection(confirm_restore, "是 - 恢复 boot"))
                nandroid_restore(file, 1, 0, 0, 0, 0, 0);
            break;
        case 1:
            if (confirm_selection(confirm_restore, "是 - 恢复 system"))
                nandroid_restore(file, 0, 1, 0, 0, 0, 0);
            break;
        case 2:
            if (confirm_selection(confirm_restore, "是 - 恢复 data"))
                nandroid_restore(file, 0, 0, 1, 0, 0, 0);
            break;
        case 3:
            if (confirm_selection(confirm_restore, "是 - 恢复 cache"))
                nandroid_restore(file, 0, 0, 0, 1, 0, 0);
            break;
        case 4:
            if (confirm_selection(confirm_restore, "是 - 恢复 sd-ext"))
                nandroid_restore(file, 0, 0, 0, 0, 1, 0);
            break;
        case 5:
            if (confirm_selection(confirm_restore, "是 - 恢复 wimax"))
                nandroid_restore(file, 0, 0, 0, 0, 0, 1);
            break;
    }
}
void show_nandroid_advanced_restore_menu()
{
    const char* sdcard_path;
    char* backup_path[PATH_MAX];

    if (target_sdcard == TARGET_INTERNAL_SDCARD) {
        sdcard_path = INTERNAL_SDCARD_PATH;
    } else {
        sdcard_path = EXTERNAL_SDCARD_PATH;
    }

    if (ensure_path_mounted(sdcard_path) != 0) {
        LOGE ("Can't mount %s\n", sdcard_path);
        return;
    }

    static char* advancedheaders[] = {  "Choose an image to restore",
                                "",
                                "Choose an image to restore",
                                "first. The next menu will",
                                "you more options.",
                                "",
                                NULL
    };

    sprintf(backup_path, "%s/clockworkmod/backup/", sdcard_path);
    char* file = choose_file_menu(backup_path, NULL, advancedheaders);
    if (file == NULL)
        return;

    static char* headers[] = {  "Nandroid Advanced Restore",
                                "",
                                NULL
    };

    static char* list[] = { "Restore boot",
                            "Restore system",
                            "Restore data",
                            "Restore cache",
#ifdef RECOVERY_HAVE_SD_EXT
                            "Restore sd-ext",
#endif
                            "Restore wimax",
                            NULL
    };
    
    char tmp[PATH_MAX];
    if (0 != get_partition_device("wimax", tmp)) {
        // disable wimax restore option
        list[5] = NULL;
    }

    static char* confirm_restore  = "Confirm restore?";

    int chosen_item = get_menu_selection(headers, list, 0, 0);
    switch (chosen_item)
    {
        case 0:
            if (confirm_selection(confirm_restore, "Yes - Restore boot"))
                nandroid_restore(file, 1, 0, 0, 0, 0, 0);
            break;
        case 1:
            if (confirm_selection(confirm_restore, "Yes - Restore system"))
                nandroid_restore(file, 0, 1, 0, 0, 0, 0);
            break;
        case 2:
            if (confirm_selection(confirm_restore, "Yes - Restore data"))
                nandroid_restore(file, 0, 0, 1, 0, 0, 0);
            break;
        case 3:
            if (confirm_selection(confirm_restore, "Yes - Restore cache"))
                nandroid_restore(file, 0, 0, 0, 1, 0, 0);
            break;
#ifdef RECOVERY_HAVE_SD_EXT
        case 4:
            if (confirm_selection(confirm_restore, "Yes - Restore sd-ext"))
                nandroid_restore(file, 0, 0, 0, 0, 1, 0);
            break;
        case 5:
#else
		case 4:
#endif
            if (confirm_selection(confirm_restore, "Yes - Restore wimax"))
                nandroid_restore(file, 0, 0, 0, 0, 0, 1);
            break;
    }
}
void show_nandroid_advanced_restore_menu(const char* path)
{
    if (ensure_path_mounted(path) != 0) {
        LOGE ("Can't mount sdcard\n");
        return;
    }

    static char* advancedheaders[] = {  "Choose an image to restore",
                                "",
                                "Choose an image to restore",
                                "first. The next menu will",
                                "show you more options.",
                                "",
                                NULL
    };

    char tmp[PATH_MAX];
    sprintf(tmp, "%s/clockworkmod/backup/", path);
    char* file = choose_file_menu(tmp, NULL, advancedheaders);
    if (file == NULL)
        return;

    static char* headers[] = {  "Advanced Restore",
                                "",
                                NULL
    };

    static char* list[] = { "Restore boot",
                            "Restore system",
                            "Restore data",
                            "Restore cache",
                            "Restore sd-ext",
                            "Restore wimax",
                            NULL
    };
    
    if (0 != get_partition_device("wimax", tmp)) {
        // disable wimax restore option
        list[5] = NULL;
    }

    static char* confirm_restore  = "Confirm restore?";

    int chosen_item = get_menu_selection(headers, list, 0, 0);
    switch (chosen_item)
    {
        case 0:
            if (confirm_selection(confirm_restore, "Yes - Restore boot"))
                nandroid_restore(file, 1, 0, 0, 0, 0, 0);
            break;
        case 1:
            if (confirm_selection(confirm_restore, "Yes - Restore system"))
                nandroid_restore(file, 0, 1, 0, 0, 0, 0);
            break;
        case 2:
            if (confirm_selection(confirm_restore, "Yes - Restore data"))
                nandroid_restore(file, 0, 0, 1, 0, 0, 0);
            break;
        case 3:
            if (confirm_selection(confirm_restore, "Yes - Restore cache"))
                nandroid_restore(file, 0, 0, 0, 1, 0, 0);
            break;
        case 4:
            if (confirm_selection(confirm_restore, "Yes - Restore sd-ext"))
                nandroid_restore(file, 0, 0, 0, 0, 1, 0);
            break;
        case 5:
            if (confirm_selection(confirm_restore, "Yes - Restore wimax"))
                nandroid_restore(file, 0, 0, 0, 0, 0, 1);
            break;
    }
}
int do_lagfix(int do_fr) {
  ui_print("old config was:\n");
  ui_print_file("/system/etc/lagfix.conf.old");
  ui_print("new config is:\n");
  ui_print_file("/system/etc/lagfix.conf");
  ui_print("checking mounts available\n");
  if (ensure_root_path_mounted("DATA:")!=0) return -1;
  if (ensure_root_path_mounted("DATADATA:")!=0) return -1;
  if (ensure_root_path_mounted("CACHE:")!=0) return -1;
  if (ensure_root_path_mounted("SDCARD:")!=0) return -1;

  char tmp[PATH_MAX];
  nandroid_generate_timestamp_path(tmp);
  if (do_fr!=2) {
    ui_print("Creating a nandroid backup at %s\n",tmp);
    if (nandroid_backup_flags(tmp,DONT_BACKUP_SYSTEM)!=0) return -1;
  } else {
    ui_print("Not creating a backup\n");
  }

  ui_print("Backup completed, recreating file systems\n");

  ui_print("Unmounting\n");
  unmount_all_lagfixed();

  ui_print("Switching to new config\n");
  __system("cp /system/etc/lagfix.conf /system/etc/lagfix.conf.old");

  ui_print("Creating /data\n");
  create_lagfix_partition(0);
  ui_print("Creating /dbdata\n");
  create_lagfix_partition(1);
  ui_print("Creating /cache\n");
  create_lagfix_partition(2);

  ui_print("Mounting to test\n");
  dont_use_bind_options = 1;
  if (ensure_root_path_mounted("DATA:")!=0) return -1;
  if (ensure_root_path_mounted("DATADATA:")!=0) return -1;
  if (ensure_root_path_mounted("CACHE:")!=0) return -1;
  dont_use_bind_options = 0;
  __system("mount"); // for debug purposes
  if (get_bind_options()) {
    ui_print("Creating bind directories\n");
    __system("mkdir -p /dbdata/.data/data");
    __system("mkdir -p /data/data");
  }

  ui_print("Unmounting again\n");
  unmount_all_lagfixed();

  if (do_fr) {
    ui_print("Factory reset was requested, not restoring backed up data\n");
  } else {
    ui_print("Restoring data\n");
    nandroid_restore(tmp,0,0,1,1,0);
    // restore might have brought some .data into dbdata, clear them
    if (!get_bind_options()) {
      if (ensure_root_path_mounted("DATADATA:")!=0) return -1;
      __system("rm -rf /dbdata/.data");
    }
  }

  __system("mount");
  ui_print("Unmounting again to be sure\n");
  sync();
  sleep(5);
  unmount_all_lagfixed();
  sync();
  return 0;
}