[Base] Android content URI file memory mapping
This commit is contained in:
@@ -15,16 +15,15 @@
|
||||
#include <unistd.h>
|
||||
#include <memory>
|
||||
|
||||
#include "xenia/base/string.h"
|
||||
#include "xenia/base/filesystem.h"
|
||||
#include "xenia/base/platform.h"
|
||||
|
||||
namespace xe {
|
||||
|
||||
class PosixMappedMemory : public MappedMemory {
|
||||
public:
|
||||
PosixMappedMemory(const std::filesystem::path& path, Mode mode, void* data,
|
||||
size_t size, int file_descriptor)
|
||||
: MappedMemory(path, mode, data, size),
|
||||
file_descriptor_(file_descriptor) {}
|
||||
PosixMappedMemory(void* data, size_t size, int file_descriptor)
|
||||
: MappedMemory(data, size), file_descriptor_(file_descriptor) {}
|
||||
|
||||
~PosixMappedMemory() override {
|
||||
if (data_) {
|
||||
@@ -35,6 +34,39 @@ class PosixMappedMemory : public MappedMemory {
|
||||
}
|
||||
}
|
||||
|
||||
static std::unique_ptr<PosixMappedMemory> WrapFileDescriptor(
|
||||
int file_descriptor, Mode mode, size_t offset = 0, size_t length = 0) {
|
||||
int protection = 0;
|
||||
switch (mode) {
|
||||
case Mode::kRead:
|
||||
protection |= PROT_READ;
|
||||
break;
|
||||
case Mode::kReadWrite:
|
||||
protection |= PROT_READ | PROT_WRITE;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t map_length = length;
|
||||
if (!length) {
|
||||
struct stat64 file_stat;
|
||||
if (fstat64(file_descriptor, &file_stat)) {
|
||||
close(file_descriptor);
|
||||
return nullptr;
|
||||
}
|
||||
map_length = size_t(file_stat.st_size);
|
||||
}
|
||||
|
||||
void* data =
|
||||
mmap(0, map_length, protection, MAP_SHARED, file_descriptor, offset);
|
||||
if (!data) {
|
||||
close(file_descriptor);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<PosixMappedMemory>(data, map_length,
|
||||
file_descriptor);
|
||||
}
|
||||
|
||||
void Close(uint64_t truncate_size) override {
|
||||
if (data_) {
|
||||
munmap(data_, size());
|
||||
@@ -59,42 +91,43 @@ std::unique_ptr<MappedMemory> MappedMemory::Open(
|
||||
const std::filesystem::path& path, Mode mode, size_t offset,
|
||||
size_t length) {
|
||||
int open_flags = 0;
|
||||
int prot;
|
||||
switch (mode) {
|
||||
case Mode::kRead:
|
||||
open_flags |= O_RDONLY;
|
||||
prot = PROT_READ;
|
||||
break;
|
||||
case Mode::kReadWrite:
|
||||
open_flags |= O_RDWR;
|
||||
prot = PROT_READ | PROT_WRITE;
|
||||
break;
|
||||
}
|
||||
|
||||
int file_descriptor = open(path.c_str(), open_flags);
|
||||
if (file_descriptor < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return PosixMappedMemory::WrapFileDescriptor(file_descriptor, mode, offset,
|
||||
length);
|
||||
}
|
||||
|
||||
size_t map_length = length;
|
||||
if (!length) {
|
||||
struct stat64 file_stat;
|
||||
if (fstat64(file_descriptor, &file_stat)) {
|
||||
close(file_descriptor);
|
||||
return nullptr;
|
||||
}
|
||||
map_length = size_t(file_stat.st_size);
|
||||
#if XE_PLATFORM_ANDROID
|
||||
std::unique_ptr<MappedMemory> MappedMemory::OpenForAndroidContentUri(
|
||||
const std::string_view uri, Mode mode, size_t offset, size_t length) {
|
||||
const char* open_mode = nullptr;
|
||||
switch (mode) {
|
||||
case Mode::kRead:
|
||||
open_mode = "r";
|
||||
break;
|
||||
case Mode::kReadWrite:
|
||||
open_mode = "rw";
|
||||
break;
|
||||
}
|
||||
|
||||
void* data = mmap(0, map_length, prot, MAP_SHARED, file_descriptor, offset);
|
||||
if (!data) {
|
||||
close(file_descriptor);
|
||||
int file_descriptor =
|
||||
xe::filesystem::OpenAndroidContentFileDescriptor(uri, open_mode);
|
||||
if (file_descriptor < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::unique_ptr<MappedMemory>(
|
||||
new PosixMappedMemory(path, mode, data, map_length, file_descriptor));
|
||||
return PosixMappedMemory::WrapFileDescriptor(file_descriptor, mode, offset,
|
||||
length);
|
||||
}
|
||||
#endif // XE_PLATFORM_ANDROID
|
||||
|
||||
std::unique_ptr<ChunkedMappedMemoryWriter> ChunkedMappedMemoryWriter::Open(
|
||||
const std::filesystem::path& path, size_t chunk_size,
|
||||
|
||||
Reference in New Issue
Block a user