2014-11-15 16:33:24 +01:00
|
|
|
#include "Fuse.h"
|
2014-11-04 22:33:43 +01:00
|
|
|
#include <memory>
|
|
|
|
#include <cassert>
|
|
|
|
|
2015-02-17 00:48:49 +01:00
|
|
|
#include "FuseErrnoException.h"
|
2014-11-28 14:46:45 +01:00
|
|
|
#include "Filesystem.h"
|
2014-11-15 16:33:24 +01:00
|
|
|
|
2014-11-04 22:33:43 +01:00
|
|
|
using std::unique_ptr;
|
|
|
|
using std::make_unique;
|
|
|
|
using std::string;
|
|
|
|
|
|
|
|
namespace bf = boost::filesystem;
|
|
|
|
|
2014-11-16 00:05:28 +01:00
|
|
|
using namespace fspp::fuse;
|
2014-11-04 22:33:43 +01:00
|
|
|
|
|
|
|
#define FUSE_OBJ ((Fuse *) fuse_get_context()->private_data)
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
int fusepp_getattr(const char *path, struct stat *stbuf) {
|
2014-11-20 13:11:07 +01:00
|
|
|
int rs = FUSE_OBJ->getattr(bf::path(path), stbuf);
|
|
|
|
return rs;
|
2014-11-04 22:33:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_fgetattr(const char *path, struct stat *stbuf, fuse_file_info *fileinfo) {
|
|
|
|
return FUSE_OBJ->fgetattr(bf::path(path), stbuf, fileinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_readlink(const char *path, char *buf, size_t size) {
|
|
|
|
return FUSE_OBJ->readlink(bf::path(path), buf, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_mknod(const char *path, mode_t mode, dev_t rdev) {
|
|
|
|
return FUSE_OBJ->mknod(bf::path(path), mode, rdev);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_mkdir(const char *path, mode_t mode) {
|
|
|
|
return FUSE_OBJ->mkdir(bf::path(path), mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_unlink(const char *path) {
|
|
|
|
return FUSE_OBJ->unlink(bf::path(path));
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_rmdir(const char *path) {
|
|
|
|
return FUSE_OBJ->rmdir(bf::path(path));
|
|
|
|
}
|
|
|
|
|
2015-04-22 16:00:14 +02:00
|
|
|
int fusepp_symlink(const char *to, const char *from) {
|
|
|
|
return FUSE_OBJ->symlink(bf::path(to), bf::path(from));
|
2014-11-04 22:33:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_rename(const char *from, const char *to) {
|
|
|
|
return FUSE_OBJ->rename(bf::path(from), bf::path(to));
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_link(const char *from, const char *to) {
|
|
|
|
return FUSE_OBJ->link(bf::path(from), bf::path(to));
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_chmod(const char *path, mode_t mode) {
|
|
|
|
return FUSE_OBJ->chmod(bf::path(path), mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_chown(const char *path, uid_t uid, gid_t gid) {
|
|
|
|
return FUSE_OBJ->chown(bf::path(path), uid, gid);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_truncate(const char *path, off_t size) {
|
|
|
|
return FUSE_OBJ->truncate(bf::path(path), size);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_ftruncate(const char *path, off_t size, fuse_file_info *fileinfo) {
|
|
|
|
return FUSE_OBJ->ftruncate(bf::path(path), size, fileinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_utimens(const char *path, const timespec times[2]) {
|
|
|
|
return FUSE_OBJ->utimens(bf::path(path), times);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_open(const char *path, fuse_file_info *fileinfo) {
|
|
|
|
return FUSE_OBJ->open(bf::path(path), fileinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_release(const char *path, fuse_file_info *fileinfo) {
|
|
|
|
return FUSE_OBJ->release(bf::path(path), fileinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_read(const char *path, char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) {
|
|
|
|
return FUSE_OBJ->read(bf::path(path), buf, size, offset, fileinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_write(const char *path, const char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) {
|
|
|
|
return FUSE_OBJ->write(bf::path(path), buf, size, offset, fileinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_statfs(const char *path, struct statvfs *fsstat) {
|
|
|
|
return FUSE_OBJ->statfs(bf::path(path), fsstat);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_flush(const char *path, fuse_file_info *fileinfo) {
|
|
|
|
return FUSE_OBJ->flush(bf::path(path), fileinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_fsync(const char *path, int datasync, fuse_file_info *fileinfo) {
|
|
|
|
return FUSE_OBJ->fsync(bf::path(path), datasync, fileinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
//int fusepp_setxattr(const char*, const char*, const char*, size_t, int)
|
|
|
|
//int fusepp_getxattr(const char*, const char*, char*, size_t)
|
|
|
|
//int fusepp_listxattr(const char*, char*, size_t)
|
|
|
|
//int fusepp_removexattr(const char*, const char*)
|
|
|
|
|
|
|
|
int fusepp_opendir(const char *path, fuse_file_info *fileinfo) {
|
|
|
|
return FUSE_OBJ->opendir(bf::path(path), fileinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, fuse_file_info *fileinfo) {
|
|
|
|
return FUSE_OBJ->readdir(bf::path(path), buf, filler, offset, fileinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_releasedir(const char *path, fuse_file_info *fileinfo) {
|
|
|
|
return FUSE_OBJ->releasedir(bf::path(path), fileinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_fsyncdir(const char *path, int datasync, fuse_file_info *fileinfo) {
|
|
|
|
return FUSE_OBJ->fsyncdir(bf::path(path), datasync, fileinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
void* fusepp_init(fuse_conn_info *conn) {
|
|
|
|
auto f = FUSE_OBJ;
|
|
|
|
f->init(conn);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
void fusepp_destroy(void *userdata) {
|
|
|
|
auto f = FUSE_OBJ;
|
|
|
|
assert(userdata == f);
|
2014-11-12 22:38:12 +01:00
|
|
|
UNUSED(userdata); //In the Release build, the assert doesn't run
|
2014-11-04 22:33:43 +01:00
|
|
|
f->destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_access(const char *path, int mask) {
|
|
|
|
return FUSE_OBJ->access(bf::path(path), mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
int fusepp_create(const char *path, mode_t mode, fuse_file_info *fileinfo) {
|
|
|
|
return FUSE_OBJ->create(bf::path(path), mode, fileinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*int fusepp_lock(const char*, fuse_file_info*, int cmd, flock*)
|
|
|
|
int fusepp_bmap(const char*, size_t blocksize, uint64_t *idx)
|
|
|
|
int fusepp_ioctl(const char*, int cmd, void *arg, fuse_file_info*, unsigned int flags, void *data)
|
|
|
|
int fusepp_poll(const char*, fuse_file_info*, fuse_pollhandle *ph, unsigned *reventsp)
|
|
|
|
int fusepp_write_buf(const char*, fuse_bufvec *buf, off_t off, fuse_file_info*)
|
|
|
|
int fusepp_read_buf(const chas*, struct fuse_bufvec **bufp, size_t size, off_T off, fuse_file_info*)
|
|
|
|
int fusepp_flock(const char*, fuse_file_info*, int op)
|
|
|
|
int fusepp_fallocate(const char*, int, off_t, off_t, fuse_file_info*)*/
|
|
|
|
|
|
|
|
fuse_operations *operations() {
|
|
|
|
static unique_ptr<fuse_operations> singleton(nullptr);
|
|
|
|
|
|
|
|
if (!singleton) {
|
|
|
|
singleton = make_unique<fuse_operations>();
|
|
|
|
singleton->getattr = &fusepp_getattr;
|
|
|
|
singleton->fgetattr = &fusepp_fgetattr;
|
|
|
|
singleton->readlink = &fusepp_readlink;
|
|
|
|
singleton->mknod = &fusepp_mknod;
|
|
|
|
singleton->mkdir = &fusepp_mkdir;
|
|
|
|
singleton->unlink = &fusepp_unlink;
|
|
|
|
singleton->rmdir = &fusepp_rmdir;
|
|
|
|
singleton->symlink = &fusepp_symlink;
|
|
|
|
singleton->rename = &fusepp_rename;
|
|
|
|
singleton->link = &fusepp_link;
|
|
|
|
singleton->chmod = &fusepp_chmod;
|
|
|
|
singleton->chown = &fusepp_chown;
|
|
|
|
singleton->truncate = &fusepp_truncate;
|
|
|
|
singleton->utimens = &fusepp_utimens;
|
|
|
|
singleton->open = &fusepp_open;
|
|
|
|
singleton->read = &fusepp_read;
|
|
|
|
singleton->write = &fusepp_write;
|
|
|
|
singleton->statfs = &fusepp_statfs;
|
|
|
|
singleton->flush = &fusepp_flush;
|
|
|
|
singleton->release = &fusepp_release;
|
|
|
|
singleton->fsync = &fusepp_fsync;
|
|
|
|
/*#ifdef HAVE_SYS_XATTR_H
|
|
|
|
singleton->setxattr = &fusepp_setxattr;
|
|
|
|
singleton->getxattr = &fusepp_getxattr;
|
|
|
|
singleton->listxattr = &fusepp_listxattr;
|
|
|
|
singleton->removexattr = &fusepp_removexattr;
|
|
|
|
#endif*/
|
|
|
|
singleton->opendir = &fusepp_opendir;
|
|
|
|
singleton->readdir = &fusepp_readdir;
|
|
|
|
singleton->releasedir = &fusepp_releasedir;
|
|
|
|
singleton->fsyncdir = &fusepp_fsyncdir;
|
|
|
|
singleton->init = &fusepp_init;
|
|
|
|
singleton->destroy = &fusepp_destroy;
|
|
|
|
singleton->access = &fusepp_access;
|
|
|
|
singleton->create = &fusepp_create;
|
|
|
|
singleton->ftruncate = &fusepp_ftruncate;
|
|
|
|
}
|
|
|
|
|
|
|
|
return singleton.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Fuse::~Fuse() {
|
|
|
|
}
|
|
|
|
|
2014-11-19 00:14:35 +01:00
|
|
|
Fuse::Fuse(Filesystem *fs)
|
|
|
|
:_fs(fs), _running(false) {
|
2014-11-15 16:33:24 +01:00
|
|
|
}
|
|
|
|
|
2014-11-04 22:33:43 +01:00
|
|
|
void Fuse::run(int argc, char **argv) {
|
|
|
|
fuse_main(argc, argv, operations(), (void*)this);
|
|
|
|
}
|
2014-11-15 16:33:24 +01:00
|
|
|
|
2014-11-18 00:14:33 +01:00
|
|
|
bool Fuse::running() const {
|
|
|
|
return _running;
|
|
|
|
}
|
|
|
|
|
2014-11-15 16:33:24 +01:00
|
|
|
int Fuse::getattr(const bf::path &path, struct stat *stbuf) {
|
|
|
|
//printf("getattr(%s, _, _)\n", path.c_str());
|
|
|
|
try {
|
2014-11-19 00:14:35 +01:00
|
|
|
_fs->lstat(path, stbuf);
|
2014-11-15 16:33:24 +01:00
|
|
|
return 0;
|
2014-11-28 14:46:45 +01:00
|
|
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
2014-11-15 16:33:24 +01:00
|
|
|
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 {
|
2015-04-21 21:08:23 +02:00
|
|
|
_fs->fstat(fileinfo->fh, stbuf);
|
2014-11-15 16:33:24 +01:00
|
|
|
return 0;
|
2014-11-28 14:46:45 +01:00
|
|
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
2014-11-15 16:33:24 +01:00
|
|
|
return -e.getErrno();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int Fuse::readlink(const bf::path &path, char *buf, size_t size) {
|
2015-04-22 16:00:14 +02:00
|
|
|
//printf("readlink(%s, _, %zu)\n", path.c_str(), size);
|
|
|
|
try {
|
|
|
|
_fs->readSymlink(path, buf, size);
|
|
|
|
return 0;
|
|
|
|
} catch (fspp::fuse::FuseErrnoException &e) {
|
|
|
|
return -e.getErrno();
|
|
|
|
}
|
2014-11-15 16:33:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2015-04-22 14:31:15 +02:00
|
|
|
auto context = fuse_get_context();
|
|
|
|
_fs->mkdir(path, mode, context->uid, context->gid);
|
2014-11-15 16:33:24 +01:00
|
|
|
return 0;
|
2014-11-28 14:46:45 +01:00
|
|
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
2014-11-15 16:33:24 +01:00
|
|
|
return -e.getErrno();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int Fuse::unlink(const bf::path &path) {
|
|
|
|
//printf("unlink(%s)\n", path.c_str());
|
|
|
|
try {
|
2014-11-19 00:14:35 +01:00
|
|
|
_fs->unlink(path);
|
2014-11-15 16:33:24 +01:00
|
|
|
return 0;
|
2014-11-28 14:46:45 +01:00
|
|
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
2014-11-15 16:33:24 +01:00
|
|
|
return -e.getErrno();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int Fuse::rmdir(const bf::path &path) {
|
|
|
|
try {
|
2014-11-19 00:14:35 +01:00
|
|
|
_fs->rmdir(path);
|
2014-11-15 16:33:24 +01:00
|
|
|
return 0;
|
2014-11-28 14:46:45 +01:00
|
|
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
2014-11-15 16:33:24 +01:00
|
|
|
return -e.getErrno();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int Fuse::symlink(const bf::path &from, const bf::path &to) {
|
2015-04-22 16:00:14 +02:00
|
|
|
//printf("symlink(%s, %s)\n", from.c_str(), to.c_str());
|
|
|
|
try {
|
2015-04-23 09:17:23 +02:00
|
|
|
auto context = fuse_get_context();
|
|
|
|
_fs->createSymlink(from, to, context->uid, context->gid);
|
2015-04-22 16:00:14 +02:00
|
|
|
return 0;
|
|
|
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
|
|
|
return -e.getErrno();
|
|
|
|
}
|
2014-11-15 16:33:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int Fuse::rename(const bf::path &from, const bf::path &to) {
|
|
|
|
//printf("rename(%s, %s)\n", from.c_str(), to.c_str());
|
|
|
|
try {
|
2014-11-19 00:14:35 +01:00
|
|
|
_fs->rename(from, to);
|
2014-11-15 16:33:24 +01:00
|
|
|
return 0;
|
2014-11-28 14:46:45 +01:00
|
|
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
2014-11-15 16:33:24 +01:00
|
|
|
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());
|
2014-11-15 17:24:07 +01:00
|
|
|
//auto real_from = _impl->RootDir() / from;
|
|
|
|
//auto real_to = _impl->RootDir() / to;
|
2014-11-15 16:33:24 +01:00
|
|
|
//int retstat = ::link(real_from.c_str(), real_to.c_str());
|
|
|
|
//return errcode_map(retstat);
|
|
|
|
return ENOSYS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Fuse::chmod(const bf::path &path, mode_t mode) {
|
2015-04-21 21:08:23 +02:00
|
|
|
try {
|
|
|
|
_fs->chmod(path, mode);
|
|
|
|
return 0;
|
|
|
|
} catch (fspp::fuse::FuseErrnoException &e) {
|
|
|
|
return -e.getErrno();
|
|
|
|
}
|
2014-11-15 16:33:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int Fuse::chown(const bf::path &path, uid_t uid, gid_t gid) {
|
2015-04-21 21:08:23 +02:00
|
|
|
try {
|
|
|
|
_fs->chown(path, uid, gid);
|
|
|
|
return 0;
|
|
|
|
} catch (fspp::fuse::FuseErrnoException &e) {
|
|
|
|
return -e.getErrno();
|
|
|
|
}
|
2014-11-15 16:33:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int Fuse::truncate(const bf::path &path, off_t size) {
|
|
|
|
//printf("truncate(%s, %zu)\n", path.c_str(), size);
|
|
|
|
try {
|
2014-11-19 00:14:35 +01:00
|
|
|
_fs->truncate(path, size);
|
2014-11-15 16:33:24 +01:00
|
|
|
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 {
|
2014-11-19 00:14:35 +01:00
|
|
|
_fs->ftruncate(fileinfo->fh, size);
|
2014-11-15 16:33:24 +01:00
|
|
|
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 {
|
2014-11-19 00:14:35 +01:00
|
|
|
_fs->utimens(path, times);
|
2014-11-15 16:33:24 +01:00
|
|
|
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 {
|
2014-11-19 00:14:35 +01:00
|
|
|
fileinfo->fh = _fs->openFile(path, fileinfo->flags);
|
2014-11-15 16:33:24 +01:00
|
|
|
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 {
|
2014-11-19 00:14:35 +01:00
|
|
|
_fs->closeFile(fileinfo->fh);
|
2014-11-15 16:33:24 +01:00
|
|
|
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 {
|
2014-11-19 00:14:35 +01:00
|
|
|
return _fs->read(fileinfo->fh, buf, size, offset);
|
2014-11-15 16:33:24 +01:00
|
|
|
} 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 {
|
2014-11-19 00:14:35 +01:00
|
|
|
_fs->write(fileinfo->fh, buf, size, offset);
|
2014-11-15 16:33:24 +01:00
|
|
|
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 {
|
2014-11-19 00:14:35 +01:00
|
|
|
_fs->statfs(path, fsstat);
|
2014-11-15 16:33:24 +01:00
|
|
|
return 0;
|
|
|
|
} catch (FuseErrnoException &e) {
|
|
|
|
return -e.getErrno();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//TODO
|
|
|
|
int Fuse::flush(const bf::path &path, fuse_file_info *fileinfo) {
|
|
|
|
UNUSED(path);
|
2014-11-21 01:11:24 +01:00
|
|
|
//printf("Called non-implemented flush(%s, _)\n", path.c_str());
|
|
|
|
try {
|
|
|
|
_fs->flush(fileinfo->fh);
|
|
|
|
return 0;
|
|
|
|
} catch (FuseErrnoException &e) {
|
|
|
|
return -e.getErrno();
|
|
|
|
}
|
2014-11-15 16:33:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2014-11-19 00:14:35 +01:00
|
|
|
_fs->fdatasync(fileinfo->fh);
|
2014-11-15 16:33:24 +01:00
|
|
|
} else {
|
2014-11-19 00:14:35 +01:00
|
|
|
_fs->fsync(fileinfo->fh);
|
2014-11-15 16:33:24 +01:00
|
|
|
}
|
|
|
|
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 {
|
2014-11-19 00:14:35 +01:00
|
|
|
auto entries = _fs->readDir(path);
|
2015-03-11 00:22:36 +01:00
|
|
|
struct stat stbuf;
|
2014-11-15 16:33:24 +01:00
|
|
|
for (const auto &entry : *entries) {
|
2015-04-21 23:19:50 +02:00
|
|
|
//We could pass more file metadata to filler() in its third parameter,
|
|
|
|
//but it doesn't help performance since fuse ignores everything in stbuf
|
|
|
|
//except for file-type bits in st_mode and (if used) st_ino.
|
2014-11-15 16:33:24 +01:00
|
|
|
//It does getattr() calls on all entries nevertheless.
|
2015-03-11 00:22:36 +01:00
|
|
|
if (entry.type == Dir::EntryType::DIR) {
|
2015-04-21 23:19:50 +02:00
|
|
|
stbuf.st_mode = S_IFDIR;
|
2015-04-22 16:00:14 +02:00
|
|
|
} else if (entry.type == Dir::EntryType::FILE) {
|
2015-04-21 23:19:50 +02:00
|
|
|
stbuf.st_mode = S_IFREG;
|
2015-04-22 16:00:14 +02:00
|
|
|
} else if (entry.type == Dir::EntryType::SYMLINK) {
|
|
|
|
stbuf.st_mode = S_IFLNK;
|
|
|
|
} else {
|
|
|
|
assert(false);
|
2015-03-11 00:22:36 +01:00
|
|
|
}
|
|
|
|
if (filler(buf, entry.name.c_str(), &stbuf, 0) != 0) {
|
2014-11-15 16:33:24 +01:00
|
|
|
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);
|
2014-11-18 00:14:33 +01:00
|
|
|
_running = true;
|
2014-11-15 16:33:24 +01:00
|
|
|
//printf("init()\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void Fuse::destroy() {
|
2014-11-18 00:14:33 +01:00
|
|
|
_running = false;
|
2014-11-15 16:33:24 +01:00
|
|
|
//printf("destroy()\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
int Fuse::access(const bf::path &path, int mask) {
|
|
|
|
//printf("access(%s, %d)\n", path.c_str(), mask);
|
|
|
|
try {
|
2014-11-19 00:14:35 +01:00
|
|
|
_fs->access(path, mask);
|
2014-11-15 16:33:24 +01:00
|
|
|
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 {
|
2015-04-22 14:31:15 +02:00
|
|
|
auto context = fuse_get_context();
|
|
|
|
fileinfo->fh = _fs->createAndOpenFile(path, mode, context->uid, context->gid);
|
2014-11-15 16:33:24 +01:00
|
|
|
return 0;
|
|
|
|
} catch (FuseErrnoException &e) {
|
|
|
|
return -e.getErrno();
|
|
|
|
}
|
|
|
|
}
|