Refactor: Add fsblobstore layer

This commit is contained in:
Sebastian Messmer 2015-09-30 13:21:07 +02:00
parent dd39f242a2
commit e3d2fdb2fd
26 changed files with 514 additions and 350 deletions

View File

@ -1,6 +1,6 @@
#include <messmer/blockstore/implementations/caching/CachingBlockStore.h>
#include <messmer/blockstore/implementations/encrypted/ciphers/ciphers.h>
#include "impl/DirBlob.h"
#include "fsblobstore/DirBlob.h"
#include "CryDevice.h"
#include "CryDir.h"
@ -11,6 +11,7 @@
#include "messmer/blobstore/implementations/onblocks/BlobStoreOnBlocks.h"
#include "messmer/blobstore/implementations/onblocks/BlobOnBlocks.h"
#include "messmer/blockstore/implementations/encrypted/EncryptedBlockStore.h"
#include "fsblobstore/FsBlobStore.h"
using std::string;
@ -27,8 +28,14 @@ using blobstore::onblocks::BlobOnBlocks;
using blockstore::caching::CachingBlockStore;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using cpputils::dynamic_pointer_move;
using boost::optional;
using boost::none;
using cryfs::fsblobstore::FsBlobStore;
using cryfs::fsblobstore::FileBlob;
using cryfs::fsblobstore::DirBlob;
using cryfs::fsblobstore::SymlinkBlob;
using cryfs::fsblobstore::FsBlob;
namespace bf = boost::filesystem;
@ -37,14 +44,16 @@ namespace cryfs {
constexpr uint32_t CryDevice::BLOCKSIZE_BYTES;
CryDevice::CryDevice(unique_ref<CryConfig> config, unique_ref<BlockStore> blockStore)
: _blobStore(make_unique_ref<BlobStoreOnBlocks>(make_unique_ref<CachingBlockStore>(CreateEncryptedBlockStore(*config, std::move(blockStore))), BLOCKSIZE_BYTES)), _rootKey(GetOrCreateRootKey(config.get())) {
: _fsBlobStore(make_unique_ref<FsBlobStore>(
make_unique_ref<BlobStoreOnBlocks>(
make_unique_ref<CachingBlockStore>(
CreateEncryptedBlockStore(*config, std::move(blockStore))
), BLOCKSIZE_BYTES))),
_rootKey(GetOrCreateRootKey(config.get())) {
}
Key CryDevice::CreateRootBlobAndReturnKey() {
auto rootBlob = _blobStore->create();
Key rootBlobKey = rootBlob->key();
DirBlob::InitializeEmptyDir(std::move(rootBlob), this);
return rootBlobKey;
return _fsBlobStore->createDirBlob()->key();
}
CryDevice::~CryDevice() {
@ -58,63 +67,73 @@ optional<unique_ref<fspp::Node>> CryDevice::Load(const bf::path &path) {
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, none, _rootKey));
}
auto parent = LoadDirBlob(path.parent_path());
if (parent == none) {
//TODO Return correct fuse error
return none;
}
auto entry = (*parent)->GetChild(path.filename().native());
auto entry = parent->GetChild(path.filename().native());
if (entry.type == fspp::Dir::EntryType::DIR) {
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, std::move(*parent), entry.key));
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, std::move(parent), entry.key));
} else if (entry.type == fspp::Dir::EntryType::FILE) {
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryFile>(this, std::move(*parent), entry.key));
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryFile>(this, std::move(parent), entry.key));
} else if (entry.type == fspp::Dir::EntryType::SYMLINK) {
return optional<unique_ref<fspp::Node>>(make_unique_ref<CrySymlink>(this, std::move(*parent), entry.key));
return optional<unique_ref<fspp::Node>>(make_unique_ref<CrySymlink>(this, std::move(parent), entry.key));
} else {
ASSERT(false, "Unknown entry type");
}
}
optional<unique_ref<DirBlob>> CryDevice::LoadDirBlob(const bf::path &path) {
auto currentBlob = _blobStore->load(_rootKey);
if(currentBlob == none) {
//TODO Return correct fuse error
return none;
}
unique_ref<DirBlob> CryDevice::LoadDirBlob(const bf::path &path) {
auto blob = LoadBlob(path);
auto dir = dynamic_pointer_move<DirBlob>(blob);
ASSERT(dir != none, "Loaded blob is not a directory");
return std::move(*dir);
}
unique_ref<FsBlob> CryDevice::LoadBlob(const bf::path &path) {
auto currentBlob = _fsBlobStore->load(_rootKey);
//TODO Return correct fuse error
ASSERT(currentBlob != none, "rootDir not found");
for (const bf::path &component : path.relative_path()) {
//TODO Check whether the next path component is a dir.
// Right now, an assertion in DirBlob constructor will fail if it isn't.
// But fuse should rather return the correct error code.
unique_ref<DirBlob> currentDir = make_unique_ref<DirBlob>(std::move(*currentBlob), this);
auto currentDir = dynamic_pointer_move<DirBlob>(*currentBlob);
ASSERT(currentDir != none, "Path component is not a dir");
Key childKey = currentDir->GetChild(component.c_str()).key;
currentBlob = _blobStore->load(childKey);
if(currentBlob == none) {
//TODO Return correct fuse error
return none;
}
Key childKey = (*currentDir)->GetChild(component.c_str()).key;
currentBlob = _fsBlobStore->load(childKey);
ASSERT(currentBlob != none, "Blob for directory entry not found");
}
return make_unique_ref<DirBlob>(std::move(*currentBlob), this);
return std::move(*currentBlob);
//TODO Running the python script, waiting for "Create files in sequential order...", then going into dir ~/tmp/cryfs-mount-.../Bonnie.../ and calling "ls"
// crashes cryfs with a sigsegv.
// Possible reason: Many parallel changes to a directory blob are a race condition. Need something like ParallelAccessStore!
}
void CryDevice::statfs(const bf::path &path, struct statvfs *fsstat) {
throw FuseErrnoException(ENOTSUP);
}
unique_ref<blobstore::Blob> CryDevice::CreateBlob() {
return _blobStore->create();
unique_ref<FileBlob> CryDevice::CreateFileBlob() {
return _fsBlobStore->createFileBlob();
}
optional<unique_ref<blobstore::Blob>> CryDevice::LoadBlob(const blockstore::Key &key) {
return _blobStore->load(key);
unique_ref<DirBlob> CryDevice::CreateDirBlob() {
return _fsBlobStore->createDirBlob();
}
unique_ref<SymlinkBlob> CryDevice::CreateSymlinkBlob(const bf::path &target) {
return _fsBlobStore->createSymlinkBlob(target);
}
unique_ref<FsBlob> CryDevice::LoadBlob(const blockstore::Key &key) {
auto blob = _fsBlobStore->load(key);
ASSERT(blob != none, "Blob not found");
return std::move(*blob);
}
void CryDevice::RemoveBlob(const blockstore::Key &key) {
auto blob = _blobStore->load(key);
auto blob = _fsBlobStore->load(key);
ASSERT(blob != none, "Blob not found");
_blobStore->remove(std::move(*blob));
_fsBlobStore->remove(std::move(*blob));
}
Key CryDevice::GetOrCreateRootKey(CryConfig *config) {

View File

@ -3,16 +3,17 @@
#define CRYFS_LIB_CRYDEVICE_H_
#include <messmer/blockstore/interface/BlockStore.h>
#include <messmer/blobstore/interface/BlobStore.h>
#include "../config/CryConfigLoader.h"
#include <boost/filesystem.hpp>
#include <messmer/fspp/fs_interface/Device.h>
#include "messmer/cpp-utils/macros.h"
#include "fsblobstore/FsBlobStore.h"
#include "fsblobstore/DirBlob.h"
#include "fsblobstore/FileBlob.h"
#include "fsblobstore/SymlinkBlob.h"
namespace cryfs {
class DirBlob;
class CryDevice: public fspp::Device {
public:
@ -23,17 +24,20 @@ public:
void statfs(const boost::filesystem::path &path, struct ::statvfs *fsstat) override;
cpputils::unique_ref<blobstore::Blob> CreateBlob();
boost::optional<cpputils::unique_ref<blobstore::Blob>> LoadBlob(const blockstore::Key &key);
cpputils::unique_ref<fsblobstore::FileBlob> CreateFileBlob();
cpputils::unique_ref<fsblobstore::DirBlob> CreateDirBlob();
cpputils::unique_ref<fsblobstore::SymlinkBlob> CreateSymlinkBlob(const boost::filesystem::path &target);
cpputils::unique_ref<fsblobstore::FsBlob> LoadBlob(const blockstore::Key &key); //TODO Do I still need this function?
cpputils::unique_ref<fsblobstore::FsBlob> LoadBlob(const boost::filesystem::path &path);
cpputils::unique_ref<fsblobstore::DirBlob> LoadDirBlob(const boost::filesystem::path &path);
void RemoveBlob(const blockstore::Key &key);
boost::optional<cpputils::unique_ref<fspp::Node>> Load(const boost::filesystem::path &path) override;
boost::optional<cpputils::unique_ref<DirBlob>> LoadDirBlob(const boost::filesystem::path &path);
private:
cpputils::unique_ref<blobstore::BlobStore> _blobStore;
cpputils::unique_ref<fsblobstore::FsBlobStore> _fsBlobStore;
blockstore::Key _rootKey;

View File

@ -9,7 +9,7 @@
#include "CryDevice.h"
#include "CryFile.h"
#include "CryOpenFile.h"
#include "impl/SymlinkBlob.h"
#include "fsblobstore/SymlinkBlob.h"
//TODO Get rid of this in favor of exception hierarchy
using fspp::fuse::CHECK_RETVAL;
@ -23,8 +23,10 @@ using std::vector;
using blockstore::Key;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using cpputils::dynamic_pointer_move;
using boost::optional;
using boost::none;
using cryfs::fsblobstore::DirBlob;
namespace cryfs {
@ -37,36 +39,22 @@ CryDir::~CryDir() {
unique_ref<fspp::OpenFile> CryDir::createAndOpenFile(const string &name, mode_t mode, uid_t uid, gid_t gid) {
auto blob = LoadBlob();
if (blob == none) {
//TODO Return correct fuse error
throw FuseErrnoException(EIO);
}
auto child = device()->CreateBlob();
Key childkey = child->key();
(*blob)->AddChildFile(name, childkey, mode, uid, gid);
auto childblob = FileBlob::InitializeEmptyFile(std::move(child));
return make_unique_ref<CryOpenFile>(std::move(childblob));
auto child = device()->CreateFileBlob();
blob->AddChildFile(name, child->key(), mode, uid, gid);
return make_unique_ref<CryOpenFile>(std::move(child));
}
void CryDir::createDir(const string &name, mode_t mode, uid_t uid, gid_t gid) {
auto blob = LoadBlob();
if (blob == none) {
//TODO Return correct fuse error
throw FuseErrnoException(EIO);
}
auto child = device()->CreateBlob();
Key childkey = child->key();
(*blob)->AddChildDir(name, childkey, mode, uid, gid);
DirBlob::InitializeEmptyDir(std::move(child), device());
auto child = device()->CreateDirBlob();
blob->AddChildDir(name, child->key(), mode, uid, gid);
}
optional<unique_ref<DirBlob>> CryDir::LoadBlob() const {
unique_ref<DirBlob> CryDir::LoadBlob() const {
auto blob = CryNode::LoadBlob();
if(blob == none) {
return none;
}
//TODO Without const_cast?
return make_unique_ref<DirBlob>(std::move(*blob), const_cast<CryDevice*>(device()));
auto dir_blob = dynamic_pointer_move<DirBlob>(blob);
ASSERT(dir_blob != none, "Blob does not store a directory");
return std::move(*dir_blob);
}
unique_ref<vector<fspp::Dir::Entry>> CryDir::children() const {
@ -74,11 +62,7 @@ unique_ref<vector<fspp::Dir::Entry>> CryDir::children() const {
children->push_back(fspp::Dir::Entry(fspp::Dir::EntryType::DIR, "."));
children->push_back(fspp::Dir::Entry(fspp::Dir::EntryType::DIR, ".."));
auto blob = LoadBlob();
if (blob == none) {
//TODO Return correct fuse error
throw FuseErrnoException(EIO);
}
(*blob)->AppendChildrenTo(children.get());
blob->AppendChildrenTo(children.get());
return children;
}
@ -88,14 +72,8 @@ fspp::Dir::EntryType CryDir::getType() const {
void CryDir::createSymlink(const string &name, const bf::path &target, uid_t uid, gid_t gid) {
auto blob = LoadBlob();
if (blob == none) {
//TODO Return correct fuse error
throw FuseErrnoException(EIO);
}
auto child = device()->CreateBlob();
Key childkey = child->key();
(*blob)->AddChildSymlink(name, childkey, uid, gid);
SymlinkBlob::InitializeSymlink(std::move(child), target);
auto child = device()->CreateSymlinkBlob(target);
blob->AddChildSymlink(name, child->key(), uid, gid);
}
}

View File

@ -4,13 +4,13 @@
#include <messmer/fspp/fs_interface/Dir.h>
#include "CryNode.h"
#include "impl/DirBlob.h"
#include "fsblobstore/DirBlob.h"
namespace cryfs {
class CryDir: public fspp::Dir, CryNode {
public:
CryDir(CryDevice *device, boost::optional<cpputils::unique_ref<DirBlob>> parent, const blockstore::Key &key);
CryDir(CryDevice *device, boost::optional<cpputils::unique_ref<fsblobstore::DirBlob>> parent, const blockstore::Key &key);
virtual ~CryDir();
//TODO return type variance to CryFile/CryDir?
@ -24,7 +24,7 @@ public:
fspp::Dir::EntryType getType() const override;
private:
boost::optional<cpputils::unique_ref<DirBlob>> LoadBlob() const;
cpputils::unique_ref<fsblobstore::DirBlob> LoadBlob() const;
DISALLOW_COPY_AND_ASSIGN(CryDir);
};

View File

@ -3,7 +3,6 @@
#include "CryDevice.h"
#include "CryOpenFile.h"
#include "messmer/fspp/fuse/FuseErrnoException.h"
#include "impl/DirBlob.h"
namespace bf = boost::filesystem;
@ -15,6 +14,9 @@ using blockstore::Key;
using boost::none;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using cpputils::dynamic_pointer_move;
using cryfs::fsblobstore::DirBlob;
using cryfs::fsblobstore::FileBlob;
namespace cryfs {
@ -25,19 +27,21 @@ CryFile::CryFile(CryDevice *device, unique_ref<DirBlob> parent, const Key &key)
CryFile::~CryFile() {
}
unique_ref<fsblobstore::FileBlob> CryFile::LoadBlob() const {
auto blob = CryNode::LoadBlob();
auto file_blob = dynamic_pointer_move<FileBlob>(blob);
ASSERT(file_blob != none, "Blob does not store a file");
return std::move(*file_blob);
}
unique_ref<fspp::OpenFile> CryFile::open(int flags) const {
auto blob = LoadBlob();
ASSERT(blob != none, "Couldn't load blob");
return make_unique_ref<CryOpenFile>(make_unique_ref<FileBlob>(std::move(*blob)));
return make_unique_ref<CryOpenFile>(std::move(blob));
}
void CryFile::truncate(off_t size) const {
auto blob = LoadBlob();
if (blob == none) {
//TODO Log error
return;
}
FileBlob(std::move(*blob)).resize(size);
blob->resize(size);
}
fspp::Dir::EntryType CryFile::getType() const {

View File

@ -2,16 +2,16 @@
#ifndef CRYFS_LIB_CRYFILE_H_
#define CRYFS_LIB_CRYFILE_H_
#include "impl/FileBlob.h"
#include "fsblobstore/FileBlob.h"
#include "fsblobstore/DirBlob.h"
#include <messmer/fspp/fs_interface/File.h>
#include "CryNode.h"
namespace cryfs {
class CryFile: public fspp::File, CryNode {
public:
CryFile(CryDevice *device, cpputils::unique_ref<DirBlob> parent, const blockstore::Key &key);
CryFile(CryDevice *device, cpputils::unique_ref<fsblobstore::DirBlob> parent, const blockstore::Key &key);
virtual ~CryFile();
cpputils::unique_ref<fspp::OpenFile> open(int flags) const override;
@ -19,6 +19,7 @@ public:
fspp::Dir::EntryType getType() const override;
private:
cpputils::unique_ref<fsblobstore::FileBlob> LoadBlob() const;
DISALLOW_COPY_AND_ASSIGN(CryFile);
};

View File

@ -16,6 +16,8 @@ using cpputils::dynamic_pointer_move;
using cpputils::unique_ref;
using boost::optional;
using boost::none;
using cryfs::fsblobstore::FsBlob;
using cryfs::fsblobstore::DirBlob;
//TODO Get rid of this in favor of an exception hierarchy
using fspp::fuse::CHECK_RETVAL;
@ -53,11 +55,7 @@ void CryNode::rename(const bf::path &to) {
(*_parent)->RemoveChild(_key);
(*_parent)->flush();
auto targetDir = _device->LoadDirBlob(to.parent_path());
if (targetDir == none) {
//TODO Return correct fuse error
throw FuseErrnoException(ENOSPC);
}
(*targetDir)->AddChild(to.filename().native(), _key, getType(), mode, uid, gid);
targetDir->AddChild(to.filename().native(), _key, getType(), mode, uid, gid);
}
void CryNode::utimens(const timespec times[2]) {
@ -84,7 +82,7 @@ const CryDevice *CryNode::device() const {
return _device;
}
optional<unique_ref<Blob>> CryNode::LoadBlob() const {
unique_ref<FsBlob> CryNode::LoadBlob() const {
return _device->LoadBlob(_key);
}

View File

@ -5,14 +5,14 @@
#include <messmer/fspp/fs_interface/Node.h>
#include "messmer/cpp-utils/macros.h"
#include <messmer/fspp/fs_interface/Dir.h>
#include "fsblobstore/DirBlob.h"
#include "CryDevice.h"
namespace cryfs {
class CryNode: public virtual fspp::Node {
public:
CryNode(CryDevice *device, boost::optional<cpputils::unique_ref<DirBlob>> parent, const blockstore::Key &key);
CryNode(CryDevice *device, boost::optional<cpputils::unique_ref<fsblobstore::DirBlob>> parent, const blockstore::Key &key);
void access(int mask) const override;
void stat(struct ::stat *result) const override;
void chmod(mode_t mode) override;
@ -27,13 +27,13 @@ protected:
CryDevice *device();
const CryDevice *device() const;
boost::optional<cpputils::unique_ref<blobstore::Blob>> LoadBlob() const;
cpputils::unique_ref<fsblobstore::FsBlob> LoadBlob() const;
virtual fspp::Dir::EntryType getType() const = 0;
private:
CryDevice *_device;
boost::optional<cpputils::unique_ref<DirBlob>> _parent;
boost::optional<cpputils::unique_ref<fsblobstore::DirBlob>> _parent;
blockstore::Key _key;
DISALLOW_COPY_AND_ASSIGN(CryNode);

View File

@ -5,12 +5,11 @@
#include "CryDevice.h"
#include "messmer/fspp/fuse/FuseErrnoException.h"
#include "impl/FileBlob.h"
namespace bf = boost::filesystem;
using cpputils::unique_ref;
using blobstore::Blob;
using cryfs::fsblobstore::FileBlob;
//TODO Get rid of this in favor of a exception hierarchy
using fspp::fuse::CHECK_RETVAL;

View File

@ -3,16 +3,14 @@
#define CRYFS_LIB_CRYOPENFILE_H_
#include "messmer/fspp/fs_interface/OpenFile.h"
#include <messmer/cpp-utils/macros.h>
#include <messmer/cpp-utils/pointer/unique_ref.h>
#include "fsblobstore/FileBlob.h"
namespace cryfs {
class CryDevice;
class FileBlob;
class CryOpenFile: public fspp::OpenFile {
public:
explicit CryOpenFile(cpputils::unique_ref<FileBlob> fileBlob);
explicit CryOpenFile(cpputils::unique_ref<fsblobstore::FileBlob> fileBlob);
virtual ~CryOpenFile();
void stat(struct ::stat *result) const override;
@ -24,7 +22,7 @@ public:
void fdatasync() override;
private:
cpputils::unique_ref<FileBlob> _fileBlob;
cpputils::unique_ref<fsblobstore::FileBlob> _fileBlob;
DISALLOW_COPY_AND_ASSIGN(CryOpenFile);
};

View File

@ -3,7 +3,7 @@
#include "messmer/fspp/fuse/FuseErrnoException.h"
#include "CryDevice.h"
#include "CrySymlink.h"
#include "impl/SymlinkBlob.h"
#include "fsblobstore/SymlinkBlob.h"
//TODO Get rid of this in favor of exception hierarchy
using fspp::fuse::CHECK_RETVAL;
@ -19,6 +19,9 @@ using boost::none;
using boost::optional;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using cpputils::dynamic_pointer_move;
using cryfs::fsblobstore::SymlinkBlob;
using cryfs::fsblobstore::DirBlob;
namespace cryfs {
@ -29,12 +32,11 @@ CrySymlink::CrySymlink(CryDevice *device, unique_ref<DirBlob> parent, const Key
CrySymlink::~CrySymlink() {
}
optional<unique_ref<SymlinkBlob>> CrySymlink::LoadBlob() const {
unique_ref<SymlinkBlob> CrySymlink::LoadBlob() const {
auto blob = CryNode::LoadBlob();
if (blob == none) {
return none;
}
return make_unique_ref<SymlinkBlob>(std::move(*blob));
auto symlink_blob = dynamic_pointer_move<SymlinkBlob>(blob);
ASSERT(symlink_blob != none, "Blob does not store a symlink");
return std::move(*symlink_blob);
}
fspp::Dir::EntryType CrySymlink::getType() const {
@ -43,11 +45,7 @@ fspp::Dir::EntryType CrySymlink::getType() const {
bf::path CrySymlink::target() const {
auto blob = LoadBlob();
if (blob == none) {
//TODO Return correct fuse error
throw FuseErrnoException(EIO);
}
return (*blob)->target();
return blob->target();
}
}

View File

@ -4,14 +4,14 @@
#include <messmer/fspp/fs_interface/Symlink.h>
#include "CryNode.h"
#include "impl/SymlinkBlob.h"
#include "impl/DirBlob.h"
#include "fsblobstore/SymlinkBlob.h"
#include "fsblobstore/DirBlob.h"
namespace cryfs {
class CrySymlink: public fspp::Symlink, CryNode {
public:
CrySymlink(CryDevice *device, cpputils::unique_ref<DirBlob> parent, const blockstore::Key &key);
CrySymlink(CryDevice *device, cpputils::unique_ref<fsblobstore::DirBlob> parent, const blockstore::Key &key);
virtual ~CrySymlink();
boost::filesystem::path target() const override;
@ -19,7 +19,7 @@ public:
fspp::Dir::EntryType getType() const override;
private:
boost::optional<cpputils::unique_ref<SymlinkBlob>> LoadBlob() const;
cpputils::unique_ref<fsblobstore::SymlinkBlob> LoadBlob() const;
DISALLOW_COPY_AND_ASSIGN(CrySymlink);
};

View File

@ -24,9 +24,12 @@ using cpputils::make_unique_ref;
using boost::none;
namespace cryfs {
namespace fsblobstore {
DirBlob::DirBlob(unique_ref<Blob> blob, CryDevice *device) :
_device(device), _blob(std::move(blob)), _entries(), _changed(false) {
//TODO Factor out a DirEntryList class
DirBlob::DirBlob(unique_ref<Blob> blob, FsBlobStore *fsBlobStore) :
FsBlob(std::move(blob)), _fsBlobStore(fsBlobStore), _entries(), _changed(false) {
ASSERT(magicNumber() == MagicNumbers::DIR, "Loaded blob is not a directory");
_readEntriesFromBlob();
}
@ -37,43 +40,35 @@ DirBlob::~DirBlob() {
void DirBlob::flush() {
_writeEntriesToBlob();
_blob->flush();
baseBlob().flush();
}
unique_ref<DirBlob> DirBlob::InitializeEmptyDir(unique_ref<Blob> blob, CryDevice *device) {
blob->resize(1);
unsigned char magicNumber = MagicNumbers::DIR;
blob->write(&magicNumber, 0, 1);
return make_unique_ref<DirBlob>(std::move(blob), device);
}
unsigned char DirBlob::magicNumber() const {
unsigned char number;
_blob->read(&number, 0, 1);
return number;
unique_ref<DirBlob> DirBlob::InitializeEmptyDir(unique_ref<Blob> blob, FsBlobStore *fsBlobStore) {
InitializeBlobWithMagicNumber(blob.get(), MagicNumbers::DIR);
return make_unique_ref<DirBlob>(std::move(blob), fsBlobStore);
}
void DirBlob::_writeEntriesToBlob() {
if (_changed) {
//TODO Resizing is imperformant
_blob->resize(1);
baseBlob().resize(1);
unsigned int offset = 1;
for (const auto &entry : _entries) {
uint8_t entryTypeMagicNumber = static_cast<uint8_t>(entry.type);
_blob->write(&entryTypeMagicNumber, offset, 1);
baseBlob().write(&entryTypeMagicNumber, offset, 1);
offset += 1;
_blob->write(entry.name.c_str(), offset, entry.name.size() + 1);
baseBlob().write(entry.name.c_str(), offset, entry.name.size() + 1);
offset += entry.name.size() + 1;
string keystr = entry.key.ToString();
_blob->write(keystr.c_str(), offset, keystr.size() + 1);
baseBlob().write(keystr.c_str(), offset, keystr.size() + 1);
offset += keystr.size() + 1;
_blob->write(&entry.uid, offset, sizeof(uid_t));
baseBlob().write(&entry.uid, offset, sizeof(uid_t));
//TODO Writing them all in separate write calls is maybe imperformant. We could write the whole entry in one write call instead.
offset += sizeof(uid_t);
_blob->write(&entry.gid, offset, sizeof(gid_t));
offset += sizeof(gid_t);
_blob->write(&entry.mode, offset, sizeof(mode_t));
offset += sizeof(mode_t);
baseBlob().write(&entry.gid, offset, sizeof(gid_t));
offset += sizeof(gid_t);
baseBlob().write(&entry.mode, offset, sizeof(mode_t));
offset += sizeof(mode_t);
}
_changed = false;
}
@ -81,8 +76,9 @@ void DirBlob::_writeEntriesToBlob() {
void DirBlob::_readEntriesFromBlob() {
_entries.clear();
Data data(_blob->size() - 1);
_blob->read(data.data(), 1, _blob->size() - 1);
//TODO Getting size and then reading traverses tree twice. Something like readAll() would be faster.
Data data(baseBlob().size() - 1);
baseBlob().read(data.data(), 1, baseBlob().size() - 1);
const char *pos = (const char*) data.data();
while (pos < (const char*) data.data() + data.size()) {
@ -193,10 +189,15 @@ void DirBlob::AppendChildrenTo(vector<fspp::Dir::Entry> *result) const {
}
}
off_t DirBlob::lstat_size() const {
//TODO Why do dirs have 4096 bytes in size? Does that make sense?
return 4096;
}
void DirBlob::statChild(const Key &key, struct ::stat *result) const {
auto child = GetChild(key);
//TODO Loading the blob for only getting the size of the file/symlink is not very performant.
// Furthermore, this is the only reason why DirBlob needs a pointer to CryDevice, which is ugly
// Furthermore, this is the only reason why DirBlob needs a pointer to _fsBlobStore, which is ugly
result->st_mode = child.mode;
result->st_uid = child.uid;
result->st_gid = child.gid;
@ -204,30 +205,12 @@ void DirBlob::statChild(const Key &key, struct ::stat *result) const {
result->st_nlink = 1;
//TODO Handle file access times
result->st_mtime = result->st_ctime = result->st_atime = 0;
if (child.type == fspp::Dir::EntryType::FILE) {
auto blob = _device->LoadBlob(key);
if (blob == none) {
//TODO Log error
} else {
result->st_size = FileBlob(std::move(*blob)).size();
}
} else if (child.type == fspp::Dir::EntryType::DIR) {
//TODO Why do dirs have 4096 bytes in size? Does that make sense?
result->st_size = 4096;
} else if (child.type == fspp::Dir::EntryType::SYMLINK) {
//TODO Necessary with fuse or does fuse set this on symlinks anyhow?
auto blob = _device->LoadBlob(key);
if (blob == none) {
//TODO Log error
} else {
result->st_size = SymlinkBlob(std::move(*blob)).target().native().size();
}
} else {
ASSERT(false, "Unknown child type");
}
auto blob = _fsBlobStore->load(key);
ASSERT(blob != none, "Blob for directory entry not found");
result->st_size = (*blob)->lstat_size();
//TODO Move ceilDivision to general utils which can be used by cryfs as well
result->st_blocks = blobstore::onblocks::utils::ceilDivision(result->st_size, 512);
result->st_blksize = _device->BLOCKSIZE_BYTES;
result->st_blksize = CryDevice::BLOCKSIZE_BYTES; //TODO _fsBlobStore->BLOCKSIZE_BYTES would be cleaner
}
void DirBlob::chmodChild(const Key &key, mode_t mode) {
@ -250,3 +233,4 @@ void DirBlob::chownChild(const Key &key, uid_t uid, gid_t gid) {
}
}
}

View File

@ -0,0 +1,104 @@
#pragma once
#ifndef CRYFS_FSBLOBSTORE_DIRBLOB_H_
#define CRYFS_FSBLOBSTORE_DIRBLOB_H_
#include <messmer/blockstore/utils/Key.h>
#include <messmer/cpp-utils/macros.h>
#include <messmer/fspp/fs_interface/Dir.h>
#include "FsBlob.h"
#include <vector>
namespace cryfs {
namespace fsblobstore {
class FsBlobStore;
class DirBlob : public FsBlob {
public:
struct Entry {
Entry(fspp::Dir::EntryType type_, const std::string &name_, const blockstore::Key &key_, mode_t mode_,
uid_t uid_, gid_t gid_) : type(type_), name(name_), key(key_), mode(mode_), uid(uid_), gid(gid_) {
switch (type) {
case fspp::Dir::EntryType::FILE:
mode |= S_IFREG;
break;
case fspp::Dir::EntryType::DIR:
mode |= S_IFDIR;
break;
case fspp::Dir::EntryType::SYMLINK:
mode |= S_IFLNK;
break;
}
ASSERT((S_ISREG(mode) && type == fspp::Dir::EntryType::FILE) ||
(S_ISDIR(mode) && type == fspp::Dir::EntryType::DIR) ||
(S_ISLNK(mode) && type == fspp::Dir::EntryType::SYMLINK), "Unknown mode in entry");
}
fspp::Dir::EntryType type;
std::string name;
blockstore::Key key;
mode_t mode;
uid_t uid;
gid_t gid;
};
static cpputils::unique_ref<DirBlob> InitializeEmptyDir(cpputils::unique_ref<blobstore::Blob> blob,
FsBlobStore *fsBlobStore);
DirBlob(cpputils::unique_ref<blobstore::Blob> blob, FsBlobStore *fsBlobStore);
virtual ~DirBlob();
off_t lstat_size() const override;
void AppendChildrenTo(std::vector<fspp::Dir::Entry> *result) const;
const Entry &GetChild(const std::string &name) const;
const Entry &GetChild(const blockstore::Key &key) const;
void AddChildDir(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid,
gid_t gid);
void AddChildFile(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid,
gid_t gid);
void AddChildSymlink(const std::string &name, const blockstore::Key &blobKey, uid_t uid, gid_t gid);
void AddChild(const std::string &name, const blockstore::Key &blobKey, fspp::Dir::EntryType type,
mode_t mode,
uid_t uid, gid_t gid);
void RemoveChild(const blockstore::Key &key);
void flush();
void statChild(const blockstore::Key &key, struct ::stat *result) const;
void chmodChild(const blockstore::Key &key, mode_t mode);
void chownChild(const blockstore::Key &key, uid_t uid, gid_t gid);
private:
const char *readAndAddNextChild(const char *pos, std::vector<Entry> *result) const;
bool hasChild(const std::string &name) const;
void _readEntriesFromBlob();
void _writeEntriesToBlob();
std::vector<DirBlob::Entry>::iterator _findChild(const blockstore::Key &key);
FsBlobStore *_fsBlobStore;
std::vector<Entry> _entries;
bool _changed;
DISALLOW_COPY_AND_ASSIGN(DirBlob);
};
}
}
#endif

View File

@ -9,49 +9,45 @@ using cpputils::unique_ref;
using cpputils::make_unique_ref;
namespace cryfs {
namespace fsblobstore {
FileBlob::FileBlob(unique_ref<Blob> blob)
: _blob(std::move(blob)) {
}
FileBlob::~FileBlob() {
: FsBlob(std::move(blob)) {
}
unique_ref<FileBlob> FileBlob::InitializeEmptyFile(unique_ref<Blob> blob) {
blob->resize(1);
unsigned char magicNumber = MagicNumbers::FILE;
blob->write(&magicNumber, 0, 1);
InitializeBlobWithMagicNumber(blob.get(), MagicNumbers::FILE);
return make_unique_ref<FileBlob>(std::move(blob));
}
unsigned char FileBlob::magicNumber() const {
unsigned char value;
_blob->read(&value, 0, 1);
return value;
}
ssize_t FileBlob::read(void *target, uint64_t offset, uint64_t count) const {
return _blob->tryRead(target, offset + 1, count);
return baseBlob().tryRead(target, offset + 1, count);
}
void FileBlob::write(const void *source, uint64_t offset, uint64_t count) {
_blob->write(source, offset + 1, count);
baseBlob().write(source, offset + 1, count);
}
void FileBlob::flush() {
_blob->flush();
baseBlob().flush();
}
blockstore::Key FileBlob::key() const {
return _blob->key();
return baseBlob().key();
}
void FileBlob::resize(off_t size) {
_blob->resize(size+1);
baseBlob().resize(size+1);
}
off_t FileBlob::lstat_size() const {
return size();
}
off_t FileBlob::size() const {
return _blob->size()-1;
return baseBlob().size()-1;
}
}
}

View File

@ -0,0 +1,34 @@
#pragma once
#ifndef CRYFS_FSBLOBSTORE_FILEBLOB_H_
#define CRYFS_FSBLOBSTORE_FILEBLOB_H_
#include "FsBlob.h"
namespace cryfs {
namespace fsblobstore {
class FileBlob: public FsBlob {
public:
static cpputils::unique_ref<FileBlob> InitializeEmptyFile(cpputils::unique_ref<blobstore::Blob> blob);
FileBlob(cpputils::unique_ref<blobstore::Blob> blob);
ssize_t read(void *target, uint64_t offset, uint64_t count) const;
void write(const void *source, uint64_t offset, uint64_t count);
void flush();
void resize(off_t size);
off_t lstat_size() const override;
off_t size() const;
blockstore::Key key() const;
};
}
}
#endif

View File

@ -0,0 +1 @@
#include "FsBlob.h"

View File

@ -0,0 +1,75 @@
#ifndef CRYFS_FSBLOBSTORE_FSBLOB_H
#define CRYFS_FSBLOBSTORE_FSBLOB_H
#include <messmer/cpp-utils/pointer/unique_ref.h>
#include <messmer/blobstore/interface/Blob.h>
namespace cryfs {
namespace fsblobstore {
class FsBlob {
public:
virtual ~FsBlob();
virtual off_t lstat_size() const = 0;
blockstore::Key key() const;
protected:
FsBlob(cpputils::unique_ref<blobstore::Blob> baseBlob);
blobstore::Blob &baseBlob();
const blobstore::Blob &baseBlob() const;
unsigned char magicNumber() const;
static unsigned char magicNumber(const blobstore::Blob &blob);
static void InitializeBlobWithMagicNumber(blobstore::Blob *blob, unsigned char magicNumber);
private:
friend class FsBlobStore;
cpputils::unique_ref<blobstore::Blob> releaseBaseBlob();
cpputils::unique_ref<blobstore::Blob> _baseBlob;
DISALLOW_COPY_AND_ASSIGN(FsBlob);
};
inline FsBlob::FsBlob(cpputils::unique_ref<blobstore::Blob> baseBlob): _baseBlob(std::move(baseBlob)) {
}
inline FsBlob::~FsBlob() {
}
inline blockstore::Key FsBlob::key() const {
return _baseBlob->key();
}
inline const blobstore::Blob &FsBlob::baseBlob() const {
return *_baseBlob;
}
inline blobstore::Blob &FsBlob::baseBlob() {
return *_baseBlob;
}
inline unsigned char FsBlob::magicNumber(const blobstore::Blob &blob) {
unsigned char value;
blob.read(&value, 0, 1);
return value;
}
inline unsigned char FsBlob::magicNumber() const {
return magicNumber(*_baseBlob);
}
inline void FsBlob::InitializeBlobWithMagicNumber(blobstore::Blob *blob, unsigned char magicNumber) {
blob->resize(1);
blob->write(&magicNumber, 0, 1);
}
inline cpputils::unique_ref<blobstore::Blob> FsBlob::releaseBaseBlob() {
return std::move(_baseBlob);
}
}
}
#endif

View File

@ -0,0 +1,55 @@
#include "FsBlobStore.h"
#include "FileBlob.h"
#include "DirBlob.h"
#include "SymlinkBlob.h"
#include "MagicNumbers.h"
namespace bf = boost::filesystem;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using blobstore::BlobStore;
using boost::none;
namespace cryfs {
namespace fsblobstore {
FsBlobStore::FsBlobStore(unique_ref<BlobStore> baseBlobStore): _baseBlobStore(std::move(baseBlobStore)) {
}
unique_ref<FileBlob> FsBlobStore::createFileBlob() {
return FileBlob::InitializeEmptyFile(_baseBlobStore->create());
}
unique_ref<DirBlob> FsBlobStore::createDirBlob() {
//TODO Passed in fsBlobStore should be ParallelAccessFsBlobStore later
return DirBlob::InitializeEmptyDir(_baseBlobStore->create(), this);
}
unique_ref<SymlinkBlob> FsBlobStore::createSymlinkBlob(const bf::path &target) {
return SymlinkBlob::InitializeSymlink(_baseBlobStore->create(), target);
}
boost::optional<unique_ref<FsBlob>> FsBlobStore::load(const blockstore::Key &key) {
auto blob = _baseBlobStore->load(key);
if (blob == none) {
return none;
}
unsigned char magicNumber = FsBlob::magicNumber(**blob);
if (magicNumber == MagicNumbers::FILE) {
return unique_ref<FsBlob>(make_unique_ref<FileBlob>(std::move(*blob)));
} else if (magicNumber == MagicNumbers::DIR) {
//TODO Passed in fsBlobStore should be ParallelAccessFsBlobStore later
return unique_ref<FsBlob>(make_unique_ref<DirBlob>(std::move(*blob), this));
} else if (magicNumber == MagicNumbers::SYMLINK) {
return unique_ref<FsBlob>(make_unique_ref<SymlinkBlob>(std::move(*blob)));
} else {
ASSERT(false, "Unknown magic number");
}
}
void FsBlobStore::remove(cpputils::unique_ref<FsBlob> blob) {
_baseBlobStore->remove(blob->releaseBaseBlob());
}
}
}

View File

@ -0,0 +1,28 @@
#ifndef CRYFS_FSBLOBSTORE_FSBLOBSTORE_H
#define CRYFS_FSBLOBSTORE_FSBLOBSTORE_H
#include <messmer/cpp-utils/pointer/unique_ref.h>
#include <messmer/blobstore/interface/BlobStore.h>
#include "FileBlob.h"
#include "DirBlob.h"
#include "SymlinkBlob.h"
namespace cryfs {
namespace fsblobstore {
class FsBlobStore {
public:
FsBlobStore(cpputils::unique_ref<blobstore::BlobStore> baseBlobStore);
cpputils::unique_ref<FileBlob> createFileBlob();
cpputils::unique_ref<DirBlob> createDirBlob();
cpputils::unique_ref<SymlinkBlob> createSymlinkBlob(const boost::filesystem::path &target);
boost::optional<cpputils::unique_ref<FsBlob>> load(const blockstore::Key &key);
void remove(cpputils::unique_ref<FsBlob> blob);
private:
cpputils::unique_ref<blobstore::BlobStore> _baseBlobStore;
};
}
}
#endif

View File

@ -1,8 +1,9 @@
#pragma once
#ifndef CRYFS_LIB_IMPL_MAGICNUMBERS_H_
#define CRYFS_LIB_IMPL_MAGICNUMBERS_H_
#ifndef CRYFS_FSBLOBSTORE_MAGICNUMBERS_H_
#define CRYFS_FSBLOBSTORE_MAGICNUMBERS_H_
namespace cryfs {
namespace fsblobstore {
//TODO enum class
enum MagicNumbers {
@ -12,6 +13,7 @@ enum MagicNumbers {
};
}
}

View File

@ -12,15 +12,10 @@ using cpputils::make_unique_ref;
namespace bf = boost::filesystem;
namespace cryfs {
namespace fsblobstore {
SymlinkBlob::SymlinkBlob(unique_ref<Blob> blob)
: _target(_readTargetFromBlob(*blob)) {
}
SymlinkBlob::SymlinkBlob(const bf::path &target) :_target(target) {
}
SymlinkBlob::~SymlinkBlob() {
: FsBlob(std::move(blob)), _target(_readTargetFromBlob(baseBlob())) {
}
unique_ref<SymlinkBlob> SymlinkBlob::InitializeSymlink(unique_ref<Blob> blob, const bf::path &target) {
@ -29,7 +24,7 @@ unique_ref<SymlinkBlob> SymlinkBlob::InitializeSymlink(unique_ref<Blob> blob, co
unsigned char magicNumber = MagicNumbers::SYMLINK;
blob->write(&magicNumber, 0, 1);
blob->write(targetStr.c_str(), 1, targetStr.size());
return make_unique_ref<SymlinkBlob>(target);
return make_unique_ref<SymlinkBlob>(std::move(blob));
}
void SymlinkBlob::_checkMagicNumber(const Blob &blob) {
@ -51,4 +46,9 @@ const bf::path &SymlinkBlob::target() const {
return _target;
}
off_t SymlinkBlob::lstat_size() const {
return target().native().size();
}
}
}

View File

@ -0,0 +1,32 @@
#pragma once
#ifndef CRYFS_FSBLOBSTORE_SYMLINKBLOB_H_
#define CRYFS_FSBLOBSTORE_SYMLINKBLOB_H_
#include <boost/filesystem/path.hpp>
#include "FsBlob.h"
namespace cryfs {
namespace fsblobstore {
class SymlinkBlob: public FsBlob {
public:
static cpputils::unique_ref<SymlinkBlob> InitializeSymlink(cpputils::unique_ref<blobstore::Blob> blob,
const boost::filesystem::path &target);
SymlinkBlob(cpputils::unique_ref<blobstore::Blob> blob);
const boost::filesystem::path &target() const;
off_t lstat_size() const override;
private:
boost::filesystem::path _target;
static void _checkMagicNumber(const blobstore::Blob &blob);
static boost::filesystem::path _readTargetFromBlob(const blobstore::Blob &blob);
};
}
}
#endif

View File

@ -1,82 +0,0 @@
#pragma once
#ifndef CRYFS_LIB_IMPL_DIRBLOB_H_
#define CRYFS_LIB_IMPL_DIRBLOB_H_
#include <messmer/blobstore/interface/Blob.h>
#include <messmer/blockstore/utils/Key.h>
#include <messmer/cpp-utils/macros.h>
#include <messmer/fspp/fs_interface/Dir.h>
#include <messmer/cpp-utils/pointer/unique_ref.h>
#include <vector>
namespace cryfs{
class CryDevice;
class DirBlob {
public:
struct Entry {
Entry(fspp::Dir::EntryType type_, const std::string &name_, const blockstore::Key &key_, mode_t mode_, uid_t uid_, gid_t gid_): type(type_), name(name_), key(key_), mode(mode_), uid(uid_), gid(gid_) {
switch(type) {
case fspp::Dir::EntryType::FILE:
mode |= S_IFREG;
break;
case fspp::Dir::EntryType::DIR:
mode |= S_IFDIR;
break;
case fspp::Dir::EntryType::SYMLINK:
mode |= S_IFLNK;
break;
}
ASSERT((S_ISREG(mode) && type == fspp::Dir::EntryType::FILE) || (S_ISDIR(mode) && type == fspp::Dir::EntryType::DIR) || (S_ISLNK(mode) && type == fspp::Dir::EntryType::SYMLINK), "Unknown mode in entry");
}
fspp::Dir::EntryType type;
std::string name;
blockstore::Key key;
mode_t mode;
uid_t uid;
gid_t gid;
};
static cpputils::unique_ref<DirBlob> InitializeEmptyDir(cpputils::unique_ref<blobstore::Blob> blob, CryDevice *device);
DirBlob(cpputils::unique_ref<blobstore::Blob> blob, CryDevice *device);
virtual ~DirBlob();
void AppendChildrenTo(std::vector<fspp::Dir::Entry> *result) const;
const Entry &GetChild(const std::string &name) const;
const Entry &GetChild(const blockstore::Key &key) const;
void AddChildDir(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, gid_t gid);
void AddChildFile(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, gid_t gid);
void AddChildSymlink(const std::string &name, const blockstore::Key &blobKey, uid_t uid, gid_t gid);
void AddChild(const std::string &name, const blockstore::Key &blobKey, fspp::Dir::EntryType type, mode_t mode, uid_t uid, gid_t gid);
void RemoveChild(const blockstore::Key &key);
void flush();
void statChild(const blockstore::Key &key, struct ::stat *result) const;
void chmodChild(const blockstore::Key &key, mode_t mode);
void chownChild(const blockstore::Key &key, uid_t uid, gid_t gid);
private:
unsigned char magicNumber() const;
const char *readAndAddNextChild(const char *pos, std::vector<Entry> *result) const;
bool hasChild(const std::string &name) const;
void _readEntriesFromBlob();
void _writeEntriesToBlob();
std::vector<DirBlob::Entry>::iterator _findChild(const blockstore::Key &key);
CryDevice *_device;
cpputils::unique_ref<blobstore::Blob> _blob;
std::vector<Entry> _entries;
bool _changed;
DISALLOW_COPY_AND_ASSIGN(DirBlob);
};
}
#endif

View File

@ -1,34 +0,0 @@
#pragma once
#ifndef CRYFS_LIB_IMPL_FILEBLOB_H_
#define CRYFS_LIB_IMPL_FILEBLOB_H_
#include <messmer/blobstore/interface/Blob.h>
#include <messmer/cpp-utils/pointer/unique_ref.h>
namespace cryfs {
class FileBlob {
public:
static cpputils::unique_ref<FileBlob> InitializeEmptyFile(cpputils::unique_ref<blobstore::Blob> blob);
FileBlob(cpputils::unique_ref<blobstore::Blob> blob);
virtual ~FileBlob();
ssize_t read(void *target, uint64_t offset, uint64_t count) const;
void write(const void *source, uint64_t offset, uint64_t count);
void flush();
void resize(off_t size);
off_t size() const;
blockstore::Key key() const;
private:
cpputils::unique_ref<blobstore::Blob> _blob;
unsigned char magicNumber() const;
};
}
#endif

View File

@ -1,30 +0,0 @@
#pragma once
#ifndef CRYFS_LIB_IMPL_SYMLINKBLOB_H_
#define CRYFS_LIB_IMPL_SYMLINKBLOB_H_
#include <messmer/blobstore/interface/Blob.h>
#include <boost/filesystem/path.hpp>
#include <messmer/cpp-utils/pointer/unique_ref.h>
namespace cryfs {
class SymlinkBlob {
public:
static cpputils::unique_ref<SymlinkBlob> InitializeSymlink(cpputils::unique_ref<blobstore::Blob> blob, const boost::filesystem::path &target);
SymlinkBlob(cpputils::unique_ref<blobstore::Blob> blob);
SymlinkBlob(const boost::filesystem::path &target);
virtual ~SymlinkBlob();
const boost::filesystem::path &target() const;
private:
boost::filesystem::path _target;
static void _checkMagicNumber(const blobstore::Blob &blob);
static boost::filesystem::path _readTargetFromBlob(const blobstore::Blob &blob);
};
}
#endif