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:
Zachary Anderson 2016-07-22 14:00:31 -07:00
parent 5680532769
commit 53374c3b99
23 changed files with 1593 additions and 11 deletions

View file

@ -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

View file

@ -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',

View 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)

View 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)

View file

@ -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)

View 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)

View 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_

View 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
View 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)

View 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)

View file

@ -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',

View file

@ -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;

View 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)

View 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)

View file

@ -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)

View 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)

View 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_

View 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)

View 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)

View file

@ -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);

View file

@ -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);

View file

@ -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

View 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!");
}