blob: 33c3294d5a276b3960c83106b13c1cf14482e0e8 [file] [log] [blame]
// Copyright 2022 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 <fidl/fuchsia.process.lifecycle/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/component/outgoing/cpp/outgoing_directory.h>
#include <lib/fdio/namespace.h>
#include <lib/fit/defer.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <unordered_set>
#include "src/lib/fxl/strings/join_strings.h"
int main(int argc, const char** argv) {
fidl::ServerEnd<fuchsia_process_lifecycle::Lifecycle> component_lifecycle_request(
zx::channel(zx_take_startup_handle(PA_LIFECYCLE)));
if (!component_lifecycle_request.is_valid()) {
FX_SLOG(FATAL, "No valid handle found for lifecycle events");
}
if (zx::result result = component::Connect(std::move(component_lifecycle_request),
"/svc/fuchsia.device.fs.lifecycle.Lifecycle");
result.is_error()) {
// TODO(https://fxbug.dev/42052807): Standardize status emission.
FX_SLOG(FATAL, "Failed to connect to fuchsia.device.fs.lifecycle",
FX_KV("status", result.status_string()));
}
async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
component::OutgoingDirectory outgoing(loop.dispatcher());
{
fdio_flat_namespace_t* ns;
if (zx_status_t status = fdio_ns_export_root(&ns); status != ZX_OK) {
// TODO(https://fxbug.dev/42052807): Standardize status emission.
FX_SLOG(FATAL, "Failed to export flat namespace",
FX_KV("status", zx_status_get_string(status)));
}
const fit::deferred_action cleanup = fit::defer([ns]() { fdio_ns_free_flat_ns(ns); });
// Expose expected entries and error if any remain unexposed.
std::unordered_set<std::string_view> expose = {"dev"};
for (size_t i = 0; i < ns->count; ++i) {
std::string_view path{ns->path[i]};
// Leading slashes are not allowed.
if (cpp20::starts_with(path, '/')) {
path.remove_prefix(1);
}
if (auto nh = expose.extract(path); nh.empty()) {
continue;
}
// Ensure the handle isn't closed when the namespace is freed.
zx_handle_t handle = std::exchange(ns->handle[i], ZX_HANDLE_INVALID);
fidl::ClientEnd<fuchsia_io::Directory> client_end{zx::channel{handle}};
if (zx::result result = outgoing.AddDirectory(std::move(client_end), path);
result.is_error()) {
// TODO(https://fxbug.dev/42052807): Standardize status emission.
FX_SLOG(FATAL, "Failed to expose", FX_KV("path", path),
FX_KV("status", result.status_string()));
}
}
if (!expose.empty()) {
const std::string missing = fxl::JoinStrings(expose, ",");
FX_SLOG(FATAL, "Failed to expose all entries", FX_KV("missing", missing));
}
}
if (zx::result result = outgoing.ServeFromStartupInfo(); result.is_error()) {
// TODO(https://fxbug.dev/42052807): Standardize status emission.
FX_SLOG(FATAL, "Failed to serve from startup info", FX_KV("status", result.status_string()));
}
FX_SLOG(DEBUG, "Initialized.");
if (zx_status_t status = loop.Run(); status != ZX_OK) {
// TODO(https://fxbug.dev/42052807): Standardize status emission.
FX_SLOG(FATAL, "Failed to run async loop", FX_KV("status", zx_status_get_string(status)));
}
return 0;
}