mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 16:02:37 +00:00
* macos: POSIX platform layer (host fault handler, virtual memory) - hostException: Mach/POSIX signal-based host fault handler mirroring the Windows vectored handler (SIGSEGV/SIGBUS/SIGILL), behind '#elif defined(__APPLE__)'. Windows and Linux branches are untouched. - sysLinuxVirtual: mach_vm_region-based is_mapped (no /proc/self/maps on macOS), PTHREAD_MUTEX_NORMAL, and a MAP_FIXED carve-in-place allocator that never leaves an unmapped hole for dyld/Rosetta/Metal to claim. All __APPLE__-guarded; the original Linux allocator path is preserved verbatim. - sysLinuxDbg/sysLinuxFileIO: libgen.h for basename(), and a POSIX opendir/readdir implementation of SysFileGetDents (previously a stub). * macos: guest kernel backing, threads, and POSIX libs - memory/memoryAddressSpace: anonymous shm_open backing (macOS has no memfd_create) and re-reserve-on-unmap so a guest MAP_FIXED remap never destroys a host mapping (__APPLE__-guarded). Drops host <sys/mman.h> MAP_* macros so the guest's constexpr MAP_* constants compile (no-op on Windows). - pthread: undef the host PTHREAD_STACK_MIN macro; on non-Windows, pin the stack-switch asm's guest rsp/rbp to callee-saved r14/r15 (the template clobbers r12/r13); __APPLE__ no-op for the absent pthread_condattr_setclock. The Windows stack-switch asm is byte-identical. - network: define SOCKET/INVALID_SOCKET for the non-Windows paths (were undefined at 20+ use sites), and rename the non-Windows kernel_clock_* helpers to the CamelCase names the callers already use. Both repair the shared non-Windows build. Integer reinterpret_cast -> static_cast. * loader: pin stack-switch asm operands to callee-saved registers RunEntry switches to the guest stack with an asm template that clobbers r12/r13 before consuming its inputs. With plain "r" constraints the compiler may place func/guest_rsp/guest_rbp into r12/r13, so 'callq *func' jumps through the saved host rsp -- a latent miscompile on every platform that any unrelated codegen change can trigger. Pin the inputs to rbx/r14/r15, which the template never touches and the SysV callee preserves. General correctness fix (not macOS-specific); the same fix is applied to pthread RunOnGuestStack. * macos: Vulkan/MoltenVK graphics enablement - pageManager: GPU write-tracking via Mach VM queries + mprotect (mprotect cannot report the previous protection, so the expected-old check is dropped), thread id via pthread_mach_thread_np, 4 KB page-size check -- __APPLE__-guarded. - shaders/renderDraw/vulkanWindow: MoltenVK lacks VK_EXT_color_write_enable, VK_EXT_depth_clip_enable and depthBounds; fall back to static color-write masks and default depth clipping, request VK_KHR_portability_subset, and reuse the graphics queue for present when only one queue is exposed. Non-Apple pipeline/extension setup is unchanged. - window: optional borderless window (KYTY_BORDERLESS) to sidestep a Rosetta NSException in macOS window chrome. * graphics: macOS thread identity for region tracking Region-ownership locks resolve the current thread via GetCurrentThreadId() on Windows and EXIT elsewhere. Use the Mach thread port on macOS (nonzero per-thread id; 0 stays the no-owner sentinel). * macos: marshal AppKit window operations to the main thread The present worker thread shows the window, updates its icon and title, and recreates a lost Vulkan surface. AppKit traps with 'Must only be used from the main thread' when these run off the main thread. Route them through a small task queue drained by the SDL main loop (an SDL_USEREVENT wakes the loop when it is blocked in SDL_WaitEvent). Title updates are fire-and-forget; showing the window and surface recreation wait for completion. Windows and Linux call the SDL functions directly, as before. * build: ignore the _Build output directory _Build is the conventional out-of-tree build location (only _Build/vscode-clang was ignored); a stray git add could sweep build artifacts into a commit. * macos: isolate stack-switch workaround --------- Co-authored-by: nmzik <Nmzik@mail.ru>
577 lines
13 KiB
C++
577 lines
13 KiB
C++
#include "common/common.h"
|
|
|
|
#if KYTY_PLATFORM != KYTY_PLATFORM_LINUX
|
|
// #error "KYTY_PLATFORM != KYTY_PLATFORM_LINUX"
|
|
#else
|
|
|
|
#include "common/assert.h"
|
|
#include "common/platform/sysFileIO.h"
|
|
#include "common/platform/sysTimer.h"
|
|
#include "common/stringUtils.h"
|
|
|
|
#include <cerrno>
|
|
#include <cstdlib>
|
|
#include <dirent.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <utime.h>
|
|
|
|
// NOLINTNEXTLINE(readability-identifier-naming)
|
|
enum sys_file_type_t {
|
|
SYS_FILE_ERROR, // NOLINT(readability-identifier-naming)
|
|
SYS_FILE_MEMORY_STAT, // NOLINT(readability-identifier-naming)
|
|
SYS_FILE_FILE, // NOLINT(readability-identifier-naming)
|
|
SYS_FILE_MEMORY_DYN // NOLINT(readability-identifier-naming)
|
|
};
|
|
|
|
// NOLINTNEXTLINE(readability-identifier-naming)
|
|
struct sys_file_mem_buf_t {
|
|
uint8_t* base;
|
|
uint8_t* ptr;
|
|
uint32_t size;
|
|
};
|
|
|
|
// NOLINTNEXTLINE(readability-identifier-naming)
|
|
struct sys_file_t {
|
|
sys_file_type_t type;
|
|
union {
|
|
FILE* f;
|
|
sys_file_mem_buf_t* buf;
|
|
};
|
|
};
|
|
|
|
static std::filesystem::path get_internal_name(const std::filesystem::path& name) {
|
|
return name.is_absolute() ? name : (std::filesystem::path(".") / name);
|
|
}
|
|
|
|
void SysFileRead(void* data, uint32_t size, sys_file_t& f, uint32_t* bytes_read) {
|
|
if (f.type == SYS_FILE_FILE) {
|
|
size_t w = fread(data, 1, size, f.f);
|
|
if (bytes_read != nullptr) {
|
|
*bytes_read = w;
|
|
}
|
|
} else if (f.type == SYS_FILE_MEMORY_STAT) {
|
|
uint32_t s = size;
|
|
if (f.buf->size != 0) {
|
|
uint32_t l = f.buf->size - (f.buf->ptr - f.buf->base);
|
|
if (s > l) {
|
|
s = l;
|
|
}
|
|
}
|
|
memcpy(data, f.buf->ptr, s);
|
|
f.buf->ptr += s;
|
|
if (bytes_read != nullptr) {
|
|
*bytes_read = s;
|
|
}
|
|
} else if (f.type == SYS_FILE_MEMORY_DYN) {
|
|
uint32_t s = size;
|
|
if (f.buf->size != 0) {
|
|
uint32_t l = f.buf->size - (f.buf->ptr - f.buf->base);
|
|
if (s > l) {
|
|
s = l;
|
|
}
|
|
} else {
|
|
s = 0;
|
|
}
|
|
memcpy(data, f.buf->ptr, s);
|
|
f.buf->ptr += s;
|
|
if (bytes_read != nullptr) {
|
|
*bytes_read = s;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SysFileWrite(const void* data, uint32_t size, sys_file_t& f, uint32_t* bytes_written) {
|
|
if (f.type == SYS_FILE_FILE) {
|
|
size_t w = fwrite(data, 1, size, f.f);
|
|
if (bytes_written != nullptr) {
|
|
*bytes_written = w;
|
|
}
|
|
} else if (f.type == SYS_FILE_MEMORY_STAT) {
|
|
uint32_t s = size;
|
|
if (f.buf->size != 0) {
|
|
uint32_t l = f.buf->size - (f.buf->ptr - f.buf->base);
|
|
if (s > l) {
|
|
s = l;
|
|
}
|
|
}
|
|
memcpy(f.buf->ptr, data, s);
|
|
f.buf->ptr += s;
|
|
if (bytes_written != nullptr) {
|
|
*bytes_written = s;
|
|
}
|
|
} else if (f.type == SYS_FILE_MEMORY_DYN) {
|
|
uint32_t pos = f.buf->ptr - f.buf->base;
|
|
if (f.buf->size < pos + size) {
|
|
f.buf->base = static_cast<uint8_t*>(std::realloc(f.buf->base, pos + size));
|
|
f.buf->ptr = f.buf->base + pos;
|
|
f.buf->size = pos + size;
|
|
}
|
|
memcpy(f.buf->ptr, data, size);
|
|
f.buf->ptr += size;
|
|
if (bytes_written != nullptr) {
|
|
*bytes_written = size;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SysFileWrite(uint32_t n, sys_file_t& f) {
|
|
SysFileWrite(&n, 4, f);
|
|
}
|
|
|
|
sys_file_t* SysFileCreate(const std::filesystem::path& file_name) {
|
|
auto* ret = new sys_file_t;
|
|
|
|
auto real_name = get_internal_name(file_name);
|
|
auto real_name_str = real_name.string();
|
|
|
|
ret->f = fopen(real_name_str.c_str(), "w+");
|
|
|
|
if (ret->f == nullptr) {
|
|
printf("can't create file: %s\n", real_name_str.c_str());
|
|
}
|
|
|
|
ret->type = SYS_FILE_FILE;
|
|
|
|
return ret;
|
|
}
|
|
|
|
sys_file_t* SysFileOpenR(const std::filesystem::path& file_name,
|
|
sys_file_cache_type_t /*cache_type*/) {
|
|
auto* ret = new sys_file_t;
|
|
|
|
ret->type = SYS_FILE_FILE;
|
|
|
|
auto internal_name = get_internal_name(file_name);
|
|
auto internal_name_str = internal_name.string();
|
|
|
|
FILE* f = fopen(internal_name_str.c_str(), "r");
|
|
|
|
if (f == nullptr) {
|
|
ret->type = SYS_FILE_ERROR;
|
|
}
|
|
|
|
ret->f = f;
|
|
|
|
return ret;
|
|
}
|
|
|
|
sys_file_t* SysFileOpen(uint8_t* buf, uint32_t buf_size) {
|
|
auto* ret = new sys_file_t;
|
|
|
|
ret->type = SYS_FILE_MEMORY_STAT;
|
|
ret->buf = new sys_file_mem_buf_t;
|
|
ret->buf->base = buf;
|
|
ret->buf->ptr = buf;
|
|
ret->buf->size = buf_size;
|
|
|
|
return ret;
|
|
}
|
|
|
|
sys_file_t* SysFileCreate() {
|
|
auto* ret = new sys_file_t;
|
|
|
|
ret->type = SYS_FILE_MEMORY_DYN;
|
|
ret->buf = new sys_file_mem_buf_t;
|
|
ret->buf->base = nullptr;
|
|
ret->buf->ptr = nullptr;
|
|
ret->buf->size = 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
sys_file_t* SysFileOpenW(const std::filesystem::path& file_name,
|
|
sys_file_cache_type_t /*cache_type*/) {
|
|
auto* ret = new sys_file_t;
|
|
|
|
auto real_name = get_internal_name(file_name);
|
|
auto real_name_str = real_name.string();
|
|
|
|
FILE* f = fopen(real_name_str.c_str(), "r+");
|
|
|
|
if (f == nullptr) {
|
|
ret->type = SYS_FILE_ERROR;
|
|
} else {
|
|
ret->type = SYS_FILE_FILE;
|
|
}
|
|
|
|
ret->f = f;
|
|
|
|
return ret;
|
|
}
|
|
|
|
sys_file_t* SysFileOpenRw(const std::filesystem::path& file_name,
|
|
sys_file_cache_type_t /*cache_type*/) {
|
|
auto* ret = new sys_file_t;
|
|
|
|
auto real_name = get_internal_name(file_name);
|
|
auto real_name_str = real_name.string();
|
|
|
|
FILE* f = fopen(real_name_str.c_str(), "r+");
|
|
|
|
if (f == nullptr) {
|
|
ret->type = SYS_FILE_ERROR;
|
|
} else {
|
|
ret->type = SYS_FILE_FILE;
|
|
}
|
|
|
|
ret->f = f;
|
|
|
|
return ret;
|
|
}
|
|
|
|
void SysFileClose(sys_file_t* f) {
|
|
[[maybe_unused]] int result = 0;
|
|
|
|
if (f->type == SYS_FILE_FILE && f->f != nullptr) {
|
|
result = fclose(f->f);
|
|
} else if (f->type == SYS_FILE_MEMORY_STAT) {
|
|
delete f->buf;
|
|
} else if (f->type == SYS_FILE_MEMORY_DYN) {
|
|
std::free(f->buf->base);
|
|
delete f->buf;
|
|
}
|
|
|
|
// f.type = SYS_FILE_ERROR;
|
|
delete f;
|
|
}
|
|
|
|
uint64_t SysFileSize(sys_file_t& f) {
|
|
[[maybe_unused]] int result = 0;
|
|
|
|
if (f.type == SYS_FILE_FILE) {
|
|
uint32_t pos = ftell(f.f);
|
|
result = fseek(f.f, 0, SEEK_END);
|
|
uint32_t size = ftell(f.f);
|
|
result = fseek(f.f, pos, SEEK_SET);
|
|
return size;
|
|
}
|
|
|
|
if (f.type == SYS_FILE_MEMORY_STAT || f.type == SYS_FILE_MEMORY_DYN) {
|
|
return f.buf->size;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint64_t SysFileSize(const std::filesystem::path& file_name) {
|
|
sys_file_t* f = SysFileOpenR(file_name);
|
|
uint64_t size = SysFileSize(*f);
|
|
SysFileClose(f);
|
|
return size;
|
|
}
|
|
|
|
bool SysFileTruncate(sys_file_t& /*f*/, uint64_t /*size*/) {
|
|
return false;
|
|
}
|
|
|
|
bool SysFileUnlink(sys_file_t& /*f*/, const std::filesystem::path& name) {
|
|
return SysFileDeleteFile(name);
|
|
}
|
|
|
|
bool SysFileSeek(sys_file_t& f, uint64_t offset) {
|
|
bool ok = true;
|
|
if (f.type == SYS_FILE_FILE) {
|
|
ok = (fseek(f.f, static_cast<int64_t>(offset), SEEK_SET) == 0);
|
|
// LARGE_INTEGER s;
|
|
// s.QuadPart = offset;
|
|
// SetFilePointerEx(f.handle, s, 0, FILE_BEGIN);
|
|
// printf("seek: %u\n", offset);
|
|
} else if (f.type == SYS_FILE_MEMORY_STAT || f.type == SYS_FILE_MEMORY_DYN) {
|
|
f.buf->ptr = f.buf->base + offset;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
uint64_t SysFileTell(sys_file_t& f) {
|
|
if (f.type == SYS_FILE_FILE) {
|
|
return ftell(f.f);
|
|
}
|
|
|
|
if (f.type == SYS_FILE_MEMORY_STAT || f.type == SYS_FILE_MEMORY_DYN) {
|
|
return f.buf->ptr - f.buf->base;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool SysFileIsError(sys_file_t& f) {
|
|
return f.type == SYS_FILE_ERROR || (f.type == SYS_FILE_FILE && f.f == nullptr);
|
|
}
|
|
|
|
bool SysFileIsDirectoryExisting(const std::filesystem::path& path) {
|
|
auto real_name = get_internal_name(path);
|
|
auto real_name_str = real_name.string();
|
|
|
|
struct stat s {};
|
|
|
|
if (0 != stat(real_name_str.c_str(), &s)) {
|
|
return false;
|
|
}
|
|
|
|
return S_ISDIR(s.st_mode); // NOLINT
|
|
}
|
|
|
|
bool SysFileIsFileExisting(const std::filesystem::path& name) {
|
|
auto real_name = get_internal_name(name);
|
|
auto real_name_str = real_name.string();
|
|
|
|
struct stat s {};
|
|
|
|
if (0 != stat(real_name_str.c_str(), &s)) {
|
|
return false;
|
|
}
|
|
|
|
return !S_ISDIR(s.st_mode); // NOLINT
|
|
}
|
|
|
|
bool SysFileCreateDirectory(const std::filesystem::path& path) {
|
|
auto real_name = get_internal_name(path);
|
|
auto real_name_str = real_name.string();
|
|
|
|
mode_t m = S_IRWXU | S_IRWXG | S_IRWXO; // NOLINT
|
|
|
|
int r = mkdir(real_name_str.c_str(), m);
|
|
|
|
if (r != 0) {
|
|
int e = errno;
|
|
if (e == EEXIST) {
|
|
printf("mkdir(%s, %" PRIx32 ") failed: The named file exists\n", real_name_str.c_str(),
|
|
static_cast<uint32_t>(m));
|
|
} else {
|
|
printf("mkdir(%s, %" PRIx32 ") failed: %d\n", real_name_str.c_str(),
|
|
static_cast<uint32_t>(m), e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SysFileDeleteDirectory(const std::filesystem::path& path) {
|
|
auto real_name = get_internal_name(path);
|
|
auto real_name_str = real_name.string();
|
|
|
|
return 0 == remove(real_name_str.c_str());
|
|
}
|
|
|
|
bool SysFileDeleteFile(const std::filesystem::path& name) {
|
|
auto real_name = get_internal_name(name);
|
|
auto real_name_str = real_name.string();
|
|
|
|
return 0 == unlink(real_name_str.c_str());
|
|
}
|
|
|
|
bool SysFileFlush(sys_file_t& f) {
|
|
if (f.type == SYS_FILE_FILE && f.f != nullptr) {
|
|
return (fflush(f.f) == 0);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
SysFileTimeStruct SysFileGetLastAccessTimeUtc(const std::filesystem::path& name) {
|
|
SysFileTimeStruct r {};
|
|
|
|
auto real_name = get_internal_name(name);
|
|
auto real_name_str = real_name.string();
|
|
|
|
struct stat s {};
|
|
|
|
if (0 != stat(real_name_str.c_str(), &s)) {
|
|
r.is_invalid = true;
|
|
} else {
|
|
r.is_invalid = false;
|
|
r.time = s.st_atime;
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
SysFileTimeStruct SysFileGetLastWriteTimeUtc(const std::filesystem::path& name) {
|
|
SysFileTimeStruct r {};
|
|
|
|
auto real_name = get_internal_name(name);
|
|
auto real_name_str = real_name.string();
|
|
|
|
struct stat s {};
|
|
|
|
if (0 != stat(real_name_str.c_str(), &s)) {
|
|
r.is_invalid = true;
|
|
} else {
|
|
r.is_invalid = false;
|
|
r.time = s.st_mtime;
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
void SysFileGetLastAccessAndWriteTimeUtc(const std::filesystem::path& name, SysFileTimeStruct& a,
|
|
SysFileTimeStruct& w) {
|
|
auto real_name = get_internal_name(name);
|
|
auto real_name_str = real_name.string();
|
|
|
|
struct stat s {};
|
|
|
|
if (0 != stat(real_name_str.c_str(), &s)) {
|
|
a.is_invalid = true;
|
|
w.is_invalid = true;
|
|
} else {
|
|
a.is_invalid = false;
|
|
w.is_invalid = false;
|
|
a.time = s.st_atime;
|
|
w.time = s.st_mtime;
|
|
}
|
|
}
|
|
|
|
void SysFileGetLastAccessAndWriteTimeUtc(sys_file_t& /*f*/, SysFileTimeStruct& /*a*/,
|
|
SysFileTimeStruct& /*w*/) {
|
|
EXIT("not implemented\n");
|
|
}
|
|
|
|
bool SysFileSetLastAccessTimeUtc(const std::filesystem::path& name, SysFileTimeStruct& access) {
|
|
if (access.is_invalid) {
|
|
return false;
|
|
}
|
|
|
|
auto real_name = get_internal_name(name);
|
|
auto real_name_str = real_name.string();
|
|
|
|
struct stat s {};
|
|
|
|
if (0 != stat(real_name_str.c_str(), &s)) {
|
|
return false;
|
|
}
|
|
|
|
utimbuf times {};
|
|
times.actime = access.time;
|
|
times.modtime = s.st_mtime;
|
|
|
|
return !(0 != utime(real_name_str.c_str(), ×));
|
|
|
|
// if (0 != stat(n.data(), &s))
|
|
// {
|
|
// return false;
|
|
// }
|
|
//
|
|
// times.actime += times.actime - s.st_atime;
|
|
// times.modtime += times.modtime - s.st_mtime;
|
|
//
|
|
// if (0 != utime(n.data(), ×))
|
|
// {
|
|
// return false;
|
|
// }
|
|
}
|
|
|
|
bool SysFileSetLastWriteTimeUtc(const std::filesystem::path& name, SysFileTimeStruct& write) {
|
|
if (write.is_invalid) {
|
|
return false;
|
|
}
|
|
|
|
auto real_name = get_internal_name(name);
|
|
auto real_name_str = real_name.string();
|
|
|
|
struct stat s {};
|
|
|
|
if (0 != stat(real_name_str.c_str(), &s)) {
|
|
return false;
|
|
}
|
|
|
|
utimbuf times {};
|
|
times.actime = s.st_atime;
|
|
times.modtime = write.time;
|
|
|
|
return !(0 != utime(real_name_str.c_str(), ×));
|
|
|
|
// if (0 != stat(n.data(), &s))
|
|
// {
|
|
// return false;
|
|
// }
|
|
//
|
|
// times.actime += times.actime - s.st_atime;
|
|
// times.modtime += times.modtime - s.st_mtime;
|
|
//
|
|
// if (0 != utime(n.data(), ×))
|
|
// {
|
|
// return false;
|
|
// }
|
|
}
|
|
|
|
bool SysFileSetLastAccessAndWriteTimeUtc(const std::filesystem::path& name,
|
|
SysFileTimeStruct& access, SysFileTimeStruct& write) {
|
|
if (access.is_invalid || write.is_invalid) {
|
|
return false;
|
|
}
|
|
|
|
auto real_name = get_internal_name(name);
|
|
auto real_name_str = real_name.string();
|
|
|
|
struct stat s {};
|
|
|
|
if (0 != stat(real_name_str.c_str(), &s)) {
|
|
return false;
|
|
}
|
|
|
|
utimbuf times {};
|
|
times.actime = access.time;
|
|
times.modtime = write.time;
|
|
|
|
return !(0 != utime(real_name_str.c_str(), ×));
|
|
|
|
// if (0 != stat(n.data(), &s))
|
|
// {
|
|
// return false;
|
|
// }
|
|
//
|
|
// times.actime += times.actime - s.st_atime;
|
|
// times.modtime += times.modtime - s.st_mtime;
|
|
//
|
|
// if (0 != utime(n.data(), ×))
|
|
// {
|
|
// return false;
|
|
// }
|
|
}
|
|
|
|
void SysFileFindFiles(const std::filesystem::path& /*path*/,
|
|
std::vector<sys_file_find_t>& /*out*/) {
|
|
EXIT("not implemented\n");
|
|
}
|
|
|
|
void SysFileGetDents(const std::filesystem::path& path, std::vector<sys_dir_entry_t>& out) {
|
|
DIR* dir = opendir(path.c_str());
|
|
if (dir == nullptr) {
|
|
return;
|
|
}
|
|
for (dirent* entry = readdir(dir); entry != nullptr; entry = readdir(dir)) {
|
|
sys_dir_entry_t r {};
|
|
r.name = entry->d_name;
|
|
if (entry->d_type == DT_REG) {
|
|
r.is_file = true;
|
|
} else if (entry->d_type == DT_DIR) {
|
|
r.is_file = false;
|
|
} else {
|
|
// DT_UNKNOWN / symlink: resolve with stat.
|
|
struct stat st {};
|
|
r.is_file = (stat((path / entry->d_name).c_str(), &st) == 0) ? S_ISREG(st.st_mode) : true;
|
|
}
|
|
out.push_back(std::move(r));
|
|
}
|
|
closedir(dir);
|
|
}
|
|
|
|
bool SysFileCopyFile(const std::filesystem::path& /*src*/, const std::filesystem::path& /*dst*/) {
|
|
EXIT("not implemented\n");
|
|
return false;
|
|
}
|
|
|
|
bool SysFileMoveFile(const std::filesystem::path& /*src*/, const std::filesystem::path& /*dst*/) {
|
|
EXIT("not implemented\n");
|
|
return false;
|
|
}
|
|
|
|
void SysFileRemoveReadonly(const std::filesystem::path& /*name*/) {
|
|
EXIT("not implemented\n");
|
|
}
|
|
|
|
#endif
|