1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2025-02-24 17:35:41 +00:00

Implement file splitting for file copy

This commit is contained in:
MCMrARM 2018-05-16 23:29:43 +02:00
parent f5403611b8
commit b00b6d1e28
3 changed files with 61 additions and 22 deletions

View file

@ -4,10 +4,15 @@
#include <malloc.h> #include <malloc.h>
#include <dirent.h> #include <dirent.h>
#include <memory.h> #include <memory.h>
#include <limits.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <alloca.h>
#include "ccolor.h" #include "ccolor.h"
#include "util.h" #include "util.h"
#define FILE_MAX INT_MAX
#define SPLIT_FILE_MIN 4000000000u
void workaroundPartitionZeroAccess(FsDeviceOperator* fsOperator) { void workaroundPartitionZeroAccess(FsDeviceOperator* fsOperator) {
u32 handle; u32 handle;
if (R_FAILED(fsDeviceOperatorGetGameCardHandle(fsOperator, &handle))) if (R_FAILED(fsDeviceOperatorGetGameCardHandle(fsOperator, &handle)))
@ -111,33 +116,66 @@ bool dumpPartitionRaw(FsDeviceOperator* fsOperator, u32 partition) {
return success; return success;
} }
bool copyFile(const char* source, const char* dest) { #define NAME_BUF_LEN 4096
bool copyFile(const char* source, const char* dest, bool doSplitting) {
printf("Copying %s...", source); printf("Copying %s...", source);
syncDisplay();
FILE* inFile = fopen(source, "rb"); FILE* inFile = fopen(source, "rb");
if (!inFile) { if (!inFile) {
printf("\nFailed to open input file\n"); printf("\nFailed to open input file\n");
return false; 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); fseek(inFile, 0L, SEEK_END);
long int size = ftell(inFile); long int size = ftell(inFile);
fseek(inFile, 0L, SEEK_SET); fseek(inFile, 0L, SEEK_SET);
char* splitFilename = NULL;
size_t destLen = strlen(dest);
if (size > SPLIT_FILE_MIN && doSplitting) {
if (destLen + 1 > NAME_BUF_LEN) {
printf("\nFilename is too long\n");
return 0;
}
splitFilename = alloca(NAME_BUF_LEN);
strcpy(splitFilename, dest);
sprintf(&splitFilename[destLen], ".%02i", 0);
}
FILE* outFile = fopen(splitFilename != NULL ? splitFilename : dest, "wb");
if (!outFile) {
printf("\nFailed to open output file\n");
fclose(inFile);
return false;
}
const size_t bufs = 1024 * 1024; const size_t bufs = 1024 * 1024;
char* buf = (char*) malloc(bufs); char* buf = (char*) malloc(bufs);
bool success = true; bool success = true;
ssize_t n; ssize_t n;
size_t total = 0; size_t total = 0;
size_t file_off = 0;
size_t last_report = 0; size_t last_report = 0;
printf(" [00%%]"); printf(" [00%%]");
syncDisplay(); syncDisplay();
int lastp = 0;
while (true) { while (true) {
if (total - file_off >= FILE_MAX && splitFilename != NULL) {
fclose(outFile);
file_off += FILE_MAX;
sprintf(&splitFilename[destLen], ".%02i", (int) (file_off / FILE_MAX));
outFile = fopen(splitFilename, "wb");
if (!outFile) {
printf("\nFailed to open output file\n");
free(buf);
fclose(inFile);
return false;
}
}
size_t readCount = bufs;
if (FILE_MAX - (total - file_off) < readCount)
readCount = FILE_MAX - (total - file_off);
n = fread(buf, 1, bufs, inFile); n = fread(buf, 1, bufs, inFile);
if (n <= 0) { if (n <= 0) {
if (feof(inFile)) if (feof(inFile))
@ -163,8 +201,11 @@ bool copyFile(const char* source, const char* dest) {
int p = (int) (total * 100 / size); int p = (int) (total * 100 / size);
if (p >= 100) if (p >= 100)
p = 99; p = 99;
if (lastp != p) {
printf("\b\b\b\b%02i%%]", p); printf("\b\b\b\b%02i%%]", p);
syncDisplay(); syncDisplay();
lastp = p;
}
last_report = total; last_report = total;
} }
} }
@ -176,9 +217,7 @@ bool copyFile(const char* source, const char* dest) {
return success; return success;
} }
#define NAME_BUF_LEN 4096 bool _copyDirectory(char* sbuf, size_t source_len, char* dbuf, size_t dest_len, bool splitting) {
bool _copyDirectory(char* sbuf, size_t source_len, char* dbuf, size_t dest_len) {
DIR* dir = opendir(sbuf); DIR* dir = opendir(sbuf);
struct dirent* ent; struct dirent* ent;
sbuf[source_len] = '/'; sbuf[source_len] = '/';
@ -195,12 +234,12 @@ bool _copyDirectory(char* sbuf, size_t source_len, char* dbuf, size_t dest_len)
strcpy(dbuf + dest_len + 1, ent->d_name); strcpy(dbuf + dest_len + 1, ent->d_name);
if (ent->d_type == DT_DIR) { if (ent->d_type == DT_DIR) {
mkdir(dbuf, 0744); mkdir(dbuf, 0744);
if (!_copyDirectory(sbuf, source_len + 1 + d_name_len, dbuf, dest_len + 1 + d_name_len)) { if (!_copyDirectory(sbuf, source_len + 1 + d_name_len, dbuf, dest_len + 1 + d_name_len, splitting)) {
closedir(dir); closedir(dir);
return false; return false;
} }
} else { } else {
if (!copyFile(sbuf, dbuf)) { if (!copyFile(sbuf, dbuf, splitting)) {
closedir(dir); closedir(dir);
return false; return false;
} }
@ -210,7 +249,7 @@ bool _copyDirectory(char* sbuf, size_t source_len, char* dbuf, size_t dest_len)
return true; return true;
} }
bool copyDirectory(const char* source, const char* dest) { bool copyDirectory(const char* source, const char* dest, bool splitting) {
char sbuf[NAME_BUF_LEN]; char sbuf[NAME_BUF_LEN];
char dbuf[NAME_BUF_LEN]; char dbuf[NAME_BUF_LEN];
size_t source_len = strlen(source); size_t source_len = strlen(source);
@ -226,5 +265,5 @@ bool copyDirectory(const char* source, const char* dest) {
strcpy(sbuf, source); strcpy(sbuf, source);
strcpy(dbuf, dest); strcpy(dbuf, dest);
mkdir(dbuf, 0744); mkdir(dbuf, 0744);
return _copyDirectory(sbuf, source_len, dbuf, dest_len); return _copyDirectory(sbuf, source_len, dbuf, dest_len, splitting);
} }

View file

@ -5,5 +5,5 @@
void workaroundPartitionZeroAccess(FsDeviceOperator* fsOperator); void workaroundPartitionZeroAccess(FsDeviceOperator* fsOperator);
bool openPartitionFs(FsFileSystem* ret, FsDeviceOperator* fsOperator, u32 partition); 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 copyFile(const char* source, const char* dest, bool doSplitting);
bool copyDirectory(const char* source, const char* dest); bool copyDirectory(const char* source, const char* dest, bool doSplitting);

View file

@ -55,7 +55,7 @@ void dumpPartitionDataMenuItem(MenuItem* item) {
char outbuf[64]; char outbuf[64];
sprintf(outbuf, "/dump_%u", partition); sprintf(outbuf, "/dump_%u", partition);
printf("Copying to %s\n", outbuf); printf("Copying to %s\n", outbuf);
if (copyDirectory("gamecard:/", outbuf)) { if (copyDirectory("gamecard:/", outbuf, true)) {
printf("Done!\n"); printf("Done!\n");
} }
} }
@ -93,8 +93,8 @@ MenuItem mainMenu[] = {
{ .text = "Dump Partition 1 (Normal)", .callback = dumpPartitionDataMenuItem, .userdata = (void*) 1 }, { .text = "Dump Partition 1 (Normal)", .callback = dumpPartitionDataMenuItem, .userdata = (void*) 1 },
{ .text = "Dump Partition 2 (Secure)", .callback = dumpPartitionDataMenuItem, .userdata = (void*) 2 }, { .text = "Dump Partition 2 (Secure)", .callback = dumpPartitionDataMenuItem, .userdata = (void*) 2 },
{ .text = "Raw Dump Partition 0 (SysUpdate)", .callback = dumpPartitionRawMenuItem, .userdata = (void*) 0 }, { .text = "Raw Dump Partition 0 (SysUpdate)", .callback = dumpPartitionRawMenuItem, .userdata = (void*) 0 },
{ .text = "Raw Dump Partition 0 (Normal)", .callback = dumpPartitionRawMenuItem, .userdata = (void*) 1 }, { .text = "Raw Dump Partition 1 (Normal)", .callback = dumpPartitionRawMenuItem, .userdata = (void*) 1 },
{ .text = "Raw Dump Partition 0 (Secure)", .callback = dumpPartitionRawMenuItem, .userdata = (void*) 2 }, { .text = "Raw Dump Partition 2 (Secure)", .callback = dumpPartitionRawMenuItem, .userdata = (void*) 2 },
{ .text = "View files on Game Card (SysUpdate)", .callback = viewPartitionMenuItem, .userdata = (void*) 0 }, { .text = "View files on Game Card (SysUpdate)", .callback = viewPartitionMenuItem, .userdata = (void*) 0 },
{ .text = "View files on Game Card (Normal)", .callback = viewPartitionMenuItem, .userdata = (void*) 1 }, { .text = "View files on Game Card (Normal)", .callback = viewPartitionMenuItem, .userdata = (void*) 1 },
{ .text = "View files on Game Card (Secure)", .callback = viewPartitionMenuItem, .userdata = (void*) 2 }, { .text = "View files on Game Card (Secure)", .callback = viewPartitionMenuItem, .userdata = (void*) 2 },