diff --git a/shell/platform/fuchsia/dart-pkg/zircon/BUILD.gn b/shell/platform/fuchsia/dart-pkg/zircon/BUILD.gn index 39329c34cee50..ae8aa96b80398 100644 --- a/shell/platform/fuchsia/dart-pkg/zircon/BUILD.gn +++ b/shell/platform/fuchsia/dart-pkg/zircon/BUILD.gn @@ -26,6 +26,7 @@ source_set("zircon") { ] deps = [ + "$fuchsia_sdk_root/fidl:fuchsia.io", "$fuchsia_sdk_root/pkg:async-cpp", "$fuchsia_sdk_root/pkg:async-default", "$fuchsia_sdk_root/pkg:async-loop-cpp", diff --git a/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/system.cc b/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/system.cc index b455909feb5b1..cdb51c1ad7987 100644 --- a/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/system.cc +++ b/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/system.cc @@ -6,8 +6,9 @@ #include -#include +#include #include +#include #include #include #include @@ -172,17 +173,25 @@ fdio_ns_t* GetNamespace() { return reinterpret_cast(fdio_ns_ptr); } -fml::UniqueFD FdFromPath(std::string path) { - // Get a VMO for the file. - fdio_ns_t* ns = reinterpret_cast(GetNamespace()); - fml::UniqueFD dirfd(fdio_ns_opendir(ns)); - if (!dirfd.is_valid()) - return fml::UniqueFD(); - - const char* c_path = path.c_str(); - if (path.length() > 0 && c_path[0] == '/') - c_path = &c_path[1]; - return fml::UniqueFD(openat(dirfd.get(), c_path, O_RDONLY)); +zx_status_t FdFromPath(const char* path, fml::UniqueFD& fd) { + fml::UniqueFD dir_fd(fdio_ns_opendir(GetNamespace())); + if (!dir_fd.is_valid()) { + // TODO: can we return errno? + return ZX_ERR_IO; + } + if (path != nullptr && *path == '/') { + path++; + } + int raw_fd; + if (zx_status_t status = fdio_open_fd_at( + dir_fd.get(), path, + static_cast(fuchsia::io::OpenFlags::RIGHT_READABLE), + &raw_fd); + status != ZX_OK) { + return status; + } + fd.reset(raw_fd); + return ZX_OK; } } // namespace @@ -207,36 +216,30 @@ zx_status_t System::ConnectToService(std::string path, channel->ReleaseHandle()); } -zx::channel System::CloneChannelFromFileDescriptor(int fd) { - zx::handle handle; - zx_status_t status = fdio_fd_clone(fd, handle.reset_and_get_address()); - if (status != ZX_OK) - return zx::channel(); - - zx_info_handle_basic_t info = {}; - status = - handle.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), NULL, NULL); - - if (status != ZX_OK || info.type != ZX_OBJ_TYPE_CHANNEL) - return zx::channel(); - - return zx::channel(handle.release()); -} - Dart_Handle System::ChannelFromFile(std::string path) { - fml::UniqueFD fd = FdFromPath(path); - if (!fd.is_valid()) { - return ConstructDartObject(kHandleResult, ToDart(ZX_ERR_IO)); + fml::UniqueFD fd; + if (zx_status_t status = FdFromPath(path.c_str(), fd); status != ZX_OK) { + return ConstructDartObject(kHandleResult, ToDart(status)); } - // Get channel from fd. - zx::channel channel = CloneChannelFromFileDescriptor(fd.get()); - if (!channel) { - return ConstructDartObject(kHandleResult, ToDart(ZX_ERR_IO)); + zx::handle handle; + if (zx_status_t status = + fdio_fd_transfer(fd.release(), handle.reset_and_get_address()); + status != ZX_OK) { + return ConstructDartObject(kHandleResult, ToDart(status)); + } + zx_info_handle_basic_t info; + if (zx_status_t status = handle.get_info(ZX_INFO_HANDLE_BASIC, &info, + sizeof(info), nullptr, nullptr); + status != ZX_OK) { + return ConstructDartObject(kHandleResult, ToDart(status)); + } + if (info.type != ZX_OBJ_TYPE_CHANNEL) { + return ConstructDartObject(kHandleResult, ToDart(ZX_ERR_WRONG_TYPE)); } return ConstructDartObject(kHandleResult, ToDart(ZX_OK), - ToDart(Handle::Create(channel.release()))); + ToDart(Handle::Create(handle.release()))); } zx_status_t System::ChannelWrite(fml::RefPtr channel, @@ -451,20 +454,25 @@ Dart_Handle System::VmoCreate(uint64_t size, uint32_t options) { } Dart_Handle System::VmoFromFile(std::string path) { - fml::UniqueFD fd = FdFromPath(path); - if (!fd.is_valid()) - return ConstructDartObject(kFromFileResult, ToDart(ZX_ERR_IO)); + fml::UniqueFD fd; + if (zx_status_t status = FdFromPath(path.c_str(), fd); status != ZX_OK) { + return ConstructDartObject(kHandleResult, ToDart(status)); + } struct stat stat_struct; - if (fstat(fd.get(), &stat_struct) == -1) + if (fstat(fd.get(), &stat_struct) != 0) { + // TODO: can we return errno? return ConstructDartObject(kFromFileResult, ToDart(ZX_ERR_IO)); - zx_handle_t vmo = ZX_HANDLE_INVALID; - zx_status_t status = fdio_get_vmo_clone(fd.get(), &vmo); - if (status != ZX_OK) + } + zx::vmo vmo; + if (zx_status_t status = + fdio_get_vmo_clone(fd.get(), vmo.reset_and_get_address()); + status != ZX_OK) { return ConstructDartObject(kFromFileResult, ToDart(status)); + } - return ConstructDartObject(kFromFileResult, ToDart(status), - ToDart(Handle::Create(vmo)), + return ConstructDartObject(kFromFileResult, ToDart(ZX_OK), + ToDart(Handle::Create(vmo.release())), ToDart(stat_struct.st_size)); } diff --git a/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/system.h b/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/system.h index f5b8abbd4783c..ba5adba05e637 100644 --- a/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/system.h +++ b/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/system.h @@ -76,8 +76,6 @@ class System : public fml::RefCountedThreadSafe, private: static void VmoMapFinalizer(void* isolate_callback_data, void* peer); - - static zx::channel CloneChannelFromFileDescriptor(int fd); }; } // namespace dart