diff --git a/src/FSWrapper.cpp b/src/FSWrapper.cpp index 62ae0bd..8fe9d07 100644 --- a/src/FSWrapper.cpp +++ b/src/FSWrapper.cpp @@ -103,10 +103,11 @@ FSError FSWrapper::FSReadDirWrapper(FSDirectoryHandle handle, FSDirectoryEntry * char path[strLen]; snprintf(path, sizeof(path), "%s/%s", dirHandle->path, entry_->d_name); if (stat(path, &sb) >= 0) { - entry->info.size = sb.st_size; - entry->info.flags = (FSStatFlags) 0; - entry->info.owner = sb.st_uid; - entry->info.group = sb.st_gid; + translate_stat(&sb, &entry->info); + } else { + DEBUG_FUNCTION_LINE_ERR("[%s] Failed to stat file (%s) in read dir %08X (dir handle %08X)", getName().c_str(), path, dir, handle); + result = FS_ERROR_MEDIA_ERROR; + break; } } } @@ -322,17 +323,7 @@ FSError FSWrapper::FSGetStatWrapper(const char *path, FSStat *stats) { DEBUG_FUNCTION_LINE_VERBOSE("[%s] Path %s (%s) not found ", getName().c_str(), path, newPath.c_str()); result = FS_ERROR_NOT_FOUND; } else { - memset(&(stats->flags), 0, sizeof(stats->flags)); - if (S_ISDIR(path_stat.st_mode)) { - stats->flags = (FSStatFlags) ((uint32_t) FS_STAT_DIRECTORY); - } else { - stats->size = path_stat.st_size; - stats->mode = (FSMode) FS_MODE_READ_OWNER; - stats->flags = (FSStatFlags) 0; - stats->owner = path_stat.st_uid; - stats->group = path_stat.st_gid; - } - DEBUG_FUNCTION_LINE_VERBOSE("[%s] Stats file for %s (%s), size %08X", getName().c_str(), path, newPath.c_str(), stats->size); + translate_stat(&path_stat, stats); } return result; } @@ -353,13 +344,7 @@ FSError FSWrapper::FSGetStatFileWrapper(FSFileHandle handle, FSStat *stats) { DEBUG_FUNCTION_LINE_ERR("[%s] fstat of fd %d (FSFileHandle %08X) failed", getName().c_str(), real_fd, handle); result = FS_ERROR_MEDIA_ERROR; } else { - memset(&(stats->flags), 0, sizeof(stats->flags)); - - stats->size = path_stat.st_size; - stats->mode = (FSMode) FS_MODE_READ_OWNER; - stats->flags = (FSStatFlags) 0; - stats->owner = path_stat.st_uid; - stats->group = path_stat.st_gid; + translate_stat(&path_stat, stats); } return result; diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index bbe9a07..5d338bf 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -1,5 +1,8 @@ #include "utils/logger.h" +#include +#include #include +#include #include #define PRINTF_BUFFER_LENGTH 2048 @@ -36,4 +39,39 @@ void dumpHex(const void *data, size_t size) { } } } -} \ No newline at end of file +} + +FSMode 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)); +} + +FSTime translate_time(time_t timeValue) { + // FSTime stats at 1980-01-01, time_t starts at 1970-01-01 + auto EPOCH_DIFF_SECS_WII_U_FS_TIME = 315532800; //EPOCH_DIFF_SECS(WIIU_FSTIME_EPOCH_YEAR) + auto adjustedTimeValue = timeValue - EPOCH_DIFF_SECS_WII_U_FS_TIME; + // FSTime is in microseconds, time_t is in seconds + return adjustedTimeValue * 1000000; +} + +void translate_stat(struct stat *posStat, FSStat *fsStat) { + memset(fsStat, 0, sizeof(FSStat)); + fsStat->size = posStat->st_size; + + fsStat->mode = translate_permission_mode(posStat->st_mode); + + fsStat->flags = static_cast(0x1C000000); // These bits are always set + if (S_ISDIR(posStat->st_mode)) { + fsStat->flags = static_cast(fsStat->flags | FS_STAT_DIRECTORY); + } else if (S_ISREG(posStat->st_mode)) { + fsStat->flags = static_cast(fsStat->flags | FS_STAT_FILE); + fsStat->allocSize = posStat->st_size; + fsStat->quotaSize = posStat->st_size; + } + fsStat->modified = translate_time(posStat->st_atime); + fsStat->created = translate_time(posStat->st_ctime); + fsStat->entryId = posStat->st_ino; + + fsStat->owner = posStat->st_uid; + fsStat->group = posStat->st_gid; +} diff --git a/src/utils/utils.h b/src/utils/utils.h index b1a3c03..a9d7a6f 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -30,4 +30,6 @@ bool remove_locked_first_if(std::mutex &mutex, std::vector &list, // those work only in powers of 2 #define ROUNDDOWN(val, align) ((val) & ~(align - 1)) -#define ROUNDUP(val, align) ROUNDDOWN(((val) + (align - 1)), align) \ No newline at end of file +#define ROUNDUP(val, align) ROUNDDOWN(((val) + (align - 1)), align) + +void translate_stat(struct stat *posStat, FSStat *fsStat); \ No newline at end of file