mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +00:00
Implement a fs-based dumper (for now for sysupdate)
This commit is contained in:
parent
7a47bf55e3
commit
a8acac46e4
3 changed files with 142 additions and 3 deletions
120
source/dumper.c
120
source/dumper.c
|
@ -2,6 +2,9 @@
|
|||
#include "fsext.h"
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <dirent.h>
|
||||
#include <memory.h>
|
||||
#include <sys/stat.h>
|
||||
#include "ccolor.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -27,6 +30,7 @@ bool openPartitionFs(FsFileSystem* ret, FsDeviceOperator* fsOperator, u32 partit
|
|||
return false;
|
||||
}
|
||||
printf("Opened card\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dumpPartitionRaw(FsDeviceOperator* fsOperator, u32 partition) {
|
||||
|
@ -105,4 +109,120 @@ bool dumpPartitionRaw(FsDeviceOperator* fsOperator, u32 partition) {
|
|||
fsStorageClose(&gameCardStorage);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool copyFile(const char* source, const char* dest) {
|
||||
printf("Copying %s...", source);
|
||||
FILE* inFile = fopen(source, "rb");
|
||||
if (!inFile) {
|
||||
printf("\nFailed to open input file\n");
|
||||
return false;
|
||||
}
|
||||
FILE* outFile = fopen(dest, "wb");
|
||||
if (!outFile) {
|
||||
printf("\nFailed to open output file\n");
|
||||
fclose(outFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(inFile, 0L, SEEK_END);
|
||||
long int size = ftell(inFile);
|
||||
fseek(inFile, 0L, SEEK_SET);
|
||||
|
||||
const size_t bufs = 1024 * 1024;
|
||||
char* buf = (char*) malloc(bufs);
|
||||
bool success = true;
|
||||
ssize_t n;
|
||||
size_t total = 0;
|
||||
size_t last_report = 0;
|
||||
printf(" [00%%]");
|
||||
syncDisplay();
|
||||
while (true) {
|
||||
n = fread(buf, 1, bufs, inFile);
|
||||
if (n <= 0) {
|
||||
if (feof(inFile))
|
||||
break;
|
||||
printf("\nRead error; retrying\n");
|
||||
continue;
|
||||
}
|
||||
if (fwrite(buf, 1, n, outFile) != n) {
|
||||
printf("\nWrite error\n");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
total += n;
|
||||
if ((total - last_report) > 1024 * 1024) {
|
||||
hidScanInput();
|
||||
u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
|
||||
if (kDown & KEY_B) {
|
||||
printf("\nCancelled\n");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
int p = (int) (total * 100 / size);
|
||||
if (p >= 100)
|
||||
p = 99;
|
||||
printf("\b\b\b\b%02i%%]", p);
|
||||
syncDisplay();
|
||||
last_report = total;
|
||||
}
|
||||
}
|
||||
printf("\b\b\b\b\bDone!\n");
|
||||
free(buf);
|
||||
fclose(inFile);
|
||||
fclose(outFile);
|
||||
return success;
|
||||
}
|
||||
|
||||
#define NAME_BUF_LEN 4096
|
||||
|
||||
bool _copyDirectory(char* sbuf, size_t source_len, char* dbuf, size_t dest_len) {
|
||||
DIR* dir = opendir(sbuf);
|
||||
struct dirent* ent;
|
||||
sbuf[source_len] = '/';
|
||||
dbuf[dest_len] = '/';
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
size_t d_name_len = strlen(ent->d_name);
|
||||
if (source_len + 1 + d_name_len + 1 >= NAME_BUF_LEN ||
|
||||
dest_len + 1 + d_name_len + 1 >= NAME_BUF_LEN) {
|
||||
printf("Too long file name!\n");
|
||||
closedir(dir);
|
||||
return false;
|
||||
}
|
||||
strcpy(sbuf + source_len + 1, ent->d_name);
|
||||
strcpy(dbuf + dest_len + 1, ent->d_name);
|
||||
if (ent->d_type == DT_DIR) {
|
||||
mkdir(dbuf, 0744);
|
||||
if (!_copyDirectory(sbuf, source_len + 1 + d_name_len, dbuf, dest_len + 1 + d_name_len)) {
|
||||
closedir(dir);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!copyFile(sbuf, dbuf)) {
|
||||
closedir(dir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool copyDirectory(const char* source, const char* dest) {
|
||||
char sbuf[NAME_BUF_LEN];
|
||||
char dbuf[NAME_BUF_LEN];
|
||||
size_t source_len = strlen(source);
|
||||
size_t dest_len = strlen(dest);
|
||||
if (source_len + 1 >= NAME_BUF_LEN) {
|
||||
printf("Directory name too long %li: %s\n", source_len + 1, source);
|
||||
return false;
|
||||
}
|
||||
if (dest_len + 1 >= NAME_BUF_LEN) {
|
||||
printf("Directory name too long %li: %s\n", dest_len + + 1, dest);
|
||||
return false;
|
||||
}
|
||||
strcpy(sbuf, source);
|
||||
strcpy(dbuf, dest);
|
||||
mkdir(dbuf, 0744);
|
||||
return _copyDirectory(sbuf, source_len, dbuf, dest_len);
|
||||
}
|
|
@ -4,4 +4,6 @@
|
|||
|
||||
void workaroundPartitionZeroAccess(FsDeviceOperator* fsOperator);
|
||||
bool openPartitionFs(FsFileSystem* ret, FsDeviceOperator* fsOperator, u32 partition);
|
||||
bool dumpPartitionRaw(FsDeviceOperator* fsOperator, u32 partition);
|
||||
bool dumpPartitionRaw(FsDeviceOperator* fsOperator, u32 partition);
|
||||
bool copyFile(const char* source, const char* dest);
|
||||
bool copyDirectory(const char* source, const char* dest);
|
|
@ -29,13 +29,28 @@ void startOperation(const char* title) {
|
|||
printf(C_DIM "%s\n\n" C_RESET, title);
|
||||
}
|
||||
|
||||
void dumpPartitionZero(MenuItem* item) {
|
||||
void dumpPartitionZeroRaw(MenuItem* item) {
|
||||
startOperation("Raw Dump Partition 0 (SysUpdate)");
|
||||
workaroundPartitionZeroAccess(&fsOperatorInstance);
|
||||
dumpPartitionRaw(&fsOperatorInstance, 0);
|
||||
menuWaitForAnyButton();
|
||||
}
|
||||
|
||||
void dumpPartitionZeroData(MenuItem* item) {
|
||||
startOperation("Dump Partition 0 (SysUpdate)");
|
||||
workaroundPartitionZeroAccess(&fsOperatorInstance);
|
||||
FsFileSystem fs;
|
||||
if (openPartitionFs(&fs, &fsOperatorInstance, 0) &&
|
||||
fsdevMountDevice("gamecard", fs) != -1) {
|
||||
printf("Copying to /dump_0\n");
|
||||
if (copyDirectory("gamecard:/", "/dump_0")) {
|
||||
printf("Done!\n");
|
||||
}
|
||||
}
|
||||
fsdevUnmountDevice("dump");
|
||||
menuWaitForAnyButton();
|
||||
}
|
||||
|
||||
void viewPartitionZero() {
|
||||
startOperation("Mount Partition 0 (SysUpdate)");
|
||||
workaroundPartitionZeroAccess(&fsOperatorInstance);
|
||||
|
@ -44,6 +59,7 @@ void viewPartitionZero() {
|
|||
menuWaitForAnyButton();
|
||||
return;
|
||||
}
|
||||
fsdevUnmountDevice("test"); // unmount it if it exists
|
||||
if (fsdevMountDevice("test", fs) == -1) {
|
||||
printf("fsdevMountDevice failed\n");
|
||||
menuWaitForAnyButton();
|
||||
|
@ -54,7 +70,8 @@ void viewPartitionZero() {
|
|||
|
||||
|
||||
MenuItem mainMenu[] = {
|
||||
{ .text = "Raw Dump Partition 0 (SysUpdate)", .callback = dumpPartitionZero },
|
||||
{ .text = "Dump Partition 0 (SysUpdate)", .callback = dumpPartitionZeroData },
|
||||
{ .text = "Raw Dump Partition 0 (SysUpdate)", .callback = dumpPartitionZeroRaw },
|
||||
{ .text = "View files on Game Card (SysUpdate)", .callback = viewPartitionZero },
|
||||
{ .text = NULL }
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue