Added ability to copy virtual files

This commit is contained in:
d0k3 2016-03-21 23:19:23 +01:00
parent 50c9091d2c
commit 4d4a037874
3 changed files with 154 additions and 22 deletions

View File

@ -147,6 +147,131 @@ bool FileGetData(const char* path, u8* data, size_t size, size_t foffset)
return (bytes_read == size);
}
bool PathCopyVirtual(const char* destdir, const char* orig) {
char dest[256]; // maximum path name length in FAT
char* oname = strrchr(orig, '/');
char deststr[36 + 1];
char origstr[36 + 1];
bool ret = true;
if (oname == NULL) return false; // not a proper origin path
oname++;
snprintf(dest, 256, "%s/%s", destdir, oname);
TruncateString(deststr, dest, 36, 8);
TruncateString(origstr, orig, 36, 8);
if (IsVirtualPath(dest) && IsVirtualPath(orig)) { // virtual to virtual
VirtualFile dvfile;
VirtualFile ovfile;
u32 osize;
if (!FindVirtualFile(&dvfile, dest))
return false;
if (!FindVirtualFile(&ovfile, orig))
return false;
osize = ovfile.size;
if (dvfile.size != osize) { // almost impossible, but so what...
ShowPrompt(false, "Virtual file size mismatch:\n%s\n%s", origstr, deststr);
return false;
}
if ((dvfile.keyslot == ovfile.keyslot) && (dvfile.offset == ovfile.offset)) // this improves copy times
dvfile.keyslot = ovfile.keyslot = 0xFF;
DeinitNandFS();
if (!ShowProgress(0, 0, orig)) ret = false;
for (size_t pos = 0; (pos < osize) && ret; pos += MAIN_BUFFER_SIZE) {
UINT read_bytes = min(MAIN_BUFFER_SIZE, osize - pos);
if (ReadVirtualFile(&ovfile, MAIN_BUFFER, pos, read_bytes) != 0)
ret = false;
if (!ShowProgress(pos + (read_bytes / 2), osize, orig))
ret = false;
if (WriteVirtualFile(&dvfile, MAIN_BUFFER, pos, read_bytes) != 0)
ret = false;
}
ShowProgress(1, 1, orig);
InitNandFS();
} else if (IsVirtualPath(dest)) { // SD card to virtual (other FAT not allowed!)
VirtualFile dvfile;
FIL ofile;
u32 osize;
if (!FindVirtualFile(&dvfile, dest))
return false;
if (f_open(&ofile, orig, FA_READ | FA_OPEN_EXISTING) != FR_OK)
return false;
f_lseek(&ofile, 0);
f_sync(&ofile);
osize = f_size(&ofile);
if (dvfile.size != osize) {
char osizestr[32];
char dsizestr[32];
FormatBytes(osizestr, osize);
FormatBytes(dsizestr, dvfile.size);
ShowPrompt(false, "File size mismatch:\n%s (%s)\n%s (%s)", origstr, osizestr, deststr, dsizestr);
f_close(&ofile);
return false;
}
DeinitNandFS();
if (!ShowProgress(0, 0, orig)) ret = false;
for (size_t pos = 0; (pos < osize) && ret; pos += MAIN_BUFFER_SIZE) {
UINT bytes_read = 0;
if (f_read(&ofile, MAIN_BUFFER, MAIN_BUFFER_SIZE, &bytes_read) != FR_OK)
ret = false;
if (!ShowProgress(pos + (bytes_read / 2), osize, orig))
ret = false;
if (WriteVirtualFile(&dvfile, MAIN_BUFFER, pos, bytes_read) != 0)
ret = false;
}
ShowProgress(1, 1, orig);
f_close(&ofile);
InitNandFS();
} else if (IsVirtualPath(orig)) { // virtual to SD card (other FAT not allowed)
VirtualFile ovfile;
FIL dfile;
u32 osize;
if (!FindVirtualFile(&ovfile, orig))
return false;
// check if destination exists
if (f_stat(dest, NULL) == FR_OK) {
if (!ShowPrompt(true, "Destination already exists:\n%s\nOverwrite existing file(s)?", deststr))
return false;
}
if (f_open(&dfile, dest, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK)
return false;
f_lseek(&dfile, 0);
f_sync(&dfile);
osize = ovfile.size;
if (GetFreeSpace(dest) < osize) {
ShowPrompt(false, "Error: File is too big for destination");
f_close(&dfile);
return false;
}
if (!ShowProgress(0, 0, orig)) ret = false;
for (size_t pos = 0; (pos < osize) && ret; pos += MAIN_BUFFER_SIZE) {
UINT read_bytes = min(MAIN_BUFFER_SIZE, osize - pos);
UINT bytes_written = 0;
if (ReadVirtualFile(&ovfile, MAIN_BUFFER, pos, read_bytes) != 0)
ret = false;
if (!ShowProgress(pos + (read_bytes / 2), osize, orig))
ret = false;
if (f_write(&dfile, MAIN_BUFFER, read_bytes, &bytes_written) != FR_OK)
ret = false;
if (read_bytes != bytes_written)
ret = false;
}
ShowProgress(1, 1, orig);
f_close(&dfile);
} else {
return false;
}
return ret;
}
bool PathCopyWorker(char* dest, char* orig, bool overwrite) {
FILINFO fno = {.lfname = NULL};
bool ret = false;
@ -261,12 +386,21 @@ bool PathCopyWorker(char* dest, char* orig, bool overwrite) {
}
bool PathCopy(const char* destdir, const char* orig) {
if (!CheckWritePermissions(destdir)) return false;
if (IsVirtualPath(destdir) || IsVirtualPath(orig)) {
// users are inventive...
if ((PathToNumFS(orig) > 0) && IsVirtualPath(destdir)) {
ShowPrompt(false, "Only files from SD card are accepted");
return false;
}
return PathCopyVirtual(destdir, orig);
} else {
char fdpath[256]; // 256 is the maximum length of a full path
char fopath[256];
if (!CheckWritePermissions(destdir)) return false;
strncpy(fdpath, destdir, 255);
strncpy(fopath, orig, 255);
return PathCopyWorker(fdpath, fopath, false);
}
}
bool PathDeleteWorker(char* fpath) {
@ -401,8 +535,8 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
for (u32 pdrv = 0; (pdrv < MAX_FS+2) && (n_entries < MAX_ENTRIES); pdrv++) {
DirEntry* entry = &(contents->entry[n_entries]);
if ((pdrv < MAX_FS) && !fs_mounted[pdrv]) continue;
if ((pdrv == MAX_FS+0) && (!fs_mounted[1] || !fs_mounted[2] || !fs_mounted[3])) continue;
if ((pdrv == MAX_FS+1) && (!fs_mounted[4] || !fs_mounted[5] || !fs_mounted[6])) continue;
if ((pdrv == MAX_FS+0) && (!fs_mounted[1])) continue;
if ((pdrv == MAX_FS+1) && (!fs_mounted[4])) continue;
memset(entry->path, 0x00, 64);
snprintf(entry->path + 0, 4, "%s:", drvnum[pdrv]);
snprintf(entry->path + 4, 32, "[%s:] %s", drvnum[pdrv], drvname[pdrv]);

View File

@ -5,24 +5,24 @@
#define VFLAG_ON_N3DS NAND_TYPE_N3DS
#define VFLAG_ON_NO3DS NAND_TYPE_NO3DS
#define VFLAG_ON_ALL (VFLAG_ON_O3DS | VFLAG_ON_N3DS | VFLAG_ON_NO3DS)
#define VFLAG_NAND_SIZE (1<<29)
#define VFLAG_ON_EMUNAND (1<<30)
#define VFLAG_NAND_SIZE (1<<30)
#define VFLAG_ON_EMUNAND (1<<31)
VirtualFile virtualFileTemplates[] = {
{ "twln.bin" , 0x00012E00, 0x08FB5200, 0x03, VFLAG_ON_ALL | VFLAG_EXT_NAND_REMOUNT },
{ "twlp.bin" , 0x09011A00, 0x020B6600, 0x03, VFLAG_ON_ALL | VFLAG_EXT_NAND_REMOUNT },
{ "twln.bin" , 0x00012E00, 0x08FB5200, 0x03, VFLAG_ON_ALL },
{ "twlp.bin" , 0x09011A00, 0x020B6600, 0x03, VFLAG_ON_ALL },
{ "agbsave.bin" , 0x0B100000, 0x00030000, 0x07, VFLAG_ON_ALL },
{ "firm0.bin" , 0x0B130000, 0x00400000, 0x06, VFLAG_ON_ALL },
{ "firm1.bin" , 0x0B530000, 0x00400000, 0x06, VFLAG_ON_ALL },
{ "ctrnand_fat.bin" , 0x0B95CA00, 0x2F3E3600, 0x04, VFLAG_ON_O3DS | VFLAG_EXT_NAND_REMOUNT },
{ "ctrnand_fat.bin" , 0x0B95AE00, 0x41D2D200, 0x05, VFLAG_ON_N3DS | VFLAG_EXT_NAND_REMOUNT },
{ "ctrnand_fat.bin" , 0x0B95AE00, 0x41D2D200, 0x04, VFLAG_ON_NO3DS | VFLAG_EXT_NAND_REMOUNT },
{ "ctrnand_full.bin" , 0x0B930000, 0x2F5D0000, 0x04, VFLAG_ON_O3DS | VFLAG_EXT_NAND_REMOUNT },
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x05, VFLAG_ON_N3DS | VFLAG_EXT_NAND_REMOUNT },
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x04, VFLAG_ON_NO3DS | VFLAG_EXT_NAND_REMOUNT },
{ "nand.bin" , 0x00000000, 0x00000000, 0xFF, VFLAG_ON_ALL | VFLAG_NAND_SIZE | VFLAG_EXT_NAND_REMOUNT },
{ "nand_minsize.bin" , 0x00000000, 0x3AF00000, 0xFF, VFLAG_ON_O3DS | VFLAG_EXT_NAND_REMOUNT },
{ "nand_minsize.bin" , 0x00000000, 0x4D800000, 0xFF, VFLAG_ON_N3DS | VFLAG_ON_NO3DS | VFLAG_EXT_NAND_REMOUNT },
{ "ctrnand_fat.bin" , 0x0B95CA00, 0x2F3E3600, 0x04, VFLAG_ON_O3DS },
{ "ctrnand_fat.bin" , 0x0B95AE00, 0x41D2D200, 0x05, VFLAG_ON_N3DS },
{ "ctrnand_fat.bin" , 0x0B95AE00, 0x41D2D200, 0x04, VFLAG_ON_NO3DS },
{ "ctrnand_full.bin" , 0x0B930000, 0x2F5D0000, 0x04, VFLAG_ON_O3DS },
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x05, VFLAG_ON_N3DS },
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x04, VFLAG_ON_NO3DS },
{ "nand.bin" , 0x00000000, 0x00000000, 0xFF, VFLAG_ON_ALL | VFLAG_NAND_SIZE },
{ "nand_minsize.bin" , 0x00000000, 0x3AF00000, 0xFF, VFLAG_ON_O3DS },
{ "nand_minsize.bin" , 0x00000000, 0x4D800000, 0xFF, VFLAG_ON_N3DS | VFLAG_ON_NO3DS },
{ "nand_hdr.bin" , 0x00000000, 0x00000200, 0xFF, VFLAG_ON_ALL },
{ "sector0x96.bin" , 0x00012C00, 0x00000200, 0xFF, VFLAG_ON_ALL }
};

View File

@ -3,8 +3,6 @@
#include "common.h"
#include "nand.h"
#define VFLAG_EXT_NAND_REMOUNT (1<<31)
static const char* virtualFileList[] = { // must have a match in virtualFileTemplates[]
"twln.bin", "twlp.bin", "agbsave.bin", "firm0.bin", "firm1.bin", "ctrnand_fat.bin", "ctrnand_full.bin",
"nand.bin", "nand_minsize.bin", "nand_hdr.bin", "sector0x96.bin"