[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:
parent
9fd63519bf
commit
65137e58bd
|
@ -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(
|
||||||
|
|
Loading…
Reference in New Issue