diff --git a/source/ui/section/action/pastefiles.c b/source/ui/section/action/pastefiles.c index e8d3d01..105f498 100644 --- a/source/ui/section/action/pastefiles.c +++ b/source/ui/section/action/pastefiles.c @@ -12,9 +12,17 @@ #include "../../../screen.h" #include "../../../util.h" +#define PASTE_BUFFER_SIZE (1024 * 512) + typedef struct { file_info* base; bool* populated; + bool started; + u8* buffer; + Handle currSrc; + Handle currDst; + u64 currProcessed; + u64 currTotal; u32 processed; u32 total; char** contents; @@ -30,6 +38,7 @@ static void action_paste_files_failure_onresponse(ui_view* view, void* data, boo static void action_paste_files_free_data(paste_files_data* data) { util_free_contents(data->contents, data->total); + free(data->buffer); free(data); } @@ -43,6 +52,16 @@ static void action_paste_files_update(ui_view* view, void* data, float* progress paste_files_data* pasteData = (paste_files_data*) data; if(hidKeysDown() & KEY_B) { + if(pasteData->currSrc != 0) { + FSFILE_Close(pasteData->currSrc); + pasteData->currSrc = 0; + } + + if(pasteData->currDst != 0) { + FSFILE_Close(pasteData->currDst); + pasteData->currDst = 0; + } + progressbar_destroy(view); ui_pop(); @@ -50,88 +69,144 @@ static void action_paste_files_update(ui_view* view, void* data, float* progress return; } - if(pasteData->processed >= pasteData->total) { - progressbar_destroy(view); - ui_pop(); + if(!pasteData->started || pasteData->currProcessed >= pasteData->currTotal) { + if(pasteData->started) { + if(pasteData->currSrc != 0) { + FSFILE_Close(pasteData->currSrc); + pasteData->currSrc = 0; + } - ui_push(prompt_create("Success", "Contents pasted.", COLOR_TEXT, false, data, NULL, action_paste_files_draw_top, action_paste_files_done_onresponse)); - } else { - FS_Archive* srcArchive = clipboard_get_archive(); - char* srcPath = pasteData->contents[pasteData->processed]; - FS_Path srcFsPath = fsMakePath(PATH_ASCII, srcPath); + if(pasteData->currDst != 0) { + FSFILE_Close(pasteData->currDst); + pasteData->currDst = 0; + } - char baseDstPath[PATH_MAX]; - if(pasteData->base->isDirectory) { - strncpy(baseDstPath, pasteData->base->path, PATH_MAX); - } else { - util_get_parent_path(baseDstPath, pasteData->base->path, PATH_MAX); + if(pasteData->base->archive->id == ARCHIVE_USER_SAVEDATA) { + FSUSER_ControlArchive(*pasteData->base->archive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0); + } + + pasteData->currProcessed = 0; + pasteData->currTotal = 0; + + pasteData->processed++; } - FS_Archive* dstArchive = pasteData->base->archive; - char dstPath[PATH_MAX]; - util_get_parent_path(dstPath, clipboard_get_path(), PATH_MAX); - snprintf(dstPath, PATH_MAX, "%s%s", baseDstPath, srcPath + strlen(dstPath)); - FS_Path dstFsPath = fsMakePath(PATH_ASCII, dstPath); + if(pasteData->processed >= pasteData->total) { + ui_pop(); + progressbar_destroy(view); - Result res = 0; - - if(util_is_dir(srcArchive, srcPath)) { - res = FSUSER_CreateDirectory(*dstArchive, dstFsPath, 0); + ui_push(prompt_create("Success", "Contents pasted.", COLOR_TEXT, false, data, NULL, action_paste_files_draw_top, action_paste_files_done_onresponse)); + return; } else { - Handle srcFileHandle; - if(R_SUCCEEDED(res = FSUSER_OpenFile(&srcFileHandle, *srcArchive, srcFsPath, FS_OPEN_READ, 0))) { - Handle dstFileHandle; - if(R_SUCCEEDED(res = FSUSER_OpenFile(&dstFileHandle, *dstArchive, dstFsPath, FS_OPEN_WRITE | FS_OPEN_CREATE, 0))) { - u32 bytesRead = 0; - u32 offset = 0; - u8* buffer = (u8*) calloc(1, 1024 * 512); - while(R_SUCCEEDED(FSFILE_Read(srcFileHandle, &bytesRead, offset, buffer, 1024 * 512)) && bytesRead > 0) { - u32 bytesWritten = 0; - if(R_FAILED(res = FSFILE_Write(dstFileHandle, &bytesWritten, offset, buffer, bytesRead, 0))) { - break; - } + FS_Archive* srcArchive = clipboard_get_archive(); + char* srcPath = pasteData->contents[pasteData->processed]; - offset += bytesWritten; - } + char baseDstPath[PATH_MAX]; + if(pasteData->base->isDirectory) { + strncpy(baseDstPath, pasteData->base->path, PATH_MAX); + } else { + util_get_parent_path(baseDstPath, pasteData->base->path, PATH_MAX); + } - free(buffer); + FS_Archive* dstArchive = pasteData->base->archive; + char dstPath[PATH_MAX]; + util_get_parent_path(dstPath, clipboard_get_path(), PATH_MAX); + snprintf(dstPath, PATH_MAX, "%s%s", baseDstPath, srcPath + strlen(dstPath)); - FSFILE_Close(dstFileHandle); + Result res = 0; - if(R_SUCCEEDED(res) && dstArchive->id == ARCHIVE_USER_SAVEDATA) { - res = FSUSER_ControlArchive(*dstArchive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0); - } + if(util_is_dir(srcArchive, srcPath)) { + res = FSUSER_CreateDirectory(*dstArchive, fsMakePath(PATH_ASCII, dstPath), 0); + } else { + if(R_SUCCEEDED(res = FSUSER_OpenFile(&pasteData->currSrc, *srcArchive, fsMakePath(PATH_ASCII, srcPath), FS_OPEN_READ, 0)) && R_SUCCEEDED(res = FSFILE_GetSize(pasteData->currSrc, &pasteData->currTotal))) { + res = FSUSER_OpenFile(&pasteData->currDst, *dstArchive, fsMakePath(PATH_ASCII, dstPath), FS_OPEN_WRITE | FS_OPEN_CREATE, 0); + } + } + + if(R_FAILED(res)) { + if(pasteData->currSrc != 0) { + FSFILE_Close(pasteData->currSrc); + pasteData->currSrc = 0; } - FSFILE_Close(srcFileHandle); + if(pasteData->currDst != 0) { + FSFILE_Close(pasteData->currDst); + pasteData->currDst = 0; + } + + if(pasteData->processed >= pasteData->total - 1) { + ui_pop(); + progressbar_destroy(view); + } + + if(strlen(srcPath) > 48) { + error_display_res(pasteData->base, ui_draw_file_info, res, "Failed to paste content.\n%.45s...", srcPath); + } else { + error_display_res(pasteData->base, ui_draw_file_info, res, "Failed to paste content.\n%.48s", srcPath); + } + + if(pasteData->processed >= pasteData->total - 1) { + action_paste_files_free_data(pasteData); + + return; + } + } else { + *pasteData->populated = false; + + pasteData->started = true; + } + } + } else if(pasteData->currSrc != 0 && pasteData->currDst != 0) { + Result res = 0; + + u32 size = PASTE_BUFFER_SIZE; + if((u64) size > pasteData->currTotal - pasteData->currProcessed) { + size = (u32) (pasteData->currTotal - pasteData->currProcessed); + } + + u32 bytesRead = 0; + if(R_SUCCEEDED(res = FSFILE_Read(pasteData->currSrc, &bytesRead, pasteData->currProcessed, pasteData->buffer, size)) && bytesRead > 0) { + u32 bytesWritten = 0; + if(R_SUCCEEDED(res = FSFILE_Write(pasteData->currDst, &bytesWritten, pasteData->currProcessed, pasteData->buffer, bytesRead, 0))) { + pasteData->currProcessed += bytesWritten; } } if(R_FAILED(res)) { - if(pasteData->processed >= pasteData->total - 1) { - ui_pop(); + if(pasteData->currSrc != 0) { + FSFILE_Close(pasteData->currSrc); + pasteData->currSrc = 0; } + if(pasteData->currDst != 0) { + FSFILE_Close(pasteData->currDst); + pasteData->currDst = 0; + } + + if(pasteData->processed >= pasteData->total - 1) { + ui_pop(); + progressbar_destroy(view); + } + + char* srcPath = pasteData->contents[pasteData->processed]; if(strlen(srcPath) > 48) { error_display_res(pasteData->base, ui_draw_file_info, res, "Failed to paste content.\n%.45s...", srcPath); } else { error_display_res(pasteData->base, ui_draw_file_info, res, "Failed to paste content.\n%.48s", srcPath); } + pasteData->currProcessed = pasteData->currTotal; + if(pasteData->processed >= pasteData->total - 1) { action_paste_files_free_data(pasteData); - progressbar_destroy(view); + return; } - } else { - *pasteData->populated = false; } - - pasteData->processed++; - - *progress = (float) pasteData->processed / (float) pasteData->total; - snprintf(progressText, PROGRESS_TEXT_MAX, "%lu / %lu", pasteData->processed, pasteData->total); } + + *progress = pasteData->currTotal != 0 ? (float) ((double) pasteData->currProcessed / (double) pasteData->currTotal) : 1; + snprintf(progressText, PROGRESS_TEXT_MAX, "%lu / %lu\n%.2f MB / %.2f MB", pasteData->processed, pasteData->total, pasteData->currProcessed / 1024.0 / 1024.0, pasteData->currTotal / 1024.0 / 1024.0); } static void action_paste_files_onresponse(ui_view* view, void* data, bool response) { @@ -155,6 +230,12 @@ void action_paste_contents(file_info* info, bool* populated) { paste_files_data* data = (paste_files_data*) calloc(1, sizeof(paste_files_data)); data->base = info; data->populated = populated; + data->started = false; + data->buffer = (u8*) calloc(1, PASTE_BUFFER_SIZE); + data->currSrc = 0; + data->currDst = 0; + data->currProcessed = 0; + data->currTotal = 0; data->processed = 0; Result res = 0; diff --git a/source/ui/section/tickets.c b/source/ui/section/tickets.c index c639710..f1c94f2 100644 --- a/source/ui/section/tickets.c +++ b/source/ui/section/tickets.c @@ -4,7 +4,6 @@ #include <3ds.h> #include "action/action.h" -#include "task/task.h" #include "../../screen.h" #include "section.h"