mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 11:58:13 +00:00
Fuchsia: Build standalone VM. Make it run "Hello, World!".
This CL adds targets to the GN build that build the standalone Dart VM without the observatory, and with dart:io enabled but with most of the functionality stubbed out as UNIMPLEMENTED(). It also adds a simple eventhandler for Fuchsia for implementing Timers. R=asiva@google.com, johnmccutchan@google.com Review URL: https://codereview.chromium.org/2168193002 .
This commit is contained in:
parent
5680532769
commit
53374c3b99
|
@ -138,6 +138,7 @@ static_library("libdart_builtin") {
|
|||
set_sources_assignment_filter(["*_test.cc", "*_test.h"])
|
||||
sources = [
|
||||
"log_android.cc",
|
||||
"log_fuchsia.cc",
|
||||
"log_linux.cc",
|
||||
"log_macos.cc",
|
||||
"log_win.cc",
|
||||
|
@ -212,14 +213,11 @@ static_library("libdart_nosnapshot_with_precompiler") {
|
|||
]
|
||||
}
|
||||
|
||||
if ((current_toolchain == host_toolchain) ||
|
||||
(!defined(is_fuchsia) || !is_fuchsia)) {
|
||||
io_impl_sources_gypi =
|
||||
exec_script("../../tools/gypi_to_gn.py",
|
||||
[ rebase_path("io_impl_sources.gypi") ],
|
||||
"scope",
|
||||
[ "io_impl_sources.gypi" ])
|
||||
}
|
||||
|
||||
if (!defined(is_fuchsia) || (current_toolchain == host_toolchain)) {
|
||||
|
||||
|
@ -312,7 +310,6 @@ source_set("libdart_embedder_noio") {
|
|||
]
|
||||
}
|
||||
|
||||
if (!defined(is_fuchsia) || !is_fuchsia) {
|
||||
|
||||
# A source set for the implementation of 'dart:io' library
|
||||
# (without secure sockets).
|
||||
|
@ -340,6 +337,10 @@ source_set("embedded_dart_io") {
|
|||
libs = [
|
||||
"Security.framework",
|
||||
]
|
||||
} else if (defined(is_fuchsia) && is_fuchsia) {
|
||||
defines = [
|
||||
"DART_IO_SECURE_SOCKET_DISABLED"
|
||||
]
|
||||
} else {
|
||||
deps = [
|
||||
rebase_path(dart_boringssl_path, "."),
|
||||
|
@ -369,7 +370,6 @@ source_set("embedded_dart_io") {
|
|||
"//third_party"
|
||||
]
|
||||
}
|
||||
} # !is_fuchsia
|
||||
|
||||
|
||||
action("generate_snapshot_bin") {
|
||||
|
@ -466,4 +466,42 @@ if (defined(is_fuchsia) && is_fuchsia) {
|
|||
":libdart_embedder_noio",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
copy("hello_fuchsia") {
|
||||
sources = [ "../tests/vm/dart/hello_fuchsia_test.dart" ]
|
||||
outputs = [ "$root_out_dir/hello_fuchsia.dart" ]
|
||||
}
|
||||
|
||||
executable("dart_no_observatory") {
|
||||
configs += ["..:dart_config",
|
||||
"..:dart_product_config",
|
||||
"..:dart_precompiled_runtime_config",]
|
||||
deps = [
|
||||
":hello_fuchsia",
|
||||
":gen_resources_cc",
|
||||
":embedded_dart_io",
|
||||
":libdart_builtin",
|
||||
"../vm:libdart_platform",
|
||||
"..:libdart",
|
||||
":dart_snapshot_cc",
|
||||
"//third_party/zlib",
|
||||
]
|
||||
|
||||
defines = [
|
||||
"NO_OBSERVATORY",
|
||||
]
|
||||
|
||||
sources = [
|
||||
"main.cc",
|
||||
"observatory_assets_empty.cc",
|
||||
"vmservice_impl.cc",
|
||||
"vmservice_impl.h",
|
||||
"$target_gen_dir/resources_gen.cc",
|
||||
]
|
||||
|
||||
include_dirs = [
|
||||
"..",
|
||||
"//third_party",
|
||||
]
|
||||
}
|
||||
} # defined(is_fuchsia) && is_fuchsia
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
'crypto.cc',
|
||||
'crypto.h',
|
||||
'crypto_android.cc',
|
||||
'crypto_fuchsia.cc',
|
||||
'crypto_linux.cc',
|
||||
'crypto_macos.cc',
|
||||
'crypto_win.cc',
|
||||
|
@ -19,6 +20,7 @@
|
|||
'directory.cc',
|
||||
'directory.h',
|
||||
'directory_android.cc',
|
||||
'directory_fuchsia.cc',
|
||||
'directory_linux.cc',
|
||||
'directory_macos.cc',
|
||||
'directory_unsupported.cc',
|
||||
|
@ -27,6 +29,7 @@
|
|||
'extensions.h',
|
||||
'extensions.cc',
|
||||
'extensions_android.cc',
|
||||
'extensions_fuchsia.cc',
|
||||
'extensions_linux.cc',
|
||||
'extensions_macos.cc',
|
||||
'extensions_win.cc',
|
||||
|
@ -37,6 +40,7 @@
|
|||
'file.cc',
|
||||
'file.h',
|
||||
'file_android.cc',
|
||||
'file_fuchsia.cc',
|
||||
'file_linux.cc',
|
||||
'file_macos.cc',
|
||||
'file_support.cc',
|
||||
|
@ -63,6 +67,7 @@
|
|||
'thread_win.h',
|
||||
'utils.h',
|
||||
'utils_android.cc',
|
||||
'utils_fuchsia.cc',
|
||||
'utils_linux.cc',
|
||||
'utils_macos.cc',
|
||||
'utils_win.cc',
|
||||
|
|
31
runtime/bin/crypto_fuchsia.cc
Normal file
31
runtime/bin/crypto_fuchsia.cc
Normal file
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#include "platform/globals.h"
|
||||
#if defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#include "bin/crypto.h"
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
bool Crypto::GetRandomBytes(intptr_t count, uint8_t* buffer) {
|
||||
uint32_t num;
|
||||
intptr_t read = 0;
|
||||
while (read < count) {
|
||||
if (rand_r(&num) != 0) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < 4 && read < count; i++) {
|
||||
buffer[read] = num >> (i * 8);
|
||||
read++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace bin
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(TARGET_OS_FUCHSIA)
|
154
runtime/bin/directory_fuchsia.cc
Normal file
154
runtime/bin/directory_fuchsia.cc
Normal file
|
@ -0,0 +1,154 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#include "platform/globals.h"
|
||||
#if defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#include "bin/directory.h"
|
||||
|
||||
#include <errno.h> // NOLINT
|
||||
#include <stdlib.h> // NOLINT
|
||||
#include <string.h> // NOLINT
|
||||
#include <unistd.h> // NOLINT
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
PathBuffer::PathBuffer() : length_(0) {
|
||||
data_ = calloc(PATH_MAX + 1, sizeof(char)); // NOLINT
|
||||
}
|
||||
|
||||
|
||||
PathBuffer::~PathBuffer() {
|
||||
free(data_);
|
||||
}
|
||||
|
||||
|
||||
bool PathBuffer::AddW(const wchar_t* name) {
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
char* PathBuffer::AsString() const {
|
||||
return reinterpret_cast<char*>(data_);
|
||||
}
|
||||
|
||||
|
||||
wchar_t* PathBuffer::AsStringW() const {
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const char* PathBuffer::AsScopedString() const {
|
||||
return DartUtils::ScopedCopyCString(AsString());
|
||||
}
|
||||
|
||||
|
||||
bool PathBuffer::Add(const char* name) {
|
||||
const intptr_t name_length = strnlen(name, PATH_MAX + 1);
|
||||
if (name_length == 0) {
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
char* data = AsString();
|
||||
int written = snprintf(data + length_,
|
||||
PATH_MAX - length_,
|
||||
"%s",
|
||||
name);
|
||||
data[PATH_MAX] = '\0';
|
||||
if ((written <= (PATH_MAX - length_)) &&
|
||||
(written > 0) &&
|
||||
(static_cast<size_t>(written) == strnlen(name, PATH_MAX + 1))) {
|
||||
length_ += written;
|
||||
return true;
|
||||
} else {
|
||||
errno = ENAMETOOLONG;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PathBuffer::Reset(intptr_t new_length) {
|
||||
length_ = new_length;
|
||||
AsString()[length_] = '\0';
|
||||
}
|
||||
|
||||
|
||||
ListType DirectoryListingEntry::Next(DirectoryListing* listing) {
|
||||
UNIMPLEMENTED();
|
||||
return kListError;
|
||||
}
|
||||
|
||||
|
||||
DirectoryListingEntry::~DirectoryListingEntry() {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
void DirectoryListingEntry::ResetLink() {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
Directory::ExistsResult Directory::Exists(const char* dir_name) {
|
||||
UNIMPLEMENTED();
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
char* Directory::CurrentNoScope() {
|
||||
return getcwd(NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
const char* Directory::Current() {
|
||||
char buffer[PATH_MAX];
|
||||
if (getcwd(buffer, PATH_MAX) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return DartUtils::ScopedCopyCString(buffer);
|
||||
}
|
||||
|
||||
|
||||
bool Directory::SetCurrent(const char* path) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Directory::Create(const char* dir_name) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const char* Directory::SystemTemp() {
|
||||
UNIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const char* Directory::CreateTemp(const char* prefix) {
|
||||
UNIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool Directory::Delete(const char* dir_name, bool recursive) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Directory::Rename(const char* path, const char* new_path) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace bin
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(TARGET_OS_LINUX)
|
|
@ -605,6 +605,8 @@ class DescriptorInfoMultipleMixin : public DI {
|
|||
// The event handler delegation class is OS specific.
|
||||
#if defined(TARGET_OS_ANDROID)
|
||||
#include "bin/eventhandler_android.h"
|
||||
#elif defined(TARGET_OS_FUCHSIA)
|
||||
#include "bin/eventhandler_fuchsia.h"
|
||||
#elif defined(TARGET_OS_LINUX)
|
||||
#include "bin/eventhandler_linux.h"
|
||||
#elif defined(TARGET_OS_MACOS)
|
||||
|
|
172
runtime/bin/eventhandler_fuchsia.cc
Normal file
172
runtime/bin/eventhandler_fuchsia.cc
Normal file
|
@ -0,0 +1,172 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#if !defined(DART_IO_DISABLED)
|
||||
|
||||
#include "platform/globals.h"
|
||||
#if defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#include "bin/eventhandler.h"
|
||||
#include "bin/eventhandler_fuchsia.h"
|
||||
|
||||
#include <magenta/syscalls.h>
|
||||
#include <runtime/status.h>
|
||||
|
||||
#include "bin/thread.h"
|
||||
#include "bin/utils.h"
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
EventHandlerImplementation::EventHandlerImplementation() {
|
||||
mx_status_t status = mx_message_pipe_create(interrupt_handles_, 0);
|
||||
if (status != NO_ERROR) {
|
||||
FATAL1("mx_message_pipe_create failed: %s\n", mx_strstatus(status));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EventHandlerImplementation::~EventHandlerImplementation() {
|
||||
mx_status_t status = mx_handle_close(interrupt_handles_[0]);
|
||||
if (status != NO_ERROR) {
|
||||
FATAL1("mx_handle_close failed: %s\n", mx_strstatus(status));
|
||||
}
|
||||
status = mx_handle_close(interrupt_handles_[1]);
|
||||
if (status != NO_ERROR) {
|
||||
FATAL1("mx_handle_close failed: %s\n", mx_strstatus(status));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EventHandlerImplementation::WakeupHandler(intptr_t id,
|
||||
Dart_Port dart_port,
|
||||
int64_t data) {
|
||||
InterruptMessage msg;
|
||||
msg.id = id;
|
||||
msg.dart_port = dart_port;
|
||||
msg.data = data;
|
||||
|
||||
mx_status_t status =
|
||||
mx_message_write(interrupt_handles_[1], &msg, sizeof(msg), NULL, 0, 0);
|
||||
if (status != NO_ERROR) {
|
||||
FATAL1("mx_message_write failed: %s\n", mx_strstatus(status));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EventHandlerImplementation::HandleInterruptFd() {
|
||||
InterruptMessage msg;
|
||||
uint32_t bytes = kInterruptMessageSize;
|
||||
mx_status_t status;
|
||||
while (true) {
|
||||
status = mx_message_read(
|
||||
interrupt_handles_[0], &msg, &bytes, NULL, NULL, 0);
|
||||
if (status != NO_ERROR) {
|
||||
break;
|
||||
}
|
||||
ASSERT(bytes == kInterruptMessageSize);
|
||||
if (msg.id == kTimerId) {
|
||||
timeout_queue_.UpdateTimeout(msg.dart_port, msg.data);
|
||||
} else if (msg.id == kShutdownId) {
|
||||
shutdown_ = true;
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
}
|
||||
// status == ERR_BAD_STATE when we try to read and there are no messages
|
||||
// available, so it is an error if we get here and status != ERR_BAD_STATE.
|
||||
if (status != ERR_BAD_STATE) {
|
||||
FATAL1("mx_message_read failed: %s\n", mx_strstatus(status));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EventHandlerImplementation::HandleEvents() {
|
||||
// TODO(zra): Handle events from other handles. At the moment we are only
|
||||
// interrupted when there is a message on interrupt_handles_[0].
|
||||
HandleInterruptFd();
|
||||
}
|
||||
|
||||
|
||||
int64_t EventHandlerImplementation::GetTimeout() const {
|
||||
if (!timeout_queue_.HasTimeout()) {
|
||||
return kInfinityTimeout;
|
||||
}
|
||||
int64_t millis = timeout_queue_.CurrentTimeout() -
|
||||
TimerUtils::GetCurrentMonotonicMillis();
|
||||
return (millis < 0) ? 0 : millis;
|
||||
}
|
||||
|
||||
|
||||
void EventHandlerImplementation::HandleTimeout() {
|
||||
if (timeout_queue_.HasTimeout()) {
|
||||
int64_t millis = timeout_queue_.CurrentTimeout() -
|
||||
TimerUtils::GetCurrentMonotonicMillis();
|
||||
if (millis <= 0) {
|
||||
DartUtils::PostNull(timeout_queue_.CurrentPort());
|
||||
timeout_queue_.RemoveCurrent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EventHandlerImplementation::Poll(uword args) {
|
||||
EventHandler* handler = reinterpret_cast<EventHandler*>(args);
|
||||
EventHandlerImplementation* handler_impl = &handler->delegate_;
|
||||
ASSERT(handler_impl != NULL);
|
||||
|
||||
while (!handler_impl->shutdown_) {
|
||||
int64_t millis = handler_impl->GetTimeout();
|
||||
ASSERT((millis == kInfinityTimeout) || (millis >= 0));
|
||||
|
||||
mx_time_t timeout =
|
||||
millis * kMicrosecondsPerMillisecond * kNanosecondsPerMicrosecond;
|
||||
mx_signals_state_t signals_state;
|
||||
mx_status_t status = mx_handle_wait_one(
|
||||
handler_impl->interrupt_handles_[0],
|
||||
MX_SIGNAL_READABLE | MX_SIGNAL_PEER_CLOSED,
|
||||
timeout,
|
||||
&signals_state);
|
||||
if ((status != NO_ERROR) && (status != ERR_TIMED_OUT)) {
|
||||
FATAL1("mx_handle_wait_one failed: %s\n", mx_strstatus(status));
|
||||
} else {
|
||||
handler_impl->HandleTimeout();
|
||||
if ((signals_state.satisfied & MX_SIGNAL_READABLE) != 0) {
|
||||
handler_impl->HandleEvents();
|
||||
}
|
||||
if ((signals_state.satisfied & MX_SIGNAL_PEER_CLOSED) != 0) {
|
||||
FATAL("EventHandlerImplementation::Poll: Unexpected peer closed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
handler->NotifyShutdownDone();
|
||||
}
|
||||
|
||||
|
||||
void EventHandlerImplementation::Start(EventHandler* handler) {
|
||||
int result = Thread::Start(&EventHandlerImplementation::Poll,
|
||||
reinterpret_cast<uword>(handler));
|
||||
if (result != 0) {
|
||||
FATAL1("Failed to start event handler thread %d", result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EventHandlerImplementation::Shutdown() {
|
||||
SendData(kShutdownId, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
void EventHandlerImplementation::SendData(intptr_t id,
|
||||
Dart_Port dart_port,
|
||||
int64_t data) {
|
||||
WakeupHandler(id, dart_port, data);
|
||||
}
|
||||
|
||||
} // namespace bin
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#endif // !defined(DART_IO_DISABLED)
|
44
runtime/bin/eventhandler_fuchsia.h
Normal file
44
runtime/bin/eventhandler_fuchsia.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef BIN_EVENTHANDLER_FUCHSIA_H_
|
||||
#define BIN_EVENTHANDLER_FUCHSIA_H_
|
||||
|
||||
#if !defined(BIN_EVENTHANDLER_H_)
|
||||
#error Do not include eventhandler_fuchsia.h directly; use eventhandler.h instead.
|
||||
#endif
|
||||
|
||||
#include <magenta/syscalls.h>
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
class EventHandlerImplementation {
|
||||
public:
|
||||
EventHandlerImplementation();
|
||||
~EventHandlerImplementation();
|
||||
|
||||
void SendData(intptr_t id, Dart_Port dart_port, int64_t data);
|
||||
void Start(EventHandler* handler);
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
int64_t GetTimeout() const;
|
||||
void HandleEvents();
|
||||
void HandleTimeout();
|
||||
void WakeupHandler(intptr_t id, Dart_Port dart_port, int64_t data);
|
||||
void HandleInterruptFd();
|
||||
static void Poll(uword args);
|
||||
|
||||
TimeoutQueue timeout_queue_;
|
||||
bool shutdown_;
|
||||
mx_handle_t interrupt_handles_[2];
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
|
||||
};
|
||||
|
||||
} // namespace bin
|
||||
} // namespace dart
|
||||
|
||||
#endif // BIN_EVENTHANDLER_FUCHSIA_H_
|
38
runtime/bin/extensions_fuchsia.cc
Normal file
38
runtime/bin/extensions_fuchsia.cc
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#include "platform/globals.h"
|
||||
#if defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#include "bin/extensions.h"
|
||||
#include <dlfcn.h> // NOLINT
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
const char* kPrecompiledLibraryName = "libprecompiled.so";
|
||||
const char* kPrecompiledInstructionsSymbolName = "_kInstructionsSnapshot";
|
||||
const char* kPrecompiledDataSymbolName = "_kDataSnapshot";
|
||||
|
||||
void* Extensions::LoadExtensionLibrary(const char* library_file) {
|
||||
return dlopen(library_file, RTLD_LAZY);
|
||||
}
|
||||
|
||||
void* Extensions::ResolveSymbol(void* lib_handle, const char* symbol) {
|
||||
dlerror();
|
||||
return dlsym(lib_handle, symbol);
|
||||
}
|
||||
|
||||
Dart_Handle Extensions::GetError() {
|
||||
const char* err_str = dlerror();
|
||||
if (err_str != NULL) {
|
||||
return Dart_NewApiError(err_str);
|
||||
}
|
||||
return Dart_Null();
|
||||
}
|
||||
|
||||
} // namespace bin
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(TARGET_OS_FUCHSIA)
|
452
runtime/bin/file_fuchsia.cc
Normal file
452
runtime/bin/file_fuchsia.cc
Normal file
|
@ -0,0 +1,452 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#include "platform/globals.h"
|
||||
#if defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#include "bin/file.h"
|
||||
|
||||
#include <errno.h> // NOLINT
|
||||
#include <fcntl.h> // NOLINT
|
||||
#include <libgen.h> // NOLINT
|
||||
#include <sys/mman.h> // NOLINT
|
||||
#include <sys/stat.h> // NOLINT
|
||||
#include <sys/types.h> // NOLINT
|
||||
#include <unistd.h> // NOLINT
|
||||
|
||||
#include "bin/builtin.h"
|
||||
#include "bin/log.h"
|
||||
#include "platform/signal_blocker.h"
|
||||
#include "platform/utils.h"
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
class FileHandle {
|
||||
public:
|
||||
explicit FileHandle(int fd) : fd_(fd) { }
|
||||
~FileHandle() { }
|
||||
int fd() const { return fd_; }
|
||||
void set_fd(int fd) { fd_ = fd; }
|
||||
|
||||
private:
|
||||
int fd_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FileHandle);
|
||||
};
|
||||
|
||||
|
||||
File::~File() {
|
||||
if (!IsClosed()) {
|
||||
Close();
|
||||
}
|
||||
delete handle_;
|
||||
}
|
||||
|
||||
|
||||
void File::Close() {
|
||||
ASSERT(handle_->fd() >= 0);
|
||||
if (handle_->fd() == STDOUT_FILENO) {
|
||||
// If stdout, redirect fd to /dev/null.
|
||||
int null_fd = NO_RETRY_EXPECTED(open("/dev/null", O_WRONLY));
|
||||
ASSERT(null_fd >= 0);
|
||||
VOID_NO_RETRY_EXPECTED(dup2(null_fd, handle_->fd()));
|
||||
VOID_NO_RETRY_EXPECTED(close(null_fd));
|
||||
} else {
|
||||
int err = NO_RETRY_EXPECTED(close(handle_->fd()));
|
||||
if (err != 0) {
|
||||
const int kBufferSize = 1024;
|
||||
char error_buf[kBufferSize];
|
||||
Log::PrintErr("%s\n", Utils::StrError(errno, error_buf, kBufferSize));
|
||||
}
|
||||
}
|
||||
handle_->set_fd(kClosedFd);
|
||||
}
|
||||
|
||||
|
||||
intptr_t File::GetFD() {
|
||||
return handle_->fd();
|
||||
}
|
||||
|
||||
|
||||
bool File::IsClosed() {
|
||||
return handle_->fd() == kClosedFd;
|
||||
}
|
||||
|
||||
|
||||
void* File::MapExecutable(intptr_t* len) {
|
||||
UNIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int64_t File::Read(void* buffer, int64_t num_bytes) {
|
||||
ASSERT(handle_->fd() >= 0);
|
||||
return NO_RETRY_EXPECTED(read(handle_->fd(), buffer, num_bytes));
|
||||
}
|
||||
|
||||
|
||||
int64_t File::Write(const void* buffer, int64_t num_bytes) {
|
||||
ASSERT(handle_->fd() >= 0);
|
||||
return NO_RETRY_EXPECTED(write(handle_->fd(), buffer, num_bytes));
|
||||
}
|
||||
|
||||
|
||||
int64_t File::Position() {
|
||||
ASSERT(handle_->fd() >= 0);
|
||||
return NO_RETRY_EXPECTED(lseek(handle_->fd(), 0, SEEK_CUR));
|
||||
}
|
||||
|
||||
|
||||
bool File::SetPosition(int64_t position) {
|
||||
ASSERT(handle_->fd() >= 0);
|
||||
return NO_RETRY_EXPECTED(lseek(handle_->fd(), position, SEEK_SET)) >= 0;
|
||||
}
|
||||
|
||||
|
||||
bool File::Truncate(int64_t length) {
|
||||
ASSERT(handle_->fd() >= 0);
|
||||
return NO_RETRY_EXPECTED(ftruncate(handle_->fd(), length) != -1);
|
||||
}
|
||||
|
||||
|
||||
bool File::Flush() {
|
||||
ASSERT(handle_->fd() >= 0);
|
||||
return NO_RETRY_EXPECTED(fsync(handle_->fd())) != -1;
|
||||
}
|
||||
|
||||
|
||||
bool File::Lock(File::LockType lock, int64_t start, int64_t end) {
|
||||
ASSERT(handle_->fd() >= 0);
|
||||
ASSERT((end == -1) || (end > start));
|
||||
struct flock fl;
|
||||
switch (lock) {
|
||||
case File::kLockUnlock:
|
||||
fl.l_type = F_UNLCK;
|
||||
break;
|
||||
case File::kLockShared:
|
||||
case File::kLockBlockingShared:
|
||||
fl.l_type = F_RDLCK;
|
||||
break;
|
||||
case File::kLockExclusive:
|
||||
case File::kLockBlockingExclusive:
|
||||
fl.l_type = F_WRLCK;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = start;
|
||||
fl.l_len = end == -1 ? 0 : end - start;
|
||||
int cmd = F_SETLK;
|
||||
if ((lock == File::kLockBlockingShared) ||
|
||||
(lock == File::kLockBlockingExclusive)) {
|
||||
cmd = F_SETLKW;
|
||||
}
|
||||
return NO_RETRY_EXPECTED(fcntl(handle_->fd(), cmd, &fl)) != -1;
|
||||
}
|
||||
|
||||
|
||||
int64_t File::Length() {
|
||||
ASSERT(handle_->fd() >= 0);
|
||||
struct stat st;
|
||||
if (NO_RETRY_EXPECTED(fstat(handle_->fd(), &st)) == 0) {
|
||||
return st.st_size;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
File* File::FileOpenW(const wchar_t* system_name, FileOpenMode mode) {
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
File* File::ScopedOpen(const char* name, FileOpenMode mode) {
|
||||
// Report errors for non-regular files.
|
||||
struct stat st;
|
||||
if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
errno = (S_ISDIR(st.st_mode)) ? EISDIR : ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
int flags = O_RDONLY;
|
||||
if ((mode & kWrite) != 0) {
|
||||
ASSERT((mode & kWriteOnly) == 0);
|
||||
flags = (O_RDWR | O_CREAT);
|
||||
}
|
||||
if ((mode & kWriteOnly) != 0) {
|
||||
ASSERT((mode & kWrite) == 0);
|
||||
flags = (O_WRONLY | O_CREAT);
|
||||
}
|
||||
if ((mode & kTruncate) != 0) {
|
||||
flags = flags | O_TRUNC;
|
||||
}
|
||||
flags |= O_CLOEXEC;
|
||||
int fd = NO_RETRY_EXPECTED(open(name, flags, 0666));
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if ((((mode & kWrite) != 0) && ((mode & kTruncate) == 0)) ||
|
||||
(((mode & kWriteOnly) != 0) && ((mode & kTruncate) == 0))) {
|
||||
int64_t position = lseek(fd, 0, SEEK_END);
|
||||
if (position < 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return new File(new FileHandle(fd));
|
||||
}
|
||||
|
||||
|
||||
File* File::Open(const char* path, FileOpenMode mode) {
|
||||
// ScopedOpen doesn't actually need a scope.
|
||||
return ScopedOpen(path, mode);
|
||||
}
|
||||
|
||||
|
||||
File* File::OpenStdio(int fd) {
|
||||
return ((fd < 0) || (2 < fd)) ? NULL : new File(new FileHandle(fd));
|
||||
}
|
||||
|
||||
|
||||
bool File::Exists(const char* name) {
|
||||
struct stat st;
|
||||
if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
|
||||
return S_ISREG(st.st_mode);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool File::Create(const char* name) {
|
||||
int fd = NO_RETRY_EXPECTED(open(name, O_RDONLY | O_CREAT | O_CLOEXEC, 0666));
|
||||
if (fd < 0) {
|
||||
return false;
|
||||
}
|
||||
return (close(fd) == 0);
|
||||
}
|
||||
|
||||
|
||||
bool File::CreateLink(const char* name, const char* target) {
|
||||
return NO_RETRY_EXPECTED(symlink(target, name)) == 0;
|
||||
}
|
||||
|
||||
|
||||
bool File::Delete(const char* name) {
|
||||
File::Type type = File::GetType(name, true);
|
||||
if (type == kIsFile) {
|
||||
return NO_RETRY_EXPECTED(unlink(name)) == 0;
|
||||
} else if (type == kIsDirectory) {
|
||||
errno = EISDIR;
|
||||
} else {
|
||||
errno = ENOENT;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool File::DeleteLink(const char* name) {
|
||||
File::Type type = File::GetType(name, false);
|
||||
if (type == kIsLink) {
|
||||
return NO_RETRY_EXPECTED(unlink(name)) == 0;
|
||||
}
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool File::Rename(const char* old_path, const char* new_path) {
|
||||
File::Type type = File::GetType(old_path, true);
|
||||
if (type == kIsFile) {
|
||||
return NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0;
|
||||
} else if (type == kIsDirectory) {
|
||||
errno = EISDIR;
|
||||
} else {
|
||||
errno = ENOENT;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool File::RenameLink(const char* old_path, const char* new_path) {
|
||||
File::Type type = File::GetType(old_path, false);
|
||||
if (type == kIsLink) {
|
||||
return NO_RETRY_EXPECTED(rename(old_path, new_path)) == 0;
|
||||
} else if (type == kIsDirectory) {
|
||||
errno = EISDIR;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool File::Copy(const char* old_path, const char* new_path) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int64_t File::LengthFromPath(const char* name) {
|
||||
struct stat st;
|
||||
if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
|
||||
return st.st_size;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void File::Stat(const char* name, int64_t* data) {
|
||||
struct stat st;
|
||||
if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
data[kType] = kIsFile;
|
||||
} else if (S_ISDIR(st.st_mode)) {
|
||||
data[kType] = kIsDirectory;
|
||||
} else if (S_ISLNK(st.st_mode)) {
|
||||
data[kType] = kIsLink;
|
||||
} else {
|
||||
data[kType] = kDoesNotExist;
|
||||
}
|
||||
data[kCreatedTime] = static_cast<int64_t>(st.st_ctime) * 1000;
|
||||
data[kModifiedTime] = static_cast<int64_t>(st.st_mtime) * 1000;
|
||||
data[kAccessedTime] = static_cast<int64_t>(st.st_atime) * 1000;
|
||||
data[kMode] = st.st_mode;
|
||||
data[kSize] = st.st_size;
|
||||
} else {
|
||||
data[kType] = kDoesNotExist;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
time_t File::LastModified(const char* name) {
|
||||
struct stat st;
|
||||
if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
|
||||
return st.st_mtime;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
const char* File::LinkTarget(const char* pathname) {
|
||||
struct stat link_stats;
|
||||
if (lstat(pathname, &link_stats) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (!S_ISLNK(link_stats.st_mode)) {
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
size_t target_size = link_stats.st_size;
|
||||
char* target_name = DartUtils::ScopedCString(target_size + 1);
|
||||
ASSERT(target_name != NULL);
|
||||
size_t read_size = readlink(pathname, target_name, target_size + 1);
|
||||
if (read_size != target_size) {
|
||||
return NULL;
|
||||
}
|
||||
target_name[target_size] = '\0';
|
||||
return target_name;
|
||||
}
|
||||
|
||||
|
||||
bool File::IsAbsolutePath(const char* pathname) {
|
||||
return ((pathname != NULL) && (pathname[0] == '/'));
|
||||
}
|
||||
|
||||
|
||||
const char* File::GetCanonicalPath(const char* pathname) {
|
||||
char* abs_path = NULL;
|
||||
if (pathname != NULL) {
|
||||
char* resolved_path = DartUtils::ScopedCString(PATH_MAX + 1);
|
||||
ASSERT(resolved_path != NULL);
|
||||
do {
|
||||
abs_path = realpath(pathname, resolved_path);
|
||||
} while ((abs_path == NULL) && (errno == EINTR));
|
||||
ASSERT((abs_path == NULL) || IsAbsolutePath(abs_path));
|
||||
ASSERT((abs_path == NULL) || (abs_path == resolved_path));
|
||||
}
|
||||
return abs_path;
|
||||
}
|
||||
|
||||
|
||||
const char* File::PathSeparator() {
|
||||
return "/";
|
||||
}
|
||||
|
||||
|
||||
const char* File::StringEscapedPathSeparator() {
|
||||
return "/";
|
||||
}
|
||||
|
||||
|
||||
File::StdioHandleType File::GetStdioHandleType(int fd) {
|
||||
ASSERT((0 <= fd) && (fd <= 2));
|
||||
struct stat buf;
|
||||
int result = fstat(fd, &buf);
|
||||
if (result == -1) {
|
||||
const int kBufferSize = 1024;
|
||||
char error_message[kBufferSize];
|
||||
Utils::StrError(errno, error_message, kBufferSize);
|
||||
FATAL2("Failed stat on file descriptor %d: %s", fd, error_message);
|
||||
}
|
||||
if (S_ISCHR(buf.st_mode)) {
|
||||
return kTerminal;
|
||||
}
|
||||
if (S_ISFIFO(buf.st_mode)) {
|
||||
return kPipe;
|
||||
}
|
||||
if (S_ISSOCK(buf.st_mode)) {
|
||||
return kSocket;
|
||||
}
|
||||
if (S_ISREG(buf.st_mode)) {
|
||||
return kFile;
|
||||
}
|
||||
return kOther;
|
||||
}
|
||||
|
||||
|
||||
File::Type File::GetType(const char* pathname, bool follow_links) {
|
||||
struct stat entry_info;
|
||||
int stat_success;
|
||||
if (follow_links) {
|
||||
stat_success = NO_RETRY_EXPECTED(stat(pathname, &entry_info));
|
||||
} else {
|
||||
stat_success = NO_RETRY_EXPECTED(lstat(pathname, &entry_info));
|
||||
}
|
||||
if (stat_success == -1) {
|
||||
return File::kDoesNotExist;
|
||||
}
|
||||
if (S_ISDIR(entry_info.st_mode)) {
|
||||
return File::kIsDirectory;
|
||||
}
|
||||
if (S_ISREG(entry_info.st_mode)) {
|
||||
return File::kIsFile;
|
||||
}
|
||||
if (S_ISLNK(entry_info.st_mode)) {
|
||||
return File::kIsLink;
|
||||
}
|
||||
return File::kDoesNotExist;
|
||||
}
|
||||
|
||||
|
||||
File::Identical File::AreIdentical(const char* file_1, const char* file_2) {
|
||||
struct stat file_1_info;
|
||||
struct stat file_2_info;
|
||||
if ((NO_RETRY_EXPECTED(lstat(file_1, &file_1_info)) == -1) ||
|
||||
(NO_RETRY_EXPECTED(lstat(file_2, &file_2_info)) == -1)) {
|
||||
return File::kError;
|
||||
}
|
||||
return ((file_1_info.st_ino == file_2_info.st_ino) &&
|
||||
(file_1_info.st_dev == file_2_info.st_dev)) ?
|
||||
File::kIdentical :
|
||||
File::kDifferent;
|
||||
}
|
||||
|
||||
} // namespace bin
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(TARGET_OS_FUCHSIA)
|
60
runtime/bin/file_system_watcher_fuchsia.cc
Normal file
60
runtime/bin/file_system_watcher_fuchsia.cc
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#if !defined(DART_IO_DISABLED)
|
||||
|
||||
#include "platform/globals.h"
|
||||
#if defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#include "bin/file_system_watcher.h"
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
Dart_Handle FileSystemWatcher::ReadEvents(intptr_t id, intptr_t path_id) {
|
||||
UNIMPLEMENTED();
|
||||
return DartUtils::NewDartOSError();
|
||||
}
|
||||
|
||||
|
||||
intptr_t FileSystemWatcher::GetSocketId(intptr_t id, intptr_t path_id) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool FileSystemWatcher::IsSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void FileSystemWatcher::UnwatchPath(intptr_t id, intptr_t path_id) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
intptr_t FileSystemWatcher::Init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void FileSystemWatcher::Close(intptr_t id) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
intptr_t FileSystemWatcher::WatchPath(intptr_t id,
|
||||
const char* path,
|
||||
int events,
|
||||
bool recursive) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace bin
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#endif // !defined(DART_IO_DISABLED)
|
|
@ -10,6 +10,8 @@
|
|||
'eventhandler.h',
|
||||
'eventhandler_android.cc',
|
||||
'eventhandler_android.h',
|
||||
'eventhandler_fuchsia.cc',
|
||||
'eventhandler_fuchsia.h',
|
||||
'eventhandler_linux.cc',
|
||||
'eventhandler_linux.h',
|
||||
'eventhandler_macos.cc',
|
||||
|
@ -20,6 +22,7 @@
|
|||
'file_system_watcher.cc',
|
||||
'file_system_watcher.h',
|
||||
'file_system_watcher_android.cc',
|
||||
'file_system_watcher_fuchsia.cc',
|
||||
'file_system_watcher_linux.cc',
|
||||
'file_system_watcher_macos.cc',
|
||||
'file_system_watcher_unsupported.cc',
|
||||
|
@ -35,6 +38,7 @@
|
|||
'platform.cc',
|
||||
'platform.h',
|
||||
'platform_android.cc',
|
||||
'platform_fuchsia.cc',
|
||||
'platform_linux.cc',
|
||||
'platform_macos.cc',
|
||||
'platform_unsupported.cc',
|
||||
|
@ -42,6 +46,7 @@
|
|||
'process.cc',
|
||||
'process.h',
|
||||
'process_android.cc',
|
||||
'process_fuchsia.cc',
|
||||
'process_linux.cc',
|
||||
'process_macos.cc',
|
||||
'process_unsupported.cc',
|
||||
|
@ -60,6 +65,8 @@
|
|||
'socket.h',
|
||||
'socket_android.cc',
|
||||
'socket_android.h',
|
||||
'socket_fuchsia.cc',
|
||||
'socket_fuchsia.h',
|
||||
'socket_linux.cc',
|
||||
'socket_linux.h',
|
||||
'socket_macos.cc',
|
||||
|
@ -70,6 +77,7 @@
|
|||
'stdio.cc',
|
||||
'stdio.h',
|
||||
'stdio_android.cc',
|
||||
'stdio_fuchsia.cc',
|
||||
'stdio_linux.cc',
|
||||
'stdio_macos.cc',
|
||||
'stdio_unsupported.cc',
|
||||
|
|
|
@ -1499,7 +1499,7 @@ bool RunMainIsolate(const char* script_name,
|
|||
|
||||
|
||||
// Observatory assets are only needed in the regular dart binary.
|
||||
#if !defined(DART_PRECOMPILER)
|
||||
#if !defined(DART_PRECOMPILER) || !defined(NO_OBSERVATORY)
|
||||
extern unsigned int observatory_assets_archive_len;
|
||||
extern const uint8_t* observatory_assets_archive;
|
||||
|
||||
|
|
75
runtime/bin/platform_fuchsia.cc
Normal file
75
runtime/bin/platform_fuchsia.cc
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#include "platform/globals.h"
|
||||
#if defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#include "bin/platform.h"
|
||||
|
||||
#include <runtime/sysinfo.h>
|
||||
#include <string.h> // NOLINT
|
||||
#include <unistd.h> // NOLINT
|
||||
|
||||
#include "bin/fdutils.h"
|
||||
#include "bin/file.h"
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
const char* Platform::executable_name_ = NULL;
|
||||
char* Platform::resolved_executable_name_ = NULL;
|
||||
int Platform::script_index_ = 1;
|
||||
char** Platform::argv_ = NULL;
|
||||
|
||||
bool Platform::Initialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int Platform::NumberOfProcessors() {
|
||||
return mxr_get_nprocs();
|
||||
}
|
||||
|
||||
|
||||
const char* Platform::OperatingSystem() {
|
||||
return "fuchsia";
|
||||
}
|
||||
|
||||
|
||||
const char* Platform::LibraryPrefix() {
|
||||
return "lib";
|
||||
}
|
||||
|
||||
|
||||
const char* Platform::LibraryExtension() {
|
||||
return "so";
|
||||
}
|
||||
|
||||
|
||||
bool Platform::LocalHostname(char *buffer, intptr_t buffer_length) {
|
||||
return gethostname(buffer, buffer_length) == 0;
|
||||
}
|
||||
|
||||
|
||||
char** Platform::Environment(intptr_t* count) {
|
||||
char** result =
|
||||
reinterpret_cast<char**>(Dart_ScopeAllocate(1 * sizeof(*result)));
|
||||
result[0] = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
const char* Platform::ResolveExecutablePath() {
|
||||
return "dart";
|
||||
}
|
||||
|
||||
|
||||
void Platform::Exit(int exit_code) {
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
} // namespace bin
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(TARGET_OS_FUCHSIA)
|
77
runtime/bin/process_fuchsia.cc
Normal file
77
runtime/bin/process_fuchsia.cc
Normal file
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#if !defined(DART_IO_DISABLED)
|
||||
|
||||
#include "platform/globals.h"
|
||||
#if defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#include "bin/process.h"
|
||||
|
||||
#include "bin/lockers.h"
|
||||
#include "platform/assert.h"
|
||||
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
int Process::global_exit_code_ = 0;
|
||||
Mutex* Process::global_exit_code_mutex_ = new Mutex();
|
||||
|
||||
void Process::TerminateExitCodeHandler() {
|
||||
}
|
||||
|
||||
intptr_t Process::CurrentProcessId() {
|
||||
UNIMPLEMENTED();
|
||||
return 0;
|
||||
}
|
||||
|
||||
intptr_t Process::SetSignalHandler(intptr_t signal) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void Process::ClearSignalHandler(intptr_t signal) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
bool Process::Wait(intptr_t pid,
|
||||
intptr_t in,
|
||||
intptr_t out,
|
||||
intptr_t err,
|
||||
intptr_t exit_event,
|
||||
ProcessResult* result) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Process::Kill(intptr_t id, int signal) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
int Process::Start(const char* path,
|
||||
char* arguments[],
|
||||
intptr_t arguments_length,
|
||||
const char* working_directory,
|
||||
char* environment[],
|
||||
intptr_t environment_length,
|
||||
ProcessStartMode mode,
|
||||
intptr_t* in,
|
||||
intptr_t* out,
|
||||
intptr_t* err,
|
||||
intptr_t* id,
|
||||
intptr_t* exit_event,
|
||||
char** os_error_message) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace bin
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#endif // !defined(DART_IO_DISABLED)
|
|
@ -13,6 +13,8 @@
|
|||
// Declare the OS-specific types ahead of defining the generic class.
|
||||
#if defined(TARGET_OS_ANDROID)
|
||||
#include "bin/socket_android.h"
|
||||
#elif defined(TARGET_OS_FUCHSIA)
|
||||
#include "bin/socket_fuchsia.h"
|
||||
#elif defined(TARGET_OS_LINUX)
|
||||
#include "bin/socket_linux.h"
|
||||
#elif defined(TARGET_OS_MACOS)
|
||||
|
|
242
runtime/bin/socket_fuchsia.cc
Normal file
242
runtime/bin/socket_fuchsia.cc
Normal file
|
@ -0,0 +1,242 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#if !defined(DART_IO_DISABLED)
|
||||
|
||||
#include "platform/globals.h"
|
||||
#if defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#include "bin/socket.h"
|
||||
#include "bin/socket_fuchsia.h"
|
||||
|
||||
#include "bin/file.h"
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
SocketAddress::SocketAddress(struct sockaddr* sa) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
bool Socket::FormatNumericAddress(const RawAddr& addr, char* address, int len) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Socket::Initialize() {
|
||||
UNIMPLEMENTED();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
intptr_t Socket::CreateConnect(const RawAddr& addr) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
intptr_t Socket::CreateBindConnect(const RawAddr& addr,
|
||||
const RawAddr& source_addr) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
intptr_t Socket::Available(intptr_t fd) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
intptr_t Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
intptr_t Socket::RecvFrom(
|
||||
intptr_t fd, void* buffer, intptr_t num_bytes, RawAddr* addr) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
intptr_t Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
intptr_t Socket::SendTo(
|
||||
intptr_t fd, const void* buffer, intptr_t num_bytes, const RawAddr& addr) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
intptr_t Socket::GetPort(intptr_t fd) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
SocketAddress* Socket::GetRemotePeer(intptr_t fd, intptr_t* port) {
|
||||
UNIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void Socket::GetError(intptr_t fd, OSError* os_error) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
int Socket::GetType(intptr_t fd) {
|
||||
UNIMPLEMENTED();
|
||||
return File::kOther;
|
||||
}
|
||||
|
||||
|
||||
intptr_t Socket::GetStdioHandle(intptr_t num) {
|
||||
UNIMPLEMENTED();
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
AddressList<SocketAddress>* Socket::LookupAddress(const char* host,
|
||||
int type,
|
||||
OSError** os_error) {
|
||||
UNIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool Socket::ReverseLookup(const RawAddr& addr,
|
||||
char* host,
|
||||
intptr_t host_len,
|
||||
OSError** os_error) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Socket::ParseAddress(int type, const char* address, RawAddr* addr) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
intptr_t Socket::CreateBindDatagram(const RawAddr& addr, bool reuseAddress) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool Socket::ListInterfacesSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
AddressList<InterfaceSocketAddress>* Socket::ListInterfaces(
|
||||
int type,
|
||||
OSError** os_error) {
|
||||
UNIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
intptr_t ServerSocket::CreateBindListen(const RawAddr& addr,
|
||||
intptr_t backlog,
|
||||
bool v6_only) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool ServerSocket::StartAccept(intptr_t fd) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
intptr_t ServerSocket::Accept(intptr_t fd) {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void Socket::Close(intptr_t fd) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
bool Socket::GetNoDelay(intptr_t fd, bool* enabled) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Socket::SetNoDelay(intptr_t fd, bool enabled) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Socket::GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Socket::SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Socket::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Socket::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Socket::GetBroadcast(intptr_t fd, bool* enabled) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Socket::SetBroadcast(intptr_t fd, bool enabled) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Socket::JoinMulticast(
|
||||
intptr_t fd, const RawAddr& addr, const RawAddr&, int interfaceIndex) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Socket::LeaveMulticast(
|
||||
intptr_t fd, const RawAddr& addr, const RawAddr&, int interfaceIndex) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace bin
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#endif // !defined(DART_IO_DISABLED)
|
12
runtime/bin/socket_fuchsia.h
Normal file
12
runtime/bin/socket_fuchsia.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef BIN_SOCKET_FUCHSIA_H_
|
||||
#define BIN_SOCKET_FUCHSIA_H_
|
||||
|
||||
#if !defined(BIN_SOCKET_H_)
|
||||
#error Do not include socket_fuchsia.h directly. Use socket.h.
|
||||
#endif
|
||||
|
||||
#endif // BIN_SOCKET_FUCHSIA_H_
|
53
runtime/bin/stdio_fuchsia.cc
Normal file
53
runtime/bin/stdio_fuchsia.cc
Normal file
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#if !defined(DART_IO_DISABLED)
|
||||
|
||||
#include "platform/globals.h"
|
||||
#if defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#include "bin/stdio.h"
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
int Stdin::ReadByte() {
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool Stdin::GetEchoMode() {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Stdin::SetEchoMode(bool enabled) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
bool Stdin::GetLineMode() {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Stdin::SetLineMode(bool enabled) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
bool Stdout::GetTerminalSize(intptr_t fd, int size[2]) {
|
||||
UNIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace bin
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#endif // !defined(DART_IO_DISABLED)
|
99
runtime/bin/utils_fuchsia.cc
Normal file
99
runtime/bin/utils_fuchsia.cc
Normal file
|
@ -0,0 +1,99 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#include "platform/globals.h"
|
||||
#if defined(TARGET_OS_FUCHSIA)
|
||||
|
||||
#include <errno.h>
|
||||
#include <magenta/syscalls.h>
|
||||
#include <magenta/types.h>
|
||||
|
||||
#include "bin/utils.h"
|
||||
#include "platform/assert.h"
|
||||
#include "platform/utils.h"
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
OSError::OSError() : sub_system_(kSystem), code_(0), message_(NULL) {
|
||||
set_sub_system(kSystem);
|
||||
set_code(errno);
|
||||
const int kBufferSize = 1024;
|
||||
char error_buf[kBufferSize];
|
||||
SetMessage(Utils::StrError(errno, error_buf, kBufferSize));
|
||||
}
|
||||
|
||||
|
||||
void OSError::SetCodeAndMessage(SubSystem sub_system, int code) {
|
||||
set_sub_system(sub_system);
|
||||
set_code(code);
|
||||
if (sub_system == kSystem) {
|
||||
const int kBufferSize = 1024;
|
||||
char error_buf[kBufferSize];
|
||||
SetMessage(Utils::StrError(code, error_buf, kBufferSize));
|
||||
} else if (sub_system == kGetAddressInfo) {
|
||||
UNIMPLEMENTED();
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char* StringUtils::ConsoleStringToUtf8(
|
||||
const char* str, intptr_t len, intptr_t* result_len) {
|
||||
UNIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const char* StringUtils::Utf8ToConsoleString(
|
||||
const char* utf8, intptr_t len, intptr_t* result_len) {
|
||||
UNIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char* StringUtils::ConsoleStringToUtf8(
|
||||
char* str, intptr_t len, intptr_t* result_len) {
|
||||
UNIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char* StringUtils::Utf8ToConsoleString(
|
||||
char* utf8, intptr_t len, intptr_t* result_len) {
|
||||
UNIMPLEMENTED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void TimerUtils::InitOnce() {
|
||||
}
|
||||
|
||||
|
||||
int64_t TimerUtils::GetCurrentMonotonicMillis() {
|
||||
return GetCurrentMonotonicMicros() / 1000;
|
||||
}
|
||||
|
||||
|
||||
int64_t TimerUtils::GetCurrentMonotonicMicros() {
|
||||
int64_t ticks = mx_current_time();
|
||||
return ticks / kNanosecondsPerMicrosecond;
|
||||
}
|
||||
|
||||
|
||||
void TimerUtils::Sleep(int64_t millis) {
|
||||
mx_nanosleep(
|
||||
millis * kMicrosecondsPerMillisecond * kNanosecondsPerMicrosecond);
|
||||
}
|
||||
|
||||
} // namespace bin
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined(TARGET_OS_FUCHSIA)
|
|
@ -22,6 +22,7 @@ bool _autoStart;
|
|||
// Should the HTTP server run in devmode?
|
||||
bool _originCheckDisabled;
|
||||
bool _isWindows = false;
|
||||
bool _isFuchsia = false;
|
||||
var _signalWatch;
|
||||
var _signalSubscription;
|
||||
|
||||
|
@ -177,8 +178,8 @@ _registerSignalHandler() {
|
|||
// Cannot register for signals.
|
||||
return;
|
||||
}
|
||||
if (_isWindows) {
|
||||
// Cannot register for signals on Windows.
|
||||
if (_isWindows || _isFuchsia) {
|
||||
// Cannot register for signals on Windows or Fuchsia.
|
||||
return;
|
||||
}
|
||||
_signalSubscription = _signalWatch(ProcessSignal.SIGQUIT).listen(_onSignal);
|
||||
|
|
|
@ -256,6 +256,16 @@ bool VmService::Setup(const char* server_ip,
|
|||
Dart_SetField(library, DartUtils::NewString("_isWindows"), is_windows);
|
||||
SHUTDOWN_ON_ERROR(result);
|
||||
|
||||
// Are we running on Fuchsia?
|
||||
#if defined(TARGET_OS_FUCHSIA)
|
||||
Dart_Handle is_fuchsia = Dart_True();
|
||||
#else
|
||||
Dart_Handle is_fuchsia = Dart_False();
|
||||
#endif
|
||||
result =
|
||||
Dart_SetField(library, DartUtils::NewString("_isFuchsia"), is_fuchsia);
|
||||
SHUTDOWN_ON_ERROR(result);
|
||||
|
||||
// Get _getWatchSignalInternal from dart:io.
|
||||
Dart_Handle dart_io_str = Dart_NewStringFromCString(DartUtils::kIOLibURL);
|
||||
SHUTDOWN_ON_ERROR(dart_io_str);
|
||||
|
|
|
@ -68,8 +68,8 @@ inline uint64_t Utils::HostToLittleEndian64(uint64_t value) {
|
|||
|
||||
|
||||
inline char* Utils::StrError(int err, char* buffer, size_t bufsize) {
|
||||
UNIMPLEMENTED();
|
||||
return NULL;
|
||||
snprintf(buffer, bufsize, "errno = %d", err);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
|
7
runtime/tests/vm/dart/hello_fuchsia_test.dart
Normal file
7
runtime/tests/vm/dart/hello_fuchsia_test.dart
Normal file
|
@ -0,0 +1,7 @@
|
|||
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
main() {
|
||||
print("Hello, Fuchsia!");
|
||||
}
|
Loading…
Reference in a new issue