// 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 <dirent.h>
#include <fidl/fuchsia.device/cpp/wire.h>
#include <fidl/fuchsia.fxfs/cpp/wire_types.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <fidl/fuchsia.io/cpp/wire_types.h>
#include <fidl/fuchsia.update.verify/cpp/wire.h>
#include <lib/fdio/directory.h>
#include <lib/fidl/llcpp/vector_view.h>
#include <lib/inspect/service/cpp/service.h>
#include <lib/service/llcpp/service.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/process.h>
#include <sys/stat.h>
#include <zircon/status.h>

#include <fbl/ref_ptr.h>

#include "constants.h"
#include "fdio.h"
#include "src/storage/blobfs/mount.h"
#include "src/storage/minfs/minfs.h"

namespace fshost {

namespace fio = fuchsia_io;

constexpr unsigned char kInsecureCryptDataKey[32] = {
    0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,  0x7,  0x8,  0x9,  0xa,  0xb,  0xc,  0xd,  0xe,  0xf,
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
};

constexpr unsigned char kInsecureCryptMetadataKey[32] = {
    0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
    0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0,
};

zx::status<> FilesystemMounter::LaunchFsComponent(zx::channel block_device,
                                                  fuchsia_fs_startup::wire::StartOptions options,
                                                  const std::string& partition_name) {
  std::string startup_service_path =
      std::string("/") + partition_name + "/fuchsia.fs.startup.Startup";
  auto startup_client_end =
      service::Connect<fuchsia_fs_startup::Startup>(startup_service_path.c_str());
  if (startup_client_end.is_error()) {
    FX_LOGS(ERROR) << "failed to connect to startup service at " << startup_service_path << ": "
                   << startup_client_end.status_string();
    return startup_client_end.take_error();
  }
  auto startup_client = fidl::BindSyncClient(std::move(*startup_client_end));
  fidl::ClientEnd<fuchsia_hardware_block::Block> block_client_end(std::move(block_device));
  auto startup_res = startup_client->Start(std::move(block_client_end), std::move(options));
  if (!startup_res.ok()) {
    FX_LOGS(ERROR) << "failed to start through startup service at " << startup_service_path << ": "
                   << startup_res.status_string();
    return zx::make_status(startup_res.status());
  }
  FX_LOGS(INFO) << "successfully mounted " << partition_name;
  return zx::ok();
}

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

std::string FilesystemMounter::GetDevicePath(const zx::channel& block_device) {
  std::string device_path;
  if (auto result =
          fidl::WireCall(fidl::UnownedClientEnd<fuchsia_device::Controller>(block_device.borrow()))
              ->GetTopologicalPath();
      result.status() != ZX_OK) {
    FX_LOGS(WARNING) << "Unable to get device topological path (FIDL error): "
                     << zx_status_get_string(result.status());
  } else if (result->is_error()) {
    FX_LOGS(WARNING) << "Unable to get device topological path: "
                     << zx_status_get_string(result->error_value());
  } else {
    device_path = result->value()->path.get();
  }
  return device_path;
}

zx::status<> FilesystemMounter::MountFilesystem(FsManager::MountPoint point, const char* binary,
                                                const fs_management::MountOptions& options,
                                                zx::channel block_device_client,
                                                fidl::ClientEnd<fuchsia_fxfs::Crypt> crypt_client) {
  FX_LOGS(INFO) << "FilesystemMounter::MountFilesystem(" << binary << ")";
  std::string device_path = GetDevicePath(block_device_client);
  FX_LOGS(INFO) << "Mounting device " << device_path << " with " << binary << " at "
                << FsManager::MountPointPath(point);

  std::optional endpoints_or = fshost_.TakeMountPointServerEnd(point);
  if (!endpoints_or.has_value()) {
    return zx::error(ZX_ERR_BAD_STATE);
  }
  auto [export_root, server_end] = std::move(endpoints_or.value());

  size_t num_handles = crypt_client ? 3 : 2;
  zx_handle_t handles[] = {server_end.TakeChannel().release(), block_device_client.release(),
                           crypt_client.TakeChannel().release()};
  uint32_t ids[] = {PA_DIRECTORY_REQUEST, FS_HANDLE_BLOCK_DEVICE_ID, PA_HND(PA_USER0, 2)};

  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.write_compression_algorithm != nullptr) {
    argv.push_back("--compression");
    argv.push_back(options.write_compression_algorithm);
  }
  if (options.sandbox_decompression) {
    argv.push_back("--sandbox_decompression");
  }
  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);
  if (zx_status_t status =
          LaunchFs(static_cast<int>(argv.size() - 1), argv.data(), handles, ids, num_handles);
      status != ZX_OK) {
    return zx::error(status);
  }

  auto result = fidl::WireCall(export_root)->Describe();
  if (!result.ok()) {
    return zx::error(result.status());
  }

  fshost_.RegisterDevicePath(point, device_path);

  return zx::ok();
}

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

  if (format == fs_management::kDiskFormatF2fs) {
    std::string binary_path(BinaryPathForFormat(format));
    if (binary_path.empty()) {
      FX_LOGS(ERROR) << "Unsupported format: " << DiskFormatString(format);
      return ZX_ERR_INVALID_ARGS;
    }

    if (auto result = MountFilesystem(FsManager::MountPoint::kData, binary_path.c_str(), options,
                                      std::move(block_device), {});
        result.is_error()) {
      return result.error_value();
    }

    if (zx_status_t status = fshost_.ForwardFsDiagnosticsDirectory(
            FsManager::MountPoint::kData, fs_management::DiskFormatString(format));
        status != ZX_OK) {
      FX_PLOGS(ERROR, status) << "failed to add diagnostic directory for "
                              << fs_management::DiskFormatString(format);
    }
  } else {
    std::string device_path = GetDevicePath(block_device);

    auto fidl_options = options.as_start_options();
    if (format == fs_management::kDiskFormatFxfs) {
      // TODO(fxbug.dev/99591): Statically route the crypt service.
      auto crypt_client_or = service::Connect<fuchsia_fxfs::Crypt>();
      if (crypt_client_or.is_error()) {
        return crypt_client_or.error_value();
      }
      fidl_options->crypt = std::move(crypt_client_or).value();
    }

    if (zx::status<> status =
            LaunchFsComponent(std::move(block_device), *std::move(fidl_options), "data");
        status.is_error()) {
      return status.error_value();
    }

    fshost_.RegisterDevicePath(FsManager::MountPoint::kData, device_path);
  }

  // Obtain data root used for serving disk usage statistics. Must be valid otherwise the lazy node
  // serving the statistics will hang indefinitely. If we fail to get the data root, just log
  // loudly, but don't fail. Serving stats is best-effort and shouldn't cause mounting to fail.
  auto data_root_or = manager().GetRoot(FsManager::MountPoint::kData);
  if (data_root_or.is_ok()) {
    inspect_manager().ServeStats("data", std::move(data_root_or.value()));
  } else {
    FX_LOGS(WARNING) << "failed to get data root to serve inspect stats. Assuming test environment "
                        "and continuing.";
  }

  data_mounted_ = true;
  return ZX_OK;
}

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

  if (auto result = MountFilesystem(FsManager::MountPoint::kFactory, kFactoryfsPath, options,
                                    std::move(block_device));
      result.is_error()) {
    return result.error_value();
  }

  factory_mounted_ = true;
  return ZX_OK;
}

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

  if (auto result = MountFilesystem(FsManager::MountPoint::kDurable, kMinfsPath, options,
                                    std::move(block_device));
      result.is_error()) {
    return result.error_value();
  }

  durable_mounted_ = true;
  return ZX_OK;
}

zx_status_t FilesystemMounter::MountBlob(zx::channel block_device,
                                         fuchsia_fs_startup::wire::StartOptions options) {
  if (blob_mounted_) {
    return ZX_ERR_ALREADY_BOUND;
  }

  zx::status ret = LaunchFsComponent(std::move(block_device), std::move(options), "blobfs");
  if (ret.is_error()) {
    return ret.error_value();
  }

  blob_mounted_ = true;
  return ZX_OK;
}

void FilesystemMounter::ReportPartitionCorrupted(fs_management::DiskFormat format) {
  fshost_.inspect_manager().LogCorruption(format);
  // Currently the only reason we report a partition as being corrupt is if it fails fsck.
  // This may need to change in the future should we want to file synthetic crash reports for
  // other possible failure modes.
  fshost_.FileReport(format, FsManager::ReportReason::kFsckFailure);
}

zx::status<> FilesystemMounter::MaybeInitCryptClient() {
  if (config_.data_filesystem_format() != "fxfs") {
    FX_LOGS(INFO) << "Not initializing Crypt client due to configuration";
    return zx::ok();
  }
  FX_LOGS(INFO) << "Initializing Crypt client";
  auto management_endpoints_or = fidl::CreateEndpoints<fuchsia_fxfs::CryptManagement>();
  if (management_endpoints_or.is_error())
    return zx::error(management_endpoints_or.status_value());
  if (zx_status_t status =
          fdio_service_connect(fidl::DiscoverableProtocolDefaultPath<fuchsia_fxfs::CryptManagement>,
                               management_endpoints_or->server.TakeChannel().release());
      status != ZX_OK) {
    return zx::error(status);
  }
  auto client = fidl::BindSyncClient(std::move(management_endpoints_or->client));
  // TODO(fxbug.dev/94587): A hardware source should be used for keys.
  unsigned char key0[32] = {0};
  unsigned char key1[32] = {0};
  std::copy(std::begin(kInsecureCryptDataKey), std::end(kInsecureCryptDataKey), key0);
  std::copy(std::begin(kInsecureCryptMetadataKey), std::end(kInsecureCryptMetadataKey), key1);
  if (auto result = client->AddWrappingKey(0, fidl::VectorView<unsigned char>::FromExternal(key0));
      !result.ok()) {
    FX_LOGS(ERROR) << "Failed to add wrapping key: " << zx_status_get_string(result.status());
    return zx::error(result.status());
  }
  if (auto result = client->AddWrappingKey(1, fidl::VectorView<unsigned char>::FromExternal(key1));
      !result.ok()) {
    FX_LOGS(ERROR) << "Failed to add wrapping key: " << zx_status_get_string(result.status());
    return zx::error(result.status());
  }
  if (auto result = client->SetActiveKey(fuchsia_fxfs::wire::KeyPurpose::kData, 0); !result.ok()) {
    FX_LOGS(ERROR) << "Failed to set active data key: " << zx_status_get_string(result.status());
    return zx::error(result.status());
  }
  if (auto result = client->SetActiveKey(fuchsia_fxfs::wire::KeyPurpose::kMetadata, 1);
      !result.ok()) {
    FX_LOGS(ERROR) << "Failed to set active metadata key: "
                   << zx_status_get_string(result.status());
    return zx::error(result.status());
  }
  return zx::ok();
}

std::string_view BinaryPathForFormat(fs_management::DiskFormat format) {
  switch (format) {
    case fs_management::kDiskFormatFxfs:
      return kFxfsPath;
    case fs_management::kDiskFormatF2fs:
      return kF2fsPath;
    case fs_management::kDiskFormatMinfs:
      return kMinfsPath;
    default:
      return "";
  }
}

}  // namespace fshost
