blob: 1b58b8abf45ddcb58b538e14f6127a6c75c94136 [file] [log] [blame]
// 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.
#ifndef FUSEBOX_FUSE_REQUEST_H_
#define FUSEBOX_FUSE_REQUEST_H_
#include <fuse_lowlevel.h>
#include <memory>
namespace fusebox {
/**
* Kernel FUSE low level request responders: FuseRequest stores a Kernel
* fuse_req_t type in member req_ and replies to that req_ with the FUSE
* operation results (the response).
*
* Derived classes specialize the response for the given req_, and store
* any request parameters needed to complete the operation.
*
* Note: the classes only define the low level FUSE request and response
* API, they do not perform FUSE operations.
*/
class FuseRequest {
protected:
explicit FuseRequest(fuse_req_t req);
FuseRequest(const FuseRequest&) = delete;
FuseRequest& operator=(const FuseRequest&) = delete;
virtual ~FuseRequest();
public:
bool IsInterrupted() const;
int ReplyError(int error);
protected:
const fuse_req_t req_;
bool replied_ = false;
};
// FUSE request with an OK response.
class OkRequest : public FuseRequest {
public:
explicit OkRequest(fuse_req_t req) : FuseRequest(req) {}
void ReplyOk();
};
// FUSE request with a none response.
class NoneRequest : public FuseRequest {
public:
explicit NoneRequest(fuse_req_t req) : FuseRequest(req) {}
void ReplyNone();
};
// FUSE request with an attribute stat response.
class AttrRequest : public FuseRequest {
public:
explicit AttrRequest(fuse_req_t req) : FuseRequest(req) {}
void ReplyAttr(const struct stat& attr, double timeout);
};
// FUSE request with a fuse_entry_param response.
class EntryRequest : public FuseRequest {
public:
explicit EntryRequest(fuse_req_t req) : FuseRequest(req) {}
void ReplyEntry(const fuse_entry_param& entry);
};
// FUSE request with an open file handle response.
class OpenRequest : public FuseRequest {
public:
explicit OpenRequest(fuse_req_t req) : FuseRequest(req) {}
void ReplyOpen(uint64_t fh);
};
// FUSE request with an entry create response.
class CreateRequest : public FuseRequest {
public:
explicit CreateRequest(fuse_req_t req) : FuseRequest(req) {}
void ReplyCreate(const fuse_entry_param& entry, uint64_t fh);
};
// FUSE request with a data buffer response.
class BufferRequest : public FuseRequest {
public:
explicit BufferRequest(fuse_req_t req) : FuseRequest(req) {}
void ReplyBuffer(const char* buf, size_t length);
};
// FUSE request with a bytes written count response.
class WriteRequest : public FuseRequest {
public:
explicit WriteRequest(fuse_req_t req) : FuseRequest(req) {}
void ReplyWrite(size_t count);
};
// FUSE request with a DirEntry list response.
class DirEntryRequest : public FuseRequest {
public:
DirEntryRequest(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off);
// Directory ino.
fuse_ino_t parent() const { return parent_; }
// Entry buffer |buf_| size.
size_t size() const { return size_; }
// Add entry to |buf_|. Returns true if the entry was added.
bool AddEntry(struct DirEntry entry, off_t offset);
// Space used in |buf_| by the added entries.
size_t used() const { return off_; }
// Offset to the next entry.
off_t offset() const { return offset_; }
// Reply with the entry buffer result.
void ReplyDone();
private:
fuse_ino_t parent_;
const size_t size_;
off_t offset_;
std::unique_ptr<char[]> buf_;
size_t off_ = 0;
};
struct DirEntry {
fuse_ino_t ino;
const char* name;
mode_t mode;
};
} // namespace fusebox
#endif // FUSEBOX_FUSE_REQUEST_H_