2014-11-15 17:24:07 +01:00
|
|
|
#include "FilesystemImpl.h"
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
2015-02-17 00:48:49 +01:00
|
|
|
#include "../fs_interface/Device.h"
|
|
|
|
#include "../fs_interface/Dir.h"
|
2015-04-22 16:00:14 +02:00
|
|
|
#include "../fs_interface/Symlink.h"
|
2014-11-15 17:24:07 +01:00
|
|
|
|
2015-02-17 00:48:49 +01:00
|
|
|
#include "../fuse/FuseErrnoException.h"
|
|
|
|
#include "../fs_interface/File.h"
|
2014-11-15 17:24:07 +01:00
|
|
|
|
|
|
|
|
2015-06-18 19:30:52 +02:00
|
|
|
#include <messmer/cpp-utils/unique_ref.h>
|
2014-11-15 17:24:07 +01:00
|
|
|
|
2014-11-16 00:05:28 +01:00
|
|
|
using namespace fspp;
|
2015-02-17 00:48:49 +01:00
|
|
|
using cpputils::dynamic_pointer_move;
|
2015-06-18 19:30:52 +02:00
|
|
|
using cpputils::unique_ref;
|
|
|
|
using cpputils::make_unique_ref;
|
2014-11-15 17:24:07 +01:00
|
|
|
using std::vector;
|
|
|
|
using std::string;
|
2015-06-18 19:30:52 +02:00
|
|
|
using boost::none;
|
2014-11-15 17:24:07 +01:00
|
|
|
|
|
|
|
namespace bf = boost::filesystem;
|
|
|
|
|
2014-11-15 23:47:38 +01:00
|
|
|
FilesystemImpl::FilesystemImpl(Device *device)
|
2014-11-15 17:24:07 +01:00
|
|
|
:_device(device), _open_files() {
|
|
|
|
}
|
|
|
|
|
|
|
|
FilesystemImpl::~FilesystemImpl() {
|
|
|
|
}
|
|
|
|
|
2015-06-18 19:30:52 +02:00
|
|
|
unique_ref<File> FilesystemImpl::LoadFile(const bf::path &path) {
|
2014-11-15 17:24:07 +01:00
|
|
|
auto node = _device->Load(path);
|
2015-06-18 19:30:52 +02:00
|
|
|
if (node == none) {
|
|
|
|
throw fuse::FuseErrnoException(EIO);
|
|
|
|
}
|
|
|
|
auto file = dynamic_pointer_move<File>(*node);
|
|
|
|
if (file == none) {
|
2014-11-28 14:46:45 +01:00
|
|
|
throw fuse::FuseErrnoException(EISDIR);
|
2014-11-15 17:24:07 +01:00
|
|
|
}
|
2015-06-18 19:30:52 +02:00
|
|
|
return std::move(*file);
|
2014-11-15 17:24:07 +01:00
|
|
|
}
|
|
|
|
|
2015-06-18 19:30:52 +02:00
|
|
|
unique_ref<Dir> FilesystemImpl::LoadDir(const bf::path &path) {
|
2014-11-15 17:24:07 +01:00
|
|
|
auto node = _device->Load(path);
|
2015-06-18 19:30:52 +02:00
|
|
|
if (node == none) {
|
|
|
|
throw fuse::FuseErrnoException(EIO);
|
|
|
|
}
|
|
|
|
auto dir = dynamic_pointer_move<Dir>(*node);
|
|
|
|
if (dir == none) {
|
2014-11-28 14:46:45 +01:00
|
|
|
throw fuse::FuseErrnoException(ENOTDIR);
|
2014-11-15 17:24:07 +01:00
|
|
|
}
|
2015-06-18 19:30:52 +02:00
|
|
|
return std::move(*dir);
|
2014-11-15 17:24:07 +01:00
|
|
|
}
|
|
|
|
|
2015-06-18 19:30:52 +02:00
|
|
|
unique_ref<Symlink> FilesystemImpl::LoadSymlink(const bf::path &path) {
|
2015-04-22 16:00:14 +02:00
|
|
|
auto node = _device->Load(path);
|
2015-06-18 19:30:52 +02:00
|
|
|
if (node == none) {
|
|
|
|
throw fuse::FuseErrnoException(EIO);
|
|
|
|
}
|
|
|
|
auto lnk = dynamic_pointer_move<Symlink>(*node);
|
|
|
|
if (lnk == none) {
|
2015-04-22 16:00:14 +02:00
|
|
|
throw fuse::FuseErrnoException(ENOTDIR);
|
|
|
|
}
|
2015-06-18 19:30:52 +02:00
|
|
|
return std::move(*lnk);
|
2015-04-22 16:00:14 +02:00
|
|
|
}
|
|
|
|
|
2014-11-15 17:24:07 +01:00
|
|
|
int FilesystemImpl::openFile(const bf::path &path, int flags) {
|
|
|
|
auto file = LoadFile(path);
|
|
|
|
return openFile(*file, flags);
|
|
|
|
}
|
|
|
|
|
2014-11-15 23:47:38 +01:00
|
|
|
int FilesystemImpl::openFile(const File &file, int flags) {
|
2015-03-11 00:22:36 +01:00
|
|
|
return _open_files.open(file.open(flags));
|
2014-11-15 17:24:07 +01:00
|
|
|
}
|
|
|
|
|
2014-11-21 01:11:24 +01:00
|
|
|
void FilesystemImpl::flush(int descriptor) {
|
|
|
|
_open_files.get(descriptor)->flush();
|
|
|
|
}
|
|
|
|
|
2014-11-15 17:24:07 +01:00
|
|
|
void FilesystemImpl::closeFile(int descriptor) {
|
|
|
|
_open_files.close(descriptor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::lstat(const bf::path &path, struct ::stat *stbuf) {
|
2015-06-18 19:30:52 +02:00
|
|
|
auto node = _device->Load(path);
|
|
|
|
if(node == none) {
|
|
|
|
throw fuse::FuseErrnoException(ENOENT);
|
|
|
|
} else {
|
|
|
|
(*node)->stat(stbuf);
|
|
|
|
}
|
2014-11-15 17:24:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::fstat(int descriptor, struct ::stat *stbuf) {
|
|
|
|
_open_files.get(descriptor)->stat(stbuf);
|
|
|
|
}
|
|
|
|
|
2015-04-21 21:08:23 +02:00
|
|
|
void FilesystemImpl::chmod(const boost::filesystem::path &path, mode_t mode) {
|
2015-06-18 19:30:52 +02:00
|
|
|
auto node = _device->Load(path);
|
|
|
|
if(node == none) {
|
|
|
|
throw fuse::FuseErrnoException(ENOENT);
|
|
|
|
} else {
|
|
|
|
(*node)->chmod(mode);
|
|
|
|
}
|
2015-04-21 21:08:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::chown(const boost::filesystem::path &path, uid_t uid, gid_t gid) {
|
2015-06-18 19:30:52 +02:00
|
|
|
auto node = _device->Load(path);
|
|
|
|
if(node == none) {
|
|
|
|
throw fuse::FuseErrnoException(ENOENT);
|
|
|
|
} else {
|
|
|
|
(*node)->chown(uid, gid);
|
|
|
|
}
|
2015-04-21 21:08:23 +02:00
|
|
|
}
|
|
|
|
|
2014-11-15 17:24:07 +01:00
|
|
|
void FilesystemImpl::truncate(const bf::path &path, off_t size) {
|
|
|
|
LoadFile(path)->truncate(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::ftruncate(int descriptor, off_t size) {
|
|
|
|
_open_files.get(descriptor)->truncate(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
int FilesystemImpl::read(int descriptor, void *buf, size_t count, off_t offset) {
|
|
|
|
return _open_files.get(descriptor)->read(buf, count, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::write(int descriptor, const void *buf, size_t count, off_t offset) {
|
|
|
|
_open_files.get(descriptor)->write(buf, count, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::fsync(int descriptor) {
|
|
|
|
_open_files.get(descriptor)->fsync();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::fdatasync(int descriptor) {
|
|
|
|
_open_files.get(descriptor)->fdatasync();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::access(const bf::path &path, int mask) {
|
2015-06-18 19:30:52 +02:00
|
|
|
auto node = _device->Load(path);
|
|
|
|
if(node == none) {
|
|
|
|
throw fuse::FuseErrnoException(ENOENT);
|
|
|
|
} else {
|
|
|
|
(*node)->access(mask);
|
|
|
|
}
|
2014-11-15 17:24:07 +01:00
|
|
|
}
|
|
|
|
|
2015-04-22 14:31:15 +02:00
|
|
|
int FilesystemImpl::createAndOpenFile(const bf::path &path, mode_t mode, uid_t uid, gid_t gid) {
|
2014-11-15 17:24:07 +01:00
|
|
|
//TODO Creating the file opens and closes it. We then reopen it afterwards.
|
|
|
|
// This is slow. Improve!
|
|
|
|
auto dir = LoadDir(path.parent_path());
|
2015-04-22 14:31:15 +02:00
|
|
|
auto file = dir->createAndOpenFile(path.filename().native(), mode, uid, gid);
|
2015-03-11 00:22:36 +01:00
|
|
|
return _open_files.open(std::move(file));
|
2014-11-15 17:24:07 +01:00
|
|
|
}
|
|
|
|
|
2015-04-22 14:31:15 +02:00
|
|
|
void FilesystemImpl::mkdir(const bf::path &path, mode_t mode, uid_t uid, gid_t gid) {
|
2014-11-15 17:24:07 +01:00
|
|
|
auto dir = LoadDir(path.parent_path());
|
2015-04-22 14:31:15 +02:00
|
|
|
dir->createDir(path.filename().native(), mode, uid, gid);
|
2014-11-15 17:24:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::rmdir(const bf::path &path) {
|
|
|
|
auto dir = LoadDir(path);
|
2015-04-10 23:24:28 +02:00
|
|
|
dir->remove();
|
2014-11-15 17:24:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::unlink(const bf::path &path) {
|
|
|
|
auto file = LoadFile(path);
|
2015-04-10 23:24:28 +02:00
|
|
|
file->remove();
|
2014-11-15 17:24:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::rename(const bf::path &from, const bf::path &to) {
|
|
|
|
auto node = _device->Load(from);
|
2015-06-18 19:30:52 +02:00
|
|
|
if(node == none) {
|
|
|
|
throw fuse::FuseErrnoException(ENOENT);
|
|
|
|
} else {
|
|
|
|
(*node)->rename(to);
|
|
|
|
}
|
2014-11-15 17:24:07 +01:00
|
|
|
}
|
|
|
|
|
2015-06-18 19:30:52 +02:00
|
|
|
unique_ref<vector<Dir::Entry>> FilesystemImpl::readDir(const bf::path &path) {
|
2014-11-15 17:24:07 +01:00
|
|
|
auto dir = LoadDir(path);
|
|
|
|
return dir->children();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::utimens(const bf::path &path, const timespec times[2]) {
|
|
|
|
auto node = _device->Load(path);
|
2015-06-18 19:30:52 +02:00
|
|
|
if(node == none) {
|
|
|
|
throw fuse::FuseErrnoException(ENOENT);
|
|
|
|
} else {
|
|
|
|
(*node)->utimens(times);
|
|
|
|
}
|
2014-11-15 17:24:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::statfs(const bf::path &path, struct statvfs *fsstat) {
|
|
|
|
_device->statfs(path, fsstat);
|
|
|
|
}
|
2015-04-22 16:00:14 +02:00
|
|
|
|
2015-04-23 09:17:23 +02:00
|
|
|
void FilesystemImpl::createSymlink(const bf::path &to, const bf::path &from, uid_t uid, gid_t gid) {
|
2015-04-22 16:00:14 +02:00
|
|
|
auto parent = LoadDir(from.parent_path());
|
2015-04-23 09:17:23 +02:00
|
|
|
parent->createSymlink(from.filename().native(), to, uid, gid);
|
2015-04-22 16:00:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void FilesystemImpl::readSymlink(const bf::path &path, char *buf, size_t size) {
|
|
|
|
string target = LoadSymlink(path)->target().native();
|
|
|
|
std::memcpy(buf, target.c_str(), std::min(target.size()+1, size));
|
|
|
|
buf[size-1] = '\0';
|
|
|
|
}
|