86 lines
3.5 KiB
C++
86 lines
3.5 KiB
C++
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <string>
|
|
#ifdef _WIN32
|
|
#ifndef NOMINMAX
|
|
#define NOMINMAX
|
|
#endif
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
extern "C" {
|
|
int APS5_VABI truncate_nid_postfix(const char*, std::int64_t);
|
|
int APS5_VABI sceKernelTruncate_nid_postfix(const char*, std::int64_t);
|
|
int* APS5_VABI __error_nid_postfix();
|
|
}
|
|
|
|
static void Require(bool value) { if (!value) std::abort(); }
|
|
|
|
constexpr int GuestEnoent = 2;
|
|
constexpr int GuestEacces = 13;
|
|
constexpr int GuestEfault = 14;
|
|
constexpr int GuestEisdir = 21;
|
|
constexpr int GuestEinval = 22;
|
|
constexpr int SceKernelErrorBase = static_cast<int>(0x80020000u);
|
|
|
|
static void RequireFailure(int result, int error) {
|
|
Require(result == -1);
|
|
Require(*__error_nid_postfix() == error);
|
|
}
|
|
|
|
static std::string Contents(const std::filesystem::path& file) {
|
|
std::ifstream stream(file, std::ios::binary);
|
|
return std::string(std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>());
|
|
}
|
|
|
|
int main() {
|
|
const auto name = "anyps5-truncate-test-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count());
|
|
const auto directory = std::filesystem::path(name);
|
|
Require(std::filesystem::create_directory(directory));
|
|
const auto file = directory / "sized.txt";
|
|
{ std::ofstream output(file, std::ios::binary); output << "0123456789abcdef"; }
|
|
const auto path = file.string();
|
|
|
|
Require(truncate_nid_postfix(path.c_str(), 6) == 0);
|
|
Require(std::filesystem::file_size(file) == 6);
|
|
Require(Contents(file) == "012345");
|
|
|
|
Require(truncate_nid_postfix(path.c_str(), 9) == 0);
|
|
Require(std::filesystem::file_size(file) == 9);
|
|
Require(Contents(file) == std::string("012345\0\0\0", 9));
|
|
|
|
Require(truncate_nid_postfix(path.c_str(), 0) == 0);
|
|
Require(std::filesystem::file_size(file) == 0);
|
|
|
|
RequireFailure(truncate_nid_postfix(path.c_str(), -1), GuestEinval);
|
|
Require(std::filesystem::file_size(file) == 0);
|
|
RequireFailure(truncate_nid_postfix((directory / "missing").string().c_str(), 0), GuestEnoent);
|
|
RequireFailure(truncate_nid_postfix("", 0), GuestEnoent);
|
|
RequireFailure(truncate_nid_postfix(nullptr, 0), GuestEfault);
|
|
RequireFailure(truncate_nid_postfix(directory.string().c_str(), 0), GuestEisdir);
|
|
Require(std::filesystem::is_directory(directory));
|
|
Require(sceKernelTruncate_nid_postfix(directory.string().c_str(), 0) == SceKernelErrorBase + GuestEisdir);
|
|
Require(sceKernelTruncate_nid_postfix(path.c_str(), -1) == SceKernelErrorBase + GuestEinval);
|
|
|
|
{ std::ofstream output(file, std::ios::binary); output << "locked"; }
|
|
#ifdef _WIN32
|
|
Require(SetFileAttributesW(file.c_str(), FILE_ATTRIBUTE_READONLY));
|
|
RequireFailure(truncate_nid_postfix(path.c_str(), 1), GuestEacces);
|
|
Require(sceKernelTruncate_nid_postfix(path.c_str(), 1) == SceKernelErrorBase + GuestEacces);
|
|
Require(SetFileAttributesW(file.c_str(), FILE_ATTRIBUTE_NORMAL));
|
|
#else
|
|
std::filesystem::permissions(file, std::filesystem::perms::owner_read);
|
|
RequireFailure(truncate_nid_postfix(path.c_str(), 1), GuestEacces);
|
|
Require(sceKernelTruncate_nid_postfix(path.c_str(), 1) == SceKernelErrorBase + GuestEacces);
|
|
std::filesystem::permissions(file, std::filesystem::perms::owner_read | std::filesystem::perms::owner_write);
|
|
#endif
|
|
Require(Contents(file) == "locked");
|
|
|
|
Require(std::filesystem::remove(file));
|
|
Require(std::filesystem::remove(directory));
|
|
}
|