mirror of
https://github.com/wiiu-env/libmocha.git
synced 2026-04-26 16:26:52 -05:00
Sync with wut devoptab
This commit is contained in:
parent
551f88ecff
commit
0b5296b43c
4
.github/workflows/pr.yml
vendored
4
.github/workflows/pr.yml
vendored
|
|
@ -6,7 +6,7 @@ jobs:
|
||||||
clang-format:
|
clang-format:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: clang-format
|
- name: clang-format
|
||||||
run: |
|
run: |
|
||||||
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source ./include
|
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source ./include
|
||||||
|
|
@ -14,7 +14,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: clang-format
|
needs: clang-format
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: build lib
|
- name: build lib
|
||||||
run: |
|
run: |
|
||||||
docker build . -f Dockerfile.buildlocal -t builder
|
docker build . -f Dockerfile.buildlocal -t builder
|
||||||
|
|
|
||||||
2
.github/workflows/push_image.yml
vendored
2
.github/workflows/push_image.yml
vendored
|
|
@ -17,7 +17,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Extract Docker metadata
|
- name: Extract Docker metadata
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v4
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
#include "../logger.h"
|
||||||
#include "mocha/mocha.h"
|
#include "mocha/mocha.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <complex>
|
||||||
#include <coreinit/cache.h>
|
#include <coreinit/cache.h>
|
||||||
#include <coreinit/filesystem_fsa.h>
|
#include <coreinit/filesystem_fsa.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
@ -38,7 +41,7 @@ static const devoptab_t fsa_default_devoptab = {
|
||||||
static bool fsa_initialised = false;
|
static bool fsa_initialised = false;
|
||||||
static FSADeviceData fsa_mounts[0x10];
|
static FSADeviceData fsa_mounts[0x10];
|
||||||
|
|
||||||
static void fsaResetMount(FSADeviceData *mount, uint32_t id) {
|
static void fsaResetMount(FSADeviceData *mount, const uint32_t id) {
|
||||||
*mount = {};
|
*mount = {};
|
||||||
memcpy(&mount->device, &fsa_default_devoptab, sizeof(fsa_default_devoptab));
|
memcpy(&mount->device, &fsa_default_devoptab, sizeof(fsa_default_devoptab));
|
||||||
mount->device.name = mount->name;
|
mount->device.name = mount->name;
|
||||||
|
|
@ -46,17 +49,20 @@ static void fsaResetMount(FSADeviceData *mount, uint32_t id) {
|
||||||
mount->id = id;
|
mount->id = id;
|
||||||
mount->setup = false;
|
mount->setup = false;
|
||||||
mount->mounted = false;
|
mount->mounted = false;
|
||||||
|
mount->isSDCard = false;
|
||||||
mount->clientHandle = -1;
|
mount->clientHandle = -1;
|
||||||
mount->deviceSizeInSectors = 0;
|
mount->deviceSizeInSectors = 0;
|
||||||
mount->deviceSectorSize = 0;
|
mount->deviceSectorSize = 0;
|
||||||
memset(mount->mount_path, 0, sizeof(mount->mount_path));
|
mount->cwd[0] = '/';
|
||||||
|
mount->cwd[1] = '\0';
|
||||||
|
memset(mount->mountPath, 0, sizeof(mount->mountPath));
|
||||||
memset(mount->name, 0, sizeof(mount->name));
|
memset(mount->name, 0, sizeof(mount->name));
|
||||||
DCFlushRange(mount, sizeof(*mount));
|
DCFlushRange(mount, sizeof(*mount));
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsaInit() {
|
void fsaInit() {
|
||||||
if (!fsa_initialised) {
|
if (!fsa_initialised) {
|
||||||
uint32_t total = sizeof(fsa_mounts) / sizeof(fsa_mounts[0]);
|
constexpr uint32_t total = std::size(fsa_mounts);
|
||||||
for (uint32_t i = 0; i < total; i++) {
|
for (uint32_t i = 0; i < total; i++) {
|
||||||
fsaResetMount(&fsa_mounts[i], i);
|
fsaResetMount(&fsa_mounts[i], i);
|
||||||
}
|
}
|
||||||
|
|
@ -67,15 +73,10 @@ void fsaInit() {
|
||||||
std::mutex fsaMutex;
|
std::mutex fsaMutex;
|
||||||
|
|
||||||
FSADeviceData *fsa_alloc() {
|
FSADeviceData *fsa_alloc() {
|
||||||
uint32_t i;
|
|
||||||
uint32_t total = sizeof(fsa_mounts) / sizeof(fsa_mounts[0]);
|
|
||||||
FSADeviceData *mount;
|
|
||||||
|
|
||||||
fsaInit();
|
fsaInit();
|
||||||
|
|
||||||
for (i = 0; i < total; i++) {
|
for (auto &fsa_mount : fsa_mounts) {
|
||||||
mount = &fsa_mounts[i];
|
if (FSADeviceData *mount = &fsa_mount; !mount->setup) {
|
||||||
if (!mount->setup) {
|
|
||||||
return mount;
|
return mount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -86,8 +87,8 @@ FSADeviceData *fsa_alloc() {
|
||||||
static void fsa_free(FSADeviceData *mount) {
|
static void fsa_free(FSADeviceData *mount) {
|
||||||
FSError res;
|
FSError res;
|
||||||
if (mount->mounted) {
|
if (mount->mounted) {
|
||||||
if ((res = FSAUnmount(mount->clientHandle, mount->mount_path, FSA_UNMOUNT_FLAG_FORCE)) < 0) {
|
if ((res = FSAUnmount(mount->clientHandle, mount->mountPath, FSA_UNMOUNT_FLAG_FORCE)) < 0) {
|
||||||
DEBUG_FUNCTION_LINE_WARN("FSAUnmount %s for %s failed: %s", mount->mount_path, mount->name, FSAGetStatusStr(res));
|
DEBUG_FUNCTION_LINE_WARN("FSAUnmount %s for %s failed: %s", mount->mountPath, mount->name, FSAGetStatusStr(res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res = FSADelClient(mount->clientHandle);
|
res = FSADelClient(mount->clientHandle);
|
||||||
|
|
@ -101,18 +102,17 @@ MochaUtilsStatus Mocha_UnmountFS(const char *virt_name) {
|
||||||
if (!virt_name) {
|
if (!virt_name) {
|
||||||
return MOCHA_RESULT_INVALID_ARGUMENT;
|
return MOCHA_RESULT_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
std::lock_guard<std::mutex> lock(fsaMutex);
|
std::lock_guard lock(fsaMutex);
|
||||||
uint32_t total = sizeof(fsa_mounts) / sizeof(fsa_mounts[0]);
|
|
||||||
|
|
||||||
fsaInit();
|
fsaInit();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < total; i++) {
|
for (auto &fsa_mount : fsa_mounts) {
|
||||||
FSADeviceData *mount = &fsa_mounts[i];
|
FSADeviceData *mount = &fsa_mount;
|
||||||
if (!mount->setup) {
|
if (!mount->setup) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (strcmp(mount->name, virt_name) == 0) {
|
if (strcmp(mount->name, virt_name) == 0) {
|
||||||
std::string removeName = std::string(mount->name).append(":");
|
const std::string removeName = std::string(mount->name).append(":");
|
||||||
RemoveDevice(removeName.c_str());
|
RemoveDevice(removeName.c_str());
|
||||||
fsa_free(mount);
|
fsa_free(mount);
|
||||||
return MOCHA_RESULT_SUCCESS;
|
return MOCHA_RESULT_SUCCESS;
|
||||||
|
|
@ -129,6 +129,9 @@ MochaUtilsStatus Mocha_MountFS(const char *virt_name, const char *dev_path, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
MochaUtilsStatus Mocha_MountFSEx(const char *virt_name, const char *dev_path, const char *mount_path, FSAMountFlags mountFlags, void *mountArgBuf, int mountArgBufLen) {
|
MochaUtilsStatus Mocha_MountFSEx(const char *virt_name, const char *dev_path, const char *mount_path, FSAMountFlags mountFlags, void *mountArgBuf, int mountArgBufLen) {
|
||||||
|
if (virt_name == nullptr || mount_path == nullptr) {
|
||||||
|
return MOCHA_RESULT_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
if (!mochaInitDone) {
|
if (!mochaInitDone) {
|
||||||
if (Mocha_InitLibrary() != MOCHA_RESULT_SUCCESS) {
|
if (Mocha_InitLibrary() != MOCHA_RESULT_SUCCESS) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Mocha_InitLibrary failed");
|
DEBUG_FUNCTION_LINE_ERR("Mocha_InitLibrary failed");
|
||||||
|
|
@ -137,7 +140,7 @@ MochaUtilsStatus Mocha_MountFSEx(const char *virt_name, const char *dev_path, co
|
||||||
}
|
}
|
||||||
|
|
||||||
FSAInit();
|
FSAInit();
|
||||||
std::lock_guard<std::mutex> lock(fsaMutex);
|
std::lock_guard lock(fsaMutex);
|
||||||
|
|
||||||
FSADeviceData *mount = fsa_alloc();
|
FSADeviceData *mount = fsa_alloc();
|
||||||
if (mount == nullptr) {
|
if (mount == nullptr) {
|
||||||
|
|
@ -146,6 +149,23 @@ MochaUtilsStatus Mocha_MountFSEx(const char *virt_name, const char *dev_path, co
|
||||||
return MOCHA_RESULT_MAX_CLIENT;
|
return MOCHA_RESULT_MAX_CLIENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make sure the paths are normalized
|
||||||
|
std::string normalizedMountPath(mount_path);
|
||||||
|
std::ranges::replace(normalizedMountPath, '\\', '/');
|
||||||
|
while (!normalizedMountPath.empty() && (normalizedMountPath.ends_with("/"))) {
|
||||||
|
normalizedMountPath.pop_back();
|
||||||
|
}
|
||||||
|
std::string normalizedDevPath(dev_path ? dev_path : "");
|
||||||
|
std::ranges::replace(normalizedDevPath, '\\', '/');
|
||||||
|
while (!normalizedDevPath.empty() && (normalizedDevPath.ends_with("/"))) {
|
||||||
|
normalizedDevPath.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Things like statvfs behave different on sd cards!
|
||||||
|
if (normalizedDevPath.starts_with("/dev/sdcard01") || normalizedMountPath.starts_with("/vol/external01")) {
|
||||||
|
mount->isSDCard = true;
|
||||||
|
}
|
||||||
|
|
||||||
mount->clientHandle = FSAAddClient(nullptr);
|
mount->clientHandle = FSAAddClient(nullptr);
|
||||||
if (mount->clientHandle < 0) {
|
if (mount->clientHandle < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAAddClient() failed: %s", FSAGetStatusStr(static_cast<FSError>(mount->clientHandle)));
|
DEBUG_FUNCTION_LINE_ERR("FSAAddClient() failed: %s", FSAGetStatusStr(static_cast<FSError>(mount->clientHandle)));
|
||||||
|
|
@ -162,12 +182,12 @@ MochaUtilsStatus Mocha_MountFSEx(const char *virt_name, const char *dev_path, co
|
||||||
mount->mounted = false;
|
mount->mounted = false;
|
||||||
|
|
||||||
strncpy(mount->name, virt_name, sizeof(mount->name) - 1);
|
strncpy(mount->name, virt_name, sizeof(mount->name) - 1);
|
||||||
strncpy(mount->mount_path, mount_path, sizeof(mount->mount_path) - 1);
|
strncpy(mount->mountPath, normalizedMountPath.c_str(), sizeof(mount->mountPath) - 1);
|
||||||
FSError res;
|
FSError res;
|
||||||
if (dev_path) {
|
if (!normalizedDevPath.empty()) {
|
||||||
res = FSAMount(mount->clientHandle, dev_path, mount_path, mountFlags, mountArgBuf, mountArgBufLen);
|
res = FSAMount(mount->clientHandle, normalizedDevPath.c_str(), normalizedMountPath.c_str(), mountFlags, mountArgBuf, mountArgBufLen);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAMount(0x%08X, %s, %s, %08X, %p, %08X) failed: %s", mount->clientHandle, dev_path, mount_path, mountFlags, mountArgBuf, mountArgBufLen, FSAGetStatusStr(res));
|
DEBUG_FUNCTION_LINE_ERR("FSAMount(0x%08X, %s, %s, %08X, %p, %08X) failed: %s", mount->clientHandle, normalizedDevPath.c_str(), normalizedMountPath.c_str(), mountFlags, mountArgBuf, mountArgBufLen, FSAGetStatusStr(res));
|
||||||
fsa_free(mount);
|
fsa_free(mount);
|
||||||
if (res == FS_ERROR_ALREADY_EXISTS) {
|
if (res == FS_ERROR_ALREADY_EXISTS) {
|
||||||
return MOCHA_RESULT_ALREADY_EXISTS;
|
return MOCHA_RESULT_ALREADY_EXISTS;
|
||||||
|
|
@ -179,18 +199,20 @@ MochaUtilsStatus Mocha_MountFSEx(const char *virt_name, const char *dev_path, co
|
||||||
mount->mounted = false;
|
mount->mounted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = FSAChangeDir(mount->clientHandle, mount->mount_path)) < 0) {
|
if ((res = FSAChangeDir(mount->clientHandle, mount->mountPath)) < 0) {
|
||||||
DEBUG_FUNCTION_LINE_WARN("FSAChangeDir(0x%08X, %s) failed: %s", mount->clientHandle, mount->mount_path, FSAGetStatusStr(res));
|
DEBUG_FUNCTION_LINE_WARN("FSAChangeDir(0x%08X, %s) failed: %s", mount->clientHandle, mount->mountPath, FSAGetStatusStr(res));
|
||||||
|
} else {
|
||||||
|
strncpy(mount->cwd, normalizedMountPath.c_str(), sizeof(mount->mountPath) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSADeviceInfo deviceInfo;
|
FSADeviceInfo deviceInfo;
|
||||||
if ((res = FSAGetDeviceInfo(mount->clientHandle, mount_path, &deviceInfo)) >= 0) {
|
if ((res = FSAGetDeviceInfo(mount->clientHandle, normalizedMountPath.c_str(), &deviceInfo)) >= 0) {
|
||||||
mount->deviceSizeInSectors = deviceInfo.deviceSizeInSectors;
|
mount->deviceSizeInSectors = deviceInfo.deviceSizeInSectors;
|
||||||
mount->deviceSectorSize = deviceInfo.deviceSectorSize;
|
mount->deviceSectorSize = deviceInfo.deviceSectorSize;
|
||||||
} else {
|
} else {
|
||||||
mount->deviceSizeInSectors = 0xFFFFFFFF;
|
mount->deviceSizeInSectors = 0xFFFFFFFF;
|
||||||
mount->deviceSectorSize = 512;
|
mount->deviceSectorSize = 512;
|
||||||
DEBUG_FUNCTION_LINE_WARN("Failed to get DeviceInfo for %s: %s", mount_path, FSAGetStatusStr(res));
|
DEBUG_FUNCTION_LINE_WARN("Failed to get DeviceInfo for %s: %s", normalizedMountPath.c_str(), FSAGetStatusStr(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AddDevice(&mount->device) < 0) {
|
if (AddDevice(&mount->device) < 0) {
|
||||||
|
|
|
||||||
|
|
@ -13,23 +13,24 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
typedef struct FSADeviceData {
|
typedef struct FSADeviceData {
|
||||||
devoptab_t device{};
|
devoptab_t device;
|
||||||
bool setup{};
|
bool setup;
|
||||||
bool mounted{};
|
bool mounted;
|
||||||
|
bool isSDCard;
|
||||||
uint32_t id{};
|
uint32_t id{};
|
||||||
char name[32]{};
|
char name[32];
|
||||||
char mount_path[256]{};
|
char mountPath[0x80];
|
||||||
FSAClientHandle clientHandle{};
|
char cwd[FS_MAX_PATH + 1];
|
||||||
uint64_t deviceSizeInSectors{};
|
FSAClientHandle clientHandle;
|
||||||
uint32_t deviceSectorSize{};
|
uint64_t deviceSizeInSectors;
|
||||||
} FSADeviceData;
|
uint32_t deviceSectorSize;
|
||||||
|
} __fsa_device_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open file struct
|
* Open file struct
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
//! FSA file handle
|
||||||
//! FS handle
|
|
||||||
FSAFileHandle fd;
|
FSAFileHandle fd;
|
||||||
|
|
||||||
//! Flags used in open(2)
|
//! Flags used in open(2)
|
||||||
|
|
@ -38,7 +39,7 @@ typedef struct
|
||||||
//! Current file offset
|
//! Current file offset
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
|
|
||||||
//! Path stored for internal path tracking
|
//! Current file path
|
||||||
char fullPath[FS_MAX_PATH + 1];
|
char fullPath[FS_MAX_PATH + 1];
|
||||||
|
|
||||||
//! Guard file access
|
//! Guard file access
|
||||||
|
|
@ -52,17 +53,17 @@ typedef struct
|
||||||
* Open directory struct
|
* Open directory struct
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
//! Should be set to FS_DIRITER_MAGIC
|
//! Should be set to FSA_DIRITER_MAGIC
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
|
|
||||||
//! FS handle
|
//! FS directory handle
|
||||||
FSADirectoryHandle fd;
|
FSADirectoryHandle fd;
|
||||||
|
|
||||||
//! Temporary storage for reading entries
|
//! Temporary storage for reading entries
|
||||||
FSADirectoryEntry entry_data;
|
FSADirectoryEntry entry_data;
|
||||||
|
|
||||||
//! Current file path
|
//! Current directory path
|
||||||
char name[FS_MAX_PATH + 1];
|
char fullPath[FS_MAX_PATH + 1];
|
||||||
|
|
||||||
//! Guard dir access
|
//! Guard dir access
|
||||||
MutexWrapper mutex;
|
MutexWrapper mutex;
|
||||||
|
|
@ -105,13 +106,20 @@ int __fsa_fchmod(struct _reent *r, void *fd, mode_t mode);
|
||||||
int __fsa_rmdir(struct _reent *r, const char *name);
|
int __fsa_rmdir(struct _reent *r, const char *name);
|
||||||
int __fsa_utimes(struct _reent *r, const char *filename, const struct timeval times[2]);
|
int __fsa_utimes(struct _reent *r, const char *filename, const struct timeval times[2]);
|
||||||
|
|
||||||
// devoptab_fs_utils.c
|
// devoptab_fsa_utils.c
|
||||||
char *__fsa_fixpath(struct _reent *r, const char *path);
|
char *__fsa_fixpath(struct _reent *r, const char *path);
|
||||||
int __fsa_translate_error(FSError error);
|
int __fsa_translate_error(FSError error);
|
||||||
|
mode_t __fsa_translate_stat_mode(FSStat *fsStat);
|
||||||
|
void __fsa_translate_stat(FSAClientHandle handle, FSStat *fsStat, ino_t ino, struct stat *posStat);
|
||||||
|
uint32_t __fsa_hashstring(const char *str);
|
||||||
|
|
||||||
|
static inline FSMode
|
||||||
|
__fsa_translate_permission_mode(mode_t mode) {
|
||||||
|
// Convert normal Unix octal permission bits into CafeOS hexadecimal permission bits
|
||||||
|
return (FSMode) (((mode & S_IRWXU) << 2) | ((mode & S_IRWXG) << 1) | (mode & S_IRWXO));
|
||||||
|
}
|
||||||
|
|
||||||
time_t __fsa_translate_time(FSTime timeValue);
|
time_t __fsa_translate_time(FSTime timeValue);
|
||||||
FSMode __fsa_translate_permission_mode(mode_t mode);
|
|
||||||
mode_t __fsa_translate_stat_mode(FSAStat *fileStat);
|
|
||||||
void __fsa_translate_stat(FSAStat *fsStat, struct stat *posStat);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
int __fsa_chdir(struct _reent *r,
|
int __fsa_chdir(struct _reent *r,
|
||||||
const char *path) {
|
const char *path) {
|
||||||
FSError status;
|
|
||||||
|
|
||||||
if (!path) {
|
if (!path) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -16,15 +14,27 @@ int __fsa_chdir(struct _reent *r,
|
||||||
r->_errno = ENOMEM;
|
r->_errno = ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const auto deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
status = FSAChangeDir(deviceData->clientHandle, fixedPath);
|
const FSError status = FSAChangeDir(deviceData->clientHandle, fixedPath);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAChangeDir(0x%08X, %s) failed: %s", deviceData->clientHandle, fixedPath, FSAGetStatusStr(status));
|
DEBUG_FUNCTION_LINE_ERR("FSAChangeDir(0x%08X, %s) failed: %s", deviceData->clientHandle, fixedPath, FSAGetStatusStr(status));
|
||||||
free(fixedPath);
|
free(fixedPath);
|
||||||
r->_errno = __fsa_translate_error(status);
|
r->_errno = __fsa_translate_error(status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove trailing '/'
|
||||||
|
if (fixedPath[0] != '\0') {
|
||||||
|
if (fixedPath[strlen(fixedPath) - 1] == '/') {
|
||||||
|
fixedPath[strlen(fixedPath) - 1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snprintf(deviceData->cwd, sizeof(deviceData->cwd), "%s", fixedPath) >= static_cast<int>(sizeof(deviceData->cwd))) {
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("__wut_fsa_chdir: snprintf result was truncated");
|
||||||
|
}
|
||||||
|
|
||||||
free(fixedPath);
|
free(fixedPath);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
int __fsa_chmod(struct _reent *r,
|
int __fsa_chmod(struct _reent *r,
|
||||||
const char *path,
|
const char *path,
|
||||||
mode_t mode) {
|
mode_t mode) {
|
||||||
FSError status;
|
|
||||||
|
|
||||||
if (!path) {
|
if (!path) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -19,13 +17,14 @@ int __fsa_chmod(struct _reent *r,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
FSMode translatedMode = __fsa_translate_permission_mode(mode);
|
const FSMode translatedMode = __fsa_translate_permission_mode(mode);
|
||||||
|
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const __fsa_device_t *deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
status = FSAChangeMode(deviceData->clientHandle, fixedPath, translatedMode);
|
const FSError status = FSAChangeMode(deviceData->clientHandle, fixedPath, translatedMode);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAChangeMode(0x%08X, %s, 0x%X) failed: %s", deviceData->clientHandle, fixedPath, translatedMode, FSAGetStatusStr(status));
|
DEBUG_FUNCTION_LINE_ERR("FSAChangeMode(0x%08X, %s, 0x%X) failed: %s",
|
||||||
|
deviceData->clientHandle, fixedPath, translatedMode, FSAGetStatusStr(status));
|
||||||
free(fixedPath);
|
free(fixedPath);
|
||||||
r->_errno = __fsa_translate_error(status);
|
r->_errno = __fsa_translate_error(status);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,24 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
int __fsa_close(struct _reent *r,
|
int __fsa_close(struct _reent *r,
|
||||||
void *fd) {
|
void *fd) {
|
||||||
FSError status;
|
|
||||||
__fsa_file_t *file;
|
|
||||||
|
|
||||||
if (!fd) {
|
if (!fd) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
file = (__fsa_file_t *) fd;
|
const auto file = static_cast<__fsa_file_t *>(fd);
|
||||||
|
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const auto deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
std::lock_guard<MutexWrapper> lock(file->mutex);
|
std::scoped_lock lock(file->mutex);
|
||||||
|
|
||||||
status = FSACloseFile(deviceData->clientHandle, file->fd);
|
const FSError status = FSACloseFile(deviceData->clientHandle, file->fd);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSACloseFile(0x%08X, 0x%08X) failed: %s", deviceData->clientHandle, file->fd, FSAGetStatusStr(status));
|
DEBUG_FUNCTION_LINE_ERR("FSACloseFile(0x%08X, 0x%08X) (%s) failed: %s",
|
||||||
|
deviceData->clientHandle, file->fd, file->fullPath, FSAGetStatusStr(status));
|
||||||
r->_errno = __fsa_translate_error(status);
|
r->_errno = __fsa_translate_error(status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,25 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
int __fsa_dirclose(struct _reent *r,
|
int __fsa_dirclose(struct _reent *r,
|
||||||
DIR_ITER *dirState) {
|
DIR_ITER *dirState) {
|
||||||
FSError status;
|
|
||||||
|
|
||||||
if (!dirState) {
|
if (!dirState) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *dir = (__fsa_dir_t *) (dirState->dirStruct);
|
auto *dir = static_cast<__fsa_dir_t *>(dirState->dirStruct);
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
|
||||||
|
|
||||||
std::lock_guard<MutexWrapper> lock(dir->mutex);
|
const auto deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
status = FSACloseDir(deviceData->clientHandle, dir->fd);
|
std::scoped_lock lock(dir->mutex);
|
||||||
|
|
||||||
|
const FSError status = FSACloseDir(deviceData->clientHandle, dir->fd);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSACloseDir(0x%08X, 0x%08X) (%s) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSACloseDir(0x%08X, 0x%08X) (%s) failed: %s",
|
||||||
deviceData->clientHandle, dir->fd, dir->name, FSAGetStatusStr(status));
|
deviceData->clientHandle, dir->fd, dir->fullPath, FSAGetStatusStr(status));
|
||||||
r->_errno = __fsa_translate_error(status);
|
r->_errno = __fsa_translate_error(status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
|
@ -7,33 +7,46 @@ int __fsa_dirnext(struct _reent *r,
|
||||||
DIR_ITER *dirState,
|
DIR_ITER *dirState,
|
||||||
char *filename,
|
char *filename,
|
||||||
struct stat *filestat) {
|
struct stat *filestat) {
|
||||||
FSError status;
|
|
||||||
|
|
||||||
if (!dirState || !filename || !filestat) {
|
if (!dirState || !filename || !filestat) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const auto deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
auto *dir = (__fsa_dir_t *) (dirState->dirStruct);
|
const auto dir = static_cast<__fsa_dir_t *>(dirState->dirStruct);
|
||||||
|
|
||||||
std::lock_guard<MutexWrapper> lock(dir->mutex);
|
std::scoped_lock lock(dir->mutex);
|
||||||
memset(&dir->entry_data, 0, sizeof(dir->entry_data));
|
memset(&dir->entry_data, 0, sizeof(dir->entry_data));
|
||||||
|
|
||||||
status = FSAReadDir(deviceData->clientHandle, dir->fd, &dir->entry_data);
|
const auto status = FSAReadDir(deviceData->clientHandle, dir->fd, &dir->entry_data);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
if (status != FS_ERROR_END_OF_DIR) {
|
if (status != FS_ERROR_END_OF_DIR) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAReadDir(0x%08X, 0x%08X, %p) (%s) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSAReadDir(0x%08X, 0x%08X, %p) (%s) failed: %s",
|
||||||
deviceData->clientHandle, dir->fd, &dir->entry_data, dir->name, FSAGetStatusStr(status));
|
deviceData->clientHandle, dir->fd, &dir->entry_data, dir->fullPath, FSAGetStatusStr(status));
|
||||||
}
|
}
|
||||||
r->_errno = __fsa_translate_error(status);
|
r->_errno = __fsa_translate_error(status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
__fsa_translate_stat(&dir->entry_data.info, filestat);
|
ino_t ino;
|
||||||
|
size_t fullLen = strlen(dir->fullPath) + 1 + strlen(dir->entry_data.name) + 1;
|
||||||
|
char *fullStr = (char *) memalign(0x40, fullLen);
|
||||||
|
if (fullStr) {
|
||||||
|
if (snprintf(fullStr, fullLen, "%s/%s", dir->fullPath, dir->entry_data.name) >= (int) fullLen) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("__fsa_dirnext: snprintf fullStr result was truncated");
|
||||||
|
}
|
||||||
|
ino = __fsa_hashstring(fullStr);
|
||||||
|
free(fullStr);
|
||||||
|
} else {
|
||||||
|
ino = 0;
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("__fsa_dirnext: Failed to allocate memory for fullStr. st_ino will be set to 0");
|
||||||
|
}
|
||||||
|
__fsa_translate_stat(deviceData->clientHandle, &dir->entry_data.info, ino, filestat);
|
||||||
|
|
||||||
if (snprintf(filename, NAME_MAX, "%s", dir->entry_data.name) >= NAME_MAX) {
|
if (snprintf(filename, NAME_MAX, "%s", dir->entry_data.name) >= NAME_MAX) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("snprintf filename result was truncated\n");
|
DEBUG_FUNCTION_LINE_ERR("__fsa_dirnext: snprintf filename result was truncated");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
DIR_ITER *
|
DIR_ITER *
|
||||||
|
|
@ -7,7 +7,6 @@ __fsa_diropen(struct _reent *r,
|
||||||
DIR_ITER *dirState,
|
DIR_ITER *dirState,
|
||||||
const char *path) {
|
const char *path) {
|
||||||
FSADirectoryHandle fd;
|
FSADirectoryHandle fd;
|
||||||
FSError status;
|
|
||||||
|
|
||||||
if (!dirState || !path) {
|
if (!dirState || !path) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
|
|
@ -18,18 +17,29 @@ __fsa_diropen(struct _reent *r,
|
||||||
if (!fixedPath) {
|
if (!fixedPath) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto *dir = (__fsa_dir_t *) (dirState->dirStruct);
|
const auto dir = static_cast<__fsa_dir_t *>(dirState->dirStruct);
|
||||||
strncpy(dir->name, fixedPath, sizeof(dir->name) - 1);
|
const auto deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
|
// Remove trailing '/'
|
||||||
|
if (fixedPath[0] != '\0') {
|
||||||
|
if (fixedPath[strlen(fixedPath) - 1] == '/') {
|
||||||
|
fixedPath[strlen(fixedPath) - 1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snprintf(dir->fullPath, sizeof(dir->fullPath), "%s", fixedPath) >= (int) sizeof(dir->fullPath)) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("__fsa_diropen: snprintf result was truncated");
|
||||||
|
}
|
||||||
|
|
||||||
free(fixedPath);
|
free(fixedPath);
|
||||||
|
|
||||||
dir->mutex.init(dir->name);
|
dir->mutex.init(dir->fullPath);
|
||||||
std::lock_guard<MutexWrapper> lock(dir->mutex);
|
std::scoped_lock lock(dir->mutex);
|
||||||
|
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const FSError status = FSAOpenDir(deviceData->clientHandle, dir->fullPath, &fd);
|
||||||
status = FSAOpenDir(deviceData->clientHandle, dir->name, &fd);
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAOpenDir(0x%08X, %s, %p) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSAOpenDir(0x%08X, %s, %p) failed: %s",
|
||||||
deviceData->clientHandle, dir->name, &fd, FSAGetStatusStr(status));
|
deviceData->clientHandle, dir->fullPath, &fd, FSAGetStatusStr(status));
|
||||||
r->_errno = __fsa_translate_error(status);
|
r->_errno = __fsa_translate_error(status);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,24 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
int __fsa_dirreset(struct _reent *r,
|
int __fsa_dirreset(struct _reent *r,
|
||||||
DIR_ITER *dirState) {
|
DIR_ITER *dirState) {
|
||||||
FSError status;
|
|
||||||
|
|
||||||
if (!dirState) {
|
if (!dirState) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *dir = (__fsa_dir_t *) (dirState->dirStruct);
|
const auto dir = static_cast<__fsa_dir_t *>(dirState->dirStruct);
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const auto *deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
std::lock_guard<MutexWrapper> lock(dir->mutex);
|
std::scoped_lock lock(dir->mutex);
|
||||||
|
|
||||||
status = FSARewindDir(deviceData->clientHandle, dir->fd);
|
const FSError status = FSARewindDir(deviceData->clientHandle, dir->fd);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSARewindDir(0x%08X, 0x%08X) (%s) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSARewindDir(0x%08X, 0x%08X) (%s) failed: %s",
|
||||||
deviceData->clientHandle, dir->fd, dir->name, FSAGetStatusStr(status));
|
deviceData->clientHandle, dir->fd, dir->fullPath, FSAGetStatusStr(status));
|
||||||
r->_errno = __fsa_translate_error(status);
|
r->_errno = __fsa_translate_error(status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
int __fsa_fchmod(struct _reent *r,
|
int __fsa_fchmod(struct _reent *r,
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
int __fsa_fstat(struct _reent *r,
|
int __fsa_fstat(struct _reent *r,
|
||||||
void *fd,
|
void *fd,
|
||||||
struct stat *st) {
|
struct stat *st) {
|
||||||
FSError status;
|
|
||||||
FSAStat fsStat;
|
FSAStat fsStat;
|
||||||
|
|
||||||
if (!fd || !st) {
|
if (!fd || !st) {
|
||||||
|
|
@ -13,20 +12,22 @@ int __fsa_fstat(struct _reent *r,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *file = (__fsa_file_t *) fd;
|
const auto file = static_cast<__fsa_file_t *>(fd);
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const auto *deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
std::lock_guard<MutexWrapper> lock(file->mutex);
|
std::scoped_lock lock(file->mutex);
|
||||||
|
|
||||||
status = FSAGetStatFile(deviceData->clientHandle, file->fd, &fsStat);
|
const FSError status = FSAGetStatFile(deviceData->clientHandle, file->fd, &fsStat);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAGetStatFile(0x%08X, 0x%08X, %p) (%s) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSAGetStatFile(0x%08X, 0x%08X, %p) (%s) failed: %s",
|
||||||
deviceData->clientHandle, file->fd, &fsStat, file->fullPath, FSAGetStatusStr(status));
|
deviceData->clientHandle, file->fd, &fsStat,
|
||||||
|
file->fullPath, FSAGetStatusStr(status));
|
||||||
r->_errno = __fsa_translate_error(status);
|
r->_errno = __fsa_translate_error(status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
__fsa_translate_stat(&fsStat, st);
|
const ino_t ino = __fsa_hashstring(file->fullPath);
|
||||||
|
__fsa_translate_stat(deviceData->clientHandle, &fsStat, ino, st);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,20 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
int __fsa_fsync(struct _reent *r,
|
int __fsa_fsync(struct _reent *r,
|
||||||
void *fd) {
|
void *fd) {
|
||||||
FSError status;
|
|
||||||
|
|
||||||
if (!fd) {
|
if (!fd) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *file = (__fsa_file_t *) fd;
|
auto *file = static_cast<__fsa_file_t *>(fd);
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const auto *deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
std::lock_guard<MutexWrapper> lock(file->mutex);
|
std::scoped_lock lock(file->mutex);
|
||||||
|
|
||||||
status = FSAFlushFile(deviceData->clientHandle, file->fd);
|
const FSError status = FSAFlushFile(deviceData->clientHandle, file->fd);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAFlushFile(0x%08X, 0x%08X) (%s) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSAFlushFile(0x%08X, 0x%08X) (%s) failed: %s",
|
||||||
deviceData->clientHandle, file->fd, file->fullPath, FSAGetStatusStr(status));
|
deviceData->clientHandle, file->fd, file->fullPath, FSAGetStatusStr(status));
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,26 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
int __fsa_mkdir(struct _reent *r,
|
int __fsa_mkdir(struct _reent *r,
|
||||||
const char *path,
|
const char *path,
|
||||||
int mode) {
|
int mode) {
|
||||||
FSError status;
|
|
||||||
char *fixedPath;
|
|
||||||
|
|
||||||
if (!path) {
|
if (!path) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fixedPath = __fsa_fixpath(r, path);
|
char *fixedPath = __fsa_fixpath(r, path);
|
||||||
if (!fixedPath) {
|
if (!fixedPath) {
|
||||||
r->_errno = ENOMEM;
|
r->_errno = ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
auto *deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
FSMode translatedMode = __fsa_translate_permission_mode(mode);
|
const FSMode translatedMode = __fsa_translate_permission_mode(mode);
|
||||||
|
|
||||||
status = FSAMakeDir(deviceData->clientHandle, fixedPath, translatedMode);
|
const FSError status = FSAMakeDir(deviceData->clientHandle, fixedPath, translatedMode);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAMakeDir(0x%08X, %s, 0x%X) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSAMakeDir(0x%08X, %s, 0x%X) failed: %s",
|
||||||
deviceData->clientHandle, fixedPath, translatedMode, FSAGetStatusStr(status));
|
deviceData->clientHandle, fixedPath, translatedMode, FSAGetStatusStr(status));
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
// Extended "magic" value that allows opening files with FS_OPEN_FLAG_UNENCRYPTED in underlying FSOpenFileEx() call similar to O_DIRECTORY
|
// Extended "magic" value that allows opening files with FS_OPEN_FLAG_UNENCRYPTED in underlying FSOpenFileEx() call similar to O_DIRECTORY
|
||||||
|
|
@ -33,6 +33,12 @@ int __fsa_open(struct _reent *r,
|
||||||
fsMode = "w";
|
fsMode = "w";
|
||||||
} else if (((flags & O_ACCMODE) == O_RDWR) && ((flags & commonFlagMask) == (O_CREAT | O_TRUNC))) {
|
} else if (((flags & O_ACCMODE) == O_RDWR) && ((flags & commonFlagMask) == (O_CREAT | O_TRUNC))) {
|
||||||
fsMode = "w+";
|
fsMode = "w+";
|
||||||
|
} else if (((flags & O_ACCMODE) == O_WRONLY) && ((flags & commonFlagMask) == O_CREAT) && (flags & O_EXCL) == O_EXCL) {
|
||||||
|
// if O_EXCL is set, we don't need O_TRUNC
|
||||||
|
fsMode = "w";
|
||||||
|
} else if (((flags & O_ACCMODE) == O_RDWR) && ((flags & commonFlagMask) == O_CREAT) && (flags & O_EXCL) == O_EXCL) {
|
||||||
|
// if O_EXCL is set, we don't need O_TRUNC
|
||||||
|
fsMode = "w+";
|
||||||
} else if (((flags & O_ACCMODE) == O_WRONLY) && ((flags & commonFlagMask) == (O_CREAT | O_APPEND))) {
|
} else if (((flags & O_ACCMODE) == O_WRONLY) && ((flags & commonFlagMask) == (O_CREAT | O_APPEND))) {
|
||||||
fsMode = "a";
|
fsMode = "a";
|
||||||
} else if (((flags & O_ACCMODE) == O_RDWR) && ((flags & commonFlagMask) == (O_CREAT | O_APPEND))) {
|
} else if (((flags & O_ACCMODE) == O_RDWR) && ((flags & commonFlagMask) == (O_CREAT | O_APPEND))) {
|
||||||
|
|
@ -43,6 +49,10 @@ int __fsa_open(struct _reent *r,
|
||||||
// It's not possible to open a file with write only mode which doesn't truncate the file
|
// It's not possible to open a file with write only mode which doesn't truncate the file
|
||||||
// Technically we could read from the file, but our read implementation is blocking this.
|
// Technically we could read from the file, but our read implementation is blocking this.
|
||||||
fsMode = "r+";
|
fsMode = "r+";
|
||||||
|
} else if (((flags & O_ACCMODE) == O_RDWR) && ((flags & commonFlagMask) == (O_CREAT))) {
|
||||||
|
// Cafe OS doesn't have a matching mode for this, so we have to be creative and create the file.
|
||||||
|
createFileIfNotFound = true;
|
||||||
|
fsMode = "r+";
|
||||||
} else if (((flags & O_ACCMODE) == O_WRONLY) && ((flags & commonFlagMask) == (O_APPEND))) {
|
} else if (((flags & O_ACCMODE) == O_WRONLY) && ((flags & commonFlagMask) == (O_APPEND))) {
|
||||||
// Cafe OS doesn't have a matching mode for this, so we have to check if the file exists.
|
// Cafe OS doesn't have a matching mode for this, so we have to check if the file exists.
|
||||||
failIfFileNotFound = true;
|
failIfFileNotFound = true;
|
||||||
|
|
@ -62,8 +72,13 @@ int __fsa_open(struct _reent *r,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *file = (__fsa_file_t *) fileStruct;
|
|
||||||
strncpy(file->fullPath, fixedPath, sizeof(file->fullPath) - 1);
|
auto *file = static_cast<__fsa_file_t *>(fileStruct);
|
||||||
|
const auto deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
|
if (snprintf(file->fullPath, sizeof(file->fullPath), "%s", fixedPath) >= (int) sizeof(file->fullPath)) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("__fsa_open: snprintf result was truncated");
|
||||||
|
}
|
||||||
free(fixedPath);
|
free(fixedPath);
|
||||||
|
|
||||||
// Prepare flags
|
// Prepare flags
|
||||||
|
|
@ -73,9 +88,7 @@ int __fsa_open(struct _reent *r,
|
||||||
|
|
||||||
// Init mutex and lock
|
// Init mutex and lock
|
||||||
file->mutex.init(file->fullPath);
|
file->mutex.init(file->fullPath);
|
||||||
std::lock_guard<MutexWrapper> lock(file->mutex);
|
std::scoped_lock lock(file->mutex);
|
||||||
|
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
|
||||||
|
|
||||||
if (createFileIfNotFound || failIfFileNotFound || (flags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) {
|
if (createFileIfNotFound || failIfFileNotFound || (flags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) {
|
||||||
// Check if file exists
|
// Check if file exists
|
||||||
|
|
@ -113,9 +126,11 @@ int __fsa_open(struct _reent *r,
|
||||||
|
|
||||||
status = FSAOpenFileEx(deviceData->clientHandle, file->fullPath, fsMode, translatedMode, openFlags, preAllocSize, &fd);
|
status = FSAOpenFileEx(deviceData->clientHandle, file->fullPath, fsMode, translatedMode, openFlags, preAllocSize, &fd);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAOpenFileEx(0x%08X, %s, %s, 0x%X, 0x%08X, 0x%08X, %p) failed: %s",
|
if (status != FS_ERROR_NOT_FOUND) {
|
||||||
deviceData->clientHandle, file->fullPath, fsMode, translatedMode, openFlags, preAllocSize, &fd,
|
DEBUG_FUNCTION_LINE_ERR("FSAOpenFileEx(0x%08X, %s, %s, 0x%X, 0x%08X, 0x%08X, %p) failed: %s",
|
||||||
FSAGetStatusStr(status));
|
deviceData->clientHandle, file->fullPath, fsMode, translatedMode, openFlags, preAllocSize, &fd,
|
||||||
|
FSAGetStatusStr(status));
|
||||||
|
}
|
||||||
r->_errno = __fsa_translate_error(status);
|
r->_errno = __fsa_translate_error(status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,17 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
ssize_t __fsa_read(struct _reent *r, void *fd, char *ptr, size_t len) {
|
ssize_t __fsa_read(struct _reent *r, void *fd, char *ptr, size_t len) {
|
||||||
FSError status;
|
|
||||||
if (!fd || !ptr) {
|
if (!fd || !ptr) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the file was opened with read access
|
// Check that the file was opened with read access
|
||||||
auto *file = (__fsa_file_t *) fd;
|
const auto file = static_cast<__fsa_file_t *>(fd);
|
||||||
if ((file->flags & O_ACCMODE) == O_WRONLY) {
|
if ((file->flags & O_ACCMODE) == O_WRONLY) {
|
||||||
r->_errno = EBADF;
|
r->_errno = EBADF;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -21,9 +20,9 @@ ssize_t __fsa_read(struct _reent *r, void *fd, char *ptr, size_t len) {
|
||||||
// cache-aligned, cache-line-sized
|
// cache-aligned, cache-line-sized
|
||||||
__attribute__((aligned(0x40))) uint8_t alignedBuffer[0x40];
|
__attribute__((aligned(0x40))) uint8_t alignedBuffer[0x40];
|
||||||
|
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const auto deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
std::lock_guard<MutexWrapper> lock(file->mutex);
|
std::scoped_lock lock(file->mutex);
|
||||||
|
|
||||||
size_t bytesRead = 0;
|
size_t bytesRead = 0;
|
||||||
while (bytesRead < len) {
|
while (bytesRead < len) {
|
||||||
|
|
@ -32,13 +31,13 @@ ssize_t __fsa_read(struct _reent *r, void *fd, char *ptr, size_t len) {
|
||||||
uint8_t *tmp = (uint8_t *) ptr;
|
uint8_t *tmp = (uint8_t *) ptr;
|
||||||
size_t size = len - bytesRead;
|
size_t size = len - bytesRead;
|
||||||
|
|
||||||
if ((uintptr_t) ptr & 0x3F) {
|
if (size < 0x40) {
|
||||||
|
// read partial cache-line back-end
|
||||||
|
tmp = alignedBuffer;
|
||||||
|
} else if ((uintptr_t) ptr & 0x3F) {
|
||||||
// read partial cache-line front-end
|
// read partial cache-line front-end
|
||||||
tmp = alignedBuffer;
|
tmp = alignedBuffer;
|
||||||
size = MIN(size, 0x40 - ((uintptr_t) ptr & 0x3F));
|
size = MIN(size, 0x40 - ((uintptr_t) ptr & 0x3F));
|
||||||
} else if (size < 0x40) {
|
|
||||||
// read partial cache-line back-end
|
|
||||||
tmp = alignedBuffer;
|
|
||||||
} else {
|
} else {
|
||||||
// read whole cache lines
|
// read whole cache lines
|
||||||
size &= ~0x3F;
|
size &= ~0x3F;
|
||||||
|
|
@ -49,11 +48,12 @@ ssize_t __fsa_read(struct _reent *r, void *fd, char *ptr, size_t len) {
|
||||||
size = 0x100000;
|
size = 0x100000;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = FSAReadFile(deviceData->clientHandle, tmp, 1, size, file->fd, 0);
|
const FSError status = FSAReadFile(deviceData->clientHandle, tmp, 1, size, file->fd, 0);
|
||||||
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAReadFile(0x%08X, %p, 1, 0x%08X, 0x%08X, 0) (%s) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSAReadFile(0x%08X, %p, 1, 0x%08X, 0x%08X, 0) (%s) failed: %s",
|
||||||
deviceData->clientHandle, tmp, size, file->fd, file->fullPath, FSAGetStatusStr(status));
|
deviceData->clientHandle, tmp, size, file->fd, file->fullPath, FSAGetStatusStr(status));
|
||||||
|
|
||||||
if (bytesRead != 0) {
|
if (bytesRead != 0) {
|
||||||
return bytesRead; // error after partial read
|
return bytesRead; // error after partial read
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,31 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
int __fsa_rename(struct _reent *r,
|
int __fsa_rename(struct _reent *r,
|
||||||
const char *oldName,
|
const char *oldName,
|
||||||
const char *newName) {
|
const char *newName) {
|
||||||
FSError status;
|
|
||||||
char *fixedOldPath, *fixedNewPath;
|
|
||||||
|
|
||||||
if (!oldName || !newName) {
|
if (!oldName || !newName) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fixedOldPath = __fsa_fixpath(r, oldName);
|
char *fixedOldPath = __fsa_fixpath(r, oldName);
|
||||||
if (!fixedOldPath) {
|
if (!fixedOldPath) {
|
||||||
r->_errno = ENOMEM;
|
r->_errno = ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fixedNewPath = __fsa_fixpath(r, newName);
|
char *fixedNewPath = __fsa_fixpath(r, newName);
|
||||||
if (!fixedNewPath) {
|
if (!fixedNewPath) {
|
||||||
free(fixedOldPath);
|
free(fixedOldPath);
|
||||||
r->_errno = ENOMEM;
|
r->_errno = ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const auto deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
status = FSARename(deviceData->clientHandle, fixedOldPath, fixedNewPath);
|
const FSError status = FSARename(deviceData->clientHandle, fixedOldPath, fixedNewPath);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSARename(0x%08X, %s, %s) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSARename(0x%08X, %s, %s) failed: %s",
|
||||||
deviceData->clientHandle, fixedOldPath, fixedNewPath, FSAGetStatusStr(status));
|
deviceData->clientHandle, fixedOldPath, fixedNewPath, FSAGetStatusStr(status));
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
int __fsa_rmdir(struct _reent *r,
|
int __fsa_rmdir(struct _reent *r,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
FSError status;
|
|
||||||
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -17,14 +15,14 @@ int __fsa_rmdir(struct _reent *r,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const auto *deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
status = FSARemove(deviceData->clientHandle, fixedPath);
|
const FSError status = FSARemove(deviceData->clientHandle, fixedPath);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSARemove(0x%08X, %s) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSARemove(0x%08X, %s) failed: %s",
|
||||||
deviceData->clientHandle, fixedPath, FSAGetStatusStr(status));
|
deviceData->clientHandle, fixedPath, FSAGetStatusStr(status));
|
||||||
free(fixedPath);
|
free(fixedPath);
|
||||||
r->_errno = status == FS_ERROR_ALREADY_EXISTS ? ENOTEMPTY : __fsa_translate_error(status);
|
r->_errno = __fsa_translate_error(status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
off_t __fsa_seek(struct _reent *r,
|
off_t __fsa_seek(struct _reent *r,
|
||||||
|
|
@ -15,10 +15,11 @@ off_t __fsa_seek(struct _reent *r,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *file = (__fsa_file_t *) fd;
|
const auto file = static_cast<__fsa_file_t *>(fd);
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
|
||||||
|
|
||||||
std::lock_guard<MutexWrapper> lock(file->mutex);
|
const auto deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
|
std::scoped_lock lock(file->mutex);
|
||||||
|
|
||||||
// Find the offset to see from
|
// Find the offset to see from
|
||||||
switch (whence) {
|
switch (whence) {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
int __fsa_stat(struct _reent *r,
|
int __fsa_stat(struct _reent *r,
|
||||||
const char *path,
|
const char *path,
|
||||||
struct stat *st) {
|
struct stat *st) {
|
||||||
FSError status;
|
|
||||||
FSAStat fsStat;
|
FSAStat fsStat;
|
||||||
|
|
||||||
if (!path || !st) {
|
if (!path || !st) {
|
||||||
|
|
@ -19,18 +18,22 @@ int __fsa_stat(struct _reent *r,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const auto deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
status = FSAGetStat(deviceData->clientHandle, fixedPath, &fsStat);
|
const FSError status = FSAGetStat(deviceData->clientHandle, fixedPath, &fsStat);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAGetStat(0x%08X, %s, %p) failed: %s",
|
if (status != FS_ERROR_NOT_FOUND) {
|
||||||
deviceData->clientHandle, fixedPath, &fsStat, FSAGetStatusStr(status));
|
DEBUG_FUNCTION_LINE_ERR("FSAGetStat(0x%08X, %s, %p) failed: %s",
|
||||||
|
deviceData->clientHandle, fixedPath, &fsStat, FSAGetStatusStr(status));
|
||||||
|
}
|
||||||
free(fixedPath);
|
free(fixedPath);
|
||||||
r->_errno = __fsa_translate_error(status);
|
r->_errno = __fsa_translate_error(status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
const ino_t ino = __fsa_hashstring(fixedPath);
|
||||||
free(fixedPath);
|
free(fixedPath);
|
||||||
|
|
||||||
__fsa_translate_stat(&fsStat, st);
|
__fsa_translate_stat(deviceData->clientHandle, &fsStat, ino, st);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,17 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
int __fsa_statvfs(struct _reent *r,
|
int __fsa_statvfs(struct _reent *r,
|
||||||
const char *path,
|
const char *path,
|
||||||
struct statvfs *buf) {
|
struct statvfs *buf) {
|
||||||
FSError status;
|
|
||||||
uint64_t freeSpace;
|
uint64_t freeSpace;
|
||||||
|
|
||||||
|
const auto *deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
if (deviceData->isSDCard) {
|
||||||
|
r->_errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
memset(buf, 0, sizeof(struct statvfs));
|
memset(buf, 0, sizeof(struct statvfs));
|
||||||
|
|
||||||
char *fixedPath = __fsa_fixpath(r, path);
|
char *fixedPath = __fsa_fixpath(r, path);
|
||||||
|
|
@ -16,9 +20,7 @@ int __fsa_statvfs(struct _reent *r,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const FSError status = FSAGetFreeSpaceSize(deviceData->clientHandle, fixedPath, &freeSpace);
|
||||||
|
|
||||||
status = FSAGetFreeSpaceSize(deviceData->clientHandle, fixedPath, &freeSpace);
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAGetFreeSpaceSize(0x%08X, %s, %p) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSAGetFreeSpaceSize(0x%08X, %s, %p) failed: %s",
|
||||||
deviceData->clientHandle, fixedPath, &freeSpace, FSAGetStatusStr(status));
|
deviceData->clientHandle, fixedPath, &freeSpace, FSAGetStatusStr(status));
|
||||||
|
|
@ -48,4 +50,4 @@ int __fsa_statvfs(struct _reent *r,
|
||||||
buf->f_namemax = 255;
|
buf->f_namemax = 255;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
int __fsa_ftruncate(struct _reent *r,
|
int __fsa_ftruncate(struct _reent *r,
|
||||||
void *fd,
|
void *fd,
|
||||||
off_t len) {
|
off_t len) {
|
||||||
FSError status;
|
|
||||||
|
|
||||||
// Make sure length is non-negative
|
// Make sure length is non-negative
|
||||||
if (!fd || len < 0) {
|
if (!fd || len < 0) {
|
||||||
|
|
@ -13,13 +12,13 @@ int __fsa_ftruncate(struct _reent *r,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *file = (__fsa_file_t *) fd;
|
auto *file = static_cast<__fsa_file_t *>(fd);
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const auto *deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
std::lock_guard<MutexWrapper> lock(file->mutex);
|
std::scoped_lock lock(file->mutex);
|
||||||
|
|
||||||
// Set the new file size
|
// Set the new file size
|
||||||
status = FSASetPosFile(deviceData->clientHandle, file->fd, len);
|
FSError status = FSASetPosFile(deviceData->clientHandle, file->fd, len);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSASetPosFile(0x%08X, 0x%08X, 0x%08llX) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSASetPosFile(0x%08X, 0x%08X, 0x%08llX) failed: %s",
|
||||||
deviceData->clientHandle, file->fd, len, FSAGetStatusStr(status));
|
deviceData->clientHandle, file->fd, len, FSAGetStatusStr(status));
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,23 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
int __fsa_unlink(struct _reent *r,
|
int __fsa_unlink(struct _reent *r,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
FSError status;
|
|
||||||
char *fixedPath;
|
|
||||||
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fixedPath = __fsa_fixpath(r, name);
|
char *fixedPath = __fsa_fixpath(r, name);
|
||||||
if (!fixedPath) {
|
if (!fixedPath) {
|
||||||
r->_errno = ENOMEM;
|
r->_errno = ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const auto *deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
status = FSARemove(deviceData->clientHandle, fixedPath);
|
const FSError status = FSARemove(deviceData->clientHandle, fixedPath);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSARemove(0x%08X, %s) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSARemove(0x%08X, %s) failed: %s",
|
||||||
deviceData->clientHandle, fixedPath, FSAGetStatusStr(status));
|
deviceData->clientHandle, fixedPath, FSAGetStatusStr(status));
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,90 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#define COMP_MAX 50
|
||||||
|
|
||||||
|
#define ispathsep(ch) ((ch) == '/' || (ch) == '\\')
|
||||||
|
#define iseos(ch) ((ch) == '\0')
|
||||||
|
#define ispathend(ch) (ispathsep(ch) || iseos(ch))
|
||||||
|
|
||||||
|
// https://gist.github.com/starwing/2761647
|
||||||
|
static char *
|
||||||
|
__fsa_normpath(char *out, const char *in) {
|
||||||
|
char *pos[COMP_MAX], **top = pos, *head = out;
|
||||||
|
int isabs = ispathsep(*in);
|
||||||
|
|
||||||
|
if (isabs) *out++ = '/';
|
||||||
|
*top++ = out;
|
||||||
|
|
||||||
|
while (!iseos(*in)) {
|
||||||
|
while (ispathsep(*in)) {
|
||||||
|
++in;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iseos(*in)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(in, ".", 1) == 0 && ispathend(in[1])) {
|
||||||
|
++in;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(in, "..", 2) == 0 && ispathend(in[2])) {
|
||||||
|
in += 2;
|
||||||
|
if (top != pos + 1) {
|
||||||
|
out = *--top;
|
||||||
|
} else if (isabs) {
|
||||||
|
out = top[-1];
|
||||||
|
} else {
|
||||||
|
strcpy(out, "../");
|
||||||
|
out += 3;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (top - pos >= COMP_MAX) {
|
||||||
|
return NULL; // path to complicate
|
||||||
|
}
|
||||||
|
|
||||||
|
*top++ = out;
|
||||||
|
while (!ispathend(*in)) {
|
||||||
|
*out++ = *in++;
|
||||||
|
}
|
||||||
|
if (ispathsep(*in)) {
|
||||||
|
*out++ = '/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = '\0';
|
||||||
|
if (*head == '\0') {
|
||||||
|
strcpy(head, "./");
|
||||||
|
}
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
__fsa_hashstring(const char *str) {
|
||||||
|
uint32_t h;
|
||||||
|
uint8_t *p;
|
||||||
|
|
||||||
|
h = 0;
|
||||||
|
for (p = (uint8_t *) str; *p != '\0'; p++) {
|
||||||
|
h = 37 * h + *p;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
__fsa_fixpath(struct _reent *r,
|
__fsa_fixpath(struct _reent *r,
|
||||||
const char *path) {
|
const char *path) {
|
||||||
char *p;
|
char *p;
|
||||||
char *fixedPath;
|
|
||||||
|
|
||||||
if (!path) {
|
if (!path) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return nullptr;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = strchr(path, ':') + 1;
|
p = strchr(path, ':') + 1;
|
||||||
|
|
@ -16,63 +92,95 @@ __fsa_fixpath(struct _reent *r,
|
||||||
p = (char *) path;
|
p = (char *) path;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t pathLength = strlen(p);
|
|
||||||
if (pathLength > FS_MAX_PATH) {
|
|
||||||
r->_errno = ENAMETOOLONG;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// wii u softlocks on empty strings so give expected error back
|
// wii u softlocks on empty strings so give expected error back
|
||||||
if (pathLength == 0) {
|
if (strlen(p) == 0) {
|
||||||
r->_errno = ENOENT;
|
r->_errno = ENOENT;
|
||||||
return nullptr;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fixedPath = static_cast<char *>(memalign(0x40, FS_MAX_PATH + 1));
|
int maxPathLength = PATH_MAX;
|
||||||
|
auto fixedPath = static_cast<char *>(memalign(0x40, maxPathLength));
|
||||||
if (!fixedPath) {
|
if (!fixedPath) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("__fsa_fixpath: failed to allocate memory for fixedPath");
|
||||||
r->_errno = ENOMEM;
|
r->_errno = ENOMEM;
|
||||||
return nullptr;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p[0] == '/') {
|
// Convert to an absolute path
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
if (p[0] != '\0' && p[0] != '\\' && p[0] != '/') {
|
||||||
strcpy(fixedPath, deviceData->mount_path);
|
__fsa_device_t *deviceData = (__fsa_device_t *) r->deviceData;
|
||||||
strcat(fixedPath, p);
|
if (snprintf(fixedPath, maxPathLength, "%s/%s", deviceData->cwd, p) >= maxPathLength) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("__fsa_fixpath: fixedPath snprintf result (relative) was truncated");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
strcpy(fixedPath, p);
|
const auto deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
if (snprintf(fixedPath, maxPathLength, "%s%s", deviceData->mountPath, p) >= maxPathLength) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("__fsa_fixpath: fixedPath snprintf result (absolute) was truncated");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize path (resolve any ".", "..", or "//")
|
||||||
|
char *normalizedPath = strdup(fixedPath);
|
||||||
|
if (!normalizedPath) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("__fsa_fixpath: failed to allocate memory for normalizedPath");
|
||||||
|
free(fixedPath);
|
||||||
|
r->_errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *resPath = __fsa_normpath(normalizedPath, fixedPath);
|
||||||
|
if (!resPath) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("__fsa_fixpath: failed to normalize path");
|
||||||
|
free(normalizedPath);
|
||||||
|
free(fixedPath);
|
||||||
|
r->_errno = EIO;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snprintf(fixedPath, maxPathLength, "%s", resPath) >= maxPathLength) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("__fsa_fixpath: fixedPath snprintf result (relative) was truncated");
|
||||||
|
}
|
||||||
|
|
||||||
|
free(normalizedPath);
|
||||||
|
|
||||||
|
size_t pathLength = strlen(fixedPath);
|
||||||
|
if (pathLength > FS_MAX_PATH) {
|
||||||
|
free(fixedPath);
|
||||||
|
r->_errno = ENAMETOOLONG;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fixedPath;
|
return fixedPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
mode_t __fsa_translate_stat_mode(FSAStat *fileStat) {
|
mode_t __fsa_translate_stat_mode(FSStat *fsStat) {
|
||||||
mode_t retMode = 0;
|
mode_t retMode = 0;
|
||||||
|
|
||||||
if ((fileStat->flags & FS_STAT_LINK) == FS_STAT_LINK) {
|
if ((fsStat->flags & FS_STAT_LINK) == FS_STAT_LINK) {
|
||||||
retMode |= S_IFLNK;
|
retMode |= S_IFLNK;
|
||||||
} else if ((fileStat->flags & FS_STAT_DIRECTORY) == FS_STAT_DIRECTORY) {
|
} else if ((fsStat->flags & FS_STAT_DIRECTORY) == FS_STAT_DIRECTORY) {
|
||||||
retMode |= S_IFDIR;
|
retMode |= S_IFDIR;
|
||||||
} else if ((fileStat->flags & FS_STAT_FILE) == FS_STAT_FILE) {
|
} else if ((fsStat->flags & FS_STAT_FILE) == FS_STAT_FILE) {
|
||||||
retMode |= S_IFREG;
|
retMode |= S_IFREG;
|
||||||
} else if (fileStat->size == 0) {
|
} else if (fsStat->size == 0) {
|
||||||
// Mounted paths like /vol/external01 have no flags set.
|
// Mounted paths like /vol/external01 have no flags set.
|
||||||
// If no flag is set and the size is 0, it's a (root) dir
|
// If no flag is set and the size is 0, it's a (root) dir
|
||||||
retMode |= S_IFDIR;
|
retMode |= S_IFDIR;
|
||||||
} else if (fileStat->size > 0) {
|
} else if (fsStat->size > 0) {
|
||||||
// Some regular Wii U files have no type info but will have a size
|
// Some regular Wii U files have no type info but will have a size
|
||||||
retMode |= S_IFREG;
|
retMode |= S_IFREG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert normal CafeOS hexadecimal permission bits into Unix octal permission bits
|
// Convert normal CafeOS hexadecimal permission bits into Unix octal permission bits
|
||||||
mode_t permissionMode = (((fileStat->mode >> 2) & S_IRWXU) | ((fileStat->mode >> 1) & S_IRWXG) | (fileStat->mode & S_IRWXO));
|
mode_t permissionMode = (((fsStat->mode >> 2) & S_IRWXU) | ((fsStat->mode >> 1) & S_IRWXG) | (fsStat->mode & S_IRWXO));
|
||||||
|
|
||||||
return retMode | permissionMode;
|
return retMode | permissionMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __fsa_translate_stat(FSAStat *fsStat, struct stat *posStat) {
|
void __fsa_translate_stat(FSAClientHandle clientHandle, FSStat *fsStat, ino_t ino, struct stat *posStat) {
|
||||||
memset(posStat, 0, sizeof(struct stat));
|
memset(posStat, 0, sizeof(struct stat));
|
||||||
posStat->st_dev = (dev_t) nullptr;
|
posStat->st_dev = (dev_t) clientHandle;
|
||||||
posStat->st_ino = fsStat->entryId;
|
posStat->st_ino = ino;
|
||||||
posStat->st_mode = __fsa_translate_stat_mode(fsStat);
|
posStat->st_mode = __fsa_translate_stat_mode(fsStat);
|
||||||
posStat->st_nlink = 1;
|
posStat->st_nlink = 1;
|
||||||
posStat->st_uid = fsStat->owner;
|
posStat->st_uid = fsStat->owner;
|
||||||
|
|
@ -106,11 +214,6 @@ time_t __fsa_translate_time(FSTime timeValue) {
|
||||||
return (timeValue / 1000000) + EPOCH_DIFF_SECS(WIIU_FSTIME_EPOCH_YEAR);
|
return (timeValue / 1000000) + EPOCH_DIFF_SECS(WIIU_FSTIME_EPOCH_YEAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSMode __fsa_translate_permission_mode(mode_t mode) {
|
|
||||||
// Convert normal Unix octal permission bits into CafeOS hexadecimal permission bits
|
|
||||||
return (FSMode) (((mode & S_IRWXU) << 2) | ((mode & S_IRWXG) << 1) | (mode & S_IRWXO));
|
|
||||||
}
|
|
||||||
|
|
||||||
int __fsa_translate_error(FSError error) {
|
int __fsa_translate_error(FSError error) {
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case FS_ERROR_END_OF_DIR:
|
case FS_ERROR_END_OF_DIR:
|
||||||
|
|
@ -139,56 +242,46 @@ int __fsa_translate_error(FSError error) {
|
||||||
case FS_ERROR_NOT_FILE:
|
case FS_ERROR_NOT_FILE:
|
||||||
return EISDIR;
|
return EISDIR;
|
||||||
case FS_ERROR_OUT_OF_RANGE:
|
case FS_ERROR_OUT_OF_RANGE:
|
||||||
return ESPIPE;
|
return EINVAL;
|
||||||
case FS_ERROR_UNSUPPORTED_COMMAND:
|
case FS_ERROR_UNSUPPORTED_COMMAND:
|
||||||
return ENOTSUP;
|
return ENOTSUP;
|
||||||
case FS_ERROR_WRITE_PROTECTED:
|
case FS_ERROR_WRITE_PROTECTED:
|
||||||
return EROFS;
|
return EROFS;
|
||||||
case FS_ERROR_NOT_INIT:
|
case FS_ERROR_NOT_INIT:
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
// TODO
|
|
||||||
case FS_ERROR_MAX_MOUNT_POINTS:
|
case FS_ERROR_MAX_MOUNT_POINTS:
|
||||||
break;
|
|
||||||
case FS_ERROR_MAX_VOLUMES:
|
case FS_ERROR_MAX_VOLUMES:
|
||||||
break;
|
|
||||||
case FS_ERROR_MAX_CLIENTS:
|
case FS_ERROR_MAX_CLIENTS:
|
||||||
break;
|
|
||||||
case FS_ERROR_MAX_FILES:
|
case FS_ERROR_MAX_FILES:
|
||||||
break;
|
|
||||||
case FS_ERROR_MAX_DIRS:
|
case FS_ERROR_MAX_DIRS:
|
||||||
break;
|
return EMFILE;
|
||||||
case FS_ERROR_ALREADY_OPEN:
|
case FS_ERROR_ALREADY_OPEN:
|
||||||
break;
|
return EBUSY;
|
||||||
case FS_ERROR_NOT_EMPTY:
|
case FS_ERROR_NOT_EMPTY:
|
||||||
break;
|
return ENOTEMPTY;
|
||||||
case FS_ERROR_ACCESS_ERROR:
|
case FS_ERROR_ACCESS_ERROR:
|
||||||
break;
|
return EACCES;
|
||||||
case FS_ERROR_DATA_CORRUPTED:
|
case FS_ERROR_DATA_CORRUPTED:
|
||||||
break;
|
return EILSEQ;
|
||||||
case FS_ERROR_JOURNAL_FULL:
|
case FS_ERROR_JOURNAL_FULL:
|
||||||
break;
|
return EBUSY;
|
||||||
case FS_ERROR_UNAVAILABLE_COMMAND:
|
case FS_ERROR_UNAVAILABLE_COMMAND:
|
||||||
break;
|
return EBUSY;
|
||||||
case FS_ERROR_INVALID_PARAM:
|
case FS_ERROR_INVALID_PARAM:
|
||||||
break;
|
return EBUSY;
|
||||||
case FS_ERROR_INVALID_BUFFER:
|
case FS_ERROR_INVALID_BUFFER:
|
||||||
break;
|
|
||||||
case FS_ERROR_INVALID_ALIGNMENT:
|
case FS_ERROR_INVALID_ALIGNMENT:
|
||||||
break;
|
|
||||||
case FS_ERROR_INVALID_CLIENTHANDLE:
|
case FS_ERROR_INVALID_CLIENTHANDLE:
|
||||||
break;
|
|
||||||
case FS_ERROR_INVALID_FILEHANDLE:
|
case FS_ERROR_INVALID_FILEHANDLE:
|
||||||
break;
|
|
||||||
case FS_ERROR_INVALID_DIRHANDLE:
|
case FS_ERROR_INVALID_DIRHANDLE:
|
||||||
break;
|
return EINVAL;
|
||||||
case FS_ERROR_OUT_OF_RESOURCES:
|
case FS_ERROR_OUT_OF_RESOURCES:
|
||||||
break;
|
return ENOMEM;
|
||||||
case FS_ERROR_MEDIA_NOT_READY:
|
case FS_ERROR_MEDIA_NOT_READY:
|
||||||
break;
|
return EIO;
|
||||||
case FS_ERROR_INVALID_MEDIA:
|
case FS_ERROR_INVALID_MEDIA:
|
||||||
break;
|
return EIO;
|
||||||
default:
|
default:
|
||||||
break;
|
return EIO;
|
||||||
}
|
}
|
||||||
return (int) EIO;
|
}
|
||||||
}
|
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
|
#include "../logger.h"
|
||||||
#include "devoptab_fsa.h"
|
#include "devoptab_fsa.h"
|
||||||
#include "logger.h"
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
ssize_t __fsa_write(struct _reent *r, void *fd, const char *ptr, size_t len) {
|
ssize_t __fsa_write(struct _reent *r, void *fd, const char *ptr, size_t len) {
|
||||||
FSError status;
|
|
||||||
|
|
||||||
if (!fd || !ptr) {
|
if (!fd || !ptr) {
|
||||||
r->_errno = EINVAL;
|
r->_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the file was opened with write access
|
// Check that the file was opened with write access
|
||||||
auto *file = (__fsa_file_t *) fd;
|
auto *file = static_cast<__fsa_file_t *>(fd);
|
||||||
if ((file->flags & O_ACCMODE) == O_RDONLY) {
|
if ((file->flags & O_ACCMODE) == O_RDONLY) {
|
||||||
r->_errno = EBADF;
|
r->_errno = EBADF;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -20,9 +18,9 @@ ssize_t __fsa_write(struct _reent *r, void *fd, const char *ptr, size_t len) {
|
||||||
// cache-aligned, cache-line-sized
|
// cache-aligned, cache-line-sized
|
||||||
__attribute__((aligned(0x40))) uint8_t alignedBuffer[0x40];
|
__attribute__((aligned(0x40))) uint8_t alignedBuffer[0x40];
|
||||||
|
|
||||||
auto *deviceData = (FSADeviceData *) r->deviceData;
|
const auto deviceData = static_cast<__fsa_device_t *>(r->deviceData);
|
||||||
|
|
||||||
std::lock_guard<MutexWrapper> lock(file->mutex);
|
std::scoped_lock lock(file->mutex);
|
||||||
|
|
||||||
// If O_APPEND is set, we always write to the end of the file.
|
// If O_APPEND is set, we always write to the end of the file.
|
||||||
// When writing we file->offset to the file size to keep in sync.
|
// When writing we file->offset to the file size to keep in sync.
|
||||||
|
|
@ -37,13 +35,13 @@ ssize_t __fsa_write(struct _reent *r, void *fd, const char *ptr, size_t len) {
|
||||||
uint8_t *tmp = (uint8_t *) ptr;
|
uint8_t *tmp = (uint8_t *) ptr;
|
||||||
size_t size = len - bytesWritten;
|
size_t size = len - bytesWritten;
|
||||||
|
|
||||||
if ((uintptr_t) ptr & 0x3F) {
|
if (size < 0x40) {
|
||||||
|
// write partial cache-line back-end
|
||||||
|
tmp = alignedBuffer;
|
||||||
|
} else if ((uintptr_t) ptr & 0x3F) {
|
||||||
// write partial cache-line front-end
|
// write partial cache-line front-end
|
||||||
tmp = alignedBuffer;
|
tmp = alignedBuffer;
|
||||||
size = MIN(size, 0x40 - ((uintptr_t) ptr & 0x3F));
|
size = MIN(size, 0x40 - ((uintptr_t) ptr & 0x3F));
|
||||||
} else if (size < 0x40) {
|
|
||||||
// write partial cache-line back-end
|
|
||||||
tmp = alignedBuffer;
|
|
||||||
} else {
|
} else {
|
||||||
// write whole cache lines
|
// write whole cache lines
|
||||||
size &= ~0x3F;
|
size &= ~0x3F;
|
||||||
|
|
@ -58,7 +56,7 @@ ssize_t __fsa_write(struct _reent *r, void *fd, const char *ptr, size_t len) {
|
||||||
memcpy(tmp, ptr, size);
|
memcpy(tmp, ptr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = FSAWriteFile(deviceData->clientHandle, tmp, 1, size, file->fd, 0);
|
const FSError status = FSAWriteFile(deviceData->clientHandle, tmp, 1, size, file->fd, 0);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("FSAWriteFile(0x%08X, %p, 1, 0x%08X, 0x%08X, 0) (%s) failed: %s",
|
DEBUG_FUNCTION_LINE_ERR("FSAWriteFile(0x%08X, %p, 1, 0x%08X, 0x%08X, 0) (%s) failed: %s",
|
||||||
deviceData->clientHandle, tmp, size, file->fd, file->fullPath, FSAGetStatusStr(status));
|
deviceData->clientHandle, tmp, size, file->fd, file->fullPath, FSAGetStatusStr(status));
|
||||||
|
|
|
||||||
|
|
@ -104,10 +104,10 @@ FSError FSAEx_RawReadEx(int clientHandle, void *data, uint32_t size_bytes, uint3
|
||||||
if ((uint32_t) data & 0x3F) {
|
if ((uint32_t) data & 0x3F) {
|
||||||
auto *alignedBuffer = memalign(0x40, ROUNDUP(size_bytes * cnt, 0x40));
|
auto *alignedBuffer = memalign(0x40, ROUNDUP(size_bytes * cnt, 0x40));
|
||||||
if (!alignedBuffer) {
|
if (!alignedBuffer) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Buffer not aligned (%p).\n", data);
|
DEBUG_FUNCTION_LINE_ERR("Buffer not aligned (%p).", data);
|
||||||
return FS_ERROR_INVALID_ALIGNMENT;
|
return FS_ERROR_INVALID_ALIGNMENT;
|
||||||
}
|
}
|
||||||
DEBUG_FUNCTION_LINE_WARN("Buffer not aligned (%p). Align to 0x40 for best performance\n", data);
|
DEBUG_FUNCTION_LINE_WARN("Buffer not aligned (%p). Align to 0x40 for best performance", data);
|
||||||
tmp = alignedBuffer;
|
tmp = alignedBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user