[Base] PosixMappedMemory: fd instead of stdio

Android ContentResolver, which is needed for content:// URIs, provides file descriptors rather than stdio files
This commit is contained in:
Triang3l 2022-07-14 22:11:46 +03:00
parent 9fd63519bf
commit 65137e58bd
1 changed files with 29 additions and 25 deletions

View File

@ -9,8 +9,10 @@
#include "xenia/base/mapped_memory.h" #include "xenia/base/mapped_memory.h"
#include <fcntl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <cstdio> #include <sys/stat.h>
#include <unistd.h>
#include <memory> #include <memory>
#include "xenia/base/string.h" #include "xenia/base/string.h"
@ -19,61 +21,63 @@ namespace xe {
class PosixMappedMemory : public MappedMemory { class PosixMappedMemory : public MappedMemory {
public: public:
PosixMappedMemory(const std::filesystem::path& path, Mode mode) PosixMappedMemory(const std::filesystem::path& path, Mode mode, void* data,
: MappedMemory(path, mode), file_handle(nullptr) {} size_t size, int file_descriptor)
: MappedMemory(path, mode, data, size),
file_descriptor_(file_descriptor) {}
~PosixMappedMemory() override { ~PosixMappedMemory() override {
if (data_) { if (data_) {
munmap(data_, size_); munmap(data_, size());
} }
if (file_handle) { if (file_descriptor_ >= 0) {
fclose(file_handle); close(file_descriptor_);
} }
} }
FILE* file_handle; private:
int file_descriptor_;
}; };
std::unique_ptr<MappedMemory> MappedMemory::Open( std::unique_ptr<MappedMemory> MappedMemory::Open(
const std::filesystem::path& path, Mode mode, size_t offset, const std::filesystem::path& path, Mode mode, size_t offset,
size_t length) { size_t length) {
const char* mode_str; int open_flags = 0;
int prot; int prot;
switch (mode) { switch (mode) {
case Mode::kRead: case Mode::kRead:
mode_str = "rb"; open_flags |= O_RDONLY;
prot = PROT_READ; prot = PROT_READ;
break; break;
case Mode::kReadWrite: case Mode::kReadWrite:
mode_str = "r+b"; open_flags |= O_RDWR;
prot = PROT_READ | PROT_WRITE; prot = PROT_READ | PROT_WRITE;
break; break;
} }
auto mm = int file_descriptor = open(path.c_str(), open_flags);
std::unique_ptr<PosixMappedMemory>(new PosixMappedMemory(path, mode)); if (file_descriptor < 0) {
mm->file_handle = fopen(path.c_str(), mode_str);
if (!mm->file_handle) {
return nullptr; return nullptr;
} }
size_t map_length; size_t map_length = length;
map_length = length;
if (!length) { if (!length) {
fseeko(mm->file_handle, 0, SEEK_END); struct stat64 file_stat;
map_length = ftello(mm->file_handle); if (fstat64(file_descriptor, &file_stat)) {
fseeko(mm->file_handle, 0, SEEK_SET); close(file_descriptor);
return nullptr;
}
map_length = size_t(file_stat.st_size);
} }
mm->size_ = map_length;
mm->data_ = void* data = mmap(0, map_length, prot, MAP_SHARED, file_descriptor, offset);
mmap(0, map_length, prot, MAP_SHARED, fileno(mm->file_handle), offset); if (!data) {
if (!mm->data_) { close(file_descriptor);
return nullptr; return nullptr;
} }
return std::move(mm); return std::unique_ptr<MappedMemory>(
new PosixMappedMemory(path, mode, data, map_length, file_descriptor));
} }
std::unique_ptr<ChunkedMappedMemoryWriter> ChunkedMappedMemoryWriter::Open( std::unique_ptr<ChunkedMappedMemoryWriter> ChunkedMappedMemoryWriter::Open(