diff --git a/source/ui/section/action/deleteallpendingtitles.c b/source/ui/section/action/deleteallpendingtitles.c deleted file mode 100644 index e7d4b89..0000000 --- a/source/ui/section/action/deleteallpendingtitles.c +++ /dev/null @@ -1,128 +0,0 @@ -#include -#include - -#include <3ds.h> - -#include "action.h" -#include "../../error.h" -#include "../../progressbar.h" -#include "../../prompt.h" -#include "../../../screen.h" -#include "../task/task.h" - -typedef struct { - pending_title_info* info; - bool* populated; - - u64* titleIds; - u32 processed; - u32 total; - - u32 sdTotal; - u32 nandTotal; -} delete_pending_titles_data; - -static void action_delete_pending_titles_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2) { - delete_pending_titles_data* deleteData = (delete_pending_titles_data*) data; - - if(deleteData->info != NULL) { - ui_draw_pending_title_info(view, deleteData->info, x1, y1, x2, y2); - } -} - -static void action_delete_pending_titles_free_data(delete_pending_titles_data* data) { - free(data->titleIds); - free(data); -} - -static void action_delete_pending_titles_success_onresponse(ui_view* view, void* data, bool response) { - prompt_destroy(view); - - action_delete_pending_titles_free_data((delete_pending_titles_data*) data); -} - -static void action_delete_pending_titles_update(ui_view* view, void* data, float* progress, char* progressText) { - delete_pending_titles_data* deleteData = (delete_pending_titles_data*) data; - - if(deleteData->processed >= deleteData->total) { - progressbar_destroy(view); - ui_pop(); - - ui_push(prompt_create("Success", "Pending title(s) deleted.", COLOR_TEXT, false, data, NULL, action_delete_pending_titles_draw_top, action_delete_pending_titles_success_onresponse)); - return; - } else { - Result res = AM_DeletePendingTitle(deleteData->processed >= deleteData->sdTotal ? MEDIATYPE_NAND : MEDIATYPE_SD, deleteData->titleIds[deleteData->processed]); - if(R_FAILED(res)) { - progressbar_destroy(view); - ui_pop(); - - error_display_res(NULL, deleteData->info, deleteData->info != NULL ? ui_draw_pending_title_info : NULL, res, "Failed to delete pending title(s)."); - - action_delete_pending_titles_free_data(deleteData); - - return; - } else { - *deleteData->populated = false; - - deleteData->processed++; - } - } - - *progress = deleteData->total > 0 ? (float) deleteData->processed / (float) deleteData->total : 0; - snprintf(progressText, PROGRESS_TEXT_MAX, "%lu / %lu", deleteData->processed, deleteData->total); -} - -static void action_delete_pending_titles_onresponse(ui_view* view, void* data, bool response) { - prompt_destroy(view); - - if(response) { - ui_push(progressbar_create("Deleting Pending Title(s)", "", data, action_delete_pending_titles_update, action_delete_pending_titles_draw_top)); - } else { - action_delete_pending_titles_free_data((delete_pending_titles_data*) data); - } -} - -void action_delete_pending_title(pending_title_info* info, bool* populated) { - delete_pending_titles_data* data = (delete_pending_titles_data*) calloc(1, sizeof(delete_pending_titles_data)); - data->info = info; - data->populated = populated; - data->titleIds = (u64*) calloc(1, sizeof(u64)); - data->titleIds[0] = info->titleId; - data->processed = 0; - data->total = 1; - data->sdTotal = info->mediaType == MEDIATYPE_SD ? 1 : 0; - data->nandTotal = info->mediaType == MEDIATYPE_NAND ? 1 : 0; - - ui_push(prompt_create("Confirmation", "Delete the selected pending title?", COLOR_TEXT, true, data, NULL, action_delete_pending_titles_draw_top, action_delete_pending_titles_onresponse)); -} - -void action_delete_all_pending_titles(pending_title_info* info, bool* populated) { - delete_pending_titles_data* data = (delete_pending_titles_data*) calloc(1, sizeof(delete_pending_titles_data)); - data->info = NULL; - data->populated = populated; - data->titleIds = NULL; - data->processed = 0; - data->total = 0; - data->sdTotal = 0; - data->nandTotal = 0; - - Result res = 0; - if(R_FAILED(res = AM_GetPendingTitleCount(&data->sdTotal, MEDIATYPE_SD, AM_STATUS_MASK_INSTALLING | AM_STATUS_MASK_AWAITING_FINALIZATION)) || R_FAILED(res = AM_GetPendingTitleCount(&data->nandTotal, MEDIATYPE_NAND, AM_STATUS_MASK_INSTALLING | AM_STATUS_MASK_AWAITING_FINALIZATION))) { - error_display_res(NULL, NULL, NULL, res, "Failed to retrieve pending title count."); - - free(data); - return; - } - - data->total = data->sdTotal + data->nandTotal; - data->titleIds = (u64*) calloc(data->total, sizeof(u64)); - if(R_FAILED(res = AM_GetPendingTitleList(&data->sdTotal, data->sdTotal, MEDIATYPE_SD, AM_STATUS_MASK_INSTALLING | AM_STATUS_MASK_AWAITING_FINALIZATION, data->titleIds)) || R_FAILED(res = AM_GetPendingTitleList(&data->nandTotal, data->nandTotal, MEDIATYPE_NAND, AM_STATUS_MASK_INSTALLING | AM_STATUS_MASK_AWAITING_FINALIZATION, &data->titleIds[data->sdTotal]))) { - error_display_res(NULL, NULL, NULL, res, "Failed to retrieve pending title list."); - - free(data->titleIds); - free(data); - return; - } - - ui_push(prompt_create("Confirmation", "Delete all pending titles?", COLOR_TEXT, true, data, NULL, action_delete_pending_titles_draw_top, action_delete_pending_titles_onresponse)); -} \ No newline at end of file diff --git a/source/ui/section/action/deletecontents.c b/source/ui/section/action/deletecontents.c index c26d170..1b4bad6 100644 --- a/source/ui/section/action/deletecontents.c +++ b/source/ui/section/action/deletecontents.c @@ -10,21 +10,83 @@ #include "../../prompt.h" #include "../../../screen.h" #include "../../../util.h" +#include "../task/task.h" typedef struct { file_info* base; bool* populated; - u32 processed; - u32 total; char** contents; + + data_op_info deleteInfo; + Handle cancelEvent; } delete_contents_data; +static Result action_delete_contents_delete(void* data, u32 index) { + delete_contents_data* deleteData = (delete_contents_data*) data; + + FS_Path* fsPath = util_make_path_utf8(deleteData->contents[index]); + + Result res = 0; + if(util_is_dir(deleteData->base->archive, deleteData->contents[index])) { + res = FSUSER_DeleteDirectory(*deleteData->base->archive, *fsPath); + } else { + res = FSUSER_DeleteFile(*deleteData->base->archive, *fsPath); + } + + util_free_path_utf8(fsPath); + + return res; +} + +static bool action_delete_contents_result_error(void* data, u32 index, Result res) { + delete_contents_data* deleteData = (delete_contents_data*) data; + + if(res == MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_CANCEL_REQUESTED)) { + ui_push(prompt_create("Failure", "Delete cancelled.", COLOR_TEXT, false, deleteData->base, NULL, ui_draw_file_info, NULL)); + return false; + } else { + char* path = deleteData->contents[index]; + + volatile bool dismissed = false; + if(strlen(path) > 48) { + error_display_res(&dismissed, deleteData->base, ui_draw_file_info, res, "Failed to delete content.\n%.45s...", path); + } else { + error_display_res(&dismissed, deleteData->base, ui_draw_file_info, res, "Failed to delete content.\n%.48s", path); + } + + while(!dismissed) { + svcSleepThread(1000000); + } + } + + return index < deleteData->deleteInfo.total - 1; +} + +static bool action_delete_contents_io_error(void* data, u32 index, int err) { + delete_contents_data* deleteData = (delete_contents_data*) data; + + char* path = deleteData->contents[index]; + + volatile bool dismissed = false; + if(strlen(path) > 48) { + error_display_errno(&dismissed, deleteData->base, ui_draw_file_info, err, "Failed to delete content.\n%.45s...", path); + } else { + error_display_errno(&dismissed, deleteData->base, ui_draw_file_info, err, "Failed to delete content.\n%.48s", path); + } + + while(!dismissed) { + svcSleepThread(1000000); + } + + return index < deleteData->deleteInfo.total - 1; +} + static void action_delete_contents_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2) { ui_draw_file_info(view, ((delete_contents_data*) data)->base, x1, y1, x2, y2); } static void action_delete_contents_free_data(delete_contents_data* data) { - util_free_contents(data->contents, data->total); + util_free_contents(data->contents, data->deleteInfo.total); free(data); } @@ -37,142 +99,91 @@ static void action_delete_contents_done_onresponse(ui_view* view, void* data, bo static void action_delete_contents_update(ui_view* view, void* data, float* progress, char* progressText) { delete_contents_data* deleteData = (delete_contents_data*) data; + if(deleteData->deleteInfo.finished) { + *deleteData->populated = false; + + if(deleteData->base->archive->id == ARCHIVE_USER_SAVEDATA) { + FSUSER_ControlArchive(*deleteData->base->archive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0); + } + + progressbar_destroy(view); + ui_pop(); + + if(deleteData->deleteInfo.premature) { + action_delete_contents_free_data(deleteData); + } else { + ui_push(prompt_create("Success", "Contents deleted.", COLOR_TEXT, false, data, NULL, action_delete_contents_draw_top, action_delete_contents_done_onresponse)); + } + + return; + } + if(hidKeysDown() & KEY_B) { - progressbar_destroy(view); - ui_pop(); - - ui_push(prompt_create("Failure", "Delete cancelled.", COLOR_TEXT, false, data, NULL, action_delete_contents_draw_top, action_delete_contents_done_onresponse)); - return; + svcSignalEvent(deleteData->cancelEvent); } - if(deleteData->processed >= deleteData->total) { - progressbar_destroy(view); - ui_pop(); - - ui_push(prompt_create("Success", "Contents deleted.", COLOR_TEXT, false, data, NULL, action_delete_contents_draw_top, action_delete_contents_done_onresponse)); - return; - } else { - FS_Archive* archive = deleteData->base->archive; - char* path = deleteData->contents[deleteData->processed]; - - FS_Path* fsPath = util_make_path_utf8(path); - - Result res = 0; - if(util_is_dir(archive, path)) { - res = FSUSER_DeleteDirectory(*archive, *fsPath); - } else { - res = FSUSER_DeleteFile(*archive, *fsPath); - } - - util_free_path_utf8(fsPath); - - if(R_SUCCEEDED(res) && archive->id == ARCHIVE_USER_SAVEDATA) { - res = FSUSER_ControlArchive(*archive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0); - } - - if(R_FAILED(res)) { - if(deleteData->processed >= deleteData->total - 1) { - ui_pop(); - } - - if(strlen(path) > 48) { - error_display_res(NULL, deleteData->base, ui_draw_file_info, res, "Failed to delete content.\n%.45s...", path); - } else { - error_display_res(NULL, deleteData->base, ui_draw_file_info, res, "Failed to delete content.\n%.48s", path); - } - - if(deleteData->processed >= deleteData->total - 1) { - action_delete_contents_free_data(deleteData); - progressbar_destroy(view); - return; - } - } else { - *deleteData->populated = false; - } - - deleteData->processed++; - } - - *progress = deleteData->total > 0 ? (float) deleteData->processed / (float) deleteData->total : 0; - snprintf(progressText, PROGRESS_TEXT_MAX, "%lu / %lu", deleteData->processed, deleteData->total); + *progress = deleteData->deleteInfo.total > 0 ? (float) deleteData->deleteInfo.processed / (float) deleteData->deleteInfo.total : 0; + snprintf(progressText, PROGRESS_TEXT_MAX, "%lu / %lu", deleteData->deleteInfo.processed, deleteData->deleteInfo.total); } static void action_delete_contents_onresponse(ui_view* view, void* data, bool response) { prompt_destroy(view); + delete_contents_data* deleteData = (delete_contents_data*) data; + if(response) { - ui_view* progressView = progressbar_create("Deleting Contents", "Press B to cancel.", data, action_delete_contents_update, action_delete_contents_draw_top); - snprintf(progressbar_get_progress_text(progressView), PROGRESS_TEXT_MAX, "0 / %lu", ((delete_contents_data*) data)->total); - ui_push(progressView); + deleteData->cancelEvent = task_data_op(&deleteData->deleteInfo); + if(deleteData->cancelEvent != 0) { + ui_view* progressView = progressbar_create("Deleting Contents", "Press B to cancel.", data, action_delete_contents_update, action_delete_contents_draw_top); + snprintf(progressbar_get_progress_text(progressView), PROGRESS_TEXT_MAX, "0 / %lu", deleteData->deleteInfo.total); + ui_push(progressView); + } else { + error_display(NULL, NULL, NULL, "Failed to initiate delete operation."); + } } else { - action_delete_contents_free_data((delete_contents_data*) data); + action_delete_contents_free_data(deleteData); } } +static void action_delete_contents_internal(file_info* info, bool* populated, const char* message, bool recursive, void* filterData, bool (*filter)(void* data, FS_Archive* archive, const char* path, u32 attributes)) { + delete_contents_data* data = (delete_contents_data*) calloc(1, sizeof(delete_contents_data)); + data->base = info; + data->populated = populated; + + data->deleteInfo.data = data; + + data->deleteInfo.op = DATAOP_DELETE; + + data->deleteInfo.delete = action_delete_contents_delete; + + data->deleteInfo.resultError = action_delete_contents_result_error; + data->deleteInfo.ioError = action_delete_contents_io_error; + + data->cancelEvent = 0; + + Result res = 0; + if(R_FAILED(res = util_populate_contents(&data->contents, &data->deleteInfo.total, info->archive, info->path, recursive, false, filterData, filter))) { + error_display_res(NULL, info, ui_draw_file_info, res, "Failed to retrieve content list."); + + free(data); + return; + } + + ui_push(prompt_create("Confirmation", message, COLOR_TEXT, true, data, NULL, action_delete_contents_draw_top, action_delete_contents_onresponse)); +} + void action_delete_contents(file_info* info, bool* populated) { - delete_contents_data* data = (delete_contents_data*) calloc(1, sizeof(delete_contents_data)); - data->base = info; - data->populated = populated; - data->processed = 0; - - Result res = 0; - if(R_FAILED(res = util_populate_contents(&data->contents, &data->total, info->archive, info->path, true, false, NULL, NULL))) { - error_display_res(NULL, info, ui_draw_file_info, res, "Failed to retrieve content list."); - - free(data); - return; - } - - ui_push(prompt_create("Confirmation", "Delete the selected content?", COLOR_TEXT, true, data, NULL, action_delete_contents_draw_top, action_delete_contents_onresponse)); + action_delete_contents_internal(info, populated, "Delete the selected content?", true, NULL, NULL); } void action_delete_dir(file_info* info, bool* populated) { - delete_contents_data* data = (delete_contents_data*) calloc(1, sizeof(delete_contents_data)); - data->base = info; - data->populated = populated; - data->processed = 0; - - Result res = 0; - if(R_FAILED(res = util_populate_contents(&data->contents, &data->total, info->archive, info->path, true, false, NULL, NULL))) { - error_display_res(NULL, info, ui_draw_file_info, res, "Failed to retrieve content list."); - - free(data); - return; - } - - ui_push(prompt_create("Confirmation", "Delete the current directory?", COLOR_TEXT, true, data, NULL, action_delete_contents_draw_top, action_delete_contents_onresponse)); + action_delete_contents_internal(info, populated, "Delete the current directory?", true, NULL, NULL); } void action_delete_dir_contents(file_info* info, bool* populated) { - delete_contents_data* data = (delete_contents_data*) calloc(1, sizeof(delete_contents_data)); - data->base = info; - data->populated = populated; - data->processed = 0; - - Result res = 0; - if(R_FAILED(res = util_populate_contents(&data->contents, &data->total, info->archive, info->path, true, false, info->path, util_filter_not_path))) { - error_display_res(NULL, info, ui_draw_file_info, res, "Failed to retrieve content list."); - - free(data); - return; - } - - ui_push(prompt_create("Confirmation", "Delete all contents of the current directory?", COLOR_TEXT, true, data, NULL, action_delete_contents_draw_top, action_delete_contents_onresponse)); + action_delete_contents_internal(info, populated, "Delete all contents of the current directory?", true, info->path, util_filter_not_path); } void action_delete_dir_cias(file_info* info, bool* populated) { - delete_contents_data* data = (delete_contents_data*) calloc(1, sizeof(delete_contents_data)); - data->base = info; - data->populated = populated; - data->processed = 0; - - Result res = 0; - if(R_FAILED(res = util_populate_contents(&data->contents, &data->total, info->archive, info->path, false, false, ".cia", util_filter_file_extension))) { - error_display_res(NULL, info, ui_draw_file_info, res, "Failed to retrieve content list."); - - free(data); - return; - } - - ui_push(prompt_create("Confirmation", "Delete all CIAs in the current directory?", COLOR_TEXT, true, data, NULL, action_delete_contents_draw_top, action_delete_contents_onresponse)); + action_delete_contents_internal(info, populated, "Delete all CIAs in the current directory?", false, ".cia", util_filter_file_extension); } \ No newline at end of file diff --git a/source/ui/section/action/deletependingtitles.c b/source/ui/section/action/deletependingtitles.c new file mode 100644 index 0000000..a52c598 --- /dev/null +++ b/source/ui/section/action/deletependingtitles.c @@ -0,0 +1,187 @@ +#include +#include + +#include <3ds.h> + +#include "action.h" +#include "../../error.h" +#include "../../progressbar.h" +#include "../../prompt.h" +#include "../../../screen.h" +#include "../task/task.h" + +typedef struct { + pending_title_info* info; + bool* populated; + u64* titleIds; + + u32 sdTotal; + u32 nandTotal; + + data_op_info deleteInfo; + Handle cancelEvent; +} delete_pending_titles_data; + +static Result action_delete_pending_titles_delete(void* data, u32 index) { + delete_pending_titles_data* deleteData = (delete_pending_titles_data*) data; + + Result res = 0; + + if(R_SUCCEEDED(res = AM_DeletePendingTitle(index >= deleteData->sdTotal ? MEDIATYPE_NAND : MEDIATYPE_SD, deleteData->titleIds[index]))) { + *deleteData->populated = false; + } + + return res; +} + +static bool action_delete_pending_titles_result_error(void* data, u32 index, Result res) { + delete_pending_titles_data* deleteData = (delete_pending_titles_data*) data; + + if(res == MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_CANCEL_REQUESTED)) { + ui_push(prompt_create("Failure", "Delete cancelled.", COLOR_TEXT, false, deleteData->info, NULL, deleteData->info != NULL ? ui_draw_pending_title_info : NULL, NULL)); + return false; + } else { + u64 titleId = deleteData->titleIds[index]; + + volatile bool dismissed = false; + error_display_res(&dismissed, deleteData->info, deleteData->info != NULL ? ui_draw_pending_title_info : NULL, res, "Failed to delete pending title.\n%llX", titleId); + + while(!dismissed) { + svcSleepThread(1000000); + } + } + + return index < deleteData->deleteInfo.total - 1; +} + +static bool action_delete_pending_titles_io_error(void* data, u32 index, int err) { + delete_pending_titles_data* deleteData = (delete_pending_titles_data*) data; + + u64 titleId = deleteData->titleIds[index]; + + volatile bool dismissed = false; + error_display_errno(&dismissed, deleteData->info, deleteData->info != NULL ? ui_draw_pending_title_info : NULL, err, "Failed to delete pending title.\n%llX", titleId); + + while(!dismissed) { + svcSleepThread(1000000); + } + + return index < deleteData->deleteInfo.total - 1; +} + +static void action_delete_pending_titles_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2) { + delete_pending_titles_data* deleteData = (delete_pending_titles_data*) data; + + if(deleteData->info != NULL) { + ui_draw_pending_title_info(view, deleteData->info, x1, y1, x2, y2); + } +} + +static void action_delete_pending_titles_free_data(delete_pending_titles_data* data) { + free(data->titleIds); + free(data); +} + +static void action_delete_pending_titles_success_onresponse(ui_view* view, void* data, bool response) { + prompt_destroy(view); + + action_delete_pending_titles_free_data((delete_pending_titles_data*) data); +} + +static void action_delete_pending_titles_update(ui_view* view, void* data, float* progress, char* progressText) { + delete_pending_titles_data* deleteData = (delete_pending_titles_data*) data; + + if(deleteData->deleteInfo.finished) { + progressbar_destroy(view); + ui_pop(); + + if(deleteData->deleteInfo.premature) { + action_delete_pending_titles_free_data(deleteData); + } else { + ui_push(prompt_create("Success", "Pending title(s) deleted.", COLOR_TEXT, false, data, NULL, action_delete_pending_titles_draw_top, action_delete_pending_titles_success_onresponse)); + } + + return; + } + + if(hidKeysDown() & KEY_B) { + svcSignalEvent(deleteData->cancelEvent); + } + + *progress = deleteData->deleteInfo.total > 0 ? (float) deleteData->deleteInfo.processed / (float) deleteData->deleteInfo.total : 0; + snprintf(progressText, PROGRESS_TEXT_MAX, "%lu / %lu", deleteData->deleteInfo.processed, deleteData->deleteInfo.total); +} + +static void action_delete_pending_titles_onresponse(ui_view* view, void* data, bool response) { + prompt_destroy(view); + + delete_pending_titles_data* deleteData = (delete_pending_titles_data*) data; + + if(response) { + deleteData->cancelEvent = task_data_op(&deleteData->deleteInfo); + if(deleteData->cancelEvent != 0) { + ui_view* progressView = progressbar_create("Deleting Pending Title(s)", "Press B to cancel.", data, action_delete_pending_titles_update, action_delete_pending_titles_draw_top); + snprintf(progressbar_get_progress_text(progressView), PROGRESS_TEXT_MAX, "0 / %lu", deleteData->deleteInfo.total); + ui_push(progressView); + } else { + error_display(NULL, NULL, NULL, "Failed to initiate delete operation."); + } + } else { + action_delete_pending_titles_free_data(deleteData); + } +} + +void action_delete_pending_titles(pending_title_info* info, bool* populated, const char* message, u64* titleIds, u32 sdTotal, u32 nandTotal) { + delete_pending_titles_data* data = (delete_pending_titles_data*) calloc(1, sizeof(delete_pending_titles_data)); + data->info = info; + data->populated = populated; + data->titleIds = titleIds; + data->sdTotal = sdTotal; + data->nandTotal = nandTotal; + + data->deleteInfo.data = data; + + data->deleteInfo.op = DATAOP_DELETE; + + data->deleteInfo.total = sdTotal + nandTotal; + + data->deleteInfo.delete = action_delete_pending_titles_delete; + + data->deleteInfo.resultError = action_delete_pending_titles_result_error; + data->deleteInfo.ioError = action_delete_pending_titles_io_error; + + data->cancelEvent = 0; + + ui_push(prompt_create("Confirmation", message, COLOR_TEXT, true, data, NULL, action_delete_pending_titles_draw_top, action_delete_pending_titles_onresponse)); +} + +void action_delete_pending_title(pending_title_info* info, bool* populated) { + u64* titleIds = (u64*) calloc(1, sizeof(u64)); + titleIds[0] = info->titleId; + u32 sdTotal = info->mediaType == MEDIATYPE_SD ? 1 : 0; + u32 nandTotal = info->mediaType == MEDIATYPE_NAND ? 1 : 0; + + action_delete_pending_titles(info, populated, "Delete the selected pending title?", titleIds, sdTotal, nandTotal); +} + +void action_delete_all_pending_titles(pending_title_info* info, bool* populated) { + u32 sdTotal = 0; + u32 nandTotal = 0; + + Result res = 0; + if(R_FAILED(res = AM_GetPendingTitleCount(&sdTotal, MEDIATYPE_SD, AM_STATUS_MASK_INSTALLING | AM_STATUS_MASK_AWAITING_FINALIZATION)) || R_FAILED(res = AM_GetPendingTitleCount(&nandTotal, MEDIATYPE_NAND, AM_STATUS_MASK_INSTALLING | AM_STATUS_MASK_AWAITING_FINALIZATION))) { + error_display_res(NULL, NULL, NULL, res, "Failed to retrieve pending title count."); + + return; + } + + u64* titleIds = (u64*) calloc(sdTotal + nandTotal, sizeof(u64)); + if(R_FAILED(res = AM_GetPendingTitleList(&sdTotal, sdTotal, MEDIATYPE_SD, AM_STATUS_MASK_INSTALLING | AM_STATUS_MASK_AWAITING_FINALIZATION, titleIds)) || R_FAILED(res = AM_GetPendingTitleList(&nandTotal, nandTotal, MEDIATYPE_NAND, AM_STATUS_MASK_INSTALLING | AM_STATUS_MASK_AWAITING_FINALIZATION, &titleIds[sdTotal]))) { + error_display_res(NULL, NULL, NULL, res, "Failed to retrieve pending title list."); + + free(titleIds); + return; + } + + action_delete_pending_titles(info, populated, "Delete all pending titles?", titleIds, sdTotal, nandTotal); +} \ No newline at end of file diff --git a/source/ui/section/action/installcias.c b/source/ui/section/action/installcias.c index 8e95719..54a3c46 100644 --- a/source/ui/section/action/installcias.c +++ b/source/ui/section/action/installcias.c @@ -20,20 +20,20 @@ typedef struct { u64 currTitleId; - copy_data_info installInfo; + data_op_info installInfo; Handle cancelEvent; } install_cias_data; -Result action_install_cias_is_src_directory(void* data, u32 index, bool* isDirectory) { +static Result action_install_cias_is_src_directory(void* data, u32 index, bool* isDirectory) { *isDirectory = false; return 0; } -Result action_install_cias_make_dst_directory(void* data, u32 index) { +static Result action_install_cias_make_dst_directory(void* data, u32 index) { return 0; } -Result action_install_cias_open_src(void* data, u32 index, u32* handle) { +static Result action_install_cias_open_src(void* data, u32 index, u32* handle) { install_cias_data* installData = (install_cias_data*) data; FS_Path* fsPath = util_make_path_utf8(installData->contents[index]); @@ -45,7 +45,7 @@ Result action_install_cias_open_src(void* data, u32 index, u32* handle) { return res; } -Result action_install_cias_close_src(void* data, u32 index, bool succeeded, u32 handle) { +static Result action_install_cias_close_src(void* data, u32 index, bool succeeded, u32 handle) { install_cias_data* installData = (install_cias_data*) data; Result res = 0; @@ -60,15 +60,15 @@ Result action_install_cias_close_src(void* data, u32 index, bool succeeded, u32 return res; } -Result action_install_cias_get_src_size(void* data, u32 handle, u64* size) { +static Result action_install_cias_get_src_size(void* data, u32 handle, u64* size) { return FSFILE_GetSize(handle, size); } -Result action_install_cias_read_src(void* data, u32 handle, u32* bytesRead, void* buffer, u64 offset, u32 size) { +static Result action_install_cias_read_src(void* data, u32 handle, u32* bytesRead, void* buffer, u64 offset, u32 size) { return FSFILE_Read(handle, bytesRead, offset, buffer, size); } -Result action_install_cias_open_dst(void* data, u32 index, void* initialReadBlock, u32* handle) { +static Result action_install_cias_open_dst(void* data, u32 index, void* initialReadBlock, u32* handle) { install_cias_data* installData = (install_cias_data*) data; u8* buffer = (u8*) initialReadBlock; @@ -102,7 +102,7 @@ Result action_install_cias_open_dst(void* data, u32 index, void* initialReadBloc return res; } -Result action_install_cias_close_dst(void* data, u32 index, bool succeeded, u32 handle) { +static Result action_install_cias_close_dst(void* data, u32 index, bool succeeded, u32 handle) { if(succeeded) { install_cias_data* installData = (install_cias_data*) data; @@ -119,7 +119,7 @@ Result action_install_cias_close_dst(void* data, u32 index, bool succeeded, u32 } } -Result action_install_cias_write_dst(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size) { +static Result action_install_cias_write_dst(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size) { return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0); } @@ -223,7 +223,7 @@ static void action_install_cias_onresponse(ui_view* view, void* data, bool respo install_cias_data* installData = (install_cias_data*) data; if(response) { - installData->cancelEvent = task_copy_data(&installData->installInfo); + installData->cancelEvent = task_data_op(&installData->installInfo); if(installData->cancelEvent != 0) { ui_view* progressView = progressbar_create("Installing CIA(s)", "Press B to cancel.", data, action_install_cias_update, action_install_cias_draw_top); snprintf(progressbar_get_progress_text(progressView), PROGRESS_TEXT_MAX, "0 / %lu", installData->installInfo.total); @@ -248,6 +248,8 @@ static void action_install_cias_internal(file_info* info, bool* populated, bool data->installInfo.data = data; + data->installInfo.op = DATAOP_COPY; + data->installInfo.copyEmpty = false; data->installInfo.isSrcDirectory = action_install_cias_is_src_directory; diff --git a/source/ui/section/action/installtickets.c b/source/ui/section/action/installtickets.c index d67e0a0..d16274a 100644 --- a/source/ui/section/action/installtickets.c +++ b/source/ui/section/action/installtickets.c @@ -16,20 +16,20 @@ typedef struct { file_info* base; char** contents; - copy_data_info installInfo; + data_op_info installInfo; Handle cancelEvent; } install_tickets_data; -Result action_install_tickets_is_src_directory(void* data, u32 index, bool* isDirectory) { +static Result action_install_tickets_is_src_directory(void* data, u32 index, bool* isDirectory) { *isDirectory = false; return 0; } -Result action_install_tickets_make_dst_directory(void* data, u32 index) { +static Result action_install_tickets_make_dst_directory(void* data, u32 index) { return 0; } -Result action_install_tickets_open_src(void* data, u32 index, u32* handle) { +static Result action_install_tickets_open_src(void* data, u32 index, u32* handle) { install_tickets_data* installData = (install_tickets_data*) data; FS_Path* fsPath = util_make_path_utf8(installData->contents[index]); @@ -41,23 +41,23 @@ Result action_install_tickets_open_src(void* data, u32 index, u32* handle) { return res; } -Result action_install_tickets_close_src(void* data, u32 index, bool succeeded, u32 handle) { +static Result action_install_tickets_close_src(void* data, u32 index, bool succeeded, u32 handle) { return FSFILE_Close(handle); } -Result action_install_tickets_get_src_size(void* data, u32 handle, u64* size) { +static Result action_install_tickets_get_src_size(void* data, u32 handle, u64* size) { return FSFILE_GetSize(handle, size); } -Result action_install_tickets_read_src(void* data, u32 handle, u32* bytesRead, void* buffer, u64 offset, u32 size) { +static Result action_install_tickets_read_src(void* data, u32 handle, u32* bytesRead, void* buffer, u64 offset, u32 size) { return FSFILE_Read(handle, bytesRead, offset, buffer, size); } -Result action_install_tickets_open_dst(void* data, u32 index, void* initialReadBlock, u32* handle) { +static Result action_install_tickets_open_dst(void* data, u32 index, void* initialReadBlock, u32* handle) { return AM_InstallTicketBegin(handle); } -Result action_install_tickets_close_dst(void* data, u32 index, bool succeeded, u32 handle) { +static Result action_install_tickets_close_dst(void* data, u32 index, bool succeeded, u32 handle) { if(succeeded) { return AM_InstallTicketFinalize(handle); } else { @@ -65,11 +65,11 @@ Result action_install_tickets_close_dst(void* data, u32 index, bool succeeded, u } } -Result action_install_tickets_write_dst(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size) { +static Result action_install_tickets_write_dst(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size) { return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0); } -bool action_install_tickets_result_error(void* data, u32 index, Result res) { +static bool action_install_tickets_result_error(void* data, u32 index, Result res) { install_tickets_data* installData = (install_tickets_data*) data; if(res == MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_CANCEL_REQUESTED)) { @@ -93,7 +93,7 @@ bool action_install_tickets_result_error(void* data, u32 index, Result res) { return index < installData->installInfo.total - 1; } -bool action_install_tickets_io_error(void* data, u32 index, int err) { +static bool action_install_tickets_io_error(void* data, u32 index, int err) { install_tickets_data* installData = (install_tickets_data*) data; char* path = installData->contents[index]; @@ -157,7 +157,7 @@ static void action_install_tickets_onresponse(ui_view* view, void* data, bool re install_tickets_data* installData = (install_tickets_data*) data; if(response) { - installData->cancelEvent = task_copy_data(&installData->installInfo); + installData->cancelEvent = task_data_op(&installData->installInfo); if(installData->cancelEvent != 0) { ui_view* progressView = progressbar_create("Installing ticket(s)", "Press B to cancel.", data, action_install_tickets_update, action_install_tickets_draw_top); snprintf(progressbar_get_progress_text(progressView), PROGRESS_TEXT_MAX, "0 / %lu", installData->installInfo.total); @@ -178,6 +178,8 @@ void action_install_tickets(file_info* info, bool* populated) { data->installInfo.data = data; + data->installInfo.op = DATAOP_COPY; + data->installInfo.copyEmpty = false; data->installInfo.isSrcDirectory = action_install_tickets_is_src_directory; diff --git a/source/ui/section/action/pastefiles.c b/source/ui/section/action/pastefiles.c index 46532ec..d63553c 100644 --- a/source/ui/section/action/pastefiles.c +++ b/source/ui/section/action/pastefiles.c @@ -18,7 +18,7 @@ typedef struct { bool* populated; char** contents; - copy_data_info pasteInfo; + data_op_info pasteInfo; Handle cancelEvent; } paste_files_data; @@ -34,14 +34,14 @@ static void action_paste_files_get_dst_path(paste_files_data* data, u32 index, c snprintf(dstPath, PATH_MAX, "%s%s", baseDstPath, data->contents[index] + strlen(dstPath)); } -Result action_paste_files_is_src_directory(void* data, u32 index, bool* isDirectory) { +static Result action_paste_files_is_src_directory(void* data, u32 index, bool* isDirectory) { paste_files_data* pasteData = (paste_files_data*) data; *isDirectory = util_is_dir(pasteData->base->archive, pasteData->contents[index]); return 0; } -Result action_paste_files_make_dst_directory(void* data, u32 index) { +static Result action_paste_files_make_dst_directory(void* data, u32 index) { paste_files_data* pasteData = (paste_files_data*) data; char dstPath[PATH_MAX]; @@ -56,7 +56,7 @@ Result action_paste_files_make_dst_directory(void* data, u32 index) { return res; } -Result action_paste_files_open_src(void* data, u32 index, u32* handle) { +static Result action_paste_files_open_src(void* data, u32 index, u32* handle) { paste_files_data* pasteData = (paste_files_data*) data; FS_Path* fsPath = util_make_path_utf8(pasteData->contents[index]); @@ -68,19 +68,19 @@ Result action_paste_files_open_src(void* data, u32 index, u32* handle) { return res; } -Result action_paste_files_close_src(void* data, u32 index, bool succeeded, u32 handle) { +static Result action_paste_files_close_src(void* data, u32 index, bool succeeded, u32 handle) { return FSFILE_Close(handle); } -Result action_paste_files_get_src_size(void* data, u32 handle, u64* size) { +static Result action_paste_files_get_src_size(void* data, u32 handle, u64* size) { return FSFILE_GetSize(handle, size); } -Result action_paste_files_read_src(void* data, u32 handle, u32* bytesRead, void* buffer, u64 offset, u32 size) { +static Result action_paste_files_read_src(void* data, u32 handle, u32* bytesRead, void* buffer, u64 offset, u32 size) { return FSFILE_Read(handle, bytesRead, offset, buffer, size); } -Result action_paste_files_open_dst(void* data, u32 index, void* initialReadBlock, u32* handle) { +static Result action_paste_files_open_dst(void* data, u32 index, void* initialReadBlock, u32* handle) { paste_files_data* pasteData = (paste_files_data*) data; char dstPath[PATH_MAX]; @@ -95,15 +95,15 @@ Result action_paste_files_open_dst(void* data, u32 index, void* initialReadBlock return res; } -Result action_paste_files_close_dst(void* data, u32 index, bool succeeded, u32 handle) { +static Result action_paste_files_close_dst(void* data, u32 index, bool succeeded, u32 handle) { return FSFILE_Close(handle); } -Result action_paste_files_write_dst(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size) { +static Result action_paste_files_write_dst(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size) { return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0); } -bool action_paste_files_result_error(void* data, u32 index, Result res) { +static bool action_paste_files_result_error(void* data, u32 index, Result res) { paste_files_data* pasteData = (paste_files_data*) data; if(res == MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_CANCEL_REQUESTED)) { @@ -127,7 +127,7 @@ bool action_paste_files_result_error(void* data, u32 index, Result res) { return index < pasteData->pasteInfo.total - 1; } -bool action_paste_files_io_error(void* data, u32 index, int err) { +static bool action_paste_files_io_error(void* data, u32 index, int err) { paste_files_data* pasteData = (paste_files_data*) data; char* path = pasteData->contents[index]; @@ -171,6 +171,10 @@ static void action_paste_files_update(ui_view* view, void* data, float* progress if(pasteData->pasteInfo.finished) { *pasteData->populated = false; + if(pasteData->base->archive->id == ARCHIVE_USER_SAVEDATA) { + FSUSER_ControlArchive(*pasteData->base->archive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0); + } + ui_pop(); progressbar_destroy(view); @@ -196,7 +200,7 @@ static void action_paste_files_onresponse(ui_view* view, void* data, bool respon paste_files_data* pasteData = (paste_files_data*) data; if(response) { - pasteData->cancelEvent = task_copy_data(&pasteData->pasteInfo); + pasteData->cancelEvent = task_data_op(&pasteData->pasteInfo); if(pasteData->cancelEvent != 0) { ui_view* progressView = progressbar_create("Pasting Contents", "Press B to cancel.", data, action_paste_files_update, action_paste_files_draw_top); snprintf(progressbar_get_progress_text(progressView), PROGRESS_TEXT_MAX, "0 / %lu", ((paste_files_data*) data)->pasteInfo.total); @@ -221,6 +225,8 @@ void action_paste_contents(file_info* info, bool* populated) { data->pasteInfo.data = data; + data->pasteInfo.op = DATAOP_COPY; + data->pasteInfo.copyEmpty = true; data->pasteInfo.isSrcDirectory = action_paste_files_is_src_directory; diff --git a/source/ui/section/dumpnand.c b/source/ui/section/dumpnand.c index cb3958c..ad659df 100644 --- a/source/ui/section/dumpnand.c +++ b/source/ui/section/dumpnand.c @@ -10,50 +10,50 @@ #include "../../screen.h" typedef struct { - copy_data_info dumpInfo; + data_op_info dumpInfo; Handle cancelEvent; } dump_nand_data; -Result dumpnand_is_src_directory(void* data, u32 index, bool* isDirectory) { +static Result dumpnand_is_src_directory(void* data, u32 index, bool* isDirectory) { *isDirectory = false; return 0; } -Result dumpnand_make_dst_directory(void* data, u32 index) { +static Result dumpnand_make_dst_directory(void* data, u32 index) { return 0; } -Result dumpnand_open_src(void* data, u32 index, u32* handle) { +static Result dumpnand_open_src(void* data, u32 index, u32* handle) { FS_Archive wnandArchive = {ARCHIVE_NAND_W_FS, fsMakePath(PATH_EMPTY, "")}; return FSUSER_OpenFileDirectly(handle, wnandArchive, fsMakePath(PATH_UTF16, u"/"), FS_OPEN_READ, 0); } -Result dumpnand_close_src(void* data, u32 index, bool succeeded, u32 handle) { +static Result dumpnand_close_src(void* data, u32 index, bool succeeded, u32 handle) { return FSFILE_Close(handle); } -Result dumpnand_get_src_size(void* data, u32 handle, u64* size) { +static Result dumpnand_get_src_size(void* data, u32 handle, u64* size) { return FSFILE_GetSize(handle, size); } -Result dumpnand_read_src(void* data, u32 handle, u32* bytesRead, void* buffer, u64 offset, u32 size) { +static Result dumpnand_read_src(void* data, u32 handle, u32* bytesRead, void* buffer, u64 offset, u32 size) { return FSFILE_Read(handle, bytesRead, offset, buffer, size); } -Result dumpnand_open_dst(void* data, u32 index, void* initialReadBlock, u32* handle) { +static Result dumpnand_open_dst(void* data, u32 index, void* initialReadBlock, u32* handle) { FS_Archive sdmcArchive = {ARCHIVE_SDMC, {PATH_BINARY, 0, (u8*) ""}}; return FSUSER_OpenFileDirectly(handle, sdmcArchive, fsMakePath(PATH_UTF16, u"/NAND.bin"), FS_OPEN_WRITE | FS_OPEN_CREATE, 0); } -Result dumpnand_close_dst(void* data, u32 index, bool succeeded, u32 handle) { +static Result dumpnand_close_dst(void* data, u32 index, bool succeeded, u32 handle) { return FSFILE_Close(handle); } -Result dumpnand_write_dst(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size) { +static Result dumpnand_write_dst(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size) { return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0); } -bool dumpnand_result_error(void* data, u32 index, Result res) { +static bool dumpnand_result_error(void* data, u32 index, Result res) { if(res == MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_CANCEL_REQUESTED)) { ui_push(prompt_create("Failure", "Dump cancelled.", COLOR_TEXT, false, NULL, NULL, NULL, NULL)); } else { @@ -63,7 +63,7 @@ bool dumpnand_result_error(void* data, u32 index, Result res) { return false; } -bool dumpnand_io_error(void* data, u32 index, int err) { +static bool dumpnand_io_error(void* data, u32 index, int err) { error_display_errno(NULL, NULL, NULL, err, "Failed to dump NAND."); return false; } @@ -102,7 +102,7 @@ static void dumpnand_onresponse(ui_view* view, void* data, bool response) { if(response) { dump_nand_data* dumpData = (dump_nand_data*) data; - dumpData->cancelEvent = task_copy_data(&dumpData->dumpInfo); + dumpData->cancelEvent = task_data_op(&dumpData->dumpInfo); if(dumpData->cancelEvent != 0) { ui_push(progressbar_create("Dumping NAND", "Press B to cancel.", data, dumpnand_update, NULL)); } else { @@ -118,6 +118,8 @@ void dump_nand() { data->dumpInfo.data = data; + data->dumpInfo.op = DATAOP_COPY; + data->dumpInfo.copyEmpty = true; data->dumpInfo.total = 1; diff --git a/source/ui/section/networkinstall.c b/source/ui/section/networkinstall.c index 2e590ac..c817406 100644 --- a/source/ui/section/networkinstall.c +++ b/source/ui/section/networkinstall.c @@ -23,7 +23,7 @@ typedef struct { u64 currTitleId; - copy_data_info installInfo; + data_op_info installInfo; Handle cancelEvent; } network_install_data; @@ -51,16 +51,16 @@ static int sendwait(int sockfd, void* buf, size_t len, int flags) { return ret < 0 ? ret : (int) written; } -Result networkinstall_is_src_directory(void* data, u32 index, bool* isDirectory) { +static Result networkinstall_is_src_directory(void* data, u32 index, bool* isDirectory) { *isDirectory = false; return 0; } -Result networkinstall_make_dst_directory(void* data, u32 index) { +static Result networkinstall_make_dst_directory(void* data, u32 index) { return 0; } -Result networkinstall_open_src(void* data, u32 index, u32* handle) { +static Result networkinstall_open_src(void* data, u32 index, u32* handle) { network_install_data* networkInstallData = (network_install_data*) data; u8 ack = 1; @@ -71,11 +71,11 @@ Result networkinstall_open_src(void* data, u32 index, u32* handle) { return 0; } -Result networkinstall_close_src(void* data, u32 index, bool succeeded, u32 handle) { +static Result networkinstall_close_src(void* data, u32 index, bool succeeded, u32 handle) { return 0; } -Result networkinstall_get_src_size(void* data, u32 handle, u64* size) { +static Result networkinstall_get_src_size(void* data, u32 handle, u64* size) { network_install_data* networkInstallData = (network_install_data*) data; u64 netSize = 0; @@ -87,7 +87,7 @@ Result networkinstall_get_src_size(void* data, u32 handle, u64* size) { return 0; } -Result networkinstall_read_src(void* data, u32 handle, u32* bytesRead, void* buffer, u64 offset, u32 size) { +static Result networkinstall_read_src(void* data, u32 handle, u32* bytesRead, void* buffer, u64 offset, u32 size) { network_install_data* networkInstallData = (network_install_data*) data; int ret = 0; @@ -99,7 +99,7 @@ Result networkinstall_read_src(void* data, u32 handle, u32* bytesRead, void* buf return 0; } -Result networkinstall_open_dst(void* data, u32 index, void* initialReadBlock, u32* handle) { +static Result networkinstall_open_dst(void* data, u32 index, void* initialReadBlock, u32* handle) { network_install_data* networkInstallData = (network_install_data*) data; u8* buffer = (u8*) initialReadBlock; @@ -133,7 +133,7 @@ Result networkinstall_open_dst(void* data, u32 index, void* initialReadBlock, u3 return res; } -Result networkinstall_close_dst(void* data, u32 index, bool succeeded, u32 handle) { +static Result networkinstall_close_dst(void* data, u32 index, bool succeeded, u32 handle) { if(succeeded) { network_install_data* networkInstallData = (network_install_data*) data; @@ -150,11 +150,11 @@ Result networkinstall_close_dst(void* data, u32 index, bool succeeded, u32 handl } } -Result networkinstall_write_dst(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size) { +static Result networkinstall_write_dst(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size) { return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0); } -bool networkinstall_result_error(void* data, u32 index, Result res) { +static bool networkinstall_result_error(void* data, u32 index, Result res) { network_install_data* networkInstallData = (network_install_data*) data; if(res == MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, RD_CANCEL_REQUESTED)) { @@ -176,7 +176,7 @@ bool networkinstall_result_error(void* data, u32 index, Result res) { return index < networkInstallData->installInfo.total - 1; } -bool networkinstall_io_error(void* data, u32 index, int err) { +static bool networkinstall_io_error(void* data, u32 index, int err) { network_install_data* networkInstallData = (network_install_data*) data; volatile bool dismissed = false; @@ -232,7 +232,7 @@ static void networkinstall_confirm_onresponse(ui_view* view, void* data, bool re network_install_data* networkInstallData = (network_install_data*) data; if(response) { - networkInstallData->cancelEvent = task_copy_data(&networkInstallData->installInfo); + networkInstallData->cancelEvent = task_data_op(&networkInstallData->installInfo); if(networkInstallData->cancelEvent != 0) { ui_view* progressView = progressbar_create("Installing CIA(s)", "Press B to cancel.", data, networkinstall_install_update, NULL); snprintf(progressbar_get_progress_text(progressView), PROGRESS_TEXT_MAX, "0 / %lu", networkInstallData->installInfo.total); @@ -335,6 +335,8 @@ void networkinstall_open() { data->installInfo.data = data; + data->installInfo.op = DATAOP_COPY; + data->installInfo.copyEmpty = false; data->installInfo.isSrcDirectory = networkinstall_is_src_directory; diff --git a/source/ui/section/task/copydata.c b/source/ui/section/task/copydata.c index 2917e37..0e378c9 100644 --- a/source/ui/section/task/copydata.c +++ b/source/ui/section/task/copydata.c @@ -9,12 +9,12 @@ #include "task.h" typedef struct { - copy_data_info* info; + data_op_info* info; Handle cancelEvent; -} copy_data_data; +} data_op_data; -static bool task_copy_data_item(copy_data_data* data, u32 index) { +static bool task_data_op_copy(data_op_data* data, u32 index) { data->info->currProcessed = 0; data->info->currTotal = 0; @@ -105,8 +105,21 @@ static bool task_copy_data_item(copy_data_data* data, u32 index) { return true; } -static void task_copy_data_thread(void* arg) { - copy_data_data* data = (copy_data_data*) arg; +static bool task_data_op_delete(data_op_data* data, u32 index) { + Result res = 0; + if(R_FAILED(res = data->info->delete(data->info->data, index))) { + if(res == -1) { + return data->info->ioError(data->info->data, index, errno); + } else { + return data->info->resultError(data->info->data, index, res); + } + } + + return true; +} + +static void task_data_op_thread(void* arg) { + data_op_data* data = (data_op_data*) arg; data->info->finished = false; data->info->premature = false; @@ -114,7 +127,20 @@ static void task_copy_data_thread(void* arg) { data->info->processed = 0; for(data->info->processed = 0; data->info->processed < data->info->total; data->info->processed++) { - if(!task_copy_data_item(data, data->info->processed)) { + bool cont = false; + + switch(data->info->op) { + case DATAOP_COPY: + cont = task_data_op_copy(data, data->info->processed); + break; + case DATAOP_DELETE: + cont = task_data_op_delete(data, data->info->processed); + break; + default: + break; + } + + if(!cont) { data->info->premature = true; break; } @@ -126,7 +152,7 @@ static void task_copy_data_thread(void* arg) { free(data); } -static void task_copy_data_reset_info(copy_data_info* info) { +static void task_data_op_reset_info(data_op_info* info) { info->finished = false; info->premature = false; @@ -136,14 +162,14 @@ static void task_copy_data_reset_info(copy_data_info* info) { info->currTotal = 0; } -Handle task_copy_data(copy_data_info* info) { +Handle task_data_op(data_op_info* info) { if(info == NULL) { return 0; } - task_copy_data_reset_info(info); + task_data_op_reset_info(info); - copy_data_data* installData = (copy_data_data*) calloc(1, sizeof(copy_data_data)); + data_op_data* installData = (data_op_data*) calloc(1, sizeof(data_op_data)); installData->info = info; Result eventRes = svcCreateEvent(&installData->cancelEvent, 1); @@ -154,7 +180,7 @@ Handle task_copy_data(copy_data_info* info) { return 0; } - if(threadCreate(task_copy_data_thread, installData, 0x4000, 0x18, 1, true) == NULL) { + if(threadCreate(task_data_op_thread, installData, 0x4000, 0x18, 1, true) == NULL) { error_display(NULL, NULL, NULL, "Failed to create CIA installation thread."); svcCloseHandle(installData->cancelEvent); diff --git a/source/ui/section/task/task.h b/source/ui/section/task/task.h index 204928f..15b5abc 100644 --- a/source/ui/section/task/task.h +++ b/source/ui/section/task/task.h @@ -68,9 +68,17 @@ typedef struct { ticket_info ticketInfo; } file_info; +typedef enum { + DATAOP_COPY, + DATAOP_DELETE +} DataOp; + typedef struct { void* data; + DataOp op; + + // Copy bool copyEmpty; bool finished; @@ -96,9 +104,13 @@ typedef struct { Result (*writeDst)(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size); + // Delete + Result (*delete)(void* data, u32 index); + + // Errors bool (*resultError)(void* data, u32 index, Result res); bool (*ioError)(void* data, u32 index, int err); -} copy_data_info; +} data_op_info; bool task_is_quit_all(); void task_quit_all(); @@ -109,4 +121,4 @@ Handle task_populate_pending_titles(list_item* items, u32* count, u32 max); Handle task_populate_system_save_data(list_item* items, u32* count, u32 max); Handle task_populate_tickets(list_item* items, u32* count, u32 max); Handle task_populate_titles(list_item* items, u32* count, u32 max); -Handle task_copy_data(copy_data_info* info); \ No newline at end of file +Handle task_data_op(data_op_info* info); \ No newline at end of file