// Copyright 2018 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/blobfs/directory.h"

#include <fidl/fuchsia.device/cpp/wire.h>
#include <lib/sync/completion.h>
#include <stdlib.h>
#include <string.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

#include <string_view>
#include <utility>
#include <vector>

#include <fbl/ref_ptr.h>

#include "src/lib/digest/digest.h"
#include "src/storage/blobfs/blob.h"
#include "src/storage/blobfs/blobfs.h"
#include "src/storage/blobfs/delivery_blob.h"

namespace blobfs {

Directory::Directory(Blobfs* bs) : blobfs_(bs) {}

Directory::~Directory() = default;

fuchsia_io::NodeProtocolKinds Directory::GetProtocols() const {
  return fuchsia_io::NodeProtocolKinds::kDirectory;
}

zx_status_t Directory::Readdir(fs::VdirCookie* cookie, void* dirents, size_t len,
                               size_t* out_actual) {
  return blobfs_->Readdir(cookie, dirents, len, out_actual);
}

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("blobfs", "Directory::Lookup", "name", name);
  assert(memchr(name.data(), '/', name.length()) == nullptr);

  return blobfs_->node_operations().lookup.Track([&] {
    if (name == ".") {
      // Special case: Accessing root directory via '.'
      *out = fbl::RefPtr<Directory>(this);
      return ZX_OK;
    }

    // Special case: If this is a delivery blob, we have to strip the prefix.
    if (name.length() > kDeliveryBlobPrefix.length() &&
        name.substr(0, kDeliveryBlobPrefix.length()) == kDeliveryBlobPrefix) {
      name.remove_prefix(kDeliveryBlobPrefix.length());
    }

    Digest digest;
    if (zx_status_t status = digest.Parse(name.data(), name.length()); status != ZX_OK) {
      return status;
    }
    fbl::RefPtr<CacheNode> cache_node;
    if (zx_status_t status = blobfs_->GetCache().Lookup(digest, &cache_node); status != ZX_OK) {
      return status;
    }
    auto vnode = fbl::RefPtr<Blob>::Downcast(std::move(cache_node));
    blobfs_->GetMetrics()->UpdateLookup(vnode->FileSize());
    *out = std::move(vnode);
    return ZX_OK;
  });
}

zx_status_t Directory::GetAttributes(fs::VnodeAttributes* a) {
  *a = fs::VnodeAttributes();
  a->mode = V_TYPE_DIR | V_IRUSR;
  a->inode = fuchsia_io::wire::kInoUnknown;
  a->content_size = 0;
  a->storage_size = 0;
  a->link_count = 1;
  a->creation_time = 0;
  a->modification_time = 0;
  return ZX_OK;
}

zx::result<fbl::RefPtr<fs::Vnode>> Directory::Create(std::string_view name, fs::CreationType type) {
  TRACE_DURATION("blobfs", "Directory::Create", "name", name);
  ZX_DEBUG_ASSERT(name.find('/') == std::string_view::npos);

  fbl::RefPtr<Blob> new_blob;
  zx_status_t status = blobfs_->node_operations().create.Track([&]() -> zx_status_t {
    switch (type) {
      case fs::CreationType::kFile:
        break;
      default:
        return ZX_ERR_INVALID_ARGS;
    }

    bool is_delivery_blob = false;
    // Special case: If this is a delivery blob, we have to strip the prefix.
    if (name.length() > kDeliveryBlobPrefix.length() &&
        name.substr(0, kDeliveryBlobPrefix.length()) == kDeliveryBlobPrefix) {
      name.remove_prefix(kDeliveryBlobPrefix.length());
      is_delivery_blob = true;
    }

    Digest digest;
    if (zx_status_t status = digest.Parse(name.data(), name.length()); status != ZX_OK) {
      return status;
    }

    new_blob = fbl::AdoptRef(new Blob(*blobfs_, digest, is_delivery_blob));
    if (zx_status_t status = blobfs_->GetCache().Add(new_blob); status != ZX_OK) {
      return status;
    }
    if (zx_status_t status = new_blob->Open(nullptr); status != ZX_OK) {
      return status;
    }
    return ZX_OK;
  });
  return zx::make_result(status, std::move(new_blob));
}

zx::result<std::string> Directory::GetDevicePath() const {
  return blobfs_->Device()->GetTopologicalPath();
}

zx_status_t Directory::Unlink(std::string_view name, bool must_be_dir) {
  TRACE_DURATION("blobfs", "Directory::Unlink", "name", name, "must_be_dir", must_be_dir);
  assert(memchr(name.data(), '/', name.length()) == nullptr);

  return blobfs_->node_operations().unlink.Track([&] {
    Digest digest;
    if (zx_status_t status = digest.Parse(name.data(), name.length()); status != ZX_OK) {
      return status;
    }
    fbl::RefPtr<CacheNode> cache_node;
    if (zx_status_t status = blobfs_->GetCache().Lookup(digest, &cache_node); status != ZX_OK) {
      return status;
    }
    auto vnode = fbl::RefPtr<Blob>::Downcast(std::move(cache_node));
    blobfs_->GetMetrics()->UpdateLookup(vnode->FileSize());
    return vnode->QueueUnlink();
  });
}

void Directory::Sync(SyncCallback closure) {
  auto event = blobfs_->node_operations().sync.NewEvent();
  blobfs_->Sync(
      [this, cb = std::move(closure), event = std::move(event)](zx_status_t status) mutable {
        // This callback will be issued on the journal thread in the normal case. This is important
        // because the flush must happen there or it will block the main thread which would block
        // processing other requests.
        //
        // If called during shutdown this may get issued on the main thread but then the flush
        // transaction should be a no-op.
        if (status == ZX_OK) {
          status = blobfs_->Flush();
        }
        cb(status);
        event.SetStatus(status);
      });
}

}  // namespace blobfs
