Merge pull request #4038 from santhoshkumar-dev/fix/libkernel-symlink-file-size
fix(libkernel): report the target size of symbolic links on Windows
This commit is contained in:
commit
fe66af13ef
|
|
@ -77,7 +77,7 @@ bool _fileSize(const std::filesystem::path& path, std::uint64_t& bytes) {
|
|||
const HANDLE find = FindFirstFileExW((path.parent_path() / L"*").c_str(), FindExInfoBasic, &entry, FindExSearchNameMatch, nullptr, FIND_FIRST_EX_LARGE_FETCH);
|
||||
if (find != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
if ((entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) continue;
|
||||
if ((entry.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) != 0) continue;
|
||||
const auto size = (static_cast<std::uint64_t>(entry.nFileSizeHigh) << 32u) | entry.nFileSizeLow;
|
||||
sizes.emplace(_foldCase(std::filesystem::path(entry.cFileName).string()), size);
|
||||
} while (FindNextFileW(find, &entry));
|
||||
|
|
@ -101,8 +101,11 @@ bool _fileSize(const std::filesystem::path& path, std::uint64_t& bytes) {
|
|||
}
|
||||
// Not in the listing (created since, or an unusual name): ask the file system directly.
|
||||
std::error_code error;
|
||||
bytes = std::filesystem::file_size(path, error);
|
||||
return !error;
|
||||
if (!std::filesystem::is_regular_file(path, error)) return false;
|
||||
FileStat stat{};
|
||||
File::FillFileStat(path, &stat);
|
||||
bytes = static_cast<std::uint64_t>(stat.st_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
int _fail(int guestErrno) {
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ static void CopyNativeStat(const NativeStat& st, FileStat* sb) {
|
|||
sb->st_mode = static_cast<std::uint16_t>(st.st_mode);
|
||||
sb->st_size = static_cast<std::int64_t>(st.st_size);
|
||||
#ifdef _WIN32
|
||||
if (st.hasIdentity) sb->st_size = static_cast<std::int64_t>((static_cast<std::uint64_t>(st.identity.nFileSizeHigh) << 32u) | st.identity.nFileSizeLow);
|
||||
sb->st_dev = static_cast<std::uint32_t>(st.st_dev);
|
||||
sb->st_ino = static_cast<std::uint32_t>(st.st_ino);
|
||||
sb->st_nlink = static_cast<std::uint16_t>(st.st_nlink);
|
||||
|
|
|
|||
|
|
@ -9,12 +9,16 @@
|
|||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <future>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
int APS5_VABI sceAmprCommandBufferConstructor(Apr::CommandBufferObject*);
|
||||
|
|
@ -671,6 +675,31 @@ void TestMalformedCommandSizes() {
|
|||
Require(rejected);
|
||||
}
|
||||
|
||||
void TestResolveSymbolicLink() {
|
||||
const std::filesystem::path directory = "ampr_resolve_links";
|
||||
std::filesystem::remove_all(directory);
|
||||
Require(std::filesystem::create_directory(directory));
|
||||
{ std::ofstream file(directory / "target.bin", std::ios::binary); file << "linked data"; }
|
||||
const auto link = directory / "link.bin";
|
||||
#ifdef _WIN32
|
||||
if (CreateSymbolicLinkW(link.c_str(), L"target.bin", SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) == 0) {
|
||||
Require(GetLastError() == ERROR_PRIVILEGE_NOT_HELD);
|
||||
std::fprintf(stderr, "APR symbolic link check skipped: creating symbolic links needs Developer Mode or administrator rights\n");
|
||||
std::filesystem::remove_all(directory);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
std::filesystem::create_symlink("target.bin", link);
|
||||
#endif
|
||||
const std::string linkPath = link.generic_string();
|
||||
const char* path = linkPath.c_str();
|
||||
std::uint32_t id = 0;
|
||||
std::uint64_t size = 0;
|
||||
std::uint32_t failed = 0;
|
||||
Require(sceKernelAprResolveFilepathsToIdsAndFileSizes(&path, 1, &id, &size, &failed) == 0 && size == 11);
|
||||
std::filesystem::remove_all(directory);
|
||||
}
|
||||
|
||||
void TestGatherScatter() {
|
||||
const char* path = "ampr_gather_scatter.bin";
|
||||
{
|
||||
|
|
@ -1230,6 +1259,7 @@ int main() {
|
|||
TestZeroFilledBuffer();
|
||||
TestResolveFailures();
|
||||
TestMalformedCommandSizes();
|
||||
TestResolveSymbolicLink();
|
||||
TestGatherScatter();
|
||||
TestAmmRangesAboveHintedMaps();
|
||||
TestAmm();
|
||||
|
|
|
|||
|
|
@ -428,7 +428,7 @@ int main() {
|
|||
std::filesystem::create_symlink("present.txt", link);
|
||||
Require(lstat_nid_postfix(link.string().c_str(), &linkStatus) == 0);
|
||||
Require((linkStatus.st_mode & 0170000) == 0120000 && linkStatus.st_size == 11);
|
||||
Require(stat_nid_postfix(link.string().c_str(), &status) == 0 && (status.st_mode & 0170000) == 0100000);
|
||||
Require(stat_nid_postfix(link.string().c_str(), &status) == 0 && (status.st_mode & 0170000) == 0100000 && status.st_size == 5);
|
||||
const auto dangling = root / "dangling";
|
||||
std::filesystem::create_symlink("missing.txt", dangling);
|
||||
Require(lstat_nid_postfix(dangling.string().c_str(), &linkStatus) == 0 && (linkStatus.st_mode & 0170000) == 0120000);
|
||||
|
|
@ -443,7 +443,7 @@ int main() {
|
|||
Require(unlink_nid_postfix(link.string().c_str()) == 0 && unlink_nid_postfix(dangling.string().c_str()) == 0);
|
||||
#else
|
||||
const auto fileLink = root / "file-link";
|
||||
if (CreateSymbolicLinkW(fileLink.c_str(), present.c_str(), SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) == 0) {
|
||||
if (CreateSymbolicLinkW(fileLink.c_str(), L"present.txt", SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) == 0) {
|
||||
Require(GetLastError() == ERROR_PRIVILEGE_NOT_HELD);
|
||||
std::fprintf(stderr, "Windows lstat link checks skipped: creating symbolic links needs Developer Mode or administrator rights\n");
|
||||
} else {
|
||||
|
|
@ -451,7 +451,7 @@ int main() {
|
|||
Require(std::filesystem::create_directory(targetDirectory));
|
||||
const auto directoryLink = root / "directory-link";
|
||||
const auto danglingLink = root / "dangling-link";
|
||||
Require(CreateSymbolicLinkW(directoryLink.c_str(), targetDirectory.c_str(),
|
||||
Require(CreateSymbolicLinkW(directoryLink.c_str(), L"target-directory",
|
||||
SYMBOLIC_LINK_FLAG_DIRECTORY | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) != 0);
|
||||
Require(CreateSymbolicLinkW(danglingLink.c_str(), missing.c_str(), SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) != 0);
|
||||
const auto checkUnsupportedLink = [](const std::filesystem::path& link) {
|
||||
|
|
@ -470,6 +470,7 @@ int main() {
|
|||
const bool statusUnchanged = std::all_of(bytes, bytes + sizeof(untouched), [](unsigned char value) { return value == 0x5a; });
|
||||
return rejected && errorUnchanged && statusUnchanged;
|
||||
};
|
||||
Require(stat_nid_postfix(fileLink.string().c_str(), &status) == 0 && status.st_size == 5);
|
||||
Require(checkUnsupportedLink(fileLink));
|
||||
Require(checkUnsupportedLink(directoryLink));
|
||||
Require(checkUnsupportedLink(danglingLink));
|
||||
|
|
|
|||
Loading…
Reference in New Issue