mirror of
https://github.com/devkitPro/wut.git
synced 2026-04-08 02:05:11 -05:00
- Improved error codes for unlink and rmdir regarding non-empty directories. - Return ENOENT on empty strings since it softlocks the Wii U. Since the devoptab relies on the cwd it's pretty easy to run into with stuff like recursive path creation for example. - Clean up open_r mode_t->string conversion - Improved FSStat->mode_t conversion - Add FSOpenFileEx and flags
133 lines
3.9 KiB
C
133 lines
3.9 KiB
C
#include "devoptab_fs.h"
|
|
#include "../wutnewlib/wut_clock.h"
|
|
|
|
char *
|
|
__wut_fs_fixpath(struct _reent *r,
|
|
const char *path) {
|
|
char *p;
|
|
char *fixedPath;
|
|
|
|
if (!path) {
|
|
r->_errno = EINVAL;
|
|
return NULL;
|
|
}
|
|
|
|
p = strchr(path, ':') + 1;
|
|
if (!strchr(path, ':')) {
|
|
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) {
|
|
r->_errno = ENOENT;
|
|
return NULL;
|
|
}
|
|
|
|
fixedPath = memalign(0x40, FS_MAX_PATH + 1);
|
|
if (!fixedPath) {
|
|
r->_errno = ENOMEM;
|
|
return NULL;
|
|
}
|
|
|
|
// cwd is handled by coreinit, so just strip the 'device:' if it exists
|
|
strcpy(fixedPath, p);
|
|
return fixedPath;
|
|
}
|
|
|
|
mode_t __wut_fs_translate_stat_mode(FSStat* fsStat) {
|
|
mode_t retMode = 0;
|
|
|
|
if ((fsStat->flags & FS_STAT_LINK) == FS_STAT_LINK) {
|
|
retMode |= S_IFLNK;
|
|
} else if ((fsStat->flags & FS_STAT_DIRECTORY) == FS_STAT_DIRECTORY) {
|
|
retMode |= S_IFDIR;
|
|
} else if ((fsStat->flags & FS_STAT_FILE) == FS_STAT_FILE) {
|
|
retMode |= S_IFREG;
|
|
} else if (fsStat->size == 0) {
|
|
// 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) {
|
|
// Some regular Wii U files have no type info but will have a size
|
|
retMode |= S_IFREG;
|
|
}
|
|
|
|
// Convert normal CafeOS hexadecimal permission bits into Unix octal permission bits
|
|
mode_t permissionMode = (((fsStat->mode >> 2) & S_IRWXU) | ((fsStat->mode >> 1) & S_IRWXG) | (fsStat->mode & S_IRWXO));
|
|
|
|
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) {
|
|
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_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_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:
|
|
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;
|
|
}
|