mirror of
https://github.com/wiiu-env/ContentRedirectionModule.git
synced 2024-11-10 13:45:16 +01:00
Implement support for redirecting FSA function
This commit is contained in:
parent
921725efdb
commit
bff5fa8351
82
src/FSADirReplacements.cpp
Normal file
82
src/FSADirReplacements.cpp
Normal 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
10
src/FSADirReplacements.h
Normal 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
238
src/FSAFileReplacements.cpp
Normal 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
15
src/FSAFileReplacements.h
Normal 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
|
@ -10,22 +10,25 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
std::mutex workingDirMutexFS;
|
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::mutex fsLayerMutex;
|
||||||
std::vector<std::unique_ptr<IFSWrapper>> fsLayers;
|
std::vector<std::unique_ptr<IFSWrapper>> fsLayers;
|
||||||
|
|
||||||
std::string getFullPathForFSClient(FSClient *pClient, const char *path) {
|
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(workingDirMutexFS);
|
std::lock_guard<std::mutex> workingDirLock(mutex);
|
||||||
|
|
||||||
std::string res;
|
std::string res;
|
||||||
|
|
||||||
if (path[0] != '/' && path[0] != '\\') {
|
if (path[0] != '/' && path[0] != '\\') {
|
||||||
if (workingDirsFS.count(pClient) == 0) {
|
if (map.count(client) == 0) {
|
||||||
DEBUG_FUNCTION_LINE_WARN("No working dir found for FS client %08X, fallback to \"/\"", pClient);
|
DEBUG_FUNCTION_LINE_WARN("No working dir found for client %08X, fallback to \"/\"", client);
|
||||||
workingDirsFS[pClient] = "/";
|
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 {
|
} else {
|
||||||
res = path;
|
res = path;
|
||||||
}
|
}
|
||||||
@ -35,33 +38,92 @@ std::string getFullPathForFSClient(FSClient *pClient, const char *path) {
|
|||||||
return res;
|
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) {
|
if (!path) {
|
||||||
DEBUG_FUNCTION_LINE_WARN("Path was NULL");
|
DEBUG_FUNCTION_LINE_WARN("Path was NULL");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::lock_guard<std::mutex> workingDirLock(workingDirMutexFS);
|
|
||||||
|
std::lock_guard<std::mutex> workingDirLock(mutex);
|
||||||
|
|
||||||
std::string cwd(path);
|
std::string cwd(path);
|
||||||
if (cwd.empty() || cwd.back() != '/') {
|
if (cwd.empty() || cwd.back() != '/') {
|
||||||
cwd.push_back('/');
|
cwd.push_back('/');
|
||||||
}
|
}
|
||||||
|
map[client] = cwd;
|
||||||
workingDirsFS[client] = cwd;
|
|
||||||
OSMemoryBarrier();
|
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() {
|
void clearFSLayer() {
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> workingDirLock(workingDirMutexFS);
|
std::lock_guard<std::mutex> workingDirLock(workingDirMutexFS);
|
||||||
workingDirsFS.clear();
|
workingDirsFS.clear();
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> workingDirLock(workingDirMutexFSA);
|
||||||
|
workingDirsFSA.clear();
|
||||||
|
}
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> layerLock(fsLayerMutex);
|
std::lock_guard<std::mutex> layerLock(fsLayerMutex);
|
||||||
fsLayers.clear();
|
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
|
// FUN_0204cc20
|
||||||
#define fsClientHandleFatalErrorAndBlock ((void (*)(FSClientBody *, uint32_t))(0x101C400 + 0x4cc20))
|
#define fsClientHandleFatalErrorAndBlock ((void (*)(FSClientBody *, uint32_t))(0x101C400 + 0x4cc20))
|
||||||
#define fsaDecodeFsaStatusToFsStatus ((FSStatus(*)(FSError))(0x101C400 + 0x4b148))
|
#define fsaDecodeFsaStatusToFsStatus ((FSStatus(*)(FSError))(0x101C400 + 0x4b148))
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "IFSWrapper.h"
|
#include "IFSWrapper.h"
|
||||||
#include <coreinit/filesystem.h>
|
#include <coreinit/filesystem.h>
|
||||||
|
#include <coreinit/filesystem_fsa.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <romfs_dev.h>
|
#include <romfs_dev.h>
|
||||||
@ -20,6 +21,11 @@ extern std::vector<std::unique_ptr<IFSWrapper>> fsLayers;
|
|||||||
return send_result_async(c, b, a, res); \
|
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_EXTRA_MASK (FSErrorFlag) 0xFFFF0000
|
||||||
#define FS_ERROR_FLAG_REAL_MASK (FSErrorFlag) 0x0000FFFF
|
#define FS_ERROR_FLAG_REAL_MASK (FSErrorFlag) 0x0000FFFF
|
||||||
#define FS_ERROR_FLAG_FORCE_REAL (FSErrorFlag) 0xFEDC0000
|
#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);
|
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,
|
FSStatus doForLayer(FSClient *client,
|
||||||
FSErrorFlag errorMask,
|
FSErrorFlag errorMask,
|
||||||
const std::function<FSStatus(FSErrorFlag errorMask)> &real_function,
|
const std::function<FSStatus(FSErrorFlag errorMask)> &real_function,
|
||||||
|
12
src/main.cpp
12
src/main.cpp
@ -1,3 +1,5 @@
|
|||||||
|
#include "FSADirReplacements.h"
|
||||||
|
#include "FSAFileReplacements.h"
|
||||||
#include "FSDirReplacements.h"
|
#include "FSDirReplacements.h"
|
||||||
#include "FSFileReplacements.h"
|
#include "FSFileReplacements.h"
|
||||||
#include "FileUtils.h"
|
#include "FileUtils.h"
|
||||||
@ -15,11 +17,21 @@ WUMS_INITIALIZE() {
|
|||||||
OSFatal("homebrew_content_redirection: Failed to patch function");
|
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++) {
|
for (uint32_t i = 0; i < fs_dir_function_replacements_size; i++) {
|
||||||
if (!FunctionPatcherPatchFunction(&fs_dir_function_replacements[i], nullptr)) {
|
if (!FunctionPatcherPatchFunction(&fs_dir_function_replacements[i], nullptr)) {
|
||||||
OSFatal("homebrew_content_redirection: Failed to patch function");
|
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");
|
DEBUG_FUNCTION_LINE("Patch functions finished");
|
||||||
deinitLogging();
|
deinitLogging();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user