Implement migration for old filesystems that don't have parent pointers.
This commit is contained in:
parent
bfb397f44e
commit
3425760daf
@ -54,28 +54,36 @@ namespace bf = boost::filesystem;
|
||||
namespace cryfs {
|
||||
|
||||
CryDevice::CryDevice(CryConfigFile configFile, unique_ref<BlockStore> blockStore, uint32_t myClientId)
|
||||
: _fsBlobStore(
|
||||
make_unique_ref<ParallelAccessFsBlobStore>(
|
||||
make_unique_ref<CachingFsBlobStore>(
|
||||
make_unique_ref<FsBlobStore>(
|
||||
CreateBlobStore(std::move(blockStore), &configFile, myClientId)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
: _fsBlobStore(CreateFsBlobStore(std::move(blockStore), &configFile, myClientId)),
|
||||
_rootKey(GetOrCreateRootKey(&configFile)),
|
||||
_onFsAction() {
|
||||
}
|
||||
|
||||
unique_ref<parallelaccessfsblobstore::ParallelAccessFsBlobStore> CryDevice::CreateFsBlobStore(unique_ref<BlockStore> blockStore, CryConfigFile *configFile, uint32_t myClientId) {
|
||||
auto blobStore = CreateBlobStore(std::move(blockStore), configFile, myClientId);
|
||||
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
auto fsBlobStore = FsBlobStore::migrateIfNeeded(std::move(blobStore), Key::FromString(configFile->config()->RootBlob()));
|
||||
#else
|
||||
auto fsBlobStore = make_unique_ref<FsBlobStore>(std::move(blobStore));
|
||||
#endif
|
||||
|
||||
return make_unique_ref<ParallelAccessFsBlobStore>(
|
||||
make_unique_ref<CachingFsBlobStore>(
|
||||
std::move(fsBlobStore)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
unique_ref<blobstore::BlobStore> CryDevice::CreateBlobStore(unique_ref<BlockStore> blockStore, CryConfigFile *configFile, uint32_t myClientId) {
|
||||
auto versionCountingEncryptedBlockStore = CreateVersionCountingEncryptedBlockStore(std::move(blockStore), configFile, myClientId);
|
||||
// Create versionCountingEncryptedBlockStore not in the same line as BlobStoreOnBlocks, because it can modify BlocksizeBytes
|
||||
// in the configFile and therefore has to be run before the second parameter to the BlobStoreOnBlocks parameter is evaluated.
|
||||
return make_unique_ref<BlobStoreOnBlocks>(
|
||||
make_unique_ref<CachingBlockStore>(
|
||||
std::move(versionCountingEncryptedBlockStore)
|
||||
),
|
||||
configFile->config()->BlocksizeBytes());
|
||||
make_unique_ref<CachingBlockStore>(
|
||||
std::move(versionCountingEncryptedBlockStore)
|
||||
),
|
||||
configFile->config()->BlocksizeBytes());
|
||||
}
|
||||
|
||||
unique_ref<BlockStore> CryDevice::CreateVersionCountingEncryptedBlockStore(unique_ref<BlockStore> blockStore, CryConfigFile *configFile, uint32_t myClientId) {
|
||||
|
@ -49,6 +49,7 @@ private:
|
||||
|
||||
blockstore::Key GetOrCreateRootKey(CryConfigFile *config);
|
||||
blockstore::Key CreateRootBlobAndReturnKey();
|
||||
static cpputils::unique_ref<parallelaccessfsblobstore::ParallelAccessFsBlobStore> CreateFsBlobStore(cpputils::unique_ref<blockstore::BlockStore> blockStore, CryConfigFile *configFile, uint32_t myClientId);
|
||||
static cpputils::unique_ref<blobstore::BlobStore> CreateBlobStore(cpputils::unique_ref<blockstore::BlockStore> blockStore, CryConfigFile *configFile, uint32_t myClientId);
|
||||
static cpputils::unique_ref<blockstore::BlockStore> CreateVersionCountingEncryptedBlockStore(cpputils::unique_ref<blockstore::BlockStore> blockStore, CryConfigFile *configFile, uint32_t myClientId);
|
||||
static cpputils::unique_ref<blockstore::BlockStore> CreateEncryptedBlockStore(const CryConfig &config, cpputils::unique_ref<blockstore::BlockStore> baseBlockStore);
|
||||
|
@ -10,6 +10,7 @@ using blobstore::BlobStore;
|
||||
using blockstore::Key;
|
||||
using boost::none;
|
||||
using std::function;
|
||||
using std::vector;
|
||||
|
||||
namespace cryfs {
|
||||
namespace fsblobstore {
|
||||
@ -31,5 +32,38 @@ boost::optional<unique_ref<FsBlob>> FsBlobStore::load(const blockstore::Key &key
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
unique_ref<FsBlobStore> FsBlobStore::migrateIfNeeded(unique_ref<BlobStore> blobStore, const blockstore::Key &rootKey) {
|
||||
auto rootBlob = blobStore->load(rootKey);
|
||||
ASSERT(rootBlob != none, "Could not load root blob");
|
||||
uint16_t format = FsBlobView::getFormatVersionHeader(**rootBlob);
|
||||
|
||||
auto fsBlobStore = make_unique_ref<FsBlobStore>(std::move(blobStore));
|
||||
if (format == 0) {
|
||||
// migration needed
|
||||
std::cout << "Migrating file system for conflict resolution features. Please don't interrupt this process. This can take a while..." << std::flush;
|
||||
fsBlobStore->_migrate(std::move(*rootBlob), blockstore::Key::Null());
|
||||
std::cout << "done" << std::endl;
|
||||
}
|
||||
return fsBlobStore;
|
||||
}
|
||||
|
||||
void FsBlobStore::_migrate(unique_ref<blobstore::Blob> node, const blockstore::Key &parentKey) {
|
||||
FsBlobView::migrate(node.get(), parentKey);
|
||||
if (FsBlobView::blobType(*node) == FsBlobView::BlobType::DIR) {
|
||||
DirBlob dir(this, std::move(node), _getLstatSize());
|
||||
vector<fspp::Dir::Entry> children;
|
||||
dir.AppendChildrenTo(&children);
|
||||
for (const auto &child : children) {
|
||||
auto childEntry = dir.GetChild(child.name);
|
||||
ASSERT(childEntry != none, "Couldn't load child, although it was returned as a child in the lsit.");
|
||||
auto childBlob = _baseBlobStore->load(childEntry->key());
|
||||
ASSERT(childBlob != none, "Couldn't load child blob");
|
||||
_migrate(std::move(*childBlob), dir.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -27,8 +27,16 @@ namespace cryfs {
|
||||
|
||||
uint64_t virtualBlocksizeBytes() const;
|
||||
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
static cpputils::unique_ref<FsBlobStore> migrateIfNeeded(cpputils::unique_ref<blobstore::BlobStore> blobStore, const blockstore::Key &rootKey);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
void _migrate(cpputils::unique_ref<blobstore::Blob> node, const blockstore::Key &parentKey);
|
||||
#endif
|
||||
|
||||
std::function<off_t(const blockstore::Key &)> _getLstatSize();
|
||||
|
||||
cpputils::unique_ref<blobstore::BlobStore> _baseBlobStore;
|
||||
|
@ -1,6 +1,24 @@
|
||||
#include "FsBlobView.h"
|
||||
|
||||
using cpputils::Data;
|
||||
|
||||
namespace cryfs {
|
||||
constexpr uint16_t FsBlobView::FORMAT_VERSION_HEADER;
|
||||
constexpr unsigned int FsBlobView::HEADER_SIZE;
|
||||
}
|
||||
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
void FsBlobView::migrate(blobstore::Blob *blob, const blockstore::Key &parentKey) {
|
||||
constexpr unsigned int OLD_HEADER_SIZE = sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t);
|
||||
|
||||
ASSERT(FsBlobView::getFormatVersionHeader(*blob) == 0, "Block already migrated");
|
||||
// Resize blob and move data back
|
||||
cpputils::Data data = blob->readAll();
|
||||
blob->resize(blob->size() + blockstore::Key::BINARY_LENGTH);
|
||||
blob->write(data.dataOffset(OLD_HEADER_SIZE), HEADER_SIZE, data.size() - OLD_HEADER_SIZE);
|
||||
// Write parent pointer
|
||||
blob->write(parentKey.data(), sizeof(FORMAT_VERSION_HEADER) + sizeof(uint8_t), blockstore::Key::BINARY_LENGTH);
|
||||
// Update format version number
|
||||
blob->write(&FORMAT_VERSION_HEADER, 0, sizeof(FORMAT_VERSION_HEADER));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -89,14 +89,23 @@ namespace cryfs {
|
||||
return std::move(_baseBlob);
|
||||
}
|
||||
|
||||
static uint16_t getFormatVersionHeader(const blobstore::Blob &blob) {
|
||||
static_assert(sizeof(uint16_t) == sizeof(FORMAT_VERSION_HEADER), "Wrong type used to read format version header");
|
||||
uint16_t actualFormatVersion;
|
||||
blob.read(&actualFormatVersion, 0, sizeof(FORMAT_VERSION_HEADER));
|
||||
return actualFormatVersion;
|
||||
}
|
||||
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
static void migrate(blobstore::Blob *blob, const blockstore::Key &parentKey);
|
||||
#endif
|
||||
|
||||
private:
|
||||
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");
|
||||
uint16_t actualFormatVersion;
|
||||
blob.read(&actualFormatVersion, 0, sizeof(FORMAT_VERSION_HEADER));
|
||||
uint16_t actualFormatVersion = getFormatVersionHeader(blob);
|
||||
if (FORMAT_VERSION_HEADER != actualFormatVersion) {
|
||||
throw std::runtime_error("This file system entity has the wrong format. Was it created with a newer version of CryFS?");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user