// 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 "src/storage/minfs/directory.h"

#include <fcntl.h>
#include <lib/fit/defer.h>
#include <lib/syslog/cpp/macros.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <zircon/time.h>

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

#include <fbl/algorithm.h>

#include "lib/zx/status.h"
#include "src/lib/storage/vfs/cpp/debug.h"
#include "src/lib/storage/vfs/cpp/vfs_types.h"
#include "zircon/assert.h"
#include "zircon/errors.h"

#ifdef __Fuchsia__
#include <lib/fidl-utils/bind.h>
#include <zircon/syscalls.h>

#include <utility>

#include <fbl/auto_lock.h>
#endif

#include "src/storage/minfs/minfs_private.h"
#include "src/storage/minfs/unowned_vmo_buffer.h"
#include "src/storage/minfs/vnode.h"

namespace minfs {
namespace {

zx::status<> ValidateDirent(Dirent* de, size_t bytes_read, size_t off) {
  if (bytes_read < kMinfsDirentSize) {
    FX_LOGS(ERROR) << "vn_dir: Short read (" << bytes_read << " bytes) at offset " << off;
    return zx::error(ZX_ERR_IO);
  }
  uint32_t reclen = static_cast<uint32_t>(DirentReservedSize(de, off));
  if (reclen < kMinfsDirentSize) {
    FX_LOGS(ERROR) << "vn_dir: Could not read dirent at offset: " << off;
    return zx::error(ZX_ERR_IO);
  }
  if ((off + reclen > kMinfsMaxDirectorySize) || (reclen & kMinfsDirentAlignmentMask)) {
    FX_LOGS(ERROR) << "vn_dir: bad reclen " << reclen << " > " << kMinfsMaxDirectorySize;
    return zx::error(ZX_ERR_IO);
  }
  if (de->ino != 0) {
    if ((de->namelen == 0) || (de->namelen > (reclen - kMinfsDirentSize))) {
      FX_LOGS(ERROR) << "vn_dir: bad namelen " << de->namelen << " / " << reclen;
      return zx::error(ZX_ERR_IO);
    }
  }
  return zx::ok();
}

}  // namespace

Directory::Directory(Minfs* fs) : VnodeMinfs(fs) {}

Directory::~Directory() = default;

blk_t Directory::GetBlockCount() const { return GetInode()->block_count; }

uint64_t Directory::GetSize() const { return GetInode()->size; }

void Directory::SetSize(uint32_t new_size) { GetMutableInode()->size = new_size; }

void Directory::AcquireWritableBlock(Transaction* transaction, blk_t local_bno, blk_t old_bno,
                                     blk_t* out_bno) {
  bool using_new_block = (old_bno == 0);
  if (using_new_block) {
    Vfs()->BlockNew(transaction, out_bno);
    GetMutableInode()->block_count++;
  }
}

void Directory::DeleteBlock(PendingWork* transaction, blk_t local_bno, blk_t old_bno,
                            bool indirect) {
  // If we found a block that was previously allocated, delete it.
  if (old_bno != 0) {
    transaction->DeallocateBlock(old_bno);
    GetMutableInode()->block_count--;
  }
}

#ifdef __Fuchsia__
void Directory::IssueWriteback(Transaction* transaction, blk_t vmo_offset, blk_t dev_offset,
                               blk_t count) {
  storage::Operation operation = {
      .type = storage::OperationType::kWrite,
      .vmo_offset = vmo_offset,
      .dev_offset = dev_offset,
      .length = count,
  };
  UnownedVmoBuffer buffer(vmo());
  transaction->EnqueueMetadata(operation, &buffer);
}

bool Directory::HasPendingAllocation(blk_t vmo_offset) { return false; }

void Directory::CancelPendingWriteback() {}

#endif

zx::status<Directory::IteratorCommand> Directory::DirentCallbackFind(fbl::RefPtr<Directory> vndir,
                                                                     Dirent* de, DirArgs* args) {
  if ((de->ino != 0) && std::string_view(de->name, de->namelen) == args->name) {
    args->ino = de->ino;
    args->type = de->type;
    return zx::ok(IteratorCommand::kIteratorDone);
  }
  return NextDirent(de, &args->offs);
}

zx::status<> Directory::CanUnlink() const {
  // directories must be empty (dirent_count == 2)
  if (GetInode()->dirent_count != 2) {
    // if we have more than "." and "..", not empty, cannot unlink
    return zx::error(ZX_ERR_NOT_EMPTY);
#ifdef __Fuchsia__
  } else if (IsRemote()) {
    // we cannot unlink mount points
    return zx::error(ZX_ERR_UNAVAILABLE);
#endif
  }
  return zx::ok();
}

zx::status<Directory::IteratorCommand> Directory::UnlinkChild(Transaction* transaction,
                                                              fbl::RefPtr<VnodeMinfs> childvn,
                                                              Dirent* de, DirectoryOffset* offs) {
  // Coalesce the current dirent with the previous/next dirent, if they
  // (1) exist and (2) are free.
  size_t off_prev = offs->off_prev;
  size_t off = offs->off;
  size_t off_next = off + DirentReservedSize(de, off);

  // Read the direntries we're considering merging with.
  // Verify they are free and small enough to merge.
  size_t coalesced_size = DirentReservedSize(de, off);
  // Coalesce with "next" first, so the kMinfsReclenLast bit can easily flow
  // back to "de" and "de_prev".
  if (!(de->reclen & kMinfsReclenLast)) {
    Dirent de_next;
    size_t len = kMinfsDirentSize;
    if (auto status = ReadExactInternal(transaction, &de_next, len, off_next); status.is_error()) {
      FX_LOGS(ERROR) << "unlink: Failed to read next dirent";
      return status.take_error();
    }
    if (auto status = ValidateDirent(&de_next, len, off_next); status.is_error()) {
      FX_LOGS(ERROR) << "unlink: Read invalid dirent";
      return status.take_error();
    }
    if (de_next.ino == 0) {
      coalesced_size += DirentReservedSize(&de_next, off_next);
      // If the next entry *was* last, then 'de' is now last.
      de->reclen |= (de_next.reclen & kMinfsReclenLast);
    }
  }
  if (off_prev != off) {
    Dirent de_prev;
    size_t len = kMinfsDirentSize;
    if (auto status = ReadExactInternal(transaction, &de_prev, len, off_prev); status.is_error()) {
      FX_LOGS(ERROR) << "unlink: Failed to read previous dirent";
      return status.take_error();
    }
    if (auto status = ValidateDirent(&de_prev, len, off_prev); status.is_error()) {
      FX_LOGS(ERROR) << "unlink: Read invalid dirent";
      return status.take_error();
    }
    if (de_prev.ino == 0) {
      coalesced_size += DirentReservedSize(&de_prev, off_prev);
      off = off_prev;
    }
  }

  if (!(de->reclen & kMinfsReclenLast) && (coalesced_size >= kMinfsReclenMask)) {
    // Should only be possible if the on-disk record format is corrupted
    FX_LOGS(ERROR) << "unlink: Corrupted direntry with impossibly large size";
    return zx::error(ZX_ERR_IO);
  }
  de->ino = 0;
  de->reclen =
      static_cast<uint32_t>(coalesced_size & kMinfsReclenMask) | (de->reclen & kMinfsReclenLast);
  // Erase dirent (replace with 'empty' dirent)
  if (auto status = WriteExactInternal(transaction, de, kMinfsDirentSize, off); status.is_error()) {
    return status.take_error();
  }

  if (de->reclen & kMinfsReclenLast) {
    // Truncating the directory merely removed unused space; if it fails,
    // the directory contents are still valid.
    [[maybe_unused]] auto _ = TruncateInternal(transaction, off + kMinfsDirentSize);
  }

  GetMutableInode()->dirent_count--;

  if (MinfsMagicType(childvn->GetInode()->magic) == kMinfsTypeDir) {
    // Child directory had '..' which pointed to parent directory
    GetMutableInode()->link_count--;
  }

  if (auto status = childvn->RemoveInodeLink(transaction); status.is_error()) {
    return status.take_error();
  }
  transaction->PinVnode(fbl::RefPtr(this));
  transaction->PinVnode(std::move(childvn));
  return zx::ok(IteratorCommand::kIteratorSaveSync);
}

// caller is expected to prevent unlink of "." or ".."
zx::status<Directory::IteratorCommand> Directory::DirentCallbackUnlink(fbl::RefPtr<Directory> vndir,
                                                                       Dirent* de, DirArgs* args) {
  if ((de->ino == 0) || std::string_view(de->name, de->namelen) != args->name) {
    return NextDirent(de, &args->offs);
  }

  auto vn_or = vndir->Vfs()->VnodeGet(de->ino);
  if (vn_or.is_error()) {
    return vn_or.take_error();
  }

  // If a directory was requested, then only try unlinking a directory
  if ((args->type == kMinfsTypeDir) && !vn_or->IsDirectory()) {
    return zx::error(ZX_ERR_NOT_DIR);
  }
  if (auto status = vn_or->CanUnlink(); status.is_error()) {
    return status.take_error();
  }
  return vndir->UnlinkChild(args->transaction, std::move(vn_or.value()), de, &args->offs);
}

// same as unlink, but do not validate vnode
zx::status<Directory::IteratorCommand> Directory::DirentCallbackForceUnlink(
    fbl::RefPtr<Directory> vndir, Dirent* de, DirArgs* args) {
  if ((de->ino == 0) || std::string_view(de->name, de->namelen) != args->name) {
    return NextDirent(de, &args->offs);
  }

  auto vn_or = vndir->Vfs()->VnodeGet(de->ino);
  if (vn_or.is_error()) {
    return vn_or.take_error();
  }
  return vndir->UnlinkChild(args->transaction, std::move(vn_or.value()), de, &args->offs);
}

// Given a (name, inode, type) combination:
//   - If no corresponding 'name' is found, ZX_ERR_NOT_FOUND is returned
//   - If the 'name' corresponds to a vnode, check that the target vnode:
//      - Does not have the same inode as the argument inode
//      - Is the same type as the argument 'type'
//      - Is unlinkable
//   - If the previous checks pass, then:
//      - Remove the old vnode (decrement link count by one)
//      - Replace the old vnode's position in the directory with the new inode
zx::status<Directory::IteratorCommand> Directory::DirentCallbackAttemptRename(
    fbl::RefPtr<Directory> vndir, Dirent* de, DirArgs* args) {
  if ((de->ino == 0) || std::string_view(de->name, de->namelen) != args->name) {
    return NextDirent(de, &args->offs);
  }

  auto vn_or = vndir->Vfs()->VnodeGet(de->ino);
  if (vn_or.is_error()) {
    return vn_or.take_error();
  }
  if (args->ino == vn_or->GetIno()) {
    // cannot rename node to itself
    return zx::error(ZX_ERR_BAD_STATE);
  }
  if (args->type != de->type) {
    // cannot rename directory to file (or vice versa)
    return args->type == kMinfsTypeDir ? zx::error(ZX_ERR_NOT_DIR) : zx::error(ZX_ERR_NOT_FILE);
  }
  if (auto status = vn_or->CanUnlink(); status.is_error()) {
    // if we cannot unlink the target, we cannot rename the target
    return status.take_error();
  }

  // If we are renaming ON TOP of a directory, then we can skip
  // updating the parent link count -- the old directory had a ".." entry to
  // the parent (link count of 1), but the new directory will ALSO have a ".."
  // entry, making the rename operation idempotent w.r.t. the parent link
  // count.

  if (auto status = vn_or->RemoveInodeLink(args->transaction); status.is_error()) {
    return status.take_error();
  }

  de->ino = args->ino;

  if (auto status =
          vndir->WriteExactInternal(args->transaction, de, DirentSize(de->namelen), args->offs.off);
      status.is_error()) {
    return status.take_error();
  }

  args->transaction->PinVnode(std::move(vn_or.value()));
  args->transaction->PinVnode(vndir);
  return zx::ok(IteratorCommand::kIteratorSaveSync);
}

zx::status<Directory::IteratorCommand> Directory::DirentCallbackUpdateInode(
    fbl::RefPtr<Directory> vndir, Dirent* de, DirArgs* args) {
  if ((de->ino == 0) || std::string_view(de->name, de->namelen) != args->name) {
    return NextDirent(de, &args->offs);
  }

  de->ino = args->ino;

  if (auto status =
          vndir->WriteExactInternal(args->transaction, de, DirentSize(de->namelen), args->offs.off);
      status.is_error()) {
    return status.take_error();
    ;
  }
  args->transaction->PinVnode(vndir);
  return zx::ok(IteratorCommand::kIteratorSaveSync);
}

zx::status<Directory::IteratorCommand> Directory::DirentCallbackFindSpace(
    fbl::RefPtr<Directory> vndir, Dirent* de, DirArgs* args) {
  // Reserved space for this record (possibly going to the max directory size if it's the last
  // one).
  uint32_t reserved_size = static_cast<uint32_t>(DirentReservedSize(de, args->offs.off));
  if (de->ino == 0) {
    // Empty entry, do we fit?
    if (args->reclen > reserved_size) {
      return NextDirent(de, &args->offs);  // Don't fit.
    }
    return zx::ok(IteratorCommand::kIteratorDone);
  }

  // Filled entry, can we sub-divide? The entry might not use the full amount of space reserved for
  // it if a larger entry was later filled with a smaller one. We might be able to fit in the
  // extra.
  uint32_t used_size = static_cast<uint32_t>(DirentSize(de->namelen));
  if (used_size > reserved_size) {
    FX_LOGS(ERROR) << "bad reclen (smaller than dirent) " << reserved_size << " < " << used_size;
    return zx::error(ZX_ERR_IO);
  }
  uint32_t available_size = reserved_size - used_size;
  if (available_size < args->reclen) {
    return NextDirent(de, &args->offs);  // Don't fit in the extra space.
  }

  // Could subdivide this one.
  return zx::ok(IteratorCommand::kIteratorDone);
}

// Updates offset information to move to the next direntry in the directory.
zx::status<Directory::IteratorCommand> Directory::NextDirent(Dirent* de, DirectoryOffset* offs) {
  offs->off_prev = offs->off;
  offs->off += DirentReservedSize(de, offs->off);
  return zx::ok(IteratorCommand::kIteratorNext);
}

zx::status<> Directory::AppendDirent(DirArgs* args) {
  DirentBuffer dirent_buffer;
  Dirent* de = &dirent_buffer.dirent;

  size_t r;
  if (auto status = ReadInternal(args->transaction, de, kMinfsMaxDirentSize, args->offs.off, &r);
      status.is_error()) {
    return status;
  }

  if (auto status = ValidateDirent(de, r, args->offs.off); status.is_error()) {
    return status;
  }

  uint32_t reclen = static_cast<uint32_t>(DirentReservedSize(de, args->offs.off));
  if (de->ino == 0) {
    // empty entry, do we fit?
    if (args->reclen > reclen) {
      FX_LOGS(ERROR) << "Directory::AppendDirent: new entry can't fit in requested empty dirent.";
      return zx::error(ZX_ERR_NO_SPACE);
    }
  } else {
    // filled entry, can we sub-divide?
    uint32_t size = static_cast<uint32_t>(DirentSize(de->namelen));
    if (size > reclen) {
      FX_LOGS(ERROR) << "bad reclen (smaller than dirent) " << reclen << " < " << size;
      return zx::error(ZX_ERR_IO);
    }
    uint32_t extra = reclen - size;
    if (extra < args->reclen) {
      FX_LOGS(ERROR) << "Directory::AppendDirent: new entry can't fit in free space.";
      return zx::error(ZX_ERR_NO_SPACE);
    }
    // shrink existing entry
    bool was_last_record = de->reclen & kMinfsReclenLast;
    de->reclen = size;
    if (auto status =
            WriteExactInternal(args->transaction, de, DirentSize(de->namelen), args->offs.off);
        status.is_error()) {
      return status;
    }

    args->offs.off += size;
    // Overwrite dirent data to reflect the new dirent.
    de->reclen = extra | (was_last_record ? kMinfsReclenLast : 0);
  }

  de->ino = args->ino;
  de->type = static_cast<uint8_t>(args->type);
  de->namelen = static_cast<uint8_t>(args->name.length());
  memcpy(de->name, args->name.data(), de->namelen);
  if (auto status =
          WriteExactInternal(args->transaction, de, DirentSize(de->namelen), args->offs.off);
      status.is_error()) {
    return status;
  }

  if (args->type == kMinfsTypeDir) {
    // Child directory has '..' which will point to parent directory
    GetMutableInode()->link_count++;
  }

  GetMutableInode()->dirent_count++;
  GetMutableInode()->seq_num++;
  InodeSync(args->transaction, kMxFsSyncMtime);
  args->transaction->PinVnode(fbl::RefPtr(this));
  return zx::ok();
}

// Calls a callback 'func' on all direntries in a directory 'vn' with the
// provided arguments, reacting to the return code of the callback.
//
// When 'func' is called, it receives a few arguments:
//  'vndir': The directory on which the callback is operating
//  'de': A pointer the start of a single dirent.
//        Only DirentSize(de->namelen) bytes are guaranteed to exist in
//        memory from this starting pointer.
//  'args': Additional arguments plumbed through ForEachDirent
//  'offs': Offset info about where in the directory this direntry is located.
//          Since 'func' may create / remove surrounding dirents, it is responsible for
//          updating the offset information to access the next dirent.
zx::status<bool> Directory::ForEachDirent(DirArgs* args, const DirentCallback func) {
  DirentBuffer dirent_buffer;
  Dirent* de = &dirent_buffer.dirent;

  args->offs.off = 0;
  args->offs.off_prev = 0;
  while (args->offs.off + kMinfsDirentSize < kMinfsMaxDirectorySize && args->offs.off < GetSize()) {
    FX_LOGS(DEBUG) << "Reading dirent at offset " << args->offs.off;
    size_t r;

    if (auto status = ReadInternal(args->transaction, de, kMinfsMaxDirentSize, args->offs.off, &r);
        status.is_error()) {
      return status.take_error();
    }
    if (auto status = ValidateDirent(de, r, args->offs.off); status.is_error()) {
      return status.take_error();
    }

    auto command_or = func(fbl::RefPtr<Directory>(this), de, args);
    if (command_or.is_error()) {
      return command_or.take_error();
    }

    switch (command_or.value()) {
      case IteratorCommand::kIteratorNext:
        break;
      case IteratorCommand::kIteratorSaveSync:
        GetMutableInode()->seq_num++;
        InodeSync(args->transaction, kMxFsSyncMtime);
        args->transaction->PinVnode(fbl::RefPtr(this));
        return zx::ok(true);
      case IteratorCommand::kIteratorDone:
        return zx::ok(true);
    }
  }

  return zx::ok(false);
}

fs::VnodeProtocolSet Directory::GetProtocols() const { return fs::VnodeProtocol::kDirectory; }

zx_status_t Directory::Read(void* data, size_t len, size_t off, size_t* out_actual) {
  return ZX_ERR_NOT_FILE;
}

zx_status_t Directory::Write(const void* data, size_t len, size_t offset, size_t* out_actual) {
  return ZX_ERR_NOT_FILE;
}

zx_status_t Directory::Append(const void* data, size_t len, size_t* out_end, size_t* out_actual) {
  return ZX_ERR_NOT_FILE;
}

zx_status_t Directory::Lookup(std::string_view name, fbl::RefPtr<fs::Vnode>* out) {
  TRACE_DURATION("minfs", "Directory::Lookup", "name", name);
  ZX_DEBUG_ASSERT(fs::IsValidName(name));

  return Vfs()->GetNodeOperations()->lookup.Track([&] {
    auto vn_or = LookupInternal(name);
    if (vn_or.is_ok()) {
      *out = std::move(vn_or.value());
    }

    return vn_or.status_value();
  });
}

zx::status<fbl::RefPtr<fs::Vnode>> Directory::LookupInternal(std::string_view name) {
  DirArgs args;
  args.name = name;

  zx::status<bool> found_or = ForEachDirent(&args, DirentCallbackFind);
  if (found_or.is_error()) {
    return found_or.take_error();
  }
  if (!found_or.value()) {
    return zx::error(ZX_ERR_NOT_FOUND);
  }

  auto vn_or = Vfs()->VnodeGet(args.ino);
  if (vn_or.is_error()) {
    return vn_or.take_error();
  }

  return zx::ok(std::move(vn_or.value()));
}

struct DirCookie {
  size_t off;         // Offset into directory
  uint32_t reserved;  // Unused
  uint32_t seqno;     // inode seq no
};

static_assert(sizeof(DirCookie) <= sizeof(fs::VdirCookie),
              "MinFS DirCookie too large to fit in IO state");

zx_status_t Directory::Readdir(fs::VdirCookie* cookie, void* dirents, size_t len,
                               size_t* out_actual) {
  TRACE_DURATION("minfs", "Directory::Readdir");
  FX_LOGS(DEBUG) << "minfs_readdir() vn=" << this << "(#" << GetIno() << ") cookie=" << cookie
                 << " len=" << len;

  return Vfs()->GetNodeOperations()->read_dir.Track([&] {
    if (IsUnlinked()) {
      *out_actual = 0;
      return ZX_OK;
    }

    DirCookie* dc = reinterpret_cast<DirCookie*>(cookie);
    fs::DirentFiller df(dirents, len);

    size_t off = dc->off;
    size_t r;

    DirentBuffer dirent_buffer;
    Dirent* de = &dirent_buffer.dirent;

    if (off != 0 && dc->seqno != GetInode()->seq_num) {
      // The offset *might* be invalid, if we called Readdir after a directory
      // has been modified. In this case, we need to re-read the directory
      // until we get to the direntry at or after the previously identified offset.

      size_t off_recovered = 0;
      while (off_recovered < off) {
        if (off_recovered + kMinfsDirentSize >= kMinfsMaxDirectorySize) {
          FX_LOGS(ERROR) << "Readdir: Corrupt dirent; dirent reclen too large";
          goto fail;
        }
        auto read_status = ReadInternal(nullptr, de, kMinfsMaxDirentSize, off_recovered, &r);
        if (read_status.is_error() || ValidateDirent(de, r, off_recovered).is_error()) {
          FX_LOGS(ERROR) << "Readdir: Corrupt dirent unreadable/failed validation";
          goto fail;
        }
        off_recovered += DirentReservedSize(de, off_recovered);
      }
      off = off_recovered;
    }

    while (off + kMinfsDirentSize < kMinfsMaxDirectorySize) {
      if (auto status = ReadInternal(nullptr, de, kMinfsMaxDirentSize, off, &r);
          status.is_error()) {
        FX_LOGS(ERROR) << "Readdir: Unreadable dirent " << status.status_value();
        goto fail;
      }
      if (auto status = ValidateDirent(de, r, off); status.is_error()) {
        FX_LOGS(ERROR) << "Readdir: Corrupt dirent failed validation " << status.status_value();
        goto fail;
      }

      std::string_view name(de->name, de->namelen);

      if (de->ino && name != "..") {
        zx_status_t status;
        if ((status = df.Next(name, de->type, de->ino)) != ZX_OK) {
          // no more space
          goto done;
        }
      }

      off += DirentReservedSize(de, off);
    }

  done:
    // save our place in the DirCookie
    dc->off = off;
    dc->seqno = GetInode()->seq_num;
    *out_actual = df.BytesFilled();
    ZX_DEBUG_ASSERT(*out_actual <= len);  // Otherwise, we're overflowing the input buffer.
    return ZX_OK;

  fail:
    dc->off = 0;
    return ZX_ERR_IO;
  });
}

zx_status_t Directory::Create(std::string_view name, uint32_t mode, fbl::RefPtr<fs::Vnode>* out) {
  TRACE_DURATION("minfs", "Directory::Create", "name", name);

  if (!fs::IsValidName(name)) {
    return ZX_ERR_INVALID_ARGS;
  }

  if (IsUnlinked()) {
    return ZX_ERR_BAD_STATE;
  }

  DirArgs args;
  args.name = name;

  // Ensure file does not exist.
  {
    TRACE_DURATION("minfs", "Directory::Create::ExistenceCheck");
    zx::status<bool> found_or = ForEachDirent(&args, DirentCallbackFind);
    if (found_or.is_error()) {
      return found_or.error_value();
    }
    if (found_or.value()) {
      return ZX_ERR_ALREADY_EXISTS;
    }
  }

  // Creating a directory?
  uint32_t type = S_ISDIR(mode) ? kMinfsTypeDir : kMinfsTypeFile;

  // Ensure that we have enough space to write the new vnode's direntry
  // before updating any other metadata.
  {
    TRACE_DURATION("minfs", "Directory::Create::SpaceCheck");
    args.type = type;
    args.reclen = static_cast<uint32_t>(DirentSize(static_cast<uint8_t>(name.length())));
    zx::status<bool> found_or = ForEachDirent(&args, DirentCallbackFindSpace);
    if (found_or.is_error()) {
      return found_or.error_value();
    }
    if (!found_or.value()) {
      FX_LOGS(WARNING) << "Directory::Create: Can't find a dirent to put this file.";
      return ZX_ERR_NO_SPACE;
    }
  }

  // Calculate maximum blocks to reserve for the current directory, based on the size and offset
  // of the new direntry (Assuming that the offset is the current size of the directory).
  auto reserve_blocks_or = GetRequiredBlockCount(GetSize(), args.reclen, Vfs()->BlockSize());
  if (reserve_blocks_or.is_error()) {
    return reserve_blocks_or.error_value();
  }

  // Reserve 1 additional block for the new directory's initial . and .. entries.
  blk_t reserve_blocks = reserve_blocks_or.value() + 1;

  ZX_DEBUG_ASSERT(reserve_blocks <= Vfs()->Limits().GetMaximumMetaDataBlocks());
  zx_status_t status;

  // In addition to reserve_blocks, reserve 1 inode for the vnode to be created.
  auto transaction_or = Vfs()->BeginTransaction(1, reserve_blocks);
  if (transaction_or.is_error()) {
    return transaction_or.error_value();
  }

  // mint a new inode and vnode for it
  auto vn_or = Vfs()->VnodeNew(transaction_or.value().get(), type);
  if (vn_or.is_error()) {
    return vn_or.error_value();
  }

  // If the new node is a directory, fill it with '.' and '..'.
  if (type == kMinfsTypeDir) {
    TRACE_DURATION("minfs", "Directory::Create::InitDir");
    char bdata[DirentSize(1) + DirentSize(2)];
    InitializeDirectory(bdata, vn_or->GetIno(), GetIno());
    size_t expected = DirentSize(1) + DirentSize(2);
    if (auto status = vn_or->WriteExactInternal(transaction_or.value().get(), bdata, expected, 0);
        status.is_error()) {
      FX_LOGS(ERROR) << "Create: Failed to initialize empty directory: " << status.status_value();
      return ZX_ERR_IO;
    }
    vn_or->InodeSync(transaction_or.value().get(), kMxFsSyncDefault);
  }

  // add directory entry for the new child node
  args.ino = vn_or->GetIno();
  args.transaction = transaction_or.value().get();
  if (auto status = AppendDirent(&args); status.is_error()) {
    return status.error_value();
  }

  transaction_or->PinVnode(fbl::RefPtr(this));
  transaction_or->PinVnode(vn_or.value());
  Vfs()->CommitTransaction(std::move(transaction_or.value()));

  if ((status = vn_or->OpenValidating(fs::VnodeConnectionOptions(), nullptr)) != ZX_OK) {
    return status;
  }
  *out = std::move(vn_or.value());
  return ZX_OK;
}

zx_status_t Directory::Unlink(std::string_view name, bool must_be_dir) {
  TRACE_DURATION("minfs", "Directory::Unlink", "name", name);
  ZX_DEBUG_ASSERT(fs::IsValidName(name));
  return Vfs()->GetNodeOperations()->unlink.Track([&] {
    auto transaction_or = Vfs()->BeginTransaction(0, 0);
    if (transaction_or.is_error()) {
      return transaction_or.error_value();
    }

    DirArgs args;
    args.name = name;
    args.type = must_be_dir ? kMinfsTypeDir : 0;
    args.transaction = transaction_or.value().get();

    zx::status<bool> found_or = ForEachDirent(&args, DirentCallbackUnlink);
    if (found_or.is_error()) {
      return found_or.error_value();
    }
    if (!found_or.value()) {
      return ZX_ERR_NOT_FOUND;
    }
    transaction_or->PinVnode(fbl::RefPtr(this));
    Vfs()->CommitTransaction(std::move(transaction_or.value()));
    return ZX_OK;
  });
}

zx_status_t Directory::Truncate(size_t len) { return ZX_ERR_NOT_FILE; }

// Verify that the 'newdir' inode is not a subdirectory of the source.
zx::status<> Directory::CheckNotSubdirectory(fbl::RefPtr<Directory> newdir) {
  fbl::RefPtr<Directory> vn = std::move(newdir);
  zx::status<> status = zx::ok();
  while (vn->GetIno() != kMinfsRootIno) {
    if (vn->GetIno() == GetIno()) {
      status = zx::error(ZX_ERR_INVALID_ARGS);
      break;
    }

    auto lookup_or = vn->LookupInternal("..");
    if (lookup_or.is_error()) {
      status = lookup_or.take_error();
      break;
    }
    vn = fbl::RefPtr<Directory>::Downcast(lookup_or.value());
  }
  return status;
}

zx_status_t Directory::Rename(fbl::RefPtr<fs::Vnode> _newdir, std::string_view oldname,
                              std::string_view newname, bool src_must_be_dir,
                              bool dst_must_be_dir) {
  TRACE_DURATION("minfs", "Directory::Rename", "src", oldname, "dst", newname);
  ZX_DEBUG_ASSERT(fs::IsValidName(oldname));
  ZX_DEBUG_ASSERT(fs::IsValidName(newname));

  auto newdir_minfs = fbl::RefPtr<VnodeMinfs>::Downcast(_newdir);

  // Ensure that the vnodes containing oldname and newname are directories.
  if (!(newdir_minfs->IsDirectory())) {
    return ZX_ERR_NOT_SUPPORTED;
  }
  if (newdir_minfs->IsUnlinked()) {
    return ZX_ERR_NOT_FOUND;
  }
  auto newdir = fbl::RefPtr<Directory>::Downcast(newdir_minfs);

  // Acquire the 'oldname' node (it must exist).
  DirArgs args;
  args.name = oldname;

  if (zx::status<bool> found_or = ForEachDirent(&args, DirentCallbackFind); found_or.is_error()) {
    return found_or.error_value();
  } else if (!found_or.value()) {
    return ZX_ERR_NOT_FOUND;
  }

  auto oldvn_or = Vfs()->VnodeGet(args.ino);
  if (oldvn_or.is_error()) {
    return oldvn_or.error_value();
  }
  if (oldvn_or->IsDirectory()) {
    auto olddir = fbl::RefPtr<Directory>::Downcast(oldvn_or.value());
    if (auto status = olddir->CheckNotSubdirectory(newdir); status.is_error()) {
      return status.error_value();
    }
  }

  // If either the 'src' or 'dst' must be directories, BOTH of them must be directories.
  if (!oldvn_or->IsDirectory() && (src_must_be_dir || dst_must_be_dir)) {
    return ZX_ERR_NOT_DIR;
  }
  if ((newdir->GetIno() == GetIno()) && (oldname == newname)) {
    // Renaming a file or directory to itself?
    // Shortcut success case.
    return ZX_OK;
  }

  // Ensure that we have enough space to write the vnode's new direntry
  // before updating any other metadata.
  args.type = oldvn_or->IsDirectory() ? kMinfsTypeDir : kMinfsTypeFile;
  args.reclen = static_cast<uint32_t>(DirentSize(static_cast<uint8_t>(newname.length())));

  if (zx::status<bool> found_or = newdir->ForEachDirent(&args, DirentCallbackFindSpace);
      found_or.is_error()) {
    return found_or.error_value();
  } else if (!found_or.value()) {
    FX_LOGS(WARNING) << "Directory::Rename: Can't find a dirent to put this file.";
    return ZX_ERR_NO_SPACE;
  }

  DirectoryOffset append_offs = args.offs;

  // Reserve potential blocks to add a new direntry to newdir.
  auto reserved_blocks_or =
      GetRequiredBlockCount(newdir->GetInode()->size, args.reclen, Vfs()->BlockSize());
  if (reserved_blocks_or.is_error()) {
    return reserved_blocks_or.error_value();
  }

  auto transaction_or = Vfs()->BeginTransaction(0, reserved_blocks_or.value());
  if (transaction_or.is_error()) {
    return transaction_or.error_value();
  }

  // If the entry for 'newname' exists, make sure it can be replaced by
  // the vnode behind 'oldname'.
  args.transaction = transaction_or.value().get();
  args.name = newname;
  args.ino = oldvn_or->GetIno();

  if (zx::status<bool> found_or = newdir->ForEachDirent(&args, DirentCallbackAttemptRename);
      found_or.is_error()) {
    return found_or.error_value();
  } else if (!found_or.value()) {
    // If 'newname' does not exist, create it.
    args.offs = append_offs;
    if (auto status = newdir->AppendDirent(&args); status.is_error()) {
      return status.error_value();
    }
  }

  // Update the oldvn's entry for '..' if (1) it was a directory, and (2) it moved to a new
  // directory.
  if ((args.type == kMinfsTypeDir) && (GetIno() != newdir->GetIno())) {
    fbl::RefPtr<fs::Vnode> vn_fs;
    if (zx_status_t status = newdir->Lookup(newname, &vn_fs); status < 0) {
      return status;
    }
    auto vn = fbl::RefPtr<Directory>::Downcast(vn_fs);
    args.name = "..";
    args.ino = newdir->GetIno();

    if (zx::status<bool> found_or = vn->ForEachDirent(&args, DirentCallbackUpdateInode);
        found_or.is_error()) {
      return found_or.error_value();
    } else if (!found_or.value()) {
      return ZX_ERR_NOT_FOUND;
    }
  }

  // At this point, the oldvn exists with multiple names (or the same name in different
  // directories).
  oldvn_or->AddLink();

  // finally, remove oldname from its original position
  args.name = oldname;
  zx::status<bool> found_or = ForEachDirent(&args, DirentCallbackForceUnlink);
  if (found_or.is_error()) {
    return found_or.error_value();
  }
  if (!found_or.value()) {
    return ZX_ERR_NOT_FOUND;
  }
  transaction_or->PinVnode(std::move(oldvn_or.value()));
  transaction_or->PinVnode(std::move(newdir));
  Vfs()->CommitTransaction(std::move(transaction_or.value()));
  return ZX_OK;
}

zx_status_t Directory::Link(std::string_view name, fbl::RefPtr<fs::Vnode> _target) {
  TRACE_DURATION("minfs", "Directory::Link", "name", name);
  ZX_DEBUG_ASSERT(fs::IsValidName(name));

  return Vfs()->GetNodeOperations()->link.Track([&] {
    if (IsUnlinked()) {
      return ZX_ERR_BAD_STATE;
    }

    auto target = fbl::RefPtr<VnodeMinfs>::Downcast(_target);
    if (target->IsDirectory()) {
      // The target must not be a directory
      return ZX_ERR_NOT_FILE;
    }

    // The destination should not exist
    DirArgs args;
    args.name = name;
    zx::status<bool> found_or = ForEachDirent(&args, DirentCallbackFind);
    if (found_or.is_error()) {
      return found_or.error_value();
    }
    if (found_or.value()) {
      return ZX_ERR_ALREADY_EXISTS;
    }

    // Ensure that we have enough space to write the new vnode's direntry
    // before updating any other metadata.
    args.type = kMinfsTypeFile;  // We can't hard link directories
    args.reclen = static_cast<uint32_t>(DirentSize(static_cast<uint8_t>(name.length())));
    if (zx::status<bool> found_or = ForEachDirent(&args, DirentCallbackFindSpace);
        found_or.is_error()) {
      return found_or.error_value();
    } else if (!found_or.value()) {
      FX_LOGS(WARNING) << "Directory::Link: Can't find a dirent to put this file.";
      return ZX_ERR_NO_SPACE;
    }

    // Reserve potential blocks to write a new direntry.
    auto reserved_blocks_or =
        GetRequiredBlockCount(GetInode()->size, args.reclen, Vfs()->BlockSize());
    if (reserved_blocks_or.is_error()) {
      return reserved_blocks_or.error_value();
    }

    auto transaction_or = Vfs()->BeginTransaction(0, reserved_blocks_or.value());
    if (transaction_or.is_error()) {
      return transaction_or.error_value();
    }

    args.ino = target->GetIno();
    args.transaction = transaction_or.value().get();
    if (auto status = AppendDirent(&args); status.is_error()) {
      return status.error_value();
    }

    // We have successfully added the vn to a new location. Increment the link count.
    target->AddLink();
    target->InodeSync(transaction_or.value().get(), kMxFsSyncDefault);
    transaction_or->PinVnode(fbl::RefPtr(this));
    transaction_or->PinVnode(target);
    Vfs()->CommitTransaction(std::move(transaction_or.value()));
    return ZX_OK;
  });
}

}  // namespace minfs
