symlinks on *dows

This commit is contained in:
marecl 2025-11-27 14:30:02 +01:00
parent 4c5d46f92c
commit f603db3abb
2 changed files with 34 additions and 23 deletions

View File

@ -5,6 +5,7 @@
#ifdef _WIN32
#include <cstdint>
#include <unordered_map>
#include <fcntl.h>
#include <windows.h>
@ -15,6 +16,9 @@ namespace HostIODriver {
class HostIO_Win32 final : public HostIO_Base {
std::unordered_map<fs::path, fs::path> symlinks;
fs::path GetSymlink(fs::path path);
public:
//
// Conversion helpers
@ -50,21 +54,13 @@ public:
if (quasi_flags & QUASI_O_APPEND)
flags |= _O_APPEND;
// No info, maybe there are some equivalents
// if (quasi_flags & QUASI_O_NONBLOCK)
// flags |= _O_NONBLOCK;
// if (quasi_flags & QUASI_O_SYNC)
// flags |= _O_SYNC;
// if (quasi_flags & QUASI_O_FSYNC)
// flags |= _O_FSYNC;
if (quasi_flags & QUASI_O_DIRECTORY)
flags |= _O_OBTAIN_DIR; // I don't like how this one looks
// if (quasi_flags & QUASI_O_DIRECT)
// flags |= _O_DIRECT;
// if (quasi_flags & QUASI_O_DSYNC)
// flags |= _O_DSYNC;
if (int status = quasi_flags & (QUASI_O_NONBLOCK | QUASI_O_SYNC | QUASI_O_FSYNC |
QUASI_O_DIRECT | QUASI_O_DSYNC);
0 != status)
LOG_WARNING(Kernel_Fs, "Received unknown or unsupported flags: {:x}", status);
return flags;
}

View File

@ -12,18 +12,22 @@
namespace HostIODriver {
HostIO_Win32::HostIO_Win32() = default;
HostIO_Win32::HostIO_Win32() {
this->symlinks.clear();
this->symlinks.reserve(16);
}
HostIO_Win32::~HostIO_Win32() = default;
s32 HostIO_Win32::Open(const fs::path& path, s32 flags, u16 mode) {
errno = 0;
s32 status = _wopen(path.c_str(), ToWIN32OpenFlags(flags), mode);
s32 status = _wopen(GetSymlink(path).c_str(), ToWIN32OpenFlags(flags), mode);
return status >= 0 ? status : -unix2bsd(errno);
}
s32 HostIO_Win32::Creat(const fs::path& path, u16 mode) {
errno = 0;
s32 status = _wcreat(path.c_str(), mode);
s32 status = _wcreat(GetSymlink(path).c_str(), mode);
return status >= 0 ? status : -unix2bsd(errno);
}
@ -35,7 +39,7 @@ s32 HostIO_Win32::Close(const s32 fd) {
s32 HostIO_Win32::Link(const fs::path& src, const fs::path& dst) {
errno = 0;
s32 status = CreateHardLinkW(dst.c_str(), src.c_str(), nullptr);
s32 status = CreateHardLinkW(dst.c_str(), GetSymlink(src).c_str(), nullptr);
return 0 == status ? 0 : -win2bsd(GetLastError());
}
@ -47,14 +51,14 @@ s32 HostIO_Win32::Link(const fs::path& src, const fs::path& dst) {
s32 HostIO_Win32::Unlink(const fs::path& path) {
errno = 0;
s32 status = DeleteFileW(path.c_str());
s32 status = DeleteFileW(GetSymlink(path).c_str());
return status > 0 ? status : -win2bsd(GetLastError());
}
s32 HostIO_Win32::Remove(const fs::path& path) {
errno = 0;
if (int status = DeleteFileW(path.c_str()); status > 0)
if (int status = DeleteFileW(GetSymlink(path).c_str()); status > 0)
return 0;
auto last_error = GetLastError();
// no idea if these are correlated (yet)
@ -64,7 +68,7 @@ s32 HostIO_Win32::Remove(const fs::path& path) {
if (last_error == ERROR_FILE_NOT_FOUND || last_error == ERROR_PATH_NOT_FOUND)
return false;
return RemoveDirectoryW(path.c_str());
return RemoveDirectoryW(GetSymlink(path).c_str());
}
s32 HostIO_Win32::Flush(const s32 fd) {
@ -90,7 +94,7 @@ s64 HostIO_Win32::Tell(const s32 fd) {
int HostIO_Win32::Truncate(const fs::path& path, u64 size) {
errno = 0;
s32 fd = _wopen(path.c_str(), _O_RDONLY);
s32 fd = _wopen(GetSymlink(path).c_str(), _O_RDONLY);
if (fd < 0)
return -unix2bsd(errno);
s32 status = _chsize_s(fd, size);
@ -158,13 +162,13 @@ s64 HostIO_Win32::PWriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt,
s32 HostIO_Win32::MKDir(const fs::path& path, u16 mode) {
errno = 0;
s32 status = _wmkdir(path.c_str());
s32 status = _wmkdir(GetSymlink(path).c_str());
return status >= 0 ? status : -unix2bsd(errno);
}
s32 HostIO_Win32::RMDir(const fs::path& path) {
errno = 0;
s32 status = _wrmdir(path.c_str());
s32 status = _wrmdir(GetSymlink(path).c_str());
return status >= 0 ? status : -unix2bsd(errno);
}
@ -176,7 +180,7 @@ s32 HostIO_Win32::RMDir(const fs::path& path) {
s32 HostIO_Win32::Copy(const fs::path& src, const fs::path& dst, bool fail_if_exists) {
errno = 0;
auto status = CopyFileW(src.c_str(), dst.c_str(), fail_if_exists);
auto status = CopyFileW(GetSymlink(src).c_str(), dst.c_str(), fail_if_exists);
return status > 0 ? status : -unix2bsd(GetLastError());
}
@ -185,4 +189,15 @@ s32 HostIO_Win32::Move(const fs::path& src, const fs::path& dst, bool fail_if_ex
return -unix2bsd(ENOSYS);
}
fs::path HostIO_Win32::GetSymlink(fs::path path) {
// this is a very, **very** bad implementation of symlinks
// may work for files, but certainly not for directories
// in fact, i am terribly ashamed of going this route, but
// since games don't use symlinks often, i can get away with this
auto sym = this->symlinks.find(path);
if (this->symlinks.end() == sym)
return path;
return sym->second;
}
} // namespace HostIODriver