// Copyright 2021 The ChromiumOS Authors
// 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 FsattrRequest::ReplyFsattr(const struct statvfs& fs_attr) {
  DCHECK(!replied_);
  fuse_reply_statfs(req_, &fs_attr);
  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_);
  replied_ = true;

  DCHECK_NE(0, fh);
  fuse_file_info fi = {0};
  fi.fh = fh;

  if (create_) {
    DCHECK_GT(entry_.ino, FUSE_ROOT_ID);
    fuse_reply_create(req_, &entry_, &fi);
  } else {
    fuse_reply_open(req_, &fi);
  }
}

void CreateRequest::ReplyCreate(const fuse_entry_param& entry, uint64_t fh) {
  DCHECK(!replied_);
  replied_ = true;

  DCHECK_NE(0, fh);
  fuse_file_info fi = {0};
  fi.fh = fh;

  DCHECK(create_);
  fuse_reply_create(req_, &entry, &fi);
}

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,
                                 size_t buf_size,
                                 off_t dir_offset)
    : FuseRequest(req, fi), buf_size_(buf_size), dir_offset_(dir_offset) {
  DCHECK(buf_size_);
}

bool DirEntryRequest::AddEntry(const struct DirEntry& entry, off_t dir_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[]>(buf_size_);
    CHECK(buf_.get());
    buf_offset_ = 0;
  }

  char* data = buf_.get() + buf_offset_;
  const size_t size = buf_size_ - buf_offset_;
  size_t used = fuse_add_direntry(req_, data, size, name, &stat, dir_offset);
  if (used > size) {
    return false;  // no |buf_| space.
  }

  buf_offset_ += used;
  CHECK_LE(buf_offset_, buf_size_);
  dir_offset_ = dir_offset;
  return true;
}

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

DirEntryBuffer::DirEntryBuffer() = default;

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

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

int DirEntryBuffer::AppendResponse(int error) {
  error_ = error;
  Respond();
  return error;
}

void DirEntryBuffer::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 dir_offset = request->dir_offset();
    if (dir_offset < 0) {
      request->ReplyError(EINVAL);
      return true;
    }

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

    DCHECK_GE(dir_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
