// Copyright 2021 The Chromium OS 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 "fusebox/fuse_request.h"

#include <utility>

#include <base/check.h>
#include <base/check_op.h>

namespace fusebox {

FuseRequest::FuseRequest(fuse_req_t req, fuse_file_info* fi) : req_(req) {
  flags_ = fi ? fi->flags : 0;
  fh_ = fi ? fi->fh : 0;
}

bool FuseRequest::IsInterrupted() const {  // Kernel FUSE interrupt
  return fuse_req_interrupted(req_);
}

FuseRequest::~FuseRequest() {
  if (!replied_)
    fuse_reply_err(req_, EINTR);  // User-space FUSE interrupt
}

int FuseRequest::ReplyError(int error) {
  DCHECK(!replied_);
  DCHECK_GT(error, 0);
  fuse_reply_err(req_, error);
  replied_ = true;
  return error;
}

void OkRequest::ReplyOk() {
  DCHECK(!replied_);
  fuse_reply_err(req_, 0);
  replied_ = true;
}

void NoneRequest::ReplyNone() {
  DCHECK(!replied_);
  fuse_reply_none(req_);
  replied_ = true;
}

void AttrRequest::ReplyAttr(const struct stat& attr, double timeout) {
  DCHECK(!replied_);
  fuse_reply_attr(req_, &attr, timeout);
  replied_ = true;
}

void EntryRequest::ReplyEntry(const fuse_entry_param& entry) {
  DCHECK(!replied_);
  fuse_reply_entry(req_, &entry);
  replied_ = true;
}

void OpenRequest::ReplyOpen(uint64_t fh) {
  DCHECK(!replied_);
  DCHECK_NE(0, fh);
  fuse_file_info fi = {0};
  fi.fh = fh;
  fuse_reply_open(req_, &fi);
  replied_ = true;
}

void CreateRequest::ReplyCreate(const fuse_entry_param& entry, uint64_t fh) {
  DCHECK(!replied_);
  DCHECK_NE(0, fh);
  fuse_file_info fi = {0};
  fi.fh = fh;
  fuse_reply_create(req_, &entry, &fi);
  replied_ = true;
}

void BufferRequest::ReplyBuffer(const void* data, size_t size) {
  DCHECK(!replied_);
  replied_ = true;

  if (data) {
    fuse_reply_buf(req_, static_cast<const char*>(data), size);
  } else {
    fuse_reply_buf(req_, nullptr, 0);
  }
}

void WriteRequest::ReplyWrite(size_t count) {
  DCHECK(!replied_);
  fuse_reply_write(req_, count);
  replied_ = true;
}

DirEntryRequest::DirEntryRequest(
    fuse_req_t req, fuse_file_info* fi, fuse_ino_t ino, size_t size, off_t off)
    : FuseRequest(req, fi), parent_(ino), size_(size), offset_(off) {
  DCHECK(size_);
}

bool DirEntryRequest::AddEntry(const struct DirEntry& entry, off_t offset) {
  DCHECK(!replied_);

  const char* name = entry.name.c_str();
  struct stat stat = {0};
  stat.st_ino = entry.ino;
  stat.st_mode = entry.mode;

  if (!buf_.get()) {
    buf_ = std::make_unique<char[]>(size_);
    CHECK(buf_.get());
    off_ = 0;
  }

  char* data = buf_.get() + off_;
  const size_t size = size_ - off_;
  size_t used = fuse_add_direntry(req_, data, size, name, &stat, offset);
  if (used > size)
    return false;  // no |buf_| space.

  off_ += used;
  CHECK_LE(off_, size_);
  offset_ = offset;
  return true;
}

void DirEntryRequest::ReplyDone() {
  DCHECK(!replied_);
  fuse_reply_buf(req_, buf_.get(), off_);
  replied_ = true;
}

DirEntryResponse::DirEntryResponse(fuse_ino_t ino, uint64_t handle)
    : parent_(ino), handle_(handle) {
  DCHECK(handle_);
}

void DirEntryResponse::Append(std::vector<struct DirEntry> entry, bool end) {
  entry_.insert(entry_.end(), entry.begin(), entry.end());
  end_ = end;
  Respond();
}

void DirEntryResponse::Append(std::unique_ptr<DirEntryRequest> request) {
  request_.emplace_back(std::move(request));
  Respond();
}

int DirEntryResponse::Append(int error) {
  error_ = error;
  Respond();
  return error;
}

void DirEntryResponse::Respond() {
  constexpr size_t kFlushAddedEntries = 25;

  const auto process_next_request = [&](auto& request) {
    if (request->IsInterrupted())
      return true;

    if (error_) {
      request->ReplyError(error_);
      return true;
    }

    off_t offset = request->offset();
    if (offset < 0) {
      request->ReplyError(EINVAL);
      return true;
    }

    size_t added;
    for (added = 0; offset < entry_.size(); ++added) {
      const off_t next = 1 + offset;
      if (request->AddEntry(entry_[offset++], next))
        continue;  // add next entry
      request->ReplyDone();
      return true;
    }

    DCHECK_GE(offset, entry_.size());
    bool done = end_ || added >= kFlushAddedEntries;
    if (done)
      request->ReplyDone();
    return done;
  };

  while (!request_.empty()) {
    if (!process_next_request(*request_.begin()))
      break;
    request_.erase(request_.begin());
  }
}

}  // namespace fusebox
