Skip to content

Commit c6aa522

Browse files
committed
nx: rescan user accounts on opendir in save, option to skip converting to ascii for save zips.
fixes #11
1 parent 7f17afc commit c6aa522

File tree

6 files changed

+101
-87
lines changed

6 files changed

+101
-87
lines changed

assets/config.ini.template

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ mount_bis = 0
4949
# enables led on the controller to light flash
5050
led = 0
5151

52+
# set to disable convert non-ascii characters to _
53+
skip_ascii_convert = 0
54+
5255
# options specific to Nintendo Switch App
5356
[Nx-App]
5457
; anon = 0

src/platform/nx/main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ int main(int argc, char** argv) {
154154
bool mount_bis = ini_getbool("Nx", "mount_bis", 0, INI_PATH);
155155
bool save_writable = ini_getbool("Nx", "save_writable", 0, INI_PATH);
156156
g_led_enabled = ini_getbool("Nx", "led", 1, INI_PATH);
157+
bool skip_ascii_convert = ini_getbool("Nx", "skip_ascii_convert", 0, INI_PATH);
157158
g_ftpsrv_config.port = ini_getl("Nx", "app_port", g_ftpsrv_config.port, INI_PATH); // compat
158159

159160
// get Nx-App overrides
@@ -187,7 +188,7 @@ int main(int argc, char** argv) {
187188
return error_loop("failed to get current ip address");
188189
}
189190

190-
vfs_nx_init(NULL, mount_devices, save_writable, mount_bis);
191+
vfs_nx_init(NULL, mount_devices, save_writable, mount_bis, skip_ascii_convert);
191192

192193
const struct in_addr addr = {ip};
193194
printf(TEXT_YELLOW "ip: %s\n", inet_ntoa(addr));

src/platform/nx/main_sysmod.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ int main(void) {
4545
bool mount_bis = ini_getbool("Nx", "mount_bis", 0, INI_PATH);
4646
bool save_writable = ini_getbool("Nx", "save_writable", 0, INI_PATH);
4747
g_led_enabled = ini_getbool("Nx", "led", 1, INI_PATH);
48+
bool skip_ascii_convert = ini_getbool("Nx", "skip_ascii_convert", 0, INI_PATH);
4849
g_ftpsrv_config.port = ini_getl("Nx", "sys_port", g_ftpsrv_config.port, INI_PATH); // compat
4950

5051
// get Nx-Sys overrides
@@ -70,7 +71,7 @@ int main(void) {
7071
return EXIT_FAILURE;
7172
}
7273

73-
vfs_nx_init(NULL, mount_devices, save_writable, mount_bis);
74+
vfs_nx_init(NULL, mount_devices, save_writable, mount_bis, skip_ascii_convert);
7475

7576
int timeout = -1;
7677
if (g_ftpsrv_config.timeout) {

src/platform/nx/vfs/vfs_nx_save.c

Lines changed: 42 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -429,59 +429,6 @@ static struct SaveAcc g_acc_profile[12];
429429
static s32 g_acc_count;
430430
static bool g_writable;
431431

432-
// list of all characters that are invalid for fat,
433-
// these are coverted to "_"
434-
static const char INVALID_CHAR_TABLE[] = {
435-
'<',
436-
'>',
437-
':',
438-
'"',
439-
'/',
440-
'\\',
441-
'|',
442-
'?',
443-
'*',
444-
'.',
445-
',',
446-
';',
447-
'+',
448-
'=',
449-
'&',
450-
'%', // probably invalid
451-
};
452-
453-
static void make_zip_string_valid(char* str) {
454-
for (int i = 0; str[i]; i++) {
455-
const unsigned char c = str[i];
456-
const unsigned char c2 = str[i + 1];
457-
if (c < 0x20 || c >= 0x80) {
458-
if (c == 195 && c2 == 169) {
459-
str[i + 1] = 'e';
460-
memcpy(str + i, str + i + 1, strlen(str) - i);
461-
} else if (c == 226 && c2 == 128 && (unsigned char)str[i + 2] == 153) {
462-
str[i + 2] = '\'';
463-
memcpy(str + i, str + i + 2, strlen(str) - i);
464-
} else {
465-
str[i] = '_';
466-
}
467-
} else {
468-
for (int j = 0; j < ARRAY_SIZE(INVALID_CHAR_TABLE); j++) {
469-
if (c == INVALID_CHAR_TABLE[j]) {
470-
// see what the next character is
471-
if (str[i + 1] == '\0') {
472-
str[i] = '\0';
473-
} else if (str[i + 1] != ' ') {
474-
str[i] = '_';
475-
} else {
476-
memcpy(str + i, str + i + 1, strlen(str) - i);
477-
}
478-
break;
479-
}
480-
}
481-
}
482-
}
483-
}
484-
485432
static FsFileSystem* mount_save_fs(const struct SavePathData* d) {
486433
for (int i = 0; i < ARRAY_SIZE(g_save_cache); i++) {
487434
struct SaveCacheEntry* entry = &g_save_cache[i];
@@ -613,6 +560,40 @@ static void build_native_path(char out[FS_MAX_PATH], const char* path, const str
613560
}
614561
}
615562

563+
static void rescan_users(void) {
564+
memset(g_acc_profile, 0, sizeof(g_acc_profile));
565+
g_acc_count = 0;
566+
567+
AccountUid uids[8];
568+
s32 count;
569+
Result rc;
570+
if (R_FAILED(rc = accountListAllUsers(uids, 8, &count))) {
571+
log_file_fwrite("failed: accountListAllUsers() 0x%X\n", rc);
572+
} else {
573+
for (int i = 0; i < count; i++) {
574+
AccountProfile profile;
575+
if (R_FAILED(rc = accountGetProfile(&profile, uids[i]))) {
576+
log_file_fwrite("failed: accountGetProfile() 0x%X\n", rc);
577+
} else {
578+
AccountProfileBase base;
579+
if (R_FAILED(rc = accountProfileGet(&profile, NULL, &base))) {
580+
log_file_fwrite("failed: accountProfileGet() 0x%X\n", rc);
581+
} else {
582+
strcpy(g_acc_profile[g_acc_count].name, base.nickname);
583+
g_acc_profile[g_acc_count].uid = uids[i];
584+
g_acc_count++;
585+
}
586+
accountProfileClose(&profile);
587+
}
588+
}
589+
}
590+
591+
strcpy(g_acc_profile[g_acc_count++].name, "bcat");
592+
strcpy(g_acc_profile[g_acc_count++].name, "cache");
593+
strcpy(g_acc_profile[g_acc_count++].name, "device");
594+
strcpy(g_acc_profile[g_acc_count++].name, "system");
595+
}
596+
616597
static int vfs_save_open(void* user, const char* path, enum FtpVfsOpenMode mode) {
617598
struct VfsSaveFile* f = user;
618599
f->data = get_type(path);
@@ -727,6 +708,9 @@ static int vfs_save_opendir(void* user, const char* path) {
727708
default: return -1;
728709

729710
case SaveDirType_Root:
711+
rescan_users();
712+
break;
713+
730714
case SaveDirType_User1:
731715
break;
732716

@@ -822,7 +806,7 @@ static const char* vfs_save_readdir(void* user, void* user_entry) {
822806
snprintf(entry->name, sizeof(entry->name), "[%016lX]%s", entry->info.application_id, ext);
823807
} else {
824808
if (f->data.type == SaveDirType_Zip) {
825-
make_zip_string_valid(name.str);
809+
utilsReplaceIllegalCharacters(name.str, true);
826810
}
827811
snprintf(entry->name, sizeof(entry->name), "%s [%016lX]%s", name.str, entry->info.application_id, ext);
828812
}
@@ -1023,35 +1007,7 @@ static int vfs_save_rename(const char* src, const char* dst) {
10231007

10241008
void vfs_save_init(bool save_writable) {
10251009
g_writable = save_writable;
1026-
1027-
AccountUid uids[8];
1028-
s32 count;
1029-
Result rc;
1030-
if (R_FAILED(rc = accountListAllUsers(uids, 8, &count))) {
1031-
log_file_fwrite("failed: accountListAllUsers() 0x%X\n", rc);
1032-
} else {
1033-
for (int i = 0; i < count; i++) {
1034-
AccountProfile profile;
1035-
if (R_FAILED(rc = accountGetProfile(&profile, uids[i]))) {
1036-
log_file_fwrite("failed: accountGetProfile() 0x%X\n", rc);
1037-
} else {
1038-
AccountProfileBase base;
1039-
if (R_FAILED(rc = accountProfileGet(&profile, NULL, &base))) {
1040-
log_file_fwrite("failed: accountProfileGet() 0x%X\n", rc);
1041-
} else {
1042-
strcpy(g_acc_profile[g_acc_count].name, base.nickname);
1043-
g_acc_profile[g_acc_count].uid = base.uid;
1044-
g_acc_count++;
1045-
}
1046-
accountProfileClose(&profile);
1047-
}
1048-
}
1049-
}
1050-
1051-
strcpy(g_acc_profile[g_acc_count++].name, "bcat");
1052-
strcpy(g_acc_profile[g_acc_count++].name, "cache");
1053-
strcpy(g_acc_profile[g_acc_count++].name, "device");
1054-
strcpy(g_acc_profile[g_acc_count++].name, "system");
1010+
rescan_users();
10551011
}
10561012

10571013
void vfs_save_exit(void) {
@@ -1064,6 +1020,9 @@ void vfs_save_exit(void) {
10641020
fsFsClose(&entry->fs);
10651021
}
10661022
}
1023+
1024+
memset(g_acc_profile, 0, sizeof(g_acc_profile));
1025+
g_acc_count = 0;
10671026
}
10681027

10691028
const FtpVfs g_vfs_save = {

src/platform/nx/vfs_nx.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ static NcmContentMetaDatabase g_db[NCM_SIZE];
2121
static struct VfsDeviceEntry g_device[DEVICE_NUM];
2222
static enum VFS_TYPE g_device_type[DEVICE_NUM];
2323
static u32 g_device_count;
24+
static bool g_skip_ascii_convert = false;
2425

2526
static const FtpVfs* g_vfs[] = {
2627
[VFS_TYPE_NONE] = &g_vfs_none,
@@ -289,6 +290,50 @@ Result get_app_name(u64 app_id, NcmContentId* id, struct AppName* name) {
289290
return rc;
290291
}
291292

293+
// taken from nxdumptool.
294+
void utilsReplaceIllegalCharacters(char *str, bool ascii_only)
295+
{
296+
static const char g_illegalFileSystemChars[] = "\\/:*?\"<>|";
297+
298+
if (g_skip_ascii_convert) {
299+
return;
300+
}
301+
302+
size_t str_size = 0, cur_pos = 0;
303+
304+
if (!str || !(str_size = strlen(str))) return;
305+
306+
u8 *ptr1 = (u8*)str, *ptr2 = ptr1;
307+
ssize_t units = 0;
308+
u32 code = 0;
309+
bool repl = false;
310+
311+
while(cur_pos < str_size)
312+
{
313+
units = decode_utf8(&code, ptr1);
314+
if (units < 0) break;
315+
316+
if (code < 0x20 || (!ascii_only && code == 0x7F) || (ascii_only && code >= 0x7F) || \
317+
(units == 1 && memchr(g_illegalFileSystemChars, (int)code, sizeof(g_illegalFileSystemChars))))
318+
{
319+
if (!repl)
320+
{
321+
*ptr2++ = '_';
322+
repl = true;
323+
}
324+
} else {
325+
if (ptr2 != ptr1) memmove(ptr2, ptr1, (size_t)units);
326+
ptr2 += units;
327+
repl = false;
328+
}
329+
330+
ptr1 += units;
331+
cur_pos += (size_t)units;
332+
}
333+
334+
*ptr2 = '\0';
335+
}
336+
292337
struct MountEntry {
293338
const char* name;
294339
FsBisPartitionId id;
@@ -301,8 +346,10 @@ static const struct MountEntry BIS_NAMES[] = {
301346
{ "bis_system", FsBisPartitionId_System },
302347
};
303348

304-
void vfs_nx_init(const struct VfsNxCustomPath* custom, bool enable_devices, bool save_writable, bool mount_bis) {
349+
void vfs_nx_init(const struct VfsNxCustomPath* custom, bool enable_devices, bool save_writable, bool mount_bis, bool skip_ascii_convert) {
305350
g_enabled_devices = enable_devices;
351+
g_skip_ascii_convert = skip_ascii_convert;
352+
306353
if (g_enabled_devices) {
307354
vfs_nx_add_device("sdmc", VFS_TYPE_FS);
308355

src/platform/nx/vfs_nx.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,16 @@ struct VfsNxCustomPath {
163163
FtpVfs* func;
164164
};
165165

166-
void vfs_nx_init(const struct VfsNxCustomPath* custom, bool enable_devices, bool save_writable, bool mount_bis);
166+
void vfs_nx_init(const struct VfsNxCustomPath* custom, bool enable_devices, bool save_writable, bool mount_bis, bool skip_ascii_convert);
167167
void vfs_nx_exit(void);
168168
void vfs_nx_add_device(const char* name, enum VFS_TYPE type);
169169

170170
Result get_app_name(u64 app_id, NcmContentId* id, struct AppName* name);
171171
Result get_app_name2(u64 app_id, NcmContentMetaDatabase* db, NcmContentStorage* cs, NcmContentId* id, struct AppName* name);
172172

173+
// taken from nxdumptool.
174+
void utilsReplaceIllegalCharacters(char *str, bool ascii_only);
175+
173176
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
174177

175178
#ifdef __cplusplus

0 commit comments

Comments
 (0)