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:
parent
f5403611b8
commit
b00b6d1e28
3 changed files with 61 additions and 22 deletions
|
@ -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;
|
||||||
printf("\b\b\b\b%02i%%]", p);
|
if (lastp != p) {
|
||||||
syncDisplay();
|
printf("\b\b\b\b%02i%%]", p);
|
||||||
|
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);
|
||||||
}
|
}
|
|
@ -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);
|
|
@ -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 },
|
||||||
|
|
Loading…
Add table
Reference in a new issue