forked from Mirror/GodMode9
Added ability to calculate & compare file SHA-256
This commit is contained in:
parent
369061cf5b
commit
663aa681f6
48
source/fs.c
48
source/fs.c
@ -2,6 +2,7 @@
|
|||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
#include "sha.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
|
||||||
#define MAIN_BUFFER ((u8*)0x21200000)
|
#define MAIN_BUFFER ((u8*)0x21200000)
|
||||||
@ -204,6 +205,53 @@ size_t FileGetSize(const char* path) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileGetSha256(const char* path, u8* sha256) {
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
sha_init(SHA256_MODE);
|
||||||
|
ShowProgress(0, 0, path);
|
||||||
|
if (GetVirtualSource(path)) { // for virtual files
|
||||||
|
VirtualFile vfile;
|
||||||
|
u32 fsize;
|
||||||
|
|
||||||
|
if (!FindVirtualFile(&vfile, path, 0))
|
||||||
|
return false;
|
||||||
|
fsize = vfile.size;
|
||||||
|
|
||||||
|
for (size_t pos = 0; (pos < fsize) && ret; pos += MAIN_BUFFER_SIZE) {
|
||||||
|
UINT read_bytes = min(MAIN_BUFFER_SIZE, fsize - pos);
|
||||||
|
if (ReadVirtualFile(&vfile, MAIN_BUFFER, pos, read_bytes, NULL) != 0)
|
||||||
|
ret = false;
|
||||||
|
if (!ShowProgress(pos + read_bytes, fsize, path))
|
||||||
|
ret = false;
|
||||||
|
sha_update(MAIN_BUFFER, read_bytes);
|
||||||
|
}
|
||||||
|
} else { // for regular FAT files
|
||||||
|
FIL file;
|
||||||
|
size_t fsize;
|
||||||
|
|
||||||
|
if (f_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK)
|
||||||
|
return false;
|
||||||
|
fsize = f_size(&file);
|
||||||
|
f_lseek(&file, 0);
|
||||||
|
f_sync(&file);
|
||||||
|
|
||||||
|
for (size_t pos = 0; (pos < fsize) && ret; pos += MAIN_BUFFER_SIZE) {
|
||||||
|
UINT bytes_read = 0;
|
||||||
|
if (f_read(&file, MAIN_BUFFER, MAIN_BUFFER_SIZE, &bytes_read) != FR_OK)
|
||||||
|
ret = false;
|
||||||
|
if (!ShowProgress(pos + bytes_read, fsize, path))
|
||||||
|
ret = false;
|
||||||
|
sha_update(MAIN_BUFFER, bytes_read);
|
||||||
|
}
|
||||||
|
f_close(&file);
|
||||||
|
}
|
||||||
|
ShowProgress(1, 1, path);
|
||||||
|
sha_get(sha256);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool PathCopyVirtual(const char* destdir, const char* orig) {
|
bool PathCopyVirtual(const char* destdir, const char* orig) {
|
||||||
char dest[256]; // maximum path name length in FAT
|
char dest[256]; // maximum path name length in FAT
|
||||||
char* oname = strrchr(orig, '/');
|
char* oname = strrchr(orig, '/');
|
||||||
|
@ -47,6 +47,9 @@ size_t FileGetData(const char* path, u8* data, size_t size, size_t foffset);
|
|||||||
/** Get size of file **/
|
/** Get size of file **/
|
||||||
size_t FileGetSize(const char* path);
|
size_t FileGetSize(const char* path);
|
||||||
|
|
||||||
|
/** Get SHA-256 of file **/
|
||||||
|
bool FileGetSha256(const char* path, u8* sha256);
|
||||||
|
|
||||||
/** Recursively copy a file or directory **/
|
/** Recursively copy a file or directory **/
|
||||||
bool PathCopy(const char* destdir, const char* orig);
|
bool PathCopy(const char* destdir, const char* orig);
|
||||||
|
|
||||||
|
@ -335,9 +335,46 @@ u32 GodMode() {
|
|||||||
scroll = 0;
|
scroll = 0;
|
||||||
} else cursor = 0;
|
} else cursor = 0;
|
||||||
} else if ((pad_state & BUTTON_A) && (curr_entry->type == T_FILE)) { // process a file
|
} else if ((pad_state & BUTTON_A) && (curr_entry->type == T_FILE)) { // process a file
|
||||||
u32 file_type = IdentifyImage(curr_entry->path);
|
u32 file_type = IdentifyImage(curr_entry->path);
|
||||||
if (file_type && (PathToNumFS(curr_entry->path) == 0) && // try to mount image / only on SD
|
char pathstr[32 + 1];
|
||||||
ShowPrompt(true, "This looks like a %s image\nTry to mount it?", (file_type == IMG_NAND) ? "NAND" : "FAT")) {
|
const char* options[4];
|
||||||
|
u32 n_opt = 2;
|
||||||
|
|
||||||
|
TruncateString(pathstr, curr_entry->path, 32, 8);
|
||||||
|
options[0] = "Show in Hexviewer";
|
||||||
|
options[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";
|
||||||
|
n_opt = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 user_select = ShowSelectPrompt(n_opt, options, pathstr);
|
||||||
|
if (user_select == 1) { // -> show in hex viewer
|
||||||
|
static bool show_instr = true;
|
||||||
|
if (show_instr) {
|
||||||
|
ShowPrompt(false, "HexViewer Controls:\n \n\x18\x19\x1A\x1B(+R) - Scroll\nR+Y - Switch view\nB - Exit\n");
|
||||||
|
show_instr = false;
|
||||||
|
}
|
||||||
|
HexViewer(curr_entry->path);
|
||||||
|
} else if (user_select == 2) { // -> calculate SHA-256
|
||||||
|
static char pathstr_prev[32 + 1] = { 0 };
|
||||||
|
static u8 sha256_prev[32] = { 0 };
|
||||||
|
u8 sha256[32];
|
||||||
|
if (!FileGetSha256(curr_entry->path, sha256)) {
|
||||||
|
ShowPrompt(false, "Calculating SHA-256: failed!");
|
||||||
|
} else {
|
||||||
|
ShowPrompt(false, "%s\n%08X%08X%08X%08X\n%08X%08X%08X%08X%s%s",
|
||||||
|
pathstr,
|
||||||
|
getbe32(sha256 + 0), getbe32(sha256 + 4),
|
||||||
|
getbe32(sha256 + 8), getbe32(sha256 + 12),
|
||||||
|
getbe32(sha256 + 16), getbe32(sha256 + 20),
|
||||||
|
getbe32(sha256 + 24), getbe32(sha256 + 28),
|
||||||
|
(memcmp(sha256, sha256_prev, 32) == 0) ? "\n \nIdentical with previous file:\n" : "",
|
||||||
|
(memcmp(sha256, sha256_prev, 32) == 0) ? pathstr_prev : "");
|
||||||
|
strncpy(pathstr_prev, pathstr, 32 + 1);
|
||||||
|
memcpy(sha256_prev, sha256, 32);
|
||||||
|
}
|
||||||
|
} else if (user_select == 3) { // -> mount as image
|
||||||
DeinitExtFS();
|
DeinitExtFS();
|
||||||
u32 mount_state = MountImage(curr_entry->path);
|
u32 mount_state = MountImage(curr_entry->path);
|
||||||
InitExtFS();
|
InitExtFS();
|
||||||
@ -353,9 +390,6 @@ u32 GodMode() {
|
|||||||
}
|
}
|
||||||
if (clipboard->n_entries && (strcspn(clipboard->entry[0].path, IMG_DRV) == 0))
|
if (clipboard->n_entries && (strcspn(clipboard->entry[0].path, IMG_DRV) == 0))
|
||||||
clipboard->n_entries = 0; // remove invalid clipboard stuff
|
clipboard->n_entries = 0; // remove invalid clipboard stuff
|
||||||
} else if (FileGetSize(curr_entry->path) &&
|
|
||||||
ShowPrompt(true, "Show HexViewer?\n \nControls:\n\x18\x19\x1A\x1B(+R) - Scroll\nR+Y - Switch view\nB - Exit\n")) {
|
|
||||||
HexViewer(curr_entry->path);
|
|
||||||
}
|
}
|
||||||
} else if (*current_path && ((pad_state & BUTTON_B) || // one level down
|
} else if (*current_path && ((pad_state & BUTTON_B) || // one level down
|
||||||
((pad_state & BUTTON_A) && (curr_entry->type == T_DOTDOT)))) {
|
((pad_state & BUTTON_A) && (curr_entry->type == T_DOTDOT)))) {
|
||||||
|
@ -25,7 +25,7 @@ VirtualFile virtualFileTemplates[] = {
|
|||||||
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x05, VFLAG_ON_N3DS },
|
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x05, VFLAG_ON_N3DS },
|
||||||
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x04, VFLAG_ON_NO3DS },
|
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x04, VFLAG_ON_NO3DS },
|
||||||
{ "nand.bin" , 0x00000000, 0x00000000, 0xFF, VFLAG_ON_NAND | VFLAG_NAND_SIZE | VFLAG_A9LH_AREA },
|
{ "nand.bin" , 0x00000000, 0x00000000, 0xFF, VFLAG_ON_NAND | VFLAG_NAND_SIZE | VFLAG_A9LH_AREA },
|
||||||
{ "nand_minsize.bin" , 0x00000000, 0x3AF00000, 0xFF, VFLAG_ON_O3DS | VFLAG_A9LH_AREA},
|
{ "nand_minsize.bin" , 0x00000000, 0x3AF00000, 0xFF, VFLAG_ON_O3DS | VFLAG_A9LH_AREA },
|
||||||
{ "nand_minsize.bin" , 0x00000000, 0x4D800000, 0xFF, VFLAG_ON_N3DS | VFLAG_ON_NO3DS | VFLAG_A9LH_AREA },
|
{ "nand_minsize.bin" , 0x00000000, 0x4D800000, 0xFF, VFLAG_ON_N3DS | VFLAG_ON_NO3DS | VFLAG_A9LH_AREA },
|
||||||
{ "sector0x96.bin" , 0x00012C00, 0x00000200, 0xFF, VFLAG_ON_NAND | VFLAG_A9LH_AREA },
|
{ "sector0x96.bin" , 0x00012C00, 0x00000200, 0xFF, VFLAG_ON_NAND | VFLAG_A9LH_AREA },
|
||||||
{ "nand_hdr.bin" , 0x00000000, 0x00000200, 0xFF, VFLAG_ON_NAND | VFLAG_A9LH_AREA },
|
{ "nand_hdr.bin" , 0x00000000, 0x00000200, 0xFF, VFLAG_ON_NAND | VFLAG_A9LH_AREA },
|
||||||
|
47
source/ui.c
47
source/ui.c
@ -203,7 +203,7 @@ bool ShowPrompt(bool ask, const char *format, ...)
|
|||||||
while (true) {
|
while (true) {
|
||||||
u32 pad_state = InputWait();
|
u32 pad_state = InputWait();
|
||||||
if (pad_state & BUTTON_A) break;
|
if (pad_state & BUTTON_A) break;
|
||||||
else if (ask && (pad_state & BUTTON_B)) {
|
else if (pad_state & BUTTON_B) {
|
||||||
ret = false;
|
ret = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -274,6 +274,51 @@ bool ShowUnlockSequence(u32 seqlvl, const char *format, ...) {
|
|||||||
return (lvl >= len);
|
return (lvl >= len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...) {
|
||||||
|
u32 str_width, str_height;
|
||||||
|
u32 x, y, yopt;
|
||||||
|
u32 sel = 0;
|
||||||
|
|
||||||
|
char str[512] = {}; // 512 should be more than enough
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, format);
|
||||||
|
vsnprintf(str, 512, format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
if (n == 0) return 0; // check for low number of options
|
||||||
|
else if (n == 1) return ShowPrompt(true, "%s\n%s?", str, options[0]) ? 1 : 0;
|
||||||
|
|
||||||
|
str_width = GetDrawStringWidth(str);
|
||||||
|
str_height = GetDrawStringHeight(str) + (n * 12) + (3 * 10);
|
||||||
|
if (str_width < 18*8) str_width = 18 * 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;
|
||||||
|
|
||||||
|
ClearScreenF(true, false, COLOR_STD_BG);
|
||||||
|
DrawStringF(true, x, y, COLOR_STD_FONT, COLOR_STD_BG, str);
|
||||||
|
DrawStringF(true, x, yopt + (n*12) + 10, COLOR_STD_FONT, COLOR_STD_BG, "(<A> select, <B> cancel)");
|
||||||
|
while (true) {
|
||||||
|
for (u32 i = 0; i < n; i++) {
|
||||||
|
DrawStringF(true, x, yopt + (12*i), (sel == i) ? COLOR_STD_FONT : COLOR_LIGHTGREY, COLOR_STD_BG, "%2.2s %s",
|
||||||
|
(sel == i) ? "->" : "", options[i]);
|
||||||
|
}
|
||||||
|
u32 pad_state = InputWait();
|
||||||
|
if (pad_state & BUTTON_DOWN) sel = (sel+1) % n;
|
||||||
|
else if (pad_state & BUTTON_UP) sel = (sel+n-1) % n;
|
||||||
|
else if (pad_state & BUTTON_A) break;
|
||||||
|
else if (pad_state & BUTTON_B) {
|
||||||
|
sel = n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearScreenF(true, false, COLOR_STD_BG);
|
||||||
|
|
||||||
|
return (sel >= n) ? 0 : sel + 1;
|
||||||
|
}
|
||||||
|
|
||||||
bool ShowInputPrompt(char* inputstr, u32 max_size, const char *format, ...) {
|
bool ShowInputPrompt(char* inputstr, u32 max_size, const char *format, ...) {
|
||||||
const char* alphabet = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz(){}[]'`^,~!@#$%&0123456789=+-_.";
|
const char* alphabet = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz(){}[]'`^,~!@#$%&0123456789=+-_.";
|
||||||
const u32 alphabet_size = strnlen(alphabet, 256);
|
const u32 alphabet_size = strnlen(alphabet, 256);
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#define COLOR_TINTEDBLUE RGB(0x60, 0x60, 0x80)
|
#define COLOR_TINTEDBLUE RGB(0x60, 0x60, 0x80)
|
||||||
#define COLOR_TINTEDYELLOW RGB(0xD0, 0xD0, 0x60)
|
#define COLOR_TINTEDYELLOW RGB(0xD0, 0xD0, 0x60)
|
||||||
#define COLOR_TINTEDGREEN RGB(0x70, 0x80, 0x70)
|
#define COLOR_TINTEDGREEN RGB(0x70, 0x80, 0x70)
|
||||||
|
#define COLOR_LIGHTGREY RGB(0xB0, 0xB0, 0xB0)
|
||||||
#define COLOR_DARKGREY RGB(0x50, 0x50, 0x50)
|
#define COLOR_DARKGREY RGB(0x50, 0x50, 0x50)
|
||||||
#define COLOR_DARKESTGREY RGB(0x20, 0x20, 0x20)
|
#define COLOR_DARKESTGREY RGB(0x20, 0x20, 0x20)
|
||||||
|
|
||||||
@ -72,5 +73,6 @@ void FormatBytes(char* str, u64 bytes);
|
|||||||
|
|
||||||
bool ShowPrompt(bool ask, const char *format, ...);
|
bool ShowPrompt(bool ask, const char *format, ...);
|
||||||
bool ShowUnlockSequence(u32 seqlvl, const char *format, ...);
|
bool ShowUnlockSequence(u32 seqlvl, const char *format, ...);
|
||||||
|
u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...);
|
||||||
bool ShowInputPrompt(char* inputstr, u32 max_size, const char *format, ...);
|
bool ShowInputPrompt(char* inputstr, u32 max_size, const char *format, ...);
|
||||||
bool ShowProgress(u64 current, u64 total, const char* opstr);
|
bool ShowProgress(u64 current, u64 total, const char* opstr);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user