From 1c7914e2f4152da582544a7f0d27e1098c1e22da Mon Sep 17 00:00:00 2001 From: fincs Date: Thu, 2 Jul 2020 21:34:02 +0200 Subject: [PATCH] archive/romfs: Reduce TLS usage by sharing buffers + changed archive_rename to use a VLA --- libctru/source/archive_dev.c | 44 ++++++++++++++---------------- libctru/source/path_buf.c | 4 +++ libctru/source/path_buf.h | 6 ++++ libctru/source/romfs_dev.c | 53 ++++++++++++++++++------------------ 4 files changed, 57 insertions(+), 50 deletions(-) create mode 100644 libctru/source/path_buf.c create mode 100644 libctru/source/path_buf.h diff --git a/libctru/source/archive_dev.c b/libctru/source/archive_dev.c index a0edff9..a2b3a76 100644 --- a/libctru/source/archive_dev.c +++ b/libctru/source/archive_dev.c @@ -14,6 +14,7 @@ #include <3ds/services/fs.h> #include <3ds/util/utf.h> +#include "path_buf.h" /*! @internal * @@ -110,9 +111,6 @@ static archive_fsdevice archive_devices[32]; /*! @endcond */ -static __thread char __fixedpath[PATH_MAX+1]; -static __thread uint16_t __utf16path[PATH_MAX+1]; - static archive_fsdevice *archiveFindDevice(const char *name) { u32 i; @@ -204,17 +202,17 @@ archive_fixpath(struct _reent *r, } if(path[0] == '/') - strncpy(__fixedpath, path, PATH_MAX); + strncpy(__ctru_dev_path_buf, path, PATH_MAX); else { - strncpy(__fixedpath, dev->cwd, PATH_MAX); - __fixedpath[PATH_MAX] = '\0'; - strncat(__fixedpath, path, PATH_MAX); + strncpy(__ctru_dev_path_buf, dev->cwd, PATH_MAX); + __ctru_dev_path_buf[PATH_MAX] = '\0'; + 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; return NULL; } @@ -222,7 +220,7 @@ archive_fixpath(struct _reent *r, if(device) *device = dev; - return __fixedpath; + return __ctru_dev_path_buf; } static const FS_Path @@ -238,23 +236,23 @@ archive_utf16path(struct _reent *r, if(archive_fixpath(r, path, device) == NULL) 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) { r->_errno = EILSEQ; return fspath; } - if(units >= PATH_MAX) + if(units > PATH_MAX) { r->_errno = ENAMETOOLONG; return fspath; } - __utf16path[units] = 0; + __ctru_dev_utf16_buf[units] = 0; fspath.type = PATH_UTF16; fspath.size = (units+1)*sizeof(uint16_t); - fspath.data = (const u8*)__utf16path; + fspath.data = __ctru_dev_utf16_buf; return fspath; } @@ -379,15 +377,15 @@ Result archiveMountSdmc(void) { if(FindDevice(__system_argv[0]) == rc) { - strncpy(__fixedpath,__system_argv[0],PATH_MAX); - if(__fixedpath[PATH_MAX] != 0) + strncpy(__ctru_dev_path_buf,__system_argv[0],PATH_MAX); + if(__ctru_dev_path_buf[PATH_MAX] != 0) { - __fixedpath[PATH_MAX] = 0; + __ctru_dev_path_buf[PATH_MAX] = 0; } else { char *last_slash = NULL; - p = __fixedpath; + p = __ctru_dev_path_buf; do { units = decode_utf8(&code, (const uint8_t*)p); @@ -406,7 +404,7 @@ Result archiveMountSdmc(void) if(last_slash != NULL) { last_slash[0] = 0; - chdir(__fixedpath); + chdir(__ctru_dev_path_buf); } } } @@ -927,7 +925,7 @@ archive_chdir(struct _reent *r, if(R_SUCCEEDED(rc)) { 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'; return 0; } @@ -952,7 +950,6 @@ archive_rename(struct _reent *r, { Result rc; FS_Path fs_path_old, fs_path_new; - static __thread uint16_t __utf16path_old[PATH_MAX+1]; archive_fsdevice *sourceDevice = r->deviceData; archive_fsdevice *destDevice = NULL; @@ -967,8 +964,9 @@ archive_rename(struct _reent *r, if(fs_path_old.data == NULL) return -1; - memcpy(__utf16path_old, __utf16path, sizeof(__utf16path)); - fs_path_old.data = (const u8*)__utf16path_old; + uint8_t old_path_copy[fs_path_old.size]; + 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); if(fs_path_new.data == NULL) diff --git a/libctru/source/path_buf.c b/libctru/source/path_buf.c new file mode 100644 index 0000000..c87fbb3 --- /dev/null +++ b/libctru/source/path_buf.c @@ -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]; diff --git a/libctru/source/path_buf.h b/libctru/source/path_buf.h new file mode 100644 index 0000000..50de7b7 --- /dev/null +++ b/libctru/source/path_buf.h @@ -0,0 +1,6 @@ +#pragma once +#include +#include + +extern char __thread __ctru_dev_path_buf[PATH_MAX+1]; +extern uint16_t __thread __ctru_dev_utf16_buf[PATH_MAX+1]; diff --git a/libctru/source/romfs_dev.c b/libctru/source/romfs_dev.c index c280f48..0ae5a63 100644 --- a/libctru/source/romfs_dev.c +++ b/libctru/source/romfs_dev.c @@ -16,6 +16,8 @@ #include <3ds/util/utf.h> #include <3ds/env.h> +#include "path_buf.h" + typedef struct romfs_mount { Handle fd; @@ -31,9 +33,6 @@ typedef struct romfs_mount extern int __system_argc; 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_dir(m,x) ((romfs_dir*) ((u8*)(m)->dirTable + (x))) #define romFS_file(m,x) ((romfs_file*)((u8*)(m)->fileTable + (x))) @@ -192,10 +191,10 @@ Result romfsMount(struct romfs_mount **p) filename += 5; else if (strncmp(filename, "3dslink:/", 9) == 0) { - strncpy(__component, "/3ds", PATH_MAX); - strncat(__component, filename+8, PATH_MAX); - __component[PATH_MAX] = 0; - filename = __component; + strncpy(__ctru_dev_path_buf, "/3ds", PATH_MAX); + strncat(__ctru_dev_path_buf, filename+8, PATH_MAX); + __ctru_dev_path_buf[PATH_MAX] = 0; + filename = __ctru_dev_path_buf; } else { @@ -203,21 +202,21 @@ Result romfsMount(struct romfs_mount **p) 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) { romfs_free(mount); return 3; } - if (units >= PATH_MAX) + if (units > PATH_MAX) { romfs_free(mount); return 4; } - __utf16path[units] = 0; + __ctru_dev_utf16_buf[units] = 0; 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); if (R_FAILED(rc)) @@ -456,7 +455,7 @@ static int navigateToDir(romfs_mount *mount, romfs_dir** ppDir, const char** pPa while (**pPath) { char* slashPos = strchr(*pPath, '/'); - char* component = __component; + char* component = __ctru_dev_path_buf; 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) return EILSEQ; - if (units >= PATH_MAX) + if (units > PATH_MAX) return ENAMETOOLONG; - *ppDir = searchForDir(mount, *ppDir, __utf16path, units); + *ppDir = searchForDir(mount, *ppDir, __ctru_dev_utf16_buf, units); if (!*ppDir) return ENOENT; } @@ -581,7 +580,7 @@ int romfs_open(struct _reent *r, void *fileStruct, const char *path, int flags, if (r->_errno != 0) 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) { r->_errno = EILSEQ; @@ -593,7 +592,7 @@ int romfs_open(struct _reent *r, void *fileStruct, const char *path, int flags, 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(flags & O_CREAT) @@ -709,26 +708,26 @@ int romfs_stat(struct _reent *r, const char *path, struct stat *st) 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) { r->_errno = EILSEQ; return -1; } - if (units >= PATH_MAX) + if (units > PATH_MAX) { r->_errno = ENAMETOOLONG; return -1; } - romfs_dir* dir = searchForDir(mount, curDir, __utf16path, units); + romfs_dir* dir = searchForDir(mount, curDir, __ctru_dev_utf16_buf, units); if(dir) { fill_dir(st, mount, dir); return 0; } - romfs_file* file = searchForFile(mount, curDir, __utf16path, units); + romfs_file* file = searchForFile(mount, curDir, __ctru_dev_utf16_buf, units); if(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 */ memset(filename, 0, NAME_MAX); - memcpy(__utf16path, dir->name, dir->nameLen*sizeof(uint16_t)); - __utf16path[dir->nameLen/sizeof(uint16_t)] = 0; - units = utf16_to_utf8((uint8_t*)filename, __utf16path, NAME_MAX); + memcpy(__ctru_dev_utf16_buf, dir->name, dir->nameLen*sizeof(uint16_t)); + __ctru_dev_utf16_buf[dir->nameLen/sizeof(uint16_t)] = 0; + units = utf16_to_utf8((uint8_t*)filename, __ctru_dev_utf16_buf, NAME_MAX); 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 */ memset(filename, 0, NAME_MAX); - memcpy(__utf16path, file->name, file->nameLen*sizeof(uint16_t)); - __utf16path[file->nameLen/sizeof(uint16_t)] = 0; - units = utf16_to_utf8((uint8_t*)filename, __utf16path, NAME_MAX); + memcpy(__ctru_dev_utf16_buf, file->name, file->nameLen*sizeof(uint16_t)); + __ctru_dev_utf16_buf[file->nameLen/sizeof(uint16_t)] = 0; + units = utf16_to_utf8((uint8_t*)filename, __ctru_dev_utf16_buf, NAME_MAX); if(units < 0) {