This commit is contained in:
Maschell 2025-02-07 15:53:14 +01:00
parent 17591be18b
commit 0a6cca3402
11 changed files with 117 additions and 97 deletions

View File

@ -3,12 +3,15 @@
#include "utils/StringTools.h" #include "utils/StringTools.h"
#include "utils/logger.h" #include "utils/logger.h"
#include "utils/utils.h" #include "utils/utils.h"
#include <algorithm>
#include <coreinit/cache.h> #include <coreinit/cache.h>
#include <coreinit/debug.h> #include <coreinit/debug.h>
#include <coreinit/filesystem_fsa.h>
#include <cstdio> #include <algorithm>
#include <filesystem> #include <filesystem>
#include <cstdio>
#include <sys/dirent.h> #include <sys/dirent.h>
#include <sys/fcntl.h> #include <sys/fcntl.h>
#include <sys/unistd.h> #include <sys/unistd.h>
@ -68,7 +71,7 @@ FSError FSWrapper::FSOpenDirWrapper(const char *path, FSDirectoryHandle *handle)
return result; return result;
} }
FSError FSWrapper::FSReadDirWrapper(FSDirectoryHandle handle, FSDirectoryEntry *entry) { FSError FSWrapper::FSReadDirWrapper(const FSDirectoryHandle handle, FSDirectoryEntry *entry) {
if (!isValidDirHandle(handle)) { if (!isValidDirHandle(handle)) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
@ -139,7 +142,7 @@ FSError FSWrapper::FSReadDirWrapper(FSDirectoryHandle handle, FSDirectoryEntry *
return result; return result;
} }
FSError FSWrapper::FSCloseDirWrapper(FSDirectoryHandle handle) { FSError FSWrapper::FSCloseDirWrapper(const FSDirectoryHandle handle) {
if (!isValidDirHandle(handle)) { if (!isValidDirHandle(handle)) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
@ -158,7 +161,7 @@ FSError FSWrapper::FSCloseDirWrapper(FSDirectoryHandle handle) {
return result; return result;
} }
FSError FSWrapper::FSRewindDirWrapper(FSDirectoryHandle handle) { FSError FSWrapper::FSRewindDirWrapper(const FSDirectoryHandle handle) {
if (!isValidDirHandle(handle)) { if (!isValidDirHandle(handle)) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
@ -295,7 +298,7 @@ FSError FSWrapper::FSOpenFileWrapper(const char *path, const char *mode, FSFileH
return result; return result;
} }
FSError FSWrapper::FSCloseFileWrapper(FSFileHandle handle) { FSError FSWrapper::FSCloseFileWrapper(const FSFileHandle handle) {
if (!isValidFileHandle(handle)) { if (!isValidFileHandle(handle)) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
@ -360,7 +363,7 @@ FSError FSWrapper::FSGetStatWrapper(const char *path, FSStat *stats) {
return result; return result;
} }
FSError FSWrapper::FSGetStatFileWrapper(FSFileHandle handle, FSStat *stats) { FSError FSWrapper::FSGetStatFileWrapper(const FSFileHandle handle, FSStat *stats) {
if (!isValidFileHandle(handle)) { if (!isValidFileHandle(handle)) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
@ -382,7 +385,7 @@ FSError FSWrapper::FSGetStatFileWrapper(FSFileHandle handle, FSStat *stats) {
return result; return result;
} }
FSError FSWrapper::FSReadFileWrapper(void *buffer, uint32_t size, uint32_t count, FSFileHandle handle, [[maybe_unused]] uint32_t unk1) { FSError FSWrapper::FSReadFileWrapper(void *buffer, const uint32_t size, const uint32_t count, const FSFileHandle handle, [[maybe_unused]] uint32_t unk1) {
if (!isValidFileHandle(handle)) { if (!isValidFileHandle(handle)) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
@ -417,7 +420,7 @@ FSError FSWrapper::FSReadFileWrapper(void *buffer, uint32_t size, uint32_t count
return result; return result;
} }
FSError FSWrapper::FSReadFileWithPosWrapper(void *buffer, uint32_t size, uint32_t count, uint32_t pos, FSFileHandle handle, int32_t unk1) { FSError FSWrapper::FSReadFileWithPosWrapper(void *buffer, const uint32_t size, const uint32_t count, const uint32_t pos, const FSFileHandle handle, const int32_t unk1) {
if (!isValidFileHandle(handle)) { if (!isValidFileHandle(handle)) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
@ -432,7 +435,7 @@ FSError FSWrapper::FSReadFileWithPosWrapper(void *buffer, uint32_t size, uint32_
return result; return result;
} }
FSError FSWrapper::FSSetPosFileWrapper(FSFileHandle handle, uint32_t pos) { FSError FSWrapper::FSSetPosFileWrapper(const FSFileHandle handle, const uint32_t pos) {
if (!isValidFileHandle(handle)) { if (!isValidFileHandle(handle)) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
@ -457,7 +460,7 @@ FSError FSWrapper::FSSetPosFileWrapper(FSFileHandle handle, uint32_t pos) {
return result; return result;
} }
FSError FSWrapper::FSGetPosFileWrapper(FSFileHandle handle, uint32_t *pos) { FSError FSWrapper::FSGetPosFileWrapper(const FSFileHandle handle, uint32_t *pos) {
if (!isValidFileHandle(handle)) { if (!isValidFileHandle(handle)) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
@ -478,7 +481,7 @@ FSError FSWrapper::FSGetPosFileWrapper(FSFileHandle handle, uint32_t *pos) {
return result; return result;
} }
FSError FSWrapper::FSIsEofWrapper(FSFileHandle handle) { FSError FSWrapper::FSIsEofWrapper(const FSFileHandle handle) {
if (!isValidFileHandle(handle)) { if (!isValidFileHandle(handle)) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
@ -509,7 +512,7 @@ FSError FSWrapper::FSIsEofWrapper(FSFileHandle handle) {
return result; return result;
} }
FSError FSWrapper::FSTruncateFileWrapper(FSFileHandle handle) { FSError FSWrapper::FSTruncateFileWrapper(const FSFileHandle handle) {
if (!isValidFileHandle(handle)) { if (!isValidFileHandle(handle)) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
@ -542,7 +545,7 @@ FSError FSWrapper::FSTruncateFileWrapper(FSFileHandle handle) {
return result; return result;
} }
FSError FSWrapper::FSWriteFileWrapper(const uint8_t *buffer, uint32_t size, uint32_t count, FSFileHandle handle, [[maybe_unused]] uint32_t unk1) { FSError FSWrapper::FSWriteFileWrapper(const uint8_t *buffer, const uint32_t size, const uint32_t count, const FSFileHandle handle, [[maybe_unused]] uint32_t unk1) {
if (!isValidFileHandle(handle)) { if (!isValidFileHandle(handle)) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
@ -569,7 +572,7 @@ FSError FSWrapper::FSWriteFileWrapper(const uint8_t *buffer, uint32_t size, uint
result = FS_ERROR_MEDIA_ERROR; result = FS_ERROR_MEDIA_ERROR;
} }
} else { } else {
result = static_cast<FSError>(((uint32_t) writeRes) / size); result = static_cast<FSError>(static_cast<uint32_t>(writeRes) / size);
} }
return result; return result;
@ -630,7 +633,7 @@ FSError FSWrapper::FSRenameWrapper(const char *oldPath, const char *newPath) {
return FS_ERROR_OK; return FS_ERROR_OK;
} }
FSError FSWrapper::FSFlushFileWrapper(FSFileHandle handle) { FSError FSWrapper::FSFlushFileWrapper(const FSFileHandle handle) {
if (!isValidFileHandle(handle)) { if (!isValidFileHandle(handle)) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
@ -639,8 +642,8 @@ FSError FSWrapper::FSFlushFileWrapper(FSFileHandle handle) {
return FS_ERROR_ACCESS_ERROR; return FS_ERROR_ACCESS_ERROR;
} }
auto fileHandle = getFileFromHandle(handle); const auto fileHandle = getFileFromHandle(handle);
int real_fd = fileHandle->fd; const int real_fd = fileHandle->fd;
DEBUG_FUNCTION_LINE_VERBOSE("[%s] fsync fd %08X (FSFileHandle %08X)", real_fd, handle); DEBUG_FUNCTION_LINE_VERBOSE("[%s] fsync fd %08X (FSFileHandle %08X)", real_fd, handle);
FSError result = FS_ERROR_OK; FSError result = FS_ERROR_OK;
@ -682,7 +685,7 @@ std::string FSWrapper::GetNewPath(const std::string_view &path) {
auto subStr = path.substr(this->pPathToReplace.length()); auto subStr = path.substr(this->pPathToReplace.length());
auto res = string_format("%s%.*s", this->pReplacePathWith.c_str(), int(subStr.length()), subStr.data()); auto res = string_format("%s%.*s", this->pReplacePathWith.c_str(), int(subStr.length()), subStr.data());
std::replace(res.begin(), res.end(), '\\', '/'); std::ranges::replace(res, '\\', '/');
uint32_t length = res.size(); uint32_t length = res.size();
@ -700,15 +703,16 @@ std::string FSWrapper::GetNewPath(const std::string_view &path) {
} }
bool FSWrapper::isValidFileHandle(FSFileHandle handle) { bool FSWrapper::isValidFileHandle(FSFileHandle handle) {
std::lock_guard<std::mutex> lock(openFilesMutex); std::lock_guard lock(openFilesMutex);
return std::ranges::any_of(openFiles, [handle](auto &cur) { return cur->handle == handle; }); return std::ranges::any_of(openFiles, [handle](auto &cur) { return cur->handle == handle; });
} }
bool FSWrapper::isValidDirHandle(FSDirectoryHandle handle) { bool FSWrapper::isValidDirHandle(FSDirectoryHandle handle) {
std::lock_guard<std::mutex> lock(openDirsMutex); std::lock_guard lock(openDirsMutex);
return std::ranges::any_of(openDirs, [handle](auto &cur) { return cur->handle == handle; }); return std::ranges::any_of(openDirs, [handle](auto &cur) { return cur->handle == handle; });
} }
std::shared_ptr<FileInfo> FSWrapper::getNewFileHandle() { std::shared_ptr<FileInfo> FSWrapper::getNewFileHandle() {
return make_shared_nothrow<FileInfo>(); return make_shared_nothrow<FileInfo>();
} }
@ -717,8 +721,8 @@ std::shared_ptr<DirInfo> FSWrapper::getNewDirHandle() {
return make_shared_nothrow<DirInfo>(); return make_shared_nothrow<DirInfo>();
} }
std::shared_ptr<FileInfo> FSWrapper::getFileFromHandle(FSFileHandle handle) { std::shared_ptr<FileInfo> FSWrapper::getFileFromHandle(const FSFileHandle handle) {
std::lock_guard<std::mutex> lock(openFilesMutex); std::lock_guard lock(openFilesMutex);
for (auto &file : openFiles) { for (auto &file : openFiles) {
if (file->handle == handle) { if (file->handle == handle) {
return file; return file;
@ -729,8 +733,8 @@ std::shared_ptr<FileInfo> FSWrapper::getFileFromHandle(FSFileHandle handle) {
return nullptr; return nullptr;
} }
std::shared_ptr<DirInfo> FSWrapper::getDirFromHandle(FSDirectoryHandle handle) { std::shared_ptr<DirInfoBase> FSWrapper::getDirFromHandle(const FSDirectoryHandle handle) {
std::lock_guard<std::mutex> lock(openDirsMutex); std::lock_guard lock(openDirsMutex);
for (auto &dir : openDirs) { for (auto &dir : openDirs) {
if (dir->handle == handle) { if (dir->handle == handle) {
return dir; return dir;
@ -742,13 +746,13 @@ std::shared_ptr<DirInfo> FSWrapper::getDirFromHandle(FSDirectoryHandle handle) {
} }
void FSWrapper::deleteDirHandle(FSDirectoryHandle handle) { void FSWrapper::deleteDirHandle(FSDirectoryHandle handle) {
if (!remove_locked_first_if(openDirsMutex, openDirs, [handle](auto &cur) { return (FSFileHandle) cur->handle == handle; })) { if (!remove_locked_first_if(openDirsMutex, openDirs, [handle](auto &cur) { return static_cast<FSDirectoryHandle>(cur->handle) == handle; })) {
DEBUG_FUNCTION_LINE_ERR("[%s] Delete failed because the handle %08X was not found", getName().c_str(), handle); DEBUG_FUNCTION_LINE_ERR("[%s] Delete failed because the handle %08X was not found", getName().c_str(), handle);
} }
} }
void FSWrapper::deleteFileHandle(FSFileHandle handle) { void FSWrapper::deleteFileHandle(FSFileHandle handle) {
if (!remove_locked_first_if(openFilesMutex, openFiles, [handle](auto &cur) { return (FSFileHandle) cur->handle == handle; })) { if (!remove_locked_first_if(openFilesMutex, openFiles, [handle](auto &cur) { return static_cast<FSFileHandle>(cur->handle) == handle; })) {
DEBUG_FUNCTION_LINE_ERR("[%s] Delete failed because the handle %08X was not found", getName().c_str(), handle); DEBUG_FUNCTION_LINE_ERR("[%s] Delete failed because the handle %08X was not found", getName().c_str(), handle);
} }
} }

View File

@ -1,16 +1,19 @@
#pragma once #pragma once
#include "DirInfo.h" #include "DirInfo.h"
#include "FileInfo.h" #include "FileInfo.h"
#include "IFSWrapper.h" #include "IFSWrapper.h"
#include "utils/logger.h" #include "utils/logger.h"
#include <coreinit/filesystem.h> #include <coreinit/filesystem.h>
#include <coreinit/mutex.h>
#include <algorithm>
#include <functional> #include <functional>
#include <mutex> #include <mutex>
class FSWrapper : public IFSWrapper { class FSWrapper : public IFSWrapper {
public: public:
FSWrapper(const std::string &name, const std::string &pathToReplace, const std::string &replacePathWith, bool fallbackOnError, bool isWriteable) { FSWrapper(const std::string &name, const std::string &pathToReplace, const std::string &replacePathWith, const bool fallbackOnError, const bool isWriteable) {
this->pName = name; this->pName = name;
this->pPathToReplace = pathToReplace; this->pPathToReplace = pathToReplace;
this->pReplacePathWith = replacePathWith; this->pReplacePathWith = replacePathWith;
@ -18,16 +21,16 @@ public:
this->pIsWriteable = isWriteable; this->pIsWriteable = isWriteable;
this->pCheckIfDeleted = fallbackOnError; this->pCheckIfDeleted = fallbackOnError;
std::replace(pPathToReplace.begin(), pPathToReplace.end(), '\\', '/'); std::ranges::replace(pPathToReplace, '\\', '/');
std::replace(pReplacePathWith.begin(), pReplacePathWith.end(), '\\', '/'); std::ranges::replace(pReplacePathWith, '\\', '/');
} }
~FSWrapper() override { ~FSWrapper() override {
{ {
std::lock_guard<std::mutex> lockFiles(openFilesMutex); std::lock_guard lockFiles(openFilesMutex);
openFiles.clear(); openFiles.clear();
} }
{ {
std::lock_guard<std::mutex> lockDirs(openDirsMutex); std::lock_guard lockDirs(openDirsMutex);
openDirs.clear(); openDirs.clear();
} }
} }
@ -35,7 +38,6 @@ public:
FSError FSOpenDirWrapper(const char *path, FSError FSOpenDirWrapper(const char *path,
FSDirectoryHandle *handle) override; FSDirectoryHandle *handle) override;
FSError FSReadDirWrapper(FSDirectoryHandle handle, FSError FSReadDirWrapper(FSDirectoryHandle handle,
FSDirectoryEntry *entry) override; FSDirectoryEntry *entry) override;
@ -96,7 +98,7 @@ public:
FSError FSFlushFileWrapper(FSFileHandle handle) override; FSError FSFlushFileWrapper(FSFileHandle handle) override;
uint32_t getLayerId() override { uint32_t getLayerId() override {
return (uint32_t) this; return getHandle();
} }
protected: protected:

View File

@ -2,9 +2,11 @@
#include "utils/StringTools.h" #include "utils/StringTools.h"
#include "utils/logger.h" #include "utils/logger.h"
#include "utils/utils.h" #include "utils/utils.h"
#include <coreinit/cache.h> #include <coreinit/cache.h>
#include <coreinit/debug.h> #include <coreinit/debug.h>
#include <coreinit/filesystem.h> #include <coreinit/filesystem.h>
#include <filesystem> #include <filesystem>
FSError FSWrapperMergeDirsWithParent::FSOpenDirWrapper(const char *path, FSError FSWrapperMergeDirsWithParent::FSOpenDirWrapper(const char *path,
@ -27,11 +29,11 @@ FSError FSWrapperMergeDirsWithParent::FSOpenDirWrapper(const char *path,
dirHandle->readResultNumberOfEntries = 0; dirHandle->readResultNumberOfEntries = 0;
dirHandle->realDirHandle = 0; dirHandle->realDirHandle = 0;
if (clientHandle) { if (mClientHandle) {
FSADirectoryHandle realHandle = 0; FSADirectoryHandle realHandle = 0;
DEBUG_FUNCTION_LINE_VERBOSE("[%s] Call FSAOpenDir with %s for parent layer", getName().c_str(), path); DEBUG_FUNCTION_LINE_VERBOSE("[%s] Call FSAOpenDir with %s for parent layer", getName().c_str(), path);
FSError err; FSError err;
if ((err = FSAOpenDir(clientHandle, path, &realHandle)) == FS_ERROR_OK) { if ((err = FSAOpenDir(mClientHandle, path, &realHandle)) == FS_ERROR_OK) {
dirHandle->realDirHandle = realHandle; dirHandle->realDirHandle = realHandle;
} else { } else {
DEBUG_FUNCTION_LINE_ERR("[%s] Failed to open real dir %s. %s (%d)", getName().c_str(), path, FSAGetStatusStr(err), err); DEBUG_FUNCTION_LINE_ERR("[%s] Failed to open real dir %s. %s (%d)", getName().c_str(), path, FSAGetStatusStr(err), err);
@ -58,6 +60,10 @@ FSError FSWrapperMergeDirsWithParent::FSReadDirWrapper(FSADirectoryHandle handle
return FS_ERROR_INVALID_DIRHANDLE; return FS_ERROR_INVALID_DIRHANDLE;
} }
auto dirHandle = getDirExFromHandle(handle); auto dirHandle = getDirExFromHandle(handle);
if (!dirHandle) {
DEBUG_FUNCTION_LINE_ERR("[%s] No valid dir handle %08X", getName().c_str(), handle);
return FS_ERROR_INVALID_DIRHANDLE;
}
if (res == FS_ERROR_OK) { if (res == FS_ERROR_OK) {
if (dirHandle->readResultCapacity == 0) { if (dirHandle->readResultCapacity == 0) {
dirHandle->readResult = (FSDirectoryEntryEx *) malloc(sizeof(FSDirectoryEntryEx)); dirHandle->readResult = (FSDirectoryEntryEx *) malloc(sizeof(FSDirectoryEntryEx));
@ -92,16 +98,15 @@ FSError FSWrapperMergeDirsWithParent::FSReadDirWrapper(FSADirectoryHandle handle
} }
OSMemoryBarrier(); OSMemoryBarrier();
} else if (res == FS_ERROR_END_OF_DIR) { } else if (res == FS_ERROR_END_OF_DIR) {
// Read the real directory. // Read the real directory.
if (dirHandle->realDirHandle != 0) { if (dirHandle->realDirHandle != 0) {
if (clientHandle) { if (mClientHandle) {
FSADirectoryEntry realDirEntry; FSADirectoryEntry realDirEntry;
FSError readDirResult; FSError readDirResult;
while (true) { while (true) {
DEBUG_FUNCTION_LINE_VERBOSE("[%s] Call FSReadDir with %08X for parent layer", getName().c_str(), dirHandle->realDirHandle); DEBUG_FUNCTION_LINE_VERBOSE("[%s] Call FSReadDir with %08X for parent layer", getName().c_str(), dirHandle->realDirHandle);
readDirResult = FSAReadDir(clientHandle, dirHandle->realDirHandle, &realDirEntry); readDirResult = FSAReadDir(mClientHandle, dirHandle->realDirHandle, &realDirEntry);
if (readDirResult == FS_ERROR_OK) { if (readDirResult == FS_ERROR_OK) {
bool found = false; bool found = false;
auto nameDeleted = deletePrefix + realDirEntry.name; auto nameDeleted = deletePrefix + realDirEntry.name;
@ -156,9 +161,9 @@ FSError FSWrapperMergeDirsWithParent::FSCloseDirWrapper(FSADirectoryHandle handl
} }
auto dirHandle = getDirExFromHandle(handle); auto dirHandle = getDirExFromHandle(handle);
if (dirHandle->realDirHandle != 0) { if (dirHandle->realDirHandle != 0) {
if (clientHandle) { if (mClientHandle) {
DEBUG_FUNCTION_LINE_VERBOSE("[%s] Call FSCloseDir with %08X for parent layer", getName().c_str(), dirHandle->realDirHandle); DEBUG_FUNCTION_LINE_VERBOSE("[%s] Call FSCloseDir with %08X for parent layer", getName().c_str(), dirHandle->realDirHandle);
auto realResult = FSACloseDir(clientHandle, dirHandle->realDirHandle); auto realResult = FSACloseDir(mClientHandle, dirHandle->realDirHandle);
if (realResult == FS_ERROR_OK) { if (realResult == FS_ERROR_OK) {
dirHandle->realDirHandle = 0; dirHandle->realDirHandle = 0;
} else { } else {
@ -201,10 +206,10 @@ FSError FSWrapperMergeDirsWithParent::FSRewindDirWrapper(FSADirectoryHandle hand
} }
if (dirHandle->realDirHandle != 0) { if (dirHandle->realDirHandle != 0) {
if (clientHandle) { if (mClientHandle) {
DEBUG_FUNCTION_LINE_VERBOSE("[%s] Call FSARewindDir with %08X for parent layer", getName().c_str(), dirHandle->realDirHandle); DEBUG_FUNCTION_LINE_VERBOSE("[%s] Call FSARewindDir with %08X for parent layer", getName().c_str(), dirHandle->realDirHandle);
FSError err; FSError err;
if ((err = FSARewindDir(clientHandle, dirHandle->realDirHandle)) == FS_ERROR_OK) { if ((err = FSARewindDir(mClientHandle, dirHandle->realDirHandle)) == FS_ERROR_OK) {
dirHandle->realDirHandle = 0; dirHandle->realDirHandle = 0;
} else { } else {
DEBUG_FUNCTION_LINE_ERR("[%s] Failed to rewind dir for realDirHandle %08X. %s (%d)", getName().c_str(), dirHandle->realDirHandle, FSAGetStatusStr(err), err); DEBUG_FUNCTION_LINE_ERR("[%s] Failed to rewind dir for realDirHandle %08X. %s (%d)", getName().c_str(), dirHandle->realDirHandle, FSAGetStatusStr(err), err);
@ -229,20 +234,20 @@ FSWrapperMergeDirsWithParent::FSWrapperMergeDirsWithParent(const std::string &na
fallbackOnError, fallbackOnError,
false) { false) {
FSAInit(); FSAInit();
this->clientHandle = FSAAddClient(nullptr); this->mClientHandle = FSAAddClient(nullptr);
if (clientHandle < 0) { if (mClientHandle < 0) {
DEBUG_FUNCTION_LINE_ERR("[%s] FSAClientHandle failed: %s (%d)", name.c_str(), FSAGetStatusStr(static_cast<FSError>(clientHandle)), clientHandle); DEBUG_FUNCTION_LINE_ERR("[%s] FSAClientHandle failed: %s (%d)", name.c_str(), FSAGetStatusStr(static_cast<FSError>(mClientHandle)), mClientHandle);
clientHandle = 0; mClientHandle = 0;
} }
} }
FSWrapperMergeDirsWithParent::~FSWrapperMergeDirsWithParent() { FSWrapperMergeDirsWithParent::~FSWrapperMergeDirsWithParent() {
if (clientHandle) { if (mClientHandle) {
FSError res; FSError res;
if ((res = FSADelClient(clientHandle)) != FS_ERROR_OK) { if ((res = FSADelClient(mClientHandle)) != FS_ERROR_OK) {
DEBUG_FUNCTION_LINE_ERR("[%s] FSADelClient failed: %s (%d)", FSAGetStatusStr(res), res); DEBUG_FUNCTION_LINE_ERR("[%s] FSADelClient failed: %s (%d)", FSAGetStatusStr(res), res);
} }
clientHandle = 0; mClientHandle = 0;
} }
} }

View File

@ -1,10 +1,10 @@
#pragma once #pragma once
#include "DirInfoEx.h" #include "DirInfoEx.h"
#include "FSWrapper.h" #include "FSWrapper.h"
#include <coreinit/filesystem.h>
#include <functional>
class FSWrapperMergeDirsWithParent : public FSWrapper { #include <coreinit/filesystem.h>
class FSWrapperMergeDirsWithParent final : public FSWrapper {
public: public:
FSWrapperMergeDirsWithParent(const std::string &name, FSWrapperMergeDirsWithParent(const std::string &name,
const std::string &pathToReplace, const std::string &pathToReplace,
@ -28,11 +28,11 @@ public:
bool SkipDeletedFilesInReadDir() override; bool SkipDeletedFilesInReadDir() override;
uint32_t getLayerId() override { uint32_t getLayerId() override {
return (uint32_t) clientHandle; return static_cast<uint32_t>(mClientHandle);
} }
private: private:
FSAClientHandle clientHandle; FSAClientHandle mClientHandle;
std::shared_ptr<DirInfoEx> getDirExFromHandle(FSDirectoryHandle handle); std::shared_ptr<DirInfoEx> getDirExFromHandle(FSDirectoryHandle handle);
}; };

View File

@ -11,39 +11,41 @@
#include <map> #include <map>
#include <unistd.h> #include <unistd.h>
std::mutex workingDirMutex; namespace {
std::map<FSAClientHandle, std::string> workingDirs; std::mutex sWorkingDirMutex;
std::map<FSAClientHandle, std::string> sWorkingDirs;
} // namespace
std::mutex fsLayerMutex; std::mutex gFSLayerMutex;
std::vector<std::unique_ptr<IFSWrapper>> fsLayers; std::vector<std::unique_ptr<IFSWrapper>> gFSLayers;
std::string getFullPathGeneric(FSAClientHandle client, const char *path, std::mutex &mutex, std::map<FSAClientHandle, std::string> &map) { std::string getFullPathGeneric(const FSAClientHandle client, const char *path, std::mutex &mutex, const std::map<FSAClientHandle, std::string> &map) {
std::lock_guard<std::mutex> workingDirLock(mutex); std::lock_guard workingDirLock(mutex);
std::string res; std::string res;
if (path[0] != '/' && path[0] != '\\') { if (path[0] != '/' && path[0] != '\\') {
if (map.count(client) == 0) { if (map.count(client) == 0) {
DEBUG_FUNCTION_LINE_WARN("No working dir found for client %08X, fallback to \"/\"", client); DEBUG_FUNCTION_LINE_WARN("No working dir found for client %08X, fallback to \"/\"", client);
workingDirs[client] = "/"; sWorkingDirs[client] = "/";
} }
res = string_format("%s%s", map.at(client).c_str(), path); res = string_format("%s%s", map.at(client).c_str(), path);
} else { } else {
res = path; res = path;
} }
std::replace(res.begin(), res.end(), '\\', '/'); std::ranges::replace(res, '\\', '/');
return res; return res;
} }
void setWorkingDirGeneric(FSAClientHandle client, const char *path, std::mutex &mutex, std::map<FSAClientHandle, std::string> &map) { void setWorkingDirGeneric(const FSAClientHandle client, const char *path, std::mutex &mutex, std::map<FSAClientHandle, std::string> &map) {
if (!path) { if (!path) {
DEBUG_FUNCTION_LINE_WARN("Path was NULL"); DEBUG_FUNCTION_LINE_WARN("Path was NULL");
return; return;
} }
std::lock_guard<std::mutex> workingDirLock(mutex); std::lock_guard workingDirLock(mutex);
std::string cwd(path); std::string cwd(path);
if (cwd.empty() || cwd.back() != '/') { if (cwd.empty() || cwd.back() != '/') {
@ -54,22 +56,22 @@ void setWorkingDirGeneric(FSAClientHandle client, const char *path, std::mutex &
} }
std::string getFullPath(FSAClientHandle pClient, const char *path) { std::string getFullPath(const FSAClientHandle pClient, const char *path) {
return getFullPathGeneric(pClient, path, workingDirMutex, workingDirs); return getFullPathGeneric(pClient, path, sWorkingDirMutex, sWorkingDirs);
} }
void setWorkingDir(FSAClientHandle client, const char *path) { void setWorkingDir(const FSAClientHandle client, const char *path) {
setWorkingDirGeneric(client, path, workingDirMutex, workingDirs); setWorkingDirGeneric(client, path, sWorkingDirMutex, sWorkingDirs);
} }
void clearFSLayer() { void clearFSLayer() {
{ {
std::lock_guard<std::mutex> workingDirLock(workingDirMutex); std::lock_guard workingDirLock(sWorkingDirMutex);
workingDirs.clear(); sWorkingDirs.clear();
} }
{ {
std::lock_guard<std::mutex> layerLock(fsLayerMutex); std::lock_guard layerLock(gFSLayerMutex);
fsLayers.clear(); gFSLayers.clear();
} }
} }
@ -93,11 +95,11 @@ bool sendMessageToThread(FSShimWrapperMessage *param) {
} }
FSError doForLayer(FSShimWrapper *param) { FSError doForLayer(FSShimWrapper *param) {
std::lock_guard<std::mutex> lock(fsLayerMutex); std::lock_guard lock(gFSLayerMutex);
if (!fsLayers.empty()) { if (!gFSLayers.empty()) {
uint32_t startIndex = fsLayers.size(); uint32_t startIndex = gFSLayers.size();
for (uint32_t i = fsLayers.size(); i > 0; i--) { for (uint32_t i = gFSLayers.size(); i > 0; i--) {
if ((uint32_t) fsLayers[i - 1]->getLayerId() == param->shim->clientHandle) { if (gFSLayers[i - 1]->getLayerId() == param->shim->clientHandle) {
startIndex = i - 1; startIndex = i - 1;
break; break;
} }
@ -105,7 +107,7 @@ FSError doForLayer(FSShimWrapper *param) {
if (startIndex > 0) { if (startIndex > 0) {
for (uint32_t i = startIndex; i > 0; i--) { for (uint32_t i = startIndex; i > 0; i--) {
auto &layer = fsLayers[i - 1]; auto &layer = gFSLayers[i - 1];
if (!layer->isActive()) { if (!layer->isActive()) {
continue; continue;
} }

View File

@ -55,8 +55,8 @@ struct FSShimWrapperMessage {
extern bool gThreadsRunning; extern bool gThreadsRunning;
extern FSIOThreadData gThreadData[3]; extern FSIOThreadData gThreadData[3];
extern std::mutex fsLayerMutex; extern std::mutex gFSLayerMutex;
extern std::vector<std::unique_ptr<IFSWrapper>> fsLayers; extern std::vector<std::unique_ptr<IFSWrapper>> gFSLayers;
#define fsaShimPrepareRequestReadFile ((FSError(*)(FSAShimBuffer * shim, IOSHandle clientHandle, uint8_t * buffer, uint32_t size, uint32_t count, uint32_t pos, FSFileHandle handle, FSAReadFlag readFlags))(0x101C400 + 0x436cc)) #define fsaShimPrepareRequestReadFile ((FSError(*)(FSAShimBuffer * shim, IOSHandle clientHandle, uint8_t * buffer, uint32_t size, uint32_t count, uint32_t pos, FSFileHandle handle, FSAReadFlag readFlags))(0x101C400 + 0x436cc))
#define fsaShimPrepareRequestWriteFile ((FSError(*)(FSAShimBuffer * shim, IOSHandle clientHandle, const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t pos, FSFileHandle handle, FSAWriteFlag writeFlags))(0x101C400 + 0x437f4)) #define fsaShimPrepareRequestWriteFile ((FSError(*)(FSAShimBuffer * shim, IOSHandle clientHandle, const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t pos, FSFileHandle handle, FSAWriteFlag writeFlags))(0x101C400 + 0x437f4))

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <coreinit/filesystem_fsa.h> #include <coreinit/filesystem_fsa.h>
#include <functional> #include <memory>
#include <string> #include <string>
#define FS_ERROR_EXTRA_MASK 0xFFF00000 #define FS_ERROR_EXTRA_MASK 0xFFF00000
@ -53,7 +54,6 @@ public:
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
} }
virtual FSError FSGetStatFileWrapper(FSAFileHandle handle, virtual FSError FSGetStatFileWrapper(FSAFileHandle handle,
FSAStat *stats) { FSAStat *stats) {
return FS_ERROR_FORCE_PARENT_LAYER; return FS_ERROR_FORCE_PARENT_LAYER;
@ -151,11 +151,17 @@ public:
virtual uint32_t getLayerId() = 0; virtual uint32_t getLayerId() = 0;
virtual uint32_t getHandle() { virtual uint32_t getHandle() {
return (uint32_t) this; return reinterpret_cast<uint32_t>(this);
}
IFSWrapper() {
// Abuse this as a stable handle that references itself and survives std::move
*mHandle = reinterpret_cast<uint32_t>(mHandle.get());
} }
private: private:
bool pIsActive = true; bool pIsActive = true;
std::unique_ptr<uint32_t> mHandle = std::make_unique<uint32_t>();
protected: protected:
bool pFallbackOnError = false; bool pFallbackOnError = false;

View File

@ -15,6 +15,7 @@
struct AOCTitle { struct AOCTitle {
WUT_UNKNOWN_BYTES(0x68); WUT_UNKNOWN_BYTES(0x68);
}; };
WUT_CHECK_SIZE(AOCTitle, 0x68); WUT_CHECK_SIZE(AOCTitle, 0x68);
bool getAOCPath(std::string &outStr) { bool getAOCPath(std::string &outStr) {
@ -90,7 +91,7 @@ end:
return result; return result;
} }
ContentRedirectionApiErrorType CRAddFSLayer(CRLayerHandle *handle, const char *layerName, const char *replacementDir, FSLayerType layerType) { ContentRedirectionApiErrorType CRAddFSLayer(CRLayerHandle *handle, const char *layerName, const char *replacementDir, const FSLayerType layerType) {
if (!handle || layerName == nullptr || replacementDir == nullptr) { if (!handle || layerName == nullptr || replacementDir == nullptr) {
DEBUG_FUNCTION_LINE_WARN("CONTENT_REDIRECTION_API_ERROR_INVALID_ARG"); DEBUG_FUNCTION_LINE_WARN("CONTENT_REDIRECTION_API_ERROR_INVALID_ARG");
return CONTENT_REDIRECTION_API_ERROR_INVALID_ARG; return CONTENT_REDIRECTION_API_ERROR_INVALID_ARG;
@ -132,9 +133,9 @@ ContentRedirectionApiErrorType CRAddFSLayer(CRLayerHandle *handle, const char *l
} }
if (ptr) { if (ptr) {
DEBUG_FUNCTION_LINE_VERBOSE("Added new layer (%s). Replacement dir: %s Type:%d", layerName, replacementDir, layerType); DEBUG_FUNCTION_LINE_VERBOSE("Added new layer (%s). Replacement dir: %s Type:%d", layerName, replacementDir, layerType);
std::lock_guard<std::mutex> lock(fsLayerMutex); std::lock_guard lock(gFSLayerMutex);
*handle = (CRLayerHandle) ptr->getHandle(); *handle = (CRLayerHandle) ptr->getHandle();
fsLayers.push_back(std::move(ptr)); gFSLayers.push_back(std::move(ptr));
return CONTENT_REDIRECTION_API_ERROR_NONE; return CONTENT_REDIRECTION_API_ERROR_NONE;
} }
DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory"); DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory");
@ -142,7 +143,7 @@ ContentRedirectionApiErrorType CRAddFSLayer(CRLayerHandle *handle, const char *l
} }
ContentRedirectionApiErrorType CRRemoveFSLayer(CRLayerHandle handle) { ContentRedirectionApiErrorType CRRemoveFSLayer(CRLayerHandle handle) {
if (!remove_locked_first_if(fsLayerMutex, fsLayers, [handle](auto &cur) { return (CRLayerHandle) cur->getHandle() == handle; })) { if (!remove_locked_first_if(gFSLayerMutex, gFSLayers, [handle](auto &cur) { return (CRLayerHandle) cur->getHandle() == handle; })) {
DEBUG_FUNCTION_LINE_WARN("CONTENT_REDIRECTION_API_ERROR_LAYER_NOT_FOUND for handle %08X", handle); DEBUG_FUNCTION_LINE_WARN("CONTENT_REDIRECTION_API_ERROR_LAYER_NOT_FOUND for handle %08X", handle);
return CONTENT_REDIRECTION_API_ERROR_LAYER_NOT_FOUND; return CONTENT_REDIRECTION_API_ERROR_LAYER_NOT_FOUND;
} }
@ -150,8 +151,8 @@ ContentRedirectionApiErrorType CRRemoveFSLayer(CRLayerHandle handle) {
} }
ContentRedirectionApiErrorType CRSetActive(CRLayerHandle handle, bool active) { ContentRedirectionApiErrorType CRSetActive(CRLayerHandle handle, bool active) {
std::lock_guard<std::mutex> lock(fsLayerMutex); std::lock_guard lock(gFSLayerMutex);
for (auto &cur : fsLayers) { for (auto &cur : gFSLayers) {
if ((CRLayerHandle) cur->getHandle() == handle) { if ((CRLayerHandle) cur->getHandle() == handle) {
cur->setActive(active); cur->setActive(active);
return CONTENT_REDIRECTION_API_ERROR_NONE; return CONTENT_REDIRECTION_API_ERROR_NONE;

View File

@ -13,12 +13,12 @@ std::string string_format(const std::string &format, Args... args) {
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
} }
static inline bool starts_with_case_insensitive(std::string_view str, std::string_view prefix) { static inline bool starts_with_case_insensitive(const std::string_view str, const std::string_view prefix) {
if (str.size() < prefix.size()) if (str.size() < prefix.size())
return false; return false;
return std::equal(prefix.begin(), prefix.end(), str.begin(), return std::equal(prefix.begin(), prefix.end(), str.begin(),
[](char a, char b) { [](const char a, const char b) {
return std::tolower(a) == std::tolower(b); return std::tolower(a) == std::tolower(b);
}); });
} }

View File

@ -54,7 +54,7 @@ FSTime translate_time(time_t timeValue) {
return adjustedTimeValue * 1000000; return adjustedTimeValue * 1000000;
} }
void translate_stat(struct stat *posStat, FSStat *fsStat) { void translate_stat(const struct stat *posStat, FSStat *fsStat) {
memset(fsStat, 0, sizeof(FSStat)); memset(fsStat, 0, sizeof(FSStat));
fsStat->size = posStat->st_size; fsStat->size = posStat->st_size;

View File

@ -32,4 +32,4 @@ bool remove_locked_first_if(std::mutex &mutex, std::vector<T, Allocator> &list,
#define ROUNDDOWN(val, align) ((val) & ~(align - 1)) #define ROUNDDOWN(val, align) ((val) & ~(align - 1))
#define ROUNDUP(val, align) ROUNDDOWN(((val) + (align - 1)), align) #define ROUNDUP(val, align) ROUNDDOWN(((val) + (align - 1)), align)
void translate_stat(struct stat *posStat, FSStat *fsStat); void translate_stat(const struct stat *posStat, FSStat *fsStat);