// Copyright 2016 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 "fs-manager.h"

#include <fcntl.h>
#include <fuchsia/fshost/llcpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/wait.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/io.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zircon-internal/debug.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <threads.h>
#include <zircon/device/vfs.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

#include <iterator>
#include <memory>
#include <string_view>
#include <utility>

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_lock.h>
#include <fs/remote_dir.h>
#include <fs/vfs.h>
#include <fs/vfs_types.h>

#include "admin-server.h"
#include "block-watcher.h"
#include "fshost-boot-args.h"
#include "lib/async/cpp/task.h"
#include "lifecycle.h"
#include "metrics.h"

#define ZXDEBUG 0

namespace devmgr {

FsManager::FsManager(std::shared_ptr<FshostBootArgs> boot_args,
                     std::unique_ptr<FsHostMetrics> metrics)
    : global_loop_(new async::Loop(&kAsyncLoopConfigNoAttachToCurrentThread)),
      outgoing_vfs_(fs::ManagedVfs(global_loop_->dispatcher())),
      registry_(global_loop_.get()),
      metrics_(std::move(metrics)),
      boot_args_(boot_args) {
  ZX_ASSERT(global_root_ == nullptr);
}

// In the event that we haven't been explicitly signalled, tear ourself down.
FsManager::~FsManager() {
  if (global_shutdown_.has_handler()) {
    event_.signal(0, FSHOST_SIGNAL_EXIT);
    auto deadline = zx::deadline_after(zx::sec(2));
    zx_signals_t pending;
    event_.wait_one(FSHOST_SIGNAL_EXIT_DONE, deadline, &pending);
  }
  sync_completion_t sync;
  outgoing_vfs_.Shutdown([&](zx_status_t status) { sync_completion_signal(&sync); });
  sync_completion_wait(&sync, ZX_TIME_INFINITE);
  // Ensure all asynchronous work on global_loop_ finishes.
  // Some of the asynchronous work references memory owned by this instance, so we need to ensure
  // the work is complete before destruction.
  // TODO(sdemos): Clean up ordering of fields to let the natural destructor ordering handle
  // shutdown.
  global_loop_->Shutdown();
}

zx_status_t FsManager::SetupLifecycleServer(zx::channel lifecycle_request) {
  return devmgr::LifecycleServer::Create(global_loop_->dispatcher(), this,
                                         std::move(lifecycle_request));
}

// Sets up the outgoing directory, and runs it on the PA_DIRECTORY_REQUEST
// handle if it exists. See fshost.cml for a list of what's in the directory.
zx_status_t FsManager::SetupOutgoingDirectory(zx::channel dir_request,
                                              std::shared_ptr<loader::LoaderServiceBase> loader,
                                              BlockWatcher& watcher) {
  auto outgoing_dir = fbl::MakeRefCounted<fs::PseudoDir>();

  // TODO(unknown): fshost exposes two separate service directories, one here and one in
  // the registry vfs that's mounted under fs-manager-svc further down in this
  // function. These should be combined by either pulling the registry services
  // into this VFS or by pushing the services in this directory into the
  // registry.

  // Add loader and admin services to the vfs
  auto svc_dir = fbl::MakeRefCounted<fs::PseudoDir>();
  // This service name is breaking the convention whereby the directory entry
  // name matches the protocol name. This is an implementation of
  // fuchsia.ldsvc.Loader, and is renamed to make it easier to identify that
  // this implementation comes from fshost.
  svc_dir->AddEntry(
      "fuchsia.fshost.Loader", fbl::MakeRefCounted<fs::Service>([loader](zx::channel chan) {
        auto status = loader->Bind(std::move(chan));
        if (status.is_error()) {
          FX_LOGS(ERROR) << "failed to attach loader service: " << status.status_string();
        }
        return status.status_value();
      }));
  svc_dir->AddEntry(llcpp::fuchsia::fshost::Admin::Name,
                    AdminServer::Create(this, global_loop_->dispatcher()));

  svc_dir->AddEntry(llcpp::fuchsia::fshost::BlockWatcher::Name,
                    BlockWatcherServer::Create(global_loop_->dispatcher(), watcher));

  outgoing_dir->AddEntry("svc", std::move(svc_dir));

  // Add /fs to the outgoing vfs
  zx::channel filesystems_client, filesystems_server;
  zx_status_t status = zx::channel::create(0, &filesystems_client, &filesystems_server);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to create channel";
    return status;
  }
  status = this->ServeRoot(std::move(filesystems_server));
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Cannot serve root filesystem";
    return status;
  }
  outgoing_dir->AddEntry("fs", fbl::MakeRefCounted<fs::RemoteDir>(std::move(filesystems_client)));

  // Add /fs-manager-svc to the vfs
  zx::channel services_client, services_server;
  status = zx::channel::create(0, &services_client, &services_server);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to create channel";
    return status;
  }
  status = this->ServeFshostRoot(std::move(services_server));
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Cannot serve export directory";
    return status;
  }
  outgoing_dir->AddEntry("fs-manager-svc",
                         fbl::MakeRefCounted<fs::RemoteDir>(std::move(services_client)));

  // TODO(fxbug.dev/39588): delete this
  // Add the delayed directory
  zx::channel filesystems_client_2, filesystems_server_2;
  status = zx::channel::create(0, &filesystems_client_2, &filesystems_server_2);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to create channel";
    return status;
  }
  status = this->ServeRoot(std::move(filesystems_server_2));
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "cannot serve root filesystem";
    return status;
  }
  outgoing_dir->AddEntry("delayed", delayed_outdir_.Initialize(std::move(filesystems_client_2)));

  // Add the diagnostics directory
  diagnostics_dir_ = inspect_.Initialize(global_loop_->dispatcher());
  outgoing_dir->AddEntry("diagnostics", diagnostics_dir_);

  // Run the outgoing directory
  outgoing_vfs_.ServeDirectory(outgoing_dir, std::move(dir_request));
  return ZX_OK;
}

zx_status_t FsManager::Initialize(zx::channel dir_request, zx::channel lifecycle_request,
                                  std::shared_ptr<loader::LoaderServiceBase> loader,
                                  BlockWatcher& watcher) {
  zx_status_t status = memfs::Vfs::Create("<root>", &root_vfs_, &global_root_);
  if (status != ZX_OK) {
    return status;
  }

  fbl::RefPtr<fs::Vnode> vn;
  if ((status = global_root_->Create("boot", S_IFDIR, &vn)) != ZX_OK) {
    return status;
  }
  if ((status = global_root_->Create("tmp", S_IFDIR, &vn)) != ZX_OK) {
    return status;
  }
  for (unsigned n = 0; n < std::size(kMountPoints); n++) {
    auto open_result = root_vfs_->Open(global_root_, std::string_view(kMountPoints[n]),
                                       fs::VnodeConnectionOptions::ReadWrite().set_create(),
                                       fs::Rights::ReadWrite(), S_IFDIR);
    if (open_result.is_error()) {
      return open_result.error();
    }

    ZX_ASSERT(open_result.is_ok());
    mount_nodes[n] = std::move(open_result.ok().vnode);
  }

  auto open_result =
      root_vfs_->Open(global_root_, std::string_view("/data"),
                      fs::VnodeConnectionOptions::ReadOnly(), fs::Rights::ReadOnly(), S_IFDIR);
  if (open_result.is_ok()) {
    inspect_.ServeStats("data", open_result.ok().vnode);
  } else {
    FX_LOGS(ERROR) << "failed to serve /data stats";
  }

  status = zx::event::create(0, &event_);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to create fs-manager event: " << status;
    return status;
  }

  global_loop_->StartThread("root-dispatcher");
  root_vfs_->SetDispatcher(global_loop_->dispatcher());
  if (dir_request.is_valid()) {
    status = SetupOutgoingDirectory(std::move(dir_request), std::move(loader), watcher);
    if (status != ZX_OK) {
      return status;
    }
  }
  if (lifecycle_request.is_valid()) {
    status = SetupLifecycleServer(std::move(lifecycle_request));
    if (status != ZX_OK) {
      return status;
    }
  }
  return ZX_OK;
}

void FsManager::FlushMetrics() { mutable_metrics()->Flush(); }

zx_status_t FsManager::InstallFs(const char* path, zx::channel h) {
  for (unsigned n = 0; n < std::size(kMountPoints); n++) {
    if (!strcmp(path, kMountPoints[n])) {
      return root_vfs_->InstallRemote(mount_nodes[n], fs::MountChannel(std::move(h)));
    }
  }
  return ZX_ERR_NOT_FOUND;
}

zx_status_t FsManager::ServeRoot(zx::channel server) {
  fs::Rights rights;
  rights.read = true;
  rights.write = true;
  rights.admin = true;
  rights.execute = true;
  return root_vfs_->ServeDirectory(global_root_, std::move(server), rights);
}

void FsManager::WatchExit() {
  FX_LOGS(INFO) << "watching for exit";
  global_shutdown_.set_handler([this](async_dispatcher_t* dispatcher, async::Wait* wait,
                                      zx_status_t status, const zx_packet_signal_t* signal) {
    FX_LOGS(INFO) << "exit signal detected";
    root_vfs_->UninstallAll(zx::time::infinite());
    event_.signal(0, FSHOST_SIGNAL_EXIT_DONE);
  });

  global_shutdown_.set_object(event_.get());
  global_shutdown_.set_trigger(FSHOST_SIGNAL_EXIT);
  global_shutdown_.Begin(global_loop_->dispatcher());
}

void FsManager::Shutdown(fit::function<void(zx_status_t)> callback) {
  zx_status_t status = event_.signal(0, FSHOST_SIGNAL_EXIT);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "error signalling event: " << zx_status_get_string(status);
    return;
  }

  shutdown_waiter_ = std::make_unique<async::Wait>(event_.get(), FSHOST_SIGNAL_EXIT_DONE);
  shutdown_waiter_->set_handler(
      [callback = std::move(callback)](
          async_dispatcher_t* unused_dispatched, async::Wait* unused_wait, zx_status_t status,
          /*signal*/ const zx_packet_signal_t* unused_packet_signal) { callback(status); });
  shutdown_waiter_->Begin(global_loop_->dispatcher());
}

zx_status_t FsManager::AddFsDiagnosticsDirectory(const char* diagnostics_dir_name,
                                                 zx::channel fs_diagnostics_dir_client) {
  // The diagnostics directory may not be initialized in tests.
  if (diagnostics_dir_ == nullptr) {
    return ZX_ERR_INTERNAL;
  }
  auto fs_diagnostics_dir =
      fbl::MakeRefCounted<fs::RemoteDir>(std::move(fs_diagnostics_dir_client));
  return diagnostics_dir_->AddEntry(diagnostics_dir_name, fs_diagnostics_dir);
}

}  // namespace devmgr
