// Copyright 2019 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 "local-connection.h"

#include <fcntl.h>
#include <lib/fdio/namespace.h>
#include <lib/zxio/inception.h>
#include <lib/zxio/null.h>
#include <zircon/device/vfs.h>
#include <zircon/types.h>

#include <atomic>
#include <new>

#include <fbl/ref_ptr.h>

#include "../internal.h"
#include "local-filesystem.h"
#include "local-vnode.h"

namespace fdio_internal {
namespace {

namespace fio = ::llcpp::fuchsia::io;

// The directory represents a local directory (either "/" or
// some directory between "/" and a mount point), so it has
// to emulate directory behavior.
struct LocalConnection {
  // Hack to embed LocalConnection in the |storage| field of the |fdio_t| struct.
  // See definition of |zxio_storage_t|, where |zxio_t io| is also the first element.
  // This allows us to track extra state related to the local connection, as
  // witnessed by the fields below.
  zxio_t io;

  // For the following two fields, although these are raw pointers for
  // C compatibility, they are actually strong references to both the
  // namespace and vnode object.
  //
  // On close, they must be destroyed.

  // The namespace instance, containing a directory tree terminating
  // with various remote channels.
  const fdio_namespace* fs;

  // The vnode corresponding to this directory. |vn| references some
  // directory in |fs|.
  LocalVnode* vn;
};

static_assert(offsetof(LocalConnection, io) == 0, "LocalConnection must be castable to zxio_t");
static_assert(offsetof(zxio_storage_t, io) == 0, "LocalConnection must be castable to zxio_t");

static_assert(sizeof(LocalConnection) <= sizeof(zxio_storage_t),
              "LocalConnection must fit inside zxio_storage_t.");

LocalConnection* fdio_get_local_dir(fdio_t* io) {
  return reinterpret_cast<LocalConnection*>(fdio_get_zxio(io));
}

zx_status_t local_dir_close(fdio_t* io) {
  LocalConnection* dir = fdio_get_local_dir(io);
  // Reclaim a strong reference to |fs| which was leaked during
  // |CreateLocalConnection()|
  __UNUSED auto fs = fbl::ImportFromRawPtr<const fdio_namespace>(dir->fs);
  __UNUSED auto vn = fbl::ImportFromRawPtr<const LocalVnode>(dir->vn);
  dir->fs = nullptr;
  dir->vn = nullptr;
  return ZX_OK;
}

// Expects a canonical path (no ..) with no leading
// slash and no trailing slash
zx_status_t local_dir_open(fdio_t* io, const char* path, uint32_t flags, uint32_t mode,
                           fdio_t** out) {
  LocalConnection* dir = fdio_get_local_dir(io);

  return dir->fs->Open(fbl::RefPtr(dir->vn), path, flags, mode, out);
}

zx_status_t local_dir_get_attr(fdio_t* io, zxio_node_attributes_t* attr) {
  *attr = {};
  ZXIO_NODE_ATTR_SET(*attr, protocols, ZXIO_NODE_PROTOCOL_DIRECTORY);
  ZXIO_NODE_ATTR_SET(
      *attr, abilities,
      ZXIO_OPERATION_ENUMERATE | ZXIO_OPERATION_TRAVERSE | ZXIO_OPERATION_GET_ATTRIBUTES);
  ZXIO_NODE_ATTR_SET(*attr, link_count, 1);
  return ZX_OK;
}

uint32_t local_dir_convert_to_posix_mode(fdio_t* io, zxio_node_protocols_t protocols,
                                         zxio_abilities_t abilities) {
  return zxio_node_protocols_to_posix_type(protocols) |
         zxio_abilities_to_posix_permissions_for_directory(abilities);
}

zx_status_t local_dir_unlink(fdio_t* io, const char* path, size_t len) {
  return ZX_ERR_UNAVAILABLE;
}

struct local_dir_dirent_iterator {
  // Buffer for storing dirents.
  void* buffer;

  // Size of |buffer|.
  size_t capacity;

  // Used by |Readdir| to resume from the middle of a directory.
  DirentIteratorState iterator_state;
};

zx_status_t local_dir_dirent_iterator_init(fdio_t* io, zxio_dirent_iterator_t* iterator,
                                           zxio_t* directory) {
  auto dir_iterator = new (iterator) local_dir_dirent_iterator;
  size_t capacity_of_one = sizeof(zxio_dirent_t) + fio::MAX_FILENAME + 1;
  dir_iterator->buffer = malloc(capacity_of_one);
  dir_iterator->capacity = capacity_of_one;
  return ZX_OK;
}

zx_status_t local_dir_dirent_iterator_next(fdio_t* io, zxio_dirent_iterator_t* iterator,
                                           zxio_dirent_t** out_entry) {
  LocalConnection* dir = fdio_get_local_dir(io);
  auto dir_iterator = reinterpret_cast<local_dir_dirent_iterator*>(iterator);
  zx_status_t status = dir->fs->Readdir(*dir->vn, &dir_iterator->iterator_state,
                                        dir_iterator->buffer, dir_iterator->capacity, out_entry);
  if (*out_entry == nullptr && status == ZX_OK) {
    return ZX_ERR_NOT_FOUND;
  }
  return status;
}

void local_dir_dirent_iterator_destroy(fdio_t* io, zxio_dirent_iterator_t* iterator) {
  auto dir_iterator = reinterpret_cast<local_dir_dirent_iterator*>(iterator);
  free(dir_iterator->buffer);
  static_assert(std::is_trivially_destructible<local_dir_dirent_iterator>::value,
                "local_dir_dirent_iterator must have trivial destructor");
}

constexpr fdio_ops_t kLocalConnectionOps = []() {
  fdio_ops_t ops = {};
  ops.get_attr = local_dir_get_attr;
  ops.close = local_dir_close;
  ops.open = local_dir_open;
  ops.clone = fdio_default_clone;
  ops.wait_begin = fdio_default_wait_begin;
  ops.wait_end = fdio_default_wait_end;
  ops.unwrap = fdio_default_unwrap;
  ops.borrow_channel = fdio_default_borrow_channel;
  ops.posix_ioctl = fdio_default_posix_ioctl;
  ops.get_token = fdio_default_get_token;
  ops.set_attr = fdio_default_set_attr;
  ops.convert_to_posix_mode = local_dir_convert_to_posix_mode;
  ops.dirent_iterator_init = local_dir_dirent_iterator_init;
  ops.dirent_iterator_next = local_dir_dirent_iterator_next;
  ops.dirent_iterator_destroy = local_dir_dirent_iterator_destroy;
  ops.unlink = local_dir_unlink;
  ops.truncate = fdio_default_truncate;
  ops.rename = fdio_default_rename;
  ops.link = fdio_default_link;
  ops.get_flags = fdio_default_get_flags;
  ops.set_flags = fdio_default_set_flags;
  ops.recvmsg = fdio_default_recvmsg;
  ops.sendmsg = fdio_default_sendmsg;
  ops.shutdown = fdio_default_shutdown;
  return ops;
}();

}  // namespace

fdio_t* CreateLocalConnection(fbl::RefPtr<const fdio_namespace> fs, fbl::RefPtr<LocalVnode> vn) {
  fdio_t* io = fdio_alloc(&kLocalConnectionOps);
  if (io == nullptr) {
    return nullptr;
  }
  // Invoke placement new on the new LocalConnection. Since the object is trivially
  // destructible, we can avoid invoking the destructor.
  static_assert(std::is_trivially_destructible<LocalConnection>::value,
                "LocalConnection must have trivial destructor");
  char* storage = reinterpret_cast<char*>(fdio_get_local_dir(io));
  LocalConnection* dir = new (storage) LocalConnection();
  zxio_null_init(&(fdio_get_zxio_storage(io)->io));

  // Leak a strong reference to |this| which will be reclaimed
  // in |zxio_dir_close()|.
  dir->fs = fbl::ExportToRawPtr(&fs);
  dir->vn = fbl::ExportToRawPtr(&vn);
  return io;
}

fbl::RefPtr<LocalVnode> GetLocalNodeFromConnectionIfAny(fdio_t* io) {
  if (fdio_get_ops(io) != &kLocalConnectionOps) {
    return nullptr;
  }
  return fbl::RefPtr<LocalVnode>(fdio_get_local_dir(io)->vn);
}

}  // namespace fdio_internal
