blob: 2af30855d78d65540d1ce1faa4844ce702f765ad [file] [log] [blame]
// Copyright 2019 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 "smbfs/request.h"
#include <errno.h>
#include <base/logging.h>
#include <base/stl_util.h>
namespace smbfs {
namespace internal {
BaseRequest::BaseRequest(fuse_req_t req) : req_(req) {}
BaseRequest::~BaseRequest() {
if (!replied_) {
// If a reply was not sent, either because the request was interrupted or
// the filesystem is being shut down, send an error reply so that the
// request can be freed.
fuse_reply_err(req_, EINTR);
}
}
bool BaseRequest::IsInterrupted() const {
return fuse_req_interrupted(req_);
}
void BaseRequest::ReplyError(int error) {
DCHECK(!replied_);
DCHECK_GT(error, 0);
fuse_reply_err(req_, error);
replied_ = true;
}
} // namespace internal
void SimpleRequest::ReplyOk() {
DCHECK(!replied_);
fuse_reply_err(req_, 0);
replied_ = true;
}
void StatFsRequest::ReplyStatFs(const struct statvfs& st) {
DCHECK(!replied_);
fuse_reply_statfs(req_, &st);
replied_ = true;
}
void AttrRequest::ReplyAttr(const struct stat& attr, double attr_timeout) {
DCHECK(!replied_);
fuse_reply_attr(req_, &attr, 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 file_handle) {
DCHECK(!replied_);
DCHECK_GT(file_handle, 0);
fuse_file_info info = {0};
info.fh = file_handle;
fuse_reply_open(req_, &info);
replied_ = true;
}
void CreateRequest::ReplyCreate(const fuse_entry_param& entry,
uint64_t file_handle) {
DCHECK(!replied_);
DCHECK_GT(file_handle, 0);
fuse_file_info info = {0};
info.fh = file_handle;
fuse_reply_create(req_, &entry, &info);
replied_ = true;
}
void BufRequest::ReplyBuf(const char* buf, size_t size) {
DCHECK(!replied_);
DCHECK(buf);
fuse_reply_buf(req_, buf, size);
replied_ = true;
}
void WriteRequest::ReplyWrite(size_t written) {
DCHECK(!replied_);
fuse_reply_write(req_, written);
replied_ = true;
}
DirentryRequest::DirentryRequest(fuse_req_t req, size_t size)
: internal::BaseRequest(req),
size_(size),
buf_(std::make_unique<char[]>(size)) {
DCHECK(size_);
}
bool DirentryRequest::AddEntry(base::StringPiece name,
fuse_ino_t inode,
mode_t mode,
off_t next_offset) {
CHECK(mode & S_IFREG || mode & S_IFDIR);
CHECK_EQ(name.find('/'), base::StringPiece::npos);
DCHECK_NE(name, ".");
DCHECK_NE(name, "..");
struct stat stat = {0};
stat.st_ino = inode;
stat.st_mode = mode;
size_t remaining = size_ - off_;
size_t used = fuse_add_direntry(req_, buf_.get() + off_, remaining,
name.data(), &stat, next_offset);
if (used > remaining) {
return false;
}
off_ += used;
return true;
}
void DirentryRequest::ReplyDone() {
DCHECK(!replied_);
fuse_reply_buf(req_, buf_.get(), off_);
replied_ = true;
}
} // namespace smbfs