mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-25 20:25:38 -06:00
Implemented some link() on windows
Added copy/move/rename Added cloning FS objects (deep-copy)
This commit is contained in:
parent
7a59a19bda
commit
8d4197e71a
@ -89,8 +89,9 @@ public:
|
||||
s32 Close(const s32 fd) override;
|
||||
|
||||
s32 Link(const fs::path& src, const fs::path& dst) override;
|
||||
s32 Unlink(const fs::path& path) override;
|
||||
s32 LinkSymbolic(const fs::path& src, const fs::path& dst) override;
|
||||
s32 Unlink(const fs::path& path) override;
|
||||
s32 Remove(const fs::path& path) override;
|
||||
|
||||
s32 Flush(const s32 fd) override;
|
||||
s32 FSync(const s32 fd) override;
|
||||
@ -118,6 +119,9 @@ public:
|
||||
|
||||
s32 Chmod(const fs::path& path, u16 mode) override;
|
||||
s32 FChmod(const s32 fd, u16 mode) override;
|
||||
|
||||
s32 Copy(const char* src, const char* dst) override;
|
||||
s32 Move(const fs::path& src, const fs::path& dst, bool fail_if_exists) override;
|
||||
};
|
||||
} // namespace HostIODriver
|
||||
|
||||
|
||||
@ -50,8 +50,9 @@ public:
|
||||
s32 Close(const s32 fd) override;
|
||||
|
||||
s32 Link(const fs::path& src, const fs::path& dst) override;
|
||||
s32 Unlink(const fs::path& path) override;
|
||||
s32 LinkSymbolic(const fs::path& src, const fs::path& dst) override;
|
||||
s32 Unlink(const fs::path& path) override;
|
||||
s32 Remove(const fs::path& path) override;
|
||||
|
||||
s32 Flush(const s32 fd) override;
|
||||
s32 FSync(const s32 fd) override;
|
||||
@ -81,8 +82,8 @@ public:
|
||||
s32 FChmod(const s32 fd, u16 mode) override;
|
||||
|
||||
s64 GetDents(const s32 fd, void* buf, u64 count, s64* basep) override;
|
||||
//
|
||||
// Derived, complex functions are to be handled by main FS class
|
||||
//
|
||||
|
||||
s32 Copy(const fs::path& src, const fs::path& dst, bool fail_if_exists) override;
|
||||
s32 Move(const fs::path& src, const fs::path& dst, bool fail_if_exists) override;
|
||||
};
|
||||
} // namespace HostIODriver
|
||||
@ -4,10 +4,7 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// #error unimplemented
|
||||
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
#include <fcntl.h>
|
||||
#include <windows.h>
|
||||
|
||||
@ -79,9 +76,10 @@ public:
|
||||
s32 Creat(const fs::path& path, u16 mode = 0755) override;
|
||||
s32 Close(const s32 fd) override;
|
||||
|
||||
// s32 Link(const fs::path& src, const fs::path& dst) override;
|
||||
// s32 Unlink(const fs::path& path) override;
|
||||
s32 Link(const fs::path& src, const fs::path& dst) override;
|
||||
// s32 LinkSymbolic(const fs::path& src, const fs::path& dst) override;
|
||||
s32 Unlink(const fs::path& path) override;
|
||||
s32 Remove(const fs::path& path) override;
|
||||
|
||||
s32 Flush(const s32 fd) override;
|
||||
s32 FSync(const s32 fd) override;
|
||||
@ -109,6 +107,9 @@ public:
|
||||
|
||||
// s32 Chmod(const fs::path& path, u16 mode) override;
|
||||
// s32 FChmod(const s32 fd, u16 mode) override;
|
||||
|
||||
s32 Copy(const fs::path& src, const fs::path& dst, bool fail_if_exists) override;
|
||||
s32 Move(const fs::path& src, const fs::path& dst, bool fail_if_exists) override;
|
||||
};
|
||||
|
||||
} // namespace HostIODriver
|
||||
|
||||
@ -21,8 +21,9 @@ s32 HostIO_Base::Creat(const fs::path& path, u16 mode) { STUB(); }
|
||||
s32 HostIO_Base::Close(const s32 fd) { STUB(); }
|
||||
|
||||
s32 HostIO_Base::Link(const fs::path& src, const fs::path& dst) { STUB(); }
|
||||
s32 HostIO_Base::Unlink(const fs::path& path) { STUB(); }
|
||||
s32 HostIO_Base::LinkSymbolic(const fs::path& src, const fs::path& dst) { STUB(); }
|
||||
s32 HostIO_Base::Unlink(const fs::path& path) { STUB(); }
|
||||
s32 HostIO_Base::Remove(const fs::path& path) { STUB(); }
|
||||
|
||||
s32 HostIO_Base::Flush(const s32 fd) { STUB(); }
|
||||
s32 HostIO_Base::FSync(const s32 fd) { STUB(); }
|
||||
@ -54,6 +55,13 @@ s32 HostIO_Base::Chmod(const fs::path& path, u16 mode) { STUB(); }
|
||||
s32 HostIO_Base::FChmod(const s32 fd, u16 mode) { STUB(); }
|
||||
|
||||
s64 HostIO_Base::GetDents(const s32 fd, void* buf, u64 count, s64* basep) { STUB(); }
|
||||
|
||||
s32 HostIO_Base::Copy(const fs::path& src, const fs::path& dst, bool fail_if_exists) { STUB(); }
|
||||
s32 HostIO_Base::Move(const fs::path& src, const fs::path& dst, bool fail_if_exists) { STUB(); }
|
||||
// clang-format on
|
||||
|
||||
s32 HostIO_Base::Rename(const fs::path& src, const fs::path& dst_name, bool fail_if_exists) {
|
||||
return Move(src, src.parent_path() / dst_name, fail_if_exists);
|
||||
}
|
||||
|
||||
} // namespace HostIODriver
|
||||
@ -27,9 +27,11 @@ public:
|
||||
virtual s32 Creat(const fs::path& path, u16 mode = 0755);
|
||||
virtual s32 Close(const s32 fd);
|
||||
|
||||
virtual s32 LinkSymbolic(const fs::path& src, const fs::path& dst);
|
||||
virtual s32 Link(const fs::path& src, const fs::path& dst);
|
||||
virtual s32 LinkSymbolic(const fs::path& src, const fs::path& dst);
|
||||
virtual s32 Unlink(const fs::path& path);
|
||||
virtual s32 Remove(const fs::path& path);
|
||||
|
||||
virtual s32 Flush(const s32 fd);
|
||||
virtual s32 FSync(const s32 fd);
|
||||
virtual s32 Truncate(const fs::path& path, u64 size);
|
||||
@ -57,6 +59,10 @@ public:
|
||||
virtual s32 FChmod(const s32 fd, u16 mode);
|
||||
|
||||
virtual s64 GetDents(const s32 fd, void* buf, u64 count, s64* basep);
|
||||
|
||||
virtual s32 Copy(const fs::path& src, const fs::path& dst, bool fail_if_exists);
|
||||
virtual s32 Move(const fs::path& src, const fs::path& dst, bool fail_if_exists);
|
||||
s32 Rename(const fs::path& src, const fs::path& dst_name, bool fail_if_exists);
|
||||
//
|
||||
// Derived, complex functions are to be handled by main FS class
|
||||
//
|
||||
|
||||
@ -1,4 +1,9 @@
|
||||
#include <sys/fcntl.h>
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/libraries/kernel/posix_error.h"
|
||||
@ -6,394 +11,291 @@
|
||||
// Convert linux/unix errno to FreeBSD errno
|
||||
// They differ in higher errno numbers, which may throw Orbis off quite a bit
|
||||
|
||||
s32 posix2bsd(s32 id) {
|
||||
s32 unix2bsd(s32 id) {
|
||||
switch (id) {
|
||||
default:
|
||||
UNREACHABLE_MSG("Unknown POSIX errno");
|
||||
case:
|
||||
POSIX_EPERM:
|
||||
case POSIX_EPERM:
|
||||
return EPERM;
|
||||
case:
|
||||
POSIX_ENOENT:
|
||||
case POSIX_ENOENT:
|
||||
return ENOENT;
|
||||
case:
|
||||
POSIX_ESRCH:
|
||||
case POSIX_ESRCH:
|
||||
return ESRCH;
|
||||
case:
|
||||
POSIX_EINTR:
|
||||
case POSIX_EINTR:
|
||||
return EINTR;
|
||||
case:
|
||||
POSIX_EIO:
|
||||
case POSIX_EIO:
|
||||
return EIO;
|
||||
case:
|
||||
POSIX_ENXIO:
|
||||
case POSIX_ENXIO:
|
||||
return ENXIO;
|
||||
case:
|
||||
POSIX_E2BIG:
|
||||
case POSIX_E2BIG:
|
||||
return E2BIG;
|
||||
case:
|
||||
POSIX_ENOEXEC:
|
||||
case POSIX_ENOEXEC:
|
||||
return ENOEXEC;
|
||||
case:
|
||||
POSIX_EBADF:
|
||||
case POSIX_EBADF:
|
||||
return EBADF;
|
||||
case:
|
||||
POSIX_ECHILD:
|
||||
case POSIX_ECHILD:
|
||||
return ECHILD;
|
||||
case:
|
||||
POSIX_EDEADLK:
|
||||
case POSIX_EDEADLK:
|
||||
return EDEADLK;
|
||||
case:
|
||||
POSIX_ENOMEM:
|
||||
case POSIX_ENOMEM:
|
||||
return ENOMEM;
|
||||
case:
|
||||
POSIX_EACCES:
|
||||
case POSIX_EACCES:
|
||||
return EACCES;
|
||||
case:
|
||||
POSIX_EFAULT:
|
||||
case POSIX_EFAULT:
|
||||
return EFAULT;
|
||||
|
||||
// case:
|
||||
// POSIX_ENOTBLK:
|
||||
// return ENOTBLK;
|
||||
|
||||
case:
|
||||
POSIX_ENOTBLK:
|
||||
return ENODEV; //?
|
||||
#ifndef _WIN32
|
||||
case POSIX_ENOTBLK:
|
||||
return ENOTBLK;
|
||||
#endif
|
||||
|
||||
case:
|
||||
POSIX_EBUSY:
|
||||
case POSIX_EBUSY:
|
||||
return EBUSY;
|
||||
case:
|
||||
POSIX_EEXIST:
|
||||
case POSIX_EEXIST:
|
||||
return EEXIST;
|
||||
case:
|
||||
POSIX_EXDEV:
|
||||
case POSIX_EXDEV:
|
||||
return EXDEV;
|
||||
case:
|
||||
POSIX_ENODEV:
|
||||
case POSIX_ENODEV:
|
||||
return ENODEV;
|
||||
case:
|
||||
POSIX_ENOTDIR:
|
||||
case POSIX_ENOTDIR:
|
||||
return ENOTDIR;
|
||||
case:
|
||||
POSIX_EISDIR:
|
||||
case POSIX_EISDIR:
|
||||
return EISDIR;
|
||||
case:
|
||||
POSIX_EINVAL:
|
||||
case POSIX_EINVAL:
|
||||
return EINVAL;
|
||||
case:
|
||||
POSIX_ENFILE:
|
||||
case POSIX_ENFILE:
|
||||
return ENFILE;
|
||||
case:
|
||||
POSIX_EMFILE:
|
||||
case POSIX_EMFILE:
|
||||
return EMFILE;
|
||||
case:
|
||||
POSIX_ENOTTY:
|
||||
case POSIX_ENOTTY:
|
||||
return ENOTTY;
|
||||
case:
|
||||
POSIX_ETXTBSY:
|
||||
case POSIX_ETXTBSY:
|
||||
return ETXTBSY;
|
||||
case:
|
||||
POSIX_EFBIG:
|
||||
case POSIX_EFBIG:
|
||||
return EFBIG;
|
||||
case:
|
||||
POSIX_ENOSPC:
|
||||
case POSIX_ENOSPC:
|
||||
return ENOSPC;
|
||||
case:
|
||||
POSIX_ESPIPE:
|
||||
case POSIX_ESPIPE:
|
||||
return ESPIPE;
|
||||
case:
|
||||
POSIX_EROFS:
|
||||
case POSIX_EROFS:
|
||||
return EROFS;
|
||||
case:
|
||||
POSIX_EMLINK:
|
||||
case POSIX_EMLINK:
|
||||
return EMLINK;
|
||||
case:
|
||||
POSIX_EPIPE:
|
||||
case POSIX_EPIPE:
|
||||
return EPIPE;
|
||||
case:
|
||||
POSIX_EDOM:
|
||||
case POSIX_EDOM:
|
||||
return EDOM;
|
||||
case:
|
||||
POSIX_ERANGE:
|
||||
case POSIX_ERANGE:
|
||||
return ERANGE;
|
||||
case:
|
||||
POSIX_EAGAIN:
|
||||
case POSIX_EAGAIN:
|
||||
return EAGAIN;
|
||||
case:
|
||||
POSIX_EWOULDBLOCK:
|
||||
return EWOULDBLOCK;
|
||||
case:
|
||||
POSIX_EINPROGRESS:
|
||||
// same as POSIX_EAGAIN
|
||||
// case POSIX_EWOULDBLOCK:
|
||||
// return EWOULDBLOCK;
|
||||
case POSIX_EINPROGRESS:
|
||||
return EINPROGRESS;
|
||||
case:
|
||||
POSIX_EALREADY:
|
||||
case POSIX_EALREADY:
|
||||
return EALREADY;
|
||||
case:
|
||||
POSIX_ENOTSOCK:
|
||||
case POSIX_ENOTSOCK:
|
||||
return ENOTSOCK;
|
||||
case:
|
||||
POSIX_EDESTADDRREQ:
|
||||
case POSIX_EDESTADDRREQ:
|
||||
return EDESTADDRREQ;
|
||||
case:
|
||||
POSIX_EMSGSIZE:
|
||||
case POSIX_EMSGSIZE:
|
||||
return EMSGSIZE;
|
||||
case:
|
||||
POSIX_EPROTOTYPE:
|
||||
case POSIX_EPROTOTYPE:
|
||||
return EPROTOTYPE;
|
||||
case:
|
||||
POSIX_ENOPROTOOPT:
|
||||
case POSIX_ENOPROTOOPT:
|
||||
return ENOPROTOOPT;
|
||||
case:
|
||||
POSIX_EPROTONOSUPPORT:
|
||||
case POSIX_EPROTONOSUPPORT:
|
||||
return EPROTONOSUPPORT;
|
||||
|
||||
// case:
|
||||
// POSIX_ESOCKTNOSUPPORT:
|
||||
// return ESOCKTNOSUPPORT; // ?
|
||||
#ifndef _WIN32
|
||||
case POSIX_ESOCKTNOSUPPORT:
|
||||
return ESOCKTNOSUPPORT;
|
||||
#endif
|
||||
|
||||
case:
|
||||
POSIX_EOPNOTSUPP:
|
||||
case POSIX_EOPNOTSUPP:
|
||||
return EOPNOTSUPP;
|
||||
case:
|
||||
POSIX_ENOTSUP:
|
||||
return ENOTSUP;
|
||||
// same as POSIX_EOPNOTSUPP
|
||||
// case POSIX_ENOTSUP:
|
||||
// return ENOTSUP;
|
||||
|
||||
// case:
|
||||
// POSIX_EPFNOSUPPORT:
|
||||
// return EPFNOSUPPORT; //?
|
||||
#ifndef _WIN32
|
||||
case POSIX_EPFNOSUPPORT:
|
||||
return EPFNOSUPPORT;
|
||||
#endif
|
||||
|
||||
case:
|
||||
POSIX_EAFNOSUPPORT:
|
||||
case POSIX_EAFNOSUPPORT:
|
||||
return EAFNOSUPPORT;
|
||||
case:
|
||||
POSIX_EADDRINUSE:
|
||||
case POSIX_EADDRINUSE:
|
||||
return EADDRINUSE;
|
||||
case:
|
||||
POSIX_EADDRNOTAVAIL:
|
||||
case POSIX_EADDRNOTAVAIL:
|
||||
return EADDRNOTAVAIL;
|
||||
case:
|
||||
POSIX_ENETDOWN:
|
||||
case POSIX_ENETDOWN:
|
||||
return ENETDOWN;
|
||||
case:
|
||||
POSIX_ENETUNREACH:
|
||||
case POSIX_ENETUNREACH:
|
||||
return ENETUNREACH;
|
||||
case:
|
||||
POSIX_ENETRESET:
|
||||
case POSIX_ENETRESET:
|
||||
return ENETRESET;
|
||||
case:
|
||||
POSIX_ECONNABORTED:
|
||||
case POSIX_ECONNABORTED:
|
||||
return ECONNABORTED;
|
||||
case:
|
||||
POSIX_ECONNRESET:
|
||||
case POSIX_ECONNRESET:
|
||||
return ECONNRESET;
|
||||
case:
|
||||
POSIX_ENOBUFS:
|
||||
case POSIX_ENOBUFS:
|
||||
return ENOBUFS;
|
||||
case:
|
||||
POSIX_EISCONN:
|
||||
case POSIX_EISCONN:
|
||||
return EISCONN;
|
||||
case:
|
||||
POSIX_ENOTCONN:
|
||||
case POSIX_ENOTCONN:
|
||||
return ENOTCONN;
|
||||
|
||||
// case:
|
||||
// POSIX_ESHUTDOWN:
|
||||
// return ESHUTDOWN; // ?
|
||||
#ifndef _WIN32
|
||||
case POSIX_ESHUTDOWN:
|
||||
return ESHUTDOWN;
|
||||
case POSIX_ETOOMANYREFS:
|
||||
return ETOOMANYREFS;
|
||||
#endif
|
||||
|
||||
// case:
|
||||
// POSIX_ETOOMANYREFS:
|
||||
// return ETOOMANYREFS; // ?
|
||||
|
||||
case:
|
||||
POSIX_ETIMEDOUT:
|
||||
case POSIX_ETIMEDOUT:
|
||||
return ETIMEDOUT;
|
||||
case:
|
||||
POSIX_ECONNREFUSED:
|
||||
case POSIX_ECONNREFUSED:
|
||||
return ECONNREFUSED;
|
||||
case:
|
||||
POSIX_ELOOP:
|
||||
case POSIX_ELOOP:
|
||||
return ELOOP;
|
||||
case:
|
||||
POSIX_ENAMETOOLONG:
|
||||
case POSIX_ENAMETOOLONG:
|
||||
return ENAMETOOLONG;
|
||||
|
||||
// case:
|
||||
// POSIX_EHOSTDOWN:
|
||||
// return EHOSTDOWN; // ?
|
||||
#ifndef _WIN32
|
||||
case POSIX_EHOSTDOWN:
|
||||
return EHOSTDOWN;
|
||||
#endif
|
||||
|
||||
case:
|
||||
POSIX_EHOSTUNREACH:
|
||||
case POSIX_EHOSTUNREACH:
|
||||
return EHOSTUNREACH;
|
||||
case:
|
||||
POSIX_ENOTEMPTY:
|
||||
case POSIX_ENOTEMPTY:
|
||||
return ENOTEMPTY;
|
||||
|
||||
// case:
|
||||
// POSIX_EPROCLIM:
|
||||
// return EPROCLIM;
|
||||
// case:
|
||||
// POSIX_EUSERS:
|
||||
// return EUSERS;
|
||||
// case:
|
||||
// POSIX_EDQUOT:
|
||||
// return EDQUOT;
|
||||
// case:
|
||||
// POSIX_ESTALE:
|
||||
// return ESTALE;
|
||||
// case:
|
||||
// POSIX_EREMOTE:
|
||||
// return EREMOTE;
|
||||
// case:
|
||||
// POSIX_EBADRPC:
|
||||
// return EBADRPC;
|
||||
// case:
|
||||
// POSIX_ERPCMISMATCH:
|
||||
// return ERPCMISMATCH;
|
||||
// case:
|
||||
// POSIX_EPROGUNAVAIL:
|
||||
// return EPROGUNAVAIL;
|
||||
// case:
|
||||
// POSIX_EPROGMISMATCH:
|
||||
// return EPROGMISMATCH;
|
||||
// case:
|
||||
// POSIX_EPROCUNAVAIL:
|
||||
// return EPROCUNAVAIL;
|
||||
#ifndef _WIN32
|
||||
case POSIX_EPROCLIM:
|
||||
return EPROCLIM;
|
||||
case POSIX_EUSERS:
|
||||
return EUSERS;
|
||||
case POSIX_EDQUOT:
|
||||
return EDQUOT;
|
||||
case POSIX_ESTALE:
|
||||
return ESTALE;
|
||||
case POSIX_EREMOTE:
|
||||
return EREMOTE;
|
||||
case POSIX_EBADRPC:
|
||||
return EBADRPC;
|
||||
case POSIX_ERPCMISMATCH:
|
||||
return ERPCMISMATCH;
|
||||
case POSIX_EPROGUNAVAIL:
|
||||
return EPROGUNAVAIL;
|
||||
case POSIX_EPROGMISMATCH:
|
||||
return EPROGMISMATCH;
|
||||
case POSIX_EPROCUNAVAIL:
|
||||
return EPROCUNAVAIL;
|
||||
#endif
|
||||
|
||||
case:
|
||||
POSIX_ENOLCK:
|
||||
case POSIX_ENOLCK:
|
||||
return ENOLCK;
|
||||
case:
|
||||
POSIX_ENOSYS:
|
||||
case POSIX_ENOSYS:
|
||||
return ENOSYS;
|
||||
|
||||
// case:
|
||||
// POSIX_EFTYPE:
|
||||
// return EFTYPE;
|
||||
// case:
|
||||
// POSIX_EAUTH:
|
||||
// return EAUTH;
|
||||
// case:
|
||||
// POSIX_ENEEDAUTH:
|
||||
// return ENEEDAUTH;
|
||||
#ifndef _WIN32
|
||||
case POSIX_EFTYPE:
|
||||
return EFTYPE;
|
||||
case POSIX_EAUTH:
|
||||
return EAUTH;
|
||||
case POSIX_ENEEDAUTH:
|
||||
return ENEEDAUTH;
|
||||
#endif
|
||||
|
||||
case:
|
||||
POSIX_EIDRM:
|
||||
case POSIX_EIDRM:
|
||||
return EIDRM;
|
||||
case:
|
||||
POSIX_ENOMSG:
|
||||
case POSIX_ENOMSG:
|
||||
return ENOMSG;
|
||||
case:
|
||||
POSIX_EOVERFLOW:
|
||||
case POSIX_EOVERFLOW:
|
||||
return EOVERFLOW;
|
||||
case:
|
||||
POSIX_ECANCELED:
|
||||
case POSIX_ECANCELED:
|
||||
return ECANCELED;
|
||||
case:
|
||||
POSIX_EILSEQ:
|
||||
case POSIX_EILSEQ:
|
||||
return EILSEQ;
|
||||
|
||||
// case:
|
||||
// POSIX_ENOATTR:
|
||||
// return ENOATTR;
|
||||
// case:
|
||||
// POSIX_EDOOFUS:
|
||||
// return EDOOFUS;
|
||||
#ifndef _WIN32
|
||||
case POSIX_ENOATTR:
|
||||
return ENOATTR;
|
||||
case POSIX_EDOOFUS:
|
||||
return EDOOFUS;
|
||||
#endif
|
||||
|
||||
case:
|
||||
POSIX_EBADMSG:
|
||||
case POSIX_EBADMSG:
|
||||
return EBADMSG;
|
||||
|
||||
// case:
|
||||
// POSIX_EMULTIHOP:
|
||||
// return EMULTIHOP;
|
||||
#ifndef _WIN32
|
||||
case POSIX_EMULTIHOP:
|
||||
return EMULTIHOP;
|
||||
#endif
|
||||
|
||||
case:
|
||||
POSIX_ENOLINK:
|
||||
case POSIX_ENOLINK:
|
||||
return ENOLINK;
|
||||
case:
|
||||
POSIX_EPROTO:
|
||||
case POSIX_EPROTO:
|
||||
return EPROTO;
|
||||
|
||||
// case:
|
||||
// POSIX_ENOTCAPABLE:
|
||||
// return ENOTCAPABLE;
|
||||
// case:
|
||||
// POSIX_ECAPMODE:
|
||||
// return ECAPMODE;
|
||||
// case:
|
||||
// POSIX_ENOBLK:
|
||||
// return ENOBLK;
|
||||
// case:
|
||||
// POSIX_EICV:
|
||||
// return EICV;
|
||||
// case:
|
||||
// POSIX_ENOPLAYGOENT:
|
||||
// return ENOPLAYGOENT;
|
||||
// case:
|
||||
// POSIX_EREVOKE:
|
||||
// return EREVOKE;
|
||||
// case:
|
||||
// POSIX_ESDKVERSION:
|
||||
// return ESDKVERSION;
|
||||
// case:
|
||||
// POSIX_ESTART:
|
||||
// return ESTART;
|
||||
// case:
|
||||
// POSIX_ESTOP:
|
||||
// return ESTOP;
|
||||
// case:
|
||||
// POSIX_EINVALID2MB:
|
||||
// return EINVALID2MB;
|
||||
// case:
|
||||
// POSIX_ELAST:
|
||||
// return ELAST;
|
||||
// case:
|
||||
// POSIX_EADHOC:
|
||||
// return EADHOC;
|
||||
// case:
|
||||
// POSIX_EINACTIVEDISABLED:
|
||||
// return EINACTIVEDISABLED;
|
||||
// case:
|
||||
// POSIX_ENETNODATA:
|
||||
// return ENETNODATA;
|
||||
// case:
|
||||
// POSIX_ENETDESC:
|
||||
// return ENETDESC;
|
||||
// case:
|
||||
// POSIX_ENETDESCTIMEDOUT:
|
||||
// return ENETDESCTIMEDOUT;
|
||||
// case:
|
||||
// POSIX_ENETINTR:
|
||||
// return ENETINTR;
|
||||
// case:
|
||||
// POSIX_ERETURN:
|
||||
// return ERETURN;
|
||||
// case:
|
||||
// POSIX_EFPOS:
|
||||
// return EFPOS;
|
||||
#ifndef _WIN32
|
||||
case POSIX_ENOTCAPABLE:
|
||||
return ENOTCAPABLE;
|
||||
case POSIX_ECAPMODE:
|
||||
return ECAPMODE;
|
||||
case POSIX_ENOBLK:
|
||||
return ENOBLK;
|
||||
case POSIX_EICV:
|
||||
return EICV;
|
||||
case POSIX_ENOPLAYGOENT:
|
||||
return ENOPLAYGOENT;
|
||||
case POSIX_EREVOKE:
|
||||
return EREVOKE;
|
||||
case POSIX_ESDKVERSION:
|
||||
return ESDKVERSION;
|
||||
case POSIX_ESTART:
|
||||
return ESTART;
|
||||
case POSIX_ESTOP:
|
||||
return ESTOP;
|
||||
case POSIX_EINVALID2MB:
|
||||
return EINVALID2MB;
|
||||
case POSIX_ELAST:
|
||||
return ELAST;
|
||||
case POSIX_EADHOC:
|
||||
return EADHOC;
|
||||
case POSIX_EINACTIVEDISABLED:
|
||||
return EINACTIVEDISABLED;
|
||||
case POSIX_ENETNODATA:
|
||||
return ENETNODATA;
|
||||
case POSIX_ENETDESC:
|
||||
return ENETDESC;
|
||||
case POSIX_ENETDESCTIMEDOUT:
|
||||
return ENETDESCTIMEDOUT;
|
||||
case POSIX_ENETINTR:
|
||||
return ENETINTR;
|
||||
case POSIX_ERETURN:
|
||||
return ERETURN;
|
||||
case POSIX_EFPOS:
|
||||
return EFPOS;
|
||||
#endif
|
||||
|
||||
case:
|
||||
POSIX_ENODATA:
|
||||
case POSIX_ENODATA:
|
||||
return ENODATA;
|
||||
case:
|
||||
POSIX_ENOSR:
|
||||
case POSIX_ENOSR:
|
||||
return ENOSR;
|
||||
case:
|
||||
POSIX_ENOSTR:
|
||||
case POSIX_ENOSTR:
|
||||
return ENOSTR;
|
||||
case:
|
||||
POSIX_ENOTRECOVERABLE:
|
||||
case POSIX_ENOTRECOVERABLE:
|
||||
return ENOTRECOVERABLE;
|
||||
case:
|
||||
POSIX_EOTHER:
|
||||
case POSIX_EOTHER:
|
||||
return EOTHER;
|
||||
case:
|
||||
POSIX_EOWNERDEAD:
|
||||
case POSIX_EOWNERDEAD:
|
||||
return EOWNERDEAD;
|
||||
case:
|
||||
POSIX_ETIME:
|
||||
case POSIX_ETIME:
|
||||
return ETIME;
|
||||
}
|
||||
}
|
||||
@ -25,37 +25,43 @@ namespace HostIODriver {
|
||||
s32 HostIO_POSIX::Open(const fs::path& path, s32 flags, u16 mode) {
|
||||
errno = 0;
|
||||
s32 status = open(path.c_str(), ToPOSIXOpenFlags(flags), mode);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::Creat(const fs::path& path, u16 mode) {
|
||||
errno = 0;
|
||||
s32 status = creat(path.c_str(), mode);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::Close(const s32 fd) {
|
||||
errno = 0;
|
||||
s32 status = close(fd);
|
||||
return 0 == status ? status : -errno;
|
||||
return 0 == status ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::Link(const fs::path& src, const fs::path& dst) {
|
||||
errno = 0;
|
||||
s32 status = link(src.c_str(), dst.c_str());
|
||||
return 0 == status ? status : -errno;
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::Unlink(const fs::path& path) {
|
||||
errno = 0;
|
||||
s32 status = unlink(path.c_str());
|
||||
return 0 == status ? status : -errno;
|
||||
return 0 == status ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::LinkSymbolic(const fs::path& src, const fs::path& dst) {
|
||||
errno = 0;
|
||||
s32 status = symlink(src.c_str(), dst.c_str());
|
||||
return 0 == status ? status : -errno;
|
||||
return 0 == status ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::Unlink(const fs::path& path) {
|
||||
errno = 0;
|
||||
s32 status = unlink(path.c_str());
|
||||
return 0 == status ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::Remove(const fs::path& path) {
|
||||
errno = 0;
|
||||
s32 status = remove(path.c_str());
|
||||
return 0 == status ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::Flush(const s32 fd) {
|
||||
@ -66,13 +72,13 @@ s32 HostIO_POSIX::Flush(const s32 fd) {
|
||||
s32 HostIO_POSIX::FSync(const s32 fd) {
|
||||
errno = 0;
|
||||
s32 status = fsync(fd);
|
||||
return 0 == status ? status : -errno;
|
||||
return 0 == status ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_POSIX::LSeek(const s32 fd, s64 offset, s32 whence) {
|
||||
errno = 0;
|
||||
s32 status = lseek(fd, offset, ToPOSIXSeekOrigin(whence));
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_POSIX::Tell(const s32 fd) {
|
||||
@ -82,25 +88,25 @@ s64 HostIO_POSIX::Tell(const s32 fd) {
|
||||
s32 HostIO_POSIX::Truncate(const fs::path& path, u64 size) {
|
||||
errno = 0;
|
||||
s32 status = truncate(path.c_str(), size);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::FTruncate(const s32 fd, u64 size) {
|
||||
errno = 0;
|
||||
s32 status = ftruncate(fd, size);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_POSIX::Read(const s32 fd, void* buf, u64 count) {
|
||||
errno = 0;
|
||||
s32 status = read(fd, buf, count);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_POSIX::PRead(const s32 fd, void* buf, u64 count, s64 offset) {
|
||||
errno = 0;
|
||||
s32 status = pread(fd, buf, count, offset);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_POSIX::ReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt) {
|
||||
@ -132,13 +138,13 @@ s64 HostIO_POSIX::PReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt, s64 of
|
||||
s64 HostIO_POSIX::Write(const s32 fd, const void* buf, u64 count) {
|
||||
errno = 0;
|
||||
s32 status = write(fd, buf, count);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_POSIX::PWrite(const s32 fd, const void* buf, u64 count, s64 offset) {
|
||||
errno = 0;
|
||||
s32 status = pwrite(fd, buf, count, offset);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_POSIX::WriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt) {
|
||||
@ -170,13 +176,13 @@ s64 HostIO_POSIX::PWriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt,
|
||||
s32 HostIO_POSIX::MKDir(const fs::path& path, u16 mode) {
|
||||
errno = 0;
|
||||
s32 status = mkdir(path.c_str(), mode);
|
||||
return 0 == status ? status : -errno;
|
||||
return 0 == status ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::RMDir(const fs::path& path) {
|
||||
errno = 0;
|
||||
s32 status = rmdir(path.c_str());
|
||||
return 0 == status ? status : -errno;
|
||||
return 0 == status ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::Stat(const fs::path& path, OrbisKernelStat* statbuf) {
|
||||
@ -251,13 +257,21 @@ s32 HostIO_POSIX::FStat(const s32 fd, OrbisKernelStat* statbuf) {
|
||||
s32 HostIO_POSIX::Chmod(const fs::path& path, u16 mode) {
|
||||
errno = 0;
|
||||
s32 status = chmod(path.c_str(), mode);
|
||||
return 0 == status ? status : -errno;
|
||||
return 0 == status ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::FChmod(const s32 fd, u16 mode) {
|
||||
errno = 0;
|
||||
s32 status = fchmod(fd, mode);
|
||||
return 0 == status ? status : -errno;
|
||||
return 0 == status ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::Copy(const fs::path& src, const fs::path& dst, bool fail_if_exists) {
|
||||
return -unix2bsd(ENOSYS);
|
||||
}
|
||||
|
||||
s32 HostIO_POSIX::Move(const fs::path& src, const fs::path& dst, bool fail_if_exists) {
|
||||
return -unix2bsd(ENOSYS);
|
||||
}
|
||||
|
||||
// s32 HostIO_POSIX::GetDents(void* buf, u32 count, s64* basep) { return -POSIX_ENOSYS; }
|
||||
|
||||
@ -104,6 +104,17 @@ s32 HostIO_Virtual::Link(const fs::path& src, const fs::path& dst) {
|
||||
return part->link(src_node, dst_parent, dst_name);
|
||||
}
|
||||
|
||||
s32 HostIO_Virtual::LinkSymbolic(const fs::path& src, const fs::path& dst) {
|
||||
if (nullptr == this->res)
|
||||
return -POSIX_EINVAL;
|
||||
|
||||
symlink_ptr sym = Symlink::Create(src);
|
||||
// symlink counter is never increased
|
||||
sym->st.st_nlink = 1;
|
||||
|
||||
return this->res->mountpoint->touch(this->res->parent, dst.filename().string(), sym);
|
||||
}
|
||||
|
||||
s32 HostIO_Virtual::Unlink(const fs::path& path) {
|
||||
if (nullptr == this->res)
|
||||
return -POSIX_EINVAL;
|
||||
@ -118,15 +129,8 @@ s32 HostIO_Virtual::Unlink(const fs::path& path) {
|
||||
return part->unlink(parent, this->res->leaf);
|
||||
}
|
||||
|
||||
s32 HostIO_Virtual::LinkSymbolic(const fs::path& src, const fs::path& dst) {
|
||||
if (nullptr == this->res)
|
||||
return -POSIX_EINVAL;
|
||||
|
||||
symlink_ptr sym = Symlink::Create(src);
|
||||
// symlink counter is never increased
|
||||
sym->st.st_nlink = 1;
|
||||
|
||||
return this->res->mountpoint->touch(this->res->parent, dst.filename().string(), sym);
|
||||
s32 HostIO_Virtual::Remove(const fs::path& path) {
|
||||
return -POSIX_ENOSYS;
|
||||
}
|
||||
|
||||
s32 HostIO_Virtual::Flush(const s32 fd) {
|
||||
@ -387,8 +391,7 @@ s64 HostIO_Virtual::GetDents(const s32 fd, void* buf, u64 count, s64* basep) {
|
||||
// In most cases it's 512 bytes
|
||||
// Not sure yet if other partitions share the same size
|
||||
if (count < 512) {
|
||||
LOG_ERROR(Kernel_Fs,
|
||||
"(Partial STUB) check for block size associated. Read size must be greater");
|
||||
LOG_ERROR(Kernel_Fs, "Read size must be greater than sector size (512B)");
|
||||
return -POSIX_EINVAL;
|
||||
}
|
||||
|
||||
@ -400,4 +403,12 @@ s64 HostIO_Virtual::GetDents(const s32 fd, void* buf, u64 count, s64* basep) {
|
||||
return br;
|
||||
}
|
||||
|
||||
s32 HostIO_Virtual::Copy(const fs::path& src, const fs::path& dst, bool fail_if_exists) {
|
||||
return POSIX_ENOSYS;
|
||||
}
|
||||
|
||||
s32 HostIO_Virtual::Move(const fs::path& src, const fs::path& dst, bool fail_if_exists) {
|
||||
return POSIX_ENOSYS;
|
||||
}
|
||||
|
||||
} // namespace HostIODriver
|
||||
|
||||
31
src/core/file_sys/hostio/src/host_io_win2bsd.h
Normal file
31
src/core/file_sys/hostio/src/host_io_win2bsd.h
Normal file
@ -0,0 +1,31 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <winerror.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/libraries/kernel/posix_error.h"
|
||||
|
||||
// Convert linux/unix errno to FreeBSD errno
|
||||
// They differ in higher errno numbers, which may throw Orbis off quite a bit
|
||||
|
||||
s32 win2bsd(s32 id) {
|
||||
switch (id) {
|
||||
default:
|
||||
return EIO;
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
return ENOENT;
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
return EEXIST;
|
||||
case ERROR_ACCESS_DENIED:
|
||||
return EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -2,10 +2,14 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <io.h>
|
||||
#include <winerror.h>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "src/core/file_sys/hostio/host_io_win32.h"
|
||||
|
||||
#include "host_io_linux2bsd.h"
|
||||
#include "host_io_win2bsd.h"
|
||||
|
||||
namespace HostIODriver {
|
||||
|
||||
HostIO_Win32::HostIO_Win32() = default;
|
||||
@ -14,39 +18,55 @@ 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);
|
||||
return status >= 0 ? status : -errno;
|
||||
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);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_Win32::Close(const s32 fd) {
|
||||
errno = 0;
|
||||
s32 status = _close(fd);
|
||||
return 0 == status ? 0 : -errno;
|
||||
return 0 == status ? 0 : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
// s32 HostIO_Win32::Link(const fs::path& src, const fs::path& dst) {
|
||||
// // errno = 0;
|
||||
// // s32 status = link(src.c_str(), dst.c_str());
|
||||
// // return 0 == status ? 0 : -errno;
|
||||
// }
|
||||
|
||||
// s32 HostIO_Win32::Unlink(const fs::path& path) {
|
||||
// // errno = 0;
|
||||
// // s32 status = unlink(path.c_str());
|
||||
// // return 0 == status ? 0 : -errno;
|
||||
// }
|
||||
s32 HostIO_Win32::Link(const fs::path& src, const fs::path& dst) {
|
||||
errno = 0;
|
||||
s32 status = CreateHardLinkW(dst.c_str(), src.c_str(), nullptr);
|
||||
return 0 == status ? 0 : -win2bsd(GetLastError());
|
||||
}
|
||||
|
||||
// s32 HostIO_Win32::LinkSymbolic(const fs::path& src, const fs:
|
||||
// // errno = 0;
|
||||
// // s32 status = symlink(src.c_str(), dst.c_str());
|
||||
// // return 0 == status ? 0 : -errno;
|
||||
// // return 0 == status ? 0 :-unix2bsd(errno);
|
||||
// }
|
||||
|
||||
s32 HostIO_Win32::Unlink(const fs::path& path) {
|
||||
errno = 0;
|
||||
s32 status = DeleteFileW(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)
|
||||
return 0;
|
||||
auto last_error = GetLastError();
|
||||
// no idea if these are correlated (yet)
|
||||
LOG_CRITICAL(Kernel_Fs, "XDXDXDXD {} vs {}", errno, last_error);
|
||||
|
||||
// existence is found with both
|
||||
if (last_error == ERROR_FILE_NOT_FOUND || last_error == ERROR_PATH_NOT_FOUND)
|
||||
return false;
|
||||
|
||||
return RemoveDirectoryW(path.c_str());
|
||||
}
|
||||
|
||||
s32 HostIO_Win32::Flush(const s32 fd) {
|
||||
errno = 0;
|
||||
return 0;
|
||||
@ -55,13 +75,13 @@ s32 HostIO_Win32::Flush(const s32 fd) {
|
||||
s32 HostIO_Win32::FSync(const s32 fd) {
|
||||
errno = 0;
|
||||
s32 status = _commit(fd);
|
||||
return 0 == status ? 0 : -errno;
|
||||
return 0 == status ? 0 : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_Win32::LSeek(const s32 fd, s64 offset, s32 whence) {
|
||||
errno = 0;
|
||||
s32 status = _lseeki64(fd, offset, ToWIN32SeekOrigin(whence));
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_Win32::Tell(const s32 fd) {
|
||||
@ -72,35 +92,35 @@ int HostIO_Win32::Truncate(const fs::path& path, u64 size) {
|
||||
errno = 0;
|
||||
s32 fd = _wopen(path.c_str(), _O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
return -unix2bsd(errno);
|
||||
s32 status = _chsize_s(fd, size);
|
||||
_close(fd);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
int HostIO_Win32::FTruncate(const s32 fd, u64 size) {
|
||||
errno = 0;
|
||||
s32 status = _chsize_s(fd, size);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_Win32::Read(const s32 fd, void* buf, u64 count) {
|
||||
errno = 0;
|
||||
s32 status = _read(fd, buf, count);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_Win32::PRead(const s32 fd, void* buf, u64 count, s64 offset) {
|
||||
errno = 0;
|
||||
s64 bak = LSeek(fd, 0, SeekOrigin::CURRENT);
|
||||
if (bak < 0)
|
||||
return -errno;
|
||||
return -unix2bsd(errno);
|
||||
LSeek(fd, offset, SeekOrigin::ORIGIN);
|
||||
|
||||
s32 status = _read(fd, buf, count);
|
||||
|
||||
LSeek(fd, bak, SeekOrigin::ORIGIN);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_Win32::ReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt) {
|
||||
@ -113,20 +133,20 @@ s64 HostIO_Win32::PReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt, s64 of
|
||||
s64 HostIO_Win32::Write(const s32 fd, const void* buf, u64 count) {
|
||||
errno = 0;
|
||||
s32 status = _write(fd, buf, count);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_Win32::PWrite(const s32 fd, const void* buf, u64 count, s64 offset) {
|
||||
errno = 0;
|
||||
s64 bak = LSeek(fd, 0, SeekOrigin::CURRENT);
|
||||
if (bak < 0)
|
||||
return -errno;
|
||||
return -unix2bsd(errno);
|
||||
LSeek(fd, offset, SeekOrigin::ORIGIN);
|
||||
|
||||
s32 status = _write(fd, buf, count);
|
||||
|
||||
LSeek(fd, bak, SeekOrigin::ORIGIN);
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s64 HostIO_Win32::WriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt) {
|
||||
@ -139,13 +159,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());
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
s32 HostIO_Win32::RMDir(const fs::path& path) {
|
||||
errno = 0;
|
||||
s32 status = _wrmdir(path.c_str());
|
||||
return status >= 0 ? status : -errno;
|
||||
return status >= 0 ? status : -unix2bsd(errno);
|
||||
}
|
||||
|
||||
// s32 HostIO_Win32::Stat(const fs::path& path, Libraries::Kernel::OrbisKernelStat* statbuf) {}
|
||||
@ -154,4 +174,15 @@ s32 HostIO_Win32::RMDir(const fs::path& path) {
|
||||
// s32 HostIO_Win32::Chmod(const fs::path& path, u16 mode) {}
|
||||
// s32 HostIO_Win32::FChmod(const s32 fd, u16 mode) {}
|
||||
|
||||
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);
|
||||
return status > 0 ? status : -unix2bsd(GetLastError());
|
||||
}
|
||||
|
||||
s32 HostIO_Win32::Move(const fs::path& src, const fs::path& dst, bool fail_if_exists) {
|
||||
errno = 0;
|
||||
return -unix2bsd(ENOSYS);
|
||||
}
|
||||
|
||||
} // namespace HostIODriver
|
||||
@ -66,9 +66,12 @@ private:
|
||||
s32 Open(const fs::path& path, int flags, u16 mode = 0755) override;
|
||||
s32 Creat(const fs::path& path, u16 mode = 0755) override;
|
||||
s32 Close(const s32 fd) override;
|
||||
s32 LinkSymbolic(const fs::path& src, const fs::path& dst) override;
|
||||
|
||||
s32 Link(const fs::path& src, const fs::path& dst) override;
|
||||
s32 LinkSymbolic(const fs::path& src, const fs::path& dst) override;
|
||||
s32 Unlink(const fs::path& path) override;
|
||||
s32 Remove(const fs::path& path) override;
|
||||
|
||||
s32 Flush(const s32 fd) override;
|
||||
s32 FSync(const s32 fd) override;
|
||||
s32 Truncate(const fs::path& path, u64 size) override;
|
||||
@ -99,6 +102,9 @@ private:
|
||||
s32 FChmod(const s32 fd, u16 mode) override;
|
||||
|
||||
s64 GetDents(const s32 fd, void* buf, u64 count, s64* basep) override;
|
||||
|
||||
s32 Copy(const fs::path& src, const fs::path& dst, bool fail_if_exists) override;
|
||||
s32 Move(const fs::path& src, const fs::path& dst, bool fail_if_exists) override;
|
||||
};
|
||||
|
||||
public:
|
||||
@ -211,23 +217,11 @@ public:
|
||||
fs::path AbsolutePath(const fs::path& path, std::error_code& ec) noexcept {
|
||||
return "";
|
||||
};
|
||||
bool Remove(const fs::path& path) {
|
||||
return -POSIX_EINVAL;
|
||||
};
|
||||
bool Remove(const fs::path& path, std::error_code& ec) noexcept {
|
||||
return -POSIX_EINVAL;
|
||||
};
|
||||
uint64_t RemoveAll(const fs::path& path) = delete;
|
||||
uint64_t RemoveAll(const fs::path& path, std::error_code& ec) noexcept = delete;
|
||||
uint64_t CurrentPath(const fs::path& path) = delete;
|
||||
uint64_t CurrentPath(const fs::path& path, std::error_code& ec) noexcept = delete;
|
||||
|
||||
bool Copy(const fs::path& from, const fs::path& to) = delete;
|
||||
bool Copy(const fs::path& from, const fs::path& to, std::error_code& ec) noexcept = delete;
|
||||
bool Copy(const fs::path& from, const fs::path& to,
|
||||
std::filesystem::copy_options options) = delete;
|
||||
bool Copy(const fs::path& from, const fs::path& to, std::filesystem::copy_options options,
|
||||
std::error_code& ec) noexcept = delete;
|
||||
// uint64_t RemoveAll(const fs::path& path) = delete;
|
||||
// uint64_t RemoveAll(const fs::path& path, std::error_code& ec) noexcept = delete;
|
||||
// uint64_t CurrentPath(const fs::path& path) = delete;
|
||||
// uint64_t CurrentPath(const fs::path& path, std::error_code& ec) noexcept = delete;
|
||||
|
||||
// 0777 to mimic default C++ mode (std::filesystem::perms::all)
|
||||
bool CreateDirectory(const fs::path& path, int mode = 0777) {
|
||||
|
||||
@ -38,6 +38,13 @@ public:
|
||||
|
||||
virtual ~Inode() = default;
|
||||
|
||||
inode_ptr Clone() const {
|
||||
auto _out = std::make_shared<Inode>(*this);
|
||||
_out->fileno = -1;
|
||||
_out->st.st_nlink = 0;
|
||||
return _out;
|
||||
}
|
||||
|
||||
virtual s32 ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
return -POSIX_ENOTTY;
|
||||
}
|
||||
|
||||
@ -19,6 +19,13 @@ public:
|
||||
return std::make_shared<Device>();
|
||||
}
|
||||
|
||||
dev_ptr Clone() const {
|
||||
auto _out = std::make_shared<Device>(*this);
|
||||
_out->fileno = -1;
|
||||
_out->st.st_nlink = 0;
|
||||
return _out;
|
||||
}
|
||||
|
||||
virtual s64 read(void* buf, u64 count);
|
||||
virtual s64 write(const void* buf, u64 count);
|
||||
|
||||
|
||||
@ -56,6 +56,13 @@ public:
|
||||
return std::make_shared<QuasiDirectory>();
|
||||
}
|
||||
|
||||
dir_ptr Clone() const {
|
||||
auto _out = std::make_shared<QuasiDirectory>(*this);
|
||||
_out->fileno = -1;
|
||||
_out->st.st_nlink = 0;
|
||||
return _out;
|
||||
}
|
||||
|
||||
//
|
||||
// Inode overrides
|
||||
//
|
||||
|
||||
@ -44,6 +44,13 @@ public:
|
||||
return std::make_shared<DirectoryPFS>();
|
||||
}
|
||||
|
||||
dir_ptr Clone() const {
|
||||
auto _out = std::make_shared<DirectoryPFS>(*this);
|
||||
_out->fileno = -1;
|
||||
_out->st.st_nlink = 0;
|
||||
return _out;
|
||||
}
|
||||
|
||||
s64 pread(void* buf, u64 count, s64 offset) override;
|
||||
s64 lseek(s64 current, s64 offset, s32 whence) override;
|
||||
|
||||
|
||||
@ -22,6 +22,13 @@ public:
|
||||
return std::make_shared<QuasiFile>();
|
||||
}
|
||||
|
||||
file_ptr Clone() const {
|
||||
auto _out = std::make_shared<QuasiFile>(*this);
|
||||
_out->fileno = -1;
|
||||
_out->st.st_nlink = 0;
|
||||
return _out;
|
||||
}
|
||||
|
||||
s64 pread(void* buf, size_t count, s64 offset) override;
|
||||
s64 pwrite(const void* buf, size_t count, s64 offset) override;
|
||||
|
||||
|
||||
@ -20,9 +20,13 @@ public:
|
||||
return std::make_shared<VirtualFile>();
|
||||
}
|
||||
|
||||
//
|
||||
// Working functions
|
||||
//
|
||||
file_ptr Clone() const {
|
||||
auto _out = std::make_shared<VirtualFile>(*this);
|
||||
_out->fileno = -1;
|
||||
_out->st.st_nlink = 0;
|
||||
return _out;
|
||||
}
|
||||
|
||||
s64 pread(void* buf, size_t count, s64 offset) override;
|
||||
s64 pwrite(const void* buf, size_t count, s64 offset) override;
|
||||
s32 ftruncate(s64 length) override;
|
||||
|
||||
@ -18,6 +18,13 @@ public:
|
||||
static socket_ptr Create() {
|
||||
return std::make_shared<Socket>();
|
||||
}
|
||||
|
||||
socket_ptr Clone() const {
|
||||
auto _out = std::make_shared<Socket>(*this);
|
||||
_out->fileno = -1;
|
||||
_out->st.st_nlink = 0;
|
||||
return _out;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace QuasiFS
|
||||
@ -18,6 +18,13 @@ public:
|
||||
return std::make_shared<Symlink>(target);
|
||||
}
|
||||
|
||||
symlink_ptr Clone() const {
|
||||
auto _out = std::make_shared<Symlink>(*this);
|
||||
_out->fileno = -1;
|
||||
_out->st.st_nlink = 0;
|
||||
return _out;
|
||||
}
|
||||
|
||||
// symlinked path
|
||||
fs::path follow(void);
|
||||
};
|
||||
|
||||
@ -134,14 +134,19 @@ s32 QFS::OperationImpl::Close(s32 fd) {
|
||||
LOG_ERROR(Kernel_Fs, "Closing std stream, this will have consequences fd={}", fd);
|
||||
|
||||
// if it fails, it fails
|
||||
bool host_used = false;
|
||||
int hio_status = 0;
|
||||
if (handle->host_fd >= 0)
|
||||
if (handle->host_fd >= 0) {
|
||||
hio_status = qfs.hio_driver.Close(handle->host_fd);
|
||||
host_used = true;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(c_mutex);
|
||||
// no further action is required, this is pro-forma
|
||||
qfs.vio_driver.SetCtx(nullptr, host_used, handle);
|
||||
qfs.vio_driver.Close(fd);
|
||||
qfs.vio_driver.ClearCtx();
|
||||
}
|
||||
|
||||
// if it's the last entry, remove it to avoid blowing up fd table
|
||||
@ -155,6 +160,68 @@ s32 QFS::OperationImpl::Close(s32 fd) {
|
||||
return hio_status;
|
||||
}
|
||||
|
||||
s32 QFS::OperationImpl::Link(const fs::path& src, const fs::path& dst) {
|
||||
Resolved src_res;
|
||||
Resolved dst_res;
|
||||
int status_what = qfs.Resolve(src, src_res);
|
||||
int status_where = qfs.Resolve(dst, dst_res);
|
||||
|
||||
if (0 != status_what)
|
||||
return status_what;
|
||||
if (0 == status_where)
|
||||
return -POSIX_EEXIST;
|
||||
|
||||
// cross-partition linking is not supported
|
||||
if (src_res.mountpoint != dst_res.mountpoint)
|
||||
return -POSIX_EXDEV;
|
||||
|
||||
partition_ptr src_part = src_res.mountpoint;
|
||||
partition_ptr dst_part = dst_res.mountpoint;
|
||||
|
||||
if (src_part != dst_part) {
|
||||
LOG_ERROR(Kernel_Fs, "Hard links can only be created within one partition");
|
||||
// I think this is the right error
|
||||
return -POSIX_ENOSYS;
|
||||
}
|
||||
|
||||
if (qfs.IsPartitionRO(dst_part))
|
||||
return -POSIX_EROFS;
|
||||
|
||||
bool host_used = false;
|
||||
int hio_status = 0;
|
||||
int vio_status = 0;
|
||||
|
||||
if (dst_part->IsHostMounted()) {
|
||||
fs::path host_path_src{};
|
||||
fs::path host_path_dst{};
|
||||
|
||||
if (int hostpath_status = src_part->GetHostPath(host_path_src, src_res.local_path);
|
||||
hostpath_status != 0)
|
||||
return hostpath_status;
|
||||
if (int hostpath_status = dst_part->GetHostPath(host_path_dst, dst_res.local_path);
|
||||
hostpath_status != 0)
|
||||
return hostpath_status;
|
||||
|
||||
if (hio_status = qfs.hio_driver.Link(host_path_src, host_path_dst); hio_status < 0)
|
||||
// hosts operation must succeed in order to continue
|
||||
return hio_status;
|
||||
host_used = true;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(c_mutex);
|
||||
qfs.vio_driver.SetCtx(&src_res, host_used, nullptr);
|
||||
vio_status = qfs.vio_driver.Link(src_res.local_path, dst_res.local_path);
|
||||
qfs.vio_driver.ClearCtx();
|
||||
}
|
||||
|
||||
if (host_used && (hio_status != vio_status))
|
||||
LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status,
|
||||
vio_status);
|
||||
|
||||
return vio_status;
|
||||
}
|
||||
|
||||
s32 QFS::OperationImpl::LinkSymbolic(const fs::path& src, const fs::path& dst) {
|
||||
Resolved src_res;
|
||||
Resolved dst_res;
|
||||
@ -221,68 +288,6 @@ s32 QFS::OperationImpl::LinkSymbolic(const fs::path& src, const fs::path& dst) {
|
||||
return vio_status;
|
||||
}
|
||||
|
||||
s32 QFS::OperationImpl::Link(const fs::path& src, const fs::path& dst) {
|
||||
Resolved src_res;
|
||||
Resolved dst_res;
|
||||
int status_what = qfs.Resolve(src, src_res);
|
||||
int status_where = qfs.Resolve(dst, dst_res);
|
||||
|
||||
if (0 != status_what)
|
||||
return status_what;
|
||||
if (0 == status_where)
|
||||
return -POSIX_EEXIST;
|
||||
|
||||
// cross-partition linking is not supported
|
||||
if (src_res.mountpoint != dst_res.mountpoint)
|
||||
return -POSIX_EXDEV;
|
||||
|
||||
partition_ptr src_part = src_res.mountpoint;
|
||||
partition_ptr dst_part = dst_res.mountpoint;
|
||||
|
||||
if (src_part != dst_part) {
|
||||
LOG_ERROR(Kernel_Fs, "Hard links can only be created within one partition");
|
||||
// I think this is the right error
|
||||
return -POSIX_ENOSYS;
|
||||
}
|
||||
|
||||
if (qfs.IsPartitionRO(dst_part))
|
||||
return -POSIX_EROFS;
|
||||
|
||||
bool host_used = false;
|
||||
int hio_status = 0;
|
||||
int vio_status = 0;
|
||||
|
||||
if (dst_part->IsHostMounted()) {
|
||||
fs::path host_path_src{};
|
||||
fs::path host_path_dst{};
|
||||
|
||||
if (int hostpath_status = src_part->GetHostPath(host_path_src, src_res.local_path);
|
||||
hostpath_status != 0)
|
||||
return hostpath_status;
|
||||
if (int hostpath_status = dst_part->GetHostPath(host_path_dst, dst_res.local_path);
|
||||
hostpath_status != 0)
|
||||
return hostpath_status;
|
||||
|
||||
if (hio_status = qfs.hio_driver.Link(host_path_src, host_path_dst); hio_status < 0)
|
||||
// hosts operation must succeed in order to continue
|
||||
return hio_status;
|
||||
host_used = true;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(c_mutex);
|
||||
qfs.vio_driver.SetCtx(&src_res, host_used, nullptr);
|
||||
vio_status = qfs.vio_driver.Link(src_res.local_path, dst_res.local_path);
|
||||
qfs.vio_driver.ClearCtx();
|
||||
}
|
||||
|
||||
if (host_used && (hio_status != vio_status))
|
||||
LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status,
|
||||
vio_status);
|
||||
|
||||
return vio_status;
|
||||
}
|
||||
|
||||
s32 QFS::OperationImpl::Unlink(const fs::path& path) {
|
||||
Resolved res;
|
||||
int resolve_status;
|
||||
@ -346,6 +351,10 @@ s32 QFS::OperationImpl::Unlink(const fs::path& path) {
|
||||
return vio_status;
|
||||
}
|
||||
|
||||
s32 QFS::OperationImpl::Remove(const fs::path& path) {
|
||||
return -POSIX_ENOSYS;
|
||||
}
|
||||
|
||||
s32 QFS::OperationImpl::Flush(const s32 fd) {
|
||||
if (fd < 0)
|
||||
return -POSIX_EBADF;
|
||||
@ -1022,4 +1031,12 @@ s64 QFS::OperationImpl::GetDents(const s32 fd, void* buf, u64 count, s64* basep)
|
||||
return vio_status;
|
||||
}
|
||||
|
||||
s32 QFS::OperationImpl::Copy(const fs::path& src, const fs::path& dst, bool fail_if_exists) {
|
||||
return -POSIX_ENOSYS;
|
||||
}
|
||||
|
||||
s32 QFS::OperationImpl::Move(const fs::path& src, const fs::path& dst, bool fail_if_exists) {
|
||||
return -POSIX_ENOSYS;
|
||||
}
|
||||
|
||||
} // namespace QuasiFS
|
||||
@ -1,11 +1,11 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/libraries/error_codes.h"
|
||||
|
||||
// Posix error codes
|
||||
// BSD error codes
|
||||
constexpr int POSIX_EPERM = 1;
|
||||
constexpr int POSIX_ENOENT = 2;
|
||||
constexpr int POSIX_ESRCH = 3;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user