Support time, fix modes and translate errors

Thanks to @koolkdev for figuring out the FSStat flags and structs.
Thanks to WUT for the error codes.
This commit is contained in:
Crementif 2022-03-30 02:37:45 +02:00 committed by Maschell
parent 70e9aee0fe
commit 41a318cac5
7 changed files with 283 additions and 192 deletions

View File

@ -1,4 +1,4 @@
FROM wiiuenv/devkitppc:20211229
FROM wiiuenv/devkitppc:20220507
WORKDIR tmp_build
COPY . .

View File

@ -1,3 +1,3 @@
FROM wiiuenv/devkitppc:20211229
FROM wiiuenv/devkitppc:20220507
WORKDIR project

View File

@ -9,6 +9,9 @@ Make you to have [wut](https://github.com/devkitPro/wut/) installed and use the
```
make install
```
Note:
You might have to build the latest wut from source if you use the prebuild devkitpro packages until it has a new release.
It won't work with wut versions like wut 1.0.0-beta12 and older.
## Use this lib in Dockerfiles.
A prebuilt version of this lib can found on dockerhub. To use it for your projects, add this to your Dockerfile.

View File

@ -23,32 +23,17 @@
***************************************************************************/
#pragma once
#include <coreinit/filesystem.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t flag;
uint32_t permission;
uint32_t owner_id;
uint32_t group_id;
uint32_t size; // size in bytes
uint32_t physsize; // physical size on disk in bytes
uint32_t unk[3];
uint32_t id;
uint32_t ctime;
uint32_t mtime;
uint32_t unk2[0x0D];
} fileStat_s;
typedef struct {
fileStat_s stat;
char name[0x100];
} directoryEntry_s;
#define DIR_ENTRY_IS_DIRECTORY 0x80000000
// Deprecated: Use FS_STAT_DIRECTORY
#ifndef DIR_ENTRY_IS_DIRECTORY
#define DIR_ENTRY_IS_DIRECTORY FS_STAT_FILE
#endif
#define FSA_MOUNTFLAGS_BINDMOUNT (1 << 0)
#define FSA_MOUNTFLAGS_GLOBAL (1 << 1)
@ -88,7 +73,7 @@ int IOSUHAX_FSA_MakeDir(int fsaFd, const char *path, uint32_t flags);
int IOSUHAX_FSA_OpenDir(int fsaFd, const char *path, int *outHandle);
int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s *out_data);
int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, FSDirectoryEntry *out_data);
int IOSUHAX_FSA_RewindDir(int fsaFd, int dirHandle);
@ -102,13 +87,13 @@ int IOSUHAX_FSA_ReadFile(int fsaFd, void *data, uint32_t size, uint32_t cnt, int
int IOSUHAX_FSA_WriteFile(int fsaFd, const void *data, uint32_t size, uint32_t cnt, int fileHandle, uint32_t flags);
int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s *out_data);
int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, FSStat *out_data);
int IOSUHAX_FSA_CloseFile(int fsaFd, int fileHandle);
int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position);
int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s *out_data);
int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, FSStat *out_data);
int IOSUHAX_FSA_Remove(int fsaFd, const char *path);

View File

@ -465,7 +465,7 @@ int IOSUHAX_FSA_OpenDir(int fsaFd, const char *path, int *outHandle) {
return result_vec[0];
}
int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s *out_data) {
int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, FSDirectoryEntry *out_data) {
if (iosuhaxHandle < 0)
return iosuhaxHandle;
@ -480,7 +480,7 @@ int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s *out_data) {
io_buf[0] = fsaFd;
io_buf[1] = handle;
int result_vec_size = 4 + sizeof(directoryEntry_s);
int result_vec_size = 4 + sizeof(FSDirectoryEntry);
uint8_t *result_vec = (uint8_t *) memalign(0x20, result_vec_size);
if (!result_vec) {
free(io_buf);
@ -495,7 +495,7 @@ int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s *out_data) {
}
int result = *(int *) result_vec;
memcpy(out_data, result_vec + 4, sizeof(directoryEntry_s));
memcpy(out_data, result_vec + 4, sizeof(FSDirectoryEntry));
free(io_buf);
free(result_vec);
return result;
@ -688,7 +688,7 @@ int IOSUHAX_FSA_WriteFile(int fsaFd, const void *data, uint32_t size, uint32_t c
return result;
}
int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s *out_data) {
int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, FSStat *out_data) {
if (iosuhaxHandle < 0)
return iosuhaxHandle;
@ -703,7 +703,7 @@ int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s *out_data) {
io_buf[0] = fsaFd;
io_buf[1] = fileHandle;
int out_buf_size = 4 + sizeof(fileStat_s);
int out_buf_size = 4 + sizeof(FSStat);
uint32_t *out_buffer = (uint32_t *) memalign(0x20, out_buf_size);
if (!out_buffer) {
free(io_buf);
@ -718,7 +718,7 @@ int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s *out_data) {
}
int result = out_buffer[0];
memcpy(out_data, out_buffer + 1, sizeof(fileStat_s));
memcpy(out_data, out_buffer + 1, sizeof(FSStat));
free(io_buf);
free(out_buffer);
@ -780,7 +780,7 @@ int IOSUHAX_FSA_SetFilePos(int fsaFd, int fileHandle, uint32_t position) {
return result;
}
int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s *out_data) {
int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, FSStat *out_data) {
if (iosuhaxHandle < 0)
return iosuhaxHandle;
@ -796,7 +796,7 @@ int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s *out_data) {
io_buf[1] = sizeof(uint32_t) * input_cnt;
strcpy(((char *) io_buf) + io_buf[1], path);
int out_buf_size = 4 + sizeof(fileStat_s);
int out_buf_size = 4 + sizeof(FSStat);
uint32_t *out_buffer = (uint32_t *) memalign(0x20, out_buf_size);
if (!out_buffer) {
free(io_buf);
@ -811,7 +811,7 @@ int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s *out_data) {
}
int result = out_buffer[0];
memcpy(out_data, out_buffer + 1, sizeof(fileStat_s));
memcpy(out_data, out_buffer + 1, sizeof(FSStat));
free(io_buf);
free(out_buffer);

View File

@ -26,6 +26,7 @@
#include <errno.h>
#include <fcntl.h>
#include <malloc.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
@ -44,9 +45,9 @@ typedef struct _fs_dev_file_state_t {
fs_dev_private_t *dev;
int fd; /* File descriptor */
int flags; /* Opening flags */
int read; /* True if allowed to read from file */
int write; /* True if allowed to write to file */
int append; /* True if allowed to append to file */
bool read; /* True if allowed to read from file */
bool write; /* True if allowed to write to file */
bool append; /* True if allowed to append to file */
uint32_t pos; /* Current position within the file (in bytes) */
uint32_t len; /* Total length of the file (in bytes) */
struct _fs_dev_file_state_t *prevOpenFile; /* The previous entry in a double-linked FILO list of open files */
@ -104,6 +105,85 @@ static char *fs_dev_real_path(const char *path, fs_dev_private_t *dev) {
return new_name;
}
static int fs_dev_translate_error(FSStatus error) {
switch ((int) error) {
case FS_STATUS_END:
return ENOENT;
case FS_STATUS_CANCELLED:
return ECANCELED;
case FS_STATUS_EXISTS:
return EEXIST;
case FS_STATUS_MEDIA_ERROR:
return EIO;
case FS_STATUS_NOT_FOUND:
return ENOENT;
case FS_STATUS_PERMISSION_ERROR:
return EPERM;
case FS_STATUS_STORAGE_FULL:
return ENOSPC;
case FS_STATUS_FILE_TOO_BIG:
return EFBIG;
case FS_STATUS_NOT_DIR:
return ENOTDIR;
case FS_STATUS_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:
return ENOTSUP;
case FS_STATUS_MEDIA_NOT_READY:
return EOWNERDEAD;
case FS_STATUS_ALREADY_OPEN:
case FS_STATUS_CORRUPTED:
case FS_STATUS_FATAL_ERROR:
return EIO;
}
return (int) error;
}
static mode_t fs_dev_translate_stat_mode(FSStat fileStat, bool isRootDirectory) {
// Convert file types
mode_t typeMode = 0;
if (isRootDirectory) {
typeMode |= S_IFDIR;
} else if ((fileStat.flags & FS_STAT_LINK) == FS_STAT_LINK) {
typeMode |= S_IFLNK;
} else if ((fileStat.flags & FS_STAT_DIRECTORY) == FS_STAT_DIRECTORY) {
typeMode |= S_IFDIR;
} else if ((fileStat.flags & FS_STAT_FILE) == FS_STAT_FILE) {
typeMode |= S_IFREG;
}
// Convert normal CafeOS hexadecimal permission bits into Unix octal permission bits
mode_t permissionMode = (((fileStat.mode >> 2) & S_IRWXU) | ((fileStat.mode >> 1) & S_IRWXG) | (fileStat.mode & S_IRWXO));
return typeMode | permissionMode;
}
static FSMode fs_dev_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 time_t fs_dev_translate_time(FSTime timeValue) {
OSCalendarTime fileTime;
FSTimeToCalendarTime(timeValue, &fileTime);
struct tm posixTime = {0};
posixTime.tm_year = fileTime.tm_year - 1900;
posixTime.tm_mon = fileTime.tm_mon;
posixTime.tm_mday = fileTime.tm_mday;
posixTime.tm_hour = fileTime.tm_hour;
posixTime.tm_min = fileTime.tm_min;
posixTime.tm_sec = fileTime.tm_sec;
posixTime.tm_yday = fileTime.tm_yday;
posixTime.tm_wday = fileTime.tm_wday;
return mktime(&posixTime);
}
static int fs_dev_open_r(struct _reent *r, void *fileStruct, const char *path, int flags, int mode) {
fs_dev_private_t *dev = fs_dev_get_device_data(path);
if (!dev) {
@ -121,34 +201,34 @@ static int fs_dev_open_r(struct _reent *r, void *fileStruct, const char *path, i
// Map flags to open modes
if (flags == 0) {
file->read = 1;
file->write = 0;
file->append = 0;
file->read = true;
file->write = false;
file->append = false;
fsMode = "r";
} else if (flags == 2) {
file->read = 1;
file->write = 1;
file->append = 0;
file->read = true;
file->write = true;
file->append = false;
fsMode = "r+";
} else if (flags == 0x601) {
file->read = 0;
file->write = 1;
file->append = 0;
file->read = false;
file->write = true;
file->append = false;
fsMode = "w";
} else if (flags == 0x602) {
file->read = 1;
file->write = 1;
file->append = 0;
file->read = true;
file->write = true;
file->append = false;
fsMode = "w+";
} else if (flags == 0x209) {
file->read = 0;
file->write = 1;
file->append = 1;
file->read = false;
file->write = true;
file->append = true;
fsMode = "a";
} else if (flags == 0x20A) {
file->read = 1;
file->write = 1;
file->append = 1;
file->read = true;
file->write = true;
file->append = true;
fsMode = "a+";
} else {
r->_errno = EINVAL;
@ -172,11 +252,11 @@ static int fs_dev_open_r(struct _reent *r, void *fileStruct, const char *path, i
free(real_path);
if (result == 0) {
fileStat_s stats;
FSStat stats;
result = IOSUHAX_FSA_StatFile(dev->fsaFd, fd, &stats);
if (result != 0) {
IOSUHAX_FSA_CloseFile(dev->fsaFd, fd);
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
OSUnlockMutex(dev->pMutex);
return -1;
}
@ -187,7 +267,7 @@ static int fs_dev_open_r(struct _reent *r, void *fileStruct, const char *path, i
return (int) file;
}
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
OSUnlockMutex(dev->pMutex);
return -1;
}
@ -207,7 +287,7 @@ static int fs_dev_close_r(struct _reent *r, void *fd) {
OSUnlockMutex(file->dev->pMutex);
if (result < 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
return -1;
}
return 0;
@ -269,7 +349,7 @@ static ssize_t fs_dev_write_r(struct _reent *r, void *fd, const char *ptr, size_
int result = IOSUHAX_FSA_WriteFile(file->dev->fsaFd, ptr + done, 0x01, write_size, file->fd, 0);
if (result < 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
break;
} else if (result == 0) {
if (write_size > 0)
@ -306,7 +386,7 @@ static ssize_t fs_dev_read_r(struct _reent *r, void *fd, char *ptr, size_t len)
int result = IOSUHAX_FSA_ReadFile(file->dev->fsaFd, ptr + done, 0x01, read_size, file->fd, 0);
if (result < 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
done = 0;
break;
} else if (result == 0) {
@ -335,55 +415,32 @@ static int fs_dev_fstat_r(struct _reent *r, void *fd, struct stat *st) {
// Zero out the stat buffer
memset(st, 0, sizeof(struct stat));
fileStat_s stats;
FSStat stats;
int result = IOSUHAX_FSA_StatFile(file->dev->fsaFd, (int) fd, &stats);
if (result != 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
OSUnlockMutex(file->dev->pMutex);
return -1;
}
st->st_mode = S_IFREG;
st->st_size = stats.size;
st->st_blocks = (stats.size + 511) >> 9;
st->st_nlink = 1;
// Fill in the generic entry stats
st->st_dev = stats.id;
st->st_uid = stats.owner_id;
st->st_gid = stats.group_id;
st->st_ino = stats.id;
st->st_atime = stats.mtime;
st->st_ctime = stats.ctime;
st->st_mtime = stats.mtime;
// Convert fields to posix stat
st->st_dev = (dev_t) file->dev;
st->st_ino = stats.entryId;
st->st_mode = fs_dev_translate_stat_mode(stats, false);
st->st_nlink = 1;
st->st_uid = stats.owner;
st->st_gid = stats.group;
st->st_rdev = st->st_dev;
st->st_size = stats.size;
st->st_blksize = 512;
st->st_blocks = (st->st_size + st->st_blksize - 1) / st->st_blksize;
st->st_atime = fs_dev_translate_time(stats.modified);
st->st_ctime = fs_dev_translate_time(stats.created);
st->st_mtime = fs_dev_translate_time(stats.modified);
OSUnlockMutex(file->dev->pMutex);
return 0;
}
static int fs_dev_ftruncate_r(struct _reent *r, void *fd, off_t len) {
fs_dev_file_state_t *file = (fs_dev_file_state_t *) fd;
if (!file->dev) {
r->_errno = ENODEV;
return -1;
}
r->_errno = ENOTSUP;
// TODO
return -1;
}
static int fs_dev_fsync_r(struct _reent *r, void *fd) {
fs_dev_file_state_t *file = (fs_dev_file_state_t *) fd;
if (!file->dev) {
r->_errno = ENODEV;
return -1;
}
r->_errno = ENOTSUP;
// TODO
return -1;
}
static int fs_dev_stat_r(struct _reent *r, const char *path, struct stat *st) {
fs_dev_private_t *dev = fs_dev_get_device_data(path);
if (!dev) {
@ -403,34 +460,78 @@ static int fs_dev_stat_r(struct _reent *r, const char *path, struct stat *st) {
return -1;
}
fileStat_s stats;
FSStat stats;
int result = IOSUHAX_FSA_GetStat(dev->fsaFd, real_path, &stats);
free(real_path);
if (result < 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
OSUnlockMutex(dev->pMutex);
return -1;
}
// mark root also as directory
st->st_mode = ((stats.flag & 0x80000000) || (strlen(dev->mount_path) + 1 == strlen(real_path))) ? S_IFDIR : S_IFREG;
st->st_nlink = 1;
st->st_size = stats.size;
st->st_blocks = (stats.size + 511) >> 9;
// Fill in the generic entry stats
st->st_dev = stats.id;
st->st_uid = stats.owner_id;
st->st_gid = stats.group_id;
st->st_ino = stats.id;
st->st_atime = stats.mtime;
st->st_ctime = stats.ctime;
st->st_mtime = stats.mtime;
// Convert fields to posix stat
st->st_dev = (dev_t) dev;
st->st_ino = stats.entryId;
st->st_mode = fs_dev_translate_stat_mode(stats, (strlen(dev->mount_path) + 1 == strlen(real_path)));
st->st_nlink = 1;
st->st_uid = stats.owner;
st->st_gid = stats.group;
st->st_rdev = st->st_dev;
st->st_size = stats.size;
st->st_blksize = 512;
st->st_blocks = (st->st_size + st->st_blksize - 1) / st->st_blksize;
st->st_atime = fs_dev_translate_time(stats.modified);
st->st_ctime = fs_dev_translate_time(stats.created);
st->st_mtime = fs_dev_translate_time(stats.modified);
OSUnlockMutex(dev->pMutex);
return 0;
}
static int fs_dev_lstat_r(struct _reent *r, const char *path, struct stat *st) {
fs_dev_private_t *dev = fs_dev_get_device_data(path);
if (!dev) {
r->_errno = ENODEV;
return -1;
}
OSLockMutex(dev->pMutex);
// Zero out the stat buffer
memset(st, 0, sizeof(struct stat));
char *real_path = fs_dev_real_path(path, dev);
if (!real_path) {
r->_errno = ENOMEM;
OSUnlockMutex(dev->pMutex);
return -1;
}
FSStat stats;
int result = IOSUHAX_FSA_GetStat(dev->fsaFd, real_path, &stats);
free(real_path);
if (result < 0) {
r->_errno = fs_dev_translate_error(result);
OSUnlockMutex(dev->pMutex);
return -1;
}
// Convert fields to posix stat
st->st_dev = (dev_t) dev;
st->st_ino = stats.entryId;
st->st_mode = fs_dev_translate_stat_mode(stats, (strlen(dev->mount_path) + 1 == strlen(real_path)));
st->st_nlink = 1;
st->st_uid = stats.owner;
st->st_gid = stats.group;
st->st_rdev = st->st_dev;
st->st_size = stats.size;
st->st_blksize = 512;
st->st_blocks = (st->st_size + st->st_blksize - 1) / st->st_blksize;
st->st_atime = fs_dev_translate_time(stats.modified);
st->st_ctime = fs_dev_translate_time(stats.created);
st->st_mtime = fs_dev_translate_time(stats.modified);
OSUnlockMutex(dev->pMutex);
return 0;
}
@ -462,7 +563,7 @@ static int fs_dev_unlink_r(struct _reent *r, const char *name) {
OSUnlockMutex(dev->pMutex);
if (result < 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
return -1;
}
@ -492,7 +593,7 @@ static int fs_dev_chdir_r(struct _reent *r, const char *name) {
OSUnlockMutex(dev->pMutex);
if (result < 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
return -1;
}
@ -523,7 +624,7 @@ static int fs_dev_rename_r(struct _reent *r, const char *oldName, const char *ne
}
//! TODO
int result = -ENOTSUP;
int result = FS_ERROR_UNSUPPORTED_COMMAND;
free(real_oldpath);
free(real_newpath);
@ -531,7 +632,7 @@ static int fs_dev_rename_r(struct _reent *r, const char *oldName, const char *ne
OSUnlockMutex(dev->pMutex);
if (result < 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
return -1;
}
@ -554,21 +655,20 @@ static int fs_dev_mkdir_r(struct _reent *r, const char *path, int mode) {
return -1;
}
int result = IOSUHAX_FSA_MakeDir(dev->fsaFd, real_path, mode);
int result = IOSUHAX_FSA_MakeDir(dev->fsaFd, real_path, fs_dev_translate_permission_mode(mode));
free(real_path);
OSUnlockMutex(dev->pMutex);
if (result < 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
return -1;
}
return 0;
}
static int fs_dev_chmod_r(struct _reent *r, const char *path, int mode) {
static int fs_dev_chmod_r(struct _reent *r, const char *path, mode_t mode) {
fs_dev_private_t *dev = fs_dev_get_device_data(path);
if (!dev) {
r->_errno = ENODEV;
@ -584,14 +684,13 @@ static int fs_dev_chmod_r(struct _reent *r, const char *path, int mode) {
return -1;
}
int result = IOSUHAX_FSA_ChangeMode(dev->fsaFd, real_path, mode);
int result = IOSUHAX_FSA_ChangeMode(dev->fsaFd, real_path, fs_dev_translate_permission_mode(mode));
free(real_path);
OSUnlockMutex(dev->pMutex);
if (result < 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
return -1;
}
@ -624,7 +723,7 @@ static int fs_dev_statvfs_r(struct _reent *r, const char *path, struct statvfs *
free(real_path);
if (result < 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
OSUnlockMutex(dev->pMutex);
return -1;
}
@ -688,7 +787,7 @@ static DIR_ITER *fs_dev_diropen_r(struct _reent *r, DIR_ITER *dirState, const ch
OSUnlockMutex(dev->pMutex);
if (result < 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
return NULL;
}
@ -712,7 +811,7 @@ static int fs_dev_dirclose_r(struct _reent *r, DIR_ITER *dirState) {
OSUnlockMutex(dirIter->dev->pMutex);
if (result < 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
return -1;
}
return 0;
@ -732,7 +831,7 @@ static int fs_dev_dirreset_r(struct _reent *r, DIR_ITER *dirState) {
OSUnlockMutex(dirIter->dev->pMutex);
if (result < 0) {
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
return -1;
}
return 0;
@ -747,12 +846,12 @@ static int fs_dev_dirnext_r(struct _reent *r, DIR_ITER *dirState, char *filename
OSLockMutex(dirIter->dev->pMutex);
directoryEntry_s *dir_entry = malloc(sizeof(directoryEntry_s));
FSDirectoryEntry *dir_entry = malloc(sizeof(FSDirectoryEntry));
int result = IOSUHAX_FSA_ReadDir(dirIter->dev->fsaFd, dirIter->dirHandle, dir_entry);
if (result < 0) {
free(dir_entry);
r->_errno = result;
r->_errno = fs_dev_translate_error(result);
OSUnlockMutex(dirIter->dev->pMutex);
return -1;
}
@ -762,17 +861,21 @@ static int fs_dev_dirnext_r(struct _reent *r, DIR_ITER *dirState, char *filename
if (st) {
memset(st, 0, sizeof(struct stat));
st->st_mode = (dir_entry->stat.flag & 0x80000000) ? S_IFDIR : S_IFREG;
st->st_nlink = 1;
st->st_size = dir_entry->stat.size;
st->st_blocks = (dir_entry->stat.size + 511) >> 9;
st->st_dev = dir_entry->stat.id;
st->st_uid = dir_entry->stat.owner_id;
st->st_gid = dir_entry->stat.group_id;
st->st_ino = dir_entry->stat.id;
st->st_atime = dir_entry->stat.mtime;
st->st_ctime = dir_entry->stat.ctime;
st->st_mtime = dir_entry->stat.mtime;
// Convert fields to posix stat
st->st_dev = (dev_t) dirIter->dev;
st->st_ino = dir_entry->info.entryId;
st->st_mode = fs_dev_translate_stat_mode(dir_entry->info, false);
st->st_nlink = 1;
st->st_uid = dir_entry->info.owner;
st->st_gid = dir_entry->info.group;
st->st_rdev = st->st_dev;
st->st_size = dir_entry->info.size;
st->st_blksize = 512;
st->st_blocks = (st->st_size + st->st_blksize - 1) / st->st_blksize;
st->st_atime = fs_dev_translate_time(dir_entry->info.modified);
st->st_ctime = fs_dev_translate_time(dir_entry->info.created);
st->st_mtime = fs_dev_translate_time(dir_entry->info.modified);
}
free(dir_entry);
@ -780,33 +883,35 @@ static int fs_dev_dirnext_r(struct _reent *r, DIR_ITER *dirState, char *filename
return 0;
}
// NTFS device driver devoptab
static const devoptab_t devops_fs = {
NULL, /* Device name */
sizeof(fs_dev_file_state_t),
fs_dev_open_r,
fs_dev_close_r,
fs_dev_write_r,
fs_dev_read_r,
fs_dev_seek_r,
fs_dev_fstat_r,
fs_dev_stat_r,
fs_dev_link_r,
fs_dev_unlink_r,
fs_dev_chdir_r,
fs_dev_rename_r,
fs_dev_mkdir_r,
sizeof(fs_dev_dir_entry_t),
fs_dev_diropen_r,
fs_dev_dirreset_r,
fs_dev_dirnext_r,
fs_dev_dirclose_r,
fs_dev_statvfs_r,
fs_dev_ftruncate_r,
fs_dev_fsync_r,
fs_dev_chmod_r,
NULL, /* fs_dev_fchmod_r */
NULL /* Device data */
.name = NULL, /* Device name */
.structSize = sizeof(fs_dev_file_state_t),
.open_r = fs_dev_open_r,
.close_r = fs_dev_close_r,
.write_r = fs_dev_write_r,
.read_r = fs_dev_read_r,
.seek_r = fs_dev_seek_r,
.fstat_r = fs_dev_fstat_r,
.stat_r = fs_dev_stat_r,
.link_r = fs_dev_link_r,
.unlink_r = fs_dev_unlink_r,
.chdir_r = fs_dev_chdir_r,
.rename_r = fs_dev_rename_r,
.mkdir_r = fs_dev_mkdir_r,
.dirStateSize = sizeof(fs_dev_dir_entry_t),
.diropen_r = fs_dev_diropen_r,
.dirreset_r = fs_dev_dirreset_r,
.dirnext_r = fs_dev_dirnext_r,
.dirclose_r = fs_dev_dirclose_r,
.statvfs_r = fs_dev_statvfs_r,
.ftruncate_r = NULL, // fs_dev_ftruncate_r,
.fsync_r = NULL, // fs_dev_fsync_r,
.deviceData = NULL,
.chmod_r = fs_dev_chmod_r,
.fchmod_r = NULL, // fs_dev_fchmod_r,
.rmdir_r = NULL, // fs_dev_rmdir_r,
.lstat_r = fs_dev_lstat_r,
.utimes_r = NULL,
};
static int fs_dev_add_device(const char *name, const char *mount_path, int fsaFd, int isMounted) {

View File

@ -143,16 +143,15 @@ static bool IOSUHAX_sdio_writeSectors(uint32_t sector, uint32_t numSectors, cons
return true;
}
const DISC_INTERFACE IOSUHAX_sdio_disc_interface =
{
DEVICE_TYPE_WII_U_SD,
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_SD,
IOSUHAX_sdio_startup,
IOSUHAX_sdio_isInserted,
IOSUHAX_sdio_readSectors,
IOSUHAX_sdio_writeSectors,
IOSUHAX_sdio_clearStatus,
IOSUHAX_sdio_shutdown};
const DISC_INTERFACE IOSUHAX_sdio_disc_interface = {
DEVICE_TYPE_WII_U_SD,
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_SD,
IOSUHAX_sdio_startup,
IOSUHAX_sdio_isInserted,
IOSUHAX_sdio_readSectors,
IOSUHAX_sdio_writeSectors,
IOSUHAX_sdio_clearStatus,
IOSUHAX_sdio_shutdown};
static bool IOSUHAX_usb_startup(void) {
if (!IOSUHAX_disc_io_fsa_open(FSA_REF_USB))
@ -213,13 +212,12 @@ static bool IOSUHAX_usb_writeSectors(uint32_t sector, uint32_t numSectors, const
return true;
}
const DISC_INTERFACE IOSUHAX_usb_disc_interface =
{
DEVICE_TYPE_WII_U_USB,
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_USB,
IOSUHAX_usb_startup,
IOSUHAX_usb_isInserted,
IOSUHAX_usb_readSectors,
IOSUHAX_usb_writeSectors,
IOSUHAX_usb_clearStatus,
IOSUHAX_usb_shutdown};
const DISC_INTERFACE IOSUHAX_usb_disc_interface = {
DEVICE_TYPE_WII_U_USB,
FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_U_USB,
IOSUHAX_usb_startup,
IOSUHAX_usb_isInserted,
IOSUHAX_usb_readSectors,
IOSUHAX_usb_writeSectors,
IOSUHAX_usb_clearStatus,
IOSUHAX_usb_shutdown};