blob: 159499aaae44a4caed53fcc3b69ef3045d009082 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "file_in_namespace_buffer.h"
#include <lib/fdio/directory.h>
#include <zircon/status.h>
#include "flutter/fml/trace_event.h"
#include "runtime/dart/utils/files.h"
#include "runtime/dart/utils/handle_exception.h"
#include "runtime/dart/utils/mapped_resource.h"
#include "runtime/dart/utils/tempfs.h"
#include "runtime/dart/utils/vmo.h"
namespace flutter_runner {
namespace {
// TODO(kaushikiska): Use these constants from ::llcpp::fuchsia::io
// Can read from target object.
constexpr uint32_t OPEN_RIGHT_READABLE = 1u;
// Connection can map target object executable.
constexpr uint32_t OPEN_RIGHT_EXECUTABLE = 8u;
} // namespace
FileInNamespaceBuffer::FileInNamespaceBuffer(int namespace_fd,
const char* path,
bool executable)
: address_(nullptr), size_(0) {
fuchsia::mem::Buffer buffer;
if (!dart_utils::VmoFromFilenameAt(namespace_fd, path, executable, &buffer) ||
buffer.size == 0) {
return;
}
uint32_t flags = ZX_VM_PERM_READ;
if (executable) {
flags |= ZX_VM_PERM_EXECUTE;
}
uintptr_t addr;
const zx_status_t status =
zx::vmar::root_self()->map(flags, 0, buffer.vmo, 0, buffer.size, &addr);
if (status != ZX_OK) {
FML_LOG(FATAL) << "Failed to map " << path << ": "
<< zx_status_get_string(status);
}
address_ = reinterpret_cast<void*>(addr);
size_ = buffer.size;
}
FileInNamespaceBuffer::~FileInNamespaceBuffer() {
if (address_ != nullptr) {
zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(address_), size_);
address_ = nullptr;
size_ = 0;
}
}
const uint8_t* FileInNamespaceBuffer::GetMapping() const {
return reinterpret_cast<const uint8_t*>(address_);
}
size_t FileInNamespaceBuffer::GetSize() const {
return size_;
}
std::unique_ptr<fml::Mapping> LoadFile(int namespace_fd,
const char* path,
bool executable) {
FML_TRACE_EVENT("flutter", "LoadFile", "path", path);
return std::make_unique<FileInNamespaceBuffer>(namespace_fd, path,
executable);
}
std::unique_ptr<fml::FileMapping> MakeFileMapping(const char* path,
bool executable) {
uint32_t flags = OPEN_RIGHT_READABLE;
if (executable) {
flags |= OPEN_RIGHT_EXECUTABLE;
}
// The returned file descriptor is compatible with standard posix operations
// such as close, mmap, etc. We only need to treat open/open_at specially.
int fd;
const zx_status_t status = fdio_open_fd(path, flags, &fd);
if (status != ZX_OK) {
return nullptr;
}
using Protection = fml::FileMapping::Protection;
std::initializer_list<Protection> protection_execute = {Protection::kRead,
Protection::kExecute};
std::initializer_list<Protection> protection_read = {Protection::kRead};
auto mapping = std::make_unique<fml::FileMapping>(
fml::UniqueFD{fd}, executable ? protection_execute : protection_read);
if (!mapping->IsValid()) {
return nullptr;
}
return mapping;
}
} // namespace flutter_runner