diff --git a/source/fs.c b/source/fs.c index 90200dc..d3ff698 100644 --- a/source/fs.c +++ b/source/fs.c @@ -403,7 +403,7 @@ bool PathCopyVirtual(const char* destdir, const char* orig) { return ret; } -bool PathCopyWorker(char* dest, char* orig, bool overwrite) { +bool PathCopyWorker(char* dest, char* orig, bool overwrite, bool move) { FILINFO fno = {.lfname = NULL}; bool ret = false; @@ -442,13 +442,15 @@ bool PathCopyWorker(char* dest, char* orig, bool overwrite) { // the copy process takes place here if (!ShowProgress(0, 0, orig)) return false; - if (fno.fattrib & AM_DIR) { // processing folders... + if (move && f_stat(dest, NULL) != FR_OK) { // moving if dest not existing + ret = (f_rename(orig, dest) == FR_OK); + } else if (fno.fattrib & AM_DIR) { // processing folders (same for move & copy) DIR pdir; char* fname = orig + strnlen(orig, 256); // create the destination folder if it does not already exist if ((f_opendir(&pdir, dest) != FR_OK) && (f_mkdir(dest) != FR_OK)) { - ShowPrompt(false, "Error: Cannot create output dir"); + ShowPrompt(false, "Error: Overwriting file with dir"); return false; } else f_closedir(&pdir); @@ -466,12 +468,22 @@ bool PathCopyWorker(char* dest, char* orig, bool overwrite) { if (fno.fname[0] == 0) { ret = true; break; - } else if (!PathCopyWorker(dest, orig, overwrite)) { + } else if (!PathCopyWorker(dest, orig, overwrite, move)) { break; } } f_closedir(&pdir); - } else { // processing files... + } else if (move) { // moving if destination exists + if (f_stat(dest, &fno) != FR_OK) + return false; + if (fno.fattrib & AM_DIR) { + ShowPrompt(false, "Error: Overwriting dir with file"); + return false; + } + if (f_unlink(dest) != FR_OK) + return false; + ret = (f_rename(orig, dest) == FR_OK); + } else { // copying files FIL ofile; FIL dfile; size_t fsize; @@ -486,7 +498,7 @@ bool PathCopyWorker(char* dest, char* orig, bool overwrite) { } if (f_open(&dfile, dest, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) { - ShowPrompt(false, "Error: Cannot create output file"); + ShowPrompt(false, "Error: Cannot create destination file"); f_close(&ofile); return false; } @@ -533,7 +545,24 @@ bool PathCopy(const char* destdir, const char* orig) { char fopath[256]; strncpy(fdpath, destdir, 255); strncpy(fopath, orig, 255); - return PathCopyWorker(fdpath, fopath, false); + return PathCopyWorker(fdpath, fopath, false, false); + } +} + +bool PathMove(const char* destdir, const char* orig) { + if (!CheckWritePermissions(destdir)) return false; + if (GetVirtualSource(destdir) || GetVirtualSource(orig)) { + ShowPrompt(false, "Error: Moving virtual files not possible"); + return false; + } else { + char fdpath[256]; // 256 is the maximum length of a full path + char fopath[256]; + strncpy(fdpath, destdir, 255); + strncpy(fopath, orig, 255); + bool same_drv = (PathToNumFS(orig) == PathToNumFS(destdir)); + bool res = PathCopyWorker(fdpath, fopath, false, same_drv); + if (res) PathDelete(orig); + return res; } } diff --git a/source/fs.h b/source/fs.h index 0c9f398..4fda475 100644 --- a/source/fs.h +++ b/source/fs.h @@ -53,6 +53,9 @@ bool FileGetSha256(const char* path, u8* sha256); /** Recursively copy a file or directory **/ bool PathCopy(const char* destdir, const char* orig); +/** Recursively move a file or directory **/ +bool PathMove(const char* destdir, const char* orig); + /** Recursively delete a file or directory **/ bool PathDelete(const char* path); diff --git a/source/godmode.c b/source/godmode.c index e1421f6..3c0d936 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -7,7 +7,7 @@ #include "virtual.h" #include "image.h" -#define VERSION "0.3.7" +#define VERSION "0.3.9" #define N_PANES 2 #define IMG_DRV "789I" @@ -337,18 +337,18 @@ u32 GodMode() { } else if ((pad_state & BUTTON_A) && (curr_entry->type == T_FILE)) { // process a file u32 file_type = IdentifyImage(curr_entry->path); char pathstr[32 + 1]; - const char* options[4]; + const char* optionstr[4]; u32 n_opt = 2; TruncateString(pathstr, curr_entry->path, 32, 8); - options[0] = "Show in Hexviewer"; - options[1] = "Calculate SHA-256"; + optionstr[0] = "Show in Hexviewer"; + optionstr[1] = "Calculate SHA-256"; if (file_type && (PathToNumFS(curr_entry->path) == 0)) { - options[2] = (file_type == IMG_NAND) ? "Mount as NAND image" : "Mount as FAT image"; + optionstr[2] = (file_type == IMG_NAND) ? "Mount as NAND image" : "Mount as FAT image"; n_opt = 3; } - u32 user_select = ShowSelectPrompt(n_opt, options, pathstr); + u32 user_select = ShowSelectPrompt(n_opt, optionstr, pathstr); if (user_select == 1) { // -> show in hex viewer static bool show_instr = true; if (show_instr) { @@ -510,20 +510,26 @@ u32 GodMode() { if (clipboard->n_entries) last_clipboard_size = clipboard->n_entries; } else if (pad_state & BUTTON_Y) { // paste files + const char* optionstr[2] = { "Copy path(s)", "Move path(s)" }; char promptstr[64]; + u32 user_select; if (clipboard->n_entries == 1) { char namestr[20+1]; TruncateString(namestr, clipboard->entry[0].name, 20, 12); - snprintf(promptstr, 64, "Copy \"%s\" here?", namestr); - } else snprintf(promptstr, 64, "Copy %lu path(s) here?", clipboard->n_entries); - if (ShowPrompt(true, promptstr)) { + snprintf(promptstr, 64, "Copy / Move \"%s\" here?", namestr); + } else snprintf(promptstr, 64, "Copy / Move %lu paths here?", clipboard->n_entries); + if ((user_select = ShowSelectPrompt(2, optionstr, promptstr))) { for (u32 c = 0; c < clipboard->n_entries; c++) { - if (!PathCopy(current_path, clipboard->entry[c].path)) { - char namestr[36+1]; - TruncateString(namestr, clipboard->entry[c].name, 36, 12); + char namestr[36+1]; + TruncateString(namestr, clipboard->entry[c].name, 36, 12); + if ((user_select == 1) && !PathCopy(current_path, clipboard->entry[c].path)) { if (c + 1 < clipboard->n_entries) { if (!ShowPrompt(true, "Failed copying path:\n%s\nProcess remaining?", namestr)) break; } else ShowPrompt(false, "Failed copying path:\n%s", namestr); + } else if ((user_select == 2) && !PathMove(current_path, clipboard->entry[c].path)) { + if (c + 1 < clipboard->n_entries) { + if (!ShowPrompt(true, "Failed moving path:\n%s\nProcess remaining?", namestr)) break; + } else ShowPrompt(false, "Failed moving path:\n%s", namestr); } } } diff --git a/source/ui.c b/source/ui.c index 8cee9a0..dd0909e 100644 --- a/source/ui.c +++ b/source/ui.c @@ -291,7 +291,7 @@ u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...) { str_width = GetDrawStringWidth(str); str_height = GetDrawStringHeight(str) + (n * 12) + (3 * 10); - if (str_width < 18*8) str_width = 18 * 8; + if (str_width < 24*8) str_width = 24 * 8; x = (str_width >= SCREEN_WIDTH_TOP) ? 0 : (SCREEN_WIDTH_TOP - str_width) / 2; y = (str_height >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - str_height) / 2; yopt = y + GetDrawStringHeight(str) + 8; @@ -341,7 +341,7 @@ bool ShowInputPrompt(char* inputstr, u32 max_size, const char *format, ...) { str_width = GetDrawStringWidth(str); str_height = GetDrawStringHeight(str) + (8*10); - if (str_width < 24) str_width = 24; + if (str_width < (24*8)) str_width = 24 * 8; x = (str_width >= SCREEN_WIDTH_TOP) ? 0 : (SCREEN_WIDTH_TOP - str_width) / 2; y = (str_height >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - str_height) / 2;