FEXCore/FileLoading: Updates helper to load file that is backed by memory

When attempting to read files that aren't backed by a filesystem then
our current read file helpers fail since they query the file size
upfront.

Change the helper so that it doesn't query the size and just reads the file if it
can be opened. This lets us read `/proc/self/maps` using helpers.
This commit is contained in:
Ryan Houdek committed 2023-11-03 07:01:39 -07:00
1 parent 15c825f362
commit b15f0b5d36
2 files changed
+53 -7

No files matched your search

+31 -7
View File
@@ -24,24 +24,48 @@ static bool LoadFileImpl(T &Data, const fextl::string &Filepath, size_t FixedSiz
size_t FileSize{};
if (FixedSize == 0) {
struct stat buf;
if (fstat(FD, &buf) != 0) {
close(FD);
return false;
if (fstat(FD, &buf) == 0) {
FileSize = buf.st_size;
}
FileSize = buf.st_size;
}
else {
FileSize = FixedSize;
}
ssize_t Read = -1;
if (FileSize > 0) {
bool LoadedFile{};
if (FileSize) {
// File size is known upfront
Data.resize(FileSize);
Read = pread(FD, &Data.at(0), FileSize, 0);
LoadedFile = Read == FileSize;
}
else {
// The file is either empty or its size is unknown (e.g. procfs data).
// Try reading in chunks instead
ssize_t CurrentOffset = 0;
constexpr size_t READ_SIZE = 4096;
Data.resize(READ_SIZE);
while ((Read = pread(FD, &Data.at(CurrentOffset), READ_SIZE, CurrentOffset)) == READ_SIZE) {
CurrentOffset += Read;
Data.resize(CurrentOffset + Read);
}
if (Read == -1) {
Data.clear();
close(FD);
return false;
}
// Final resize to ensure there is no garbage data past the end.
Data.resize(CurrentOffset + Read);
LoadedFile = true;
}
close(FD);
return Read == FileSize;
return LoadedFile;
}
ssize_t LoadFileToBuffer(const fextl::string &Filepath, std::span<char> Buffer) {
@@ -0,0 +1,22 @@
#include <FEXCore/Utils/FileLoading.h>
#include <catch2/catch.hpp>
TEST_CASE("LoadFile-Doesn'tExist") {
fextl::string MapsFile;
auto Read = FEXCore::FileLoading::LoadFile(MapsFile, "/tmp/a/b/c/d/e/z");
REQUIRE(MapsFile.size() == 0);
REQUIRE(Read == false);
}
TEST_CASE("LoadFile-procfs") {
fextl::string MapsFile;
FEXCore::FileLoading::LoadFile(MapsFile, "/proc/self/maps");
REQUIRE(MapsFile.size() != 0);
}
TEST_CASE("LoadFile-Buffer") {
fextl::string MapsFile;
MapsFile.resize(16);
auto Read = FEXCore::FileLoading::LoadFileToBuffer("/proc/self/maps", MapsFile);
REQUIRE(MapsFile.size() == Read);
}