FileGetData(): Also allow virtual files

This commit also enables ReadVirtualFile() to correctly process
misaligned data
This commit is contained in:
d0k3 2016-04-08 21:02:38 +02:00
parent 2d181de5bf
commit 45501d47eb
5 changed files with 79 additions and 26 deletions

View File

@ -162,16 +162,26 @@ bool FileCreateData(const char* path, u8* data, size_t size) {
return (bytes_written == size); return (bytes_written == size);
} }
bool FileGetData(const char* path, u8* data, size_t size, size_t foffset) size_t FileGetData(const char* path, u8* data, size_t size, size_t foffset)
{ {
FIL file; if (PathToNumFS(path) >= 0) {
UINT bytes_read = 0; UINT bytes_read = 0;
if (f_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) FIL file;
return false; if (f_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK)
f_lseek(&file, foffset); return 0;
f_read(&file, data, size, &bytes_read); f_lseek(&file, foffset);
f_close(&file); if (f_read(&file, data, size, &bytes_read) != FR_OK)
return (bytes_read == size); return 0;
f_close(&file);
return bytes_read;
} else if (IsVirtualPath(path)) {
u32 bytes_read = 0;
VirtualFile vfile;
if (!FindVirtualFile(&vfile, path, 0))
return 0;
return (ReadVirtualFile(&vfile, data, foffset, size, &bytes_read) == 0) ? bytes_read : 0;
}
return 0;
} }
bool PathCopyVirtual(const char* destdir, const char* orig) { bool PathCopyVirtual(const char* destdir, const char* orig) {
@ -209,11 +219,11 @@ bool PathCopyVirtual(const char* destdir, const char* orig) {
if (!ShowProgress(0, 0, orig)) ret = false; if (!ShowProgress(0, 0, orig)) ret = false;
for (size_t pos = 0; (pos < osize) && ret; pos += MAIN_BUFFER_SIZE) { for (size_t pos = 0; (pos < osize) && ret; pos += MAIN_BUFFER_SIZE) {
UINT read_bytes = min(MAIN_BUFFER_SIZE, osize - pos); UINT read_bytes = min(MAIN_BUFFER_SIZE, osize - pos);
if (ReadVirtualFile(&ovfile, MAIN_BUFFER, pos, read_bytes) != 0) if (ReadVirtualFile(&ovfile, MAIN_BUFFER, pos, read_bytes, NULL) != 0)
ret = false; ret = false;
if (!ShowProgress(pos + (read_bytes / 2), osize, orig)) if (!ShowProgress(pos + (read_bytes / 2), osize, orig))
ret = false; ret = false;
if (WriteVirtualFile(&dvfile, MAIN_BUFFER, pos, read_bytes) != 0) if (WriteVirtualFile(&dvfile, MAIN_BUFFER, pos, read_bytes, NULL) != 0)
ret = false; ret = false;
} }
ShowProgress(1, 1, orig); ShowProgress(1, 1, orig);
@ -265,7 +275,7 @@ bool PathCopyVirtual(const char* destdir, const char* orig) {
ret = false; ret = false;
if (!ShowProgress(pos + (bytes_read / 2), osize, orig)) if (!ShowProgress(pos + (bytes_read / 2), osize, orig))
ret = false; ret = false;
if (WriteVirtualFile(&dvfile, MAIN_BUFFER, pos, bytes_read) != 0) if (WriteVirtualFile(&dvfile, MAIN_BUFFER, pos, bytes_read, NULL) != 0)
ret = false; ret = false;
} }
ShowProgress(1, 1, orig); ShowProgress(1, 1, orig);
@ -298,7 +308,7 @@ bool PathCopyVirtual(const char* destdir, const char* orig) {
for (size_t pos = 0; (pos < osize) && ret; pos += MAIN_BUFFER_SIZE) { for (size_t pos = 0; (pos < osize) && ret; pos += MAIN_BUFFER_SIZE) {
UINT read_bytes = min(MAIN_BUFFER_SIZE, osize - pos); UINT read_bytes = min(MAIN_BUFFER_SIZE, osize - pos);
UINT bytes_written = 0; UINT bytes_written = 0;
if (ReadVirtualFile(&ovfile, MAIN_BUFFER, pos, read_bytes) != 0) if (ReadVirtualFile(&ovfile, MAIN_BUFFER, pos, read_bytes, NULL) != 0)
ret = false; ret = false;
if (!ShowProgress(pos + (read_bytes / 2), osize, orig)) if (!ShowProgress(pos + (read_bytes / 2), osize, orig))
ret = false; ret = false;

View File

@ -42,7 +42,7 @@ u32 GetWritePermissions();
bool FileCreateData(const char* path, u8* data, size_t size); bool FileCreateData(const char* path, u8* data, size_t size);
/** Read data from file@offset **/ /** Read data from file@offset **/
bool FileGetData(const char* path, u8* data, size_t size, size_t foffset); size_t FileGetData(const char* path, u8* data, size_t size, size_t foffset);
/** 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);

View File

@ -61,7 +61,7 @@ bool LoadKeyFromFile(const char* folder, u8* keydata, u32 keyslot, char type, ch
if (id) strncpy((char*) key_magic + 2, id, 10); if (id) strncpy((char*) key_magic + 2, id, 10);
// try to find key in 'aeskeydb.bin' file // try to find key in 'aeskeydb.bin' file
for (u32 p = 0; FileGetData(path, buffer, 32, p); p += 32) { for (u32 p = 0; FileGetData(path, buffer, 32, p) == 32; p += 32) {
if (memcmp(buffer, key_magic, 12) == 0) { if (memcmp(buffer, key_magic, 12) == 0) {
found = true; found = true;
break; break;
@ -83,7 +83,7 @@ bool LoadKeyFromFile(const char* folder, u8* keydata, u32 keyslot, char type, ch
if (!found) { if (!found) {
snprintf(path, 256, "%s/slot0x%02XKey%.10s", folder, (unsigned int) keyslot, snprintf(path, 256, "%s/slot0x%02XKey%.10s", folder, (unsigned int) keyslot,
(id) ? id : (type == 'X') ? "X" : (type == 'Y') ? "Y" : ""); (id) ? id : (type == 'X') ? "X" : (type == 'Y') ? "Y" : "");
if (FileGetData(path, key, 16, 0)) if (FileGetData(path, key, 16, 0) == 16)
found = true; found = true;
} }
@ -198,6 +198,7 @@ void CryptNand(u8* buffer, u32 sector, u32 count, u32 keyslot)
int ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, u32 nand_src) int ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, u32 nand_src)
{ {
if (!count) return 0; // <--- just to be safe
if (nand_src == NAND_EMUNAND) { // EmuNAND if (nand_src == NAND_EMUNAND) { // EmuNAND
int errorcode = 0; int errorcode = 0;
if ((sector == 0) && (emunand_base_sector % 0x200000 == 0)) { // GW EmuNAND header handling if ((sector == 0) && (emunand_base_sector % 0x200000 == 0)) { // GW EmuNAND header handling

View File

@ -91,16 +91,58 @@ bool FindVirtualFile(VirtualFile* vfile, const char* path, u32 size)
return true; return true;
} }
int ReadVirtualFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count) int ReadVirtualFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count, u32* bytes_read)
{ {
// simple wrapper function for ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, u32 src) u32 foffset = vfile->offset + offset;
return ReadNandSectors(buffer, (vfile->offset + offset) / 0x200, (count+0x1FF) / 0x200, vfile->keyslot, if (offset >= vfile->size)
vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND)); return 0;
else if ((offset + count) > vfile->size)
count = vfile->size - offset;
if (bytes_read) *bytes_read = count;
if (!(foffset % 0x200) && !(count % 0x200)) { // aligned data -> simple case
// simple wrapper function for ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, u32 src)
return ReadNandSectors(buffer, foffset / 0x200, count / 0x200, vfile->keyslot,
vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND));
} else { // nonaligned data -> -___-
u8 l_buffer[0x200];
u32 nand_src = vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND);
u32 keyslot = vfile->keyslot;
int errorcode = 0;
if (foffset % 0x200) { // handle misaligned offset
u32 offset_fix = 0x200 - (foffset % 0x200);
errorcode = ReadNandSectors(l_buffer, foffset / 0x200, 1, keyslot, nand_src);
if (errorcode != 0) return errorcode;
memcpy(buffer, l_buffer + 0x200 - offset_fix, min(offset_fix, count));
if (count <= offset_fix) return 0;
foffset += offset_fix;
buffer += offset_fix;
count -= offset_fix;
} // foffset is now aligned and part of the data is read
if (count >= 0x200) { // otherwise this is misaligned and will be handled below
errorcode = ReadNandSectors(buffer, foffset / 0x200, count / 0x200, keyslot, nand_src);
if (errorcode != 0) return errorcode;
}
if (count % 0x200) { // handle misaligned count
u32 count_fix = count % 0x200;
errorcode = ReadNandSectors(l_buffer, (foffset + count) / 0x200, 1, keyslot, nand_src);
if (errorcode != 0) return errorcode;
memcpy(buffer + count - count_fix, l_buffer, count_fix);
}
return errorcode;
}
} }
int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u32 offset, u32 count) int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u32 offset, u32 count, u32* bytes_written)
{ {
// simple wrapper function for WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, u32 dest) u32 foffset = vfile->offset + offset;
return WriteNandSectors(buffer, (vfile->offset + offset) / 0x200, (count+0x1FF) / 0x200, vfile->keyslot, if (offset >= vfile->size)
vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND)); return 0;
else if ((offset + count) > vfile->size)
count = vfile->size - offset;
if (bytes_written) *bytes_written = count;
if (!(foffset % 0x200) && !(count % 0x200)) { // aligned data -> simple case
// simple wrapper function for WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, u32 dest)
return WriteNandSectors(buffer, foffset / 0x200, count / 0x200, vfile->keyslot,
vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND));
} else return -1; // misaligned data -> not implemented (!!!)
} }

View File

@ -24,5 +24,5 @@ typedef struct {
u32 IsVirtualPath(const char* path); u32 IsVirtualPath(const char* path);
bool CheckVirtualPath(const char* path); bool CheckVirtualPath(const char* path);
bool FindVirtualFile(VirtualFile* vfile, const char* path, u32 size); bool FindVirtualFile(VirtualFile* vfile, const char* path, u32 size);
int ReadVirtualFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count); int ReadVirtualFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count, u32* bytes_read);
int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u32 offset, u32 count); int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u32 offset, u32 count, u32* bytes_written);