mirror of
https://github.com/DarkStore-3DS/DarkStore.git
synced 2026-07-03 00:39:02 +00:00
Add safety checks for low SD card space (#90)
* Some attempt. * Enable some-safety-freespace-work nightlies * Upload elf with nightly * *Derp fixes.* * Bye Bye testing things. * Revert "Upload elf with nightly" This reverts commit 303968cd78e466a3fcc010915565d8265acaa76a. * Add safety checks to fcopy Co-authored-by: StackZ <47382115+SuperSaiyajinStackZ@users.noreply.github.com>
This commit is contained in:
@@ -34,5 +34,6 @@ Result openFile(Handle *fileHandle, const char *path, bool write);
|
|||||||
Result deleteFile(const char *path);
|
Result deleteFile(const char *path);
|
||||||
Result removeDir(const char *path);
|
Result removeDir(const char *path);
|
||||||
Result removeDirRecursive(const char *path);
|
Result removeDirRecursive(const char *path);
|
||||||
|
u64 getAvailableSpace();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
namespace StringUtils {
|
namespace StringUtils {
|
||||||
std::string lower_case(const std::string &str);
|
std::string lower_case(const std::string &str);
|
||||||
std::string FetchStringsFromVector(const std::vector<std::string> &fetch);
|
std::string FetchStringsFromVector(const std::vector<std::string> &fetch);
|
||||||
std::string formatBytes(int bytes);
|
std::string formatBytes(u64 bytes);
|
||||||
std::string GetMarkString(int marks);
|
std::string GetMarkString(int marks);
|
||||||
std::vector<std::string> GetMarks(int marks);
|
std::vector<std::string> GetMarks(int marks);
|
||||||
std::string format(const char *fmt_str, ...);
|
std::string format(const char *fmt_str, ...);
|
||||||
|
|||||||
@@ -196,10 +196,6 @@ Result Init::MainLoop() {
|
|||||||
|
|
||||||
if (!exiting) Gui::ScreenLogic(hDown, hHeld, touch, true, false);
|
if (!exiting) Gui::ScreenLogic(hDown, hHeld, touch, true, false);
|
||||||
|
|
||||||
if (aptCheckHomePressRejected()) {
|
|
||||||
if (Msg::promptMsg(Lang::get("FEATURE_SIDE_EFFECTS"))) aptSetHomeAllowed(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (exiting) {
|
if (exiting) {
|
||||||
if (hDown & KEY_START) fullExit = true; // Make it optionally faster.
|
if (hDown & KEY_START) fullExit = true; // Make it optionally faster.
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
#include "files.hpp"
|
||||||
#include "storeUtils.hpp"
|
#include "storeUtils.hpp"
|
||||||
#include "structs.hpp"
|
#include "structs.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -272,8 +272,7 @@ static void SettingsHandleMain(int &page, bool &dspSettings, int &storeMode, int
|
|||||||
Overlays::ShowCredits();
|
Overlays::ShowCredits();
|
||||||
|
|
||||||
} else if (touching(touch, mainButtons[6])) {
|
} else if (touching(touch, mainButtons[6])) {
|
||||||
if (QueueRuns) exiting = Msg::promptMsg(Lang::get("FEATURE_SIDE_EFFECTS"));
|
if (!QueueRuns) exiting = true;
|
||||||
else exiting = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,8 +312,7 @@ static void SettingsHandleMain(int &page, bool &dspSettings, int &storeMode, int
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
if (QueueRuns) exiting = Msg::promptMsg(Lang::get("FEATURE_SIDE_EFFECTS"));
|
if (!QueueRuns) exiting = true;
|
||||||
else exiting = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,19 +123,25 @@ Result Title::Install(const char *ciaPath, bool updatingSelf) {
|
|||||||
ret = FSFILE_GetSize(fileHandle, &size);
|
ret = FSFILE_GetSize(fileHandle, &size);
|
||||||
if (R_FAILED(ret)) {
|
if (R_FAILED(ret)) {
|
||||||
printf("Error in:\nFSFILE_GetSize\n");
|
printf("Error in:\nFSFILE_GetSize\n");
|
||||||
|
FSFILE_Close(fileHandle);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getAvailableSpace() >= size) {
|
||||||
ret = AM_StartCiaInstall(media, &ciaHandle);
|
ret = AM_StartCiaInstall(media, &ciaHandle);
|
||||||
if (R_FAILED(ret)) {
|
if (R_FAILED(ret)) {
|
||||||
printf("Error in:\nAM_StartCiaInstall\n");
|
printf("Error in:\nAM_StartCiaInstall\n");
|
||||||
|
FSFILE_Close(fileHandle);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 toRead = 0x200000;
|
u32 toRead = 0x200000;
|
||||||
u8 *buf = new u8[toRead];
|
u8 *buf = new u8[toRead];
|
||||||
|
|
||||||
if (!buf) return -1;
|
if (!buf) {
|
||||||
|
FSFILE_Close(fileHandle);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
installSize = size;
|
installSize = size;
|
||||||
do {
|
do {
|
||||||
@@ -148,8 +154,10 @@ Result Title::Install(const char *ciaPath, bool updatingSelf) {
|
|||||||
ret = AM_FinishCiaInstall(ciaHandle);
|
ret = AM_FinishCiaInstall(ciaHandle);
|
||||||
if (R_FAILED(ret)) {
|
if (R_FAILED(ret)) {
|
||||||
printf("Error in:\nAM_FinishCiaInstall\n");
|
printf("Error in:\nAM_FinishCiaInstall\n");
|
||||||
|
FSFILE_Close(fileHandle);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = FSFILE_Close(fileHandle);
|
ret = FSFILE_Close(fileHandle);
|
||||||
if (R_FAILED(ret)) {
|
if (R_FAILED(ret)) {
|
||||||
|
|||||||
@@ -103,11 +103,14 @@ static void commitToFileThreadFunc(void *args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t file_handle_data(char *ptr, size_t size, size_t nmemb, void *userdata) {
|
static size_t file_handle_data(char *ptr, size_t size, size_t nmemb, void *userdata) {
|
||||||
|
if (getAvailableSpace() < (u64)downloadTotal) return 0; // Out of space.
|
||||||
|
if (writeError) return 0;
|
||||||
|
if (QueueSystem::CancelCallback) return 0;
|
||||||
|
|
||||||
(void)userdata;
|
(void)userdata;
|
||||||
const size_t bsz = size * nmemb;
|
const size_t bsz = size * nmemb;
|
||||||
size_t tofill = 0;
|
size_t tofill = 0;
|
||||||
if (writeError) return 0;
|
|
||||||
if (QueueSystem::CancelCallback) return 0;
|
|
||||||
|
|
||||||
if (!g_buffers[g_index]) {
|
if (!g_buffers[g_index]) {
|
||||||
LightEvent_Init(&waitCommit, RESET_STICKY);
|
LightEvent_Init(&waitCommit, RESET_STICKY);
|
||||||
@@ -593,6 +596,7 @@ bool DownloadUniStore(const std::string &URL, int currentRev, std::string &fl, b
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getAvailableSpace() >= result_written) {
|
||||||
if (nlohmann::json::accept(result_buf)) {
|
if (nlohmann::json::accept(result_buf)) {
|
||||||
nlohmann::json parsedAPI = nlohmann::json::parse(result_buf);
|
nlohmann::json parsedAPI = nlohmann::json::parse(result_buf);
|
||||||
|
|
||||||
@@ -672,6 +676,7 @@ bool DownloadUniStore(const std::string &URL, int currentRev, std::string &fl, b
|
|||||||
Msg::waitMsg(Lang::get("UNISTORE_INVALID_ERROR"));
|
Msg::waitMsg(Lang::get("UNISTORE_INVALID_ERROR"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
socExit();
|
socExit();
|
||||||
free(result_buf);
|
free(result_buf);
|
||||||
@@ -733,6 +738,7 @@ bool DownloadSpriteSheet(const std::string &URL, const std::string &file) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getAvailableSpace() >= result_written) {
|
||||||
C2D_SpriteSheet sheet = C2D_SpriteSheetLoadFromMem(result_buf, result_written);
|
C2D_SpriteSheet sheet = C2D_SpriteSheetLoadFromMem(result_buf, result_written);
|
||||||
|
|
||||||
if (sheet) {
|
if (sheet) {
|
||||||
@@ -752,6 +758,7 @@ bool DownloadSpriteSheet(const std::string &URL, const std::string &file) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
socExit();
|
socExit();
|
||||||
free(result_buf);
|
free(result_buf);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "extract.hpp"
|
#include "extract.hpp"
|
||||||
|
#include "files.hpp"
|
||||||
#include "queueSystem.hpp"
|
#include "queueSystem.hpp"
|
||||||
#include "scriptUtils.hpp"
|
#include "scriptUtils.hpp"
|
||||||
#include <archive.hpp>
|
#include <archive.hpp>
|
||||||
@@ -65,6 +66,8 @@ Result getExtractedSize(const std::string &archivePath, const std::string &wante
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result extractArchive(const std::string &archivePath, const std::string &wantedFile, const std::string &outputPath) {
|
Result extractArchive(const std::string &archivePath, const std::string &wantedFile, const std::string &outputPath) {
|
||||||
|
if (getAvailableSpace() < extractSize) return -1; // Out of space.
|
||||||
|
|
||||||
archive *a = archive_read_new();
|
archive *a = archive_read_new();
|
||||||
archive_entry *entry;
|
archive_entry *entry;
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fileBrowse.hpp"
|
#include "fileBrowse.hpp"
|
||||||
|
#include "files.hpp"
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
#include "structs.hpp"
|
#include "structs.hpp"
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
@@ -236,6 +237,11 @@ int fcopy(const char *sourcePath, const char *destinationPath) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(getAvailableSpace() < copySize) {
|
||||||
|
fclose(sourceFile);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
FILE *destinationFile = fopen(destinationPath, "wb");
|
FILE *destinationFile = fopen(destinationPath, "wb");
|
||||||
if (!destinationFile) {
|
if (!destinationFile) {
|
||||||
fclose(sourceFile);
|
fclose(sourceFile);
|
||||||
@@ -245,7 +251,15 @@ int fcopy(const char *sourcePath, const char *destinationPath) {
|
|||||||
while(1) {
|
while(1) {
|
||||||
/* Copy file to destination path. */
|
/* Copy file to destination path. */
|
||||||
int numr = fread(copyBuf, sizeof(u32), copyBufSize, sourceFile);
|
int numr = fread(copyBuf, sizeof(u32), copyBufSize, sourceFile);
|
||||||
fwrite(copyBuf, sizeof(u32), numr, destinationFile);
|
int written = fwrite(copyBuf, sizeof(u32), numr, destinationFile);
|
||||||
|
|
||||||
|
if(written != numr) {
|
||||||
|
fclose(sourceFile);
|
||||||
|
fclose(destinationFile);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
copyOffset += copyBufSize * sizeof(u32);
|
copyOffset += copyBufSize * sizeof(u32);
|
||||||
|
|
||||||
if (copyOffset > copySize) {
|
if (copyOffset > copySize) {
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "files.hpp"
|
#include "files.hpp"
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
|
||||||
FS_Path getPathInfo(const char *path, FS_ArchiveID *archive) {
|
FS_Path getPathInfo(const char *path, FS_ArchiveID *archive) {
|
||||||
*archive = ARCHIVE_SDMC;
|
*archive = ARCHIVE_SDMC;
|
||||||
@@ -128,3 +130,12 @@ Result removeDirRecursive(const char *path) {
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Code borrowed from GodMode9i:
|
||||||
|
https://github.com/DS-Homebrew/GodMode9i/blob/d68ac105e68b4a1fc2c706a08c7a394255c325c2/arm9/source/driveOperations.cpp#L166-L170
|
||||||
|
*/
|
||||||
|
u64 getAvailableSpace() {
|
||||||
|
struct statvfs st;
|
||||||
|
statvfs("sdmc:/", &st);
|
||||||
|
return (u64)st.f_bsize * (u64)st.f_bavail;
|
||||||
|
}
|
||||||
@@ -65,14 +65,15 @@ std::string StringUtils::FetchStringsFromVector(const std::vector<std::string> &
|
|||||||
/*
|
/*
|
||||||
adapted from GM9i's byte parsing.
|
adapted from GM9i's byte parsing.
|
||||||
*/
|
*/
|
||||||
std::string StringUtils::formatBytes(int bytes) {
|
std::string StringUtils::formatBytes(u64 bytes) {
|
||||||
char out[32];
|
char out[32];
|
||||||
|
|
||||||
if (bytes == 1) snprintf(out, sizeof(out), "%d Byte", bytes);
|
if (bytes == 1) snprintf(out, sizeof(out), "%lld Byte", bytes);
|
||||||
else if (bytes < 1024) snprintf(out, sizeof(out), "%d Bytes", bytes);
|
else if (bytes < 1ull << 10) snprintf(out, sizeof(out), "%lld Bytes", bytes);
|
||||||
else if (bytes < 1024 * 1024) snprintf(out, sizeof(out), "%.1f KiB", (float)bytes / 1024);
|
else if (bytes < 1ull << 20) snprintf(out, sizeof(out), "%.1f KiB", (float)bytes / 1024);
|
||||||
else if (bytes < 1024 * 1024 * 1024) snprintf(out, sizeof(out), "%.1f MiB", (float)bytes / 1024 / 1024);
|
else if (bytes < 1ull << 30) snprintf(out, sizeof(out), "%.1f MiB", (float)bytes / 1024 / 1024);
|
||||||
else snprintf(out, sizeof(out), "%.1f GiB", (float)bytes / 1024 / 1024 / 1024);
|
else if (bytes < 1ull << 40) snprintf(out, sizeof(out), "%.1f GiB", (float)bytes / 1024 / 1024 / 1024);
|
||||||
|
else snprintf(out, sizeof(out), "%.1f TiB", (float)bytes / 1024 / 1024 / 1024 / 1024);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user