Only migrate file system if storage format changed
This commit is contained in:
parent
d74992cc0d
commit
a9556425dc
@ -20,16 +20,18 @@ using cpputils::Random;
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
constexpr const char* CryConfig::FilesystemFormatVersion;
|
||||
|
||||
CryConfig::CryConfig()
|
||||
: _rootBlob(""), _encKey(""), _cipher(""), _version(""), _createdWithVersion(""), _blocksizeBytes(0), _filesystemId(FilesystemID::Null()) {
|
||||
: _rootBlob(""), _encKey(""), _cipher(""), _version(""), _createdWithVersion(""), _lastOpenedWithVersion(""), _blocksizeBytes(0), _filesystemId(FilesystemID::Null()) {
|
||||
}
|
||||
|
||||
CryConfig::CryConfig(CryConfig &&rhs)
|
||||
: _rootBlob(std::move(rhs._rootBlob)), _encKey(std::move(rhs._encKey)), _cipher(std::move(rhs._cipher)), _version(std::move(rhs._version)), _createdWithVersion(std::move(rhs._createdWithVersion)), _blocksizeBytes(rhs._blocksizeBytes), _filesystemId(std::move(rhs._filesystemId)) {
|
||||
: _rootBlob(std::move(rhs._rootBlob)), _encKey(std::move(rhs._encKey)), _cipher(std::move(rhs._cipher)), _version(std::move(rhs._version)), _createdWithVersion(std::move(rhs._createdWithVersion)), _lastOpenedWithVersion(std::move(rhs._lastOpenedWithVersion)), _blocksizeBytes(rhs._blocksizeBytes), _filesystemId(std::move(rhs._filesystemId)) {
|
||||
}
|
||||
|
||||
CryConfig::CryConfig(const CryConfig &rhs)
|
||||
: _rootBlob(rhs._rootBlob), _encKey(rhs._encKey), _cipher(rhs._cipher), _version(rhs._version), _createdWithVersion(rhs._createdWithVersion), _blocksizeBytes(rhs._blocksizeBytes), _filesystemId(rhs._filesystemId) {
|
||||
: _rootBlob(rhs._rootBlob), _encKey(rhs._encKey), _cipher(rhs._cipher), _version(rhs._version), _createdWithVersion(rhs._createdWithVersion), _lastOpenedWithVersion(rhs._lastOpenedWithVersion), _blocksizeBytes(rhs._blocksizeBytes), _filesystemId(rhs._filesystemId) {
|
||||
}
|
||||
|
||||
CryConfig CryConfig::load(const Data &data) {
|
||||
@ -44,6 +46,7 @@ CryConfig CryConfig::load(const Data &data) {
|
||||
cfg._cipher = pt.get<string>("cryfs.cipher");
|
||||
cfg._version = pt.get<string>("cryfs.version", "0.8"); // CryFS 0.8 didn't specify this field, so if the field doesn't exist, it's 0.8.
|
||||
cfg._createdWithVersion = pt.get<string>("cryfs.createdWithVersion", cfg._version); // In CryFS <= 0.9.2, we didn't have this field, but also didn't update cryfs.version, so we can use this field instead.
|
||||
cfg._lastOpenedWithVersion = pt.get<string>("cryfs.lastOpenedWithVersion", cfg._version); // In CryFS <= 0.9.8, we didn't have this field, but used the cryfs.version field for this purpose.
|
||||
cfg._blocksizeBytes = pt.get<uint64_t>("cryfs.blocksizeBytes", 32832); // CryFS <= 0.9.2 used a 32KB block size which was this physical block size.
|
||||
|
||||
optional<string> filesystemIdOpt = pt.get_optional<string>("cryfs.filesystemId");
|
||||
@ -64,6 +67,7 @@ Data CryConfig::save() const {
|
||||
pt.put<string>("cryfs.cipher", _cipher);
|
||||
pt.put<string>("cryfs.version", _version);
|
||||
pt.put<string>("cryfs.createdWithVersion", _createdWithVersion);
|
||||
pt.put<string>("cryfs.lastOpenedWithVersion", _lastOpenedWithVersion);
|
||||
pt.put<uint64_t>("cryfs.blocksizeBytes", _blocksizeBytes);
|
||||
pt.put<string>("cryfs.filesystemId", _filesystemId.ToString());
|
||||
|
||||
@ -100,6 +104,10 @@ const std::string &CryConfig::Version() const {
|
||||
return _version;
|
||||
}
|
||||
|
||||
const std::string &CryConfig::LastOpenedWithVersion() const {
|
||||
return _lastOpenedWithVersion;
|
||||
}
|
||||
|
||||
void CryConfig::SetVersion(const std::string &value) {
|
||||
_version = value;
|
||||
}
|
||||
@ -112,6 +120,10 @@ void CryConfig::SetCreatedWithVersion(const std::string &value) {
|
||||
_createdWithVersion = value;
|
||||
}
|
||||
|
||||
void CryConfig::SetLastOpenedWithVersion(const std::string &value) {
|
||||
_lastOpenedWithVersion = value;
|
||||
}
|
||||
|
||||
uint64_t CryConfig::BlocksizeBytes() const {
|
||||
return _blocksizeBytes;
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ namespace cryfs {
|
||||
|
||||
class CryConfig final {
|
||||
public:
|
||||
static constexpr const char* FilesystemFormatVersion = "0.9.6";
|
||||
|
||||
//TODO No default constructor, pass in config values instead!
|
||||
CryConfig();
|
||||
CryConfig(CryConfig &&rhs);
|
||||
@ -32,6 +34,9 @@ public:
|
||||
const std::string &CreatedWithVersion() const;
|
||||
void SetCreatedWithVersion(const std::string &value);
|
||||
|
||||
const std::string &LastOpenedWithVersion() const;
|
||||
void SetLastOpenedWithVersion(const std::string &value);
|
||||
|
||||
uint64_t BlocksizeBytes() const;
|
||||
void SetBlocksizeBytes(uint64_t value);
|
||||
|
||||
@ -48,6 +53,7 @@ private:
|
||||
std::string _cipher;
|
||||
std::string _version;
|
||||
std::string _createdWithVersion;
|
||||
std::string _lastOpenedWithVersion;
|
||||
uint64_t _blocksizeBytes;
|
||||
FilesystemID _filesystemId;
|
||||
|
||||
|
@ -22,8 +22,9 @@ namespace cryfs {
|
||||
CryConfig CryConfigCreator::create(const optional<string> &cipherFromCommandLine, const optional<uint32_t> &blocksizeBytesFromCommandLine) {
|
||||
CryConfig config;
|
||||
config.SetCipher(_generateCipher(cipherFromCommandLine));
|
||||
config.SetVersion(gitversion::VersionString());
|
||||
config.SetVersion(CryConfig::FilesystemFormatVersion);
|
||||
config.SetCreatedWithVersion(gitversion::VersionString());
|
||||
config.SetLastOpenedWithVersion(gitversion::VersionString());
|
||||
config.SetBlocksizeBytes(_generateBlocksizeBytes(blocksizeBytesFromCommandLine));
|
||||
config.SetRootBlob(_generateRootBlobKey());
|
||||
config.SetEncryptionKey(_generateEncKey(config.Cipher()));
|
||||
|
@ -41,6 +41,12 @@ optional<CryConfigFile> CryConfigLoader::_loadConfig(const bf::path &filename, b
|
||||
return none;
|
||||
}
|
||||
std::cout << "done" << std::endl;
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
//Since 0.9.7 and 0.9.8 set their own version to cryfs.version instead of the filesystem format version (which is 0.9.6), overwrite it
|
||||
if (config->config()->Version() == "0.9.7" || config->config()->Version() == "0.9.8") {
|
||||
config->config()->SetVersion("0.9.6");
|
||||
}
|
||||
#endif
|
||||
_checkVersion(*config->config(), allowFilesystemUpgrade);
|
||||
#ifndef CRYFS_NO_COMPATIBILITY
|
||||
//Since 0.9.3-alpha set the config value cryfs.blocksizeBytes wrongly to 32768 (but didn't use the value), we have to fix this here.
|
||||
@ -48,8 +54,12 @@ optional<CryConfigFile> CryConfigLoader::_loadConfig(const bf::path &filename, b
|
||||
config->config()->SetBlocksizeBytes(32832);
|
||||
}
|
||||
#endif
|
||||
if (config->config()->Version() != gitversion::VersionString()) {
|
||||
config->config()->SetVersion(gitversion::VersionString());
|
||||
if (config->config()->Version() != CryConfig::FilesystemFormatVersion) {
|
||||
config->config()->SetVersion(CryConfig::FilesystemFormatVersion);
|
||||
config->save();
|
||||
}
|
||||
if (config->config()->LastOpenedWithVersion() != gitversion::VersionString()) {
|
||||
config->config()->SetLastOpenedWithVersion(gitversion::VersionString());
|
||||
config->save();
|
||||
}
|
||||
_checkCipher(*config->config());
|
||||
@ -57,14 +67,14 @@ optional<CryConfigFile> CryConfigLoader::_loadConfig(const bf::path &filename, b
|
||||
}
|
||||
|
||||
void CryConfigLoader::_checkVersion(const CryConfig &config, bool allowFilesystemUpgrade) {
|
||||
if (gitversion::VersionCompare::isOlderThan(gitversion::VersionString(), config.Version())) {
|
||||
if (!_console->askYesNo("This filesystem is for CryFS " + config.Version() + " and should not be opened with older versions. It is strongly recommended to update your CryFS version. However, if you have backed up your base directory and know what you're doing, you can continue trying to load it. Do you want to continue?", false)) {
|
||||
throw CryfsException("This filesystem is for CryFS " + config.Version() + ". Please update your CryFS version.", ErrorCode::TooNewFilesystemFormat);
|
||||
if (gitversion::VersionCompare::isOlderThan(CryConfig::FilesystemFormatVersion, config.Version())) {
|
||||
if (!_console->askYesNo("This filesystem is for CryFS " + config.Version() + " or later and should not be opened with older versions. It is strongly recommended to update your CryFS version. However, if you have backed up your base directory and know what you're doing, you can continue trying to load it. Do you want to continue?", false)) {
|
||||
throw CryfsException("This filesystem is for CryFS " + config.Version() + " or later. Please update your CryFS version.", ErrorCode::TooNewFilesystemFormat);
|
||||
}
|
||||
}
|
||||
if (!allowFilesystemUpgrade && gitversion::VersionCompare::isOlderThan(config.Version(), gitversion::VersionString())) {
|
||||
if (!_console->askYesNo("This filesystem is for CryFS " + config.Version() + ". It can be migrated to CryFS " + gitversion::VersionString() + ", but afterwards couldn't be opened anymore with older versions. Do you want to migrate it?", false)) {
|
||||
throw CryfsException("This filesystem is for CryFS " + config.Version() + ". It has to be migrated.", ErrorCode::TooOldFilesystemFormat);
|
||||
if (!allowFilesystemUpgrade && gitversion::VersionCompare::isOlderThan(config.Version(), CryConfig::FilesystemFormatVersion)) {
|
||||
if (!_console->askYesNo("This filesystem is for CryFS " + config.Version() + " (or a later version with the same storage format). You're running a CryFS version using storage format " + CryConfig::FilesystemFormatVersion + ". It can be migrated, but afterwards couldn't be opened anymore with older versions. Do you want to migrate it?", false)) {
|
||||
throw CryfsException("This filesystem is for CryFS " + config.Version() + " (or a later version with the same storage format). It has to be migrated.", ErrorCode::TooOldFilesystemFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,9 +150,14 @@ TEST_F(CryConfigCreatorTest, SetsCorrectCreatedWithVersion) {
|
||||
EXPECT_EQ(gitversion::VersionString(), config.CreatedWithVersion());
|
||||
}
|
||||
|
||||
TEST_F(CryConfigCreatorTest, SetsCorrectLastOpenedWithVersion) {
|
||||
CryConfig config = noninteractiveCreator.create(none, none);
|
||||
EXPECT_EQ(gitversion::VersionString(), config.CreatedWithVersion());
|
||||
}
|
||||
|
||||
TEST_F(CryConfigCreatorTest, SetsCorrectVersion) {
|
||||
CryConfig config = noninteractiveCreator.create(none, none);
|
||||
EXPECT_EQ(gitversion::VersionString(), config.Version());
|
||||
EXPECT_EQ(CryConfig::FilesystemFormatVersion, config.Version());
|
||||
}
|
||||
|
||||
//TODO Add test cases ensuring that the values entered are correctly taken
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <cpp-utils/data/DataFixture.h>
|
||||
#include <cpp-utils/io/NoninteractiveConsole.h>
|
||||
#include <gitversion/gitversion.h>
|
||||
#include <gitversion/parser.h>
|
||||
#include <gitversion/VersionCompare.h>
|
||||
|
||||
using cpputils::unique_ref;
|
||||
@ -82,6 +83,7 @@ public:
|
||||
void CreateWithVersion(const string &version, const string &password = "mypassword") {
|
||||
auto cfg = loader(password, false).loadOrCreate(file.path(), false).value();
|
||||
cfg.config()->SetVersion(version);
|
||||
cfg.config()->SetLastOpenedWithVersion(version);
|
||||
cfg.config()->SetCreatedWithVersion(version);
|
||||
cfg.save();
|
||||
}
|
||||
@ -93,19 +95,20 @@ public:
|
||||
}
|
||||
|
||||
string olderVersion() {
|
||||
auto versionInfo = gitversion::Parser::parse(CryConfig::FilesystemFormatVersion);
|
||||
string olderVersion;
|
||||
if (std::stol(gitversion::MinorVersion()) > 0) {
|
||||
olderVersion = gitversion::MajorVersion() + "." + std::to_string(std::stol(gitversion::MinorVersion()) - 1);
|
||||
if (std::stol(versionInfo.minorVersion) > 0) {
|
||||
olderVersion = versionInfo.majorVersion + "." + std::to_string(std::stol(versionInfo.minorVersion) - 1);
|
||||
} else {
|
||||
olderVersion = std::to_string(std::stol(gitversion::MajorVersion()) - 1) + "." + gitversion::MinorVersion();
|
||||
olderVersion = std::to_string(std::stol(versionInfo.majorVersion) - 1) + "." + versionInfo.minorVersion;
|
||||
}
|
||||
assert(gitversion::VersionCompare::isOlderThan(olderVersion, gitversion::VersionString()));
|
||||
assert(gitversion::VersionCompare::isOlderThan(olderVersion, CryConfig::FilesystemFormatVersion));
|
||||
return olderVersion;
|
||||
}
|
||||
|
||||
string newerVersion() {
|
||||
string newerVersion = gitversion::MajorVersion()+"."+std::to_string(std::stol(gitversion::MinorVersion())+1);
|
||||
assert(gitversion::VersionCompare::isOlderThan(gitversion::VersionString(), newerVersion));
|
||||
assert(gitversion::VersionCompare::isOlderThan(CryConfig::FilesystemFormatVersion, newerVersion));
|
||||
return newerVersion;
|
||||
}
|
||||
|
||||
@ -198,7 +201,8 @@ TEST_F(CryConfigLoaderTest, Cipher_Create) {
|
||||
TEST_F(CryConfigLoaderTest, Version_Load) {
|
||||
CreateWithVersion("0.9.2");
|
||||
auto loaded = Load().value();
|
||||
EXPECT_EQ(gitversion::VersionString(), loaded.config()->Version());
|
||||
EXPECT_EQ(CryConfig::FilesystemFormatVersion, loaded.config()->Version());
|
||||
EXPECT_EQ(gitversion::VersionString(), loaded.config()->LastOpenedWithVersion());
|
||||
EXPECT_EQ("0.9.2", loaded.config()->CreatedWithVersion());
|
||||
}
|
||||
|
||||
@ -206,13 +210,15 @@ TEST_F(CryConfigLoaderTest, Version_Load_IsStoredAndNotOnlyOverwrittenInMemoryOn
|
||||
CreateWithVersion("0.9.2", "mypassword");
|
||||
Load().value();
|
||||
auto configFile = CryConfigFile::load(file.path(), "mypassword").value();
|
||||
EXPECT_EQ(gitversion::VersionString(), configFile.config()->Version());
|
||||
EXPECT_EQ(CryConfig::FilesystemFormatVersion, configFile.config()->Version());
|
||||
EXPECT_EQ(gitversion::VersionString(), configFile.config()->LastOpenedWithVersion());
|
||||
EXPECT_EQ("0.9.2", configFile.config()->CreatedWithVersion());
|
||||
}
|
||||
|
||||
TEST_F(CryConfigLoaderTest, Version_Create) {
|
||||
auto created = Create();
|
||||
EXPECT_EQ(gitversion::VersionString(), created.config()->Version());
|
||||
EXPECT_EQ(CryConfig::FilesystemFormatVersion, created.config()->Version());
|
||||
EXPECT_EQ(gitversion::VersionString(), created.config()->LastOpenedWithVersion());
|
||||
EXPECT_EQ(gitversion::VersionString(), created.config()->CreatedWithVersion());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user