feat(kernel): implement file metadata ops and address conversion
This commit is contained in:
parent
f881e021a8
commit
a4e755ccb1
|
|
@ -281,12 +281,12 @@ if(BUILD_TESTING)
|
|||
endif()
|
||||
add_executable(guest_filesystem_tests tests/GuestFilesystem.cpp)
|
||||
target_include_directories(guest_filesystem_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(guest_filesystem_tests PRIVATE libc)
|
||||
target_link_libraries(guest_filesystem_tests PRIVATE libkernel libc)
|
||||
configure_windows_unwind(guest_filesystem_tests)
|
||||
add_test(NAME guest_filesystem COMMAND guest_filesystem_tests)
|
||||
if(WIN32)
|
||||
set_tests_properties(guest_filesystem PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
|
||||
endif()
|
||||
add_executable(guest_directory_tests tests/GuestDirectory.cpp)
|
||||
target_include_directories(guest_directory_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/utime.h>
|
||||
static int NativeRmdir(const std::filesystem::path& path) {
|
||||
return ::_wrmdir(path.wstring().c_str());
|
||||
}
|
||||
|
|
@ -33,6 +34,11 @@ static int NativeChmod(const std::filesystem::path& path, int mode) {
|
|||
static int NativeFtruncate(int descriptor, std::int64_t length) {
|
||||
return static_cast<int>(::_chsize_s(descriptor, length));
|
||||
}
|
||||
static int NativeUtimes(const std::filesystem::path& path, const KernelTimeval* times) {
|
||||
if (times == nullptr) return ::_wutime(path.wstring().c_str(), nullptr);
|
||||
struct _utimbuf values{static_cast<time_t>(times[0].tv_sec), static_cast<time_t>(times[1].tv_sec)};
|
||||
return ::_wutime(path.wstring().c_str(), &values);
|
||||
}
|
||||
static int NativeFlock(int descriptor, int operation) {
|
||||
HANDLE handle = reinterpret_cast<HANDLE>(::_get_osfhandle(descriptor));
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
|
|
@ -79,6 +85,7 @@ static std::int64_t NativePwrite(int descriptor, const void* buf, std::size_t nb
|
|||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/time.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <vector>
|
||||
|
|
@ -94,6 +101,12 @@ static int NativeChmod(const std::filesystem::path& path, int mode) {
|
|||
static int NativeFtruncate(int descriptor, std::int64_t length) {
|
||||
return ::ftruncate(descriptor, static_cast<off_t>(length));
|
||||
}
|
||||
static int NativeUtimes(const std::filesystem::path& path, const KernelTimeval* times) {
|
||||
if (times == nullptr) return ::utimes(path.c_str(), nullptr);
|
||||
struct timeval values[2]{{static_cast<time_t>(times[0].tv_sec), static_cast<suseconds_t>(times[0].tv_usec)},
|
||||
{static_cast<time_t>(times[1].tv_sec), static_cast<suseconds_t>(times[1].tv_usec)}};
|
||||
return ::utimes(path.c_str(), values);
|
||||
}
|
||||
static int NativeFlock(int descriptor, int operation) {
|
||||
return ::flock(descriptor, operation);
|
||||
}
|
||||
|
|
@ -180,6 +193,10 @@ int APS5_VABI ftruncate_nid_postfix(int d, int64_t length) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceKernelFtruncate(int d, int64_t length) {
|
||||
return ftruncate_nid_postfix(d, length);
|
||||
}
|
||||
|
||||
int64_t APS5_VABI lseek_nid_postfix(int d, int64_t offset, int whence) {
|
||||
return static_cast<int64_t>(sceKernelLseek(d, offset, whence));
|
||||
}
|
||||
|
|
@ -423,23 +440,24 @@ int APS5_VABI rmdir_nid_postfix(const char* path) {
|
|||
extern "C" {
|
||||
|
||||
int APS5_VABI sceKernelChmod_nid_postfix(const char* path, std::uint16_t mode) {
|
||||
(void)path;
|
||||
(void)mode;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
return chmod_nid_postfix(path, mode);
|
||||
}
|
||||
|
||||
int APS5_VABI sceKernelTruncate_nid_postfix(const char* path, std::int64_t length) {
|
||||
(void)path;
|
||||
(void)length;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
if (path == nullptr) throw std::invalid_argument("sceKernelTruncate: path is null");
|
||||
if (length < 0) return SceErrorFromErrno(GUEST_EINVAL);
|
||||
const auto native = ResolvePath_nid_no_patch(path);
|
||||
std::error_code error;
|
||||
if (!std::filesystem::exists(native, error)) return SceErrorFromErrno(GUEST_ENOENT);
|
||||
std::filesystem::resize_file(native, static_cast<std::uintmax_t>(length), error);
|
||||
if (error) return SceErrorFromErrno(GUEST_EIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceKernelUtimes_nid_postfix(const char* path, const KernelTimeval* times) {
|
||||
(void)path;
|
||||
(void)times;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
if (path == nullptr) throw std::invalid_argument("sceKernelUtimes: path is null");
|
||||
const auto native = ResolvePath_nid_no_patch(path);
|
||||
if (NativeUtimes(native, times) != 0) return SceErrorFromErrno(errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@
|
|||
|
||||
extern "C" {
|
||||
|
||||
const char* APS5_VABI __inet_ntop_nid_postfix(int family, const void* source, char* destination, std::uint32_t capacity);
|
||||
int APS5_VABI __inet_pton_nid_postfix(int family, const char* text, void* destination);
|
||||
|
||||
int APS5_VABI accept_nid_postfix(int s, void* addr, uint32_t* addrlen) {
|
||||
(void)s;
|
||||
(void)addr;
|
||||
|
|
@ -54,20 +57,11 @@ int64_t APS5_VABI recv_nid_postfix(int s, void* buf, uint64_t len, int flags) {
|
|||
|
||||
|
||||
const char* APS5_VABI inet_ntop_nid_postfix(int af, const void* src, char* dst, uint32_t size) {
|
||||
(void)af;
|
||||
(void)src;
|
||||
(void)dst;
|
||||
(void)size;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return nullptr;
|
||||
return __inet_ntop_nid_postfix(af, src, dst, size);
|
||||
}
|
||||
|
||||
int APS5_VABI inet_pton_nid_postfix(int af, const char* src, void* dst) {
|
||||
(void)af;
|
||||
(void)src;
|
||||
(void)dst;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
return __inet_pton_nid_postfix(af, src, dst);
|
||||
}
|
||||
|
||||
int APS5_VABI select_nid_postfix(int nfds, void* readfds, void* writefds, void* exceptfds, const void* timeout) {
|
||||
|
|
|
|||
|
|
@ -5,11 +5,6 @@
|
|||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI rename_nid_postfix() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceCoredumpWriteUserData() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
|
|
@ -35,9 +30,4 @@ int APS5_VABI sceKernelAprResolveFilepathsWithPrefixToIdsForEach() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceKernelFtruncate() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,11 @@
|
|||
extern "C" {
|
||||
int APS5_VABI remove_nid_postfix(const char*);
|
||||
int APS5_VABI rename_nid_postfix(const char*, const char*);
|
||||
int APS5_VABI sceKernelChmod_nid_postfix(const char*, unsigned short);
|
||||
int APS5_VABI sceKernelFsync(int);
|
||||
int APS5_VABI sceKernelFtruncate(int, long long);
|
||||
int APS5_VABI sceKernelTruncate_nid_postfix(const char*, long long);
|
||||
int APS5_VABI sceKernelUtimes_nid_postfix(const char*, const void*);
|
||||
int* APS5_VABI __error_nid_postfix();
|
||||
}
|
||||
static void Check(bool value, int line) {
|
||||
|
|
@ -41,6 +46,27 @@ int main() {
|
|||
Require(remove_nid_postfix(file.string().c_str()) == 0);
|
||||
Require(!std::filesystem::exists(file));
|
||||
Require(remove_nid_postfix(file.string().c_str()) == -1 && *__error_nid_postfix() == 2);
|
||||
const auto sized = root / "sized.txt";
|
||||
{ std::ofstream stream(sized); stream << "0123456789abcdef"; }
|
||||
Require(sceKernelChmod_nid_postfix(sized.string().c_str(), 0600) == 0);
|
||||
Require(sceKernelTruncate_nid_postfix(sized.string().c_str(), 6) == 0);
|
||||
Require(std::filesystem::file_size(sized) == 6);
|
||||
{ std::ifstream stream(sized); std::string contents; std::getline(stream, contents);
|
||||
Require(contents == "012345"); }
|
||||
Require(sceKernelTruncate_nid_postfix((sized / "missing").string().c_str(), 6) == static_cast<int>(0x80020002u));
|
||||
Require(sceKernelUtimes_nid_postfix(sized.string().c_str(), nullptr) == 0);
|
||||
std::FILE* native = std::fopen(sized.string().c_str(), "r+b");
|
||||
Require(native != nullptr);
|
||||
#ifdef _WIN32
|
||||
const int descriptor = _fileno(native);
|
||||
#else
|
||||
const int descriptor = ::fileno(native);
|
||||
#endif
|
||||
Require(descriptor >= 0 && sceKernelFsync(descriptor) == 0);
|
||||
Require(sceKernelFtruncate(descriptor, 3) == 0);
|
||||
Require(std::fclose(native) == 0);
|
||||
Require(std::filesystem::file_size(sized) == 3);
|
||||
Require(remove_nid_postfix(sized.string().c_str()) == 0);
|
||||
Require(remove_nid_postfix(root.string().c_str()) == 0);
|
||||
Require(!std::filesystem::exists(root));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ int APS5_VABI ioctl_nid_postfix(int, std::uint64_t, void*);
|
|||
std::int64_t APS5_VABI sendto_nid_postfix(int, const void*, std::uint64_t, int, const void*, std::uint32_t);
|
||||
std::int64_t APS5_VABI recvfrom_nid_postfix(int, void*, std::uint64_t, int, void*, std::uint32_t*);
|
||||
int APS5_VABI close_nid_postfix(int);
|
||||
const char* APS5_VABI inet_ntop_nid_postfix(int, const void*, char*, std::uint32_t);
|
||||
int APS5_VABI inet_pton_nid_postfix(int, const char*, void*);
|
||||
int* APS5_VABI __error_nid_postfix();
|
||||
}
|
||||
static void Require(bool value) { if (!value) std::abort(); }
|
||||
|
|
@ -65,5 +67,17 @@ int main() {
|
|||
Require(close_nid_postfix(receiver) == -1 && *__error_nid_postfix() == 9);
|
||||
Require(ioctl_nid_postfix(receiver, 0x4004667f, &queued) == -1);
|
||||
Require(close_nid_postfix(sender) == 0);
|
||||
unsigned char parsed[16]{};
|
||||
Require(inet_pton_nid_postfix(2, "127.0.0.1", parsed) == 1);
|
||||
Require(parsed[0] == 127 && parsed[1] == 0 && parsed[2] == 0 && parsed[3] == 1);
|
||||
char text[64]{};
|
||||
Require(inet_ntop_nid_postfix(2, parsed, text, sizeof(text)) == text);
|
||||
Require(std::strcmp(text, "127.0.0.1") == 0);
|
||||
Require(inet_pton_nid_postfix(28, "::1", parsed) == 1);
|
||||
Require(inet_ntop_nid_postfix(28, parsed, text, sizeof(text)) == text);
|
||||
Require(std::strcmp(text, "::1") == 0);
|
||||
Require(inet_pton_nid_postfix(99, "127.0.0.1", parsed) == -1 && *__error_nid_postfix() == 47);
|
||||
Require(inet_pton_nid_postfix(2, "not-an-address", parsed) == 0);
|
||||
Require(inet_ntop_nid_postfix(2, parsed, text, 4) == nullptr && *__error_nid_postfix() == 28);
|
||||
Require(socket_nid_postfix(2, 1, 0) == -1); // unsupported TCP must not appear to work
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue