mirror of
https://gitlab.com/Theopse/fbi-i18n-zh.git
synced 2025-04-06 03:58:02 +08:00
Extend copy task into a generic data operation task.
This commit is contained in:
parent
6702f4f267
commit
2c7ff25e78
@ -1,128 +0,0 @@
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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));
|
||||
}
|
@ -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);
|
||||
}
|
187
source/ui/section/action/deletependingtitles.c
Normal file
187
source/ui/section/action/deletependingtitles.c
Normal file
@ -0,0 +1,187 @@
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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);
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
Handle task_data_op(data_op_info* info);
|
Loading…
x
Reference in New Issue
Block a user