mirror of
https://github.com/wiiu-env/wut.git
synced 2025-01-06 13:58:18 +01:00
Add devoptab support for sdcard.
This commit is contained in:
parent
2f7a96e381
commit
479e9ad677
@ -11,9 +11,6 @@
|
||||
* want to run in parallel. You must ensure the previous filesystem command
|
||||
* has been completed before reusing the same FSCmdBlock, you do not need to
|
||||
* reinitialise an FSCmdBlock before reusing it.
|
||||
*
|
||||
* Calling fsDevInit initializes the stdlib devoptab, allowing for standard
|
||||
* file IO.
|
||||
* @{
|
||||
*/
|
||||
|
||||
@ -196,12 +193,6 @@ struct FSMountSource
|
||||
};
|
||||
CHECK_SIZE(FSMountSource, 0x300);
|
||||
|
||||
FSStatus
|
||||
fsDevInit();
|
||||
|
||||
FSStatus
|
||||
fsDevExit();
|
||||
|
||||
void
|
||||
FSInit();
|
||||
|
||||
|
@ -4,5 +4,6 @@ project(libraries C)
|
||||
add_subdirectory(libdefaultheap)
|
||||
add_subdirectory(libgfd)
|
||||
add_subdirectory(libwhb)
|
||||
add_subdirectory(wutdevoptab)
|
||||
add_subdirectory(wutnewlib)
|
||||
add_subdirectory(wutstdc++)
|
||||
|
34
libraries/wutdevoptab/CMakeLists.txt
Normal file
34
libraries/wutdevoptab/CMakeLists.txt
Normal file
@ -0,0 +1,34 @@
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
project(wutdevoptab C)
|
||||
|
||||
add_library(wutdevoptab
|
||||
devoptab_fs.c
|
||||
devoptab_fs_chdir.c
|
||||
devoptab_fs_chmod.c
|
||||
devoptab_fs_close.c
|
||||
devoptab_fs_dirclose.c
|
||||
devoptab_fs_dirnext.c
|
||||
devoptab_fs_diropen.c
|
||||
devoptab_fs_dirreset.c
|
||||
devoptab_fs_fchmod.c
|
||||
devoptab_fs_fstat.c
|
||||
devoptab_fs_fsync.c
|
||||
devoptab_fs_getmtime.c
|
||||
devoptab_fs_link.c
|
||||
devoptab_fs_mkdir.c
|
||||
devoptab_fs_open.c
|
||||
devoptab_fs_read.c
|
||||
devoptab_fs_rename.c
|
||||
devoptab_fs_rmdir.c
|
||||
devoptab_fs_seek.c
|
||||
devoptab_fs_stat.c
|
||||
devoptab_fs_statvfs.c
|
||||
devoptab_fs_truncate.c
|
||||
devoptab_fs_unlink.c
|
||||
devoptab_fs_utils.c
|
||||
devoptab_fs_write.c)
|
||||
|
||||
target_include_directories(wutdevoptab PRIVATE "${WUT_ROOT}/include")
|
||||
|
||||
install(TARGETS wutdevoptab
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_PREFIX}/lib")
|
109
libraries/wutdevoptab/devoptab_fs.c
Normal file
109
libraries/wutdevoptab/devoptab_fs.c
Normal file
@ -0,0 +1,109 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
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,
|
||||
.deviceData = NULL,
|
||||
.chmod_r = __wut_fs_chmod,
|
||||
.fchmod_r = __wut_fs_fchmod,
|
||||
.rmdir_r = __wut_fs_rmdir,
|
||||
};
|
||||
|
||||
FSClient *
|
||||
__wut_devoptab_fs_client = NULL;
|
||||
|
||||
static bool
|
||||
__wut_fs_initialised = false;
|
||||
|
||||
FSStatus
|
||||
__init_wut_devoptab()
|
||||
{
|
||||
FSStatus rc = 0;
|
||||
|
||||
if (__wut_fs_initialised) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
__wut_devoptab_fs_client = memalign(0x20, sizeof(FSClient));
|
||||
FSCmdBlock fsCmd;
|
||||
FSMountSource mountSource;
|
||||
char mountPath[0x80];
|
||||
char workDir[0x83];
|
||||
|
||||
FSInit();
|
||||
rc = FSAddClient(__wut_devoptab_fs_client, -1);
|
||||
|
||||
if (rc < 0) {
|
||||
free(__wut_devoptab_fs_client);
|
||||
return rc;
|
||||
}
|
||||
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
if (rc >= 0) {
|
||||
int dev = AddDevice(&__wut_fs_devoptab);
|
||||
|
||||
if(dev != -1) {
|
||||
setDefaultDevice(dev);
|
||||
__wut_fs_initialised = true;
|
||||
|
||||
// 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, mountPath, 0x80, -1);
|
||||
|
||||
if (rc >= 0) {
|
||||
// chdir to SD root for general use
|
||||
strcpy(workDir, "fs:");
|
||||
strcat(workDir, mountPath);
|
||||
chdir(workDir);
|
||||
}
|
||||
} else {
|
||||
FSDelClient(__wut_devoptab_fs_client, -1);
|
||||
free(__wut_devoptab_fs_client);
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
FSStatus
|
||||
__fini_wut_devoptab()
|
||||
{
|
||||
FSStatus rc = 0;
|
||||
|
||||
if (!__wut_fs_initialised) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
FSDelClient(__wut_devoptab_fs_client, -1);
|
||||
free(__wut_devoptab_fs_client);
|
||||
return rc;
|
||||
}
|
83
libraries/wutdevoptab/devoptab_fs.h
Normal file
83
libraries/wutdevoptab/devoptab_fs.h
Normal file
@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
#include <coreinit/filesystem.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/iosupport.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
* Open file struct
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
//! FS handle
|
||||
FSFileHandle fd;
|
||||
|
||||
//! Flags used in open(2)
|
||||
int flags;
|
||||
|
||||
//! Current file offset
|
||||
uint32_t offset;
|
||||
} __wut_fs_file_t;
|
||||
|
||||
|
||||
/**
|
||||
* Open directory struct
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
//! Should be set to FS_DIRITER_MAGIC
|
||||
u32 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);
|
||||
|
||||
// devoptab_fs_utils.c
|
||||
char * __wut_fs_fixpath(struct _reent *r, const char *path);
|
||||
int __wut_fs_translate_error(FSStatus error);
|
33
libraries/wutdevoptab/devoptab_fs_chdir.c
Normal file
33
libraries/wutdevoptab/devoptab_fs_chdir.c
Normal file
@ -0,0 +1,33 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_chdir(struct _reent *r,
|
||||
const char *name)
|
||||
{
|
||||
FSStatus rc;
|
||||
|
||||
if (name == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *path = __wut_fs_fixpath(r, name);
|
||||
|
||||
if (!path) {
|
||||
r->_errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
rc = FSChangeDir(__wut_devoptab_fs_client, &fsCmd, path, -1);
|
||||
free(path);
|
||||
|
||||
if (rc >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
29
libraries/wutdevoptab/devoptab_fs_chmod.c
Normal file
29
libraries/wutdevoptab/devoptab_fs_chmod.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_chmod(struct _reent *r,
|
||||
const char *path,
|
||||
mode_t mode)
|
||||
{
|
||||
FSStatus rc;
|
||||
char *path_fix = __wut_fs_fixpath(r, path);
|
||||
|
||||
if (!path_fix) {
|
||||
r->_errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
rc = FSChangeMode(__wut_devoptab_fs_client, &fsCmd, path_fix, (FSMode)mode, -1);
|
||||
free(path_fix);
|
||||
|
||||
if (rc >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
22
libraries/wutdevoptab/devoptab_fs_close.c
Normal file
22
libraries/wutdevoptab/devoptab_fs_close.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_close(struct _reent *r,
|
||||
void *fd)
|
||||
{
|
||||
FSStatus rc;
|
||||
__wut_fs_file_t *file = (__wut_fs_file_t *)fd;
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
rc = FSCloseFile(__wut_devoptab_fs_client, &fsCmd, file->fd, -1);
|
||||
|
||||
if (rc >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
22
libraries/wutdevoptab/devoptab_fs_dirclose.c
Normal file
22
libraries/wutdevoptab/devoptab_fs_dirclose.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_dirclose(struct _reent *r,
|
||||
DIR_ITER *dirState)
|
||||
{
|
||||
FSStatus rc;
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
__wut_fs_dir_t *dir = (__wut_fs_dir_t *)(dirState->dirStruct);
|
||||
rc = FSCloseDir(__wut_devoptab_fs_client, &fsCmd, dir->fd, -1);
|
||||
|
||||
if (rc >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
49
libraries/wutdevoptab/devoptab_fs_dirnext.c
Normal file
49
libraries/wutdevoptab/devoptab_fs_dirnext.c
Normal file
@ -0,0 +1,49 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_dirnext(struct _reent *r,
|
||||
DIR_ITER *dirState,
|
||||
char *filename,
|
||||
struct stat *filestat)
|
||||
{
|
||||
FSStatus rc;
|
||||
__wut_fs_dir_t *dir = (__wut_fs_dir_t *)(dirState->dirStruct);
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
// Fetch the next dir
|
||||
memset(&dir->entry_data, 0, sizeof(dir->entry_data));
|
||||
rc = FSReadDir(__wut_devoptab_fs_client, &fsCmd, dir->fd, &dir->entry_data, -1);
|
||||
|
||||
if (rc < 0) {
|
||||
// There are no more entries; ENOENT signals end-of-directory
|
||||
r->_errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rc >= 0) {
|
||||
memset(filestat, 0, sizeof(struct stat));
|
||||
|
||||
// Fill in the stat info
|
||||
filestat->st_ino = 0;
|
||||
|
||||
if (dir->entry_data.info.flags & FS_STAT_DIRECTORY) {
|
||||
filestat->st_mode = S_IFDIR;
|
||||
} else {
|
||||
filestat->st_mode = S_IFREG;
|
||||
}
|
||||
|
||||
filestat->st_uid = dir->entry_data.info.owner;
|
||||
filestat->st_gid = dir->entry_data.info.group;
|
||||
filestat->st_size = dir->entry_data.info.size;
|
||||
|
||||
memset(filename, 0, NAME_MAX);
|
||||
strcpy(filename, dir->entry_data.name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
40
libraries/wutdevoptab/devoptab_fs_diropen.c
Normal file
40
libraries/wutdevoptab/devoptab_fs_diropen.c
Normal file
@ -0,0 +1,40 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
DIR_ITER *
|
||||
__wut_fs_diropen(struct _reent *r,
|
||||
DIR_ITER *dirState,
|
||||
const char *path)
|
||||
{
|
||||
FSDirectoryHandle fd;
|
||||
FSStatus rc;
|
||||
|
||||
if (path == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *path_fixed = __wut_fs_fixpath(r,path);
|
||||
|
||||
if (!path_fixed) {
|
||||
r->_errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
__wut_fs_dir_t *dir = (__wut_fs_dir_t *)(dirState->dirStruct);
|
||||
rc = FSOpenDir(__wut_devoptab_fs_client, &fsCmd, path_fixed, &fd, -1);
|
||||
|
||||
if (rc >= 0) {
|
||||
dir->magic = FS_DIRITER_MAGIC;
|
||||
dir->fd = fd;
|
||||
memset(&dir->entry_data, 0, sizeof(dir->entry_data));
|
||||
free(path_fixed);
|
||||
return dirState;
|
||||
}
|
||||
|
||||
free(path_fixed);
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return NULL;
|
||||
}
|
23
libraries/wutdevoptab/devoptab_fs_dirreset.c
Normal file
23
libraries/wutdevoptab/devoptab_fs_dirreset.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_dirreset(struct _reent *r,
|
||||
DIR_ITER *dirState)
|
||||
{
|
||||
FSStatus rc;
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
__wut_fs_dir_t *dir = (__wut_fs_dir_t *)(dirState->dirStruct);
|
||||
rc = FSRewindDir(__wut_devoptab_fs_client, &fsCmd, dir->fd, -1);
|
||||
|
||||
if (rc >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
11
libraries/wutdevoptab/devoptab_fs_fchmod.c
Normal file
11
libraries/wutdevoptab/devoptab_fs_fchmod.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_fchmod(struct _reent *r,
|
||||
void *fd,
|
||||
mode_t mode)
|
||||
{
|
||||
//TODO: FSChangeMode and FSStatFile?
|
||||
r->_errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
30
libraries/wutdevoptab/devoptab_fs_fstat.c
Normal file
30
libraries/wutdevoptab/devoptab_fs_fstat.c
Normal file
@ -0,0 +1,30 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_fstat(struct _reent *r,
|
||||
void *fd,
|
||||
struct stat *st)
|
||||
{
|
||||
FSStatus rc;
|
||||
FSStat fsstat;
|
||||
__wut_fs_file_t *file = (__wut_fs_file_t *)fd;
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
rc = FSGetStatFile(__wut_devoptab_fs_client, &fsCmd, file->fd, &fsstat, -1);
|
||||
|
||||
if (rc >= 0) {
|
||||
memset(st, 0, sizeof(struct stat));
|
||||
st->st_size = fsstat.size;
|
||||
st->st_uid = fsstat.owner;
|
||||
st->st_gid = fsstat.group;
|
||||
st->st_nlink = 1;
|
||||
st->st_mode = fsstat.mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
22
libraries/wutdevoptab/devoptab_fs_fsync.c
Normal file
22
libraries/wutdevoptab/devoptab_fs_fsync.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_fsync(struct _reent *r,
|
||||
void *fd)
|
||||
{
|
||||
FSStatus rc;
|
||||
__wut_fs_file_t *file = (__wut_fs_file_t *)fd;
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
rc = FSFlushFile(__wut_devoptab_fs_client, &fsCmd, file->fd, -1);
|
||||
|
||||
if (rc >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
9
libraries/wutdevoptab/devoptab_fs_getmtime.c
Normal file
9
libraries/wutdevoptab/devoptab_fs_getmtime.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_getmtime(const char *name,
|
||||
u64 *mtime)
|
||||
{
|
||||
// TODO: Last modified time can probably be get via FSGetStatFile
|
||||
return -1;
|
||||
}
|
10
libraries/wutdevoptab/devoptab_fs_link.c
Normal file
10
libraries/wutdevoptab/devoptab_fs_link.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_link(struct _reent *r,
|
||||
const char *existing,
|
||||
const char *newLink)
|
||||
{
|
||||
r->_errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
38
libraries/wutdevoptab/devoptab_fs_mkdir.c
Normal file
38
libraries/wutdevoptab/devoptab_fs_mkdir.c
Normal file
@ -0,0 +1,38 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_mkdir(struct _reent *r,
|
||||
const char *path,
|
||||
int mode)
|
||||
{
|
||||
FSError rc;
|
||||
|
||||
if (path == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *path_fix = __wut_fs_fixpath(r, path);
|
||||
|
||||
if (!path_fix) {
|
||||
r->_errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
// TODO: Use mode to set directory attributes.
|
||||
rc = FSMakeDir(__wut_devoptab_fs_client, &fsCmd, path_fix, -1);
|
||||
free(path_fix);
|
||||
|
||||
if (rc == FS_ERROR_ALREADY_EXISTS) {
|
||||
r->_errno = EEXIST;
|
||||
return -1;
|
||||
} else if(rc >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
64
libraries/wutdevoptab/devoptab_fs_open.c
Normal file
64
libraries/wutdevoptab/devoptab_fs_open.c
Normal file
@ -0,0 +1,64 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_open(struct _reent *r,
|
||||
void *fileStruct,
|
||||
const char *path,
|
||||
int flags,
|
||||
int mode)
|
||||
{
|
||||
FSFileHandle fd;
|
||||
FSStatus rc;
|
||||
|
||||
if (path == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *path_fixed = __wut_fs_fixpath(r,path);
|
||||
if (!path_fixed) {
|
||||
r->_errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get pointer to our data
|
||||
__wut_fs_file_t *file = (__wut_fs_file_t *)fileStruct;
|
||||
const char *fs_mode;
|
||||
|
||||
// Map flags to open modes
|
||||
if (flags == 0) {
|
||||
fs_mode = "r";
|
||||
} else if (flags == 2) {
|
||||
fs_mode = "r+";
|
||||
} else if (flags == 0x601) {
|
||||
fs_mode = "w";
|
||||
} else if(flags == 0x602) {
|
||||
fs_mode = "w+";
|
||||
} else if(flags == 0x209) {
|
||||
fs_mode = "a";
|
||||
} else if(flags == 0x20A) {
|
||||
fs_mode = "a+";
|
||||
} else {
|
||||
free(path_fixed);
|
||||
r->_errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
// Open the file
|
||||
rc = FSOpenFile(__wut_devoptab_fs_client, &fsCmd, path_fixed, fs_mode, &fd, -1);
|
||||
|
||||
if (rc >= 0) {
|
||||
file->fd = fd;
|
||||
file->flags = (flags & (O_ACCMODE|O_APPEND|O_SYNC));
|
||||
FSGetPosFile(__wut_devoptab_fs_client, &fsCmd, fd, &file->offset, -1);
|
||||
free(path_fixed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(path_fixed);
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
70
libraries/wutdevoptab/devoptab_fs_read.c
Normal file
70
libraries/wutdevoptab/devoptab_fs_read.c
Normal file
@ -0,0 +1,70 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
ssize_t
|
||||
__wut_fs_read(struct _reent *r,
|
||||
void *fd,
|
||||
char *ptr,
|
||||
size_t len)
|
||||
{
|
||||
FSStatus rc;
|
||||
u32 bytes, bytesRead = 0;
|
||||
__wut_fs_file_t *file = (__wut_fs_file_t *)fd;
|
||||
|
||||
// Check that the file was opened with read access
|
||||
if ((file->flags & O_ACCMODE) == O_WRONLY) {
|
||||
r->_errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
FSStat fsstat;
|
||||
rc = FSGetStatFile(__wut_devoptab_fs_client, &fsCmd, file->fd, &fsstat, -1);
|
||||
|
||||
if(rc < 0) {
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Copy to internal buffer and read in chunks.
|
||||
u8 *tmp_buffer = memalign(0x40, 8192);
|
||||
|
||||
while(len > 0) {
|
||||
size_t toRead = len;
|
||||
|
||||
if (toRead > 8192) {
|
||||
toRead = 8192;
|
||||
}
|
||||
|
||||
// Write the data
|
||||
rc = FSReadFile(__wut_devoptab_fs_client, &fsCmd, tmp_buffer, 1, toRead, file->fd, 0, -1);
|
||||
|
||||
if(rc <= 0)
|
||||
{
|
||||
free(tmp_buffer);
|
||||
|
||||
// Return partial transfer
|
||||
if (bytesRead > 0) {
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
} else {
|
||||
bytes = rc;
|
||||
}
|
||||
|
||||
// Copy to internal buffer
|
||||
memcpy(ptr, tmp_buffer, bytes);
|
||||
|
||||
file->offset += bytes;
|
||||
bytesRead += bytes;
|
||||
ptr += bytes;
|
||||
len -= bytes;
|
||||
}
|
||||
|
||||
free(tmp_buffer);
|
||||
return bytesRead;
|
||||
}
|
46
libraries/wutdevoptab/devoptab_fs_rename.c
Normal file
46
libraries/wutdevoptab/devoptab_fs_rename.c
Normal file
@ -0,0 +1,46 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_rename(struct _reent *r,
|
||||
const char *oldName,
|
||||
const char *newName)
|
||||
{
|
||||
FSStatus rc;
|
||||
|
||||
if (oldName == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (newName == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *path_old = __wut_fs_fixpath(r, oldName);
|
||||
|
||||
if (!path_old) {
|
||||
r->_errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *path_new = __wut_fs_fixpath(r, newName);
|
||||
|
||||
if (!path_new) {
|
||||
r->_errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
rc = FSRename(__wut_devoptab_fs_client, &fsCmd, path_old, path_new, -1);
|
||||
free(path_old);
|
||||
free(path_new);
|
||||
|
||||
if (rc >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
33
libraries/wutdevoptab/devoptab_fs_rmdir.c
Normal file
33
libraries/wutdevoptab/devoptab_fs_rmdir.c
Normal file
@ -0,0 +1,33 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_rmdir(struct _reent *r,
|
||||
const char *name)
|
||||
{
|
||||
FSStatus rc;
|
||||
|
||||
if (name == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *path_fix = __wut_fs_fixpath(r, name);
|
||||
|
||||
if (!path_fix) {
|
||||
r->_errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
rc = FSRemove(__wut_devoptab_fs_client, &fsCmd, path_fix, -1);
|
||||
free(path_fix);
|
||||
|
||||
if (rc >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
64
libraries/wutdevoptab/devoptab_fs_seek.c
Normal file
64
libraries/wutdevoptab/devoptab_fs_seek.c
Normal file
@ -0,0 +1,64 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
off_t
|
||||
__wut_fs_seek(struct _reent *r,
|
||||
void *fd,
|
||||
off_t pos,
|
||||
int whence)
|
||||
{
|
||||
FSStatus rc;
|
||||
u64 offset;
|
||||
__wut_fs_file_t *file = (__wut_fs_file_t *)fd;
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
FSStat fsstat;
|
||||
rc = FSGetStatFile(__wut_devoptab_fs_client, &fsCmd, file->fd, &fsstat, -1);
|
||||
|
||||
if (rc < 0) {
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 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:
|
||||
offset = fsstat.size;
|
||||
break;
|
||||
|
||||
// An invalid option was provided
|
||||
default:
|
||||
r->_errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: A better check that prevents overflow.
|
||||
if(pos < 0 && offset < -pos) {
|
||||
// Don't allow seek to before the beginning of the file
|
||||
r->_errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Update the current offset
|
||||
file->offset = offset + pos;
|
||||
FSStatus result = FSSetPosFile(__wut_devoptab_fs_client, &fsCmd, file->fd, file->offset, -1);
|
||||
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return file->offset;
|
||||
}
|
42
libraries/wutdevoptab/devoptab_fs_stat.c
Normal file
42
libraries/wutdevoptab/devoptab_fs_stat.c
Normal file
@ -0,0 +1,42 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_stat(struct _reent *r,
|
||||
const char *file,
|
||||
struct stat *st)
|
||||
{
|
||||
int fd;
|
||||
FSStatus rc;
|
||||
|
||||
if (file == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
// First try open as file
|
||||
rc = FSOpenFile(__wut_devoptab_fs_client, &fsCmd, file, "r", (FSFileHandle*)&fd, -1);
|
||||
|
||||
if (rc >= 0) {
|
||||
__wut_fs_file_t tmpfd = { .fd = fd };
|
||||
rc = __wut_fs_fstat(r, &tmpfd, st);
|
||||
FSCloseFile(__wut_devoptab_fs_client, &fsCmd, fd, -1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// File failed, so lets try open as directory
|
||||
rc = FSOpenDir(__wut_devoptab_fs_client, &fsCmd, file, (FSDirectoryHandle*)&fd, -1);
|
||||
|
||||
if (rc >= 0) {
|
||||
memset(st, 0, sizeof(struct stat));
|
||||
st->st_nlink = 1;
|
||||
st->st_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
|
||||
FSCloseDir(__wut_devoptab_fs_client, &fsCmd, fd, -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
22
libraries/wutdevoptab/devoptab_fs_statvfs.c
Normal file
22
libraries/wutdevoptab/devoptab_fs_statvfs.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_statvfs(struct _reent *r,
|
||||
const char *path,
|
||||
struct statvfs *buf)
|
||||
{
|
||||
FSStatus rc;
|
||||
bool writable = false;
|
||||
char *path_fix = __wut_fs_fixpath(r, path);
|
||||
|
||||
if (!path_fix) {
|
||||
r->_errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//TODO: FSGetFileSystemInfo
|
||||
|
||||
free(path_fix);
|
||||
r->_errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
36
libraries/wutdevoptab/devoptab_fs_truncate.c
Normal file
36
libraries/wutdevoptab/devoptab_fs_truncate.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_ftruncate(struct _reent *r,
|
||||
void *fd,
|
||||
off_t len)
|
||||
{
|
||||
FSStatus rc;
|
||||
__wut_fs_file_t *file = (__wut_fs_file_t *)fd;
|
||||
|
||||
// Make sure length is non-negative
|
||||
if (len < 0) {
|
||||
r->_errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
// Set the new file size
|
||||
rc = FSSetPosFile(__wut_devoptab_fs_client, &fsCmd, file->fd, len, -1);
|
||||
|
||||
if (rc >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = FSTruncateFile(__wut_devoptab_fs_client, &fsCmd, file->fd, -1);
|
||||
|
||||
if (rc >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
33
libraries/wutdevoptab/devoptab_fs_unlink.c
Normal file
33
libraries/wutdevoptab/devoptab_fs_unlink.c
Normal file
@ -0,0 +1,33 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
int
|
||||
__wut_fs_unlink(struct _reent *r,
|
||||
const char *name)
|
||||
{
|
||||
FSStatus rc;
|
||||
|
||||
if (name == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *path_fix = __wut_fs_fixpath(r, name);
|
||||
|
||||
if (!path_fix) {
|
||||
r->_errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
rc = FSRemove(__wut_devoptab_fs_client, &fsCmd, path_fix, -1);
|
||||
free(path_fix);
|
||||
|
||||
if (rc >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
}
|
47
libraries/wutdevoptab/devoptab_fs_utils.c
Normal file
47
libraries/wutdevoptab/devoptab_fs_utils.c
Normal file
@ -0,0 +1,47 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
char *
|
||||
__wut_fs_fixpath(struct _reent *r,
|
||||
const char *path)
|
||||
{
|
||||
char *p = strchr(path, ':')+1;
|
||||
|
||||
if(!strchr(path, ':')) {
|
||||
p = (char*)path;
|
||||
}
|
||||
|
||||
if (strlen(p) > PATH_MAX) {
|
||||
r->_errno = ENAMETOOLONG;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *__fixedpath = memalign(0x40, PATH_MAX+1);
|
||||
|
||||
if (__fixedpath == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// cwd is handled by coreinit, so just strip the 'fs:' if it exists
|
||||
strcpy(__fixedpath, p);
|
||||
return __fixedpath;
|
||||
}
|
||||
|
||||
int
|
||||
__wut_fs_translate_error(FSStatus error)
|
||||
{
|
||||
switch (error) {
|
||||
case FS_STATUS_CANCELLED:
|
||||
return EINVAL;
|
||||
case FS_STATUS_EXISTS:
|
||||
return EEXIST;
|
||||
case FS_STATUS_NOT_FOUND:
|
||||
return ENOENT;
|
||||
case FS_STATUS_STORAGE_FULL:
|
||||
return ENOSPC;
|
||||
case FS_ERROR_INVALID_PATH:
|
||||
return ENAMETOOLONG;
|
||||
default:
|
||||
return (int)error;
|
||||
}
|
||||
}
|
||||
|
61
libraries/wutdevoptab/devoptab_fs_write.c
Normal file
61
libraries/wutdevoptab/devoptab_fs_write.c
Normal file
@ -0,0 +1,61 @@
|
||||
#include "devoptab_fs.h"
|
||||
|
||||
ssize_t
|
||||
__wut_fs_write(struct _reent *r,
|
||||
void *fd,
|
||||
const char *ptr,
|
||||
size_t len)
|
||||
{
|
||||
FSStatus rc;
|
||||
u32 bytes, bytesWritten = 0;
|
||||
__wut_fs_file_t *file = (__wut_fs_file_t *)fd;
|
||||
|
||||
// Check that the file was opened with write access
|
||||
if ((file->flags & O_ACCMODE) == O_RDONLY) {
|
||||
r->_errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Copy to internal buffer and write in chunks.
|
||||
u8 *tmp_buffer = memalign(0x40, 8192);
|
||||
|
||||
while(len > 0) {
|
||||
size_t toWrite = len;
|
||||
|
||||
if (toWrite > 8192) {
|
||||
toWrite = 8192;
|
||||
}
|
||||
|
||||
// Copy to internal buffer
|
||||
memcpy(tmp_buffer, ptr, toWrite);
|
||||
|
||||
// Set up command block
|
||||
FSCmdBlock fsCmd;
|
||||
FSInitCmdBlock(&fsCmd);
|
||||
|
||||
// Write the data
|
||||
rc = FSWriteFile(__wut_devoptab_fs_client, &fsCmd, tmp_buffer, 1, toWrite, file->fd, 0, -1);
|
||||
|
||||
if (rc < 0) {
|
||||
free(tmp_buffer);
|
||||
|
||||
// Return partial transfer
|
||||
if (bytesWritten > 0) {
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
r->_errno = __wut_fs_translate_error(rc);
|
||||
return -1;
|
||||
} else {
|
||||
bytes = rc;
|
||||
}
|
||||
|
||||
file->offset += bytes;
|
||||
bytesWritten += bytes;
|
||||
ptr += bytes;
|
||||
len -= bytes;
|
||||
}
|
||||
|
||||
free(tmp_buffer);
|
||||
return bytesWritten;
|
||||
}
|
Loading…
Reference in New Issue
Block a user