Allow injecting files into files

This commit is contained in:
d0k3 2016-06-17 19:28:43 +02:00
parent 3a59f37fc9
commit 56ac8c1e68
3 changed files with 96 additions and 6 deletions

View File

@ -301,6 +301,86 @@ bool FileGetSha256(const char* path, u8* sha256) {
return ret;
}
bool FileInjectFile(const char* dest, const char* orig, u32 offset) {
VirtualFile dvfile;
VirtualFile ovfile;
FIL ofile;
FIL dfile;
size_t osize;
size_t dsize;
bool vdest;
bool vorig;
bool ret;
if (!CheckWritePermissions(dest)) return false;
// open destination
if (GetVirtualSource(dest)) {
vdest = true;
if (!FindVirtualFile(&dvfile, dest, 0))
return false;
dsize = dvfile.size;
} else {
vdest = false;
if (f_open(&dfile, dest, FA_WRITE | FA_OPEN_EXISTING) != FR_OK)
return false;
dsize = f_size(&dfile);
f_lseek(&dfile, offset);
f_sync(&dfile);
}
// open origin
if (GetVirtualSource(orig)) {
vorig = true;
if (!FindVirtualFile(&ovfile, orig, 0)) {
if (!vdest) f_close(&dfile);
return false;
}
osize = ovfile.size;
} else {
vorig = false;
if (f_open(&ofile, orig, FA_READ | FA_OPEN_EXISTING) != FR_OK) {
if (!vdest) f_close(&dfile);
return false;
}
osize = f_size(&ofile);
f_lseek(&ofile, 0);
f_sync(&ofile);
}
// check file limits
if (offset + osize > dsize) {
ShowPrompt(false, "Operation would write beyond end of file");
if (!vdest) f_close(&dfile);
if (!vorig) f_close(&ofile);
return false;
}
ret = true;
for (size_t pos = 0; (pos < osize) && ret; pos += MAIN_BUFFER_SIZE) {
UINT read_bytes = min(MAIN_BUFFER_SIZE, osize - pos);
UINT bytes_read = read_bytes;
UINT bytes_written = read_bytes;
if ((!vorig && (f_read(&ofile, MAIN_BUFFER, read_bytes, &bytes_read) != FR_OK)) ||
(vorig && ReadVirtualFile(&ovfile, MAIN_BUFFER, pos, read_bytes, NULL) != 0))
ret = false;
if (!ShowProgress(pos + (bytes_read / 2), osize, orig))
ret = false;
if ((!vdest && (f_write(&dfile, MAIN_BUFFER, read_bytes, &bytes_written) != FR_OK)) ||
(vdest && WriteVirtualFile(&dvfile, MAIN_BUFFER, offset + pos, read_bytes, NULL) != 0))
ret = false;
if (bytes_read != bytes_written)
ret = false;
}
ShowProgress(1, 1, orig);
if (!vdest) f_close(&dfile);
if (!vorig) f_close(&ofile);
return ret;
}
bool PathCopyVirtual(const char* destdir, const char* orig) {
char dest[256]; // maximum path name length in FAT
char* oname = strrchr(orig, '/');

View File

@ -59,6 +59,9 @@ size_t FileGetSize(const char* path);
/** Get SHA-256 of file **/
bool FileGetSha256(const char* path, u8* sha256);
/** Inject file into file @offset **/
bool FileInjectFile(const char* dest, const char* orig, u32 offset);
/** Recursively copy a file or directory **/
bool PathCopy(const char* destdir, const char* orig);

View File

@ -7,7 +7,7 @@
#include "virtual.h"
#include "image.h"
#define VERSION "0.5.4"
#define VERSION "0.5.5"
#define N_PANES 2
#define IMG_DRV "789I"
@ -438,6 +438,7 @@ u32 GodMode() {
} else cursor = 0;
} else if ((pad_state & BUTTON_A) && (curr_entry->type == T_FILE)) { // process a file
u32 file_type = IdentifyImage(curr_entry->path);
bool injectable = (clipboard->n_entries == 1) && (clipboard->entry[0].type == T_FILE);
char pathstr[32 + 1];
const char* optionstr[4];
u32 n_opt = 2;
@ -445,10 +446,9 @@ u32 GodMode() {
TruncateString(pathstr, curr_entry->path, 32, 8);
optionstr[0] = "Show in Hexeditor";
optionstr[1] = "Calculate SHA-256";
if (file_type && (PathToNumFS(curr_entry->path) == 0)) {
optionstr[2] = (file_type == IMG_NAND) ? "Mount as NAND image" : "Mount as FAT image";
n_opt = 3;
}
if (injectable) optionstr[n_opt++] = "Inject data @offset";
if (file_type && (PathToNumFS(curr_entry->path) == 0))
optionstr[n_opt++] = (file_type == IMG_NAND) ? "Mount as NAND image" : "Mount as FAT image";
u32 user_select = ShowSelectPrompt(n_opt, optionstr, pathstr);
if (user_select == 1) { // -> show in hex viewer
@ -485,7 +485,7 @@ u32 GodMode() {
strncpy(pathstr_prev, pathstr, 32 + 1);
memcpy(sha256_prev, sha256, 32);
}
} else if (user_select == 3) { // -> mount as image
} else if ((!injectable && (user_select == 3)) || (user_select == 4)) { // -> mount as image
DeinitExtFS();
u32 mount_state = MountImage(curr_entry->path);
InitExtFS();
@ -501,6 +501,13 @@ u32 GodMode() {
}
if (clipboard->n_entries && (strcspn(clipboard->entry[0].path, IMG_DRV) == 0))
clipboard->n_entries = 0; // remove invalid clipboard stuff
} else if (injectable && (user_select == 3)) { // -> inject data from clipboard
char origstr[24 + 1];
TruncateString(origstr, clipboard->entry[0].name, 24, 8);
u64 offset = ShowHexPrompt(0, 8, "Inject data from %s?\nSpecifiy offset below.", origstr);
if ((offset != (u64) -1) && !FileInjectFile(curr_entry->path, clipboard->entry[0].path, (u32) offset))
ShowPrompt(false, "Failed injecting %s", origstr);
clipboard->n_entries = 0;
}
} else if (*current_path && ((pad_state & BUTTON_B) || // one level down
((pad_state & BUTTON_A) && (curr_entry->type == T_DOTDOT)))) {