// Copyright 2017 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 "filesystem-mounter.h"

#include <lib/syslog/cpp/macros.h>
#include <lib/zx/process.h>
#include <zircon/status.h>

#include <fs-management/mount.h>

#include "fdio.h"
#include "fshost-fs-provider.h"
#include "pkgfs-launcher.h"
#include "src/storage/blobfs/mount.h"
#include "src/storage/minfs/minfs.h"

namespace devmgr {

zx_status_t FilesystemMounter::LaunchFs(int argc, const char** argv, zx_handle_t* hnd,
                                        uint32_t* ids, size_t len, uint32_t fs_flags) {
  FshostFsProvider fs_provider;
  DevmgrLauncher launcher(&fs_provider);
  return launcher.Launch(*zx::job::default_job(), argv[0], argv, nullptr, -1,
                         /* TODO(fxbug.dev/32044) */ zx::resource(), hnd, ids, len, nullptr,
                         fs_flags);
}

zx_status_t FilesystemMounter::MountFilesystem(const char* mount_path, const char* binary,
                                               const mount_options_t& options,
                                               zx::channel block_device_client,
                                               zx::channel diagnostics_dir, uint32_t fs_flags) {
  zx::channel client, server;
  zx_status_t status = zx::channel::create(0, &client, &server);
  if (status != ZX_OK) {
    return status;
  }

  size_t num_handles = diagnostics_dir.is_valid() ? 3 : 2;
  zx_handle_t handles[3] = {server.release(), block_device_client.release(),
                            diagnostics_dir.release()};
  uint32_t ids[3] = {FS_HANDLE_ROOT_ID, FS_HANDLE_BLOCK_DEVICE_ID, FS_HANDLE_DIAGNOSTICS_DIR};

  fbl::Vector<const char*> argv;
  argv.push_back(binary);
  if (options.readonly) {
    argv.push_back("--readonly");
  }
  if (options.verbose_mount) {
    argv.push_back("--verbose");
  }
  if (options.collect_metrics) {
    argv.push_back("--metrics");
  }
  if (options.write_compression_algorithm != nullptr) {
    argv.push_back("--compression");
    argv.push_back(options.write_compression_algorithm);
  }
  if (options.cache_eviction_policy != nullptr) {
    argv.push_back("--eviction_policy");
    argv.push_back(options.cache_eviction_policy);
  }
  argv.push_back("mount");
  argv.push_back(nullptr);
  status =
      LaunchFs(static_cast<int>(argv.size() - 1), argv.data(), handles, ids, num_handles, fs_flags);

  if (status != ZX_OK) {
    return status;
  }

  zx_signals_t observed = 0;
  status =
      client.wait_one(ZX_USER_SIGNAL_0 | ZX_CHANNEL_PEER_CLOSED, zx::time::infinite(), &observed);
  if ((status != ZX_OK) || (observed & ZX_CHANNEL_PEER_CLOSED)) {
    status = (status != ZX_OK) ? status : ZX_ERR_BAD_STATE;
    return status;
  }

  return InstallFs(mount_path, std::move(client));
}

zx_status_t FilesystemMounter::MountData(zx::channel block_device, const mount_options_t& options) {
  if (data_mounted_) {
    return ZX_ERR_ALREADY_BOUND;
  }

  // TODO(fxbug.dev/54525): The Inspect API has not been connected for MinFS yet.
  zx::channel diagnostics_dir;

  zx_status_t status = MountFilesystem(PATH_DATA, "/boot/bin/minfs", options,
                                       std::move(block_device), std::move(diagnostics_dir), FS_SVC);
  if (status != ZX_OK) {
    return status;
  }

  data_mounted_ = true;
  return ZX_OK;
}

zx_status_t FilesystemMounter::MountInstall(zx::channel block_device,
                                            const mount_options_t& options) {
  if (install_mounted_) {
    return ZX_ERR_ALREADY_BOUND;
  }

  // TODO(fxbug.dev/54525): The Inspect API has not been connected for MinFS yet.
  zx::channel diagnostics_dir;

  zx_status_t status = MountFilesystem(PATH_INSTALL, "/boot/bin/minfs", options,
                                       std::move(block_device), std::move(diagnostics_dir), FS_SVC);
  if (status != ZX_OK) {
    return status;
  }

  install_mounted_ = true;
  return ZX_OK;
}

zx_status_t FilesystemMounter::MountFactoryFs(zx::channel block_device,
                                              const mount_options_t& options) {
  if (factory_mounted_) {
    return ZX_ERR_ALREADY_BOUND;
  }

  // TODO(fxbug.dev/54525): The Inspect API has not been connected for FactoryFs yet.
  zx::channel diagnostics_dir;

  zx_status_t status = MountFilesystem(PATH_FACTORY, "/boot/bin/factoryfs", options,
                                       std::move(block_device), std::move(diagnostics_dir), FS_SVC);

  if (status != ZX_OK) {
    return status;
  }

  factory_mounted_ = true;
  return ZX_OK;
}

zx_status_t FilesystemMounter::MountDurable(zx::channel block_device,
                                            const mount_options_t& options) {
  if (durable_mounted_) {
    return ZX_ERR_ALREADY_BOUND;
  }

  // TODO(fxbug.dev/54525): The Inspect API has not been connected for durable partition yet.
  zx::channel diagnostics_dir;
  zx_status_t status = MountFilesystem(PATH_DURABLE, "/boot/bin/minfs", options,
                                       std::move(block_device), std::move(diagnostics_dir), FS_SVC);
  if (status != ZX_OK) {
    return status;
  }

  durable_mounted_ = true;
  return ZX_OK;
}

zx_status_t FilesystemMounter::MountBlob(zx::channel block_device, const mount_options_t& options) {
  if (blob_mounted_) {
    return ZX_ERR_ALREADY_BOUND;
  }

  zx::channel fs_diagnostics_dir_client, fs_diagnostics_dir_server;
  zx_status_t status =
      zx::channel::create(0, &fs_diagnostics_dir_client, &fs_diagnostics_dir_server);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to create channel for diagnostics dir: "
                   << zx_status_get_string(status);
    return status;
  }

  status = fshost_.AddFsDiagnosticsDirectory("blobfs", std::move(fs_diagnostics_dir_client));
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to add diagnostic directory for blobfs: "
                   << zx_status_get_string(status);
  }

  status = MountFilesystem(PATH_BLOB, "/boot/bin/blobfs", options, std::move(block_device),
                           std::move(fs_diagnostics_dir_server), FS_SVC | FS_SVC_BLOBFS);
  if (status != ZX_OK) {
    return status;
  }

  blob_mounted_ = true;
  return ZX_OK;
}

void FilesystemMounter::TryMountPkgfs() {
  // Pkgfs waits for the following to mount before initializing:
  //   - Blobfs. Pkgfs is launched from blobfs, so this is a hard requirement.
  //   - Minfs. Pkgfs and other components want minfs to exist, so although they
  //   could launch and query for it later, this synchronization point means that
  //   subsequent clients will no longer need to query.
  //
  // TODO(fxbug.dev/38621): In the future, this mechanism may be replaced with a feed-forward
  // design to the mounted filesystems.
  if (!pkgfs_mounted_ && blob_mounted_ && (data_mounted_ || !WaitForData())) {
    // Historically we don't retry if pkgfs fails to launch, which seems reasonable since the cause
    // of a launch failure is unlikely to be transient.
    // TODO(fxbug.dev/58363): fshost should handle failures to mount critical filesystems better.
    auto status = LaunchPkgfs(this);
    if (status.is_error()) {
      FX_LOGS(ERROR) << "failed to launch pkgfs: " << status.status_string();
    }
    pkgfs_mounted_ = true;
  }
}

}  // namespace devmgr
