// 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 "dnode.h"

#include <lib/memfs/cpp/vnode.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <memory>
#include <string_view>
#include <utility>

#include <fbl/alloc_checker.h>
#include <fbl/ref_ptr.h>

#include "src/lib/storage/vfs/cpp/vfs.h"

namespace memfs {

// Create a new dnode and attach it to a vnode
std::unique_ptr<Dnode> Dnode::Create(std::string_view name, fbl::RefPtr<VnodeMemfs> vn) {
  if ((name.length() > kDnodeNameMax) || (name.length() < 1)) {
    return nullptr;
  }

  fbl::AllocChecker ac;
  std::unique_ptr<char[]> namebuffer(new (&ac) char[name.length() + 1]);
  if (!ac.check()) {
    return nullptr;
  }
  memcpy(namebuffer.get(), name.data(), name.length());
  namebuffer[name.length()] = '\0';
  auto dn = std::unique_ptr<Dnode>(
      new Dnode(vn, std::move(namebuffer), static_cast<uint32_t>(name.length())));
  return dn;
}

std::unique_ptr<Dnode> Dnode::RemoveFromParent() {
  ZX_DEBUG_ASSERT(vnode_ != nullptr);

  std::unique_ptr<Dnode> node;
  // Detach from parent
  if (parent_) {
    node = parent_->children_.erase(*this);
    if (IsDirectory()) {
      // '..' no longer references parent.
      parent_->vnode_->link_count_--;
    }
    parent_->vnode_->UpdateModified();
    parent_ = nullptr;
    vnode_->link_count_--;
  }
  return node;
}

void Dnode::Detach() {
  ZX_DEBUG_ASSERT(children_.is_empty());
  if (vnode_ == nullptr) {  // Dnode already detached.
    return;
  }

  auto self = RemoveFromParent();
  // Detach from vnode
  self->vnode_->dnode_ = nullptr;
  self->vnode_ = nullptr;
}

void Dnode::AddChild(Dnode* parent, std::unique_ptr<Dnode> child) {
  ZX_DEBUG_ASSERT(parent != nullptr);
  ZX_DEBUG_ASSERT(child != nullptr);
  ZX_DEBUG_ASSERT(child->parent_ == nullptr);  // Child shouldn't have a parent
  ZX_DEBUG_ASSERT(child.get() != parent);
  ZX_DEBUG_ASSERT(parent->IsDirectory());

  child->parent_ = parent;
  child->vnode_->link_count_++;
  if (child->IsDirectory()) {
    // Child has '..' pointing back at parent.
    parent->vnode_->link_count_++;
  }
  // Ensure that the ordering of tokens in the children list is absolute.
  if (parent->children_.is_empty()) {
    child->ordering_token_ = 2;  // '0' for '.', '1' for '..'
  } else {
    child->ordering_token_ = parent->children_.back().ordering_token_ + 1;
  }
  parent->children_.push_back(std::move(child));
  parent->vnode_->UpdateModified();
}

zx_status_t Dnode::Lookup(std::string_view name, Dnode** out) {
  auto dn = children_.find_if([&name](const Dnode& elem) -> bool { return elem.NameMatch(name); });
  if (dn == children_.end()) {
    return ZX_ERR_NOT_FOUND;
  }

  if (out != nullptr) {
    *out = &(*dn);
  }
  return ZX_OK;
}

fbl::RefPtr<VnodeMemfs> Dnode::AcquireVnode() const { return vnode_; }

zx_status_t Dnode::CanUnlink() const {
  if (!children_.is_empty()) {
    // Cannot unlink non-empty directory
    return ZX_ERR_NOT_EMPTY;
  } else if (vnode_->IsRemote()) {
    // Cannot unlink mount points
    return ZX_ERR_UNAVAILABLE;
  }
  return ZX_OK;
}

struct dircookie_t {
  size_t order;  // Minimum 'order' of the next dnode dirent to be read.
};

static_assert(sizeof(dircookie_t) <= sizeof(fs::VdirCookie),
              "MemFS dircookie too large to fit in IO state");

// Read the canned "." and ".." entries that should
// appear at the beginning of a directory.
zx_status_t Dnode::ReaddirStart(fs::DirentFiller* df, void* cookie) {
  dircookie_t* c = static_cast<dircookie_t*>(cookie);
  zx_status_t r;

  if (c->order == 0) {
    // TODO(smklein): Return the real ino.
    uint64_t ino = fuchsia_io::wire::kInoUnknown;
    if ((r = df->Next(".", VTYPE_TO_DTYPE(V_TYPE_DIR), ino)) != ZX_OK) {
      return r;
    }
    c->order++;
  }
  return ZX_OK;
}

void Dnode::Readdir(fs::DirentFiller* df, void* cookie) const {
  dircookie_t* c = static_cast<dircookie_t*>(cookie);
  zx_status_t r = 0;

  if (c->order < 1) {
    if ((r = Dnode::ReaddirStart(df, cookie)) != ZX_OK) {
      return;
    }
  }

  for (const auto& dn : children_) {
    if (dn.ordering_token_ < c->order) {
      continue;
    }
    uint32_t vtype = dn.IsDirectory() ? V_TYPE_DIR : V_TYPE_FILE;
    if ((r = df->Next(std::string_view(dn.name_.get(), dn.NameLen()), VTYPE_TO_DTYPE(vtype),
                      dn.AcquireVnode()->ino())) != ZX_OK) {
      return;
    }
    c->order = dn.ordering_token_ + 1;
  }
}

// Answers the question: "Is dn a subdirectory of this?"
bool Dnode::IsSubdirectory(const Dnode* dn) const {
  if (IsDirectory() && dn->IsDirectory()) {
    // Iterate all the way up to root
    while (dn->parent_ != nullptr && dn->parent_ != dn) {
      if (vnode_ == dn->vnode_) {
        return true;
      }
      dn = dn->parent_;
    }
  }
  return false;
}

std::unique_ptr<char[]> Dnode::TakeName() { return std::move(name_); }

void Dnode::PutName(std::unique_ptr<char[]> name, size_t len) {
  flags_ = static_cast<uint32_t>((flags_ & ~kDnodeNameMax) | len);
  name_ = std::move(name);
}

bool Dnode::IsDirectory() const { return vnode_->IsDirectory(); }

Dnode::Dnode(fbl::RefPtr<VnodeMemfs> vn, std::unique_ptr<char[]> name, uint32_t flags)
    : vnode_(std::move(vn)),
      parent_(nullptr),
      ordering_token_(0),
      flags_(flags),
      name_(std::move(name)) {}

Dnode::~Dnode() = default;

size_t Dnode::NameLen() const { return flags_ & kDnodeNameMax; }

bool Dnode::NameMatch(std::string_view name) const {
  return name == std::string_view(name_.get(), NameLen());
}

}  // namespace memfs
