// 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/inspect/service/cpp/service.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 <fbl/ref_ptr.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 (!shutdown_called_) {
    Shutdown([](zx_status_t status) {
      if (status != ZX_OK) {
        FX_LOGS(ERROR) << "filesystem shutdown failed: " << zx_status_get_string(status);
        return;
      }
      FX_LOGS(INFO) << "filesystem shutdown complete";
    });
  }
  sync_completion_wait(&shutdown_, ZX_TIME_INFINITE);
}

zx_status_t FsManager::SetupLifecycleServer(
    fidl::ServerEnd<::llcpp::fuchsia::process::lifecycle::Lifecycle> 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(
    fidl::ServerEnd<::llcpp::fuchsia::io::Directory> 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
  svc_dir_ = fbl::MakeRefCounted<fs::PseudoDir>();

  if (loader) {
    // 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", 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(
    fidl::ServerEnd<::llcpp::fuchsia::io::Directory> dir_request,
    fidl::ServerEnd<::llcpp::fuchsia::process::lifecycle::Lifecycle> lifecycle_request,
    fidl::ClientEnd<::llcpp::fuchsia::device::manager::Administrator> driver_admin,
    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 (const auto& point : kAllMountPoints) {
    auto open_result = root_vfs_->Open(global_root_, std::string_view(MountPointPath(point)),
                                       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_[point].root_directory = 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";
  }

  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;
    }
  }
  if (driver_admin.is_valid()) {
    driver_admin_ = fidl::Client<llcpp::fuchsia::device::manager::Administrator>(
        std::move(driver_admin), global_loop_->dispatcher());
  }
  return ZX_OK;
}

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

zx_status_t FsManager::InstallFs(MountPoint point, zx::channel root_directory) {
  if (mount_nodes_.find(point) == mount_nodes_.end()) {
    // The map should have been fully initialized.
    return ZX_ERR_BAD_STATE;
  }
  if (zx_status_t status = root_vfs_->InstallRemote(mount_nodes_[point].root_directory,
                                                    fs::MountChannel(std::move(root_directory)));
      status != ZX_OK) {
    return status;
  }
  return ZX_OK;
}

zx_status_t FsManager::SetFsExportRoot(MountPoint point, zx::channel export_root_directory) {
  if (mount_nodes_.find(point) == mount_nodes_.end()) {
    // The map should have been fully initialized.
    return ZX_ERR_BAD_STATE;
  }
  mount_nodes_[point].root_export_dir = std::move(export_root_directory);
  return ZX_OK;
}

zx_status_t FsManager::ServeRoot(fidl::ServerEnd<::llcpp::fuchsia::io::Directory> 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::RemoveSystemDrivers(fit::callback<void(zx_status_t)> callback) {
  // If we don't have a connection to Driver Manager, just return ZX_OK.
  if (driver_admin_.get() == nullptr) {
    callback(ZX_OK);
    return;
  }

  auto callback_ptr = std::make_shared<fit::callback<void(zx_status_t)>>(std::move(callback));
  auto res = driver_admin_->UnregisterSystemStorageForShutdown(
      [callback_ptr](llcpp::fuchsia::device::manager::Administrator::
                         UnregisterSystemStorageForShutdownResponse* res) {
        if (res->status != ZX_OK) {
          FX_LOGS(ERROR) << "RemoveSystemDevices returned error: "
                         << zx_status_get_string(res->status);
        }
        if (*callback_ptr) {
          (*callback_ptr)(res->status);
        }
      });
  if (res.status() != ZX_OK) {
    if (*callback_ptr) {
      (*callback_ptr)(res.status());
    }
  }
}

void FsManager::Shutdown(fit::function<void(zx_status_t)> callback) {
  std::lock_guard guard(lock_);
  if (shutdown_called_) {
    FX_LOGS(ERROR) << "shutdown called more than once";
    callback(ZX_ERR_INTERNAL);
    return;
  }
  shutdown_called_ = true;

  async::PostTask(global_loop_->dispatcher(), [this, callback = std::move(callback)]() mutable {
    FX_LOGS(INFO) << "filesystem shutdown initiated";
    RemoveSystemDrivers([this, callback = std::move(callback)](zx_status_t status) mutable {
      FX_LOGS(INFO) << "RemoveSystemDrivers returned: " << zx_status_get_string(status);

      status = root_vfs_->UninstallAll(zx::time::infinite());
      callback(status);
      sync_completion_signal(&shutdown_);
      // after this signal, FsManager can be destroyed.
    });
  });
}

bool FsManager::IsShutdown() { return sync_completion_signaled(&shutdown_); }

void FsManager::WaitForShutdown() { sync_completion_wait(&shutdown_, ZX_TIME_INFINITE); }

const char* FsManager::MountPointPath(FsManager::MountPoint point) {
  switch (point) {
    case MountPoint::kUnknown:
      return "";
    case MountPoint::kBin:
      return "/bin";
    case MountPoint::kData:
      return "/data";
    case MountPoint::kVolume:
      return "/volume";
    case MountPoint::kSystem:
      return "/system";
    case MountPoint::kInstall:
      return "/install";
    case MountPoint::kBlob:
      return "/blob";
    case MountPoint::kPkgfs:
      return "/pkgfs";
    case MountPoint::kFactory:
      return "/factory";
    case MountPoint::kDurable:
      return "/durable";
  }
}

zx_status_t FsManager::ForwardFsDiagnosticsDirectory(MountPoint point,
                                                     const char* diagnostics_dir_name) {
  // The diagnostics directory may not be initialized in tests.
  if (diagnostics_dir_ == nullptr) {
    return ZX_ERR_INTERNAL;
  }
  if (point == MountPoint::kUnknown) {
    return ZX_ERR_INVALID_ARGS;
  }
  if (!mount_nodes_[point].root_export_dir) {
    FX_LOGS(ERROR) << "Can't forward diagnostics dir for " << MountPointPath(point)
                   << ", export root directory was not set";
    return ZX_ERR_BAD_STATE;
  }

  auto inspect_node = fbl::MakeRefCounted<fs::Service>([this, point](zx::channel request) {
    std::string name = std::string("diagnostics/") + fuchsia::inspect::Tree::Name_;
    return fdio_service_connect_at(mount_nodes_[point].root_export_dir.get(), name.c_str(),
                                   request.release());
  });
  auto fs_diagnostics_dir = fbl::MakeRefCounted<fs::PseudoDir>();
  zx_status_t status = fs_diagnostics_dir->AddEntry(fuchsia::inspect::Tree::Name_, inspect_node);
  if (status != ZX_OK) {
    return status;
  }
  return diagnostics_dir_->AddEntry(diagnostics_dir_name, fs_diagnostics_dir);
}

zx_status_t FsManager::ForwardFsService(MountPoint point, const char* service_name) {
  // The outgoing service directory may not be initialized in tests.
  if (svc_dir_ == nullptr) {
    return ZX_ERR_INTERNAL;
  }
  if (point == MountPoint::kUnknown) {
    return ZX_ERR_INVALID_ARGS;
  }
  if (!mount_nodes_[point].root_export_dir) {
    FX_LOGS(ERROR) << "Can't forward service for " << MountPointPath(point)
                   << ", export root directory was not set";
    return ZX_ERR_BAD_STATE;
  }

  auto service_node =
      fbl::MakeRefCounted<fs::Service>([this, point, service_name](zx::channel request) {
        std::string name = std::string("svc/") + service_name;
        return fdio_service_connect_at(mount_nodes_[point].root_export_dir.get(), name.c_str(),
                                       request.release());
      });
  return svc_dir_->AddEntry(service_name, std::move(service_node));
}

}  // namespace devmgr
