// 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 <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fuchsia/device/c/fidl.h>
#include <fuchsia/device/llcpp/fidl.h>
#include <fuchsia/hardware/block/c/fidl.h>
#include <fuchsia/hardware/ramdisk/c/fidl.h>
#include <inttypes.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/watcher.h>
#include <lib/fit/defer.h>
#include <lib/zx/channel.h>
#include <lib/zx/time.h>
#include <lib/zx/vmo.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <zircon/boot/image.h>
#include <zircon/device/block.h>
#include <zircon/device/vfs.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <memory>

#include <fbl/string.h>
#include <fbl/string_printf.h>
#include <fbl/unique_fd.h>
#include <ramdevice-client/ramdisk.h>

#define RAMCTL_DEV_PATH "/dev"
#define RAMCTL_PATH "misc/ramctl"
#define BLOCK_EXTENSION "block"

static zx_status_t driver_watcher_cb(int dirfd, int event, const char* fn, void* cookie) {
  char* wanted = static_cast<char*>(cookie);
  if (event == WATCH_EVENT_ADD_FILE && strcmp(fn, wanted) == 0) {
    return ZX_ERR_STOP;
  }
  return ZX_OK;
}

static zx_status_t wait_for_device_impl(int dir_fd, char* path, const zx::time& deadline) {
  zx_status_t rc;

  // Peel off last path segment
  char* sep = strrchr(path, '/');
  if (path[0] == '\0' || (!sep)) {
    fprintf(stderr, "invalid device path '%s'\n", path);
    return ZX_ERR_BAD_PATH;
  }
  char* last = sep + 1;

  *sep = '\0';
  auto restore_path = fit::defer([sep] { *sep = '/'; });

  // Recursively check the path up to this point
  struct stat buf;
  if (fstatat(dir_fd, path, &buf, 0) != 0 &&
      (rc = wait_for_device_impl(dir_fd, path, deadline)) != ZX_OK) {
    fprintf(stderr, "failed to bind '%s': %s\n", path, zx_status_get_string(rc));
    return rc;
  }

  // Early exit if this segment is empty
  if (last[0] == '\0') {
    return ZX_OK;
  }

  // Open the parent directory
  fbl::unique_fd parent_dir(openat(dir_fd, path, O_RDONLY | O_DIRECTORY));
  if (!parent_dir) {
    fprintf(stderr, "unable to open '%s'\n", path);
    return ZX_ERR_NOT_FOUND;
  }

  // Wait for the next path segment to show up
  rc = fdio_watch_directory(parent_dir.get(), driver_watcher_cb, deadline.get(), last);
  if (rc != ZX_ERR_STOP) {
    fprintf(stderr, "error when waiting for '%s': %s\n", last, zx_status_get_string(rc));
    return rc;
  }

  return ZX_OK;
}

__EXPORT
zx_status_t wait_for_device_at(int dirfd, const char* path, zx_duration_t timeout) {
  if (!path || timeout == 0) {
    fprintf(stderr, "invalid args: path='%s', timeout=%" PRIu64 "\n", path, timeout);
    return ZX_ERR_INVALID_ARGS;
  }

  // Make a mutable copy
  char tmp[PATH_MAX];
  snprintf(tmp, sizeof(tmp), "%s", path);
  zx::time deadline = zx::deadline_after(zx::duration(timeout));
  return wait_for_device_impl(dirfd, tmp, deadline);
}

struct ramdisk_client {
 public:
  DISALLOW_COPY_ASSIGN_AND_MOVE(ramdisk_client);

  static zx_status_t Create(int dev_root_fd, const char* instance_name, zx::duration duration,
                            std::unique_ptr<ramdisk_client>* out) {
    fbl::String ramdisk_path = fbl::StringPrintf("%s/%s", RAMCTL_PATH, instance_name);
    fbl::String block_path = fbl::String::Concat({ramdisk_path, "/", BLOCK_EXTENSION});
    fbl::String path;
    fbl::unique_fd dirfd;
    if (dev_root_fd > -1) {
      dirfd.reset(dup(dev_root_fd));
      path = block_path;
    } else {
      dirfd.reset(open(RAMCTL_DEV_PATH, O_RDONLY | O_DIRECTORY));
      path = fbl::String::Concat({RAMCTL_DEV_PATH, "/", block_path});
    }
    if (!dirfd) {
      return ZX_ERR_BAD_STATE;
    }
    fbl::unique_fd ramdisk_fd(openat(dirfd.get(), ramdisk_path.c_str(), O_RDWR));
    if (!ramdisk_fd) {
      return ZX_ERR_BAD_STATE;
    }
    zx_handle_t ramdisk_interface_raw;
    zx_status_t status = fdio_get_service_handle(ramdisk_fd.release(), &ramdisk_interface_raw);
    if (status != ZX_OK) {
      return status;
    }
    zx::channel ramdisk_interface(ramdisk_interface_raw);

    // If binding to the block interface fails, ensure we still try to tear down the
    // ramdisk driver.
    auto cleanup = fit::defer(
        [&ramdisk_interface]() { ramdisk_client::DestroyByHandle(std::move(ramdisk_interface)); });

    status = wait_for_device_at(dirfd.get(), block_path.c_str(), duration.get());
    if (status != ZX_OK) {
      return status;
    }
    fbl::unique_fd block_fd(openat(dirfd.get(), block_path.c_str(), O_RDWR));
    if (!block_fd) {
      return ZX_ERR_BAD_STATE;
    }
    cleanup.cancel();
    *out = std::unique_ptr<ramdisk_client>(
        new ramdisk_client(std::move(path), std::move(block_path), std::move(ramdisk_interface),
                           std::move(dirfd), std::move(block_fd)));
    return ZX_OK;
  }

  zx_status_t Rebind() {
    fdio_cpp::FdioCaller disk_client(std::move(block_fd_));
    zx_status_t io_status, status;
    io_status = fuchsia_hardware_block_BlockRebindDevice(disk_client.borrow_channel(), &status);
    if (io_status != ZX_OK) {
      return io_status;
    } else if (status != ZX_OK) {
      return status;
    }
    ramdisk_interface_.reset();

    // Ramdisk paths have the form: /dev/.../ramctl/ramdisk-xxx/block.
    // To rebind successfully, first, we rebind the "ramdisk-xxx" path,
    // and then we wait for "block" to rebind.

    // Wait for the "ramdisk-xxx" path to rebind.
    const char* sep = strrchr(relative_path_.c_str(), '/');
    char ramdisk_path[PATH_MAX];
    strlcpy(ramdisk_path, relative_path_.c_str(), sep - relative_path_.c_str() + 1);
    status = wait_for_device_impl(dev_root_fd_.get(), ramdisk_path, zx::deadline_after(zx::sec(3)));
    if (status != ZX_OK) {
      return status;
    }

    fbl::unique_fd ramdisk_fd(openat(dev_root_fd_.get(), ramdisk_path, O_RDWR));
    if (!ramdisk_fd) {
      return ZX_ERR_BAD_STATE;
    }

    zx_handle_t ramdisk_interface;
    status = fdio_get_service_handle(ramdisk_fd.release(), &ramdisk_interface);
    if (status != ZX_OK) {
      return status;
    }
    ramdisk_interface_.reset(ramdisk_interface);

    // Wait for the "block" path to rebind.
    strlcpy(ramdisk_path, relative_path_.c_str(), sizeof(ramdisk_path));
    status = wait_for_device_impl(dev_root_fd_.get(), ramdisk_path, zx::deadline_after(zx::sec(3)));
    if (status != ZX_OK) {
      return status;
    }
    block_fd_.reset(openat(dev_root_fd_.get(), relative_path_.c_str(), O_RDWR));
    if (!block_fd_) {
      return ZX_ERR_BAD_STATE;
    }
    return ZX_OK;
  }

  zx_status_t Destroy() {
    if (!ramdisk_interface_) {
      return ZX_ERR_BAD_STATE;
    }

    zx_status_t status = DestroyByHandle(std::move(ramdisk_interface_));
    if (status != ZX_OK) {
      return status;
    }
    block_fd_.reset();
    return ZX_OK;
  }

  const zx::channel& ramdisk_interface() const { return ramdisk_interface_; }

  const fbl::unique_fd& block_fd() const { return block_fd_; }

  const fbl::String& path() const { return path_; }

  ~ramdisk_client() { Destroy(); }

 private:
  ramdisk_client(fbl::String path, fbl::String relative_path, zx::channel ramdisk_interface,
                 fbl::unique_fd dev_root_fd, fbl::unique_fd block_fd)
      : path_(std::move(path)),
        relative_path_(relative_path),
        ramdisk_interface_(std::move(ramdisk_interface)),
        dev_root_fd_(std::move(dev_root_fd)),
        block_fd_(std::move(block_fd)) {}

  static zx_status_t DestroyByHandle(zx::channel ramdisk) {
    zx_status_t call_status = ZX_OK;
    auto resp = fidl::WireCall<fuchsia_device::Controller>(zx::unowned_channel(ramdisk.get()))
                    .ScheduleUnbind();
    zx_status_t status = resp.status();
    if (status != ZX_OK) {
      return status;
    }
    if (resp->result.is_err()) {
      call_status = resp->result.err();
    }
    return call_status;
  }

  // The fully qualified path.
  fbl::String path_;
  // The path relative to dev_root_fd_.
  fbl::String relative_path_;
  zx::channel ramdisk_interface_;
  fbl::unique_fd dev_root_fd_;
  fbl::unique_fd block_fd_;
};

// TODO(aarongreen): This is more generic than just fs-management, or even block devices.  Move this
// (and its tests) out of ramdisk and to somewhere else?
__EXPORT
zx_status_t wait_for_device(const char* path, zx_duration_t timeout) {
  return wait_for_device_at(/*dirfd=*/-1, path, timeout);
}

static zx_status_t open_ramctl(int dev_root_fd, zx::channel* out_ramctl) {
  fbl::unique_fd dirfd;
  if (dev_root_fd > -1) {
    dirfd.reset(dup(dev_root_fd));
  } else {
    dirfd.reset(open(RAMCTL_DEV_PATH, O_RDONLY | O_DIRECTORY));
  }
  if (!dirfd) {
    return ZX_ERR_BAD_STATE;
  }
  fbl::unique_fd fd(openat(dirfd.get(), RAMCTL_PATH, O_RDWR));
  if (!fd) {
    return ZX_ERR_BAD_STATE;
  }

  zx_handle_t ramctl_interface_raw;
  zx_status_t status = fdio_get_service_handle(fd.release(), &ramctl_interface_raw);
  if (status != ZX_OK) {
    return status;
  }

  out_ramctl->reset(ramctl_interface_raw);
  return ZX_OK;
}

static const fuchsia_hardware_ramdisk_GUID* fidl_guid(const uint8_t* type_guid) {
  static_assert(sizeof(fuchsia_hardware_ramdisk_GUID) == ZBI_PARTITION_GUID_LEN,
                "Byte array cannot be reinterpreted as FIDL GUID");
  return reinterpret_cast<const fuchsia_hardware_ramdisk_GUID*>(type_guid);
}

static zx_status_t ramdisk_create_with_guid_internal(int dev_root_fd, uint64_t blk_size,
                                                     uint64_t blk_count, const uint8_t* type_guid,
                                                     ramdisk_client** out) {
  zx::channel ramctl;
  zx_status_t status = open_ramctl(dev_root_fd, &ramctl);
  if (status != ZX_OK) {
    return status;
  }

  char name[fuchsia_hardware_ramdisk_MAX_NAME_LENGTH + 1];
  size_t name_len = 0;
  zx_status_t io_status = fuchsia_hardware_ramdisk_RamdiskControllerCreate(
      ramctl.get(), blk_size, blk_count, fidl_guid(type_guid), &status, name, sizeof(name) - 1,
      &name_len);
  if (io_status != ZX_OK) {
    return io_status;
  } else if (status != ZX_OK) {
    return status;
  }

  // Always force 'name' to be null-terminated.
  name[name_len] = '\0';

  std::unique_ptr<ramdisk_client> client;
  status = ramdisk_client::Create(dev_root_fd, name, zx::sec(3), &client);
  if (status != ZX_OK) {
    return status;
  }
  *out = client.release();
  return ZX_OK;
}

__EXPORT
zx_status_t ramdisk_create_at(int dev_root_fd, uint64_t blk_size, uint64_t blk_count,
                              ramdisk_client** out) {
  return ramdisk_create_with_guid_internal(dev_root_fd, blk_size, blk_count, nullptr, out);
}

__EXPORT
zx_status_t ramdisk_create(uint64_t blk_size, uint64_t blk_count, ramdisk_client** out) {
  return ramdisk_create_at(/*dev_root_fd=*/-1, blk_size, blk_count, out);
}

__EXPORT
zx_status_t ramdisk_create_with_guid(uint64_t blk_size, uint64_t blk_count,
                                     const uint8_t* type_guid, size_t guid_len,
                                     ramdisk_client** out) {
  return ramdisk_create_at_with_guid(/*dev_root_fd=*/-1, blk_size, blk_count, type_guid, guid_len,
                                     out);
}

__EXPORT
zx_status_t ramdisk_create_at_with_guid(int dev_root_fd, uint64_t blk_size, uint64_t blk_count,
                                        const uint8_t* type_guid, size_t guid_len,
                                        ramdisk_client** out) {
  if (type_guid == nullptr || guid_len < ZBI_PARTITION_GUID_LEN) {
    return ZX_ERR_INVALID_ARGS;
  }
  return ramdisk_create_with_guid_internal(dev_root_fd, blk_size, blk_count, type_guid, out);
}

__EXPORT
zx_status_t ramdisk_create_from_vmo(zx_handle_t raw_vmo, ramdisk_client** out) {
  return ramdisk_create_at_from_vmo(/*dev_root_fd=*/-1, raw_vmo, out);
}

__EXPORT
zx_status_t ramdisk_create_from_vmo_with_block_size(zx_handle_t raw_vmo, uint64_t block_size,
                                                    ramdisk_client** out) {
  return ramdisk_create_at_from_vmo_with_block_size(/*dev_root_fd=*/-1, raw_vmo, block_size, out);
}

__EXPORT
zx_status_t ramdisk_create_at_from_vmo(int dev_root_fd, zx_handle_t vmo, ramdisk_client** out) {
  return ramdisk_create_at_from_vmo_with_block_size(dev_root_fd, vmo, /*block_size=*/0, out);
}

__EXPORT
zx_status_t ramdisk_create_at_from_vmo_with_block_size(int dev_root_fd, zx_handle_t raw_vmo,
                                                       uint64_t block_size, ramdisk_client** out) {
  zx::vmo vmo(raw_vmo);
  zx::channel ramctl;
  zx_status_t status = open_ramctl(dev_root_fd, &ramctl);
  if (status != ZX_OK) {
    return status;
  }

  char name[fuchsia_hardware_ramdisk_MAX_NAME_LENGTH + 1];
  size_t name_len = 0;
  zx_status_t io_status;
  if (block_size != 0) {
    io_status = fuchsia_hardware_ramdisk_RamdiskControllerCreateFromVmoWithBlockSize(
        ramctl.get(), vmo.release(), block_size, &status, name, sizeof(name) - 1, &name_len);
  } else {
    io_status = fuchsia_hardware_ramdisk_RamdiskControllerCreateFromVmo(
        ramctl.get(), vmo.release(), &status, name, sizeof(name) - 1, &name_len);
  }
  if (io_status != ZX_OK) {
    return io_status;
  } else if (status != ZX_OK) {
    return status;
  }

  // Always force 'name' to be null-terminated.
  name[name_len] = '\0';

  std::unique_ptr<ramdisk_client> client;
  status = ramdisk_client::Create(dev_root_fd, name, zx::sec(3), &client);
  if (status != ZX_OK) {
    return status;
  }
  *out = client.release();
  return ZX_OK;
}

__EXPORT
int ramdisk_get_block_fd(const ramdisk_client_t* client) { return client->block_fd().get(); }

__EXPORT
const char* ramdisk_get_path(const ramdisk_client_t* client) { return client->path().c_str(); }

__EXPORT
zx_status_t ramdisk_sleep_after(const ramdisk_client* client, uint64_t block_count) {
  zx_status_t status;
  zx_status_t io_status = fuchsia_hardware_ramdisk_RamdiskSleepAfter(
      client->ramdisk_interface().get(), block_count, &status);
  if (io_status != ZX_OK) {
    return io_status;
  }
  return status;
}

__EXPORT
zx_status_t ramdisk_wake(const ramdisk_client* client) {
  zx_status_t status;
  zx_status_t io_status =
      fuchsia_hardware_ramdisk_RamdiskWake(client->ramdisk_interface().get(), &status);
  if (io_status != ZX_OK) {
    return io_status;
  }
  return status;
}

__EXPORT
zx_status_t ramdisk_grow(const ramdisk_client* client, uint64_t required_size) {
  zx_status_t status;
  zx_status_t io_status = fuchsia_hardware_ramdisk_RamdiskGrow(client->ramdisk_interface().get(),
                                                               required_size, &status);
  if (io_status != ZX_OK) {
    return io_status;
  }
  return status;
}

__EXPORT
zx_status_t ramdisk_set_flags(const ramdisk_client* client, uint32_t flags) {
  zx_status_t status;
  zx_status_t io_status =
      fuchsia_hardware_ramdisk_RamdiskSetFlags(client->ramdisk_interface().get(), flags, &status);
  if (io_status != ZX_OK) {
    return io_status;
  }
  return status;
}

__EXPORT
zx_status_t ramdisk_get_block_counts(const ramdisk_client* client,
                                     ramdisk_block_write_counts_t* out_counts) {
  static_assert(
      sizeof(ramdisk_block_write_counts_t) == sizeof(fuchsia_hardware_ramdisk_BlockWriteCounts),
      "Cannot convert between C library / FIDL block counts");

  zx_status_t status;
  zx_status_t io_status = fuchsia_hardware_ramdisk_RamdiskGetBlockCounts(
      client->ramdisk_interface().get(), &status,
      reinterpret_cast<fuchsia_hardware_ramdisk_BlockWriteCounts*>(out_counts));
  if (io_status != ZX_OK) {
    return io_status;
  }
  return status;
}

__EXPORT
zx_status_t ramdisk_rebind(ramdisk_client_t* client) { return client->Rebind(); }

__EXPORT
zx_status_t ramdisk_destroy(ramdisk_client* client) {
  zx_status_t status = client->Destroy();
  delete client;
  return status;
}
