Each blob stores a parent pointer (i.e. the ID of the directory that contains this blob). This stores the directory structure in a conflict-proof way and can be used to resolve such conflicts.

This commit is contained in:
Sebastian Messmer 2016-06-27 18:22:13 -07:00
parent edc542e3c5
commit 397de9372f
24 changed files with 193 additions and 70 deletions

View File

@ -96,7 +96,7 @@ unique_ref<BlockStore> CryDevice::CreateVersionCountingEncryptedBlockStore(uniqu
}
Key CryDevice::CreateRootBlobAndReturnKey() {
auto rootBlob = _fsBlobStore->createDirBlob();
auto rootBlob = _fsBlobStore->createDirBlob(blockstore::Key::Null());
rootBlob->flush(); // Don't cache, but directly write the root blob (this causes it to fail early if the base directory is not accessible)
return rootBlob->key();
}
@ -150,6 +150,7 @@ CryDevice::BlobWithParent CryDevice::LoadBlobWithParent(const bf::path &path) {
throw FuseErrnoException(EIO);
}
unique_ref<FsBlobRef> currentBlob = std::move(*currentBlobOpt);
ASSERT(currentBlob->parentPointer() == Key::Null(), "Root Blob should have a nullptr as parent");
for (const bf::path &component : path.relative_path()) {
auto currentDir = dynamic_pointer_move<DirBlobRef>(currentBlob);
@ -168,6 +169,7 @@ CryDevice::BlobWithParent CryDevice::LoadBlobWithParent(const bf::path &path) {
}
parentBlob = std::move(*currentDir);
currentBlob = std::move(*nextBlob);
ASSERT(currentBlob->parentPointer() == (*parentBlob)->key(), "Blob has wrong parent pointer");
}
return BlobWithParent{std::move(currentBlob), std::move(parentBlob)};
@ -194,16 +196,16 @@ void CryDevice::statfs(const bf::path &path, struct statvfs *fsstat) {
//f_frsize, f_favail, f_fsid and f_flag are ignored in fuse, see http://fuse.sourcearchive.com/documentation/2.7.0/structfuse__operations_4e765e29122e7b6b533dc99849a52655.html#4e765e29122e7b6b533dc99849a52655
}
unique_ref<FileBlobRef> CryDevice::CreateFileBlob() {
return _fsBlobStore->createFileBlob();
unique_ref<FileBlobRef> CryDevice::CreateFileBlob(const blockstore::Key &parent) {
return _fsBlobStore->createFileBlob(parent);
}
unique_ref<DirBlobRef> CryDevice::CreateDirBlob() {
return _fsBlobStore->createDirBlob();
unique_ref<DirBlobRef> CryDevice::CreateDirBlob(const blockstore::Key &parent) {
return _fsBlobStore->createDirBlob(parent);
}
unique_ref<SymlinkBlobRef> CryDevice::CreateSymlinkBlob(const bf::path &target) {
return _fsBlobStore->createSymlinkBlob(target);
unique_ref<SymlinkBlobRef> CryDevice::CreateSymlinkBlob(const bf::path &target, const blockstore::Key &parent) {
return _fsBlobStore->createSymlinkBlob(target, parent);
}
unique_ref<FsBlobRef> CryDevice::LoadBlob(const blockstore::Key &key) {

View File

@ -21,9 +21,9 @@ public:
void statfs(const boost::filesystem::path &path, struct ::statvfs *fsstat) override;
cpputils::unique_ref<parallelaccessfsblobstore::FileBlobRef> CreateFileBlob();
cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> CreateDirBlob();
cpputils::unique_ref<parallelaccessfsblobstore::SymlinkBlobRef> CreateSymlinkBlob(const boost::filesystem::path &target);
cpputils::unique_ref<parallelaccessfsblobstore::FileBlobRef> CreateFileBlob(const blockstore::Key &parent);
cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> CreateDirBlob(const blockstore::Key &parent);
cpputils::unique_ref<parallelaccessfsblobstore::SymlinkBlobRef> CreateSymlinkBlob(const boost::filesystem::path &target, const blockstore::Key &parent);
cpputils::unique_ref<parallelaccessfsblobstore::FsBlobRef> LoadBlob(const blockstore::Key &key);
struct DirBlobWithParent {
cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> blob;

View File

@ -43,7 +43,7 @@ unique_ref<fspp::OpenFile> CryDir::createAndOpenFile(const string &name, mode_t
//TODO Instead of doing nothing when we're the root directory, handle timestamps in the root dir correctly (and delete isRootDir() function)
parent()->updateModificationTimestampForChild(key());
}
auto child = device()->CreateFileBlob();
auto child = device()->CreateFileBlob(key());
auto now = cpputils::time::now();
auto dirBlob = LoadBlob();
dirBlob->AddChildFile(name, child->key(), mode, uid, gid, now, now);
@ -57,7 +57,7 @@ void CryDir::createDir(const string &name, mode_t mode, uid_t uid, gid_t gid) {
parent()->updateModificationTimestampForChild(key());
}
auto blob = LoadBlob();
auto child = device()->CreateDirBlob();
auto child = device()->CreateDirBlob(key());
auto now = cpputils::time::now();
blob->AddChildDir(name, child->key(), mode, uid, gid, now, now);
}
@ -95,7 +95,7 @@ void CryDir::createSymlink(const string &name, const bf::path &target, uid_t uid
parent()->updateModificationTimestampForChild(key());
}
auto blob = LoadBlob();
auto child = device()->CreateSymlinkBlob(target);
auto child = device()->CreateSymlinkBlob(target, key());
auto now = cpputils::time::now();
blob->AddChildSymlink(name, child->key(), uid, gid, now, now);
}

View File

@ -100,6 +100,7 @@ void CryNode::rename(const bf::path &to) {
oldEntry.lastAccessTime(), oldEntry.lastModificationTime(), onOverwritten);
(*_parent)->RemoveChild(oldEntry.name());
// targetDir is now the new parent for this node. Adapt to it, so we can call further operations on this node object.
LoadBlob()->setParentPointer(targetDir->key());
_parent = cpputils::to_unique_ptr(std::move(targetDir));
}
}
@ -149,7 +150,9 @@ const CryDevice *CryNode::device() const {
}
unique_ref<FsBlobRef> CryNode::LoadBlob() const {
return _device->LoadBlob(_key);
auto blob = _device->LoadBlob(_key);
ASSERT(_parent == none || blob->parentPointer() == (*_parent)->key(), "Blob has wrong parent pointer.");
return blob;
}
const blockstore::Key &CryNode::key() const {
@ -197,4 +200,13 @@ void CryNode::chown(uid_t uid, gid_t gid) {
(*_parent)->chownChild(_key, uid, gid);
}
bool CryNode::checkParentPointer() {
auto parentPointer = LoadBlob()->parentPointer();
if (_parent == none) {
return parentPointer == Key::Null();
} else {
return parentPointer == (*_parent)->key();
}
}
}

View File

@ -23,6 +23,9 @@ public:
void rename(const boost::filesystem::path &to) override;
void utimens(timespec lastAccessTime, timespec lastModificationTime) override;
// used in test cases
bool checkParentPointer();
protected:
CryNode();

View File

@ -19,9 +19,9 @@ namespace cryfs {
CachingFsBlobStore(cpputils::unique_ref<fsblobstore::FsBlobStore> baseBlobStore);
~CachingFsBlobStore();
cpputils::unique_ref<FileBlobRef> createFileBlob();
cpputils::unique_ref<DirBlobRef> createDirBlob();
cpputils::unique_ref<SymlinkBlobRef> createSymlinkBlob(const boost::filesystem::path &target);
cpputils::unique_ref<FileBlobRef> createFileBlob(const blockstore::Key &parent);
cpputils::unique_ref<DirBlobRef> createDirBlob(const blockstore::Key &parent);
cpputils::unique_ref<SymlinkBlobRef> createSymlinkBlob(const boost::filesystem::path &target, const blockstore::Key &parent);
boost::optional<cpputils::unique_ref<FsBlobRef>> load(const blockstore::Key &key);
void remove(cpputils::unique_ref<FsBlobRef> blob);
uint64_t virtualBlocksizeBytes() const;
@ -50,25 +50,25 @@ namespace cryfs {
inline CachingFsBlobStore::~CachingFsBlobStore() {
}
inline cpputils::unique_ref<FileBlobRef> CachingFsBlobStore::createFileBlob() {
inline cpputils::unique_ref<FileBlobRef> CachingFsBlobStore::createFileBlob(const blockstore::Key &parent) {
// This already creates the file blob in the underlying blobstore.
// We could also cache this operation, but that is more complicated (blockstore::CachingBlockStore does it)
// and probably not worth it here.
return cpputils::make_unique_ref<FileBlobRef>(_baseBlobStore->createFileBlob(), this);
return cpputils::make_unique_ref<FileBlobRef>(_baseBlobStore->createFileBlob(parent), this);
}
inline cpputils::unique_ref<DirBlobRef> CachingFsBlobStore::createDirBlob() {
inline cpputils::unique_ref<DirBlobRef> CachingFsBlobStore::createDirBlob(const blockstore::Key &parent) {
// This already creates the file blob in the underlying blobstore.
// We could also cache this operation, but that is more complicated (blockstore::CachingBlockStore does it)
// and probably not worth it here.
return cpputils::make_unique_ref<DirBlobRef>(_baseBlobStore->createDirBlob(), this);
return cpputils::make_unique_ref<DirBlobRef>(_baseBlobStore->createDirBlob(parent), this);
}
inline cpputils::unique_ref<SymlinkBlobRef> CachingFsBlobStore::createSymlinkBlob(const boost::filesystem::path &target) {
inline cpputils::unique_ref<SymlinkBlobRef> CachingFsBlobStore::createSymlinkBlob(const boost::filesystem::path &target, const blockstore::Key &parent) {
// This already creates the file blob in the underlying blobstore.
// We could also cache this operation, but that is more complicated (blockstore::CachingBlockStore does it)
// and probably not worth it here.
return cpputils::make_unique_ref<SymlinkBlobRef>(_baseBlobStore->createSymlinkBlob(target), this);
return cpputils::make_unique_ref<SymlinkBlobRef>(_baseBlobStore->createSymlinkBlob(target, parent), this);
}
inline void CachingFsBlobStore::remove(cpputils::unique_ref<FsBlobRef> blob) {

View File

@ -15,6 +15,14 @@ public:
virtual const blockstore::Key &key() const = 0;
virtual off_t lstat_size() const = 0;
const blockstore::Key &parentPointer() const {
return _baseBlob->parentPointer();
}
void setParentPointer(const blockstore::Key &parentKey) {
return _baseBlob->setParentPointer(parentKey);
}
cpputils::unique_ref<fsblobstore::FsBlob> releaseBaseBlob() {
return std::move(_baseBlob);
}

View File

@ -45,8 +45,8 @@ void DirBlob::flush() {
baseBlob().flush();
}
unique_ref<DirBlob> DirBlob::InitializeEmptyDir(FsBlobStore *fsBlobStore, unique_ref<Blob> blob, std::function<off_t(const blockstore::Key&)> getLstatSize) {
InitializeBlob(blob.get(), FsBlobView::BlobType::DIR);
unique_ref<DirBlob> DirBlob::InitializeEmptyDir(FsBlobStore *fsBlobStore, unique_ref<Blob> blob, const blockstore::Key &parent, std::function<off_t(const blockstore::Key&)> getLstatSize) {
InitializeBlob(blob.get(), FsBlobView::BlobType::DIR, parent);
return make_unique_ref<DirBlob>(fsBlobStore, std::move(blob), getLstatSize);
}

View File

@ -18,6 +18,7 @@ namespace cryfs {
constexpr static off_t DIR_LSTAT_SIZE = 4096;
static cpputils::unique_ref<DirBlob> InitializeEmptyDir(FsBlobStore *fsBlobStore, cpputils::unique_ref<blobstore::Blob> blob,
const blockstore::Key &parent,
std::function<off_t (const blockstore::Key&)> getLstatSize);
DirBlob(FsBlobStore *fsBlobStore, cpputils::unique_ref<blobstore::Blob> blob, std::function<off_t (const blockstore::Key&)> getLstatSize);

View File

@ -16,8 +16,8 @@ FileBlob::FileBlob(unique_ref<Blob> blob)
ASSERT(baseBlob().blobType() == FsBlobView::BlobType::FILE, "Loaded blob is not a file");
}
unique_ref<FileBlob> FileBlob::InitializeEmptyFile(unique_ref<Blob> blob) {
InitializeBlob(blob.get(), FsBlobView::BlobType::FILE);
unique_ref<FileBlob> FileBlob::InitializeEmptyFile(unique_ref<Blob> blob, const blockstore::Key &parent) {
InitializeBlob(blob.get(), FsBlobView::BlobType::FILE, parent);
return make_unique_ref<FileBlob>(std::move(blob));
}

View File

@ -9,7 +9,7 @@ namespace cryfs {
class FileBlob final: public FsBlob {
public:
static cpputils::unique_ref<FileBlob> InitializeEmptyFile(cpputils::unique_ref<blobstore::Blob> blob);
static cpputils::unique_ref<FileBlob> InitializeEmptyFile(cpputils::unique_ref<blobstore::Blob> blob, const blockstore::Key &parent);
FileBlob(cpputils::unique_ref<blobstore::Blob> blob);

View File

@ -14,6 +14,8 @@ namespace cryfs {
virtual off_t lstat_size() const = 0;
const blockstore::Key &key() const;
const blockstore::Key &parentPointer() const;
void setParentPointer(const blockstore::Key &parentKey);
protected:
FsBlob(cpputils::unique_ref<blobstore::Blob> baseBlob);
@ -21,7 +23,7 @@ namespace cryfs {
FsBlobView &baseBlob();
const FsBlobView &baseBlob() const;
static void InitializeBlob(blobstore::Blob *blob, FsBlobView::BlobType magicNumber);
static void InitializeBlob(blobstore::Blob *blob, FsBlobView::BlobType magicNumber, const blockstore::Key &parent);
friend class FsBlobStore;
virtual cpputils::unique_ref<blobstore::Blob> releaseBaseBlob();
@ -57,13 +59,21 @@ namespace cryfs {
return _baseBlob;
}
inline void FsBlob::InitializeBlob(blobstore::Blob *blob, FsBlobView::BlobType magicNumber) {
FsBlobView::InitializeBlob(blob, magicNumber);
inline void FsBlob::InitializeBlob(blobstore::Blob *blob, FsBlobView::BlobType magicNumber, const blockstore::Key &parent) {
FsBlobView::InitializeBlob(blob, magicNumber, parent);
}
inline cpputils::unique_ref<blobstore::Blob> FsBlob::releaseBaseBlob() {
return _baseBlob.releaseBaseBlob();
}
inline const blockstore::Key &FsBlob::parentPointer() const {
return _baseBlob.parentPointer();
}
inline void FsBlob::setParentPointer(const blockstore::Key &parentKey) {
return _baseBlob.setParentPointer(parentKey);
}
}
}

View File

@ -17,9 +17,9 @@ namespace cryfs {
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);
cpputils::unique_ref<FileBlob> createFileBlob(const blockstore::Key &parent);
cpputils::unique_ref<DirBlob> createDirBlob(const blockstore::Key &parent);
cpputils::unique_ref<SymlinkBlob> createSymlinkBlob(const boost::filesystem::path &target, const blockstore::Key &parent);
boost::optional<cpputils::unique_ref<FsBlob>> load(const blockstore::Key &key);
void remove(cpputils::unique_ref<FsBlob> blob);
uint64_t numBlocks() const;
@ -40,19 +40,19 @@ namespace cryfs {
: _baseBlobStore(std::move(baseBlobStore)) {
}
inline cpputils::unique_ref<FileBlob> FsBlobStore::createFileBlob() {
inline cpputils::unique_ref<FileBlob> FsBlobStore::createFileBlob(const blockstore::Key &parent) {
auto blob = _baseBlobStore->create();
return FileBlob::InitializeEmptyFile(std::move(blob));
return FileBlob::InitializeEmptyFile(std::move(blob), parent);
}
inline cpputils::unique_ref<DirBlob> FsBlobStore::createDirBlob() {
inline cpputils::unique_ref<DirBlob> FsBlobStore::createDirBlob(const blockstore::Key &parent) {
auto blob = _baseBlobStore->create();
return DirBlob::InitializeEmptyDir(this, std::move(blob), _getLstatSize());
return DirBlob::InitializeEmptyDir(this, std::move(blob), parent, _getLstatSize());
}
inline cpputils::unique_ref<SymlinkBlob> FsBlobStore::createSymlinkBlob(const boost::filesystem::path &target) {
inline cpputils::unique_ref<SymlinkBlob> FsBlobStore::createSymlinkBlob(const boost::filesystem::path &target, const blockstore::Key &parent) {
auto blob = _baseBlobStore->create();
return SymlinkBlob::InitializeSymlink(std::move(blob), target);
return SymlinkBlob::InitializeSymlink(std::move(blob), target, parent);
}
inline uint64_t FsBlobStore::numBlocks() const {

View File

@ -2,4 +2,5 @@
namespace cryfs {
constexpr uint16_t FsBlobView::FORMAT_VERSION_HEADER;
constexpr unsigned int FsBlobView::HEADER_SIZE;
}

View File

@ -17,15 +17,18 @@ namespace cryfs {
SYMLINK = 0x02
};
FsBlobView(cpputils::unique_ref<blobstore::Blob> baseBlob): _baseBlob(std::move(baseBlob)) {
FsBlobView(cpputils::unique_ref<blobstore::Blob> baseBlob): _baseBlob(std::move(baseBlob)), _parentPointer(blockstore::Key::Null()) {
_checkHeader(*_baseBlob);
_loadParentPointer();
}
static void InitializeBlob(blobstore::Blob *baseBlob, BlobType blobType) {
static void InitializeBlob(blobstore::Blob *baseBlob, BlobType blobType, const blockstore::Key &parent) {
baseBlob->resize(sizeof(FORMAT_VERSION_HEADER) + 1);
baseBlob->write(&FORMAT_VERSION_HEADER, 0, sizeof(FORMAT_VERSION_HEADER));
uint8_t blobTypeInt = static_cast<uint8_t>(blobType);
baseBlob->write(&blobTypeInt, sizeof(FORMAT_VERSION_HEADER), 1);
baseBlob->write(&blobTypeInt, sizeof(FORMAT_VERSION_HEADER), sizeof(uint8_t));
baseBlob->write(parent.data(), sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t), blockstore::Key::BINARY_LENGTH);
static_assert(HEADER_SIZE == sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t) + blockstore::Key::BINARY_LENGTH, "If this fails, the header is not initialized correctly in this function.");
}
static BlobType blobType(const blobstore::Blob &blob) {
@ -37,36 +40,45 @@ namespace cryfs {
return _blobType(*_baseBlob);
}
const blockstore::Key &parentPointer() const {
return _parentPointer;
}
void setParentPointer(const blockstore::Key &parentKey) {
_parentPointer = parentKey;
_storeParentPointer();
}
const blockstore::Key &key() const override {
return _baseBlob->key();
}
uint64_t size() const override {
return _baseBlob->size() - sizeof(FORMAT_VERSION_HEADER) - 1;
return _baseBlob->size() - HEADER_SIZE;
}
void resize(uint64_t numBytes) override {
return _baseBlob->resize(numBytes + sizeof(FORMAT_VERSION_HEADER) + 1);
return _baseBlob->resize(numBytes + HEADER_SIZE);
}
cpputils::Data readAll() const override {
cpputils::Data data = _baseBlob->readAll();
cpputils::Data dataWithoutHeader(data.size() - sizeof(FORMAT_VERSION_HEADER) - 1);
cpputils::Data dataWithoutHeader(data.size() - HEADER_SIZE);
//Can we avoid this memcpy? Maybe by having Data::subdata() that returns a reference to the same memory region? Should we?
std::memcpy(dataWithoutHeader.data(), data.dataOffset(sizeof(FORMAT_VERSION_HEADER) + 1), dataWithoutHeader.size());
std::memcpy(dataWithoutHeader.data(), data.dataOffset(HEADER_SIZE), dataWithoutHeader.size());
return dataWithoutHeader;
}
void read(void *target, uint64_t offset, uint64_t size) const override {
return _baseBlob->read(target, offset + sizeof(FORMAT_VERSION_HEADER) + 1, size);
return _baseBlob->read(target, offset + HEADER_SIZE, size);
}
uint64_t tryRead(void *target, uint64_t offset, uint64_t size) const override {
return _baseBlob->tryRead(target, offset + sizeof(FORMAT_VERSION_HEADER) + 1, size);
return _baseBlob->tryRead(target, offset + HEADER_SIZE, size);
}
void write(const void *source, uint64_t offset, uint64_t size) override {
return _baseBlob->write(source, offset + sizeof(FORMAT_VERSION_HEADER) + 1, size);
return _baseBlob->write(source, offset + HEADER_SIZE, size);
}
void flush() override {
@ -78,7 +90,8 @@ namespace cryfs {
}
private:
static constexpr uint16_t FORMAT_VERSION_HEADER = 0;
static constexpr uint16_t FORMAT_VERSION_HEADER = 1;
static constexpr unsigned int HEADER_SIZE = sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t) + blockstore::Key::BINARY_LENGTH;
static void _checkHeader(const blobstore::Blob &blob) {
static_assert(sizeof(uint16_t) == sizeof(FORMAT_VERSION_HEADER), "Wrong type used to read format version header");
@ -91,11 +104,21 @@ namespace cryfs {
static BlobType _blobType(const blobstore::Blob &blob) {
uint8_t result;
blob.read(&result, sizeof(FORMAT_VERSION_HEADER), 1);
blob.read(&result, sizeof(FORMAT_VERSION_HEADER), sizeof(uint8_t));
return static_cast<BlobType>(result);
}
void _loadParentPointer() {
_baseBlob->read(_parentPointer.data(), sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t), blockstore::Key::BINARY_LENGTH);
}
void _storeParentPointer() {
_baseBlob->write(_parentPointer.data(), sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t), blockstore::Key::BINARY_LENGTH);
}
cpputils::unique_ref<blobstore::Blob> _baseBlob;
blockstore::Key _parentPointer;
DISALLOW_COPY_AND_ASSIGN(FsBlobView);
};

View File

@ -18,8 +18,8 @@ SymlinkBlob::SymlinkBlob(unique_ref<Blob> blob)
ASSERT(baseBlob().blobType() == FsBlobView::BlobType::SYMLINK, "Loaded blob is not a symlink");
}
unique_ref<SymlinkBlob> SymlinkBlob::InitializeSymlink(unique_ref<Blob> blob, const bf::path &target) {
InitializeBlob(blob.get(), FsBlobView::BlobType::SYMLINK);
unique_ref<SymlinkBlob> SymlinkBlob::InitializeSymlink(unique_ref<Blob> blob, const bf::path &target, const blockstore::Key &parent) {
InitializeBlob(blob.get(), FsBlobView::BlobType::SYMLINK, parent);
FsBlobView symlinkBlobView(std::move(blob));
string targetStr = target.native();
symlinkBlobView.resize(targetStr.size());

View File

@ -11,7 +11,7 @@ namespace cryfs {
class SymlinkBlob final: public FsBlob {
public:
static cpputils::unique_ref<SymlinkBlob> InitializeSymlink(cpputils::unique_ref<blobstore::Blob> blob,
const boost::filesystem::path &target);
const boost::filesystem::path &target, const blockstore::Key &parent);
SymlinkBlob(cpputils::unique_ref<blobstore::Blob> blob);

View File

@ -92,14 +92,22 @@ public:
return _base->AppendChildrenTo(result);
}
const blockstore::Key &key() const {
const blockstore::Key &key() const override {
return _base->key();
}
off_t lstat_size() const {
off_t lstat_size() const override {
return _base->lstat_size();
}
const blockstore::Key &parentPointer() const override {
return _base->parentPointer();
}
void setParentPointer(const blockstore::Key &parentKey) override {
return _base->setParentPointer(parentKey);
}
private:
cachingfsblobstore::DirBlobRef *_base;

View File

@ -32,14 +32,22 @@ public:
return _base->flush();
}
const blockstore::Key &key() const {
const blockstore::Key &key() const override {
return _base->key();
}
off_t lstat_size() const {
off_t lstat_size() const override {
return _base->lstat_size();
}
const blockstore::Key &parentPointer() const override {
return _base->parentPointer();
}
void setParentPointer(const blockstore::Key &parentKey) override {
return _base->setParentPointer(parentKey);
}
private:
cachingfsblobstore::FileBlobRef *_base;

View File

@ -13,6 +13,8 @@ public:
virtual ~FsBlobRef() {}
virtual const blockstore::Key &key() const = 0;
virtual off_t lstat_size() const = 0;
virtual const blockstore::Key &parentPointer() const = 0;
virtual void setParentPointer(const blockstore::Key &parentKey) = 0;
protected:
FsBlobRef() {}

View File

@ -36,8 +36,8 @@ optional<unique_ref<FsBlobRef>> ParallelAccessFsBlobStore::load(const Key &key)
});
}
unique_ref<DirBlobRef> ParallelAccessFsBlobStore::createDirBlob() {
auto blob = _baseBlobStore->createDirBlob();
unique_ref<DirBlobRef> ParallelAccessFsBlobStore::createDirBlob(const blockstore::Key &parent) {
auto blob = _baseBlobStore->createDirBlob(parent);
blob->setLstatSizeGetter(_getLstatSize());
Key key = blob->key();
return _parallelAccessStore.add<DirBlobRef>(key, std::move(blob), [] (cachingfsblobstore::FsBlobRef *resource) {
@ -47,8 +47,8 @@ unique_ref<DirBlobRef> ParallelAccessFsBlobStore::createDirBlob() {
});
}
unique_ref<FileBlobRef> ParallelAccessFsBlobStore::createFileBlob() {
auto blob = _baseBlobStore->createFileBlob();
unique_ref<FileBlobRef> ParallelAccessFsBlobStore::createFileBlob(const blockstore::Key &parent) {
auto blob = _baseBlobStore->createFileBlob(parent);
Key key = blob->key();
return _parallelAccessStore.add<FileBlobRef>(key, std::move(blob), [] (cachingfsblobstore::FsBlobRef *resource) {
auto fileBlob = dynamic_cast<cachingfsblobstore::FileBlobRef*>(resource);
@ -57,8 +57,8 @@ unique_ref<FileBlobRef> ParallelAccessFsBlobStore::createFileBlob() {
});
}
unique_ref<SymlinkBlobRef> ParallelAccessFsBlobStore::createSymlinkBlob(const bf::path &target) {
auto blob = _baseBlobStore->createSymlinkBlob(target);
unique_ref<SymlinkBlobRef> ParallelAccessFsBlobStore::createSymlinkBlob(const bf::path &target, const blockstore::Key &parent) {
auto blob = _baseBlobStore->createSymlinkBlob(target, parent);
Key key = blob->key();
return _parallelAccessStore.add<SymlinkBlobRef>(key, std::move(blob), [] (cachingfsblobstore::FsBlobRef *resource) {
auto symlinkBlob = dynamic_cast<cachingfsblobstore::SymlinkBlobRef*>(resource);

View File

@ -21,9 +21,9 @@ namespace cryfs {
public:
ParallelAccessFsBlobStore(cpputils::unique_ref<cachingfsblobstore::CachingFsBlobStore> baseBlobStore);
cpputils::unique_ref<FileBlobRef> createFileBlob();
cpputils::unique_ref<DirBlobRef> createDirBlob();
cpputils::unique_ref<SymlinkBlobRef> createSymlinkBlob(const boost::filesystem::path &target);
cpputils::unique_ref<FileBlobRef> createFileBlob(const blockstore::Key &parent);
cpputils::unique_ref<DirBlobRef> createDirBlob(const blockstore::Key &parent);
cpputils::unique_ref<SymlinkBlobRef> createSymlinkBlob(const boost::filesystem::path &target, const blockstore::Key &parent);
boost::optional<cpputils::unique_ref<FsBlobRef>> load(const blockstore::Key &key);
void remove(cpputils::unique_ref<FsBlobRef> blob);
uint64_t virtualBlocksizeBytes() const;

View File

@ -16,14 +16,22 @@ public:
return _base->target();
}
const blockstore::Key &key() const {
const blockstore::Key &key() const override {
return _base->key();
}
off_t lstat_size() const {
off_t lstat_size() const override {
return _base->lstat_size();
}
const blockstore::Key &parentPointer() const override {
return _base->parentPointer();
}
void setParentPointer(const blockstore::Key &parentKey) override {
return _base->setParentPointer(parentKey);
}
private:
cachingfsblobstore::SymlinkBlobRef *_base;

View File

@ -23,6 +23,22 @@ public:
auto createdFile = device().Load(path).value();
return dynamic_pointer_move<CryNode>(createdFile).value();
}
unique_ref<CryNode> CreateDir(const bf::path &path) {
auto _parentDir = device().Load(path.parent_path()).value();
auto parentDir = dynamic_pointer_move<CryDir>(_parentDir).value();
parentDir->createDir(path.filename().native(), MODE_PUBLIC, 0, 0);
auto createdDir = device().Load(path).value();
return dynamic_pointer_move<CryNode>(createdDir).value();
}
unique_ref<CryNode> CreateSymlink(const bf::path &path) {
auto _parentDir = device().Load(path.parent_path()).value();
auto parentDir = dynamic_pointer_move<CryDir>(_parentDir).value();
parentDir->createSymlink(path.filename().native(), "/target", 0, 0);
auto createdSymlink = device().Load(path).value();
return dynamic_pointer_move<CryNode>(createdSymlink).value();
}
};
TEST_F(CryNodeTest, Rename_DoesntLeaveBlocksOver) {
@ -41,3 +57,24 @@ TEST_F(CryNodeTest, Rename_Overwrite_DoesntLeaveBlocksOver) {
node->rename("/newexistingname");
EXPECT_EQ(2u, device().numBlocks()); // Only the blocks of one file are left
}
TEST_F(CryNodeTest, Rename_UpdatesParentPointers_File) {
this->CreateDir("/mydir");
auto node = this->CreateFile("/oldname");
node->rename("/mydir/newname");
EXPECT_TRUE(node->checkParentPointer());
}
TEST_F(CryNodeTest, Rename_UpdatesParentPointers_Dir) {
this->CreateDir("/mydir");
auto node = this->CreateDir("/oldname");
node->rename("/mydir/newname");
EXPECT_TRUE(node->checkParentPointer());
}
TEST_F(CryNodeTest, Rename_UpdatesParentPointers_Symlink) {
this->CreateDir("/mydir");
auto node = this->CreateSymlink("/oldname");
node->rename("/mydir/newname");
EXPECT_TRUE(node->checkParentPointer());
}