Created a CryFs implementation based on the Fuse classes
This commit is contained in:
parent
da7debdf9d
commit
272456e187
336
src/CryFuse.cpp
336
src/CryFuse.cpp
@ -1,336 +0,0 @@
|
||||
#include "CryFuse.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <dirent.h>
|
||||
#include <fusepp/FuseErrnoException.h>
|
||||
#include <fusepp/FuseNode.h>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
#define UNUSED(expr) (void)(expr)
|
||||
|
||||
using fusepp::path;
|
||||
|
||||
namespace fusepp {
|
||||
|
||||
CryFuse::CryFuse(FuseDevice *device)
|
||||
:_device(device) {
|
||||
}
|
||||
|
||||
int CryFuse::getattr(const path &path, struct stat *stbuf) {
|
||||
//printf("getattr(%s, _, _)\n", path.c_str());
|
||||
try {
|
||||
_device->lstat(path, stbuf);
|
||||
return 0;
|
||||
} catch(fusepp::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int CryFuse::fgetattr(const path &path, struct stat *stbuf, fuse_file_info *fileinfo) {
|
||||
//printf("fgetattr(%s, _, _)\n", path.c_str());
|
||||
|
||||
// On FreeBSD, trying to do anything with the mountpoint ends up
|
||||
// opening it, and then using the FD for an fgetattr. So in the
|
||||
// special case of a path of "/", I need to do a getattr on the
|
||||
// underlying root directory instead of doing the fgetattr().
|
||||
// TODO Check if necessary
|
||||
if (path.native() == "/") {
|
||||
return getattr(path, stbuf);
|
||||
}
|
||||
|
||||
try {
|
||||
_device->fstat(fileinfo->fh, stbuf);
|
||||
return 0;
|
||||
} catch(fusepp::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
int CryFuse::readlink(const path &path, char *buf, size_t size) {
|
||||
//printf("readlink(%s, _, %zu)\n", path.c_str(), size);
|
||||
auto real_path = _device->RootDir() / path;
|
||||
//size-1, because the fuse readlink() function includes the null terminating byte in the buffer size,
|
||||
//but the posix version does not and also doesn't append one.
|
||||
int real_size = ::readlink(real_path.c_str(), buf, size-1);
|
||||
if (real_size < 0) {
|
||||
return -errno;
|
||||
}
|
||||
//Terminate the string
|
||||
buf[real_size] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CryFuse::mknod(const path &path, mode_t mode, dev_t rdev) {
|
||||
UNUSED(rdev);
|
||||
UNUSED(mode);
|
||||
UNUSED(path);
|
||||
printf("Called non-implemented mknod(%s, %d, _)\n", path.c_str(), mode);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
int CryFuse::mkdir(const path &path, mode_t mode) {
|
||||
//printf("mkdir(%s, %d)\n", path.c_str(), mode);
|
||||
try {
|
||||
_device->mkdir(path, mode);
|
||||
return 0;
|
||||
} catch(fusepp::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int CryFuse::unlink(const path &path) {
|
||||
//printf("unlink(%s)\n", path.c_str());
|
||||
try {
|
||||
_device->unlink(path);
|
||||
return 0;
|
||||
} catch(fusepp::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int CryFuse::rmdir(const path &path) {
|
||||
try {
|
||||
_device->rmdir(path);
|
||||
return 0;
|
||||
} catch(fusepp::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
int CryFuse::symlink(const path &from, const path &to) {
|
||||
printf("NOT IMPLEMENTED: symlink(%s, %s)\n", from.c_str(), to.c_str());
|
||||
//auto real_from = _device->RootDir() / from;
|
||||
//auto real_to = _device->RootDir() / to;
|
||||
//int retstat = ::symlink(real_from.c_str(), real_to.c_str());
|
||||
//return errcode_map(retstat);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
int CryFuse::rename(const path &from, const path &to) {
|
||||
//printf("rename(%s, %s)\n", from.c_str(), to.c_str());
|
||||
try {
|
||||
_device->rename(from, to);
|
||||
return 0;
|
||||
} catch(fusepp::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
int CryFuse::link(const path &from, const path &to) {
|
||||
printf("NOT IMPLEMENTED: link(%s, %s)\n", from.c_str(), to.c_str());
|
||||
//auto real_from = _device->RootDir() / from;
|
||||
//auto real_to = _device->RootDir() / to;
|
||||
//int retstat = ::link(real_from.c_str(), real_to.c_str());
|
||||
//return errcode_map(retstat);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
//TODO
|
||||
int CryFuse::chmod(const path &path, mode_t mode) {
|
||||
printf("NOT IMPLEMENTED: chmod(%s, %d)\n", path.c_str(), mode);
|
||||
//auto real_path = _device->RootDir() / path;
|
||||
//int retstat = ::chmod(real_path.c_str(), mode);
|
||||
//return errcode_map(retstat);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
//TODO
|
||||
int CryFuse::chown(const path &path, uid_t uid, gid_t gid) {
|
||||
printf("NOT IMPLEMENTED: chown(%s, %d, %d)\n", path.c_str(), uid, gid);
|
||||
//auto real_path = _device->RootDir() / path;
|
||||
//int retstat = ::chown(real_path.c_str(), uid, gid);
|
||||
//return errcode_map(retstat);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
int CryFuse::truncate(const path &path, off_t size) {
|
||||
//printf("truncate(%s, %zu)\n", path.c_str(), size);
|
||||
try {
|
||||
_device->truncate(path, size);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int CryFuse::ftruncate(const path &path, off_t size, fuse_file_info *fileinfo) {
|
||||
//printf("ftruncate(%s, %zu, _)\n", path.c_str(), size);
|
||||
UNUSED(path);
|
||||
try {
|
||||
_device->ftruncate(fileinfo->fh, size);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
int CryFuse::utimens(const path &path, const timespec times[2]) {
|
||||
//printf("utimens(%s, _)\n", path.c_str());
|
||||
try {
|
||||
_device->utimens(path, times);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int CryFuse::open(const path &path, fuse_file_info *fileinfo) {
|
||||
//printf("open(%s, _)\n", path.c_str());
|
||||
try {
|
||||
fileinfo->fh = _device->openFile(path, fileinfo->flags);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int CryFuse::release(const path &path, fuse_file_info *fileinfo) {
|
||||
//printf("release(%s, _)\n", path.c_str());
|
||||
UNUSED(path);
|
||||
try {
|
||||
_device->closeFile(fileinfo->fh);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int CryFuse::read(const path &path, char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) {
|
||||
//printf("read(%s, _, %zu, %zu, _)\n", path.c_str(), size, offset);
|
||||
UNUSED(path);
|
||||
try {
|
||||
//printf("Reading from file %d\n", fileinfo->fh);
|
||||
//fflush(stdout);
|
||||
return _device->read(fileinfo->fh, buf, size, offset);
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int CryFuse::write(const path &path, const char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) {
|
||||
//printf("write(%s, _, %zu, %zu, _)\n", path.c_str(), size, offset);
|
||||
UNUSED(path);
|
||||
try {
|
||||
_device->write(fileinfo->fh, buf, size, offset);
|
||||
return size;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
int CryFuse::statfs(const path &path, struct statvfs *fsstat) {
|
||||
//printf("statfs(%s, _)\n", path.c_str());
|
||||
try {
|
||||
_device->statfs(path, fsstat);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
int CryFuse::flush(const path &path, fuse_file_info *fileinfo) {
|
||||
//printf("Called non-implemented flush(%s, _)\n", path.c_str());
|
||||
UNUSED(path);
|
||||
UNUSED(fileinfo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CryFuse::fsync(const path &path, int datasync, fuse_file_info *fileinfo) {
|
||||
//printf("fsync(%s, %d, _)\n", path.c_str(), datasync);
|
||||
UNUSED(path);
|
||||
try {
|
||||
if (datasync) {
|
||||
_device->fdatasync(fileinfo->fh);
|
||||
} else {
|
||||
_device->fsync(fileinfo->fh);
|
||||
}
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int CryFuse::opendir(const path &path, fuse_file_info *fileinfo) {
|
||||
UNUSED(path);
|
||||
UNUSED(fileinfo);
|
||||
//printf("opendir(%s, _)\n", path.c_str());
|
||||
//We don't need opendir, because readdir works directly on the path
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CryFuse::readdir(const path &path, void *buf, fuse_fill_dir_t filler, off_t offset, fuse_file_info *fileinfo) {
|
||||
UNUSED(fileinfo);
|
||||
//printf("readdir(%s, _, _, %zu, _)\n", path.c_str(), offset);
|
||||
UNUSED(offset);
|
||||
try {
|
||||
auto entries = _device->readDir(path);
|
||||
for (const auto &entry : *entries) {
|
||||
//We could pass file metadata to filler() in its third parameter,
|
||||
//but it doesn't help performance since fuse seems to ignore it.
|
||||
//It does getattr() calls on all entries nevertheless.
|
||||
if (filler(buf, entry.c_str(), nullptr, 0) != 0) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int CryFuse::releasedir(const path &path, fuse_file_info *fileinfo) {
|
||||
UNUSED(path);
|
||||
UNUSED(fileinfo);
|
||||
//printf("releasedir(%s, _)\n", path.c_str());
|
||||
//We don't need releasedir, because readdir works directly on the path
|
||||
return 0;
|
||||
}
|
||||
|
||||
//TODO
|
||||
int CryFuse::fsyncdir(const path &path, int datasync, fuse_file_info *fileinfo) {
|
||||
UNUSED(fileinfo);
|
||||
UNUSED(datasync);
|
||||
UNUSED(path);
|
||||
//printf("Called non-implemented fsyncdir(%s, %d, _)\n", path.c_str(), datasync);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CryFuse::init(fuse_conn_info *conn) {
|
||||
UNUSED(conn);
|
||||
//printf("init()\n");
|
||||
}
|
||||
|
||||
void CryFuse::destroy() {
|
||||
//printf("destroy()\n");
|
||||
}
|
||||
|
||||
int CryFuse::access(const path &path, int mask) {
|
||||
//printf("access(%s, %d)\n", path.c_str(), mask);
|
||||
try {
|
||||
_device->access(path, mask);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int CryFuse::create(const path &path, mode_t mode, fuse_file_info *fileinfo) {
|
||||
//printf("create(%s, %d, _)\n", path.c_str(), mode);
|
||||
try {
|
||||
fileinfo->fh = _device->createAndOpenFile(path, mode);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace cryfs */
|
@ -1,54 +0,0 @@
|
||||
#pragma once
|
||||
#ifndef CRYFS_LIB_CRYFUSE_H_
|
||||
#define CRYFS_LIB_CRYFUSE_H_
|
||||
|
||||
#include "fusepp/Fuse.h"
|
||||
#include "fusepp/FuseDevice.h"
|
||||
#include "fusepp/utils/macros.h"
|
||||
|
||||
namespace fusepp {
|
||||
|
||||
class CryFuse: public fusepp::Fuse {
|
||||
public:
|
||||
CryFuse(FuseDevice *device);
|
||||
|
||||
int getattr(const fusepp::path &path, struct stat *stbuf) override;
|
||||
int fgetattr(const fusepp::path &path, struct stat *stbuf, fuse_file_info *fileinfo) override;
|
||||
int readlink(const fusepp::path &path, char *buf, size_t size) override;
|
||||
int mknod(const fusepp::path &path, mode_t mode, dev_t rdev) override;
|
||||
int mkdir(const fusepp::path &path, mode_t mode) override;
|
||||
int unlink(const fusepp::path &path) override;
|
||||
int rmdir(const fusepp::path &path) override;
|
||||
int symlink(const fusepp::path &from, const fusepp::path &to) override;
|
||||
int rename(const fusepp::path &from, const fusepp::path &to) override;
|
||||
int link(const fusepp::path &from, const fusepp::path &to) override;
|
||||
int chmod(const fusepp::path &path, mode_t mode) override;
|
||||
int chown(const fusepp::path &path, uid_t uid, gid_t gid) override;
|
||||
int truncate(const fusepp::path &path, off_t size) override;
|
||||
int ftruncate(const fusepp::path &path, off_t size, fuse_file_info *fileinfo) override;
|
||||
int utimens(const fusepp::path &path, const timespec times[2]) override;
|
||||
int open(const fusepp::path &path, fuse_file_info *fileinfo) override;
|
||||
int release(const fusepp::path &path, fuse_file_info *fileinfo) override;
|
||||
int read(const fusepp::path &path, char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) override;
|
||||
int write(const fusepp::path &path, const char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) override;
|
||||
int statfs(const fusepp::path &path, struct statvfs *fsstat) override;
|
||||
int flush(const fusepp::path &path, fuse_file_info *fileinfo) override;
|
||||
int fsync(const fusepp::path &path, int flags, fuse_file_info *fileinfo) override;
|
||||
int opendir(const fusepp::path &path, fuse_file_info *fileinfo) override;
|
||||
int readdir(const fusepp::path &path, void *buf, fuse_fill_dir_t filler, off_t offset, fuse_file_info *fileinfo) override;
|
||||
int releasedir(const fusepp::path &path, fuse_file_info *fileinfo) override;
|
||||
int fsyncdir(const fusepp::path &path, int datasync, fuse_file_info *fileinfo) override;
|
||||
void init(fuse_conn_info *conn) override;
|
||||
void destroy() override;
|
||||
int access(const fusepp::path &path, int mask) override;
|
||||
int create(const fusepp::path &path, mode_t mode, fuse_file_info *fileinfo) override;
|
||||
|
||||
private:
|
||||
FuseDevice *_device;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CryFuse);
|
||||
};
|
||||
|
||||
} /* namespace cryfs */
|
||||
|
||||
#endif /* CRYFS_LIB_CRYFUSE_H_ */
|
@ -1,7 +1,10 @@
|
||||
#include "../fusepp/Fuse.h"
|
||||
#include "Fuse.h"
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
#include "FuseDevice.h"
|
||||
#include "FuseErrnoException.h"
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::make_unique;
|
||||
using std::string;
|
||||
@ -11,7 +14,6 @@ namespace bf = boost::filesystem;
|
||||
using namespace fusepp;
|
||||
|
||||
#define FUSE_OBJ ((Fuse *) fuse_get_context()->private_data)
|
||||
#define UNUSED(obj) (void)obj
|
||||
|
||||
namespace {
|
||||
int fusepp_getattr(const char *path, struct stat *stbuf) {
|
||||
@ -203,6 +205,318 @@ fuse_operations *operations() {
|
||||
Fuse::~Fuse() {
|
||||
}
|
||||
|
||||
Fuse::Fuse(FuseDevice *device)
|
||||
:_device(device) {
|
||||
}
|
||||
|
||||
void Fuse::run(int argc, char **argv) {
|
||||
fuse_main(argc, argv, operations(), (void*)this);
|
||||
}
|
||||
|
||||
int Fuse::getattr(const bf::path &path, struct stat *stbuf) {
|
||||
//printf("getattr(%s, _, _)\n", path.c_str());
|
||||
try {
|
||||
_device->lstat(path, stbuf);
|
||||
return 0;
|
||||
} catch(fusepp::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int Fuse::fgetattr(const bf::path &path, struct stat *stbuf, fuse_file_info *fileinfo) {
|
||||
//printf("fgetattr(%s, _, _)\n", path.c_str());
|
||||
|
||||
// On FreeBSD, trying to do anything with the mountpoint ends up
|
||||
// opening it, and then using the FD for an fgetattr. So in the
|
||||
// special case of a path of "/", I need to do a getattr on the
|
||||
// underlying root directory instead of doing the fgetattr().
|
||||
// TODO Check if necessary
|
||||
if (path.native() == "/") {
|
||||
return getattr(path, stbuf);
|
||||
}
|
||||
|
||||
try {
|
||||
_device->fstat(fileinfo->fh, stbuf);
|
||||
return 0;
|
||||
} catch(fusepp::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
int Fuse::readlink(const bf::path &path, char *buf, size_t size) {
|
||||
UNUSED(path);
|
||||
UNUSED(buf);
|
||||
UNUSED(size);
|
||||
printf("Called non-implemented readlink(%s, _, %zu)\n", path.c_str(), size);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
int Fuse::mknod(const bf::path &path, mode_t mode, dev_t rdev) {
|
||||
UNUSED(rdev);
|
||||
UNUSED(mode);
|
||||
UNUSED(path);
|
||||
printf("Called non-implemented mknod(%s, %d, _)\n", path.c_str(), mode);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
int Fuse::mkdir(const bf::path &path, mode_t mode) {
|
||||
//printf("mkdir(%s, %d)\n", path.c_str(), mode);
|
||||
try {
|
||||
_device->mkdir(path, mode);
|
||||
return 0;
|
||||
} catch(fusepp::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int Fuse::unlink(const bf::path &path) {
|
||||
//printf("unlink(%s)\n", path.c_str());
|
||||
try {
|
||||
_device->unlink(path);
|
||||
return 0;
|
||||
} catch(fusepp::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int Fuse::rmdir(const bf::path &path) {
|
||||
try {
|
||||
_device->rmdir(path);
|
||||
return 0;
|
||||
} catch(fusepp::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
int Fuse::symlink(const bf::path &from, const bf::path &to) {
|
||||
printf("NOT IMPLEMENTED: symlink(%s, %s)\n", from.c_str(), to.c_str());
|
||||
//auto real_from = _device->RootDir() / from;
|
||||
//auto real_to = _device->RootDir() / to;
|
||||
//int retstat = ::symlink(real_from.c_str(), real_to.c_str());
|
||||
//return errcode_map(retstat);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
int Fuse::rename(const bf::path &from, const bf::path &to) {
|
||||
//printf("rename(%s, %s)\n", from.c_str(), to.c_str());
|
||||
try {
|
||||
_device->rename(from, to);
|
||||
return 0;
|
||||
} catch(fusepp::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
int Fuse::link(const bf::path &from, const bf::path &to) {
|
||||
printf("NOT IMPLEMENTED: link(%s, %s)\n", from.c_str(), to.c_str());
|
||||
//auto real_from = _device->RootDir() / from;
|
||||
//auto real_to = _device->RootDir() / to;
|
||||
//int retstat = ::link(real_from.c_str(), real_to.c_str());
|
||||
//return errcode_map(retstat);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
//TODO
|
||||
int Fuse::chmod(const bf::path &path, mode_t mode) {
|
||||
printf("NOT IMPLEMENTED: chmod(%s, %d)\n", path.c_str(), mode);
|
||||
//auto real_path = _device->RootDir() / path;
|
||||
//int retstat = ::chmod(real_path.c_str(), mode);
|
||||
//return errcode_map(retstat);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
//TODO
|
||||
int Fuse::chown(const bf::path &path, uid_t uid, gid_t gid) {
|
||||
printf("NOT IMPLEMENTED: chown(%s, %d, %d)\n", path.c_str(), uid, gid);
|
||||
//auto real_path = _device->RootDir() / path;
|
||||
//int retstat = ::chown(real_path.c_str(), uid, gid);
|
||||
//return errcode_map(retstat);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
int Fuse::truncate(const bf::path &path, off_t size) {
|
||||
//printf("truncate(%s, %zu)\n", path.c_str(), size);
|
||||
try {
|
||||
_device->truncate(path, size);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int Fuse::ftruncate(const bf::path &path, off_t size, fuse_file_info *fileinfo) {
|
||||
//printf("ftruncate(%s, %zu, _)\n", path.c_str(), size);
|
||||
UNUSED(path);
|
||||
try {
|
||||
_device->ftruncate(fileinfo->fh, size);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
int Fuse::utimens(const bf::path &path, const timespec times[2]) {
|
||||
//printf("utimens(%s, _)\n", path.c_str());
|
||||
try {
|
||||
_device->utimens(path, times);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int Fuse::open(const bf::path &path, fuse_file_info *fileinfo) {
|
||||
//printf("open(%s, _)\n", path.c_str());
|
||||
try {
|
||||
fileinfo->fh = _device->openFile(path, fileinfo->flags);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int Fuse::release(const bf::path &path, fuse_file_info *fileinfo) {
|
||||
//printf("release(%s, _)\n", path.c_str());
|
||||
UNUSED(path);
|
||||
try {
|
||||
_device->closeFile(fileinfo->fh);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int Fuse::read(const bf::path &path, char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) {
|
||||
//printf("read(%s, _, %zu, %zu, _)\n", path.c_str(), size, offset);
|
||||
UNUSED(path);
|
||||
try {
|
||||
//printf("Reading from file %d\n", fileinfo->fh);
|
||||
//fflush(stdout);
|
||||
return _device->read(fileinfo->fh, buf, size, offset);
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int Fuse::write(const bf::path &path, const char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) {
|
||||
//printf("write(%s, _, %zu, %zu, _)\n", path.c_str(), size, offset);
|
||||
UNUSED(path);
|
||||
try {
|
||||
_device->write(fileinfo->fh, buf, size, offset);
|
||||
return size;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
int Fuse::statfs(const bf::path &path, struct statvfs *fsstat) {
|
||||
//printf("statfs(%s, _)\n", path.c_str());
|
||||
try {
|
||||
_device->statfs(path, fsstat);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
int Fuse::flush(const bf::path &path, fuse_file_info *fileinfo) {
|
||||
//printf("Called non-implemented flush(%s, _)\n", path.c_str());
|
||||
UNUSED(path);
|
||||
UNUSED(fileinfo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Fuse::fsync(const bf::path &path, int datasync, fuse_file_info *fileinfo) {
|
||||
//printf("fsync(%s, %d, _)\n", path.c_str(), datasync);
|
||||
UNUSED(path);
|
||||
try {
|
||||
if (datasync) {
|
||||
_device->fdatasync(fileinfo->fh);
|
||||
} else {
|
||||
_device->fsync(fileinfo->fh);
|
||||
}
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int Fuse::opendir(const bf::path &path, fuse_file_info *fileinfo) {
|
||||
UNUSED(path);
|
||||
UNUSED(fileinfo);
|
||||
//printf("opendir(%s, _)\n", path.c_str());
|
||||
//We don't need opendir, because readdir works directly on the path
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Fuse::readdir(const bf::path &path, void *buf, fuse_fill_dir_t filler, off_t offset, fuse_file_info *fileinfo) {
|
||||
UNUSED(fileinfo);
|
||||
//printf("readdir(%s, _, _, %zu, _)\n", path.c_str(), offset);
|
||||
UNUSED(offset);
|
||||
try {
|
||||
auto entries = _device->readDir(path);
|
||||
for (const auto &entry : *entries) {
|
||||
//We could pass file metadata to filler() in its third parameter,
|
||||
//but it doesn't help performance since fuse seems to ignore it.
|
||||
//It does getattr() calls on all entries nevertheless.
|
||||
if (filler(buf, entry.c_str(), nullptr, 0) != 0) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int Fuse::releasedir(const bf::path &path, fuse_file_info *fileinfo) {
|
||||
UNUSED(path);
|
||||
UNUSED(fileinfo);
|
||||
//printf("releasedir(%s, _)\n", path.c_str());
|
||||
//We don't need releasedir, because readdir works directly on the path
|
||||
return 0;
|
||||
}
|
||||
|
||||
//TODO
|
||||
int Fuse::fsyncdir(const bf::path &path, int datasync, fuse_file_info *fileinfo) {
|
||||
UNUSED(fileinfo);
|
||||
UNUSED(datasync);
|
||||
UNUSED(path);
|
||||
//printf("Called non-implemented fsyncdir(%s, %d, _)\n", path.c_str(), datasync);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Fuse::init(fuse_conn_info *conn) {
|
||||
UNUSED(conn);
|
||||
//printf("init()\n");
|
||||
}
|
||||
|
||||
void Fuse::destroy() {
|
||||
//printf("destroy()\n");
|
||||
}
|
||||
|
||||
int Fuse::access(const bf::path &path, int mask) {
|
||||
//printf("access(%s, %d)\n", path.c_str(), mask);
|
||||
try {
|
||||
_device->access(path, mask);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
||||
int Fuse::create(const bf::path &path, mode_t mode, fuse_file_info *fileinfo) {
|
||||
//printf("create(%s, %d, _)\n", path.c_str(), mode);
|
||||
try {
|
||||
fileinfo->fh = _device->createAndOpenFile(path, mode);
|
||||
return 0;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
}
|
||||
}
|
||||
|
@ -8,50 +8,53 @@
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "utils/macros.h"
|
||||
|
||||
namespace fusepp {
|
||||
class FuseDevice;
|
||||
|
||||
typedef boost::filesystem::path path;
|
||||
|
||||
//TODO If performance suffers here, we could use template<class FuseImpl>
|
||||
// and redirect the fuse calls directly to the FuseImpl class instead
|
||||
// of using virtual functions.
|
||||
class Fuse {
|
||||
public:
|
||||
Fuse(FuseDevice *device);
|
||||
virtual ~Fuse();
|
||||
|
||||
void run(int argc, char **argv);
|
||||
|
||||
virtual int getattr(const path &path, struct stat *stbuf) = 0;
|
||||
virtual int fgetattr(const path &path, struct stat *stbuf, fuse_file_info *fileinfo) = 0;
|
||||
virtual int readlink(const path &path, char *buf, size_t size) = 0;
|
||||
virtual int mknod(const path &path, mode_t mode, dev_t rdev) = 0;
|
||||
virtual int mkdir(const path &path, mode_t mode) = 0;
|
||||
virtual int unlink(const path &path) = 0;
|
||||
virtual int rmdir(const path &path) = 0;
|
||||
virtual int symlink(const path &from, const path &to) = 0;
|
||||
virtual int rename(const path &from, const path &to) = 0;
|
||||
virtual int link(const path &from, const path &to) = 0;
|
||||
virtual int chmod(const path &path, mode_t mode) = 0;
|
||||
virtual int chown(const path &path, uid_t uid, gid_t gid) = 0;
|
||||
virtual int truncate(const path &path, off_t size) = 0;
|
||||
virtual int ftruncate(const path &path, off_t size, fuse_file_info *fileinfo) = 0;
|
||||
virtual int utimens(const path &path, const timespec times[2]) = 0;
|
||||
virtual int open(const path &path, fuse_file_info *fileinfo) = 0;
|
||||
virtual int release(const path &path, fuse_file_info *fileinfo) = 0;
|
||||
virtual int read(const path &path, char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) = 0;
|
||||
virtual int write(const path &path, const char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) = 0;
|
||||
virtual int statfs(const path &path, struct statvfs *fsstat) = 0;
|
||||
virtual int flush(const path &path, fuse_file_info *fileinfo) = 0;
|
||||
virtual int fsync(const path &path, int datasync, fuse_file_info *fileinfo) = 0;
|
||||
virtual int opendir(const path &path, fuse_file_info *fileinfo) = 0;
|
||||
virtual int readdir(const path &path, void *buf, fuse_fill_dir_t filler, off_t offset, fuse_file_info *fileinfo) = 0;
|
||||
virtual int releasedir(const path &path, fuse_file_info *fileinfo) = 0;
|
||||
virtual int fsyncdir(const path &path, int datasync, fuse_file_info *fileinfo) = 0;
|
||||
virtual void init(fuse_conn_info *conn) = 0;
|
||||
virtual void destroy() = 0;
|
||||
virtual int access(const path &path, int mask) = 0;
|
||||
virtual int create(const path &path, mode_t mode, fuse_file_info *fileinfo) = 0;
|
||||
int getattr(const boost::filesystem::path &path, struct stat *stbuf);
|
||||
int fgetattr(const boost::filesystem::path &path, struct stat *stbuf, fuse_file_info *fileinfo);
|
||||
int readlink(const boost::filesystem::path &path, char *buf, size_t size);
|
||||
int mknod(const boost::filesystem::path &path, mode_t mode, dev_t rdev);
|
||||
int mkdir(const boost::filesystem::path &path, mode_t mode);
|
||||
int unlink(const boost::filesystem::path &path);
|
||||
int rmdir(const boost::filesystem::path &path);
|
||||
int symlink(const boost::filesystem::path &from, const boost::filesystem::path &to);
|
||||
int rename(const boost::filesystem::path &from, const boost::filesystem::path &to);
|
||||
int link(const boost::filesystem::path &from, const boost::filesystem::path &to);
|
||||
int chmod(const boost::filesystem::path &path, mode_t mode);
|
||||
int chown(const boost::filesystem::path &path, uid_t uid, gid_t gid);
|
||||
int truncate(const boost::filesystem::path &path, off_t size);
|
||||
int ftruncate(const boost::filesystem::path &path, off_t size, fuse_file_info *fileinfo);
|
||||
int utimens(const boost::filesystem::path &path, const timespec times[2]);
|
||||
int open(const boost::filesystem::path &path, fuse_file_info *fileinfo);
|
||||
int release(const boost::filesystem::path &path, fuse_file_info *fileinfo);
|
||||
int read(const boost::filesystem::path &path, char *buf, size_t size, off_t offset, fuse_file_info *fileinfo);
|
||||
int write(const boost::filesystem::path &path, const char *buf, size_t size, off_t offset, fuse_file_info *fileinfo);
|
||||
int statfs(const boost::filesystem::path &path, struct statvfs *fsstat);
|
||||
int flush(const boost::filesystem::path &path, fuse_file_info *fileinfo);
|
||||
int fsync(const boost::filesystem::path &path, int flags, fuse_file_info *fileinfo);
|
||||
int opendir(const boost::filesystem::path &path, fuse_file_info *fileinfo);
|
||||
int readdir(const boost::filesystem::path &path, void *buf, fuse_fill_dir_t filler, off_t offset, fuse_file_info *fileinfo);
|
||||
int releasedir(const boost::filesystem::path &path, fuse_file_info *fileinfo);
|
||||
int fsyncdir(const boost::filesystem::path &path, int datasync, fuse_file_info *fileinfo);
|
||||
void init(fuse_conn_info *conn);
|
||||
void destroy();
|
||||
int access(const boost::filesystem::path &path, int mask);
|
||||
int create(const boost::filesystem::path &path, mode_t mode, fuse_file_info *fileinfo);
|
||||
|
||||
private:
|
||||
FuseDevice *_device;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Fuse);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,11 @@
|
||||
|
||||
#include <memory>
|
||||
#include <fcntl.h>
|
||||
#include <fusepp/FuseDir.h>
|
||||
#include <fusepp/FuseErrnoException.h>
|
||||
#include <fusepp/FuseFile.h>
|
||||
#include <fusepp/FuseOpenFile.h>
|
||||
|
||||
#include "FuseDir.h"
|
||||
#include "FuseErrnoException.h"
|
||||
#include "FuseFile.h"
|
||||
|
||||
|
||||
#include "utils/pointer.h"
|
||||
|
||||
@ -16,24 +17,15 @@ using std::make_unique;
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
FuseDevice::FuseDevice(const bf::path &rootdir)
|
||||
:_rootdir(rootdir), _open_files() {
|
||||
namespace bf = boost::filesystem;
|
||||
|
||||
FuseDevice::FuseDevice()
|
||||
:_open_files() {
|
||||
}
|
||||
|
||||
FuseDevice::~FuseDevice() {
|
||||
}
|
||||
|
||||
unique_ptr<FuseNode> FuseDevice::Load(const bf::path &path) {
|
||||
auto real_path = RootDir() / path;
|
||||
if(bf::is_directory(real_path)) {
|
||||
return make_unique<FuseDir>(this, path);
|
||||
} else if(bf::is_regular_file(real_path)) {
|
||||
return make_unique<FuseFile>(this, path);
|
||||
}
|
||||
|
||||
throw FuseErrnoException(ENOENT);
|
||||
}
|
||||
|
||||
unique_ptr<FuseFile> FuseDevice::LoadFile(const bf::path &path) {
|
||||
auto node = Load(path);
|
||||
auto file = dynamic_pointer_move<FuseFile>(node);
|
||||
@ -138,8 +130,3 @@ void FuseDevice::utimens(const bf::path &path, const timespec times[2]) {
|
||||
auto node = Load(path);
|
||||
node->utimens(times);
|
||||
}
|
||||
|
||||
void FuseDevice::statfs(const bf::path &path, struct statvfs *fsstat) {
|
||||
int retval = ::statvfs(path.c_str(), fsstat);
|
||||
CHECK_RETVAL(retval);
|
||||
}
|
||||
|
@ -16,49 +16,41 @@ class FuseFile;
|
||||
class FuseOpenFile;
|
||||
class FuseDir;
|
||||
|
||||
namespace bf = boost::filesystem;
|
||||
|
||||
class FuseDevice {
|
||||
public:
|
||||
FuseDevice(const bf::path &rootdir);
|
||||
FuseDevice();
|
||||
virtual ~FuseDevice();
|
||||
|
||||
int openFile(const bf::path &path, int flags);
|
||||
int openFile(const boost::filesystem::path &path, int flags);
|
||||
void closeFile(int descriptor);
|
||||
void lstat(const bf::path &path, struct ::stat *stbuf);
|
||||
void lstat(const boost::filesystem::path &path, struct ::stat *stbuf);
|
||||
void fstat(int descriptor, struct ::stat *stbuf);
|
||||
void truncate(const bf::path &path, off_t size);
|
||||
void truncate(const boost::filesystem::path &path, off_t size);
|
||||
void ftruncate(int descriptor, off_t size);
|
||||
int read(int descriptor, void *buf, size_t count, off_t offset);
|
||||
void write(int descriptor, const void *buf, size_t count, off_t offset);
|
||||
void fsync(int descriptor);
|
||||
void fdatasync(int descriptor);
|
||||
void access(const bf::path &path, int mask);
|
||||
int createAndOpenFile(const bf::path &path, mode_t mode);
|
||||
void mkdir(const bf::path &path, mode_t mode);
|
||||
void rmdir(const bf::path &path);
|
||||
void unlink(const bf::path &path);
|
||||
void rename(const bf::path &from, const bf::path &to);
|
||||
std::unique_ptr<std::vector<std::string>> readDir(const bf::path &path);
|
||||
void utimens(const bf::path &path, const timespec times[2]);
|
||||
void statfs(const bf::path &path, struct statvfs *fsstat);
|
||||
void access(const boost::filesystem::path &path, int mask);
|
||||
int createAndOpenFile(const boost::filesystem::path &path, mode_t mode);
|
||||
void mkdir(const boost::filesystem::path &path, mode_t mode);
|
||||
void rmdir(const boost::filesystem::path &path);
|
||||
void unlink(const boost::filesystem::path &path);
|
||||
void rename(const boost::filesystem::path &from, const boost::filesystem::path &to);
|
||||
std::unique_ptr<std::vector<std::string>> readDir(const boost::filesystem::path &path);
|
||||
void utimens(const boost::filesystem::path &path, const timespec times[2]);
|
||||
virtual void statfs(const boost::filesystem::path &path, struct statvfs *fsstat) = 0;
|
||||
|
||||
const bf::path &RootDir() const;
|
||||
private:
|
||||
std::unique_ptr<FuseNode> Load(const bf::path &path);
|
||||
std::unique_ptr<FuseFile> LoadFile(const bf::path &path);
|
||||
std::unique_ptr<FuseDir> LoadDir(const bf::path &path);
|
||||
virtual std::unique_ptr<FuseNode> Load(const boost::filesystem::path &path) = 0;
|
||||
std::unique_ptr<FuseFile> LoadFile(const boost::filesystem::path &path);
|
||||
std::unique_ptr<FuseDir> LoadDir(const boost::filesystem::path &path);
|
||||
int openFile(const FuseFile &file, int flags);
|
||||
const bf::path _rootdir;
|
||||
FuseOpenFileList _open_files;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FuseDevice);
|
||||
};
|
||||
|
||||
inline const bf::path &FuseDevice::RootDir() const {
|
||||
return _rootdir;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* FUSEPP_FUSEDEVICE_H_ */
|
||||
|
@ -1,75 +1 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <fusepp/FuseDevice.h>
|
||||
#include <fusepp/FuseDir.h>
|
||||
#include <fusepp/FuseErrnoException.h>
|
||||
#include <fusepp/FuseFile.h>
|
||||
|
||||
|
||||
using std::string;
|
||||
using std::unique_ptr;
|
||||
using std::make_unique;
|
||||
using std::vector;
|
||||
|
||||
namespace fusepp {
|
||||
|
||||
FuseDir::FuseDir(FuseDevice *device, const bf::path &path)
|
||||
:FuseNode(device, path) {
|
||||
assert(bf::is_directory(base_path()));
|
||||
}
|
||||
|
||||
FuseDir::~FuseDir() {
|
||||
}
|
||||
|
||||
unique_ptr<FuseFile> FuseDir::createFile(const string &name, mode_t mode) {
|
||||
auto file_path = base_path() / name;
|
||||
//Create file
|
||||
int fd = ::creat(file_path.c_str(), mode);
|
||||
CHECK_RETVAL(fd);
|
||||
::close(fd);
|
||||
return make_unique<FuseFile>(device(), path() / name);
|
||||
}
|
||||
|
||||
unique_ptr<FuseDir> FuseDir::createDir(const string &name, mode_t mode) {
|
||||
auto dir_path = base_path() / name;
|
||||
//Create dir
|
||||
int retval = ::mkdir(dir_path.c_str(), mode);
|
||||
CHECK_RETVAL(retval);
|
||||
return make_unique<FuseDir>(device(), path() / name);
|
||||
}
|
||||
|
||||
void FuseDir::rmdir() {
|
||||
int retval = ::rmdir(base_path().c_str());
|
||||
CHECK_RETVAL(retval);
|
||||
}
|
||||
|
||||
unique_ptr<vector<string>> FuseDir::children() const {
|
||||
DIR *dir = ::opendir(base_path().c_str());
|
||||
if (dir == nullptr) {
|
||||
throw FuseErrnoException(errno);
|
||||
}
|
||||
|
||||
// Set errno=0 so we can detect whether it changed later
|
||||
errno = 0;
|
||||
|
||||
auto result = make_unique<vector<string>>();
|
||||
|
||||
struct dirent *entry = ::readdir(dir);
|
||||
while(entry != nullptr) {
|
||||
result->push_back(entry->d_name);
|
||||
entry = ::readdir(dir);
|
||||
}
|
||||
//On error, ::readdir returns nullptr and sets errno.
|
||||
if (errno != 0) {
|
||||
int readdir_errno = errno;
|
||||
::closedir(dir);
|
||||
throw FuseErrnoException(readdir_errno);
|
||||
}
|
||||
int retval = ::closedir(dir);
|
||||
CHECK_RETVAL(retval);
|
||||
return result;
|
||||
}
|
||||
|
||||
} /* namespace fusepp */
|
||||
#include "FuseDir.h"
|
||||
|
@ -2,28 +2,23 @@
|
||||
#ifndef FUSEPP_FUSEDIR_H_
|
||||
#define FUSEPP_FUSEDIR_H_
|
||||
|
||||
#include <fusepp/FuseNode.h>
|
||||
#include "FuseNode.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "utils/macros.h"
|
||||
|
||||
namespace fusepp {
|
||||
class FuseDevice;
|
||||
class FuseFile;
|
||||
|
||||
class FuseDir: public FuseNode {
|
||||
class FuseDir: public virtual FuseNode {
|
||||
public:
|
||||
FuseDir(FuseDevice *device, const bf::path &path);
|
||||
virtual ~FuseDir();
|
||||
virtual ~FuseDir() {}
|
||||
|
||||
std::unique_ptr<FuseFile> createFile(const std::string &name, mode_t mode);
|
||||
std::unique_ptr<FuseDir> createDir(const std::string &name, mode_t mode);
|
||||
void rmdir();
|
||||
virtual std::unique_ptr<FuseFile> createFile(const std::string &name, mode_t mode) = 0;
|
||||
virtual std::unique_ptr<FuseDir> createDir(const std::string &name, mode_t mode) = 0;
|
||||
virtual void rmdir() = 0;
|
||||
|
||||
std::unique_ptr<std::vector<std::string>> children() const;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(FuseDir);
|
||||
virtual std::unique_ptr<std::vector<std::string>> children() const = 0;
|
||||
};
|
||||
|
||||
} /* namespace fusepp */
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <fusepp/FuseErrnoException.h>
|
||||
#include "FuseErrnoException.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
@ -1,32 +1 @@
|
||||
#include <fusepp/FuseErrnoException.h>
|
||||
#include <fusepp/FuseFile.h>
|
||||
#include <fusepp/FuseOpenFile.h>
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::make_unique;
|
||||
|
||||
namespace fusepp {
|
||||
|
||||
FuseFile::FuseFile(FuseDevice *device, const bf::path &path)
|
||||
:FuseNode(device, path) {
|
||||
assert(bf::is_regular_file(base_path()));
|
||||
}
|
||||
|
||||
FuseFile::~FuseFile() {
|
||||
}
|
||||
|
||||
std::unique_ptr<FuseOpenFile> FuseFile::open(int flags) const {
|
||||
return make_unique<FuseOpenFile>(device(), path(), flags);
|
||||
}
|
||||
|
||||
void FuseFile::truncate(off_t size) const {
|
||||
int retval = ::truncate(base_path().c_str(), size);
|
||||
CHECK_RETVAL(retval);
|
||||
}
|
||||
|
||||
void FuseFile::unlink() {
|
||||
int retval = ::unlink(base_path().c_str());
|
||||
CHECK_RETVAL(retval);
|
||||
}
|
||||
|
||||
} /* namespace fusepp */
|
||||
#include "FuseFile.h"
|
||||
|
@ -2,25 +2,20 @@
|
||||
#ifndef FUSEPP_FUSEFILE_H_
|
||||
#define FUSEPP_FUSEFILE_H_
|
||||
|
||||
#include <fusepp/FuseNode.h>
|
||||
#include "FuseNode.h"
|
||||
#include <memory>
|
||||
|
||||
#include "utils/macros.h"
|
||||
|
||||
namespace fusepp {
|
||||
class FuseDevice;
|
||||
class FuseOpenFile;
|
||||
|
||||
class FuseFile: public FuseNode {
|
||||
class FuseFile: public virtual FuseNode {
|
||||
public:
|
||||
FuseFile(FuseDevice *device, const bf::path &path);
|
||||
virtual ~FuseFile();
|
||||
virtual ~FuseFile() {}
|
||||
|
||||
std::unique_ptr<FuseOpenFile> open(int flags) const;
|
||||
void truncate(off_t size) const;
|
||||
void unlink();
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(FuseFile);
|
||||
virtual std::unique_ptr<FuseOpenFile> open(int flags) const = 0;
|
||||
virtual void truncate(off_t size) const = 0;
|
||||
virtual void unlink() = 0;
|
||||
};
|
||||
|
||||
} /* namespace fusepp */
|
||||
|
@ -1,40 +1 @@
|
||||
#include <fusepp/FuseDevice.h>
|
||||
#include <fusepp/FuseErrnoException.h>
|
||||
#include <fusepp/FuseNode.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
namespace fusepp {
|
||||
|
||||
FuseNode::FuseNode(FuseDevice *device, const bf::path &path)
|
||||
:_device(device), _path(path) {
|
||||
}
|
||||
|
||||
FuseNode::~FuseNode() {
|
||||
}
|
||||
|
||||
void FuseNode::stat(struct ::stat *result) const {
|
||||
int retval = ::lstat(base_path().c_str(), result);
|
||||
CHECK_RETVAL(retval);
|
||||
}
|
||||
|
||||
void FuseNode::access(int mask) const {
|
||||
int retval = ::access(base_path().c_str(), mask);
|
||||
CHECK_RETVAL(retval);
|
||||
}
|
||||
|
||||
void FuseNode::rename(const bf::path &to) {
|
||||
auto new_base_path = device()->RootDir() / to;
|
||||
int retval = ::rename(base_path().c_str(), new_base_path.c_str());
|
||||
CHECK_RETVAL(retval);
|
||||
_path = to;
|
||||
}
|
||||
|
||||
void FuseNode::utimens(const timespec times[2]) {
|
||||
struct timeval timevals[2];
|
||||
TIMESPEC_TO_TIMEVAL(&timevals[0], ×[0]);
|
||||
TIMESPEC_TO_TIMEVAL(&timevals[1], ×[1]);
|
||||
::lutimes(base_path().c_str(), timevals);
|
||||
}
|
||||
|
||||
} /* namespace fusepp */
|
||||
#include "FuseNode.h"
|
||||
|
@ -3,54 +3,22 @@
|
||||
#define FUSEPP_FUSENODE_H_
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <fusepp/FuseDevice.h>
|
||||
|
||||
#include "utils/macros.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace fusepp {
|
||||
|
||||
namespace bf = boost::filesystem;
|
||||
|
||||
class FuseNode {
|
||||
public:
|
||||
FuseNode(FuseDevice *device, const bf::path &path);
|
||||
virtual ~FuseNode();
|
||||
virtual ~FuseNode() {}
|
||||
|
||||
void stat(struct ::stat *result) const;
|
||||
void access(int mask) const;
|
||||
void rename(const bf::path &to);
|
||||
void utimens(const timespec times[2]);
|
||||
|
||||
protected:
|
||||
bf::path base_path() const;
|
||||
const bf::path &path() const;
|
||||
FuseDevice *device();
|
||||
const FuseDevice *device() const;
|
||||
|
||||
private:
|
||||
FuseDevice *const _device;
|
||||
bf::path _path;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FuseNode);
|
||||
virtual void stat(struct ::stat *result) const = 0;
|
||||
virtual void access(int mask) const = 0;
|
||||
virtual void rename(const boost::filesystem::path &to) = 0;
|
||||
virtual void utimens(const timespec times[2]) = 0;
|
||||
};
|
||||
|
||||
inline bf::path FuseNode::base_path() const {
|
||||
return _device->RootDir() / _path;
|
||||
}
|
||||
|
||||
inline const bf::path &FuseNode::path() const {
|
||||
return _path;
|
||||
}
|
||||
|
||||
inline FuseDevice *FuseNode::device() {
|
||||
return const_cast<FuseDevice*>(const_cast<const FuseNode*>(this)->device());
|
||||
}
|
||||
|
||||
inline const FuseDevice *FuseNode::device() const {
|
||||
return _device;
|
||||
}
|
||||
|
||||
} /* namespace fusepp */
|
||||
|
||||
#endif /* FUSEPP_FUSENODE_H_ */
|
||||
|
@ -1,55 +1 @@
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <fusepp/FuseDevice.h>
|
||||
#include <fusepp/FuseErrnoException.h>
|
||||
#include <fusepp/FuseOpenFile.h>
|
||||
|
||||
|
||||
using namespace fusepp;
|
||||
|
||||
FuseOpenFile::FuseOpenFile(const FuseDevice *device, const bf::path &path, int flags)
|
||||
:_descriptor(::open((device->RootDir() / path).c_str(), flags)) {
|
||||
CHECK_RETVAL(_descriptor);
|
||||
}
|
||||
|
||||
FuseOpenFile::~FuseOpenFile() {
|
||||
int retval = close(_descriptor);
|
||||
CHECK_RETVAL(retval);
|
||||
}
|
||||
|
||||
void FuseOpenFile::stat(struct ::stat *result) const {
|
||||
int retval = ::fstat(_descriptor, result);
|
||||
CHECK_RETVAL(retval);
|
||||
}
|
||||
|
||||
void FuseOpenFile::truncate(off_t size) const {
|
||||
int retval = ::ftruncate(_descriptor, size);
|
||||
CHECK_RETVAL(retval);
|
||||
}
|
||||
|
||||
int FuseOpenFile::read(void *buf, size_t count, off_t offset) {
|
||||
//printf("Reading from real descriptor %d (%d, %d)\n", _descriptor, offset, count);
|
||||
//fflush(stdout);
|
||||
int retval = ::pread(_descriptor, buf, count, offset);
|
||||
CHECK_RETVAL(retval);
|
||||
//printf("retval: %d, count: %d\n", retval, count);
|
||||
//fflush(stdout);
|
||||
assert(static_cast<unsigned int>(retval) <= count);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void FuseOpenFile::write(const void *buf, size_t count, off_t offset) {
|
||||
int retval = ::pwrite(_descriptor, buf, count, offset);
|
||||
CHECK_RETVAL(retval);
|
||||
assert(static_cast<unsigned int>(retval) == count);
|
||||
}
|
||||
|
||||
void FuseOpenFile::fsync() {
|
||||
int retval = ::fsync(_descriptor);
|
||||
CHECK_RETVAL(retval);
|
||||
}
|
||||
|
||||
void FuseOpenFile::fdatasync() {
|
||||
int retval = ::fdatasync(_descriptor);
|
||||
CHECK_RETVAL(retval);
|
||||
}
|
||||
#include "FuseOpenFile.h"
|
||||
|
@ -5,28 +5,19 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "utils/macros.h"
|
||||
|
||||
namespace fusepp {
|
||||
class FuseDevice;
|
||||
|
||||
namespace bf = boost::filesystem;
|
||||
|
||||
class FuseOpenFile {
|
||||
public:
|
||||
FuseOpenFile(const FuseDevice *device, const bf::path &path, int flags);
|
||||
virtual ~FuseOpenFile();
|
||||
virtual ~FuseOpenFile() {}
|
||||
|
||||
void stat(struct ::stat *result) const;
|
||||
void truncate(off_t size) const;
|
||||
int read(void *buf, size_t count, off_t offset);
|
||||
void write(const void *buf, size_t count, off_t offset);
|
||||
void fsync();
|
||||
void fdatasync();
|
||||
private:
|
||||
int _descriptor;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FuseOpenFile);
|
||||
virtual void stat(struct ::stat *result) const = 0;
|
||||
virtual void truncate(off_t size) const = 0;
|
||||
virtual int read(void *buf, size_t count, off_t offset) = 0;
|
||||
virtual void write(const void *buf, size_t count, off_t offset) = 0;
|
||||
virtual void fsync() = 0;
|
||||
virtual void fdatasync() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,25 +1,6 @@
|
||||
#include <fusepp/FuseFile.h>
|
||||
#include <fusepp/FuseOpenFile.h>
|
||||
#include <fusepp/FuseOpenFileList.h>
|
||||
#include "FuseOpenFileList.h"
|
||||
|
||||
using namespace fusepp;
|
||||
|
||||
FuseOpenFileList::~FuseOpenFileList() {
|
||||
}
|
||||
|
||||
FuseOpenFileList::FuseOpenFileList()
|
||||
:_open_files() {
|
||||
}
|
||||
|
||||
int FuseOpenFileList::open(const FuseFile &file, int flags) {
|
||||
return _open_files.add(file.open(flags));
|
||||
}
|
||||
|
||||
FuseOpenFile *FuseOpenFileList::get(int descriptor) {
|
||||
return _open_files.get(descriptor);
|
||||
}
|
||||
|
||||
void FuseOpenFileList::close(int descriptor) {
|
||||
//The destructor of the stored FuseOpenFile closes the file
|
||||
_open_files.remove(descriptor);
|
||||
}
|
||||
|
@ -4,10 +4,10 @@
|
||||
|
||||
#include "utils/macros.h"
|
||||
#include "IdList.h"
|
||||
#include "FuseFile.h"
|
||||
#include "FuseOpenFile.h"
|
||||
|
||||
namespace fusepp {
|
||||
class FuseOpenFile;
|
||||
class FuseFile;
|
||||
|
||||
class FuseOpenFileList {
|
||||
public:
|
||||
@ -24,6 +24,23 @@ private:
|
||||
DISALLOW_COPY_AND_ASSIGN(FuseOpenFileList);
|
||||
};
|
||||
|
||||
inline FuseOpenFileList::FuseOpenFileList()
|
||||
:_open_files() {
|
||||
}
|
||||
|
||||
inline int FuseOpenFileList::open(const FuseFile &file, int flags) {
|
||||
return _open_files.add(file.open(flags));
|
||||
}
|
||||
|
||||
inline FuseOpenFile *FuseOpenFileList::get(int descriptor) {
|
||||
return _open_files.get(descriptor);
|
||||
}
|
||||
|
||||
inline void FuseOpenFileList::close(int descriptor) {
|
||||
//The destructor of the stored FuseOpenFile closes the file
|
||||
_open_files.remove(descriptor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* FUSEPP_FUSEOPENFILELIST_H_ */
|
||||
|
@ -1,5 +1 @@
|
||||
#include "IdList.h"
|
||||
|
||||
namespace fusepp {
|
||||
|
||||
} /* namespace fusepp */
|
||||
|
@ -6,4 +6,6 @@
|
||||
Class(const Class &rhs) = delete; \
|
||||
Class &operator=(const Class &rhs) = delete;
|
||||
|
||||
#define UNUSED(expr) (void)(expr)
|
||||
|
||||
#endif /* FUSEPP_UTILS_MACROS_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user