archive/romfs: Reduce TLS usage by sharing buffers + changed archive_rename to use a VLA

This commit is contained in:
fincs 2020-07-02 21:34:02 +02:00
parent 3e1d03aecd
commit 1c7914e2f4
No known key found for this signature in database
GPG Key ID: 62C7609ADA219C60
4 changed files with 57 additions and 50 deletions

View File

@ -14,6 +14,7 @@
#include <3ds/services/fs.h> #include <3ds/services/fs.h>
#include <3ds/util/utf.h> #include <3ds/util/utf.h>
#include "path_buf.h"
/*! @internal /*! @internal
* *
@ -110,9 +111,6 @@ static archive_fsdevice archive_devices[32];
/*! @endcond */ /*! @endcond */
static __thread char __fixedpath[PATH_MAX+1];
static __thread uint16_t __utf16path[PATH_MAX+1];
static archive_fsdevice *archiveFindDevice(const char *name) static archive_fsdevice *archiveFindDevice(const char *name)
{ {
u32 i; u32 i;
@ -204,17 +202,17 @@ archive_fixpath(struct _reent *r,
} }
if(path[0] == '/') if(path[0] == '/')
strncpy(__fixedpath, path, PATH_MAX); strncpy(__ctru_dev_path_buf, path, PATH_MAX);
else else
{ {
strncpy(__fixedpath, dev->cwd, PATH_MAX); strncpy(__ctru_dev_path_buf, dev->cwd, PATH_MAX);
__fixedpath[PATH_MAX] = '\0'; __ctru_dev_path_buf[PATH_MAX] = '\0';
strncat(__fixedpath, path, PATH_MAX); strncat(__ctru_dev_path_buf, path, PATH_MAX);
} }
if(__fixedpath[PATH_MAX] != 0) if(__ctru_dev_path_buf[PATH_MAX] != 0)
{ {
__fixedpath[PATH_MAX] = 0; __ctru_dev_path_buf[PATH_MAX] = 0;
r->_errno = ENAMETOOLONG; r->_errno = ENAMETOOLONG;
return NULL; return NULL;
} }
@ -222,7 +220,7 @@ archive_fixpath(struct _reent *r,
if(device) if(device)
*device = dev; *device = dev;
return __fixedpath; return __ctru_dev_path_buf;
} }
static const FS_Path static const FS_Path
@ -238,23 +236,23 @@ archive_utf16path(struct _reent *r,
if(archive_fixpath(r, path, device) == NULL) if(archive_fixpath(r, path, device) == NULL)
return fspath; return fspath;
units = utf8_to_utf16(__utf16path, (const uint8_t*)__fixedpath, PATH_MAX); units = utf8_to_utf16(__ctru_dev_utf16_buf, (const uint8_t*)__ctru_dev_path_buf, PATH_MAX);
if(units < 0) if(units < 0)
{ {
r->_errno = EILSEQ; r->_errno = EILSEQ;
return fspath; return fspath;
} }
if(units >= PATH_MAX) if(units > PATH_MAX)
{ {
r->_errno = ENAMETOOLONG; r->_errno = ENAMETOOLONG;
return fspath; return fspath;
} }
__utf16path[units] = 0; __ctru_dev_utf16_buf[units] = 0;
fspath.type = PATH_UTF16; fspath.type = PATH_UTF16;
fspath.size = (units+1)*sizeof(uint16_t); fspath.size = (units+1)*sizeof(uint16_t);
fspath.data = (const u8*)__utf16path; fspath.data = __ctru_dev_utf16_buf;
return fspath; return fspath;
} }
@ -379,15 +377,15 @@ Result archiveMountSdmc(void)
{ {
if(FindDevice(__system_argv[0]) == rc) if(FindDevice(__system_argv[0]) == rc)
{ {
strncpy(__fixedpath,__system_argv[0],PATH_MAX); strncpy(__ctru_dev_path_buf,__system_argv[0],PATH_MAX);
if(__fixedpath[PATH_MAX] != 0) if(__ctru_dev_path_buf[PATH_MAX] != 0)
{ {
__fixedpath[PATH_MAX] = 0; __ctru_dev_path_buf[PATH_MAX] = 0;
} }
else else
{ {
char *last_slash = NULL; char *last_slash = NULL;
p = __fixedpath; p = __ctru_dev_path_buf;
do do
{ {
units = decode_utf8(&code, (const uint8_t*)p); units = decode_utf8(&code, (const uint8_t*)p);
@ -406,7 +404,7 @@ Result archiveMountSdmc(void)
if(last_slash != NULL) if(last_slash != NULL)
{ {
last_slash[0] = 0; last_slash[0] = 0;
chdir(__fixedpath); chdir(__ctru_dev_path_buf);
} }
} }
} }
@ -927,7 +925,7 @@ archive_chdir(struct _reent *r,
if(R_SUCCEEDED(rc)) if(R_SUCCEEDED(rc))
{ {
FSDIR_Close(fd); FSDIR_Close(fd);
strncpy(device->cwd, __fixedpath, PATH_MAX + 1); strncpy(device->cwd, __ctru_dev_path_buf, PATH_MAX + 1);
device->cwd[PATH_MAX] = '\0'; device->cwd[PATH_MAX] = '\0';
return 0; return 0;
} }
@ -952,7 +950,6 @@ archive_rename(struct _reent *r,
{ {
Result rc; Result rc;
FS_Path fs_path_old, fs_path_new; FS_Path fs_path_old, fs_path_new;
static __thread uint16_t __utf16path_old[PATH_MAX+1];
archive_fsdevice *sourceDevice = r->deviceData; archive_fsdevice *sourceDevice = r->deviceData;
archive_fsdevice *destDevice = NULL; archive_fsdevice *destDevice = NULL;
@ -967,8 +964,9 @@ archive_rename(struct _reent *r,
if(fs_path_old.data == NULL) if(fs_path_old.data == NULL)
return -1; return -1;
memcpy(__utf16path_old, __utf16path, sizeof(__utf16path)); uint8_t old_path_copy[fs_path_old.size];
fs_path_old.data = (const u8*)__utf16path_old; memcpy(old_path_copy, fs_path_old.data, fs_path_old.size);
fs_path_old.data = old_path_copy;
fs_path_new = archive_utf16path(r, newName, &destDevice); fs_path_new = archive_utf16path(r, newName, &destDevice);
if(fs_path_new.data == NULL) if(fs_path_new.data == NULL)

View File

@ -0,0 +1,4 @@
#include "path_buf.h"
char __thread __ctru_dev_path_buf[PATH_MAX+1];
uint16_t __thread __ctru_dev_utf16_buf[PATH_MAX+1];

View File

@ -0,0 +1,6 @@
#pragma once
#include <stdint.h>
#include <limits.h>
extern char __thread __ctru_dev_path_buf[PATH_MAX+1];
extern uint16_t __thread __ctru_dev_utf16_buf[PATH_MAX+1];

View File

@ -16,6 +16,8 @@
#include <3ds/util/utf.h> #include <3ds/util/utf.h>
#include <3ds/env.h> #include <3ds/env.h>
#include "path_buf.h"
typedef struct romfs_mount typedef struct romfs_mount
{ {
Handle fd; Handle fd;
@ -31,9 +33,6 @@ typedef struct romfs_mount
extern int __system_argc; extern int __system_argc;
extern char** __system_argv; extern char** __system_argv;
static char __component[PATH_MAX+1];
static uint16_t __utf16path[PATH_MAX+1];
#define romFS_root(m) ((romfs_dir*)(m)->dirTable) #define romFS_root(m) ((romfs_dir*)(m)->dirTable)
#define romFS_dir(m,x) ((romfs_dir*) ((u8*)(m)->dirTable + (x))) #define romFS_dir(m,x) ((romfs_dir*) ((u8*)(m)->dirTable + (x)))
#define romFS_file(m,x) ((romfs_file*)((u8*)(m)->fileTable + (x))) #define romFS_file(m,x) ((romfs_file*)((u8*)(m)->fileTable + (x)))
@ -192,10 +191,10 @@ Result romfsMount(struct romfs_mount **p)
filename += 5; filename += 5;
else if (strncmp(filename, "3dslink:/", 9) == 0) else if (strncmp(filename, "3dslink:/", 9) == 0)
{ {
strncpy(__component, "/3ds", PATH_MAX); strncpy(__ctru_dev_path_buf, "/3ds", PATH_MAX);
strncat(__component, filename+8, PATH_MAX); strncat(__ctru_dev_path_buf, filename+8, PATH_MAX);
__component[PATH_MAX] = 0; __ctru_dev_path_buf[PATH_MAX] = 0;
filename = __component; filename = __ctru_dev_path_buf;
} }
else else
{ {
@ -203,21 +202,21 @@ Result romfsMount(struct romfs_mount **p)
return 2; return 2;
} }
ssize_t units = utf8_to_utf16(__utf16path, (const uint8_t*)filename, PATH_MAX); ssize_t units = utf8_to_utf16(__ctru_dev_utf16_buf, (const uint8_t*)filename, PATH_MAX);
if (units < 0) if (units < 0)
{ {
romfs_free(mount); romfs_free(mount);
return 3; return 3;
} }
if (units >= PATH_MAX) if (units > PATH_MAX)
{ {
romfs_free(mount); romfs_free(mount);
return 4; return 4;
} }
__utf16path[units] = 0; __ctru_dev_utf16_buf[units] = 0;
FS_Path archPath = { PATH_EMPTY, 1, "" }; FS_Path archPath = { PATH_EMPTY, 1, "" };
FS_Path filePath = { PATH_UTF16, (units+1)*2, __utf16path }; FS_Path filePath = { PATH_UTF16, (units+1)*2, __ctru_dev_utf16_buf };
Result rc = FSUSER_OpenFileDirectly(&mount->fd, ARCHIVE_SDMC, archPath, filePath, FS_OPEN_READ, 0); Result rc = FSUSER_OpenFileDirectly(&mount->fd, ARCHIVE_SDMC, archPath, filePath, FS_OPEN_READ, 0);
if (R_FAILED(rc)) if (R_FAILED(rc))
@ -456,7 +455,7 @@ static int navigateToDir(romfs_mount *mount, romfs_dir** ppDir, const char** pPa
while (**pPath) while (**pPath)
{ {
char* slashPos = strchr(*pPath, '/'); char* slashPos = strchr(*pPath, '/');
char* component = __component; char* component = __ctru_dev_path_buf;
if (slashPos) if (slashPos)
{ {
@ -486,13 +485,13 @@ static int navigateToDir(romfs_mount *mount, romfs_dir** ppDir, const char** pPa
} }
} }
units = utf8_to_utf16(__utf16path, (const uint8_t*)component, PATH_MAX); units = utf8_to_utf16(__ctru_dev_utf16_buf, (const uint8_t*)component, PATH_MAX);
if (units < 0) if (units < 0)
return EILSEQ; return EILSEQ;
if (units >= PATH_MAX) if (units > PATH_MAX)
return ENAMETOOLONG; return ENAMETOOLONG;
*ppDir = searchForDir(mount, *ppDir, __utf16path, units); *ppDir = searchForDir(mount, *ppDir, __ctru_dev_utf16_buf, units);
if (!*ppDir) if (!*ppDir)
return ENOENT; return ENOENT;
} }
@ -581,7 +580,7 @@ int romfs_open(struct _reent *r, void *fileStruct, const char *path, int flags,
if (r->_errno != 0) if (r->_errno != 0)
return -1; return -1;
ssize_t units = utf8_to_utf16(__utf16path, (const uint8_t*)path, PATH_MAX); ssize_t units = utf8_to_utf16(__ctru_dev_utf16_buf, (const uint8_t*)path, PATH_MAX);
if (units <= 0) if (units <= 0)
{ {
r->_errno = EILSEQ; r->_errno = EILSEQ;
@ -593,7 +592,7 @@ int romfs_open(struct _reent *r, void *fileStruct, const char *path, int flags,
return -1; return -1;
} }
romfs_file* file = searchForFile(fileobj->mount, curDir, __utf16path, units); romfs_file* file = searchForFile(fileobj->mount, curDir, __ctru_dev_utf16_buf, units);
if (!file) if (!file)
{ {
if(flags & O_CREAT) if(flags & O_CREAT)
@ -709,26 +708,26 @@ int romfs_stat(struct _reent *r, const char *path, struct stat *st)
return 0; return 0;
} }
ssize_t units = utf8_to_utf16(__utf16path, (const uint8_t*)path, PATH_MAX); ssize_t units = utf8_to_utf16(__ctru_dev_utf16_buf, (const uint8_t*)path, PATH_MAX);
if (units <= 0) if (units <= 0)
{ {
r->_errno = EILSEQ; r->_errno = EILSEQ;
return -1; return -1;
} }
if (units >= PATH_MAX) if (units > PATH_MAX)
{ {
r->_errno = ENAMETOOLONG; r->_errno = ENAMETOOLONG;
return -1; return -1;
} }
romfs_dir* dir = searchForDir(mount, curDir, __utf16path, units); romfs_dir* dir = searchForDir(mount, curDir, __ctru_dev_utf16_buf, units);
if(dir) if(dir)
{ {
fill_dir(st, mount, dir); fill_dir(st, mount, dir);
return 0; return 0;
} }
romfs_file* file = searchForFile(mount, curDir, __utf16path, units); romfs_file* file = searchForFile(mount, curDir, __ctru_dev_utf16_buf, units);
if(file) if(file)
{ {
fill_file(st, mount, file); fill_file(st, mount, file);
@ -821,9 +820,9 @@ int romfs_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename, struct s
/* convert name from UTF-16 to UTF-8 */ /* convert name from UTF-16 to UTF-8 */
memset(filename, 0, NAME_MAX); memset(filename, 0, NAME_MAX);
memcpy(__utf16path, dir->name, dir->nameLen*sizeof(uint16_t)); memcpy(__ctru_dev_utf16_buf, dir->name, dir->nameLen*sizeof(uint16_t));
__utf16path[dir->nameLen/sizeof(uint16_t)] = 0; __ctru_dev_utf16_buf[dir->nameLen/sizeof(uint16_t)] = 0;
units = utf16_to_utf8((uint8_t*)filename, __utf16path, NAME_MAX); units = utf16_to_utf8((uint8_t*)filename, __ctru_dev_utf16_buf, NAME_MAX);
if(units < 0) if(units < 0)
{ {
@ -852,9 +851,9 @@ int romfs_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename, struct s
/* convert name from UTF-16 to UTF-8 */ /* convert name from UTF-16 to UTF-8 */
memset(filename, 0, NAME_MAX); memset(filename, 0, NAME_MAX);
memcpy(__utf16path, file->name, file->nameLen*sizeof(uint16_t)); memcpy(__ctru_dev_utf16_buf, file->name, file->nameLen*sizeof(uint16_t));
__utf16path[file->nameLen/sizeof(uint16_t)] = 0; __ctru_dev_utf16_buf[file->nameLen/sizeof(uint16_t)] = 0;
units = utf16_to_utf8((uint8_t*)filename, __utf16path, NAME_MAX); units = utf16_to_utf8((uint8_t*)filename, __ctru_dev_utf16_buf, NAME_MAX);
if(units < 0) if(units < 0)
{ {