From 19e9d0c2de0d8b7d8306c40d1692140c83b84b6c Mon Sep 17 00:00:00 2001 From: "Herman S." <429230+has207@users.noreply.github.com> Date: Thu, 26 Mar 2026 22:39:41 +0900 Subject: [PATCH] [Base/Posix] filesystem portability and correctness fixes Replace Linux-specific fseeko64/ftello64/ftruncate64 with portable POSIX equivalents. Fix pread/pwrite error handling that assigned -1 to unsigned size_t. Implement SetAttributes via chmod instead of stubbing it out. Fix potential overflow in Unix-to-Windows filetime conversion. Clean up unused removeCallback. --- src/xenia/base/filesystem_posix.cc | 53 +++++++++++++++++++----------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc index 3c8729700..2cd71f328 100644 --- a/src/xenia/base/filesystem_posix.cc +++ b/src/xenia/base/filesystem_posix.cc @@ -11,6 +11,7 @@ #include "xenia/base/filesystem.h" #include "xenia/base/logging.h" #include "xenia/base/string.h" +#include "xenia/xbox.h" #include #include @@ -80,10 +81,10 @@ FILE* OpenFile(const std::filesystem::path& path, const std::string_view mode) { } bool Seek(FILE* file, int64_t offset, int origin) { - return fseeko64(file, off64_t(offset), origin) == 0; + return fseeko(file, offset, origin) == 0; } -int64_t Tell(FILE* file) { return int64_t(ftello64(file)); } +int64_t Tell(FILE* file) { return int64_t(ftello(file)); } bool TruncateStdioFile(FILE* file, uint64_t length) { if (fflush(file)) { @@ -93,7 +94,7 @@ bool TruncateStdioFile(FILE* file, uint64_t length) { if (position < 0) { return false; } - if (ftruncate64(fileno(file), off64_t(length))) { + if (ftruncate(fileno(file), length)) { return false; } if (uint64_t(position) > length) { @@ -104,19 +105,11 @@ bool TruncateStdioFile(FILE* file, uint64_t length) { return true; } -static int removeCallback(const char* fpath, const struct stat* sb, - int typeflag, struct FTW* ftwbuf) { - int rv = remove(fpath); - return rv; -} - static uint64_t convertUnixtimeToWinFiletime(time_t unixtime) { - // Linux uses number of seconds since 1/1/1970, and Windows uses - // number of nanoseconds since 1/1/1601 - // so we convert linux time to nanoseconds and then add the number of - // nanoseconds from 1601 to 1970 - // see https://msdn.microsoft.com/en-us/library/ms724228 - uint64_t filetime = (unixtime * 10000000) + 116444736000000000; + // Unix uses seconds since 1/1/1970, Windows uses 100ns intervals since + // 1/1/1601. Convert and add the epoch difference. + // See https://msdn.microsoft.com/en-us/library/ms724228 + uint64_t filetime = (uint64_t(unixtime) * 10000000) + 116444736000000000ULL; return filetime; } @@ -140,14 +133,24 @@ class PosixFileHandle : public FileHandle { bool Read(size_t file_offset, void* buffer, size_t buffer_length, size_t* out_bytes_read) override { ssize_t out = pread(handle_, buffer, buffer_length, file_offset); - *out_bytes_read = out; - return out >= 0 ? true : false; + if (out >= 0) { + *out_bytes_read = out; + return true; + } else { + *out_bytes_read = 0; + return false; + } } bool Write(size_t file_offset, const void* buffer, size_t buffer_length, size_t* out_bytes_written) override { ssize_t out = pwrite(handle_, buffer, buffer_length, file_offset); - *out_bytes_written = out; - return out >= 0 ? true : false; + if (out >= 0) { + *out_bytes_written = out; + return true; + } else { + *out_bytes_written = 0; + return false; + } } bool SetLength(size_t length) override { return ftruncate(handle_, length) >= 0 ? true : false; @@ -248,7 +251,17 @@ std::vector ListFiles(const std::filesystem::path& path) { } bool SetAttributes(const std::filesystem::path& path, uint64_t attributes) { - return false; + struct stat st; + if (stat(path.c_str(), &st) != 0) { + return false; + } + mode_t mode = st.st_mode; + if (attributes & X_FILE_ATTRIBUTE_READONLY) { + mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); + } else { + mode |= S_IWUSR; + } + return chmod(path.c_str(), mode) == 0; } } // namespace filesystem