Compare commits
17 Commits
Author | SHA1 | Date |
---|---|---|
Maschell | 03ea0aceae | |
Maschell | 45efb02d27 | |
Maschell | 60b711cf81 | |
Maschell | 884a3561d2 | |
Maschell | f9a4b537c8 | |
Maschell | 835881abfa | |
Maschell | d0dfbd6d4e | |
Maschell | a2c8863cbe | |
Maschell | 0d5bf8c78f | |
Maschell | 9d0dbda1db | |
Maschell | 75854a05e5 | |
dependabot[bot] | 6c2748569d | |
Maschell | 71406e2044 | |
dependabot[bot] | 12e102a4a7 | |
Callum Parsey | 0df67fc7d9 | |
Maschell | f4f50748d7 | |
Maschell | 98a137c91f |
|
@ -0,0 +1,10 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
|
@ -9,7 +9,7 @@ jobs:
|
|||
clang-format:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: clang-format
|
||||
run: |
|
||||
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./src
|
||||
|
@ -17,7 +17,7 @@ jobs:
|
|||
runs-on: ubuntu-22.04
|
||||
needs: clang-format
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: create version.h
|
||||
run: |
|
||||
git_hash=$(git rev-parse --short "$GITHUB_SHA")
|
||||
|
@ -48,7 +48,7 @@ jobs:
|
|||
- name: zip artifact
|
||||
run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip *.wms
|
||||
- name: Create Release
|
||||
uses: "softprops/action-gh-release@v1"
|
||||
uses: "softprops/action-gh-release@v2"
|
||||
with:
|
||||
tag_name: ${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
||||
draft: false
|
||||
|
|
|
@ -6,7 +6,7 @@ jobs:
|
|||
clang-format:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: clang-format
|
||||
run: |
|
||||
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./src
|
||||
|
@ -14,7 +14,7 @@ jobs:
|
|||
runs-on: ubuntu-22.04
|
||||
needs: clang-format
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: build binary with logging
|
||||
run: |
|
||||
docker build . -t builder
|
||||
|
@ -25,7 +25,7 @@ jobs:
|
|||
runs-on: ubuntu-22.04
|
||||
needs: clang-format
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: create version.h
|
||||
run: |
|
||||
git_hash=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}")
|
||||
|
|
|
@ -8,3 +8,4 @@ build/
|
|||
cmake-build-debug/
|
||||
CMakeLists.txt
|
||||
*.wms
|
||||
*.zip
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
FROM ghcr.io/wiiu-env/devkitppc:20230621
|
||||
FROM ghcr.io/wiiu-env/devkitppc:20240505
|
||||
|
||||
COPY --from=ghcr.io/wiiu-env/libfunctionpatcher:20230621 /artifacts $DEVKITPRO
|
||||
COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:20230719 /artifacts $DEVKITPRO
|
||||
COPY --from=ghcr.io/wiiu-env/libromfs_wiiu:20230621 /artifacts $DEVKITPRO
|
||||
COPY --from=ghcr.io/wiiu-env/libcontentredirection:20230621 /artifacts $DEVKITPRO
|
||||
COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:20240424 /artifacts $DEVKITPRO
|
||||
COPY --from=ghcr.io/wiiu-env/libcontentredirection:20240428 /artifacts $DEVKITPRO
|
||||
|
||||
WORKDIR project
|
||||
|
|
|
@ -560,11 +560,11 @@ function_replacement_data_t fs_file_function_replacements[] = {
|
|||
REPLACE_FUNCTION(FSCloseFileAsync, LIBRARY_COREINIT, FSCloseFileAsync),
|
||||
REPLACE_FUNCTION(FSGetStatAsync, LIBRARY_COREINIT, FSGetStatAsync),
|
||||
REPLACE_FUNCTION(FSGetStatFileAsync, LIBRARY_COREINIT, FSGetStatFileAsync),
|
||||
REPLACE_FUNCTION_VIA_ADDRESS(FSReadFileGeneric, 0x3201C400 + 0x4ecc0, 0x101C400 + 0x4ecc0),
|
||||
REPLACE_FUNCTION_VIA_ADDRESS_FOR_PROCESS(FSReadFileGeneric, 0x3201C400 + 0x4ecc0, 0x101C400 + 0x4ecc0, FP_TARGET_PROCESS_GAME_AND_MENU),
|
||||
REPLACE_FUNCTION(FSSetPosFileAsync, LIBRARY_COREINIT, FSSetPosFileAsync),
|
||||
REPLACE_FUNCTION(FSGetPosFileAsync, LIBRARY_COREINIT, FSGetPosFileAsync),
|
||||
REPLACE_FUNCTION(FSIsEofAsync, LIBRARY_COREINIT, FSIsEofAsync),
|
||||
REPLACE_FUNCTION_VIA_ADDRESS(FSWriteFileGeneric, 0x3201C400 + 0x4eec0, 0x101C400 + 0x4eec0),
|
||||
REPLACE_FUNCTION_VIA_ADDRESS_FOR_PROCESS(FSWriteFileGeneric, 0x3201C400 + 0x4eec0, 0x101C400 + 0x4eec0, FP_TARGET_PROCESS_GAME_AND_MENU),
|
||||
REPLACE_FUNCTION(FSTruncateFileAsync, LIBRARY_COREINIT, FSTruncateFileAsync),
|
||||
REPLACE_FUNCTION(FSRemoveAsync, LIBRARY_COREINIT, FSRemoveAsync),
|
||||
REPLACE_FUNCTION(FSRenameAsync, LIBRARY_COREINIT, FSRenameAsync),
|
||||
|
|
|
@ -83,7 +83,7 @@ FSError FSWrapper::FSReadDirWrapper(FSDirectoryHandle handle, FSDirectoryEntry *
|
|||
struct dirent *entry_ = readdir(dir);
|
||||
|
||||
if (entry_) {
|
||||
if (SkipDeletedFilesInReadDir() && std::string_view(entry_->d_name).starts_with(deletePrefix)) {
|
||||
if (SkipDeletedFilesInReadDir() && starts_with_case_insensitive(entry_->d_name, deletePrefix)) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Skip file file name %s because of the prefix", entry_->d_name);
|
||||
continue;
|
||||
}
|
||||
|
@ -98,6 +98,9 @@ FSError FSWrapper::FSReadDirWrapper(FSDirectoryHandle handle, FSDirectoryEntry *
|
|||
if (strcmp(entry_->d_name, ".") == 0 || strcmp(entry_->d_name, "..") == 0) {
|
||||
entry->info.size = 0;
|
||||
} else {
|
||||
#ifdef _DIRENT_HAVE_D_STAT
|
||||
translate_stat(&entry_->d_stat, &entry->info);
|
||||
#else
|
||||
struct stat sb {};
|
||||
auto path = string_format("%s/%s", dirHandle->path, entry_->d_name);
|
||||
std::replace(path.begin(), path.end(), '\\', '/');
|
||||
|
@ -120,13 +123,14 @@ FSError FSWrapper::FSReadDirWrapper(FSDirectoryHandle handle, FSDirectoryEntry *
|
|||
result = FS_ERROR_MEDIA_ERROR;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
result = FS_ERROR_OK;
|
||||
} else {
|
||||
auto err = errno;
|
||||
if (err != 0) {
|
||||
DEBUG_FUNCTION_LINE_ERR("[%s] Failed to read dir %08X (handle %08X)", getName().c_str(), dir, handle);
|
||||
DEBUG_FUNCTION_LINE_ERR("[%s] Failed to read dir %08X (handle %08X). errno %d (%s)", getName().c_str(), dir, handle, err, strerror(err));
|
||||
result = FS_ERROR_MEDIA_ERROR;
|
||||
}
|
||||
}
|
||||
|
@ -229,7 +233,7 @@ FSError FSWrapper::FSOpenFileWrapper(const char *path, const char *mode, FSFileH
|
|||
_mode = O_RDONLY;
|
||||
} else if (strcmp(mode, "r+") == 0) {
|
||||
_mode = O_RDWR;
|
||||
} else if (strcmp(mode, "w") == 0) {
|
||||
} else if (strcmp(mode, "w") == 0 || strcmp(mode, "wb") == 0) {
|
||||
_mode = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
} else if (strcmp(mode, "w+") == 0) {
|
||||
_mode = O_RDWR | O_CREAT | O_TRUNC;
|
||||
|
@ -313,7 +317,7 @@ FSError FSWrapper::FSCloseFileWrapper(FSFileHandle handle) {
|
|||
bool FSWrapper::CheckFileShouldBeIgnored(std::string &path) {
|
||||
auto asPath = std::filesystem::path(path);
|
||||
|
||||
if (std::string(asPath.filename().c_str()).starts_with(deletePrefix)) {
|
||||
if (starts_with_case_insensitive(asPath.filename().c_str(), deletePrefix)) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("[%s] Ignore %s, filename starts with %s", getName().c_str(), path.c_str(), deletePrefix.c_str());
|
||||
return true;
|
||||
}
|
||||
|
@ -659,6 +663,7 @@ bool FSWrapper::IsFileModeAllowed(const char *mode) {
|
|||
|
||||
if (pIsWriteable && (strcmp(mode, "r+") == 0 ||
|
||||
strcmp(mode, "w") == 0 ||
|
||||
strcmp(mode, "wb") == 0 ||
|
||||
strcmp(mode, "w+") == 0 ||
|
||||
strcmp(mode, "a") == 0 ||
|
||||
strcmp(mode, "a+") == 0)) {
|
||||
|
@ -668,8 +673,9 @@ bool FSWrapper::IsFileModeAllowed(const char *mode) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool FSWrapper::IsPathToReplace(const std::string_view &path) {
|
||||
return path.starts_with(pPathToReplace);
|
||||
return starts_with_case_insensitive(path, pPathToReplace);
|
||||
}
|
||||
|
||||
std::string FSWrapper::GetNewPath(const std::string_view &path) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "FSWrapperMergeDirsWithParent.h"
|
||||
#include "utils/StringTools.h"
|
||||
#include "utils/logger.h"
|
||||
#include "utils/utils.h"
|
||||
#include <coreinit/cache.h>
|
||||
|
@ -83,7 +84,7 @@ FSError FSWrapperMergeDirsWithParent::FSReadDirWrapper(FSADirectoryHandle handle
|
|||
/**
|
||||
* Read the next entry if this entry starts with deletePrefix. We keep the entry but mark it as deleted.
|
||||
*/
|
||||
if (std::string_view(entry->name).starts_with(deletePrefix)) {
|
||||
if (starts_with_case_insensitive(entry->name, deletePrefix)) {
|
||||
dirHandle->readResult[dirHandle->readResultNumberOfEntries].isMarkedAsDeleted = true;
|
||||
|
||||
OSMemoryBarrier();
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <coreinit/filesystem_fsa.h>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <romfs_dev.h>
|
||||
#include <string>
|
||||
|
||||
struct FSIOThreadData {
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
#include "FileUtils.h"
|
||||
#include "IFSWrapper.h"
|
||||
#include "malloc.h"
|
||||
#include "utils/StringTools.h"
|
||||
#include "utils/logger.h"
|
||||
#include "utils/utils.h"
|
||||
#include <content_redirection/redirection.h>
|
||||
#include <coreinit/dynload.h>
|
||||
#include <mutex>
|
||||
#include <nn/act.h>
|
||||
#include <wums/exports.h>
|
||||
|
||||
struct AOCTitle {
|
||||
|
@ -115,6 +117,15 @@ ContentRedirectionApiErrorType CRAddFSLayer(CRLayerHandle *handle, const char *l
|
|||
} else if (layerType == FS_LAYER_TYPE_SAVE_REPLACE) {
|
||||
DEBUG_FUNCTION_LINE_INFO("Redirecting \"/vol/save\" to \"%s\", mode: \"replace\"", replacementDir);
|
||||
ptr = make_unique_nothrow<FSWrapper>(layerName, "/vol/save", replacementDir, false, true);
|
||||
} else if (layerType == FS_LAYER_TYPE_SAVE_REPLACE_FOR_CURRENT_USER) {
|
||||
nn::act::Initialize();
|
||||
nn::act::PersistentId persistentId = nn::act::GetPersistentId();
|
||||
nn::act::Finalize();
|
||||
|
||||
std::string user = string_format("/vol/save/%08X", 0x80000000 | persistentId);
|
||||
|
||||
DEBUG_FUNCTION_LINE_INFO("Redirecting \"%s\" to \"%s\", mode: \"replace\"", user.c_str(), replacementDir);
|
||||
ptr = make_unique_nothrow<FSWrapper>(layerName, user, replacementDir, false, true);
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("CONTENT_REDIRECTION_API_ERROR_UNKNOWN_LAYER_DIR_TYPE: %s %s %d", layerName, replacementDir, layerType);
|
||||
return CONTENT_REDIRECTION_API_ERROR_UNKNOWN_FS_LAYER_TYPE;
|
||||
|
|
|
@ -10,7 +10,7 @@ WUMS_MODULE_EXPORT_NAME("homebrew_content_redirection");
|
|||
WUMS_USE_WUT_DEVOPTAB();
|
||||
WUMS_DEPENDS_ON(homebrew_functionpatcher);
|
||||
|
||||
#define VERSION "v0.2.5"
|
||||
#define VERSION "v0.2.7"
|
||||
|
||||
DECL_FUNCTION(void, OSCancelThread, OSThread *thread) {
|
||||
if (thread == gThreadData[0].thread || thread == gThreadData[1].thread || thread == gThreadData[2].thread) {
|
||||
|
|
|
@ -11,4 +11,14 @@ std::string string_format(const std::string &format, Args... args) {
|
|||
auto buf = std::make_unique<char[]>(size);
|
||||
std::snprintf(buf.get(), size, format.c_str(), args...);
|
||||
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) {
|
||||
if (str.size() < prefix.size())
|
||||
return false;
|
||||
|
||||
return std::equal(prefix.begin(), prefix.end(), str.begin(),
|
||||
[](char a, char b) {
|
||||
return std::tolower(a) == std::tolower(b);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue