mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +00:00
UMS changes.
* Temporarily changed tracked libusbhsfs branch from main to dev. * Minor improvements in ums.c/h. * Refactored nsp_dumper_sd into nsp_dumper_stor - now capable of dumping NSPs to a mounted partition from a UMS device. * Fixed utilsWaitForButtonPress() when no button mask is provided. * Refactored utilsGetFreeSpaceFromFileSystemByPath() into utilsGetFileSystemStatsByPath().
This commit is contained in:
parent
6f43764e1b
commit
b4bf505d4f
8 changed files with 179 additions and 56 deletions
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -1,4 +1,4 @@
|
||||||
[submodule "libusbhsfs"]
|
[submodule "libusbhsfs"]
|
||||||
path = libusbhsfs
|
path = libusbhsfs
|
||||||
url = https://github.com/DarkMatterCore/libusbhsfs
|
url = https://github.com/DarkMatterCore/libusbhsfs
|
||||||
branch = main
|
branch = dev
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
#define BLOCK_SIZE 0x800000
|
#define BLOCK_SIZE 0x800000
|
||||||
#define OUTPATH "sdmc:/nsp/"
|
#define OUTPATH "/nsp/"
|
||||||
|
|
||||||
static const char *dump_type_strings[] = {
|
static const char *dump_type_strings[] = {
|
||||||
"dump base application",
|
"dump base application",
|
||||||
|
@ -41,21 +41,25 @@ static const u32 dump_type_strings_count = MAX_ELEMENTS(dump_type_strings);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char str[64];
|
char str[64];
|
||||||
bool val;
|
u32 val;
|
||||||
} options_t;
|
} options_t;
|
||||||
|
|
||||||
static options_t options[] = {
|
static options_t options[] = {
|
||||||
{ "set download distribution type", false },
|
{ "set download distribution type", 0 },
|
||||||
{ "remove console specific data", false },
|
{ "remove console specific data", 0 },
|
||||||
{ "remove titlekey crypto (overrides previous option)", false },
|
{ "remove titlekey crypto (overrides previous option)", 0 },
|
||||||
{ "change acid rsa key/sig", false },
|
{ "change acid rsa key/sig", 0 },
|
||||||
{ "disable linked account requirement", false },
|
{ "disable linked account requirement", 0 },
|
||||||
{ "enable screenshots", false },
|
{ "enable screenshots", 0 },
|
||||||
{ "enable video capture", false }
|
{ "enable video capture", 0 },
|
||||||
|
{ "output device", 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u32 options_count = MAX_ELEMENTS(options);
|
static const u32 options_count = MAX_ELEMENTS(options);
|
||||||
|
|
||||||
|
static UsbHsFsDevice *ums_devices = NULL;
|
||||||
|
static u32 ums_device_count = 0;
|
||||||
|
|
||||||
static void consolePrint(const char *text, ...)
|
static void consolePrint(const char *text, ...)
|
||||||
{
|
{
|
||||||
va_list v;
|
va_list v;
|
||||||
|
@ -65,7 +69,7 @@ static void consolePrint(const char *text, ...)
|
||||||
consoleUpdate(NULL);
|
consoleUpdate(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nspDump(TitleInfo *title_info)
|
static void nspDump(TitleInfo *title_info, u64 free_space)
|
||||||
{
|
{
|
||||||
if (!title_info || !title_info->content_count || !title_info->content_infos) return;
|
if (!title_info || !title_info->content_count || !title_info->content_infos) return;
|
||||||
|
|
||||||
|
@ -88,15 +92,22 @@ static void nspDump(TitleInfo *title_info)
|
||||||
for(u32 i = 0; i < options_count; i++) printf("%s: %s\n", options[i].str, options[i].val ? "yes" : "no");
|
for(u32 i = 0; i < options_count; i++) printf("%s: %s\n", options[i].str, options[i].val ? "yes" : "no");
|
||||||
printf("______________________________\n\n");
|
printf("______________________________\n\n");
|
||||||
|
|
||||||
bool set_download_type = options[0].val;
|
bool set_download_type = (options[0].val == 1);
|
||||||
bool remove_console_data = options[1].val;
|
bool remove_console_data = (options[1].val == 1);
|
||||||
bool remove_titlekey_crypto = options[2].val;
|
bool remove_titlekey_crypto = (options[2].val == 1);
|
||||||
bool change_acid_rsa = options[3].val;
|
bool change_acid_rsa = (options[3].val == 1);
|
||||||
bool patch_sua = options[4].val;
|
bool patch_sua = (options[4].val == 1);
|
||||||
bool patch_screenshot = options[5].val;
|
bool patch_screenshot = (options[5].val == 1);
|
||||||
bool patch_video_capture = options[6].val;
|
bool patch_video_capture = (options[6].val == 1);
|
||||||
|
UsbHsFsDevice *ums_device = (options[7].val == 0 ? NULL : &(ums_devices[options[7].val - 1]));
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
|
if (ums_device && ums_device->write_protect)
|
||||||
|
{
|
||||||
|
printf("device \"%s\" has write protection enabled!\n", ums_device->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
u8 *buf = NULL;
|
u8 *buf = NULL;
|
||||||
char *dump_name = NULL, *path = NULL;
|
char *dump_name = NULL, *path = NULL;
|
||||||
FILE *fd = NULL;
|
FILE *fd = NULL;
|
||||||
|
@ -138,13 +149,14 @@ static void nspDump(TitleInfo *title_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate output path. */
|
/* Generate output path. */
|
||||||
if (!(dump_name = titleGenerateFileName(title_info, TitleFileNameConvention_Full, TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly)))
|
if (!(dump_name = titleGenerateFileName(title_info, TitleFileNameConvention_Full, ums_device ? TitleFileNameIllegalCharReplaceType_IllegalFsChars : TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly)))
|
||||||
{
|
{
|
||||||
consolePrint("title generate file name failed\n");
|
consolePrint("title generate file name failed\n");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(path = utilsGeneratePath(OUTPATH, dump_name, ".nsp")))
|
sprintf(entry_name, "%s" OUTPATH, ums_device ? ums_device->name : "sdmc:");
|
||||||
|
if (!(path = utilsGeneratePath(entry_name, dump_name, ".nsp")))
|
||||||
{
|
{
|
||||||
consolePrint("generate path failed\n");
|
consolePrint("generate path failed\n");
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -457,6 +469,18 @@ static void nspDump(TitleInfo *title_info)
|
||||||
nsp_size = (nsp_header_size + pfs_file_ctx.fs_size);
|
nsp_size = (nsp_header_size + pfs_file_ctx.fs_size);
|
||||||
consolePrint("nsp header size: 0x%lX | nsp size: 0x%lX\n", nsp_header_size, nsp_size);
|
consolePrint("nsp header size: 0x%lX | nsp size: 0x%lX\n", nsp_header_size, nsp_size);
|
||||||
|
|
||||||
|
if (nsp_size >= free_space)
|
||||||
|
{
|
||||||
|
consolePrint("nsp size exceeds free space\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ums_device && ums_device->fs_type < UsbHsFsDeviceFileSystemType_exFAT && nsp_size > FAT32_FILESIZE_LIMIT)
|
||||||
|
{
|
||||||
|
consolePrint("split dumps not supported for FAT12/16/32 volumes in UMS devices (yet)\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
utilsCreateDirectoryTree(path, false);
|
utilsCreateDirectoryTree(path, false);
|
||||||
|
|
||||||
if (nsp_size > FAT32_FILESIZE_LIMIT && !utilsCreateConcatenationFile(path))
|
if (nsp_size > FAT32_FILESIZE_LIMIT && !utilsCreateConcatenationFile(path))
|
||||||
|
@ -745,6 +769,10 @@ int main(int argc, char *argv[])
|
||||||
u32 type_idx = 0, type_scroll = 0;
|
u32 type_idx = 0, type_scroll = 0;
|
||||||
u32 list_count = 0, list_idx = 0;
|
u32 list_count = 0, list_idx = 0;
|
||||||
|
|
||||||
|
u64 device_total_fs_size = 0, device_free_fs_size = 0;
|
||||||
|
char device_total_fs_size_str[36] = {0}, device_free_fs_size_str[32] = {0}, device_info[0x40] = {0};
|
||||||
|
bool device_retrieved_size = false, device_retrieved_info = false;
|
||||||
|
|
||||||
app_metadata = titleGetApplicationMetadataEntries(false, &app_count);
|
app_metadata = titleGetApplicationMetadataEntries(false, &app_count);
|
||||||
if (!app_metadata || !app_count)
|
if (!app_metadata || !app_count)
|
||||||
{
|
{
|
||||||
|
@ -754,14 +782,17 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
consolePrint("app metadata succeeded\n");
|
consolePrint("app metadata succeeded\n");
|
||||||
|
|
||||||
|
ums_devices = umsGetDevices(&ums_device_count);
|
||||||
|
|
||||||
utilsSleep(1);
|
utilsSleep(1);
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
consoleClear();
|
consoleClear();
|
||||||
|
|
||||||
printf("press b to %s.\n", menu == 0 ? "exit" : "go back");
|
printf("press b to %s.", menu == 0 ? "exit" : "go back");
|
||||||
printf("______________________________\n\n");
|
if (ums_device_count) printf(" press x to safely remove all ums devices.");
|
||||||
|
printf("\n______________________________\n\n");
|
||||||
|
|
||||||
if (menu == 0)
|
if (menu == 0)
|
||||||
{
|
{
|
||||||
|
@ -817,8 +848,44 @@ int main(int argc, char *argv[])
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
printf("start nsp dump\n");
|
printf("start nsp dump\n");
|
||||||
} else {
|
} else
|
||||||
|
if (i < options_count)
|
||||||
|
{
|
||||||
printf("%s: < %s >\n", options[i - 1].str, options[i - 1].val ? "yes" : "no");
|
printf("%s: < %s >\n", options[i - 1].str, options[i - 1].val ? "yes" : "no");
|
||||||
|
} else {
|
||||||
|
u32 device_idx = options[i - 1].val;
|
||||||
|
|
||||||
|
printf("%s: ", options[i - 1].str);
|
||||||
|
|
||||||
|
if (!device_retrieved_size)
|
||||||
|
{
|
||||||
|
sprintf(device_total_fs_size_str, "%s/", device_idx == 0 ? "sdmc:" : ums_devices[device_idx - 1].name);
|
||||||
|
utilsGetFileSystemStatsByPath(device_total_fs_size_str, &device_total_fs_size, &device_free_fs_size);
|
||||||
|
utilsGenerateFormattedSizeString(device_total_fs_size, device_total_fs_size_str, sizeof(device_total_fs_size_str));
|
||||||
|
utilsGenerateFormattedSizeString(device_free_fs_size, device_free_fs_size_str, sizeof(device_free_fs_size_str));
|
||||||
|
device_retrieved_size = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device_idx == 0)
|
||||||
|
{
|
||||||
|
printf("< sdmc: (%s / %s) >\n", device_free_fs_size_str, device_total_fs_size_str);
|
||||||
|
} else {
|
||||||
|
UsbHsFsDevice *ums_device = &(ums_devices[device_idx - 1]);
|
||||||
|
|
||||||
|
if (!device_retrieved_info)
|
||||||
|
{
|
||||||
|
if (ums_device->product_id[0])
|
||||||
|
{
|
||||||
|
sprintf(device_info, "%s, LUN %u, FS #%u, %s", ums_device->product_id, ums_device->lun, ums_device->fs_idx, UMS_FS_TYPE(ums_device->fs_type));
|
||||||
|
} else {
|
||||||
|
sprintf(device_info, "LUN %u, FS #%u, %s", ums_device->lun, ums_device->fs_idx, UMS_FS_TYPE(ums_device->fs_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
device_retrieved_info = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("< %s (%s) (%s / %s) >", ums_device->name, device_info, device_free_fs_size_str, device_total_fs_size_str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -827,7 +894,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
consoleUpdate(NULL);
|
consoleUpdate(NULL);
|
||||||
|
|
||||||
bool gc_update = false;
|
bool data_update = false;
|
||||||
u64 btn_down = 0, btn_held = 0;
|
u64 btn_down = 0, btn_held = 0;
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
|
@ -854,13 +921,27 @@ int main(int argc, char *argv[])
|
||||||
type_idx = type_scroll = 0;
|
type_idx = type_scroll = 0;
|
||||||
list_count = list_idx = 0;
|
list_count = list_idx = 0;
|
||||||
|
|
||||||
gc_update = true;
|
data_update = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (umsIsDeviceInfoUpdated())
|
||||||
|
{
|
||||||
|
free(ums_devices);
|
||||||
|
|
||||||
|
ums_devices = umsGetDevices(&ums_device_count);
|
||||||
|
|
||||||
|
options[options_count - 1].val = 0;
|
||||||
|
device_retrieved_size = device_retrieved_info = false;
|
||||||
|
|
||||||
|
data_update = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gc_update) continue;
|
if (data_update) continue;
|
||||||
|
|
||||||
if (btn_down & HidNpadButton_A)
|
if (btn_down & HidNpadButton_A)
|
||||||
{
|
{
|
||||||
|
@ -909,7 +990,7 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
consoleClear();
|
consoleClear();
|
||||||
utilsChangeHomeButtonBlockStatus(true);
|
utilsChangeHomeButtonBlockStatus(true);
|
||||||
nspDump(title_info);
|
nspDump(title_info, device_free_fs_size);
|
||||||
utilsChangeHomeButtonBlockStatus(false);
|
utilsChangeHomeButtonBlockStatus(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -973,7 +1054,24 @@ int main(int argc, char *argv[])
|
||||||
} else
|
} else
|
||||||
if ((btn_down & (HidNpadButton_Left | HidNpadButton_Right)) && menu == 2 && selected_idx != 0)
|
if ((btn_down & (HidNpadButton_Left | HidNpadButton_Right)) && menu == 2 && selected_idx != 0)
|
||||||
{
|
{
|
||||||
options[selected_idx - 1].val ^= 1;
|
if (selected_idx < options_count)
|
||||||
|
{
|
||||||
|
options[selected_idx - 1].val ^= 1;
|
||||||
|
} else {
|
||||||
|
bool left = (btn_down & HidNpadButton_Left);
|
||||||
|
u32 *device_idx = &(options[selected_idx - 1].val), orig_device_idx = *device_idx;
|
||||||
|
|
||||||
|
if (left)
|
||||||
|
{
|
||||||
|
(*device_idx)--;
|
||||||
|
if (*device_idx == UINT32_MAX) *device_idx = ums_device_count;
|
||||||
|
} else {
|
||||||
|
(*device_idx)++;
|
||||||
|
if (*device_idx > ums_device_count) *device_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*device_idx != orig_device_idx) device_retrieved_size = device_retrieved_info = false;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
if ((btn_down & (HidNpadButton_L | HidNpadButton_ZL)) && menu == 2 && title_info->previous)
|
if ((btn_down & (HidNpadButton_L | HidNpadButton_ZL)) && menu == 2 && title_info->previous)
|
||||||
{
|
{
|
||||||
|
@ -984,6 +1082,17 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
title_info = title_info->next;
|
title_info = title_info->next;
|
||||||
list_idx++;
|
list_idx++;
|
||||||
|
} else
|
||||||
|
if ((btn_down & HidNpadButton_X) && ums_device_count)
|
||||||
|
{
|
||||||
|
for(u32 i = 0; i < ums_device_count; i++) usbHsFsUnmountDevice(&(ums_devices[i]), false);
|
||||||
|
|
||||||
|
options[options_count - 1].val = 0;
|
||||||
|
|
||||||
|
free(ums_devices);
|
||||||
|
ums_devices = NULL;
|
||||||
|
|
||||||
|
ums_device_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (btn_held & (HidNpadButton_StickLDown | HidNpadButton_StickRDown | HidNpadButton_StickLUp | HidNpadButton_StickRUp)) svcSleepThread(50000000); // 50 ms
|
if (btn_held & (HidNpadButton_StickLDown | HidNpadButton_StickRDown | HidNpadButton_StickLUp | HidNpadButton_StickRUp)) svcSleepThread(50000000); // 50 ms
|
||||||
|
@ -996,6 +1105,8 @@ out2:
|
||||||
utilsWaitForButtonPress(0);
|
utilsWaitForButtonPress(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ums_devices) free(ums_devices);
|
||||||
|
|
||||||
if (app_metadata) free(app_metadata);
|
if (app_metadata) free(app_metadata);
|
||||||
|
|
||||||
out:
|
out:
|
|
@ -1 +1 @@
|
||||||
Subproject commit d02e10f3c38ee54b8b2f72343a61d8626a27d1c3
|
Subproject commit 62059ce5824b454bb20fb9575bdd49674ae19022
|
|
@ -618,13 +618,10 @@ TitleApplicationMetadata **titleGetApplicationMetadataEntries(bool is_system, u3
|
||||||
app_metadata[app_count++] = cur_app_metadata;
|
app_metadata[app_count++] = cur_app_metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app_metadata && app_count)
|
/* Update output counter. */
|
||||||
{
|
*out_count = app_count;
|
||||||
/* Update output counter. */
|
|
||||||
*out_count = app_count;
|
if (!app_metadata || !app_count) LOGFILE("No content data found for %s!", is_system ? "system titles" : "user applications");
|
||||||
} else {
|
|
||||||
LOGFILE("No content data found for %s!", is_system ? "system titles" : "user applications");
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
mutexUnlock(&g_titleMutex);
|
mutexUnlock(&g_titleMutex);
|
||||||
|
|
29
source/ums.c
29
source/ums.c
|
@ -119,25 +119,28 @@ UsbHsFsDevice *umsGetDevices(u32 *out_count)
|
||||||
|
|
||||||
UsbHsFsDevice *devices = NULL;
|
UsbHsFsDevice *devices = NULL;
|
||||||
|
|
||||||
if (!g_umsInterfaceInit || !g_umsDeviceCount || !g_umsDevices || !out_count)
|
if (!g_umsInterfaceInit || !out_count)
|
||||||
{
|
{
|
||||||
LOGFILE("Invalid parameters!");
|
LOGFILE("Invalid parameters!");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate memory for the output devices. */
|
if (g_umsDeviceCount && g_umsDevices)
|
||||||
devices = calloc(g_umsDeviceCount, sizeof(UsbHsFsDevice));
|
|
||||||
if (!devices)
|
|
||||||
{
|
{
|
||||||
LOGFILE("Failed to allocate memory for %u devices!", g_umsDeviceCount);
|
/* Allocate memory for the output devices. */
|
||||||
goto end;
|
devices = calloc(g_umsDeviceCount, sizeof(UsbHsFsDevice));
|
||||||
|
if (!devices)
|
||||||
|
{
|
||||||
|
LOGFILE("Failed to allocate memory for %u devices!", g_umsDeviceCount);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy device data. */
|
||||||
|
memcpy(devices, g_umsDevices, g_umsDeviceCount * sizeof(UsbHsFsDevice));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy device data. */
|
|
||||||
memcpy(devices, g_umsDevices, g_umsDeviceCount * sizeof(UsbHsFsDevice));
|
|
||||||
|
|
||||||
/* Update output device count. */
|
/* Update output device count. */
|
||||||
*out_count = g_umsDeviceCount;
|
*out_count = ((g_umsDeviceCount && g_umsDevices) ? g_umsDeviceCount : 0);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
mutexUnlock(&g_umsMutex);
|
mutexUnlock(&g_umsMutex);
|
||||||
|
@ -203,7 +206,8 @@ static void umsDetectionThreadFunc(void *arg)
|
||||||
if (g_umsDevices)
|
if (g_umsDevices)
|
||||||
{
|
{
|
||||||
/* List mounted devices. */
|
/* List mounted devices. */
|
||||||
if ((listed_device_count = usbHsFsListMountedDevices(g_umsDevices, g_umsDeviceCount)))
|
listed_device_count = usbHsFsListMountedDevices(g_umsDevices, g_umsDeviceCount);
|
||||||
|
if (listed_device_count)
|
||||||
{
|
{
|
||||||
/* Check if we got as many devices as we expected. */
|
/* Check if we got as many devices as we expected. */
|
||||||
if (listed_device_count == g_umsDeviceCount)
|
if (listed_device_count == g_umsDeviceCount)
|
||||||
|
@ -225,6 +229,9 @@ static void umsDetectionThreadFunc(void *arg)
|
||||||
|
|
||||||
/* Free USB Mass Storage device data if something went wrong. */
|
/* Free USB Mass Storage device data if something went wrong. */
|
||||||
if (fail) umsFreeDeviceData();
|
if (fail) umsFreeDeviceData();
|
||||||
|
} else {
|
||||||
|
/* Update USB Mass Storage device info updated flag. */
|
||||||
|
g_umsDeviceInfoUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutexUnlock(&g_umsMutex);
|
mutexUnlock(&g_umsMutex);
|
||||||
|
|
|
@ -23,6 +23,12 @@
|
||||||
#ifndef __UMS_H__
|
#ifndef __UMS_H__
|
||||||
#define __UMS_H__
|
#define __UMS_H__
|
||||||
|
|
||||||
|
#include <usbhsfs.h>
|
||||||
|
|
||||||
|
#define UMS_FS_TYPE(x) ((x) == UsbHsFsDeviceFileSystemType_FAT12 ? "FAT12" : ((x) == UsbHsFsDeviceFileSystemType_FAT16 ? "FAT16" : ((x) == UsbHsFsDeviceFileSystemType_FAT32 ? "FAT32" : \
|
||||||
|
((x) == UsbHsFsDeviceFileSystemType_exFAT ? "exFAT" : ((x) == UsbHsFsDeviceFileSystemType_NTFS ? "NTFS" : ((x) == UsbHsFsDeviceFileSystemType_EXT2 ? "EXT2" : \
|
||||||
|
((x) == UsbHsFsDeviceFileSystemType_EXT3 ? "EXT3" : ((x) == UsbHsFsDeviceFileSystemType_EXT4 ? "EXT4" : "Invalid"))))))))
|
||||||
|
|
||||||
/// Initializes the USB Mass Storage interface.
|
/// Initializes the USB Mass Storage interface.
|
||||||
bool umsInitialize(void);
|
bool umsInitialize(void);
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include "services.h"
|
#include "services.h"
|
||||||
#include "nca.h"
|
#include "nca.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "ums.h"
|
|
||||||
#include "title.h"
|
#include "title.h"
|
||||||
#include "bfttf.h"
|
#include "bfttf.h"
|
||||||
#include "fatfs/ff.h"
|
#include "fatfs/ff.h"
|
||||||
|
@ -347,8 +346,8 @@ u64 utilsGetButtonsHeld(void)
|
||||||
void utilsWaitForButtonPress(u64 flag)
|
void utilsWaitForButtonPress(u64 flag)
|
||||||
{
|
{
|
||||||
/* Don't consider stick movement as button inputs. */
|
/* Don't consider stick movement as button inputs. */
|
||||||
if (!flag) flag = (HidNpadButton_StickLLeft | HidNpadButton_StickLRight | HidNpadButton_StickLUp | HidNpadButton_StickLDown | HidNpadButton_StickRLeft | HidNpadButton_StickRRight | \
|
if (!flag) flag = ~(HidNpadButton_StickLLeft | HidNpadButton_StickLRight | HidNpadButton_StickLUp | HidNpadButton_StickLDown | HidNpadButton_StickRLeft | HidNpadButton_StickRRight | \
|
||||||
HidNpadButton_StickRUp | HidNpadButton_StickRDown);
|
HidNpadButton_StickRUp | HidNpadButton_StickRDown);
|
||||||
|
|
||||||
while(appletMainLoop())
|
while(appletMainLoop())
|
||||||
{
|
{
|
||||||
|
@ -586,13 +585,13 @@ void utilsGenerateFormattedSizeString(u64 size, char *dst, size_t dst_size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool utilsGetFreeSpaceFromFileSystemByPath(const char *path, u64 *out)
|
bool utilsGetFileSystemStatsByPath(const char *path, u64 *out_total, u64 *out_free)
|
||||||
{
|
{
|
||||||
char *name_end = NULL, stat_path[32] = {0};
|
char *name_end = NULL, stat_path[32] = {0};
|
||||||
struct statvfs info = {0};
|
struct statvfs info = {0};
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (!path || !*path || !(name_end = strchr(path, ':')) || *(name_end + 1) != '/' || !out)
|
if (!path || !*path || !(name_end = strchr(path, ':')) || *(name_end + 1) != '/' || (!out_total && !out_free))
|
||||||
{
|
{
|
||||||
LOGFILE("Invalid parameters!");
|
LOGFILE("Invalid parameters!");
|
||||||
return false;
|
return false;
|
||||||
|
@ -607,7 +606,9 @@ bool utilsGetFreeSpaceFromFileSystemByPath(const char *path, u64 *out)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = ((u64)info.f_bfree * (u64)info.f_frsize);
|
if (out_total) *out_total = ((u64)info.f_blocks * (u64)info.f_frsize);
|
||||||
|
if (out_free) *out_free = ((u64)info.f_bfree * (u64)info.f_frsize);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,9 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
#include <usbhsfs.h>
|
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "ums.h"
|
||||||
|
|
||||||
#define APP_BASE_PATH "sdmc:/switch/" APP_TITLE "/"
|
#define APP_BASE_PATH "sdmc:/switch/" APP_TITLE "/"
|
||||||
|
|
||||||
|
@ -117,9 +117,10 @@ void utilsGenerateHexStringFromData(char *dst, size_t dst_size, const void *src,
|
||||||
/// Formats the provided 'size' value to a human readable size string and stores it in 'dst'.
|
/// Formats the provided 'size' value to a human readable size string and stores it in 'dst'.
|
||||||
void utilsGenerateFormattedSizeString(u64 size, char *dst, size_t dst_size);
|
void utilsGenerateFormattedSizeString(u64 size, char *dst, size_t dst_size);
|
||||||
|
|
||||||
/// Saves the free file space from the filesystem pointed to by the input path (e.g. "sdmc:/") to 'out'.
|
/// Saves the total size and free space available from the filesystem pointed to by the input path (e.g. "sdmc:/") to 'out_total' and 'out_free', respectively.
|
||||||
|
/// Either 'out_total' or 'out_free' can be set to NULL, but at least one of them must be set to a valid pointer.
|
||||||
/// Returns false if there's an error.
|
/// Returns false if there's an error.
|
||||||
bool utilsGetFreeSpaceFromFileSystemByPath(const char *path, u64 *out);
|
bool utilsGetFileSystemStatsByPath(const char *path, u64 *out_total, u64 *out_free);
|
||||||
|
|
||||||
/// Commits SD card filesystem changes.
|
/// Commits SD card filesystem changes.
|
||||||
/// Must be used after closing a file handle from the SD card.
|
/// Must be used after closing a file handle from the SD card.
|
||||||
|
|
Loading…
Reference in a new issue