|  | // Copyright 2019 The Fuchsia Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include <dirent.h> | 
|  | #include <fuchsia/io/cpp/fidl.h> | 
|  | #include <lib/fdio/directory.h> | 
|  | #include <lib/fit/defer.h> | 
|  | #include <lib/sys/service/cpp/service_aggregate.h> | 
|  |  | 
|  | #include <vector> | 
|  |  | 
|  | namespace sys { | 
|  |  | 
|  | std::vector<std::string> ServiceAggregateBase::ListInstances() const { | 
|  | std::vector<std::string> instances; | 
|  |  | 
|  | int fd; | 
|  | zx_status_t status = fdio_fd_create(fdio_service_clone(dir_.channel().get()), &fd); | 
|  | if (status != ZX_OK) { | 
|  | return instances; | 
|  | } | 
|  | auto defer_close = fit::defer([fd] { close(fd); }); | 
|  |  | 
|  | DIR* dir = fdopendir(fd); | 
|  | if (dir == nullptr) { | 
|  | return instances; | 
|  | } | 
|  | auto defer_closedir = fit::defer([dir] { closedir(dir); }); | 
|  |  | 
|  | for (dirent* entry; (entry = readdir(dir)) != nullptr;) { | 
|  | if (strcmp(entry->d_name, ".") != 0) { | 
|  | instances.emplace_back(entry->d_name); | 
|  | } | 
|  | } | 
|  |  | 
|  | return instances; | 
|  | } | 
|  |  | 
|  | fidl::InterfaceHandle<fuchsia::io::Directory> OpenNamedServiceAggregateAt( | 
|  | const fidl::InterfaceHandle<fuchsia::io::Directory>& handle, const std::string& service_path) { | 
|  | if (service_path.compare(0, 1, "/") == 0) { | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | fidl::InterfaceHandle<fuchsia::io::Directory> dir; | 
|  | zx_status_t status = fdio_service_connect_at(handle.channel().get(), service_path.data(), | 
|  | dir.NewRequest().TakeChannel().release()); | 
|  | if (status != ZX_OK) { | 
|  | return nullptr; | 
|  | } | 
|  | return dir; | 
|  | } | 
|  |  | 
|  | fidl::InterfaceHandle<fuchsia::io::Directory> OpenNamedServiceAggregateIn( | 
|  | fdio_ns_t* ns, const std::string& service_path) { | 
|  | std::string path; | 
|  | if (service_path.compare(0, 1, "/") != 0) { | 
|  | path = "/svc/"; | 
|  | } | 
|  | path += service_path; | 
|  |  | 
|  | fidl::InterfaceHandle<fuchsia::io::Directory> dir; | 
|  | zx_status_t status = fdio_ns_connect(ns, path.data(), fuchsia::io::OPEN_RIGHT_READABLE, | 
|  | dir.NewRequest().TakeChannel().release()); | 
|  | if (status != ZX_OK) { | 
|  | return nullptr; | 
|  | } | 
|  | return dir; | 
|  | } | 
|  |  | 
|  | fidl::InterfaceHandle<fuchsia::io::Directory> OpenNamedServiceAggregate( | 
|  | const std::string& service_path) { | 
|  | fdio_ns_t* ns; | 
|  | zx_status_t status = fdio_ns_get_installed(&ns); | 
|  | if (status != ZX_OK) { | 
|  | return nullptr; | 
|  | } | 
|  | return OpenNamedServiceAggregateIn(ns, service_path); | 
|  | } | 
|  |  | 
|  | }  // namespace sys |