Add ZIP restore

This commit is contained in:
J-D-K 2020-06-07 12:05:58 -04:00
parent 633a97a568
commit 8a4e68e3ff
6 changed files with 198 additions and 225 deletions

View File

@ -7,6 +7,7 @@
#include <switch.h>
#include <dirent.h>
#include <minizip/zip.h>
#include <minizip/unzip.h>
#include "fsfile.h"
#include "data.h"
@ -32,6 +33,9 @@ namespace fs
//Same as above, but commits data to 'dev' after every file is closed
void copyDirToDirCommit(const std::string& from, const std::string& to, const std::string& dev);
//Copies unzfile to 'to'
void copyZipToDir(unzFile *unz, const std::string& to, const std::string& dev);
//deletes file
void delfile(const std::string& path);
//Recursively deletes 'path'

View File

@ -49,7 +49,7 @@ namespace ui
//Strings for file mode menu
extern std::string advMenuStr[6];
//Strings for extras menu
extern std::string exMenuStr[10];
extern std::string exMenuStr[11];
//Strings for options menu
extern std::string optMenuStr[13];
//Strings for options explanations

View File

@ -6,6 +6,7 @@
#include <unistd.h>
#include <cstdarg>
#include <minizip/zip.h>
#include <minizip/unzip.h>
#include <sys/stat.h>
#include "file.h"
@ -40,154 +41,17 @@ static struct
}
} sortDirList;
typedef struct
{
std::string from, to, dev;
uint64_t *pos;
bool fin;
} copyArgs;
static copyArgs *copyArgsCreate(const std::string& _f, const std::string& _t, const std::string& _dev, uint64_t *_p)
{
copyArgs *ret = new copyArgs;
ret->from = _f;
ret->to = _t;
ret->dev = _dev;
ret->pos = _p;
ret->fin = false;
return ret;
}
static void copyfile_t(void *a)
{
copyArgs *args = (copyArgs *)a;
FILE *f = fopen(args->from.c_str(), "rb");
FILE *t = fopen(args->to.c_str(), "wb");
if(f == NULL || t == NULL)
{
fclose(f);
fclose(t);
args->fin = true;
return;
}
size_t read = 0;
unsigned char *buff = new unsigned char[BUFF_SIZE];
while((read = fread(buff, 1, BUFF_SIZE, f)))
{
fwrite(buff, 1, read, t);
*args->pos += read;
}
delete[] buff;
fclose(f);
fclose(t);
args->fin = true;
}
static void copyfileFS_t(void *a)
{
copyArgs *args = (copyArgs *)a;
FSFILE *f = fsfopen(args->from.c_str(), FsOpenMode_Read);
FSFILE *t = fsfopen(args->to.c_str(), FsOpenMode_Write);
if(f == NULL || t == NULL)
{
fsfclose(f);
fsfclose(t);
args->fin = true;
return;
}
size_t read = 0;
unsigned char *buff = new unsigned char[BUFF_SIZE];
while((read = fsfread(buff, 1, BUFF_SIZE, f)))
{
fsfwrite(buff, 1, read, t);
*args->pos += read;
}
delete[] buff;
fsfclose(f);
fsfclose(t);
args->fin = true;
}
static void copyfileCommit_t(void *a)
{
copyArgs *args = (copyArgs *)a;
FILE *f = fopen(args->from.c_str(), "rb");
FILE *t = fopen(args->to.c_str(), "wb");
if(f == NULL || t == NULL)
{
fclose(f);
fclose(t);
args->fin = true;
return;
}
size_t read = 0;
unsigned char *buff = new unsigned char[BUFF_SIZE];
while((read = fread(buff, 1, BUFF_SIZE, f)))
{
fwrite(buff, 1, read, t);
*args->pos += read;
}
delete[] buff;
fclose(f);
fclose(t);
fsdevCommitDevice(args->dev.c_str());
args->fin = true;
}
static void copyfileCommitFS_t(void *a)
{
copyArgs *args = (copyArgs *)a;
FSFILE *f = fsfopen(args->from.c_str(), FsOpenMode_Read);
FSFILE *t = fsfopen(args->to.c_str(), FsOpenMode_Write);
if(f == NULL || t == NULL)
{
fsfclose(f);
fsfclose(t);
args->fin = true;
return;
}
size_t read = 0;
unsigned char *buff = new unsigned char[BUFF_SIZE];
while((read = fsfread(buff, 1, BUFF_SIZE, f)))
{
fsfwrite(buff, 1, read, t);
*args->pos += read;
}
delete[] buff;
fsfclose(f);
fsfclose(t);
fsdevCommitDevice(args->dev.c_str());
args->fin = true;
}
static void mkdirRec(const std::string& _p)
{
//skip first slash
size_t pos = _p.find('/', 0) + 1;
while((pos = _p.find('/', pos)) != _p.npos)
{
std::string create;
create.assign(_p.begin(), _p.begin() + pos);
mkdir(create.c_str(), 777);
mkdir(_p.substr(0, pos).c_str(), 777);
++pos;
}
}
void fs::init()
{
if(fs::fileExists("sdmc:/switch/jksv_dir.txt"))
@ -381,48 +245,52 @@ int fs::dataFile::getNextValueInt()
void fs::copyFile(const std::string& from, const std::string& to)
{
Thread cpyThread;
uint64_t gProg = 0;
copyArgs *thr = copyArgsCreate(from, to, "", &gProg);
uint8_t *buff = new uint8_t[BUFF_SIZE];
ui::progBar prog(fs::fsize(from));
if(data::directFsCmd)
threadCreate(&cpyThread, copyfileFS_t, thr, NULL, 0x4000, 0x2B, 1);
else
threadCreate(&cpyThread, copyfile_t, thr, NULL, 0x4000, 0x2B, 1);
ui::progBar fileProg(fsize(from));
threadStart(&cpyThread);
while(!thr->fin)
{
fileProg.update(*thr->pos);
gfxBeginFrame();
fileProg.draw(from, ui::copyHead);
gfxEndFrame();
FSFILE *in = fsfopen(from.c_str(), FsOpenMode_Read);
FSFILE *out = fsfopen(to.c_str(), FsOpenMode_Write);
size_t readIn = 0;
while((readIn = fsfread(buff, 1, BUFF_SIZE, in)) > 0)
{
fsfwrite(buff, 1, readIn, out);
prog.update(fsftell(in));
gfxBeginFrame();
prog.draw(from, ui::copyHead);
gfxEndFrame();
}
fsfclose(in);
fsfclose(out);
}
threadClose(&cpyThread);
delete thr;
else
{
FILE *in = fopen(from.c_str(), "rb");
FILE *out = fopen(to.c_str(), "wb");
size_t readIn = 0;
while((readIn = fread(buff, 1, BUFF_SIZE, in)) > 0)
{
fwrite(buff, 1, readIn, out);
prog.update(ftell(in));
gfxBeginFrame();
prog.draw(from, ui::copyHead);
gfxEndFrame();
}
fclose(in);
fclose(out);
}
delete[] buff;
}
void fs::copyFileCommit(const std::string& from, const std::string& to, const std::string& dev)
{
Thread cpyThread;
uint64_t gProg = 0;
copyArgs *thr = copyArgsCreate(from, to, dev, &gProg);
if(data::directFsCmd)
threadCreate(&cpyThread, copyfileCommitFS_t, thr, NULL, 0x4000, 0x2B, 1);
else
threadCreate(&cpyThread, copyfileCommit_t, thr, NULL, 0x4000, 0x2B, 1);
ui::progBar fileProg(fsize(from));
threadStart(&cpyThread);
while(!thr->fin)
{
fileProg.update(*thr->pos);
gfxBeginFrame();
fileProg.draw(from, ui::copyHead);
gfxEndFrame();
}
threadClose(&cpyThread);
delete thr;
fs::copyFile(from, to);
if(R_FAILED(fsdevCommitDevice(dev.c_str())))
ui::showMessage("*Error*", "Error committing file to device.");
}
void fs::copyDirToDir(const std::string& from, const std::string& to)
@ -455,14 +323,21 @@ void fs::copyDirToDir(const std::string& from, const std::string& to)
void copyFileToZip(const std::string& from, zipFile *to)
{
ui::progBar prog(fs::fsize(from));
FILE *cpy = fopen(from.c_str(), "rb");
size_t readIn = 0;
size_t readIn = 0, offset = 0;
uint8_t *inBuff= new uint8_t[BUFF_SIZE];
while((readIn = fread(inBuff, 1, BUFF_SIZE, cpy)) > 0)
{
if(zipWriteInFileInZip(*to, inBuff, readIn) != 0)
ui::showMessage("fail", "here");
ui::showMessage("Failed", "zipWriteInFileInZip");
offset += readIn;
prog.update(offset);
gfxBeginFrame();
prog.draw(from, ui::copyHead);
gfxEndFrame();
}
delete[] inBuff;
@ -492,6 +367,59 @@ void fs::copyDirToZip(const std::string& from, zipFile *to)
}
}
void fs::copyZipToDir(unzFile *unz, const std::string& to, const std::string& dev)
{
char filename[FS_MAX_PATH];
uint8_t *buff = new uint8_t[BUFF_SIZE];
int readIn = 0;
unz_file_info info;
do
{
unzGetCurrentFileInfo(*unz, &info, filename, FS_MAX_PATH, NULL, 0, NULL, 0);
unzOpenCurrentFile(*unz);
std::string path = to + filename;
mkdirRec(path.substr(0, path.find_last_of('/') + 1));
ui::progBar prog(info.uncompressed_size);
size_t done = 0;
if(data::directFsCmd)
{
FSFILE *out = fsfopen(path.c_str(), FsOpenMode_Write);
while((readIn = unzReadCurrentFile(*unz, buff, BUFF_SIZE)) > 0)
{
done += readIn;
fsfwrite(buff, 1, readIn, out);
prog.update(done);
gfxBeginFrame();
prog.draw(filename, ui::copyHead);
gfxEndFrame();
}
fsfclose(out);
}
else
{
FILE *out = fopen(path.c_str(), "wb");
while((readIn = unzReadCurrentFile(*unz, buff, BUFF_SIZE)) > 0)
{
done += readIn;
fwrite(buff, 1, readIn, out);
prog.update(done);
gfxBeginFrame();
prog.draw(filename, ui::copyHead);
gfxEndFrame();
}
fclose(out);
}
unzCloseCurrentFile(*unz);
if(R_FAILED(fsdevCommitDevice(dev.c_str())))
ui::showMessage("*Error*", "Error committing file to device.");
}
while(unzGoToNextFile(*unz) != UNZ_END_OF_LIST_OF_FILE);
delete[] buff;
}
void fs::copyDirToDirCommit(const std::string& from, const std::string& to, const std::string& dev)
{
dirList list(from);

View File

@ -67,7 +67,7 @@ std::string ui::confEraseNand = "*WARNING*: This *will* erase the save data for
std::string ui::confEraseFolder = "*WARNING*: This *will* delete the current save data for #%s# *from your system*! Are you sure you want to continue?";
std::string ui::noSavesFound = "No saves found for #%s#!";
std::string ui::advMenuStr[6] = { "Copy to ", "Delete", "Rename", "Make Dir", "Properties", "Close" };
std::string ui::exMenuStr[10] = { "SD to SD Browser", "BIS: PRODINFOF", "BIS: SAFE", "BIS: SYSTEM", "BIS: USER", "Remove Update", "Terminate Process", "Mount System Save", "Rescan Titles", "Mount Process RomFS" };
std::string ui::exMenuStr[11] = { "SD to SD Browser", "BIS: PRODINFOF", "BIS: SAFE", "BIS: SYSTEM", "BIS: USER", "Remove Update", "Terminate Process", "Mount System Save", "Rescan Titles", "Mount Process RomFS", "Backup JKSV Folder" };
std::string ui::optMenuStr[13] = { "Include Dev Sv: ", "AutoBackup: ", "Overclock: ", "Hold to Delete: ", "Hold to Restore: ", "Hold to Overwrite: ", "Force Mount: ", "Account Sys. Saves: ", "Write to Sys. Saves: ", "Text UI Mode: ", "Direct FS Cmd: ", "Skip User Select: ", "Export to ZIP: " };
std::string ui::optMenuExp[13] =
{

View File

@ -25,14 +25,14 @@ void ui::folderMenuPrepare(data::user& usr, data::titledata& dat)
void ui::createNewBackup(const uint64_t& held)
{
std::string folder;
std::string out;
if(held & KEY_R)
folder = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD);
out = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD);
else if(held & KEY_L)
folder = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YDM);
out = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YDM);
else if(held & KEY_ZL)
folder = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_HOYSTE);
out = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_HOYSTE);
else
{
const std::string dict[] =
@ -46,21 +46,18 @@ void ui::createNewBackup(const uint64_t& held)
data::curData.getTitleSafe(),
util::generateAbbrev(data::curData)
};
folder = util::getStringInput("", "Enter a folder name", 64, 8, dict);
out = util::getStringInput("", "Enter a name", 64, 8, dict);
}
if(!folder.empty())
if(!out.empty())
{
std::string path = data::curData.getPath() + "/" + folder;
std::string path = data::curData.getPath() + "/" + out;
if(data::zip)
{
path += ".zip";
zipFile cpyTo = zipOpen(path.c_str(), 0);
if(cpyTo != NULL)
{
fs::copyDirToZip("sv:/", &cpyTo);
zipClose(cpyTo, "");
}
zipFile zip = zipOpen(path.c_str(), 0);
fs::copyDirToZip("sv:/", &zip);
zipClose(zip, NULL);
}
else
{
@ -68,7 +65,6 @@ void ui::createNewBackup(const uint64_t& held)
path += "/";
fs::copyDirToDir("sv:/", path);
}
folderMenuPrepare(data::curUser, data::curData);
}
}
@ -77,63 +73,95 @@ void ui::overwriteBackup(unsigned ind)
{
fs::dirList list(data::curData.getPath());
std::string folderName = list.getItem(ind);
if(confirm(data::holdOver, ui::confOverwrite.c_str(), folderName.c_str()))
std::string itemName = list.getItem(ind);
if(confirm(data::holdOver, ui::confOverwrite.c_str(), itemName.c_str()))
{
std::string toPath = data::curData.getPath() + folderName + "/";
//Delete and recreate
fs::delDir(toPath);
mkdir(toPath.c_str(), 777);
std::string root = "sv:/";
fs::copyDirToDir(root, toPath);
if(list.isDir(ind))
{
std::string toPath = data::curData.getPath() + itemName + "/";
//Delete and recreate
fs::delDir(toPath);
mkdir(toPath.c_str(), 777);
fs::copyDirToDir("sv:/", toPath);
}
else
{
std::string toPath = data::curData.getPath() + itemName;
fs::delfile(toPath);
zipFile zip = zipOpen(toPath.c_str(), 0);
fs::copyDirToZip("sv:/", &zip);
zipClose(zip, NULL);
}
}
}
void ui::restoreBackup(unsigned ind)
{
if((data::curData.getType() != FsSaveDataType_System || data::sysSaveWrite) && folderMenu.getSelected() > 0)
fs::dirList list(data::curData.getPath());
std::string folderName = list.getItem(ind);
if((data::curData.getType() != FsSaveDataType_System || data::sysSaveWrite) && folderMenu.getSelected() > 0 && confirm(data::holdRest, ui::confRestore.c_str(), folderName.c_str()))
{
fs::dirList list(data::curData.getPath());
std::string folderName = list.getItem(ind);
if(confirm(data::holdRest, ui::confRestore.c_str(), folderName.c_str()))
if(data::autoBack)
{
if(data::autoBack)
switch(data::zip)
{
std::string autoFolder = data::curData.getPath() + "/AUTO - " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_ASC);
mkdir(autoFolder.c_str(), 777);
autoFolder += "/";
case true:
{
std::string autoZip = data::curData.getPath() + "/AUTO " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip";
zipFile zip = zipOpen(autoZip.c_str(), 0);
fs::copyDirToZip("sv:/", &zip);
zipClose(zip, NULL);
}
break;
std::string root = "sv:/";
fs::copyDirToDir(root, autoFolder);
case false:
{
std::string autoFolder = data::curData.getPath() + "/AUTO - " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD);
mkdir(autoFolder.c_str(), 777);
autoFolder += "/";
fs::copyDirToDir("sv:/", autoFolder);
}
break;
}
}
if(!list.isDir(ind))
{
std::string path = data::curData.getPath() + list.getItem(ind);
unzFile unz = unzOpen(path.c_str());
fs::copyZipToDir(&unz, "sv:/", "sv");
unzClose(unz);
}
else
{
std::string fromPath = data::curData.getPath() + folderName + "/";
std::string root = "sv:/";
fs::delDir(root);
fs::delDir("sv:/");
fsdevCommitDevice("sv");
fs::copyDirToDirCommit(fromPath, root, "sv");
//Rescan init folder menu if autobak to show changes
if(data::autoBack)
folderMenuPrepare(data::curUser, data::curData);
fs::copyDirToDirCommit(fromPath, "sv:/", "sv");
}
}
if(data::autoBack)
folderMenuPrepare(data::curUser, data::curData);
}
void ui::deleteBackup(unsigned ind)
{
fs::dirList list(data::curData.getPath());
std::string folderName = list.getItem(folderMenu.getSelected() - 1);
if(ui::confirmDelete(folderName))
std::string itemName = list.getItem(folderMenu.getSelected() - 1);
if(ui::confirmDelete(itemName))
{
std::string delPath = data::curData.getPath() + folderName + "/";
fs::delDir(delPath);
if(list.isDir(ind))
{
std::string delPath = data::curData.getPath() + itemName + "/";
fs::delDir(delPath);
}
else
{
std::string delPath = data::curData.getPath() + itemName;
fs::delfile(delPath);
}
}
folderMenuPrepare(data::curUser, data::curData);

View File

@ -196,7 +196,7 @@ void ui::exMenuPrep()
{
exMenu.reset();
exMenu.setParams(76, 98, 310);
for(unsigned i = 0; i < 10; i++)
for(unsigned i = 0; i < 11; i++)
exMenu.addOpt(ui::exMenuStr[i]);
}
@ -320,6 +320,19 @@ void ui::updateExMenu(const uint64_t& down, const uint64_t& held)
}
}
break;
case 10:
{
fs::logClose();
remove(std::string(fs::getWorkDir() + "log.txt").c_str());
std::string zipName = "JKSV - " + util::getDateTime(util::DATE_FMT_ASC) + ".zip";
zipFile jksv = zipOpen(std::string("sdmc:/" + zipName).c_str(), 0);
fs::copyDirToZip(fs::getWorkDir(), &jksv);
zipClose(jksv, NULL);
rename(std::string("sdmc:/" + zipName).c_str(), std::string(fs::getWorkDir() + zipName).c_str());
fs::logOpen();
}
break;
}
}
else if(down & KEY_B)