// 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 <dirent.h>
#include <fidl/fuchsia.device/cpp/wire.h>
#include <fidl/fuchsia.hardware.block.partition/cpp/wire.h>
#include <fidl/fuchsia.hardware.block/cpp/wire.h>
#include <fidl/fuchsia.hardware.skipblock/cpp/wire.h>
#include <inttypes.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/fit/defer.h>
#include <lib/fzl/owned-vmo-mapper.h>
#include <lib/zx/vmo.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zircon/process.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <memory>
#include <string>

#include <fbl/unique_fd.h>
#include <gpt/c/gpt.h>
#include <gpt/guid.h>
#include <pretty/hexdump.h>

#include "src/lib/fxl/strings/string_printf.h"
#include "src/storage/lib/storage-metrics/block-metrics.h"

namespace fuchsia_block = fuchsia_hardware_block;
namespace fuchsia_partition = fuchsia_hardware_block_partition;
namespace fuchsia_skipblock = fuchsia_hardware_skipblock;

namespace {

constexpr char DEV_BLOCK[] = "/dev/class/block";
constexpr char DEV_SKIP_BLOCK[] = "/dev/class/skip-block";

char* size_to_cstring(char* str, size_t maxlen, uint64_t size) {
  constexpr size_t kibi = 1024;
  const char* unit;
  uint64_t div;
  if (size < kibi) {
    unit = "";
    div = 1;
  } else if (size >= kibi && size < kibi * kibi) {
    unit = "K";
    div = kibi;
  } else if (size >= kibi * kibi && size < kibi * kibi * kibi) {
    unit = "M";
    div = kibi * kibi;
  } else if (size >= kibi * kibi * kibi && size < kibi * kibi * kibi * kibi) {
    unit = "G";
    div = kibi * kibi * kibi;
  } else {
    unit = "T";
    div = kibi * kibi * kibi * kibi;
  }
  snprintf(str, maxlen, "%" PRIu64 "%s", size / div, unit);
  return str;
}

int cmd_list_blk() {
  struct dirent* de;
  DIR* dir = opendir(DEV_BLOCK);
  if (!dir) {
    fprintf(stderr, "Error opening %s\n", DEV_BLOCK);
    return -1;
  }
  auto cleanup = fit::defer([&dir]() { closedir(dir); });

  printf("%-3s %-4s %-16s %-20s %-6s %s\n", "ID", "SIZE", "TYPE", "LABEL", "FLAGS", "DEVICE");

  while ((de = readdir(dir)) != nullptr) {
    if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
      continue;
    }
    std::string device_path = fxl::StringPrintf("%s/%s", DEV_BLOCK, de->d_name);
    std::string controller_path = device_path + "/device_controller";

    std::string topological_path;
    {
      zx::result controller = component::Connect<fuchsia_device::Controller>(controller_path);
      if (controller.is_error()) {
        fprintf(stderr, "Error opening %s: %s\n", controller_path.c_str(),
                controller.status_string());
        continue;
      }
      fidl::WireResult result = fidl::WireCall(controller.value())->GetTopologicalPath();
      if (!result.ok()) {
        fprintf(stderr, "Error getting topological path for %s: %s\n", controller_path.c_str(),
                result.status_string());
        continue;
      }
      fit::result response = result.value();
      if (response.is_error()) {
        fprintf(stderr, "Error getting topological path for %s: %s\n", controller_path.c_str(),
                zx_status_get_string(response.error_value()));
        continue;
      }
      topological_path = response.value()->path.get();
    }

    zx::result device = component::Connect<fuchsia_partition::Partition>(device_path);
    if (device.is_error()) {
      fprintf(stderr, "Error opening %s: %s\n", device_path.c_str(), device.status_string());
      continue;
    }

    char sizestr[6] = {};
    fuchsia_block::wire::BlockInfo block_info;
    {
      if (const fidl::WireResult result = fidl::WireCall(device.value())->GetInfo(); result.ok()) {
        if (const fit::result response = result.value(); response.is_ok()) {
          block_info = response.value()->info;
          size_to_cstring(sizestr, sizeof(sizestr), block_info.block_size * block_info.block_count);
        }
      }
    }

    std::string type;
    std::string label;
    {
      if (const fidl::WireResult result = fidl::WireCall(device.value())->GetTypeGuid();
          result.ok()) {
        if (const fidl::WireResponse response = result.value(); response.status == ZX_OK) {
          type = gpt::KnownGuid::TypeDescription(response.guid->value.data());
        }
      }
      if (const fidl::WireResult result = fidl::WireCall(device.value())->GetName(); result.ok()) {
        if (const fidl::WireResponse response = result.value(); response.status == ZX_OK) {
          label = response.name.get();
        }
      }
    }

    char flags[20] = {0};
    if (block_info.flags & fuchsia_block::wire::Flag::kReadonly) {
      strlcat(flags, "RO ", sizeof(flags));
    }
    if (block_info.flags & fuchsia_block::wire::Flag::kRemovable) {
      strlcat(flags, "RE ", sizeof(flags));
    }
    if (block_info.flags & fuchsia_block::wire::Flag::kBootpart) {
      strlcat(flags, "BP ", sizeof(flags));
    }
    printf("%-3s %4s %-16s %-20s %-6s %s\n", de->d_name, sizestr, type.c_str(), label.c_str(),
           flags, topological_path.c_str());
  }
  return 0;
}

int cmd_list_skip_blk() {
  struct dirent* de;
  DIR* dir = opendir(DEV_SKIP_BLOCK);
  if (!dir) {
    fprintf(stderr, "Error opening %s\n", DEV_SKIP_BLOCK);
    return -1;
  }
  while ((de = readdir(dir)) != nullptr) {
    if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
      continue;
    }
    std::string device_path = fxl::StringPrintf("%s/%s", DEV_SKIP_BLOCK, de->d_name);
    std::string controller_path = device_path + "/device_controller";

    std::string topological_path;
    {
      zx::result controller = component::Connect<fuchsia_device::Controller>(controller_path);
      if (controller.is_error()) {
        fprintf(stderr, "Error opening %s: %s\n", controller_path.c_str(),
                controller.status_string());
        continue;
      }
      fidl::WireResult result = fidl::WireCall(controller.value())->GetTopologicalPath();
      if (!result.ok()) {
        fprintf(stderr, "Error getting topological path for %s: %s\n", controller_path.c_str(),
                result.status_string());
        continue;
      }
      fit::result response = result.value();
      if (response.is_error()) {
        fprintf(stderr, "Error getting topological path for %s: %s\n", controller_path.c_str(),
                zx_status_get_string(response.error_value()));
        continue;
      }
      topological_path = response.value()->path.get();
    }

    std::string type;
    {
      zx::result device = component::Connect<fuchsia_skipblock::SkipBlock>(device_path);
      if (device.is_error()) {
        fprintf(stderr, "Error opening %s: %s\n", device_path.c_str(), device.status_string());
        continue;
      }
      if (const fidl::WireResult result = fidl::WireCall(device.value())->GetPartitionInfo();
          result.ok()) {
        if (const fidl::WireResponse response = result.value(); response.status == ZX_OK) {
          type = gpt::KnownGuid::TypeDescription(response.partition_info.partition_guid.data());
        }
      }
    }

    printf("%-3s %4sr%-16s %-20s %-6s %s\n", de->d_name, "", type.c_str(), "", "",
           topological_path.c_str());
  }
  closedir(dir);
  return 0;
}

int try_read_skip_blk(const fidl::UnownedClientEnd<fuchsia_skipblock::SkipBlock>& skip_block,
                      off_t offset, size_t count) {
  // check that count and offset are aligned to block size
  const fidl::WireResult result = fidl::WireCall(skip_block)->GetPartitionInfo();
  if (!result.ok()) {
    fprintf(stderr, "Failed to get skip block partition info: %s\n",
            result.FormatDescription().c_str());
    return -1;
  }
  const fidl::WireResponse response = result.value();
  if (zx_status_t status = response.status; status != ZX_OK) {
    fprintf(stderr, "Failed to get skip block partition info: %s\n", zx_status_get_string(status));
    return -1;
  }
  uint64_t blksize = response.partition_info.block_size_bytes;
  if (count % blksize) {
    fprintf(stderr, "Bytes read must be a multiple of blksize=%" PRIu64 "\n", blksize);
    return -1;
  }
  if (offset % blksize) {
    fprintf(stderr, "Offset must be a multiple of blksize=%" PRIu64 "\n", blksize);
    return -1;
  }

  // allocate and map a buffer to read into
  zx::vmo vmo;
  if (zx_status_t status = zx::vmo::create(count, 0, &vmo); status != ZX_OK) {
    fprintf(stderr, "Failed to create vmo: %s\n", zx_status_get_string(status));
    return -1;
  }

  fzl::OwnedVmoMapper mapper;
  if (zx_status_t status = mapper.Map(std::move(vmo), count); status != ZX_OK) {
    fprintf(stderr, "Failed to map vmo: %s\n", zx_status_get_string(status));
    return -1;
  }
  zx::vmo dup;
  if (zx_status_t status = mapper.vmo().duplicate(ZX_RIGHT_SAME_RIGHTS, &dup); status != ZX_OK) {
    fprintf(stderr, "Failed duplicate handle: %s\n", zx_status_get_string(status));
    return -1;
  }

  // read the data
  const fidl::WireResult read_result =
      fidl::WireCall(skip_block)
          ->Read({
              .vmo = std::move(dup),
              .vmo_offset = 0,
              .block = static_cast<uint32_t>(offset / blksize),
              .block_count = static_cast<uint32_t>(count / blksize),
          });
  if (!read_result.ok()) {
    fprintf(stderr, "Failed to read skip block: %s\n", read_result.FormatDescription().c_str());
    return -1;
  }
  const fidl::WireResponse read_response = read_result.value();
  if (zx_status_t status = read_response.status; status != ZX_OK) {
    fprintf(stderr, "Failed to read skip block: %s\n", zx_status_get_string(status));
    return -1;
  }

  hexdump8_ex(mapper.start(), count, offset);
  return 0;
}

int cmd_read_blk(const char* dev, off_t offset, size_t count) {
  zx::result block = component::Connect<fuchsia_block::Block>(dev);
  if (block.is_error()) {
    fprintf(stderr, "Error connecting to %s: %s\n", dev, block.status_string());
    return -1;
  }

  const fidl::WireResult result = fidl::WireCall(block.value())->GetInfo();
  if (!result.ok()) {
    fprintf(stderr, "Error getting block size for %s: %s\n", dev,
            result.FormatDescription().c_str());
    return -1;
  }
  const fit::result response = result.value();
  if (response.is_error()) {
    zx::result skip_block = component::Connect<fuchsia_skipblock::SkipBlock>(dev);
    if (skip_block.is_error()) {
      fprintf(stderr, "Error connecting to %s: %s\n", dev, skip_block.status_string());
      return -1;
    }
    if (try_read_skip_blk(skip_block.value(), offset, count) < 0) {
      fprintf(stderr, "Error getting block size for %s\n", dev);
      return -1;
    }
    return 0;
  }
  // Check that count and offset are aligned to block size.
  uint64_t blksize = response.value()->info.block_size;
  if (count % blksize) {
    fprintf(stderr, "Bytes read must be a multiple of blksize=%" PRIu64 "\n", blksize);
    return -1;
  }
  if (offset % blksize) {
    fprintf(stderr, "Offset must be a multiple of blksize=%" PRIu64 "\n", blksize);
    return -1;
  }

  // Create vmo for reading, and handle clone for passing off.
  zx::vmo in_vmo;
  if (zx_status_t status = zx::vmo::create(count, 0u, &in_vmo); status != ZX_OK) {
    fprintf(stderr, "Failed to create read vmo: %s.\n", zx_status_get_string(status));
    return -1;
  }
  zx::vmo out_vmo;
  if (zx_status_t status = in_vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &out_vmo); status != ZX_OK) {
    fprintf(stderr, "Failed to duplicate vmo handle: %s.\n", zx_status_get_string(status));
    return -1;
  }
  fzl::OwnedVmoMapper mapper;
  if (zx_status_t status = mapper.Map(std::move(in_vmo), count); status != ZX_OK) {
    fprintf(stderr, "Failed to map vmo: %s\n", zx_status_get_string(status));
    return -1;
  }

  // read the data
  const fidl::WireResult read_result =
      fidl::WireCall(block.value())->ReadBlocks(std::move(out_vmo), count, offset, 0);
  if (!read_result.ok()) {
    fprintf(stderr, "FIDL error: %s\n", read_result.FormatDescription().c_str());
    return -1;
  }
  if (read_result.value().is_error()) {
    fprintf(stderr, "Error reading blocks from device: %s\n",
            zx_status_get_string(read_result.value().error_value()));
    return -1;
  }

  hexdump8_ex(mapper.start(), count, offset);
  return 0;
}

int cmd_stats(const char* dev, bool clear) {
  zx::result block = component::Connect<fuchsia_block::Block>(dev);
  if (block.is_error()) {
    fprintf(stderr, "Error connecting to %s: %s\n", dev, block.status_string());
    return -1;
  }
  const fidl::WireResult result = fidl::WireCall(block.value())->GetStats(clear);
  if (!result.ok()) {
    fprintf(stderr, "Error getting stats for %s: %s\n", dev, result.FormatDescription().c_str());
    return -1;
  }
  const fit::result response = result.value();
  if (response.is_error()) {
    fprintf(stderr, "Error getting stats for %s: %s\n", dev,
            zx_status_get_string(response.error_value()));
    return -1;
  }
  storage_metrics::BlockDeviceMetrics metrics(&response.value()->stats);
  metrics.Dump(stdout);
  return 0;
}

}  // namespace

int main(int argc, const char** argv) {
  int rc = 0;
  const char* cmd = argc > 1 ? argv[1] : nullptr;
  if (cmd) {
    if (!strcmp(cmd, "help")) {
      goto usage;
    } else if (!strcmp(cmd, "read")) {
      if (argc < 5)
        goto usage;
      rc = cmd_read_blk(argv[2], strtoul(argv[3], nullptr, 10), strtoull(argv[4], nullptr, 10));
    } else if (!strcmp(cmd, "stats")) {
      if (argc < 4)
        goto usage;
      if (strcmp("true", argv[3]) != 0 && strcmp("false", argv[3]) != 0)
        goto usage;
      rc = cmd_stats(argv[2], strcmp("true", argv[3]) == 0);
    } else {
      fprintf(stderr, "Unrecognized command %s!\n", cmd);
      goto usage;
    }
  } else {
    rc = cmd_list_blk() || cmd_list_skip_blk();
  }
  return rc;
usage:
  fprintf(stderr, "Usage:\n");
  fprintf(stderr, "%s\n", argv[0]);
  fprintf(stderr, "%s read <blkdev> <offset> <count>\n", argv[0]);
  fprintf(stderr, "%s stats <blkdev> <clear=true|false>\n", argv[0]);
  return 0;
}
