diff --git a/include/wut.h b/include/wut.h index 4bce60353..b66fea3ca 100644 --- a/include/wut.h +++ b/include/wut.h @@ -9,6 +9,9 @@ #include "wut_structsize.h" #include "wut_types.h" #include "wut_rplwrap.h" +#ifdef DEBUG +#include +#endif #ifdef __GNUC__ @@ -19,3 +22,9 @@ #define WUT_DEPRECATED(reason) #endif //__GNUC__ + +#ifdef DEBUG +#define WUT_DEBUG_REPORT(fmt, ...) OSReport(fmt, ##__VA_ARGS__) +#else +#define WUT_DEBUG_REPORT(fmt, ...) +#endif \ No newline at end of file diff --git a/libraries/wutdevoptab/MutexWrapper.h b/libraries/wutdevoptab/MutexWrapper.h new file mode 100644 index 000000000..b814c077a --- /dev/null +++ b/libraries/wutdevoptab/MutexWrapper.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include "coreinit/cache.h" + +class MutexWrapper { +public: + MutexWrapper() = default; + + void init(const char *name) { + OSInitMutexEx(&mutex, name); + } + + void lock() { + OSLockMutex(&mutex); + } + + void unlock() { + OSUnlockMutex(&mutex); + } + +private: + OSMutex mutex{}; +}; diff --git a/libraries/wutdevoptab/devoptab_fsa.cpp b/libraries/wutdevoptab/devoptab_fsa.cpp index 395ad2f9c..15198bfe1 100644 --- a/libraries/wutdevoptab/devoptab_fsa.cpp +++ b/libraries/wutdevoptab/devoptab_fsa.cpp @@ -1,130 +1,120 @@ #include "devoptab_fsa.h" +#include static devoptab_t -__wut_fs_devoptab = -{ - .name = "fs", - .structSize = sizeof(__wut_fs_file_t), - .open_r = __wut_fs_open, - .close_r = __wut_fs_close, - .write_r = __wut_fs_write, - .read_r = __wut_fs_read, - .seek_r = __wut_fs_seek, - .fstat_r = __wut_fs_fstat, - .stat_r = __wut_fs_stat, - .link_r = __wut_fs_link, - .unlink_r = __wut_fs_unlink, - .chdir_r = __wut_fs_chdir, - .rename_r = __wut_fs_rename, - .mkdir_r = __wut_fs_mkdir, - .dirStateSize = sizeof(__wut_fs_dir_t), - .diropen_r = __wut_fs_diropen, - .dirreset_r = __wut_fs_dirreset, - .dirnext_r = __wut_fs_dirnext, - .dirclose_r = __wut_fs_dirclose, - .statvfs_r = __wut_fs_statvfs, - .ftruncate_r = __wut_fs_ftruncate, - .fsync_r = __wut_fs_fsync, - .lstat_r = __wut_fs_stat, - .deviceData = NULL, - .chmod_r = __wut_fs_chmod, - .fchmod_r = __wut_fs_fchmod, - .rmdir_r = __wut_fs_rmdir, - .utimes_r = __wut_fs_utimes, -}; - -FSClient * -__wut_devoptab_fs_client = NULL; - -static BOOL -__wut_fs_initialised = FALSE; - -static BOOL -__wut_sd_mounted = FALSE; - -static char -sMountPath[0x80]; - -FSStatus -__init_wut_devoptab() -{ - FSStatus rc = 0; - - if (__wut_fs_initialised) { - return rc; + __wut_fsa_devoptab = + { + .name = "fs", + .structSize = sizeof(__wut_fsa_file_t), + .open_r = __wut_fsa_open, + .close_r = __wut_fsa_close, + .write_r = __wut_fsa_write, + .read_r = __wut_fsa_read, + .seek_r = __wut_fsa_seek, + .fstat_r = __wut_fsa_fstat, + .stat_r = __wut_fsa_stat, + .unlink_r = __wut_fsa_unlink, + .chdir_r = __wut_fsa_chdir, + .rename_r = __wut_fsa_rename, + .mkdir_r = __wut_fsa_mkdir, + .dirStateSize = sizeof(__wut_fsa_dir_t), + .diropen_r = __wut_fsa_diropen, + .dirreset_r = __wut_fsa_dirreset, + .dirnext_r = __wut_fsa_dirnext, + .dirclose_r = __wut_fsa_dirclose, + .statvfs_r = __wut_fsa_statvfs, + .ftruncate_r = __wut_fsa_ftruncate, + .fsync_r = __wut_fsa_fsync, + .deviceData = nullptr, + .chmod_r = __wut_fsa_chmod, + .rmdir_r = __wut_fsa_rmdir, + .lstat_r = __wut_fsa_stat, + }; + + +__wut_fsa_device_t __wut_fsa_device_data = {}; + +FSError __init_wut_devoptab() { + FSError rc; + + if (__wut_fsa_device_data.setup) { + return FS_ERROR_OK; } - __wut_devoptab_fs_client = memalign(0x20, sizeof(FSClient)); - FSCmdBlock fsCmd; - FSMountSource mountSource; - char workDir[0x83]; - - FSInit(); - rc = FSAddClient(__wut_devoptab_fs_client, -1); - - if (rc < 0) { - free(__wut_devoptab_fs_client); - return rc; + __wut_fsa_device_data = {}; + memcpy(&__wut_fsa_device_data.device, &__wut_fsa_devoptab, sizeof(__wut_fsa_devoptab)); + __wut_fsa_device_data.device.deviceData = &__wut_fsa_device_data; + snprintf(__wut_fsa_device_data.name, sizeof(__wut_fsa_device_data.name), "fs"); + __wut_fsa_device_data.device.name = __wut_fsa_device_data.name; + __wut_fsa_device_data.setup = false; + __wut_fsa_device_data.mounted = false; + __wut_fsa_device_data.isSDCard = false; + + FSAInit(); + __wut_fsa_device_data.clientHandle = FSAAddClient(nullptr); + if (__wut_fsa_device_data.clientHandle == 0) { + WUT_DEBUG_REPORT("FSAAddClient() failed"); + return FS_ERROR_MAX_CLIENTS; } - FSInitCmdBlock(&fsCmd); + int dev = AddDevice(&__wut_fsa_device_data.device); - if (rc >= 0) { - int dev = AddDevice(&__wut_fs_devoptab); + if (dev != -1) { + setDefaultDevice(dev); + __wut_fsa_device_data.setup = true; + snprintf(__wut_fsa_device_data.mountPath, sizeof(__wut_fsa_device_data.mountPath), "/vol/external01"); - if(dev != -1) { - setDefaultDevice(dev); - __wut_fs_initialised = TRUE; + rc = FSAMount(__wut_fsa_device_data.clientHandle, "/dev/sdcard01", __wut_fsa_device_data.mountPath, (FSAMountFlags) 0, nullptr, 0); - // Mount the SD card - rc = FSGetMountSource(__wut_devoptab_fs_client, &fsCmd, FS_MOUNT_SOURCE_SD, &mountSource, -1); - - if (rc < 0) { - return rc; - } + if (rc < 0 && rc != FS_ERROR_ALREADY_EXISTS) { + WUT_DEBUG_REPORT("FSAMount(0x%08X, \"/dev/sdcard01\", %s, %08X, %08X, %08X) failed: %s\n", + __wut_fsa_device_data.clientHandle, __wut_fsa_device_data.mountPath, 0, nullptr, 0, FSAGetStatusStr(rc)); + return rc; + } - rc = FSMount(__wut_devoptab_fs_client, &fsCmd, &mountSource, sMountPath, sizeof(sMountPath), FS_ERROR_FLAG_ALL); + __wut_fsa_device_data.isSDCard = true; + __wut_fsa_device_data.mounted = true; + __wut_fsa_device_data.cwd[0] = '/'; + __wut_fsa_device_data.cwd[1] = '\0'; + chdir("fs:/vol/external01"); - if (rc >= 0) { - __wut_sd_mounted = TRUE; - // chdir to SD root for general use - strcpy(workDir, "fs:"); - strcat(workDir, sMountPath); - chdir(workDir); - } + FSADeviceInfo deviceInfo; + if ((rc = FSAGetDeviceInfo(__wut_fsa_device_data.clientHandle, __wut_fsa_device_data.mountPath, &deviceInfo)) >= 0) { + __wut_fsa_device_data.deviceSizeInSectors = deviceInfo.deviceSizeInSectors; + __wut_fsa_device_data.deviceSectorSize = deviceInfo.deviceSectorSize; } else { - FSDelClient(__wut_devoptab_fs_client, FS_ERROR_FLAG_ALL); - free(__wut_devoptab_fs_client); - return dev; + __wut_fsa_device_data.deviceSizeInSectors = 0xFFFFFFFF; + __wut_fsa_device_data.deviceSectorSize = 512; + WUT_DEBUG_REPORT("Failed to get DeviceInfo for %s: %s\n", __wut_fsa_device_data.mountPath, FSAGetStatusStr(rc)); } + + } else { + FSADelClient(__wut_fsa_device_data.clientHandle); + __wut_fsa_device_data.clientHandle = 0; + return FS_ERROR_MAX_CLIENTS; } - return rc; + return FS_ERROR_OK; } -FSStatus -__fini_wut_devoptab() -{ - FSStatus rc = 0; +FSError +__fini_wut_devoptab() { + FSError rc = FS_ERROR_OK; - if (!__wut_fs_initialised) { + if (!__wut_fsa_device_data.setup) { return rc; } - FSCmdBlock fsCmd; - if(__wut_sd_mounted) { - FSInitCmdBlock(&fsCmd); - FSUnmount(__wut_devoptab_fs_client, &fsCmd, sMountPath, FS_ERROR_FLAG_ALL); - __wut_sd_mounted = FALSE; + if (__wut_fsa_device_data.mounted) { + FSAUnmount(__wut_fsa_device_data.clientHandle, __wut_fsa_device_data.mountPath, FSA_UNMOUNT_FLAG_BIND_MOUNT); + __wut_fsa_device_data.mounted = false; } - FSDelClient(__wut_devoptab_fs_client, FS_ERROR_FLAG_ALL); - free(__wut_devoptab_fs_client); + FSADelClient(__wut_fsa_device_data.clientHandle); - RemoveDevice(__wut_fs_devoptab.name); + RemoveDevice(__wut_fsa_device_data.device.name); - __wut_devoptab_fs_client = NULL; - __wut_fs_initialised = FALSE; + __wut_fsa_device_data = {}; return rc; } diff --git a/libraries/wutdevoptab/devoptab_fsa.h b/libraries/wutdevoptab/devoptab_fsa.h index 2d4990545..30f390154 100644 --- a/libraries/wutdevoptab/devoptab_fsa.h +++ b/libraries/wutdevoptab/devoptab_fsa.h @@ -1,5 +1,8 @@ #pragma once -#include + +#include +#include +#include #include #include @@ -11,81 +14,124 @@ #include #include #include +#include "MutexWrapper.h" +#include "../wutnewlib/wut_clock.h" + +typedef struct FSADeviceData { + devoptab_t device; + bool setup; + bool mounted; + bool isSDCard; + char name[32]; + char mountPath[0x80]; + char cwd[FS_MAX_PATH + 1]; + FSAClientHandle clientHandle; + uint64_t deviceSizeInSectors; + uint32_t deviceSectorSize; +} __wut_fsa_device_t; /** * Open file struct */ -typedef struct -{ - //! FS handle - FSFileHandle fd; +typedef struct { + //! FSA file handle + FSAFileHandle fd; - //! Flags used in open(2) - int flags; + //! Flags used in open(2) + int flags; - //! Current file offset - uint32_t offset; + //! Current file offset + uint32_t offset; - //! Current file size (only valid if O_APPEND is set) - uint32_t appendOffset; -} __wut_fs_file_t; + //! Current file path + char fullPath[FS_MAX_PATH + 1]; + //! Guard file access + MutexWrapper mutex; + + //! Current file size (only valid if O_APPEND is set) + uint32_t appendOffset; +} __wut_fsa_file_t; /** * Open directory struct */ -typedef struct -{ - //! Should be set to FS_DIRITER_MAGIC - uint32_t magic; - - //! FS handle - FSDirectoryHandle fd; - - //! Temporary storage for reading entries - FSDirectoryEntry entry_data; -} __wut_fs_dir_t; - -#define FS_DIRITER_MAGIC 0x77696975 - -extern FSClient * -__wut_devoptab_fs_client; - -int __wut_fs_open(struct _reent *r, void *fileStruct, const char *path, - int flags, int mode); -int __wut_fs_close(struct _reent *r, void *fd); -ssize_t __wut_fs_write(struct _reent *r, void *fd, const char *ptr, - size_t len); -ssize_t __wut_fs_read(struct _reent *r, void *fd, char *ptr, size_t len); -off_t __wut_fs_seek(struct _reent *r, void *fd, off_t pos, int dir); -int __wut_fs_fstat(struct _reent *r, void *fd, struct stat *st); -int __wut_fs_stat(struct _reent *r, const char *file, struct stat *st); -int __wut_fs_link(struct _reent *r, const char *existing, - const char *newLink); -int __wut_fs_unlink(struct _reent *r, const char *name); -int __wut_fs_chdir(struct _reent *r, const char *name); -int __wut_fs_rename(struct _reent *r, const char *oldName, - const char *newName); -int __wut_fs_mkdir(struct _reent *r, const char *path, int mode); -DIR_ITER* __wut_fs_diropen(struct _reent *r, DIR_ITER *dirState, - const char *path); -int __wut_fs_dirreset(struct _reent *r, DIR_ITER *dirState); -int __wut_fs_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename, - struct stat *filestat); -int __wut_fs_dirclose(struct _reent *r, DIR_ITER *dirState); -int __wut_fs_statvfs(struct _reent *r, const char *path, - struct statvfs *buf); -int __wut_fs_ftruncate(struct _reent *r, void *fd, off_t len); -int __wut_fs_fsync(struct _reent *r, void *fd); -int __wut_fs_chmod(struct _reent *r, const char *path, mode_t mode); -int __wut_fs_fchmod(struct _reent *r, void *fd, mode_t mode); -int __wut_fs_rmdir(struct _reent *r, const char *name); -int __wut_fs_utimes(struct _reent *r, const char *filename, const struct timeval times[2]); - -// devoptab_fs_utils.c -char * __wut_fs_fixpath(struct _reent *r, const char *path); -int __wut_fs_translate_error(FSStatus error); -time_t __wut_fs_translate_time(FSTime timeValue); -mode_t __wut_fs_translate_stat_mode(FSStat *fsStat); -FSMode __wut_fs_translate_permission_mode(mode_t mode); -void __wut_fs_translate_stat(FSStat *fsStat, struct stat* posStat); +typedef struct { + //! Should be set to FSA_DIRITER_MAGIC + uint32_t magic; + + //! FS directory handle + FSADirectoryHandle fd; + + //! Temporary storage for reading entries + FSADirectoryEntry entry_data; + + //! Current directory path + char fullPath[FS_MAX_PATH + 1]; + + //! Guard dir access + MutexWrapper mutex; +} __wut_fsa_dir_t; + +#define FSA_DIRITER_MAGIC 0x77696975 + +#ifdef __cplusplus +extern "C" { +#endif + +FSError +__init_wut_devoptab(); + +FSError +__fini_wut_devoptab(); + +int __wut_fsa_open(struct _reent *r, void *fileStruct, const char *path, + int flags, int mode); +int __wut_fsa_close(struct _reent *r, void *fd); +ssize_t __wut_fsa_write(struct _reent *r, void *fd, const char *ptr, + size_t len); +ssize_t __wut_fsa_read(struct _reent *r, void *fd, char *ptr, size_t len); +off_t __wut_fsa_seek(struct _reent *r, void *fd, off_t pos, int dir); +int __wut_fsa_fstat(struct _reent *r, void *fd, struct stat *st); +int __wut_fsa_stat(struct _reent *r, const char *file, struct stat *st); +int __wut_fsa_link(struct _reent *r, const char *existing, + const char *newLink); +int __wut_fsa_unlink(struct _reent *r, const char *name); +int __wut_fsa_chdir(struct _reent *r, const char *name); +int __wut_fsa_rename(struct _reent *r, const char *oldName, + const char *newName); +int __wut_fsa_mkdir(struct _reent *r, const char *path, int mode); +DIR_ITER *__wut_fsa_diropen(struct _reent *r, DIR_ITER *dirState, + const char *path); +int __wut_fsa_dirreset(struct _reent *r, DIR_ITER *dirState); +int __wut_fsa_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename, + struct stat *filestat); +int __wut_fsa_dirclose(struct _reent *r, DIR_ITER *dirState); +int __wut_fsa_statvfs(struct _reent *r, const char *path, + struct statvfs *buf); +int __wut_fsa_ftruncate(struct _reent *r, void *fd, off_t len); +int __wut_fsa_fsync(struct _reent *r, void *fd); +int __wut_fsa_chmod(struct _reent *r, const char *path, mode_t mode); +int __wut_fsa_fchmod(struct _reent *r, void *fd, mode_t mode); +int __wut_fsa_rmdir(struct _reent *r, const char *name); +int __wut_fsa_utimes(struct _reent *r, const char *filename, const struct timeval times[2]); + +// devoptab_fsa_utils.c +char *__wut_fsa_fixpath(struct _reent *r, const char *path); +int __wut_fsa_translate_error(FSError error); +mode_t __wut_fsa_translate_stat_mode(FSStat *fsStat); +void __wut_fsa_translate_stat(FSAClientHandle handle, FSStat *fsStat, ino_t ino, struct stat *posStat); +uint32_t __wut_fsa_hashstring(const char *str); + +static inline FSMode __wut_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)); +} + +static inline time_t __wut_fsa_translate_time(FSTime timeValue) { + return (timeValue / 1000000) + EPOCH_DIFF_SECS(WIIU_FSTIME_EPOCH_YEAR); +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/libraries/wutdevoptab/devoptab_fsa_chdir.cpp b/libraries/wutdevoptab/devoptab_fsa_chdir.cpp index 3964a55f1..b405ac5c8 100644 --- a/libraries/wutdevoptab/devoptab_fsa_chdir.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_chdir.cpp @@ -1,29 +1,44 @@ +#include #include "devoptab_fsa.h" int -__wut_fs_chdir(struct _reent *r, - const char *path) -{ - FSStatus status; - FSCmdBlock cmd; +__wut_fsa_chdir(struct _reent *r, + const char *path) { + FSError status; + __wut_fsa_device_t *deviceData; if (!path) { r->_errno = EINVAL; return -1; } - char *fixedPath = __wut_fs_fixpath(r, path); + char *fixedPath = __wut_fsa_fixpath(r, path); if (!fixedPath) { + r->_errno = ENOMEM; return -1; } + deviceData = (__wut_fsa_device_t *) r->deviceData; - FSInitCmdBlock(&cmd); - status = FSChangeDir(__wut_devoptab_fs_client, &cmd, fixedPath, FS_ERROR_FLAG_ALL); - free(fixedPath); + status = FSAChangeDir(deviceData->clientHandle, fixedPath); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSAChangeDir(0x%08X, %s) failed: %s\n", deviceData->clientHandle, fixedPath, FSAGetStatusStr(status)); + free(fixedPath); + r->_errno = __wut_fsa_translate_error(status); 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) >= (int) sizeof(deviceData->cwd)) { + WUT_DEBUG_REPORT("__wut_fsa_chdir: snprintf result was truncated\n"); + } + + free(fixedPath); + return 0; } diff --git a/libraries/wutdevoptab/devoptab_fsa_chmod.cpp b/libraries/wutdevoptab/devoptab_fsa_chmod.cpp index 76420083c..9572dcf55 100644 --- a/libraries/wutdevoptab/devoptab_fsa_chmod.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_chmod.cpp @@ -1,34 +1,38 @@ -#include #include "devoptab_fsa.h" +#include +#include int -__wut_fs_chmod(struct _reent *r, - const char *path, - mode_t mode) -{ - FSStatus status; - FSCmdBlock cmd; +__wut_fsa_chmod(struct _reent *r, + const char *path, + mode_t mode) { + FSError status; + __wut_fsa_device_t *deviceData; if (!path) { r->_errno = EINVAL; return -1; } - char *fixedPath = __wut_fs_fixpath(r, path); + char *fixedPath = __wut_fsa_fixpath(r, path); if (!fixedPath) { + r->_errno = ENOMEM; return -1; } - FSMode translatedMode = __wut_fs_translate_permission_mode(mode); + FSMode translatedMode = __wut_fsa_translate_permission_mode(mode); - FSInitCmdBlock(&cmd); - status = FSChangeMode(__wut_devoptab_fs_client, &cmd, fixedPath, - translatedMode, 0x777, FS_ERROR_FLAG_ALL); - free(fixedPath); + deviceData = (__wut_fsa_device_t *) r->deviceData; + + status = FSAChangeMode(deviceData->clientHandle, fixedPath, translatedMode); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSAChangeMode(0x%08X, %s, 0x%X) failed: %s\n", + deviceData->clientHandle, fixedPath, translatedMode, FSAGetStatusStr(status)); + free(fixedPath); + r->_errno = __wut_fsa_translate_error(status); return -1; } + free(fixedPath); return 0; } diff --git a/libraries/wutdevoptab/devoptab_fsa_close.cpp b/libraries/wutdevoptab/devoptab_fsa_close.cpp index f5740863e..f2918f8a8 100644 --- a/libraries/wutdevoptab/devoptab_fsa_close.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_close.cpp @@ -1,23 +1,29 @@ #include "devoptab_fsa.h" +#include int -__wut_fs_close(struct _reent *r, - void *fd) -{ - FSStatus status; - FSCmdBlock cmd; - __wut_fs_file_t *file; +__wut_fsa_close(struct _reent *r, + void *fd) { + FSError status; + __wut_fsa_file_t *file; + __wut_fsa_device_t *deviceData; if (!fd) { r->_errno = EINVAL; return -1; } - FSInitCmdBlock(&cmd); - file = (__wut_fs_file_t *)fd; - status = FSCloseFile(__wut_devoptab_fs_client, &cmd, file->fd, FS_ERROR_FLAG_ALL); + file = (__wut_fsa_file_t *) fd; + + deviceData = (__wut_fsa_device_t *) r->deviceData; + + std::scoped_lock lock(file->mutex); + + status = FSACloseFile(deviceData->clientHandle, file->fd); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSACloseFile(0x%08X, 0x%08X) (%s) failed: %s\n", + deviceData->clientHandle, file->fd, file->fullPath, FSAGetStatusStr(status)); + r->_errno = __wut_fsa_translate_error(status); return -1; } diff --git a/libraries/wutdevoptab/devoptab_fsa_dirclose.cpp b/libraries/wutdevoptab/devoptab_fsa_dirclose.cpp index 494b91d51..6024e1c90 100644 --- a/libraries/wutdevoptab/devoptab_fsa_dirclose.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_dirclose.cpp @@ -1,23 +1,29 @@ #include "devoptab_fsa.h" +#include int -__wut_fs_dirclose(struct _reent *r, - DIR_ITER *dirState) -{ - FSStatus status; - FSCmdBlock cmd; - __wut_fs_dir_t *dir; +__wut_fsa_dirclose(struct _reent *r, + DIR_ITER *dirState) { + FSError status; + __wut_fsa_dir_t *dir; + __wut_fsa_device_t *deviceData; if (!dirState) { r->_errno = EINVAL; return -1; } - FSInitCmdBlock(&cmd); - dir = (__wut_fs_dir_t *)(dirState->dirStruct); - status = FSCloseDir(__wut_devoptab_fs_client, &cmd, dir->fd, FS_ERROR_FLAG_ALL); + dir = (__wut_fsa_dir_t *) (dirState->dirStruct); + + deviceData = (__wut_fsa_device_t *) r->deviceData; + + std::scoped_lock lock(dir->mutex); + + status = FSACloseDir(deviceData->clientHandle, dir->fd); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSACloseDir(0x%08X, 0x%08X) (%s) failed: %s\n", + deviceData->clientHandle, dir->fd, dir->fullPath, FSAGetStatusStr(status)); + r->_errno = __wut_fsa_translate_error(status); return -1; } diff --git a/libraries/wutdevoptab/devoptab_fsa_dirnext.cpp b/libraries/wutdevoptab/devoptab_fsa_dirnext.cpp index 22a223cdf..6734b837d 100644 --- a/libraries/wutdevoptab/devoptab_fsa_dirnext.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_dirnext.cpp @@ -1,33 +1,55 @@ #include "devoptab_fsa.h" +#include +#include int -__wut_fs_dirnext(struct _reent *r, - DIR_ITER *dirState, - char *filename, - struct stat *filestat) -{ - FSStatus status; - FSCmdBlock cmd; - __wut_fs_dir_t *dir; +__wut_fsa_dirnext(struct _reent *r, + DIR_ITER *dirState, + char *filename, + struct stat *filestat) { + FSError status; + __wut_fsa_dir_t *dir; + __wut_fsa_device_t *deviceData; if (!dirState || !filename || !filestat) { r->_errno = EINVAL; return -1; } - FSInitCmdBlock(&cmd); - dir = (__wut_fs_dir_t *)(dirState->dirStruct); + deviceData = (__wut_fsa_device_t *) r->deviceData; + dir = (__wut_fsa_dir_t *) (dirState->dirStruct); + + std::scoped_lock lock(dir->mutex); memset(&dir->entry_data, 0, sizeof(dir->entry_data)); - status = FSReadDir(__wut_devoptab_fs_client, &cmd, dir->fd, &dir->entry_data, - FS_ERROR_FLAG_ALL); + + status = FSAReadDir(deviceData->clientHandle, dir->fd, &dir->entry_data); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + if (status != FS_ERROR_END_OF_DIR) { + WUT_DEBUG_REPORT("FSAReadDir(0x%08X, 0x%08X, 0x%08X) (%s) failed: %s\n", + deviceData->clientHandle, dir->fd, &dir->entry_data, dir->fullPath, FSAGetStatusStr(status)); + } + r->_errno = __wut_fsa_translate_error(status); return -1; } - __wut_fs_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) { + WUT_DEBUG_REPORT("__wut_fsa_dirnext: snprintf fullStr result was truncated\n"); + } + ino = __wut_fsa_hashstring(fullStr); + free(fullStr); + } else { + ino = 0; + WUT_DEBUG_REPORT("__wut_fsa_dirnext: Failed to allocate memory for fullStr. st_ino will be set to 0\n"); + } + __wut_fsa_translate_stat(deviceData->clientHandle, &dir->entry_data.info, ino, filestat); + + if (snprintf(filename, NAME_MAX, "%s", dir->entry_data.name) >= NAME_MAX) { + WUT_DEBUG_REPORT("__wut_fsa_dirnext: snprintf filename result was truncated\n"); + } - memset(filename, 0, NAME_MAX); - strcpy(filename, dir->entry_data.name); return 0; } diff --git a/libraries/wutdevoptab/devoptab_fsa_diropen.cpp b/libraries/wutdevoptab/devoptab_fsa_diropen.cpp index dc48fa73a..d98babf9b 100644 --- a/libraries/wutdevoptab/devoptab_fsa_diropen.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_diropen.cpp @@ -1,36 +1,53 @@ #include "devoptab_fsa.h" +#include DIR_ITER * -__wut_fs_diropen(struct _reent *r, - DIR_ITER *dirState, - const char *path) -{ - FSDirectoryHandle fd; - FSStatus status; - FSCmdBlock cmd; - __wut_fs_dir_t *dir; +__wut_fsa_diropen(struct _reent *r, + DIR_ITER *dirState, + const char *path) { + FSADirectoryHandle fd; + FSError status; + __wut_fsa_dir_t *dir; + __wut_fsa_device_t *deviceData; if (!dirState || !path) { r->_errno = EINVAL; return NULL; } - char *fixedPath = __wut_fs_fixpath(r, path); + char *fixedPath = __wut_fsa_fixpath(r, path); if (!fixedPath) { return NULL; } + dir = (__wut_fsa_dir_t *) (dirState->dirStruct); + deviceData = (__wut_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)) { + WUT_DEBUG_REPORT("__wut_fsa_diropen: snprintf result was truncated\n"); + } - FSInitCmdBlock(&cmd); - dir = (__wut_fs_dir_t *)(dirState->dirStruct); - status = FSOpenDir(__wut_devoptab_fs_client, &cmd, fixedPath, &fd, FS_ERROR_FLAG_ALL); free(fixedPath); + + dir->mutex.init(dir->fullPath); + std::scoped_lock lock(dir->mutex); + + status = FSAOpenDir(deviceData->clientHandle, dir->fullPath, &fd); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSAOpenDir(0x%08X, %s, 0x%08X) failed: %s\n", + deviceData->clientHandle, dir->fullPath, &fd, FSAGetStatusStr(status)); + r->_errno = __wut_fsa_translate_error(status); return NULL; } - dir->magic = FS_DIRITER_MAGIC; - dir->fd = fd; + dir->magic = FSA_DIRITER_MAGIC; + dir->fd = fd; memset(&dir->entry_data, 0, sizeof(dir->entry_data)); return dirState; } diff --git a/libraries/wutdevoptab/devoptab_fsa_dirreset.cpp b/libraries/wutdevoptab/devoptab_fsa_dirreset.cpp index 2a1ffd74b..c3fdad67e 100644 --- a/libraries/wutdevoptab/devoptab_fsa_dirreset.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_dirreset.cpp @@ -1,23 +1,28 @@ #include "devoptab_fsa.h" +#include int -__wut_fs_dirreset(struct _reent *r, - DIR_ITER *dirState) -{ - FSStatus status; - FSCmdBlock cmd; - __wut_fs_dir_t *dir; +__wut_fsa_dirreset(struct _reent *r, + DIR_ITER *dirState) { + FSError status; + __wut_fsa_dir_t *dir; + __wut_fsa_device_t *deviceData; if (!dirState) { r->_errno = EINVAL; return -1; } - FSInitCmdBlock(&cmd); - dir = (__wut_fs_dir_t *)(dirState->dirStruct); - status = FSRewindDir(__wut_devoptab_fs_client, &cmd, dir->fd, FS_ERROR_FLAG_ALL); + dir = (__wut_fsa_dir_t *) (dirState->dirStruct); + deviceData = (__wut_fsa_device_t *) r->deviceData; + + std::scoped_lock lock(dir->mutex); + + status = FSARewindDir(deviceData->clientHandle, dir->fd); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSARewindDir(0x%08X, 0x%08X) (%s) failed: %s\n", + deviceData->clientHandle, dir->fd, dir->fullPath, FSAGetStatusStr(status)); + r->_errno = __wut_fsa_translate_error(status); return -1; } diff --git a/libraries/wutdevoptab/devoptab_fsa_fchmod.cpp b/libraries/wutdevoptab/devoptab_fsa_fchmod.cpp deleted file mode 100644 index a6ab414e7..000000000 --- a/libraries/wutdevoptab/devoptab_fsa_fchmod.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "devoptab_fsa.h" - -int -__wut_fs_fchmod(struct _reent *r, - void *fd, - mode_t mode) -{ - // TODO: FSChangeMode and FSStatFile? - r->_errno = ENOSYS; - return -1; -} diff --git a/libraries/wutdevoptab/devoptab_fsa_fstat.cpp b/libraries/wutdevoptab/devoptab_fsa_fstat.cpp index 9d2e29a73..0e8402c15 100644 --- a/libraries/wutdevoptab/devoptab_fsa_fstat.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_fstat.cpp @@ -1,30 +1,35 @@ #include "devoptab_fsa.h" +#include int -__wut_fs_fstat(struct _reent *r, - void *fd, - struct stat *st) -{ - FSStatus status; - FSStat fsStat; - FSCmdBlock cmd; - __wut_fs_file_t *file; +__wut_fsa_fstat(struct _reent *r, + void *fd, + struct stat *st) { + FSError status; + FSAStat fsStat; + __wut_fsa_file_t *file; + __wut_fsa_device_t *deviceData; if (!fd || !st) { r->_errno = EINVAL; return -1; } - FSInitCmdBlock(&cmd); - file = (__wut_fs_file_t *)fd; - status = FSGetStatFile(__wut_devoptab_fs_client, &cmd, file->fd, &fsStat, - FS_ERROR_FLAG_ALL); + file = (__wut_fsa_file_t *) fd; + deviceData = (__wut_fsa_device_t *) r->deviceData; + + std::scoped_lock lock(file->mutex); + + status = FSAGetStatFile(deviceData->clientHandle, file->fd, &fsStat); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSAGetStatFile(0x%08X, 0x%08X, 0x%08X) (%s) failed: %s\n", + deviceData->clientHandle, file->fd, &fsStat, FSAGetStatusStr(status)); + r->_errno = __wut_fsa_translate_error(status); return -1; } - __wut_fs_translate_stat(&fsStat, st); + ino_t ino = __wut_fsa_hashstring(file->fullPath); + __wut_fsa_translate_stat(deviceData->clientHandle, &fsStat, ino, st); return 0; } diff --git a/libraries/wutdevoptab/devoptab_fsa_fsync.cpp b/libraries/wutdevoptab/devoptab_fsa_fsync.cpp index 69acdc38f..0bfb6d70a 100644 --- a/libraries/wutdevoptab/devoptab_fsa_fsync.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_fsync.cpp @@ -1,23 +1,29 @@ #include "devoptab_fsa.h" +#include int -__wut_fs_fsync(struct _reent *r, - void *fd) -{ - FSStatus status; - FSCmdBlock cmd; - __wut_fs_file_t *file; +__wut_fsa_fsync(struct _reent *r, + void *fd) { + FSError status; + __wut_fsa_file_t *file; + __wut_fsa_device_t *deviceData; if (!fd) { r->_errno = EINVAL; return -1; } - FSInitCmdBlock(&cmd); - file = (__wut_fs_file_t *)fd; - status = FSFlushFile(__wut_devoptab_fs_client, &cmd, file->fd, FS_ERROR_FLAG_ALL); + file = (__wut_fsa_file_t *) fd; + + deviceData = (__wut_fsa_device_t *) r->deviceData; + + std::scoped_lock lock(file->mutex); + + status = FSAFlushFile(deviceData->clientHandle, file->fd); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSAFlushFile(0x%08X, 0x%08X) (%s) failed: %s\n", + deviceData->clientHandle, file->fd, file->fullPath, FSAGetStatusStr(status)); + r->_errno = __wut_fsa_translate_error(status); return -1; } diff --git a/libraries/wutdevoptab/devoptab_fsa_link.cpp b/libraries/wutdevoptab/devoptab_fsa_link.cpp deleted file mode 100644 index 7eb7add36..000000000 --- a/libraries/wutdevoptab/devoptab_fsa_link.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "devoptab_fsa.h" - -int -__wut_fs_link(struct _reent *r, - const char *existing, - const char *newLink) -{ - r->_errno = ENOSYS; - return -1; -} diff --git a/libraries/wutdevoptab/devoptab_fsa_mkdir.cpp b/libraries/wutdevoptab/devoptab_fsa_mkdir.cpp index e4312bec7..22cbf5b45 100644 --- a/libraries/wutdevoptab/devoptab_fsa_mkdir.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_mkdir.cpp @@ -1,32 +1,37 @@ #include "devoptab_fsa.h" int -__wut_fs_mkdir(struct _reent *r, - const char *path, - int mode) -{ - FSStatus status; - FSCmdBlock cmd; +__wut_fsa_mkdir(struct _reent *r, + const char *path, + int mode) { + FSError status; char *fixedPath; + __wut_fsa_device_t *deviceData; if (!path) { r->_errno = EINVAL; return -1; } - fixedPath = __wut_fs_fixpath(r, path); + fixedPath = __wut_fsa_fixpath(r, path); if (!fixedPath) { + r->_errno = ENOMEM; return -1; } - // TODO: Use mode to set directory attributes. - FSInitCmdBlock(&cmd); - status = FSMakeDir(__wut_devoptab_fs_client, &cmd, fixedPath, FS_ERROR_FLAG_ALL); - free(fixedPath); + deviceData = (__wut_fsa_device_t *) r->deviceData; + + FSMode translatedMode = __wut_fsa_translate_permission_mode(mode); + + status = FSAMakeDir(deviceData->clientHandle, fixedPath, translatedMode); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSAMakeDir(0x%08X, %s, 0x%X) failed: %s\n", + deviceData->clientHandle, fixedPath, translatedMode, FSAGetStatusStr(status)); + free(fixedPath); + r->_errno = __wut_fsa_translate_error(status); return -1; } + free(fixedPath); return 0; } diff --git a/libraries/wutdevoptab/devoptab_fsa_open.cpp b/libraries/wutdevoptab/devoptab_fsa_open.cpp index 5abc33adf..b8dc41614 100644 --- a/libraries/wutdevoptab/devoptab_fsa_open.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_open.cpp @@ -1,19 +1,22 @@ #include "devoptab_fsa.h" +#include // Extended "magic" value that allows opening files with FS_OPEN_FLAG_UNENCRYPTED in underlying FSOpenFileEx() call similar to O_DIRECTORY +#ifndef O_UNENCRYPTED #define O_UNENCRYPTED 0x4000000 +#endif int -__wut_fs_open(struct _reent *r, - void *fileStruct, - const char *path, - int flags, - int mode) { - FSFileHandle fd; - FSStatus status; - FSCmdBlock cmd; +__wut_fsa_open(struct _reent *r, + void *fileStruct, + const char *path, + int flags, + int mode) { + FSAFileHandle fd; + FSError status; const char *fsMode; - __wut_fs_file_t *file; + __wut_fsa_file_t *file; + __wut_fsa_device_t *deviceData; if (!fileStruct || !path) { r->_errno = EINVAL; @@ -55,70 +58,96 @@ __wut_fs_open(struct _reent *r, return -1; } - char *fixedPath = __wut_fs_fixpath(r, path); + char *fixedPath = __wut_fsa_fixpath(r, path); if (!fixedPath) { + r->_errno = ENOMEM; return -1; } - // Open the file - FSInitCmdBlock(&cmd); + + file = (__wut_fsa_file_t *) fileStruct; + deviceData = (__wut_fsa_device_t *) r->deviceData; + + if (snprintf(file->fullPath, sizeof(file->fullPath), "%s", fixedPath) >= (int) sizeof(file->fullPath)) { + WUT_DEBUG_REPORT("__wut_fsa_open: snprintf result was truncated\n"); + } + free(fixedPath); + + // Prepare flags FSOpenFileFlags openFlags = (flags & O_UNENCRYPTED) ? FS_OPEN_FLAG_UNENCRYPTED : FS_OPEN_FLAG_NONE; - uint32_t preallocSize = 0; + FSMode translatedMode = __wut_fsa_translate_permission_mode(mode); + uint32_t preAllocSize = 0; + + // Init mutex and lock + file->mutex.init(file->fullPath); + std::scoped_lock lock(file->mutex); if (createFileIfNotFound || failIfFileNotFound || (flags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) { // Check if file exists - FSStat stat; - status = FSGetStat(__wut_devoptab_fs_client, &cmd, fixedPath, &stat, FS_ERROR_FLAG_ALL); - if (status == FS_STATUS_NOT_FOUND) { + FSAStat stat; + status = FSAGetStat(deviceData->clientHandle, file->fullPath, &stat); + if (status == FS_ERROR_NOT_FOUND) { if (createFileIfNotFound) { // Create new file if needed - status = FSOpenFileEx(__wut_devoptab_fs_client, &cmd, fixedPath, "w", __wut_fs_translate_permission_mode(mode), - openFlags, preallocSize, &fd, FS_ERROR_FLAG_ALL); - if (status == FS_STATUS_OK) { - FSCloseFile(__wut_devoptab_fs_client, &cmd, fd, FS_ERROR_FLAG_ALL); + status = FSAOpenFileEx(deviceData->clientHandle, file->fullPath, "w", translatedMode, + openFlags, preAllocSize, &fd); + if (status == FS_ERROR_OK) { + if (FSACloseFile(deviceData->clientHandle, fd) != FS_ERROR_OK) { + WUT_DEBUG_REPORT("FSACloseFile(0x%08X, 0x%08X) (%s) failed: %s\n", + deviceData->clientHandle, fd, file->fullPath, FSAGetStatusStr(status)); + } fd = -1; } else { - free(fixedPath); - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSAOpenFileEx(0x%08X, %s, %s, 0x%X, 0x%08X, 0x%08X, 0x%08X) failed: %s\n", + deviceData->clientHandle, file->fullPath, "w", translatedMode, openFlags, preAllocSize, &fd, + FSAGetStatusStr(status)); + r->_errno = __wut_fsa_translate_error(status); return -1; } } else if (failIfFileNotFound) { // Return an error if we don't we create new files - free(fixedPath); - r->_errno = __wut_fs_translate_error(status); + r->_errno = __wut_fsa_translate_error(status); return -1; } - } else if (status == FS_STATUS_OK) { + } else if (status == FS_ERROR_OK) { // If O_CREAT and O_EXCL are set, open() shall fail if the file exists. if ((flags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) { - free(fixedPath); r->_errno = EEXIST; return -1; } } } - status = FSOpenFileEx(__wut_devoptab_fs_client, &cmd, fixedPath, fsMode, __wut_fs_translate_permission_mode(mode), - openFlags, preallocSize, &fd, FS_ERROR_FLAG_ALL); - free(fixedPath); + status = FSAOpenFileEx(deviceData->clientHandle, file->fullPath, fsMode, translatedMode, openFlags, preAllocSize, &fd); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + if (status != FS_ERROR_NOT_FOUND) { + WUT_DEBUG_REPORT("FSAOpenFileEx(0x%08X, %s, %s, 0x%X, 0x%08X, 0x%08X, 0x%08X) failed: %s\n", + deviceData->clientHandle, file->fullPath, fsMode, translatedMode, openFlags, preAllocSize, &fd, + FSAGetStatusStr(status)); + } + r->_errno = __wut_fsa_translate_error(status); return -1; } - file = (__wut_fs_file_t *) fileStruct; file->fd = fd; file->flags = (flags & (O_ACCMODE | O_APPEND | O_SYNC)); // Is always 0, even if O_APPEND is set. file->offset = 0; + if (flags & O_APPEND) { - FSStat stat; - status = FSGetStatFile(__wut_devoptab_fs_client, &cmd, fd, &stat, FS_ERROR_FLAG_ALL); + FSAStat stat; + status = FSAGetStatFile(deviceData->clientHandle, fd, &stat); if (status < 0) { - FSCloseFile(__wut_devoptab_fs_client, &cmd, fd, FS_ERROR_FLAG_ALL); - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSAGetStatFile(0x%08X, 0x%08X, 0x%08X) (%s) failed: %s\n", + deviceData->clientHandle, fd, &stat, file->fullPath, FSAGetStatusStr(status)); + + r->_errno = __wut_fsa_translate_error(status); + if (FSACloseFile(deviceData->clientHandle, fd) < 0) { + WUT_DEBUG_REPORT("FSACloseFile(0x%08X, 0x%08X) (%s) failed: %s\n", + deviceData->clientHandle, fd, file->fullPath, FSAGetStatusStr(status)); + + } return -1; } file->appendOffset = stat.size; } - return 0; -} +} \ No newline at end of file diff --git a/libraries/wutdevoptab/devoptab_fsa_read.cpp b/libraries/wutdevoptab/devoptab_fsa_read.cpp index a14b61c7f..a52672600 100644 --- a/libraries/wutdevoptab/devoptab_fsa_read.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_read.cpp @@ -1,15 +1,18 @@ #include "devoptab_fsa.h" - +#include #include -ssize_t __wut_fs_read(struct _reent *r, void *fd, char *ptr, size_t len) { +ssize_t __wut_fsa_read(struct _reent *r, void *fd, char *ptr, size_t len) { + FSError status; + __wut_fsa_file_t *file; + __wut_fsa_device_t *deviceData; if (!fd || !ptr) { r->_errno = EINVAL; return -1; } // Check that the file was opened with read access - __wut_fs_file_t *file = (__wut_fs_file_t *) fd; + file = (__wut_fsa_file_t *) fd; if ((file->flags & O_ACCMODE) == O_WRONLY) { r->_errno = EBADF; return -1; @@ -18,8 +21,9 @@ ssize_t __wut_fs_read(struct _reent *r, void *fd, char *ptr, size_t len) { // cache-aligned, cache-line-sized __attribute__((aligned(0x40))) uint8_t alignedBuffer[0x40]; - FSCmdBlock cmd; - FSInitCmdBlock(&cmd); + deviceData = (__wut_fsa_device_t *) r->deviceData; + + std::scoped_lock lock(file->mutex); size_t bytesRead = 0; while (bytesRead < len) { @@ -40,15 +44,22 @@ ssize_t __wut_fs_read(struct _reent *r, void *fd, char *ptr, size_t len) { size &= ~0x3F; } - FSStatus status = FSReadFile(__wut_devoptab_fs_client, &cmd, tmp, 1, size, - file->fd, 0, FS_ERROR_FLAG_ALL); + // Limit each request to 1 MiB + if (size > 0x100000) { + size = 0x100000; + } + + status = FSAReadFile(deviceData->clientHandle, tmp, 1, size, file->fd, 0); if (status < 0) { + WUT_DEBUG_REPORT("FSAReadFile(0x%08X, 0x%08X, 1, 0x%08X, 0x%08X, 0) (%s) failed: %s\n", + deviceData->clientHandle, tmp, size, file->fd, file->fullPath, FSAGetStatusStr(status)); + if (bytesRead != 0) { return bytesRead; // error after partial read } - r->_errno = __wut_fs_translate_error(status); + r->_errno = __wut_fsa_translate_error(status); return -1; } @@ -60,7 +71,7 @@ ssize_t __wut_fs_read(struct _reent *r, void *fd, char *ptr, size_t len) { bytesRead += status; ptr += status; - if (status != size) { + if ((size_t) status != size) { return bytesRead; // partial read } } diff --git a/libraries/wutdevoptab/devoptab_fsa_rename.cpp b/libraries/wutdevoptab/devoptab_fsa_rename.cpp index 2b89f0373..f00a8f76c 100644 --- a/libraries/wutdevoptab/devoptab_fsa_rename.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_rename.cpp @@ -1,40 +1,44 @@ #include "devoptab_fsa.h" int -__wut_fs_rename(struct _reent *r, - const char *oldName, - const char *newName) -{ - FSStatus status; - FSCmdBlock cmd; +__wut_fsa_rename(struct _reent *r, + const char *oldName, + const char *newName) { + FSError status; char *fixedOldPath, *fixedNewPath; + __wut_fsa_device_t *deviceData; if (!oldName || !newName) { r->_errno = EINVAL; return -1; } - fixedOldPath = __wut_fs_fixpath(r, oldName); + fixedOldPath = __wut_fsa_fixpath(r, oldName); if (!fixedOldPath) { + r->_errno = ENOMEM; return -1; } - fixedNewPath = __wut_fs_fixpath(r, newName); + fixedNewPath = __wut_fsa_fixpath(r, newName); if (!fixedNewPath) { free(fixedOldPath); + r->_errno = ENOMEM; return -1; } - FSInitCmdBlock(&cmd); - status = FSRename(__wut_devoptab_fs_client, &cmd, fixedOldPath, fixedNewPath, - FS_ERROR_FLAG_ALL); - free(fixedOldPath); - free(fixedNewPath); + deviceData = (__wut_fsa_device_t *) r->deviceData; + status = FSARename(deviceData->clientHandle, fixedOldPath, fixedNewPath); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSARename(0x%08X, %s, %s) failed: %s\n", + deviceData->clientHandle, fixedOldPath, fixedNewPath, FSAGetStatusStr(status)); + free(fixedOldPath); + free(fixedNewPath); + r->_errno = __wut_fsa_translate_error(status); return -1; } + free(fixedOldPath); + free(fixedNewPath); return 0; } diff --git a/libraries/wutdevoptab/devoptab_fsa_rmdir.cpp b/libraries/wutdevoptab/devoptab_fsa_rmdir.cpp index 8200f0c67..ccd1a52d1 100644 --- a/libraries/wutdevoptab/devoptab_fsa_rmdir.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_rmdir.cpp @@ -1,29 +1,34 @@ #include "devoptab_fsa.h" int -__wut_fs_rmdir(struct _reent *r, - const char *name) -{ - FSStatus status; - FSCmdBlock cmd; +__wut_fsa_rmdir(struct _reent *r, + const char *name) { + FSError status; + __wut_fsa_device_t *deviceData; if (!name) { r->_errno = EINVAL; return -1; } - char *fixedPath = __wut_fs_fixpath(r, name); + char *fixedPath = __wut_fsa_fixpath(r, name); if (!fixedPath) { + r->_errno = ENOMEM; return -1; } - FSInitCmdBlock(&cmd); - status = FSRemove(__wut_devoptab_fs_client, &cmd, fixedPath, FS_ERROR_FLAG_ALL); - free(fixedPath); + deviceData = (__wut_fsa_device_t *) r->deviceData; + + status = FSARemove(deviceData->clientHandle, fixedPath); if (status < 0) { - r->_errno = status == FS_STATUS_EXISTS ? ENOTEMPTY : __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSARemove(0x%08X, %s) failed: %s\n", + deviceData->clientHandle, fixedPath, FSAGetStatusStr(status)); + free(fixedPath); + r->_errno = __wut_fsa_translate_error(status); return -1; } + free(fixedPath); + return 0; } diff --git a/libraries/wutdevoptab/devoptab_fsa_seek.cpp b/libraries/wutdevoptab/devoptab_fsa_seek.cpp index 8e6b1bf73..07ba26b53 100644 --- a/libraries/wutdevoptab/devoptab_fsa_seek.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_seek.cpp @@ -1,55 +1,56 @@ #include "devoptab_fsa.h" +#include off_t -__wut_fs_seek(struct _reent *r, - void *fd, - off_t pos, - int whence) -{ - FSStatus status; - FSCmdBlock cmd; - FSStat fsStat; +__wut_fsa_seek(struct _reent *r, + void *fd, + off_t pos, + int whence) { + FSError status; + FSAStat fsStat; uint64_t offset; - __wut_fs_file_t *file; + __wut_fsa_file_t *file; + __wut_fsa_device_t *deviceData; if (!fd) { r->_errno = EINVAL; return -1; } - FSInitCmdBlock(&cmd); - file = (__wut_fs_file_t *)fd; + file = (__wut_fsa_file_t *) fd; - // Find the offset to see from - switch(whence) { - // Set absolute position; start offset is 0 - case SEEK_SET: - offset = 0; - break; + deviceData = (__wut_fsa_device_t *) r->deviceData; - // Set position relative to the current position - case SEEK_CUR: - offset = file->offset; - break; + std::scoped_lock lock(file->mutex); - // Set position relative to the end of the file - case SEEK_END: { - status = FSGetStatFile(__wut_devoptab_fs_client, &cmd, file->fd, &fsStat, - FS_ERROR_FLAG_ALL); - if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + // Find the offset to see from + switch (whence) { + case SEEK_SET: { // Set absolute position; start offset is 0 + offset = 0; + break; + } + case SEEK_CUR: { // Set position relative to the current position + offset = file->offset; + break; + } + case SEEK_END: { // Set position relative to the end of the file + status = FSAGetStatFile(deviceData->clientHandle, file->fd, &fsStat); + if (status < 0) { + WUT_DEBUG_REPORT("FSAGetStatFile(0x%08X, 0x%08X, 0x%08X) (%s) failed: %s\n", + deviceData->clientHandle, file->fd, &fsStat, file->fullPath, FSAGetStatusStr(status)); + r->_errno = __wut_fsa_translate_error(status); + return -1; + } + offset = fsStat.size; + break; + } + default: { // An invalid option was provided + r->_errno = EINVAL; return -1; } - offset = fsStat.size; - break; - } - // An invalid option was provided - default: - r->_errno = EINVAL; - return -1; } - if(pos < 0 && offset < -pos) { + if (pos < 0 && (off_t) offset < -pos) { // Don't allow seek to before the beginning of the file r->_errno = EINVAL; return -1; @@ -58,20 +59,20 @@ __wut_fs_seek(struct _reent *r, r->_errno = EINVAL; return -1; } - - if((uint32_t) (offset + pos) == file->offset) { + + if ((uint32_t) (offset + pos) == file->offset) { return file->offset; } - uint32_t old_offset = file->offset; + uint32_t old_pos = file->offset; file->offset = offset + pos; - status = FSSetPosFile(__wut_devoptab_fs_client, &cmd, file->fd, file->offset, - FS_ERROR_FLAG_ALL); + status = FSASetPosFile(deviceData->clientHandle, file->fd, file->offset); if (status < 0) { - // revert offset update on error. - file->offset = old_offset; - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSASetPosFile(0x%08X, 0x%08X, 0x%08X) (%s) failed: %s\n", + deviceData->clientHandle, file->fd, file->offset, file->fullPath, FSAGetStatusStr(status)); + file->offset = old_pos; + r->_errno = __wut_fsa_translate_error(status); return -1; } diff --git a/libraries/wutdevoptab/devoptab_fsa_stat.cpp b/libraries/wutdevoptab/devoptab_fsa_stat.cpp index 7b2a8dcb0..80029e777 100644 --- a/libraries/wutdevoptab/devoptab_fsa_stat.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_stat.cpp @@ -1,34 +1,40 @@ #include "devoptab_fsa.h" int -__wut_fs_stat(struct _reent *r, - const char *path, - struct stat *st) { - FSStatus status; - FSCmdBlock cmd; - FSStat fsStat; +__wut_fsa_stat(struct _reent *r, + const char *path, + struct stat *st) { + FSError status; + FSAStat fsStat; + __wut_fsa_device_t *deviceData; if (!path || !st) { r->_errno = EINVAL; return -1; } - char *fixedPath = __wut_fs_fixpath(r, path); + char *fixedPath = __wut_fsa_fixpath(r, path); if (!fixedPath) { + r->_errno = ENOMEM; return -1; } - FSInitCmdBlock(&cmd); + deviceData = (__wut_fsa_device_t *) r->deviceData; - status = FSGetStat(__wut_devoptab_fs_client, &cmd, fixedPath, &fsStat, FS_ERROR_FLAG_ALL); + status = FSAGetStat(deviceData->clientHandle, fixedPath, &fsStat); if (status < 0) { + if (status != FS_ERROR_NOT_FOUND) { + WUT_DEBUG_REPORT("FSAGetStat(0x%08X, %s, 0x%08X) failed: %s\n", + deviceData->clientHandle, fixedPath, &fsStat, FSAGetStatusStr(status)); + } free(fixedPath); - r->_errno = __wut_fs_translate_error(status); + r->_errno = __wut_fsa_translate_error(status); return -1; } + ino_t ino = __wut_fsa_hashstring(fixedPath); free(fixedPath); - __wut_fs_translate_stat(&fsStat, st); + __wut_fsa_translate_stat(deviceData->clientHandle, &fsStat, ino, st); return 0; } \ No newline at end of file diff --git a/libraries/wutdevoptab/devoptab_fsa_statvfs.cpp b/libraries/wutdevoptab/devoptab_fsa_statvfs.cpp index e2fb2dcf5..971d0046b 100644 --- a/libraries/wutdevoptab/devoptab_fsa_statvfs.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_statvfs.cpp @@ -1,11 +1,55 @@ #include "devoptab_fsa.h" int -__wut_fs_statvfs(struct _reent *r, - const char *path, - struct statvfs *buf) -{ - //TODO: FSGetFileSystemInfo - r->_errno = ENOSYS; - return -1; -} +__wut_fsa_statvfs(struct _reent *r, + const char *path, + struct statvfs *buf) { + FSError status; + uint64_t freeSpace; + __wut_fsa_device_t *deviceData; + + deviceData = (__wut_fsa_device_t *) r->deviceData; + if (deviceData->isSDCard) { + r->_errno = ENOSYS; + return -1; + } + + memset(buf, 0, sizeof(struct statvfs)); + + char *fixedPath = __wut_fsa_fixpath(r, path); + if (!fixedPath) { + r->_errno = ENOMEM; + return -1; + } + + status = FSAGetFreeSpaceSize(deviceData->clientHandle, fixedPath, &freeSpace); + if (status < 0) { + WUT_DEBUG_REPORT("FSAGetFreeSpaceSize(0x%08X, %s, 0x%08X) failed: %s\n", + deviceData->clientHandle, fixedPath, &freeSpace, FSAGetStatusStr(status)); + free(fixedPath); + r->_errno = __wut_fsa_translate_error(status); + return -1; + } + free(fixedPath); + + // File system block size + buf->f_bsize = deviceData->deviceSectorSize; + // Fundamental file system block size + buf->f_frsize = deviceData->deviceSectorSize; + // Total number of blocks on file system in units of f_frsize + buf->f_blocks = deviceData->deviceSizeInSectors; + // Free blocks available for all and for non-privileged processes + buf->f_bfree = buf->f_bavail = (uint32_t) (freeSpace / buf->f_frsize); + // Number of inodes at this point in time + buf->f_files = 0xFFFFFFFF; + // Free inodes available for all and for non-privileged processes + buf->f_ffree = 0xFFFFFFFF; + // File system id + buf->f_fsid = (unsigned long) deviceData->clientHandle; + // Bit mask of f_flag values. + buf->f_flag = 0; + // Maximum length of filenames + buf->f_namemax = 255; + + return 0; +} \ No newline at end of file diff --git a/libraries/wutdevoptab/devoptab_fsa_truncate.cpp b/libraries/wutdevoptab/devoptab_fsa_truncate.cpp index 13ca9fb24..cd3e0503c 100644 --- a/libraries/wutdevoptab/devoptab_fsa_truncate.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_truncate.cpp @@ -1,13 +1,13 @@ #include "devoptab_fsa.h" +#include int -__wut_fs_ftruncate(struct _reent *r, - void *fd, - off_t len) -{ - FSStatus status; - FSCmdBlock cmd; - __wut_fs_file_t *file; +__wut_fsa_ftruncate(struct _reent *r, + void *fd, + off_t len) { + FSError status; + __wut_fsa_file_t *file; + __wut_fsa_device_t *deviceData; // Make sure length is non-negative if (!fd || len < 0) { @@ -15,18 +15,26 @@ __wut_fs_ftruncate(struct _reent *r, return -1; } + file = (__wut_fsa_file_t *) fd; + + deviceData = (__wut_fsa_device_t *) r->deviceData; + + std::scoped_lock lock(file->mutex); + // Set the new file size - FSInitCmdBlock(&cmd); - file = (__wut_fs_file_t *)fd; - status = FSSetPosFile(__wut_devoptab_fs_client, &cmd, file->fd, len, FS_ERROR_FLAG_ALL); + status = FSASetPosFile(deviceData->clientHandle, file->fd, len); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSASetPosFile(0x%08X, 0x%08X, 0x%08X) failed: %s\n", + deviceData->clientHandle, file->fd, len, FSAGetStatusStr(status)); + r->_errno = __wut_fsa_translate_error(status); return -1; } - status = FSTruncateFile(__wut_devoptab_fs_client, &cmd, file->fd, FS_ERROR_FLAG_ALL); + status = FSATruncateFile(deviceData->clientHandle, file->fd); if (status < 0) { - r->_errno = __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSATruncateFile(0x%08X, 0x%08X) failed: %s\n", + deviceData->clientHandle, file->fd, FSAGetStatusStr(status)); + r->_errno = __wut_fsa_translate_error(status); return -1; } diff --git a/libraries/wutdevoptab/devoptab_fsa_unlink.cpp b/libraries/wutdevoptab/devoptab_fsa_unlink.cpp index e5f6b6fd4..72360d845 100644 --- a/libraries/wutdevoptab/devoptab_fsa_unlink.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_unlink.cpp @@ -1,30 +1,34 @@ #include "devoptab_fsa.h" int -__wut_fs_unlink(struct _reent *r, - const char *name) -{ - FSStatus status; - FSCmdBlock cmd; +__wut_fsa_unlink(struct _reent *r, + const char *name) { + FSError status; char *fixedPath; + __wut_fsa_device_t *deviceData; if (!name) { r->_errno = EINVAL; return -1; } - fixedPath = __wut_fs_fixpath(r, name); + fixedPath = __wut_fsa_fixpath(r, name); if (!fixedPath) { + r->_errno = ENOMEM; return -1; } + deviceData = (__wut_fsa_device_t *) r->deviceData; - FSInitCmdBlock(&cmd); - status = FSRemove(__wut_devoptab_fs_client, &cmd, fixedPath, FS_ERROR_FLAG_ALL); - free(fixedPath); + status = FSARemove(deviceData->clientHandle, fixedPath); if (status < 0) { - r->_errno = status == FS_STATUS_EXISTS ? EISDIR : __wut_fs_translate_error(status); + WUT_DEBUG_REPORT("FSARemove(0x%08X, %s) failed: %s\n", + deviceData->clientHandle, fixedPath, FSAGetStatusStr(status)); + free(fixedPath); + r->_errno = __wut_fsa_translate_error(status); return -1; } + free(fixedPath); + return 0; } diff --git a/libraries/wutdevoptab/devoptab_fsa_utils.cpp b/libraries/wutdevoptab/devoptab_fsa_utils.cpp index bacc51665..5c540e495 100644 --- a/libraries/wutdevoptab/devoptab_fsa_utils.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_utils.cpp @@ -1,9 +1,84 @@ +#include #include "devoptab_fsa.h" -#include "../wutnewlib/wut_clock.h" + +#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 * +__wut_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 +__wut_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 * -__wut_fs_fixpath(struct _reent *r, - const char *path) { +__wut_fsa_fixpath(struct _reent *r, + const char *path) { char *p; char *fixedPath; @@ -17,30 +92,67 @@ __wut_fs_fixpath(struct _reent *r, p = (char *) path; } - size_t pathLength = strlen(p); - if (pathLength > FS_MAX_PATH) { - r->_errno = ENAMETOOLONG; - return NULL; - } - // wii u softlocks on empty strings so give expected error back - if (pathLength == 0) { + if (strlen(p) == 0) { r->_errno = ENOENT; return NULL; } - fixedPath = memalign(0x40, FS_MAX_PATH + 1); + int maxPathLength = PATH_MAX; + fixedPath = static_cast(memalign(0x40, maxPathLength)); if (!fixedPath) { + WUT_DEBUG_REPORT("__wut_fsa_fixpath: failed to allocate memory for fixedPath\n"); + r->_errno = ENOMEM; + return NULL; + } + + // Convert to an absolute path + if (p[0] != '\0' && p[0] != '\\' && p[0] != '/') { + __wut_fsa_device_t *deviceData = (__wut_fsa_device_t *) r->deviceData; + if (snprintf(fixedPath, maxPathLength, "%s/%s", deviceData->cwd, p) >= maxPathLength) { + WUT_DEBUG_REPORT("__wut_fsa_fixpath: fixedPath snprintf result (absolute) was truncated\n"); + } + } else { + if (snprintf(fixedPath, maxPathLength, "%s", p) >= maxPathLength) { + WUT_DEBUG_REPORT("__wut_fsa_fixpath: fixedPath snprintf result (relative) was truncated\n"); + } + } + + // Normalize path (resolve any ".", "..", or "//") + char *normalizedPath = strdup(fixedPath); + if (!normalizedPath) { + WUT_DEBUG_REPORT("__wut_fsa_fixpath: failed to allocate memory for normalizedPath\n"); + free(fixedPath); r->_errno = ENOMEM; return NULL; } - // cwd is handled by coreinit, so just strip the 'device:' if it exists - strcpy(fixedPath, p); + char *resPath = __wut_fsa_normpath(normalizedPath, fixedPath); + if (!resPath) { + WUT_DEBUG_REPORT("__wut_fsa_fixpath: failed to normalize path\n"); + free(normalizedPath); + free(fixedPath); + r->_errno = EIO; + return NULL; + } + + if (snprintf(fixedPath, maxPathLength, "%s", resPath) >= maxPathLength) { + WUT_DEBUG_REPORT("__wut_fsa_fixpath: fixedPath snprintf result (relative) was truncated\n"); + } + + free(normalizedPath); + + size_t pathLength = strlen(fixedPath); + if (pathLength > FS_MAX_PATH) { + free(fixedPath); + r->_errno = ENAMETOOLONG; + return NULL; + } + return fixedPath; } -mode_t __wut_fs_translate_stat_mode(FSStat* fsStat) { +mode_t __wut_fsa_translate_stat_mode(FSStat *fsStat) { mode_t retMode = 0; if ((fsStat->flags & FS_STAT_LINK) == FS_STAT_LINK) { @@ -53,7 +165,7 @@ mode_t __wut_fs_translate_stat_mode(FSStat* fsStat) { // Mounted paths like /vol/external01 have no flags set. // If no flag is set and the size is 0, it's a (root) dir retMode |= S_IFDIR; - } else if (fsStat->size > 0) { + } else if (fsStat->size > 0) { // Some regular Wii U files have no type info but will have a size retMode |= S_IFREG; } @@ -64,69 +176,91 @@ mode_t __wut_fs_translate_stat_mode(FSStat* fsStat) { return retMode | permissionMode; } -FSMode __wut_fs_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 __wut_fs_translate_time(FSTime timeValue) { - return (timeValue /1000000) + EPOCH_DIFF_SECS(WIIU_FSTIME_EPOCH_YEAR); -} - -void __wut_fs_translate_stat(FSStat* fsStat, struct stat* posStat) { +void __wut_fsa_translate_stat(FSAClientHandle clientHandle, FSStat *fsStat, ino_t ino, struct stat *posStat) { memset(posStat, 0, sizeof(struct stat)); - posStat->st_dev = (dev_t)__wut_devoptab_fs_client; - posStat->st_ino = fsStat->entryId; - posStat->st_mode = __wut_fs_translate_stat_mode(fsStat); + posStat->st_dev = (dev_t) clientHandle; + posStat->st_ino = ino; + posStat->st_mode = __wut_fsa_translate_stat_mode(fsStat); posStat->st_nlink = 1; posStat->st_uid = fsStat->owner; posStat->st_gid = fsStat->group; posStat->st_rdev = posStat->st_dev; posStat->st_size = fsStat->size; - posStat->st_atime = __wut_fs_translate_time(fsStat->modified); - posStat->st_ctime = __wut_fs_translate_time(fsStat->created); - posStat->st_mtime = __wut_fs_translate_time(fsStat->modified); + posStat->st_atime = __wut_fsa_translate_time(fsStat->modified); + posStat->st_ctime = __wut_fsa_translate_time(fsStat->created); + posStat->st_mtime = __wut_fsa_translate_time(fsStat->modified); posStat->st_blksize = 512; posStat->st_blocks = (posStat->st_size + posStat->st_blksize - 1) / posStat->st_size; } -int -__wut_fs_translate_error(FSStatus error) { - switch ((int) error) { - case FS_STATUS_END: +int __wut_fsa_translate_error(FSError error) { + switch (error) { + case FS_ERROR_END_OF_DIR: + case FS_ERROR_END_OF_FILE: return ENOENT; - case FS_STATUS_CANCELLED: - return ECANCELED; - case FS_STATUS_EXISTS: + case FS_ERROR_ALREADY_EXISTS: return EEXIST; - case FS_STATUS_MEDIA_ERROR: + case FS_ERROR_MEDIA_ERROR: return EIO; - case FS_STATUS_NOT_FOUND: + case FS_ERROR_NOT_FOUND: return ENOENT; - case FS_STATUS_PERMISSION_ERROR: + case FS_ERROR_PERMISSION_ERROR: return EPERM; - case FS_STATUS_STORAGE_FULL: + case FS_ERROR_STORAGE_FULL: return ENOSPC; - case FS_STATUS_FILE_TOO_BIG: + case FS_ERROR_BUSY: + return EBUSY; + case FS_ERROR_CANCELLED: + return ECANCELED; + case FS_ERROR_FILE_TOO_BIG: return EFBIG; - case FS_STATUS_NOT_DIR: + case FS_ERROR_INVALID_PATH: + return ENAMETOOLONG; + case FS_ERROR_NOT_DIR: return ENOTDIR; - case FS_STATUS_NOT_FILE: + case FS_ERROR_NOT_FILE: return EISDIR; - case FS_STATUS_MAX: - return ENFILE; - case FS_STATUS_ACCESS_ERROR: - return EACCES; - case FS_STATUS_JOURNAL_FULL: - return ENOSPC; - case FS_STATUS_UNSUPPORTED_CMD: + case FS_ERROR_OUT_OF_RANGE: + return EINVAL; + case FS_ERROR_UNSUPPORTED_COMMAND: return ENOTSUP; - case FS_STATUS_MEDIA_NOT_READY: - return EOWNERDEAD; - case FS_STATUS_ALREADY_OPEN: - case FS_STATUS_CORRUPTED: - case FS_STATUS_FATAL_ERROR: + case FS_ERROR_WRITE_PROTECTED: + return EROFS; + case FS_ERROR_NOT_INIT: + return ENODEV; + case FS_ERROR_MAX_MOUNT_POINTS: + case FS_ERROR_MAX_VOLUMES: + case FS_ERROR_MAX_CLIENTS: + case FS_ERROR_MAX_FILES: + case FS_ERROR_MAX_DIRS: + return EMFILE; + case FS_ERROR_ALREADY_OPEN: + return EBUSY; + case FS_ERROR_NOT_EMPTY: + return ENOTEMPTY; + case FS_ERROR_ACCESS_ERROR: + return EACCES; + case FS_ERROR_DATA_CORRUPTED: + return EILSEQ; + case FS_ERROR_JOURNAL_FULL: + return EBUSY; + case FS_ERROR_UNAVAILABLE_COMMAND: + return EBUSY; + case FS_ERROR_INVALID_PARAM: + return EBUSY; + case FS_ERROR_INVALID_BUFFER: + case FS_ERROR_INVALID_ALIGNMENT: + case FS_ERROR_INVALID_CLIENTHANDLE: + case FS_ERROR_INVALID_FILEHANDLE: + case FS_ERROR_INVALID_DIRHANDLE: + return EINVAL; + case FS_ERROR_OUT_OF_RESOURCES: + return ENOMEM; + case FS_ERROR_MEDIA_NOT_READY: + return EIO; + case FS_ERROR_INVALID_MEDIA: + return EIO; + default: return EIO; } - return (int) error; } diff --git a/libraries/wutdevoptab/devoptab_fsa_utimes.cpp b/libraries/wutdevoptab/devoptab_fsa_utimes.cpp deleted file mode 100644 index 2f07f5eac..000000000 --- a/libraries/wutdevoptab/devoptab_fsa_utimes.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "devoptab_fsa.h" - -int -__wut_fs_utimes(struct _reent *r, - const char *filename, - const struct timeval times[2]) -{ - r->_errno = ENOSYS; - return -1; -} diff --git a/libraries/wutdevoptab/devoptab_fsa_write.cpp b/libraries/wutdevoptab/devoptab_fsa_write.cpp index e9b18fce5..199b0bc7f 100644 --- a/libraries/wutdevoptab/devoptab_fsa_write.cpp +++ b/libraries/wutdevoptab/devoptab_fsa_write.cpp @@ -1,13 +1,18 @@ #include "devoptab_fsa.h" +#include + +ssize_t __wut_fsa_write(struct _reent *r, void *fd, const char *ptr, size_t len) { + FSError status; + __wut_fsa_file_t *file; + __wut_fsa_device_t *deviceData; -ssize_t __wut_fs_write(struct _reent *r, void *fd, const char *ptr, size_t len) { if (!fd || !ptr) { r->_errno = EINVAL; return -1; } // Check that the file was opened with write access - __wut_fs_file_t *file = (__wut_fs_file_t *) fd; + file = (__wut_fsa_file_t *) fd; if ((file->flags & O_ACCMODE) == O_RDONLY) { r->_errno = EBADF; return -1; @@ -16,12 +21,13 @@ ssize_t __wut_fs_write(struct _reent *r, void *fd, const char *ptr, size_t len) // cache-aligned, cache-line-sized __attribute__((aligned(0x40))) uint8_t alignedBuffer[0x40]; - FSCmdBlock cmd; - FSInitCmdBlock(&cmd); + deviceData = (__wut_fsa_device_t *) r->deviceData; + + std::scoped_lock lock(file->mutex); // 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. - if(file->flags & O_APPEND) { + if (file->flags & O_APPEND) { file->offset = file->appendOffset; } @@ -44,18 +50,24 @@ ssize_t __wut_fs_write(struct _reent *r, void *fd, const char *ptr, size_t len) size &= ~0x3F; } + // Limit each request to 256 KiB + if (size > 0x40000) { + size = 0x40000; + } + if (tmp == alignedBuffer) { memcpy(tmp, ptr, size); } - FSStatus status = FSWriteFile(__wut_devoptab_fs_client, &cmd, tmp, 1, size, - file->fd, 0, FS_ERROR_FLAG_ALL); + status = FSAWriteFile(deviceData->clientHandle, tmp, 1, size, file->fd, 0); if (status < 0) { + WUT_DEBUG_REPORT("FSAWriteFile(0x%08X, 0x%08X, 1, 0x%08X, 0x%08X, 0) (%s) failed: %s\n", + deviceData->clientHandle, tmp, size, file->fd, file->fullPath, FSAGetStatusStr(status)); if (bytesWritten != 0) { return bytesWritten; // error after partial write } - r->_errno = __wut_fs_translate_error(status); + r->_errno = __wut_fsa_translate_error(status); return -1; } @@ -64,7 +76,7 @@ ssize_t __wut_fs_write(struct _reent *r, void *fd, const char *ptr, size_t len) bytesWritten += status; ptr += status; - if (status != size) { + if ((size_t) status != size) { return bytesWritten; // partial write } }