[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.
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
#include "xenia/base/filesystem.h"
|
#include "xenia/base/filesystem.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/base/string.h"
|
#include "xenia/base/string.h"
|
||||||
|
#include "xenia/xbox.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
@@ -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) {
|
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) {
|
bool TruncateStdioFile(FILE* file, uint64_t length) {
|
||||||
if (fflush(file)) {
|
if (fflush(file)) {
|
||||||
@@ -93,7 +94,7 @@ bool TruncateStdioFile(FILE* file, uint64_t length) {
|
|||||||
if (position < 0) {
|
if (position < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ftruncate64(fileno(file), off64_t(length))) {
|
if (ftruncate(fileno(file), length)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (uint64_t(position) > length) {
|
if (uint64_t(position) > length) {
|
||||||
@@ -104,19 +105,11 @@ bool TruncateStdioFile(FILE* file, uint64_t length) {
|
|||||||
return true;
|
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) {
|
static uint64_t convertUnixtimeToWinFiletime(time_t unixtime) {
|
||||||
// Linux uses number of seconds since 1/1/1970, and Windows uses
|
// Unix uses seconds since 1/1/1970, Windows uses 100ns intervals since
|
||||||
// number of nanoseconds since 1/1/1601
|
// 1/1/1601. Convert and add the epoch difference.
|
||||||
// so we convert linux time to nanoseconds and then add the number of
|
// See https://msdn.microsoft.com/en-us/library/ms724228
|
||||||
// nanoseconds from 1601 to 1970
|
uint64_t filetime = (uint64_t(unixtime) * 10000000) + 116444736000000000ULL;
|
||||||
// see https://msdn.microsoft.com/en-us/library/ms724228
|
|
||||||
uint64_t filetime = (unixtime * 10000000) + 116444736000000000;
|
|
||||||
return filetime;
|
return filetime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,14 +133,24 @@ class PosixFileHandle : public FileHandle {
|
|||||||
bool Read(size_t file_offset, void* buffer, size_t buffer_length,
|
bool Read(size_t file_offset, void* buffer, size_t buffer_length,
|
||||||
size_t* out_bytes_read) override {
|
size_t* out_bytes_read) override {
|
||||||
ssize_t out = pread(handle_, buffer, buffer_length, file_offset);
|
ssize_t out = pread(handle_, buffer, buffer_length, file_offset);
|
||||||
*out_bytes_read = out;
|
if (out >= 0) {
|
||||||
return out >= 0 ? true : false;
|
*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,
|
bool Write(size_t file_offset, const void* buffer, size_t buffer_length,
|
||||||
size_t* out_bytes_written) override {
|
size_t* out_bytes_written) override {
|
||||||
ssize_t out = pwrite(handle_, buffer, buffer_length, file_offset);
|
ssize_t out = pwrite(handle_, buffer, buffer_length, file_offset);
|
||||||
*out_bytes_written = out;
|
if (out >= 0) {
|
||||||
return out >= 0 ? true : false;
|
*out_bytes_written = out;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
*out_bytes_written = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bool SetLength(size_t length) override {
|
bool SetLength(size_t length) override {
|
||||||
return ftruncate(handle_, length) >= 0 ? true : false;
|
return ftruncate(handle_, length) >= 0 ? true : false;
|
||||||
@@ -248,7 +251,17 @@ std::vector<FileInfo> ListFiles(const std::filesystem::path& path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SetAttributes(const std::filesystem::path& path, uint64_t attributes) {
|
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
|
} // namespace filesystem
|
||||||
|
|||||||
Reference in New Issue
Block a user