Implement support for redirecting FSA function

This commit is contained in:
Maschell 2022-08-09 00:28:29 +02:00
parent 78ccbd0369
commit cf51d1f724
7 changed files with 444 additions and 11 deletions

View File

@ -0,0 +1,82 @@
#include "FSDirReplacements.h"
#include "FileUtils.h"
#include "IFSWrapper.h"
#include "utils/logger.h"
#include <coreinit/cache.h>
#include <coreinit/filesystem.h>
DECL_FUNCTION(FSError, FSAOpenDir, FSAClientHandle client, const char *path, FSADirectoryHandle *dirHandle) {
DEBUG_FUNCTION_LINE_VERBOSE("%s", path);
return doForLayerFSA(
[c = client, p = path, h = dirHandle]() -> FSError {
return real_FSAOpenDir(c, p, h);
},
[p = path, h = dirHandle](std::unique_ptr<IFSWrapper> &layer) -> FSError {
return layer->FSOpenDirWrapper(p, h);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSAReadDir, FSAClientHandle client, FSADirectoryHandle dirHandle, FSADirectoryEntry *directoryEntry) {
DEBUG_FUNCTION_LINE_VERBOSE("%08X", dirHandle);
return doForLayerFSA(
[c = client, h = dirHandle, de = directoryEntry]() -> FSError {
return real_FSAReadDir(c, h, de);
},
[h = dirHandle, de = directoryEntry](std::unique_ptr<IFSWrapper> &layer) -> FSError {
return layer->FSReadDirWrapper(h, de);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSARewindDir, FSAClientHandle client, FSADirectoryHandle dirHandle) {
DEBUG_FUNCTION_LINE_VERBOSE("%08X", dirHandle);
return doForLayerFSA(
[c = client, h = dirHandle]() -> FSError {
return real_FSARewindDir(c, h);
},
[h = dirHandle](std::unique_ptr<IFSWrapper> &layer) -> FSError {
return layer->FSRewindDirWrapper(h);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSACloseDir, FSAClientHandle client, FSADirectoryHandle dirHandle) {
DEBUG_FUNCTION_LINE_VERBOSE("%08X", dirHandle);
return doForLayerFSA(
[c = client, h = dirHandle]() -> FSError {
return real_FSACloseDir(c, h);
},
[h = dirHandle](std::unique_ptr<IFSWrapper> &layer) -> FSError {
return layer->FSCloseDirWrapper(h);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSAMakeDir, FSAClientHandle client, const char *path, FSMode mode) {
DEBUG_FUNCTION_LINE_VERBOSE("%s", path);
return doForLayerFSA(
[c = client, p = path, m = mode]() -> FSError {
return real_FSAMakeDir(c, p, m);
},
[p = path, m = mode](std::unique_ptr<IFSWrapper> &layer) -> FSError {
return layer->FSMakeDirWrapper(p);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSAChangeDir, FSAClientHandle client, const char *path) {
DEBUG_FUNCTION_LINE_VERBOSE("%s", path);
setWorkingDirForFSAClient(client, path);
return real_FSAChangeDir(client, path);
}
function_replacement_data_t fsa_dir_function_replacements[] = {
REPLACE_FUNCTION(FSAOpenDir, LIBRARY_COREINIT, FSAOpenDir),
REPLACE_FUNCTION(FSAReadDir, LIBRARY_COREINIT, FSAReadDir),
REPLACE_FUNCTION(FSARewindDir, LIBRARY_COREINIT, FSARewindDir),
REPLACE_FUNCTION(FSACloseDir, LIBRARY_COREINIT, FSACloseDir),
REPLACE_FUNCTION(FSAMakeDir, LIBRARY_COREINIT, FSAMakeDir),
REPLACE_FUNCTION(FSAChangeDir, LIBRARY_COREINIT, FSAChangeDir),
};
uint32_t fsa_dir_function_replacements_size = sizeof(fsa_dir_function_replacements) / sizeof(function_replacement_data_t);

10
src/FSADirReplacements.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "IFSWrapper.h"
#include <coreinit/filesystem.h>
#include <function_patcher/function_patching.h>
#include <functional>
#include <string>
extern function_replacement_data_t fsa_dir_function_replacements[];
extern uint32_t fsa_dir_function_replacements_size;

238
src/FSAFileReplacements.cpp Normal file
View File

@ -0,0 +1,238 @@
#include "FSFileReplacements.h"
#include "FileUtils.h"
#include "utils/logger.h"
#include <coreinit/filesystem_fsa.h>
DECL_FUNCTION(FSError, FSAOpenFileEx, FSAClientHandle client, const char *path, const char *mode, FSMode createMode, FSOpenFileFlags openFlag, uint32_t preallocSize, FSAFileHandle *handle) {
DEBUG_FUNCTION_LINE_VERBOSE("path: %s mode: %d", path, mode);
return doForLayerFSA(
[c = client, p = path, m = mode, cm = createMode, of = openFlag, pa = preallocSize, h = handle]() -> FSError {
return real_FSAOpenFileEx(c, p, m, cm, of, pa, h);
},
[f = getFullPathForFSAClient(client, path), m = mode, h = handle](std::unique_ptr<IFSWrapper> &layer) -> FSError {
// FSAFileHandle is just an alias for FSFileHandle
return layer->FSOpenFileWrapper(f.c_str(), m, h);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSACloseFile, FSAClientHandle client, FSAFileHandle fileHandle) {
DEBUG_FUNCTION_LINE_VERBOSE("handle: %08X", fileHandle);
return doForLayerFSA(
[c = client, h = fileHandle]() -> FSError {
return real_FSACloseFile(c, h);
},
[h = fileHandle](std::unique_ptr<IFSWrapper> &layer) -> FSError {
// FSAFileHandle is just an alias for FSFileHandle
return layer->FSCloseFileWrapper(h);
},
[h = fileHandle, filename = __FILENAME__, func = __FUNCTION__, line = __LINE__](std::unique_ptr<IFSWrapper> &layer, FSError res) -> FSError {
if (layer->isValidFileHandle(h)) {
layer->deleteFileHandle(h);
} else {
DEBUG_FUNCTION_LINE_ERR_LAMBDA(filename, func, line, "Expected to delete fileHandle by handle %08X but it was not found", h);
}
DEBUG_FUNCTION_LINE_VERBOSE_EX(filename, func, line, "Sync result %d", res);
return res;
});
}
DECL_FUNCTION(FSError, FSAFlushFile, FSAClientHandle client, FSAFileHandle fileHandle) {
DEBUG_FUNCTION_LINE_VERBOSE("handle: %08X", fileHandle);
return doForLayerFSA(
[c = client, h = fileHandle]() -> FSError {
return real_FSAFlushFile(c, h);
},
[h = fileHandle](std::unique_ptr<IFSWrapper> &layer) -> FSError {
// FSAFileHandle is just an alias for FSFileHandle
return layer->FSFlushFileWrapper(h);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSAGetStat, FSAClientHandle client, const char *path, FSAStat *stat) {
DEBUG_FUNCTION_LINE_VERBOSE("%s", path);
return doForLayerFSA(
[c = client, p = path, s = stat]() -> FSError {
return real_FSAGetStat(c, p, s);
},
[f = getFullPathForFSAClient(client, path), s = stat](std::unique_ptr<IFSWrapper> &layer) -> FSError {
// FSAStat is just an alias for FSStat
return layer->FSGetStatWrapper(f.c_str(), s);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSAGetStatFile, FSAClientHandle client, FSAFileHandle fileHandle, FSAStat *stat) {
DEBUG_FUNCTION_LINE_VERBOSE("handle: %08X", fileHandle);
return doForLayerFSA(
[c = client, h = fileHandle, s = stat]() -> FSError {
return real_FSAGetStatFile(c, h, s);
},
[h = fileHandle, s = stat](std::unique_ptr<IFSWrapper> &layer) -> FSError {
// FSAFileHandle is just an alias for FSFileHandle
// FSAStat is just an alias for FSStat
return layer->FSGetStatFileWrapper(h, s);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSARemove, FSAClientHandle client, const char *path) {
DEBUG_FUNCTION_LINE_VERBOSE("%s", path);
return doForLayerFSA(
[c = client, p = path]() -> FSError {
return real_FSARemove(c, p);
},
[f = getFullPathForFSAClient(client, path)](std::unique_ptr<IFSWrapper> &layer) -> FSError {
return layer->FSRemoveWrapper(f.c_str());
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSARename, FSAClientHandle client, const char *oldPath, const char *newPath) {
DEBUG_FUNCTION_LINE_VERBOSE("%s %s", oldPath, newPath);
return doForLayerFSA(
[c = client, op = oldPath, np = newPath]() -> FSError {
return real_FSARename(c, op, np);
},
[op = getFullPathForFSAClient(client, oldPath), np = getFullPathForFSAClient(client, newPath)](std::unique_ptr<IFSWrapper> &layer) -> FSError {
return layer->FSRenameWrapper(op.c_str(), np.c_str());
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSASetPosFile, FSAClientHandle client, FSAFileHandle fileHandle, uint32_t pos) {
DEBUG_FUNCTION_LINE_VERBOSE("handle: %08X pos: %08X", fileHandle, pos);
return doForLayerFSA(
[c = client, h = fileHandle, p = pos]() -> FSError {
return real_FSASetPosFile(c, h, p);
},
[h = fileHandle, p = pos](std::unique_ptr<IFSWrapper> &layer) -> FSError {
return layer->FSSetPosFileWrapper(h, p);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSATruncateFile, FSAClientHandle client, FSAFileHandle fileHandle) {
DEBUG_FUNCTION_LINE_VERBOSE("%08X", fileHandle);
return doForLayerFSA(
[c = client, h = fileHandle]() -> FSError {
return real_FSATruncateFile(c, h);
},
[h = fileHandle](std::unique_ptr<IFSWrapper> &layer) -> FSError {
return layer->FSTruncateFileWrapper(h);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSAReadFile, FSAClientHandle client, void *buffer, uint32_t size, uint32_t count, FSAFileHandle handle, uint32_t flags) {
DEBUG_FUNCTION_LINE_VERBOSE("handle: %08X buffer: %08X size: %08X", handle, buffer, size * count);
return doForLayerFSA(
[c = client, b = buffer, s = size, co = count, h = handle, f = flags]() -> FSError {
return real_FSAReadFile(c, b, s, co, h, f);
},
[b = buffer, s = size, co = count, h = handle, f = flags](std::unique_ptr<IFSWrapper> &layer) -> FSError {
return layer->FSReadFileWrapper(b, s, co, h, f);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSAWriteFile, FSAClientHandle client, void *buffer, uint32_t size, uint32_t count, FSAFileHandle handle, uint32_t flags) {
DEBUG_FUNCTION_LINE_VERBOSE("handle: %08X buffer: %08X size: %08X", handle, buffer, size * count);
return doForLayerFSA(
[c = client, b = buffer, s = size, co = count, h = handle, f = flags]() -> FSError {
return real_FSAWriteFile(c, b, s, co, h, f);
},
[b = buffer, s = size, co = count, h = handle, f = flags](std::unique_ptr<IFSWrapper> &layer) -> FSError {
return layer->FSWriteFileWrapper((uint8_t *) b, s, co, h, f);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSAGetPosFile, FSAClientHandle client, FSAFileHandle handle, uint32_t *outPos) {
DEBUG_FUNCTION_LINE_VERBOSE("handle: %08X", handle);
return doForLayerFSA(
[c = client, h = handle, o = outPos]() -> FSError {
return real_FSAGetPosFile(c, h, o);
},
[h = handle, o = outPos](std::unique_ptr<IFSWrapper> &layer) -> FSError {
return layer->FSGetPosFileWrapper(h, o);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSAIsEof, FSAClientHandle client, FSAFileHandle handle) {
DEBUG_FUNCTION_LINE_VERBOSE("handle: %08X", handle);
return doForLayerFSA(
[c = client, h = handle]() -> FSError {
return real_FSAIsEof(c, h);
},
[h = handle](std::unique_ptr<IFSWrapper> &layer) -> FSError {
return layer->FSIsEofWrapper(h);
},
SYNC_RESULT_HANDLER_FSA);
}
DECL_FUNCTION(FSError, FSAFlushMultiQuota, FSAClientHandle client, const char *path) {
DEBUG_FUNCTION_LINE("NOT IMPLEMENTED. path %s", path);
return real_FSAFlushMultiQuota(client, path);
}
DECL_FUNCTION(FSError, FSAFlushQuota, FSAClientHandle client, const char *path) {
DEBUG_FUNCTION_LINE("NOT IMPLEMENTED. path %s", path);
return real_FSAFlushQuota(client, path);
}
DECL_FUNCTION(FSError, FSAChangeMode, FSAClientHandle client, const char *path, FSMode permission) {
DEBUG_FUNCTION_LINE_ERR("NOT IMPLEMENTED path %s permission: %08X", path, permission);
return real_FSAChangeMode(client, path, permission);
}
DECL_FUNCTION(FSError, FSAOpenFileByStat, FSAClientHandle client, FSAStat *stat, const char *mode, const char *path, FSAFileHandle *outFileHandle) {
DEBUG_FUNCTION_LINE_ERR("NOT IMPLEMENTED");
return real_FSAOpenFileByStat(client, stat, mode, path, outFileHandle);
}
DECL_FUNCTION(FSError, FSAAppendFile, FSAClientHandle client, FSAFileHandle fileHandle, uint32_t size, uint32_t count) {
DEBUG_FUNCTION_LINE_ERR("NOT IMPLEMENTED");
return real_FSAAppendFile(client, fileHandle, size, count);
}
DECL_FUNCTION(FSError, FSAAppendFileEx, FSAClientHandle client, FSAFileHandle fileHandle, uint32_t size, uint32_t count, uint32_t flags) {
DEBUG_FUNCTION_LINE_ERR("NOT IMPLEMENTED");
return real_FSAAppendFileEx(client, fileHandle, size, count, flags);
}
DECL_FUNCTION(FSStatus, FSAWriteFileWithPos, FSAClientHandle client, uint8_t *buffer, uint32_t size, uint32_t count, uint32_t pos, FSFileHandle handle, uint32_t flags) {
DEBUG_FUNCTION_LINE_ERR("NOT IMPLEMENTED. handle %08X size %08X", handle, size * count);
return real_FSAWriteFileWithPos(client, buffer, size, count, pos, handle, flags);
}
function_replacement_data_t fsa_file_function_replacements[] = {
REPLACE_FUNCTION(FSAOpenFileEx, LIBRARY_COREINIT, FSAOpenFileEx),
REPLACE_FUNCTION(FSACloseFile, LIBRARY_COREINIT, FSACloseFile),
REPLACE_FUNCTION(FSAFlushFile, LIBRARY_COREINIT, FSAFlushFile),
REPLACE_FUNCTION(FSAGetStat, LIBRARY_COREINIT, FSAGetStat),
REPLACE_FUNCTION(FSAGetStatFile, LIBRARY_COREINIT, FSAGetStatFile),
REPLACE_FUNCTION(FSARemove, LIBRARY_COREINIT, FSARemove),
REPLACE_FUNCTION(FSARename, LIBRARY_COREINIT, FSARename),
REPLACE_FUNCTION(FSASetPosFile, LIBRARY_COREINIT, FSASetPosFile),
REPLACE_FUNCTION(FSATruncateFile, LIBRARY_COREINIT, FSATruncateFile),
REPLACE_FUNCTION(FSAReadFile, LIBRARY_COREINIT, FSAReadFile),
REPLACE_FUNCTION(FSAWriteFile, LIBRARY_COREINIT, FSAWriteFile),
REPLACE_FUNCTION(FSAGetPosFile, LIBRARY_COREINIT, FSAGetPosFile),
REPLACE_FUNCTION(FSAIsEof, LIBRARY_COREINIT, FSAIsEof),
REPLACE_FUNCTION(FSAFlushMultiQuota, LIBRARY_COREINIT, FSAFlushMultiQuota),
REPLACE_FUNCTION(FSAFlushQuota, LIBRARY_COREINIT, FSAFlushQuota),
REPLACE_FUNCTION(FSAChangeMode, LIBRARY_COREINIT, FSAChangeMode),
REPLACE_FUNCTION(FSAOpenFileByStat, LIBRARY_COREINIT, FSAOpenFileByStat),
REPLACE_FUNCTION(FSAAppendFile, LIBRARY_COREINIT, FSAAppendFile),
REPLACE_FUNCTION(FSAAppendFileEx, LIBRARY_COREINIT, FSAAppendFileEx),
REPLACE_FUNCTION(FSAWriteFileWithPos, LIBRARY_COREINIT, FSAWriteFileWithPos),
};
uint32_t fsa_file_function_replacements_size = sizeof(fsa_file_function_replacements) / sizeof(function_replacement_data_t);

15
src/FSAFileReplacements.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include <function_patcher/function_patching.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern function_replacement_data_t fsa_file_function_replacements[];
extern uint32_t fsa_file_function_replacements_size;
#ifdef __cplusplus
}
#endif

View File

@ -10,22 +10,25 @@
#include <unistd.h>
std::mutex workingDirMutexFS;
std::map<FSClient *, std::string> workingDirsFS;
std::map<uint32_t, std::string> workingDirsFS;
std::mutex workingDirMutexFSA;
std::map<uint32_t, std::string> workingDirsFSA;
std::mutex fsLayerMutex;
std::vector<std::unique_ptr<IFSWrapper>> fsLayers;
std::string getFullPathForFSClient(FSClient *pClient, const char *path) {
std::lock_guard<std::mutex> workingDirLock(workingDirMutexFS);
std::string getFullPathGeneric(uint32_t client, const char *path, std::mutex &mutex, std::map<uint32_t, std::string> &map) {
std::lock_guard<std::mutex> workingDirLock(mutex);
std::string res;
if (path[0] != '/' && path[0] != '\\') {
if (workingDirsFS.count(pClient) == 0) {
DEBUG_FUNCTION_LINE_WARN("No working dir found for FS client %08X, fallback to \"/\"", pClient);
workingDirsFS[pClient] = "/";
if (map.count(client) == 0) {
DEBUG_FUNCTION_LINE_WARN("No working dir found for client %08X, fallback to \"/\"", client);
workingDirsFS[client] = "/";
}
res = string_format("%s%s", workingDirsFS.at(pClient).c_str(), path);
res = string_format("%s%s", map.at(client).c_str(), path);
} else {
res = path;
}
@ -35,33 +38,92 @@ std::string getFullPathForFSClient(FSClient *pClient, const char *path) {
return res;
}
void setWorkingDirForFSClient(FSClient *client, const char *path) {
void setWorkingDirGeneric(uint32_t client, const char *path, std::mutex &mutex, std::map<uint32_t, std::string> &map) {
if (!path) {
DEBUG_FUNCTION_LINE_WARN("Path was NULL");
return;
}
std::lock_guard<std::mutex> workingDirLock(workingDirMutexFS);
std::lock_guard<std::mutex> workingDirLock(mutex);
std::string cwd(path);
if (cwd.empty() || cwd.back() != '/') {
cwd.push_back('/');
}
workingDirsFS[client] = cwd;
map[client] = cwd;
OSMemoryBarrier();
}
std::string getFullPathForFSClient(FSClient *pClient, const char *path) {
return getFullPathGeneric((uint32_t) pClient, path, workingDirMutexFS, workingDirsFS);
}
void setWorkingDirForFSClient(FSClient *client, const char *path) {
setWorkingDirGeneric((uint32_t) client, path, workingDirMutexFS, workingDirsFS);
}
std::string getFullPathForFSAClient(FSAClientHandle client, const char *path) {
return getFullPathGeneric((uint32_t) client, path, workingDirMutexFSA, workingDirsFSA);
}
void setWorkingDirForFSAClient(FSAClientHandle client, const char *path) {
setWorkingDirGeneric(client, path, workingDirMutexFSA, workingDirsFSA);
}
void clearFSLayer() {
{
std::lock_guard<std::mutex> workingDirLock(workingDirMutexFS);
workingDirsFS.clear();
}
{
std::lock_guard<std::mutex> workingDirLock(workingDirMutexFSA);
workingDirsFSA.clear();
}
{
std::lock_guard<std::mutex> layerLock(fsLayerMutex);
fsLayers.clear();
}
}
FSError doForLayerFSA(const std::function<FSError()> &real_function,
const std::function<FSError(std::unique_ptr<IFSWrapper> &layer)> &layer_callback,
const std::function<FSError(std::unique_ptr<IFSWrapper> &layer, FSError)> &result_handler) {
std::lock_guard<std::mutex> lock(fsLayerMutex);
if (!fsLayers.empty()) {
uint32_t startIndex = fsLayers.size();
if (startIndex > 0) {
for (uint32_t i = startIndex; i > 0; i--) {
auto &layer = fsLayers[i - 1];
if (!layer->isActive()) {
continue;
}
FSError layerResult = layer_callback(layer);
if (layerResult != FS_ERROR_FORCE_PARENT_LAYER) {
auto result = layerResult >= 0 ? layerResult : (FSError) ((layerResult & FS_ERROR_REAL_MASK) | FS_ERROR_EXTRA_MASK);
if (result < FS_ERROR_OK && result != FS_ERROR_END_OF_DIR && result != FS_ERROR_END_OF_FILE && result != FS_ERROR_CANCELLED) {
if (layer->fallbackOnError()) {
// Only fallback if FS_ERROR_FORCE_NO_FALLBACK flag is not set.
if (static_cast<FSError>(layerResult & FS_ERROR_EXTRA_MASK) != FS_ERROR_FORCE_NO_FALLBACK) {
continue;
}
}
}
return result_handler(layer, result);
}
}
}
}
return real_function();
}
// FUN_0204cc20
#define fsClientHandleFatalErrorAndBlock ((void (*)(FSClientBody *, uint32_t))(0x101C400 + 0x4cc20))
#define fsaDecodeFsaStatusToFsStatus ((FSStatus(*)(FSError))(0x101C400 + 0x4b148))

View File

@ -2,6 +2,7 @@
#include "IFSWrapper.h"
#include <coreinit/filesystem.h>
#include <coreinit/filesystem_fsa.h>
#include <functional>
#include <mutex>
#include <romfs_dev.h>
@ -20,6 +21,11 @@ extern std::vector<std::unique_ptr<IFSWrapper>> fsLayers;
return send_result_async(c, b, a, res); \
}
#define SYNC_RESULT_HANDLER_FSA [filename = __FILENAME__, func = __FUNCTION__, line = __LINE__]([[maybe_unused]] std::unique_ptr<IFSWrapper> &layer, FSError res) -> FSError { \
DEBUG_FUNCTION_LINE_VERBOSE_EX(filename, func, line, "Sync result was %d", res); \
return res; \
}
#define FS_ERROR_FLAG_EXTRA_MASK (FSErrorFlag) 0xFFFF0000
#define FS_ERROR_FLAG_REAL_MASK (FSErrorFlag) 0x0000FFFF
#define FS_ERROR_FLAG_FORCE_REAL (FSErrorFlag) 0xFEDC0000
@ -42,6 +48,14 @@ std::string getFullPathForFSClient(FSClient *pClient, const char *path);
void setWorkingDirForFSClient(FSClient *client, const char *path);
std::string getFullPathForFSAClient(FSAClientHandle client, const char *path);
void setWorkingDirForFSAClient(FSAClientHandle client, const char *path);
FSError doForLayerFSA(const std::function<FSError()> &real_function,
const std::function<FSError(std::unique_ptr<IFSWrapper> &layer)> &layer_callback,
const std::function<FSError(std::unique_ptr<IFSWrapper> &layer, FSError)> &result_handler);
FSStatus doForLayer(FSClient *client,
FSErrorFlag errorMask,
const std::function<FSStatus(FSErrorFlag errorMask)> &real_function,

View File

@ -1,3 +1,5 @@
#include "FSADirReplacements.h"
#include "FSAFileReplacements.h"
#include "FSDirReplacements.h"
#include "FSFileReplacements.h"
#include "FileUtils.h"
@ -15,11 +17,21 @@ WUMS_INITIALIZE() {
OSFatal("homebrew_content_redirection: Failed to patch function");
}
}
for (uint32_t i = 0; i < fsa_file_function_replacements_size; i++) {
if (!FunctionPatcherPatchFunction(&fsa_file_function_replacements[i], nullptr)) {
OSFatal("homebrew_content_redirection: Failed to patch function");
}
}
for (uint32_t i = 0; i < fs_dir_function_replacements_size; i++) {
if (!FunctionPatcherPatchFunction(&fs_dir_function_replacements[i], nullptr)) {
OSFatal("homebrew_content_redirection: Failed to patch function");
}
}
for (uint32_t i = 0; i < fsa_dir_function_replacements_size; i++) {
if (!FunctionPatcherPatchFunction(&fsa_dir_function_replacements[i], nullptr)) {
OSFatal("homebrew_content_redirection: Failed to patch function");
}
}
DEBUG_FUNCTION_LINE("Patch functions finished");
deinitLogging();
}