// 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 <utility>

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

namespace memfs {

// Create a new dnode and attach it to a vnode
std::unique_ptr<Dnode> Dnode::Create(fbl::StringPiece 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(fbl::StringPiece 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 = ::llcpp::fuchsia::io::INO_UNKNOWN;
    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(fbl::StringPiece(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(fbl::StringPiece name) const {
  return name == fbl::StringPiece(name_.get(), NameLen());
}

}  // namespace memfs
