mirror of
https://github.com/devkitPro/wut.git
synced 2026-04-25 16:20:20 -05:00
wutdevoptab: Implement devoptab using FSA functions
This commit is contained in:
parent
e492c31d06
commit
4083224b51
|
|
@ -9,6 +9,9 @@
|
|||
#include "wut_structsize.h"
|
||||
#include "wut_types.h"
|
||||
#include "wut_rplwrap.h"
|
||||
#ifdef DEBUG
|
||||
#include <coreinit/debug.h>
|
||||
#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
|
||||
24
libraries/wutdevoptab/MutexWrapper.h
Normal file
24
libraries/wutdevoptab/MutexWrapper.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include <coreinit/mutex.h>
|
||||
#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{};
|
||||
};
|
||||
|
|
@ -1,130 +1,120 @@
|
|||
#include "devoptab_fsa.h"
|
||||
#include <cstdio>
|
||||
|
||||
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,
|
||||
};
|
||||
__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,
|
||||
};
|
||||
|
||||
FSClient *
|
||||
__wut_devoptab_fs_client = NULL;
|
||||
|
||||
static BOOL
|
||||
__wut_fs_initialised = FALSE;
|
||||
__wut_fsa_device_t __wut_fsa_device_data = {};
|
||||
|
||||
static BOOL
|
||||
__wut_sd_mounted = FALSE;
|
||||
FSError __init_wut_devoptab() {
|
||||
FSError rc;
|
||||
|
||||
static char
|
||||
sMountPath[0x80];
|
||||
|
||||
FSStatus
|
||||
__init_wut_devoptab()
|
||||
{
|
||||
FSStatus rc = 0;
|
||||
|
||||
if (__wut_fs_initialised) {
|
||||
return 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];
|
||||
__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;
|
||||
|
||||
FSInit();
|
||||
rc = FSAddClient(__wut_devoptab_fs_client, -1);
|
||||
|
||||
if (rc < 0) {
|
||||
free(__wut_devoptab_fs_client);
|
||||
return rc;
|
||||
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;
|
||||
}
|
||||
|
||||
rc = FSMount(__wut_devoptab_fs_client, &fsCmd, &mountSource, sMountPath, sizeof(sMountPath), FS_ERROR_FLAG_ALL);
|
||||
|
||||
if (rc >= 0) {
|
||||
__wut_sd_mounted = TRUE;
|
||||
// chdir to SD root for general use
|
||||
strcpy(workDir, "fs:");
|
||||
strcat(workDir, sMountPath);
|
||||
chdir(workDir);
|
||||
}
|
||||
} else {
|
||||
FSDelClient(__wut_devoptab_fs_client, FS_ERROR_FLAG_ALL);
|
||||
free(__wut_devoptab_fs_client);
|
||||
return dev;
|
||||
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;
|
||||
}
|
||||
|
||||
__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");
|
||||
|
||||
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 {
|
||||
__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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#pragma once
|
||||
#include <coreinit/filesystem.h>
|
||||
|
||||
#include <coreinit/filesystem_fsa.h>
|
||||
#include <coreinit/debug.h>
|
||||
#include <coreinit/mutex.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
|
@ -11,81 +14,124 @@
|
|||
#include <sys/iosupport.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
#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;
|
||||
typedef struct {
|
||||
//! Should be set to FSA_DIRITER_MAGIC
|
||||
uint32_t magic;
|
||||
|
||||
//! FS handle
|
||||
FSDirectoryHandle fd;
|
||||
//! FS directory handle
|
||||
FSADirectoryHandle fd;
|
||||
|
||||
//! Temporary storage for reading entries
|
||||
FSDirectoryEntry entry_data;
|
||||
} __wut_fs_dir_t;
|
||||
//! Temporary storage for reading entries
|
||||
FSADirectoryEntry entry_data;
|
||||
|
||||
#define FS_DIRITER_MAGIC 0x77696975
|
||||
//! Current directory path
|
||||
char fullPath[FS_MAX_PATH + 1];
|
||||
|
||||
extern FSClient *
|
||||
__wut_devoptab_fs_client;
|
||||
//! Guard dir access
|
||||
MutexWrapper mutex;
|
||||
} __wut_fsa_dir_t;
|
||||
|
||||
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]);
|
||||
#define FSA_DIRITER_MAGIC 0x77696975
|
||||
|
||||
// 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);
|
||||
#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
|
||||
|
|
@ -1,29 +1,44 @@
|
|||
#include <cstdio>
|
||||
#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;
|
||||
|
||||
status = FSAChangeDir(deviceData->clientHandle, fixedPath);
|
||||
if (status < 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
FSInitCmdBlock(&cmd);
|
||||
status = FSChangeDir(__wut_devoptab_fs_client, &cmd, fixedPath, FS_ERROR_FLAG_ALL);
|
||||
free(fixedPath);
|
||||
if (status < 0) {
|
||||
r->_errno = __wut_fs_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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +1,38 @@
|
|||
#include <sys/stat.h>
|
||||
#include "devoptab_fsa.h"
|
||||
#include <mutex>
|
||||
#include <sys/stat.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,29 @@
|
|||
#include "devoptab_fsa.h"
|
||||
#include <mutex>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,29 @@
|
|||
#include "devoptab_fsa.h"
|
||||
#include <mutex>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,33 +1,55 @@
|
|||
#include "devoptab_fsa.h"
|
||||
#include <mutex>
|
||||
#include <sys/syslimits.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,53 @@
|
|||
#include "devoptab_fsa.h"
|
||||
#include <mutex>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,28 @@
|
|||
#include "devoptab_fsa.h"
|
||||
#include <mutex>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,30 +1,35 @@
|
|||
#include "devoptab_fsa.h"
|
||||
#include <mutex>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,29 @@
|
|||
#include "devoptab_fsa.h"
|
||||
#include <mutex>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,22 @@
|
|||
#include "devoptab_fsa.h"
|
||||
#include <mutex>
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,18 @@
|
|||
#include "devoptab_fsa.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <sys/param.h>
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
deviceData = (__wut_fsa_device_t *) r->deviceData;
|
||||
|
||||
status = FSARename(deviceData->clientHandle, fixedOldPath, fixedNewPath);
|
||||
if (status < 0) {
|
||||
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);
|
||||
|
||||
if (status < 0) {
|
||||
r->_errno = __wut_fs_translate_error(status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,55 +1,56 @@
|
|||
#include "devoptab_fsa.h"
|
||||
#include <mutex>
|
||||
|
||||
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;
|
||||
|
||||
deviceData = (__wut_fsa_device_t *) r->deviceData;
|
||||
|
||||
std::scoped_lock lock(file->mutex);
|
||||
|
||||
// Find the offset to see from
|
||||
switch(whence) {
|
||||
// Set absolute position; start offset is 0
|
||||
case SEEK_SET:
|
||||
offset = 0;
|
||||
break;
|
||||
|
||||
// Set position relative to the current position
|
||||
case SEEK_CUR:
|
||||
offset = file->offset;
|
||||
break;
|
||||
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
#include "devoptab_fsa.h"
|
||||
#include <mutex>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
status = FSARemove(deviceData->clientHandle, fixedPath);
|
||||
if (status < 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
FSInitCmdBlock(&cmd);
|
||||
status = FSRemove(__wut_devoptab_fs_client, &cmd, fixedPath, FS_ERROR_FLAG_ALL);
|
||||
free(fixedPath);
|
||||
if (status < 0) {
|
||||
r->_errno = status == FS_STATUS_EXISTS ? EISDIR : __wut_fs_translate_error(status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,84 @@
|
|||
#include <cstdio>
|
||||
#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<char *>(memalign(0x40, maxPathLength));
|
||||
if (!fixedPath) {
|
||||
WUT_DEBUG_REPORT("__wut_fsa_fixpath: failed to allocate memory for fixedPath\n");
|
||||
r->_errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// cwd is handled by coreinit, so just strip the 'device:' if it exists
|
||||
strcpy(fixedPath, p);
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,13 +1,18 @@
|
|||
#include "devoptab_fsa.h"
|
||||
#include <mutex>
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user