When an integrity violation is detected, any further access to the file system is blocked. This ensures that the user notices the integrity violation.
This commit is contained in:
parent
2284571127
commit
839a511c4d
@ -18,6 +18,7 @@
|
|||||||
#include <cpp-utils/logging/logging.h>
|
#include <cpp-utils/logging/logging.h>
|
||||||
#include "../../../../vendor/googletest/gtest-1.7.0/googletest/include/gtest/gtest_prod.h"
|
#include "../../../../vendor/googletest/gtest-1.7.0/googletest/include/gtest/gtest_prod.h"
|
||||||
#include "IntegrityViolationError.h"
|
#include "IntegrityViolationError.h"
|
||||||
|
#include "VersionCountingBlockStore.h"
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace versioncounting {
|
namespace versioncounting {
|
||||||
@ -26,13 +27,13 @@ namespace versioncounting {
|
|||||||
|
|
||||||
class VersionCountingBlock final: public Block {
|
class VersionCountingBlock final: public Block {
|
||||||
public:
|
public:
|
||||||
static boost::optional<cpputils::unique_ref<VersionCountingBlock>> TryCreateNew(BlockStore *baseBlockStore, const Key &key, cpputils::Data data, KnownBlockVersions *knownBlockVersions);
|
static boost::optional<cpputils::unique_ref<VersionCountingBlock>> TryCreateNew(BlockStore *baseBlockStore, const Key &key, cpputils::Data data, VersionCountingBlockStore *blockStore);
|
||||||
static cpputils::unique_ref<VersionCountingBlock> Load(cpputils::unique_ref<Block> baseBlock, KnownBlockVersions *knownBlockVersions);
|
static cpputils::unique_ref<VersionCountingBlock> Load(cpputils::unique_ref<Block> baseBlock, VersionCountingBlockStore *blockStore);
|
||||||
|
|
||||||
static uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize);
|
static uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize);
|
||||||
|
|
||||||
//TODO Storing key twice (in parent class and in object pointed to). Once would be enough.
|
//TODO Storing key twice (in parent class and in object pointed to). Once would be enough.
|
||||||
VersionCountingBlock(cpputils::unique_ref<Block> baseBlock, cpputils::Data dataWithHeader, KnownBlockVersions *knownBlockVersions);
|
VersionCountingBlock(cpputils::unique_ref<Block> baseBlock, cpputils::Data dataWithHeader, VersionCountingBlockStore *blockStore);
|
||||||
~VersionCountingBlock();
|
~VersionCountingBlock();
|
||||||
|
|
||||||
const void *data() const override;
|
const void *data() const override;
|
||||||
@ -49,7 +50,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KnownBlockVersions *_knownBlockVersions;
|
VersionCountingBlockStore *_blockStore;
|
||||||
cpputils::unique_ref<Block> _baseBlock;
|
cpputils::unique_ref<Block> _baseBlock;
|
||||||
cpputils::Data _dataWithHeader;
|
cpputils::Data _dataWithHeader;
|
||||||
uint64_t _version;
|
uint64_t _version;
|
||||||
@ -58,9 +59,9 @@ private:
|
|||||||
void _storeToBaseBlock();
|
void _storeToBaseBlock();
|
||||||
static cpputils::Data _prependHeaderToData(uint32_t myClientId, uint64_t version, cpputils::Data data);
|
static cpputils::Data _prependHeaderToData(uint32_t myClientId, uint64_t version, cpputils::Data data);
|
||||||
static void _checkFormatHeader(const cpputils::Data &data);
|
static void _checkFormatHeader(const cpputils::Data &data);
|
||||||
static uint64_t _readVersion(const cpputils::Data &data);
|
uint64_t _readVersion();
|
||||||
static uint32_t _readClientId(const cpputils::Data &data);
|
uint32_t _readClientId();
|
||||||
static void _checkVersion(const cpputils::Data &data, const blockstore::Key &key, KnownBlockVersions *knownBlockVersions);
|
void _checkVersion();
|
||||||
|
|
||||||
// This header is prepended to blocks to allow future versions to have compatibility.
|
// This header is prepended to blocks to allow future versions to have compatibility.
|
||||||
static constexpr uint16_t FORMAT_VERSION_HEADER = 0;
|
static constexpr uint16_t FORMAT_VERSION_HEADER = 0;
|
||||||
@ -77,17 +78,17 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline boost::optional<cpputils::unique_ref<VersionCountingBlock>> VersionCountingBlock::TryCreateNew(BlockStore *baseBlockStore, const Key &key, cpputils::Data data, KnownBlockVersions *knownBlockVersions) {
|
inline boost::optional<cpputils::unique_ref<VersionCountingBlock>> VersionCountingBlock::TryCreateNew(BlockStore *baseBlockStore, const Key &key, cpputils::Data data, VersionCountingBlockStore *blockStore) {
|
||||||
uint64_t version = knownBlockVersions->incrementVersion(key, VERSION_ZERO);
|
uint64_t version = blockStore->knownBlockVersions()->incrementVersion(key, VERSION_ZERO);
|
||||||
|
|
||||||
cpputils::Data dataWithHeader = _prependHeaderToData(knownBlockVersions->myClientId(), version, std::move(data));
|
cpputils::Data dataWithHeader = _prependHeaderToData(blockStore->knownBlockVersions()->myClientId(), version, std::move(data));
|
||||||
auto baseBlock = baseBlockStore->tryCreate(key, dataWithHeader.copy()); // TODO Copy necessary?
|
auto baseBlock = baseBlockStore->tryCreate(key, dataWithHeader.copy()); // TODO Copy necessary?
|
||||||
if (baseBlock == boost::none) {
|
if (baseBlock == boost::none) {
|
||||||
//TODO Test this code branch
|
//TODO Test this code branch
|
||||||
return boost::none;
|
return boost::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cpputils::make_unique_ref<VersionCountingBlock>(std::move(*baseBlock), std::move(dataWithHeader), knownBlockVersions);
|
return cpputils::make_unique_ref<VersionCountingBlock>(std::move(*baseBlock), std::move(dataWithHeader), blockStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline cpputils::Data VersionCountingBlock::_prependHeaderToData(uint32_t myClientId, uint64_t version, cpputils::Data data) {
|
inline cpputils::Data VersionCountingBlock::_prependHeaderToData(uint32_t myClientId, uint64_t version, cpputils::Data data) {
|
||||||
@ -100,19 +101,20 @@ inline cpputils::Data VersionCountingBlock::_prependHeaderToData(uint32_t myClie
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline cpputils::unique_ref<VersionCountingBlock> VersionCountingBlock::Load(cpputils::unique_ref<Block> baseBlock, KnownBlockVersions *knownBlockVersions) {
|
inline cpputils::unique_ref<VersionCountingBlock> VersionCountingBlock::Load(cpputils::unique_ref<Block> baseBlock, VersionCountingBlockStore *blockStore) {
|
||||||
cpputils::Data data(baseBlock->size());
|
cpputils::Data data(baseBlock->size());
|
||||||
std::memcpy(data.data(), baseBlock->data(), data.size());
|
std::memcpy(data.data(), baseBlock->data(), data.size());
|
||||||
_checkFormatHeader(data);
|
_checkFormatHeader(data);
|
||||||
_checkVersion(data, baseBlock->key(), knownBlockVersions);
|
auto block = cpputils::make_unique_ref<VersionCountingBlock>(std::move(baseBlock), std::move(data), blockStore);
|
||||||
return cpputils::make_unique_ref<VersionCountingBlock>(std::move(baseBlock), std::move(data), knownBlockVersions);
|
block->_checkVersion();
|
||||||
|
return std::move(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void VersionCountingBlock::_checkVersion(const cpputils::Data &data, const blockstore::Key &key, KnownBlockVersions *knownBlockVersions) {
|
inline void VersionCountingBlock::_checkVersion() {
|
||||||
uint32_t lastClientId = _readClientId(data);
|
uint32_t lastClientId = _readClientId();
|
||||||
uint64_t version = _readVersion(data);
|
uint64_t version = _readVersion();
|
||||||
if(!knownBlockVersions->checkAndUpdateVersion(lastClientId, key, version)) {
|
if(!_blockStore->knownBlockVersions()->checkAndUpdateVersion(lastClientId, key(), version)) {
|
||||||
throw IntegrityViolationError("The block version number is too low. Did an attacker try to roll back the block or to re-introduce a deleted block?");
|
_blockStore->integrityViolationDetected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,24 +124,24 @@ inline void VersionCountingBlock::_checkFormatHeader(const cpputils::Data &data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t VersionCountingBlock::_readClientId(const cpputils::Data &data) {
|
inline uint32_t VersionCountingBlock::_readClientId() {
|
||||||
uint32_t clientId;
|
uint32_t clientId;
|
||||||
std::memcpy(&clientId, data.dataOffset(CLIENTID_HEADER_OFFSET), sizeof(clientId));
|
std::memcpy(&clientId, _dataWithHeader.dataOffset(CLIENTID_HEADER_OFFSET), sizeof(clientId));
|
||||||
return clientId;
|
return clientId;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint64_t VersionCountingBlock::_readVersion(const cpputils::Data &data) {
|
inline uint64_t VersionCountingBlock::_readVersion() {
|
||||||
uint64_t version;
|
uint64_t version;
|
||||||
std::memcpy(&version, data.dataOffset(VERSION_HEADER_OFFSET), sizeof(version));
|
std::memcpy(&version, _dataWithHeader.dataOffset(VERSION_HEADER_OFFSET), sizeof(version));
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline VersionCountingBlock::VersionCountingBlock(cpputils::unique_ref<Block> baseBlock, cpputils::Data dataWithHeader, KnownBlockVersions *knownBlockVersions)
|
inline VersionCountingBlock::VersionCountingBlock(cpputils::unique_ref<Block> baseBlock, cpputils::Data dataWithHeader, VersionCountingBlockStore *blockStore)
|
||||||
:Block(baseBlock->key()),
|
:Block(baseBlock->key()),
|
||||||
_knownBlockVersions(knownBlockVersions),
|
_blockStore(blockStore),
|
||||||
_baseBlock(std::move(baseBlock)),
|
_baseBlock(std::move(baseBlock)),
|
||||||
_dataWithHeader(std::move(dataWithHeader)),
|
_dataWithHeader(std::move(dataWithHeader)),
|
||||||
_version(_readVersion(_dataWithHeader)),
|
_version(_readVersion()),
|
||||||
_dataChanged(false),
|
_dataChanged(false),
|
||||||
_mutex() {
|
_mutex() {
|
||||||
if (_version == std::numeric_limits<uint64_t>::max()) {
|
if (_version == std::numeric_limits<uint64_t>::max()) {
|
||||||
@ -179,8 +181,8 @@ inline void VersionCountingBlock::resize(size_t newSize) {
|
|||||||
|
|
||||||
inline void VersionCountingBlock::_storeToBaseBlock() {
|
inline void VersionCountingBlock::_storeToBaseBlock() {
|
||||||
if (_dataChanged) {
|
if (_dataChanged) {
|
||||||
_version = _knownBlockVersions->incrementVersion(key(), _version);
|
_version = _blockStore->knownBlockVersions()->incrementVersion(key(), _version);
|
||||||
uint32_t myClientId = _knownBlockVersions->myClientId();
|
uint32_t myClientId = _blockStore->knownBlockVersions()->myClientId();
|
||||||
std::memcpy(_dataWithHeader.dataOffset(CLIENTID_HEADER_OFFSET), &myClientId, sizeof(myClientId));
|
std::memcpy(_dataWithHeader.dataOffset(CLIENTID_HEADER_OFFSET), &myClientId, sizeof(myClientId));
|
||||||
std::memcpy(_dataWithHeader.dataOffset(VERSION_HEADER_OFFSET), &_version, sizeof(_version));
|
std::memcpy(_dataWithHeader.dataOffset(VERSION_HEADER_OFFSET), &_version, sizeof(_version));
|
||||||
if (_baseBlock->size() != _dataWithHeader.size()) {
|
if (_baseBlock->size() != _dataWithHeader.size()) {
|
||||||
|
@ -1,14 +1,82 @@
|
|||||||
#include "VersionCountingBlockStore.h"
|
#include "VersionCountingBlockStore.h"
|
||||||
|
#include "VersionCountingBlock.h"
|
||||||
|
|
||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
using cpputils::make_unique_ref;
|
using cpputils::make_unique_ref;
|
||||||
using cpputils::Data;
|
using cpputils::Data;
|
||||||
using boost::none;
|
using boost::none;
|
||||||
|
using boost::optional;
|
||||||
namespace bf = boost::filesystem;
|
namespace bf = boost::filesystem;
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
namespace versioncounting {
|
namespace versioncounting {
|
||||||
|
|
||||||
|
VersionCountingBlockStore::VersionCountingBlockStore(unique_ref<BlockStore> baseBlockStore, const bf::path &integrityFilePath, bool missingBlockIsIntegrityViolation)
|
||||||
|
: _baseBlockStore(std::move(baseBlockStore)), _knownBlockVersions(integrityFilePath), _missingBlockIsIntegrityViolation(missingBlockIsIntegrityViolation), _integrityViolationDetected(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Key VersionCountingBlockStore::createKey() {
|
||||||
|
return _baseBlockStore->createKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<unique_ref<Block>> VersionCountingBlockStore::tryCreate(const Key &key, cpputils::Data data) {
|
||||||
|
_checkNoPastIntegrityViolations();
|
||||||
|
//TODO Easier implementation? This is only so complicated because of the cast VersionCountingBlock -> Block
|
||||||
|
auto result = VersionCountingBlock::TryCreateNew(_baseBlockStore.get(), key, std::move(data), this);
|
||||||
|
if (result == boost::none) {
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
return unique_ref<Block>(std::move(*result));
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<unique_ref<Block>> VersionCountingBlockStore::load(const Key &key) {
|
||||||
|
_checkNoPastIntegrityViolations();
|
||||||
|
auto block = _baseBlockStore->load(key);
|
||||||
|
if (block == boost::none) {
|
||||||
|
if (_missingBlockIsIntegrityViolation && _knownBlockVersions.blockShouldExist(key)) {
|
||||||
|
integrityViolationDetected();
|
||||||
|
}
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
return optional<unique_ref<Block>>(VersionCountingBlock::Load(std::move(*block), this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void VersionCountingBlockStore::_checkNoPastIntegrityViolations() {
|
||||||
|
if (_integrityViolationDetected) {
|
||||||
|
throw std::runtime_error("There was an integrity violation detected. Preventing any further access to the file system.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VersionCountingBlockStore::integrityViolationDetected() {
|
||||||
|
_integrityViolationDetected = true;
|
||||||
|
throw IntegrityViolationError("A block that should exist wasn't found. Did an attacker delete it?");
|
||||||
|
}
|
||||||
|
|
||||||
|
void VersionCountingBlockStore::remove(unique_ref<Block> block) {
|
||||||
|
Key key = block->key();
|
||||||
|
auto versionCountingBlock = cpputils::dynamic_pointer_move<VersionCountingBlock>(block);
|
||||||
|
ASSERT(versionCountingBlock != boost::none, "Block is not an VersionCountingBlock");
|
||||||
|
_knownBlockVersions.markBlockAsDeleted(key);
|
||||||
|
auto baseBlock = (*versionCountingBlock)->releaseBlock();
|
||||||
|
_baseBlockStore->remove(std::move(baseBlock));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t VersionCountingBlockStore::numBlocks() const {
|
||||||
|
return _baseBlockStore->numBlocks();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t VersionCountingBlockStore::estimateNumFreeBytes() const {
|
||||||
|
return _baseBlockStore->estimateNumFreeBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t VersionCountingBlockStore::blockSizeFromPhysicalBlockSize(uint64_t blockSize) const {
|
||||||
|
return VersionCountingBlock::blockSizeFromPhysicalBlockSize(_baseBlockStore->blockSizeFromPhysicalBlockSize(blockSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
void VersionCountingBlockStore::forEachBlock(std::function<void (const Key &)> callback) const {
|
||||||
|
return _baseBlockStore->forEachBlock(callback);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef CRYFS_NO_COMPATIBILITY
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
void VersionCountingBlockStore::migrateFromBlockstoreWithoutVersionNumbers(BlockStore *baseBlockStore, const bf::path &integrityFilePath) {
|
void VersionCountingBlockStore::migrateFromBlockstoreWithoutVersionNumbers(BlockStore *baseBlockStore, const bf::path &integrityFilePath) {
|
||||||
std::cout << "Migrating file system for integrity features. This can take a while..." << std::flush;
|
std::cout << "Migrating file system for integrity features. This can take a while..." << std::flush;
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include "../../interface/BlockStore.h"
|
#include "../../interface/BlockStore.h"
|
||||||
#include <cpp-utils/macros.h>
|
#include <cpp-utils/macros.h>
|
||||||
#include <cpp-utils/pointer/cast.h>
|
#include <cpp-utils/pointer/cast.h>
|
||||||
#include "VersionCountingBlock.h"
|
|
||||||
#include "KnownBlockVersions.h"
|
#include "KnownBlockVersions.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@ -25,6 +24,9 @@ public:
|
|||||||
uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
|
uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
|
||||||
void forEachBlock(std::function<void (const Key &)> callback) const override;
|
void forEachBlock(std::function<void (const Key &)> callback) const override;
|
||||||
|
|
||||||
|
void integrityViolationDetected();
|
||||||
|
KnownBlockVersions *knownBlockVersions();
|
||||||
|
|
||||||
#ifndef CRYFS_NO_COMPATIBILITY
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
static void migrateFromBlockstoreWithoutVersionNumbers(BlockStore *baseBlockStore, const boost::filesystem::path &integrityFilePath);
|
static void migrateFromBlockstoreWithoutVersionNumbers(BlockStore *baseBlockStore, const boost::filesystem::path &integrityFilePath);
|
||||||
#endif
|
#endif
|
||||||
@ -33,62 +35,15 @@ private:
|
|||||||
cpputils::unique_ref<BlockStore> _baseBlockStore;
|
cpputils::unique_ref<BlockStore> _baseBlockStore;
|
||||||
KnownBlockVersions _knownBlockVersions;
|
KnownBlockVersions _knownBlockVersions;
|
||||||
const bool _missingBlockIsIntegrityViolation;
|
const bool _missingBlockIsIntegrityViolation;
|
||||||
|
bool _integrityViolationDetected;
|
||||||
|
|
||||||
|
void _checkNoPastIntegrityViolations();
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(VersionCountingBlockStore);
|
DISALLOW_COPY_AND_ASSIGN(VersionCountingBlockStore);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline KnownBlockVersions *VersionCountingBlockStore::knownBlockVersions() {
|
||||||
inline VersionCountingBlockStore::VersionCountingBlockStore(cpputils::unique_ref<BlockStore> baseBlockStore, const boost::filesystem::path &integrityFilePath, bool missingBlockIsIntegrityViolation)
|
return &_knownBlockVersions;
|
||||||
: _baseBlockStore(std::move(baseBlockStore)), _knownBlockVersions(integrityFilePath), _missingBlockIsIntegrityViolation(missingBlockIsIntegrityViolation) {
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Key VersionCountingBlockStore::createKey() {
|
|
||||||
return _baseBlockStore->createKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline boost::optional<cpputils::unique_ref<Block>> VersionCountingBlockStore::tryCreate(const Key &key, cpputils::Data data) {
|
|
||||||
//TODO Easier implementation? This is only so complicated because of the cast VersionCountingBlock -> Block
|
|
||||||
auto result = VersionCountingBlock::TryCreateNew(_baseBlockStore.get(), key, std::move(data), &_knownBlockVersions);
|
|
||||||
if (result == boost::none) {
|
|
||||||
return boost::none;
|
|
||||||
}
|
|
||||||
return cpputils::unique_ref<Block>(std::move(*result));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline boost::optional<cpputils::unique_ref<Block>> VersionCountingBlockStore::load(const Key &key) {
|
|
||||||
auto block = _baseBlockStore->load(key);
|
|
||||||
if (block == boost::none) {
|
|
||||||
if (_missingBlockIsIntegrityViolation && _knownBlockVersions.blockShouldExist(key)) {
|
|
||||||
throw IntegrityViolationError("A block that should exist wasn't found. Did an attacker delete it?");
|
|
||||||
}
|
|
||||||
return boost::none;
|
|
||||||
}
|
|
||||||
return boost::optional<cpputils::unique_ref<Block>>(VersionCountingBlock::Load(std::move(*block), &_knownBlockVersions));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void VersionCountingBlockStore::remove(cpputils::unique_ref<Block> block) {
|
|
||||||
Key key = block->key();
|
|
||||||
auto versionCountingBlock = cpputils::dynamic_pointer_move<VersionCountingBlock>(block);
|
|
||||||
ASSERT(versionCountingBlock != boost::none, "Block is not an VersionCountingBlock");
|
|
||||||
_knownBlockVersions.markBlockAsDeleted(key);
|
|
||||||
auto baseBlock = (*versionCountingBlock)->releaseBlock();
|
|
||||||
_baseBlockStore->remove(std::move(baseBlock));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint64_t VersionCountingBlockStore::numBlocks() const {
|
|
||||||
return _baseBlockStore->numBlocks();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint64_t VersionCountingBlockStore::estimateNumFreeBytes() const {
|
|
||||||
return _baseBlockStore->estimateNumFreeBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint64_t VersionCountingBlockStore::blockSizeFromPhysicalBlockSize(uint64_t blockSize) const {
|
|
||||||
return VersionCountingBlock::blockSizeFromPhysicalBlockSize(_baseBlockStore->blockSizeFromPhysicalBlockSize(blockSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void VersionCountingBlockStore::forEachBlock(std::function<void (const Key &)> callback) const {
|
|
||||||
return _baseBlockStore->forEachBlock(callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include <blobstore/implementations/onblocks/BlobStoreOnBlocks.h>
|
#include <blobstore/implementations/onblocks/BlobStoreOnBlocks.h>
|
||||||
#include <blobstore/implementations/onblocks/BlobOnBlocks.h>
|
#include <blobstore/implementations/onblocks/BlobOnBlocks.h>
|
||||||
#include <blockstore/implementations/encrypted/EncryptedBlockStore.h>
|
#include <blockstore/implementations/encrypted/EncryptedBlockStore.h>
|
||||||
#include <blockstore/implementations/versioncounting/VersionCountingBlockStore.h>
|
#include <blockstore/implementations/versioncounting/VersionCountingBlock.h>
|
||||||
#include "parallelaccessfsblobstore/ParallelAccessFsBlobStore.h"
|
#include "parallelaccessfsblobstore/ParallelAccessFsBlobStore.h"
|
||||||
#include "cachingfsblobstore/CachingFsBlobStore.h"
|
#include "cachingfsblobstore/CachingFsBlobStore.h"
|
||||||
#include "../config/CryCipher.h"
|
#include "../config/CryCipher.h"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include "blockstore/implementations/versioncounting/VersionCountingBlockStore.h"
|
#include "blockstore/implementations/versioncounting/VersionCountingBlockStore.h"
|
||||||
|
#include "blockstore/implementations/versioncounting/VersionCountingBlock.h"
|
||||||
#include "blockstore/implementations/testfake/FakeBlockStore.h"
|
#include "blockstore/implementations/testfake/FakeBlockStore.h"
|
||||||
#include "blockstore/utils/BlockStoreUtils.h"
|
#include "blockstore/utils/BlockStoreUtils.h"
|
||||||
#include <cpp-utils/data/DataFixture.h>
|
#include <cpp-utils/data/DataFixture.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user