From ef76834ef40f956d14b5a420047ba0631ddae45c Mon Sep 17 00:00:00 2001 From: "Such Meme, Many Skill" Date: Sat, 4 Jan 2020 20:18:26 +0100 Subject: [PATCH] Implement folder copy + Change error messaging internally + inproved recursive file deletion --- source/gfx/gfx.c | 20 +++-- source/gfx/gfx.h | 2 + source/tegraexplorer/fs.c | 168 ++++++++++++++++++++++++++++------- source/tegraexplorer/fs.h | 5 +- source/tegraexplorer/gfx.c | 31 ++++++- source/tegraexplorer/gfx.h | 5 +- source/tegraexplorer/te.c | 6 +- source/tegraexplorer/tools.c | 2 +- 8 files changed, 189 insertions(+), 50 deletions(-) diff --git a/source/gfx/gfx.c b/source/gfx/gfx.c index 5371f4d..3d2c9cb 100644 --- a/source/gfx/gfx.c +++ b/source/gfx/gfx.c @@ -329,15 +329,10 @@ void gfx_put_big_sep() gfx_con.fntsz = prevFontSize; } -void gfx_printf(const char *fmt, ...) +void gfx_vprintf(const char *fmt, va_list ap) { - if (gfx_con.mute) - return; - - va_list ap; int fill, fcnt; - va_start(ap, fmt); while(*fmt) { if(*fmt == '%') @@ -389,7 +384,7 @@ void gfx_printf(const char *fmt, ...) gfx_putc('%'); break; case '\0': - goto out; + return; default: gfx_putc('%'); gfx_putc(*fmt); @@ -400,8 +395,17 @@ void gfx_printf(const char *fmt, ...) gfx_putc(*fmt); fmt++; } +} + +void gfx_printf(const char *fmt, ...) +{ + if (gfx_con.mute) + return; + + va_list ap; + va_start(ap, fmt); + gfx_vprintf(fmt, ap); - out: va_end(ap); } diff --git a/source/gfx/gfx.h b/source/gfx/gfx.h index a5c9fd6..f3533b8 100644 --- a/source/gfx/gfx.h +++ b/source/gfx/gfx.h @@ -20,6 +20,7 @@ #define _GFX_H_ #include "../../common/common_gfx.h" +#include #define EPRINTF(text) gfx_printf("%k"text"%k\n", 0xFFFF0000, 0xFFCCCCCC) #define EPRINTFARGS(text, args...) gfx_printf("%k"text"%k\n", 0xFFFF0000, args, 0xFFCCCCCC) @@ -37,6 +38,7 @@ void gfx_con_setpos(u32 x, u32 y); void gfx_putc(char c); void gfx_puts(const char *s); void gfx_printf(const char *fmt, ...); +void gfx_vprintf(const char *fmt, va_list ap); void gfx_hexdump(u32 base, const u8 *buf, u32 len); void gfx_set_pixel(u32 x, u32 y, u32 color); diff --git a/source/tegraexplorer/fs.c b/source/tegraexplorer/fs.c index f29c37f..b01ad08 100644 --- a/source/tegraexplorer/fs.c +++ b/source/tegraexplorer/fs.c @@ -29,10 +29,11 @@ menu_item explfilemenu[9] = { {"View Hex", COLOR_GREEN, HEXVIEW, 1} }; -menu_item explfoldermenu[4] = { +menu_item explfoldermenu[5] = { {"-- Folder Menu --\n", COLOR_BLUE, -1, 0}, {"Back", COLOR_WHITE, -1, 1}, {"Return to main menu\n", COLOR_BLUE, EXITFOLDER, 1}, + {"Copy to clipboard", COLOR_VIOLET, COPYFOLDER, 1}, {"Delete folder", COLOR_RED, DELETEFOLDER, 1} }; @@ -135,7 +136,7 @@ void viewbytes(char *path){ clearscreen(); res = f_open(&in, path, FA_READ | FA_OPEN_EXISTING); if (res != FR_OK){ - message("File Opening Failed", COLOR_RED); + message(COLOR_RED, "File Opening Failed\nErrcode %d", res); return; } @@ -146,7 +147,7 @@ void viewbytes(char *path){ res = f_read(&in, &print, 2048 * sizeof(u8), &size); if (res != FR_OK){ - message("Reading Failed", COLOR_RED); + message(COLOR_RED, "Reading Failed!\nErrcode %d", res); return; } @@ -166,8 +167,9 @@ void viewbytes(char *path){ f_close(&in); } -int copy(const char *locin, const char *locout, bool print){ +int copy(const char *locin, const char *locout, bool print, bool canCancel){ FIL in, out; + FILINFO in_info; u64 sizeoffile, sizecopied = 0, totalsize; UINT temp1, temp2; u8 *buff; @@ -183,6 +185,9 @@ int copy(const char *locin, const char *locout, bool print){ return 1; } + if (f_stat(locin, &in_info)) + return 1; + if (f_open(&out, locout, FA_CREATE_ALWAYS | FA_WRITE)){ return 2; } @@ -204,18 +209,23 @@ int copy(const char *locin, const char *locout, bool print){ sizecopied += temp1; if (print && 10 > i++){ - gfx_printf("%k[%d%%/100%%]%k", COLOR_GREEN, ((sizecopied * 100) / totalsize) ,COLOR_WHITE); + gfx_printf("%k[%d%%]%k", COLOR_GREEN, ((sizecopied * 100) / totalsize) ,COLOR_WHITE); gfx_con_setpos(x, y); - + i = 0; - if (btn_read() & BTN_VOL_DOWN){ - f_unlink(locout); - break; - } + if (canCancel) + if (btn_read() & BTN_VOL_DOWN){ + f_unlink(locout); + break; + } } } + if (in_info.fattrib & AM_ARC){ + f_chmod(locout, AM_ARC, AM_ARC); + } + f_close(&in); f_close(&out); free(buff); @@ -244,11 +254,11 @@ void copyfile(const char *path, const char *outfolder){ if (strcmp(rootpath, "emmc:/")) f_rename(path, outstring); else - message("\nMoving in emummc is not allowed!", COLOR_RED); + message(COLOR_RED, "\nMoving in emummc is not allowed!"); } else if (clipboardhelper & OPERATIONCOPY) { - res = copy(path, outstring, true); + res = copy(path, outstring, true, true); if (res){ gfx_printf("\n\n%kSomething went wrong while copying!\n\nErrcode: %d%k", COLOR_RED, res, COLOR_WHITE); btn_wait(); @@ -256,7 +266,7 @@ void copyfile(const char *path, const char *outfolder){ } else { - message("\nClipboard is empty!", COLOR_RED); + message(COLOR_RED, "\nClipboard is empty!"); } free (outstring); @@ -346,9 +356,8 @@ int readfolder(const char *path){ createfileobjects(getfolderentryamount(path)); if ((res = f_opendir(&dir, path))){ - char errmes[50] = ""; - sprintf(errmes, "Error during f_opendir: %d", res); - message(errmes, COLOR_RED); + message(COLOR_RED, "Error during f_opendir: %d", res); + return -1; } while (!f_readdir(&dir, &fno) && fno.fname[0]){ @@ -373,18 +382,20 @@ int delfile(const char *path, const char *filename){ return -1; } +void makestring(char *in, char **out){ + *out = (char *) malloc (strlen(in) + 1); + strcpy(*out, in); +} + int del_recursive(char *path){ DIR dir; FILINFO fno; int res; - char *localpath; - localpath = (char*) malloc (strlen(path) + 1); - strcpy(localpath, path); + char *localpath = NULL; + makestring(path, &localpath); if ((res = f_opendir(&dir, localpath))){ - char errmes[50] = ""; - sprintf(errmes, "Error during f_opendir: %d", res); - message(errmes, COLOR_RED); + message(COLOR_RED, "Error during f_opendir: %d", res); return -1; } @@ -392,8 +403,16 @@ int del_recursive(char *path){ if (fno.fattrib & AM_DIR) del_recursive(getnextloc(localpath, fno.fname)); - else if ((res = f_unlink(getnextloc(localpath, fno.fname)))) - return res; + else { + gfx_box(0, 47, 719, 63, COLOR_DEFAULT); + SWAPCOLOR(COLOR_RED); + gfx_printf("\r"); + gfx_print_length(37, fno.fname); + gfx_printf(" "); + + if ((res = f_unlink(getnextloc(localpath, fno.fname)))) + return res; + } } f_closedir(&dir); @@ -407,6 +426,86 @@ int del_recursive(char *path){ return 0; } +int copy_recursive(char *path, char *dstpath){ + DIR dir; + FILINFO fno; + int res; + char *startpath = NULL, *destpath = NULL, *destfoldername = NULL, *temp = NULL; + + makestring(path, &startpath); + makestring(strrchr(path, '/') + 1, &destfoldername); + + destpath = (char*) malloc (strlen(dstpath) + strlen(destfoldername) + 2); + sprintf(destpath, (dstpath[strlen(dstpath) - 1] == '/') ? "%s%s" : "%s/%s", dstpath, destfoldername); + + + if ((res = f_opendir(&dir, startpath))){ + message(COLOR_RED, "Error during f_opendir: %d", res); + return -1; + } + + f_mkdir(destpath); + + while (!f_readdir(&dir, &fno) && fno.fname[0]){ + if (fno.fattrib & AM_DIR){ + copy_recursive(getnextloc(startpath, fno.fname), destpath); + } + else { + gfx_box(0, 47, 719, 63, COLOR_DEFAULT); + SWAPCOLOR(COLOR_GREEN); + gfx_printf("\r"); + gfx_print_length(37, fno.fname); + gfx_printf(" "); + makestring(getnextloc(startpath, fno.fname), &temp); + + if ((res = copy(temp, getnextloc(destpath, fno.fname), true, false))){ + message(COLOR_RED, "Copy failed!\nErrcode %d", res); + return -1; + } + + free(temp); + } + } + + if (f_stat(startpath, &fno)) + return -2; + + if (fno.fattrib & AM_ARC){ + f_chmod(destpath, AM_ARC, AM_ARC); + } + + f_closedir(&dir); + free(startpath); + free(destpath); + free(destfoldername); + + return 0; +} + +void copyfolder(char *in, char *out){ + bool fatalerror = false; + int res; + + if (!strcmp(in, rootpath)){ + message(COLOR_RED, "In is root\nAborting!"); + fatalerror = true; + } + + if (strstr(out, in) != NULL && !fatalerror){ + message(COLOR_RED, "\nOut is a part of in!\nAborting"); + fatalerror = true; + } + + if (!fatalerror){ + clearscreen(); + gfx_printf("\nCopying folder, please wait\n"); + if ((res = copy_recursive(in, out))) + message(COLOR_RED, "copy_recursive() failed!\nErrcode %d", res); + } + + clipboardhelper = 0; +} + int filemenu(fs_entry file){ int temp; strlcpy(explfilemenu[1].name, file.name, 43); @@ -448,26 +547,28 @@ int filemenu(fs_entry file){ int foldermenu(){ int res; - char temp[50] = ""; - res = makemenu(explfoldermenu, 4); + res = makemenu(explfoldermenu, 5); switch (res){ case EXITFOLDER: return -1; case DELETEFOLDER: - if (makewaitmenu("Do you want to delete this folder?\nThe entire folder, with all subcontents\n will be deleted!!!\n\nPress vol+/- to cancel\n", "Press power to contine...", 7)){ + if (makewaitmenu("Do you want to delete this folder?\nThe entire folder, with all subcontents\n will be deleted!!!\n\nPress vol+/- to cancel\n", "Press power to contine...", 3)){ clearscreen(); - gfx_printf("\nDeleting folder, please wait..."); + gfx_printf("\nDeleting folder, please wait...\n"); if ((res = del_recursive(currentpath))){ - sprintf(temp, "Error during del_recursive()! %d", res); - message(temp, COLOR_RED); + message(COLOR_RED, "Error during del_recursive()! %d", res); } writecurpath(getprevloc(currentpath)); return readfolder(currentpath) + 1; } break; + case COPYFOLDER: + writeclipboard(currentpath, false, true); + break; } + return 0; } @@ -502,7 +603,12 @@ void fileexplorer(const char *startpath){ break; case -1: - copyfile(clipboard, currentpath); + if (clipboardhelper & ISDIR){ + copyfolder(clipboard, currentpath); + } + else { + copyfile(clipboard, currentpath); + } amount = readfolder(currentpath); break; diff --git a/source/tegraexplorer/fs.h b/source/tegraexplorer/fs.h index 89e5f20..9266f08 100644 --- a/source/tegraexplorer/fs.h +++ b/source/tegraexplorer/fs.h @@ -39,11 +39,12 @@ enum filemenuoptions { enum foldermenuoptions { EXITFOLDER = 1, - DELETEFOLDER + DELETEFOLDER, + COPYFOLDER }; int readfolder(const char *path); void fileexplorer(const char *startpath); bool checkfile(char* path); u64 getfilesize(char *path); -int copy(const char *locin, const char *locout, bool print); \ No newline at end of file +int copy(const char *locin, const char *locout, bool print, bool canCancel); \ No newline at end of file diff --git a/source/tegraexplorer/gfx.c b/source/tegraexplorer/gfx.c index d1f00b1..2d9a5e6 100644 --- a/source/tegraexplorer/gfx.c +++ b/source/tegraexplorer/gfx.c @@ -8,6 +8,7 @@ #include "gfx.h" #include "fs.h" #include "../mem/minerva.h" +#include const char fixedoptions[3][50] = { "Folder -> previous folder ", @@ -29,9 +30,16 @@ void clearscreen(){ gfx_printf("%k%KTegraexplorer v1.1.1%k%K\n", COLOR_DEFAULT, COLOR_WHITE, COLOR_WHITE, COLOR_DEFAULT); } -int message(char* message, u32 color){ +int message(u32 color, const char* message, ...){ + va_list ap; + va_start(ap, message); + clearscreen(); - gfx_printf("%k%s%k", color, message, COLOR_DEFAULT); + SWAPCOLOR(color); + + gfx_vprintf(message, ap); + + va_end(ap); return btn_wait(); } @@ -109,6 +117,22 @@ int makewaitmenu(char *initialmessage, char *hiddenmessage, int timer){ } } +void gfx_print_length(int size, char *toprint){ + char *temp; + temp = (char*) malloc (size + 1); + + if (strlen(toprint) > size){ + strlcpy(temp, toprint, size); + memset(temp + size - 3, '.', 3); + memset(temp + size, '\0', 1); + } + else + strcpy(temp, toprint); + + gfx_printf("%s", temp); + free(temp); +} + void printfsentry(fs_entry file, bool highlight, bool refresh){ int size = 0; char *display; @@ -123,6 +147,7 @@ void printfsentry(fs_entry file, bool highlight, bool refresh){ } else strcpy(display, file.name); + if (highlight) gfx_printf("%K%k", COLOR_WHITE, COLOR_DEFAULT); @@ -164,7 +189,7 @@ int makefilemenu(fs_entry *files, int amount, char *path){ bool refresh = false; clearscreen(); gfx_con_setpos(544, 0); - gfx_printf("%K%k%d\n%K%k%s%k\n\n", COLOR_WHITE, COLOR_DEFAULT, amount, COLOR_DEFAULT, COLOR_GREEN, path, COLOR_DEFAULT); + gfx_printf("%K%k%d files\n%K%k%s%k\n\n", COLOR_WHITE, COLOR_DEFAULT, amount, COLOR_DEFAULT, COLOR_GREEN, path, COLOR_DEFAULT); while (1){ gfx_con_setpos(0, 47); timer = get_tmr_ms(); diff --git a/source/tegraexplorer/gfx.h b/source/tegraexplorer/gfx.h index 5b2df77..1692323 100644 --- a/source/tegraexplorer/gfx.h +++ b/source/tegraexplorer/gfx.h @@ -6,8 +6,9 @@ #define RESETCOLOR gfx_printf("%k%K", COLOR_WHITE, COLOR_DEFAULT) int makemenu(menu_item menu[], int menuamount); -int message(char* message, u32 color); +int message(u32 color, const char* message, ...); void clearscreen(); int makefilemenu(fs_entry *files, int amount, char *path); void printbytes(u8 print[], u32 size, u32 offset); -int makewaitmenu(char *initialmessage, char *hiddenmessage, int timer); \ No newline at end of file +int makewaitmenu(char *initialmessage, char *hiddenmessage, int timer); +void gfx_print_length(int size, char *toprint); diff --git a/source/tegraexplorer/te.c b/source/tegraexplorer/te.c index 1efad6f..1180cf1 100644 --- a/source/tegraexplorer/te.c +++ b/source/tegraexplorer/te.c @@ -86,7 +86,7 @@ void te_main(){ int res; if (dump_biskeys() == -1){ - message("Biskeys failed to dump!\nEmmc will not be mounted!", COLOR_RED); + message(COLOR_RED, "Biskeys failed to dump!\nEmmc will not be mounted!"); mainmenu[1].property = -1; mainmenu[2].property = -1; mainmenu[3].property = -1; @@ -110,7 +110,7 @@ void te_main(){ fileexplorer("emmc:/"); } else - message("EMMC failed to mount!", COLOR_RED); + message(COLOR_RED, "EMMC failed to mount!"); } break; @@ -153,7 +153,7 @@ void te_main(){ break; case CREDITS: - message(CREDITS_MESSAGE, COLOR_WHITE); + message(COLOR_WHITE, CREDITS_MESSAGE); break; case EXIT: diff --git a/source/tegraexplorer/tools.c b/source/tegraexplorer/tools.c index cb1df22..0ff03a2 100644 --- a/source/tegraexplorer/tools.c +++ b/source/tegraexplorer/tools.c @@ -122,7 +122,7 @@ int dumpfirmware(){ else sprintf(syspath, "%s/%s", path, fno.fname); - ret = copy(syspath, sdpath, false); + ret = copy(syspath, sdpath, false, false); gfx_printf("%d %s\r", ++amount, fno.fname);