diff --git a/src/blockstore/implementations/integrity/IntegrityBlockStore2.cpp b/src/blockstore/implementations/integrity/IntegrityBlockStore2.cpp index ba4b7044..c8542671 100644 --- a/src/blockstore/implementations/integrity/IntegrityBlockStore2.cpp +++ b/src/blockstore/implementations/integrity/IntegrityBlockStore2.cpp @@ -96,12 +96,16 @@ void IntegrityBlockStore2::_checkNoPastIntegrityViolations() const { } void IntegrityBlockStore2::integrityViolationDetected(const string &reason) const { + if (_noIntegrityChecks) { + LOG(WARN, "Integrity violation (but integrity checks are disabled): {}", reason); + return; + } _integrityViolationDetected = true; throw IntegrityViolationError(reason); } -IntegrityBlockStore2::IntegrityBlockStore2(unique_ref baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId, bool missingBlockIsIntegrityViolation) -: _baseBlockStore(std::move(baseBlockStore)), _knownBlockVersions(integrityFilePath, myClientId), _missingBlockIsIntegrityViolation(missingBlockIsIntegrityViolation), _integrityViolationDetected(false) { +IntegrityBlockStore2::IntegrityBlockStore2(unique_ref baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation) +: _baseBlockStore(std::move(baseBlockStore)), _knownBlockVersions(integrityFilePath, myClientId), _noIntegrityChecks(noIntegrityChecks), _missingBlockIsIntegrityViolation(missingBlockIsIntegrityViolation), _integrityViolationDetected(false) { } bool IntegrityBlockStore2::tryCreate(const Key &key, const Data &data) { diff --git a/src/blockstore/implementations/integrity/IntegrityBlockStore2.h b/src/blockstore/implementations/integrity/IntegrityBlockStore2.h index 249b5b78..d82c1fdf 100644 --- a/src/blockstore/implementations/integrity/IntegrityBlockStore2.h +++ b/src/blockstore/implementations/integrity/IntegrityBlockStore2.h @@ -16,7 +16,7 @@ namespace integrity { // It depends on being used on top of an encrypted block store that protects integrity of the block contents (i.e. uses an authenticated cipher). class IntegrityBlockStore2 final: public BlockStore2 { public: - IntegrityBlockStore2(cpputils::unique_ref baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId, bool missingBlockIsIntegrityViolation); + IntegrityBlockStore2(cpputils::unique_ref baseBlockStore, const boost::filesystem::path &integrityFilePath, uint32_t myClientId, bool noIntegrityChecks, bool missingBlockIsIntegrityViolation); bool tryCreate(const Key &key, const cpputils::Data &data) override; bool remove(const Key &key) override; @@ -66,6 +66,7 @@ private: cpputils::unique_ref _baseBlockStore; mutable KnownBlockVersions _knownBlockVersions; + const bool _noIntegrityChecks; const bool _missingBlockIsIntegrityViolation; mutable bool _integrityViolationDetected; diff --git a/src/cryfs-cli/Cli.cpp b/src/cryfs-cli/Cli.cpp index bb3f44ac..877aa168 100644 --- a/src/cryfs-cli/Cli.cpp +++ b/src/cryfs-cli/Cli.cpp @@ -228,7 +228,7 @@ namespace cryfs { try { auto blockStore = make_unique_ref(options.baseDir()); auto config = _loadOrCreateConfig(options); - CryDevice device(std::move(config.configFile), std::move(blockStore), config.myClientId); + CryDevice device(std::move(config.configFile), std::move(blockStore), config.myClientId, options.noIntegrityChecks()); _sanityCheckFilesystem(&device); fspp::FilesystemImpl fsimpl(&device); fspp::fuse::Fuse fuse(&fsimpl, "cryfs", "cryfs@"+options.baseDir().native()); diff --git a/src/cryfs-cli/program_options/Parser.cpp b/src/cryfs-cli/program_options/Parser.cpp index 90649ac3..c25b58e5 100644 --- a/src/cryfs-cli/program_options/Parser.cpp +++ b/src/cryfs-cli/program_options/Parser.cpp @@ -76,6 +76,7 @@ ProgramOptions Parser::parse(const vector &supportedCiphers) const { if (vm.count("blocksize")) { blocksizeBytes = vm["blocksize"].as(); } + bool noIntegrityChecks = vm.count("no-integrity-checks"); optional missingBlockIsIntegrityViolation = none; if (vm.count("missing-block-is-integrity-violation")) { missingBlockIsIntegrityViolation = vm["missing-block-is-integrity-violation"].as(); @@ -91,7 +92,7 @@ ProgramOptions Parser::parse(const vector &supportedCiphers) const { } } - return ProgramOptions(baseDir, mountDir, configfile, foreground, unmountAfterIdleMinutes, logfile, cipher, blocksizeBytes, missingBlockIsIntegrityViolation, fuseOptions); + return ProgramOptions(baseDir, mountDir, configfile, foreground, unmountAfterIdleMinutes, logfile, cipher, blocksizeBytes, noIntegrityChecks, missingBlockIsIntegrityViolation, fuseOptions); } void Parser::_checkValidCipher(const string &cipher, const vector &supportedCiphers) { @@ -153,6 +154,7 @@ void Parser::_addAllowedOptions(po::options_description *desc) { ("fuse-option,o", po::value>(), "Add a fuse mount option. Example: atime or noatime.") ("cipher", po::value(), cipher_description.c_str()) ("blocksize", po::value(), blocksize_description.c_str()) + ("no-integrity-checks", "Disable integrity checks. Integrity checks ensure that your file system was not manipulated or rolled back to an earlier version. Disabling them is needed if you want to load an old snapshot of your file system.") ("missing-block-is-integrity-violation", po::value(), "Whether to treat a missing block as an integrity violation. This makes sure you notice if an attacker deleted some of your files, but only works in single-client mode. You will not be able to use the file system on other devices.") ("show-ciphers", "Show list of supported ciphers.") ("unmount-idle", po::value(), "Automatically unmount after specified number of idle minutes.") diff --git a/src/cryfs-cli/program_options/ProgramOptions.cpp b/src/cryfs-cli/program_options/ProgramOptions.cpp index 2a8aefa9..36ab01f7 100644 --- a/src/cryfs-cli/program_options/ProgramOptions.cpp +++ b/src/cryfs-cli/program_options/ProgramOptions.cpp @@ -12,9 +12,10 @@ ProgramOptions::ProgramOptions(const bf::path &baseDir, const bf::path &mountDir bool foreground, const optional &unmountAfterIdleMinutes, const optional &logFile, const optional &cipher, const optional &blocksizeBytes, + bool noIntegrityChecks, const boost::optional &missingBlockIsIntegrityViolation, const vector &fuseOptions) - :_baseDir(baseDir), _mountDir(mountDir), _configFile(configFile), _foreground(foreground), + :_baseDir(baseDir), _mountDir(mountDir), _configFile(configFile), _foreground(foreground), _noIntegrityChecks(noIntegrityChecks), _cipher(cipher), _blocksizeBytes(blocksizeBytes), _unmountAfterIdleMinutes(unmountAfterIdleMinutes), _missingBlockIsIntegrityViolation(missingBlockIsIntegrityViolation), _logFile(logFile), _fuseOptions(fuseOptions) { } @@ -51,6 +52,10 @@ const optional &ProgramOptions::blocksizeBytes() const { return _blocksizeBytes; } +bool ProgramOptions::noIntegrityChecks() const { + return _noIntegrityChecks; +} + const optional &ProgramOptions::missingBlockIsIntegrityViolation() const { return _missingBlockIsIntegrityViolation; } diff --git a/src/cryfs-cli/program_options/ProgramOptions.h b/src/cryfs-cli/program_options/ProgramOptions.h index b4dee062..a4582b80 100644 --- a/src/cryfs-cli/program_options/ProgramOptions.h +++ b/src/cryfs-cli/program_options/ProgramOptions.h @@ -18,6 +18,7 @@ namespace cryfs { const boost::optional &logFile, const boost::optional &cipher, const boost::optional &blocksizeBytes, + bool noIntegrityChecks, const boost::optional &missingBlockIsIntegrityViolation, const std::vector &fuseOptions); ProgramOptions(ProgramOptions &&rhs) = default; @@ -29,6 +30,7 @@ namespace cryfs { const boost::optional &cipher() const; const boost::optional &blocksizeBytes() const; const boost::optional &unmountAfterIdleMinutes() const; + bool noIntegrityChecks() const; const boost::optional &missingBlockIsIntegrityViolation() const; const boost::optional &logFile() const; const std::vector &fuseOptions() const; @@ -38,6 +40,7 @@ namespace cryfs { boost::filesystem::path _mountDir; boost::optional _configFile; bool _foreground; + bool _noIntegrityChecks; boost::optional _cipher; boost::optional _blocksizeBytes; boost::optional _unmountAfterIdleMinutes; diff --git a/src/cryfs/filesystem/CryDevice.cpp b/src/cryfs/filesystem/CryDevice.cpp index a32f93fc..12bcf373 100644 --- a/src/cryfs/filesystem/CryDevice.cpp +++ b/src/cryfs/filesystem/CryDevice.cpp @@ -57,14 +57,14 @@ namespace bf = boost::filesystem; namespace cryfs { -CryDevice::CryDevice(CryConfigFile configFile, unique_ref blockStore, uint32_t myClientId) -: _fsBlobStore(CreateFsBlobStore(std::move(blockStore), &configFile, myClientId)), +CryDevice::CryDevice(CryConfigFile configFile, unique_ref blockStore, uint32_t myClientId, bool noIntegrityChecks) +: _fsBlobStore(CreateFsBlobStore(std::move(blockStore), &configFile, myClientId, noIntegrityChecks)), _rootKey(GetOrCreateRootKey(&configFile)), _onFsAction() { } -unique_ref CryDevice::CreateFsBlobStore(unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId) { - auto blobStore = CreateBlobStore(std::move(blockStore), configFile, myClientId); +unique_ref CryDevice::CreateFsBlobStore(unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks) { + auto blobStore = CreateBlobStore(std::move(blockStore), configFile, myClientId, noIntegrityChecks); #ifndef CRYFS_NO_COMPATIBILITY auto fsBlobStore = MigrateOrCreateFsBlobStore(std::move(blobStore), configFile); @@ -89,8 +89,8 @@ unique_ref CryDevice::MigrateOrCreateFsBlobStore(uniqu } #endif -unique_ref CryDevice::CreateBlobStore(unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId) { - auto integrityEncryptedBlockStore = CreateIntegrityEncryptedBlockStore(std::move(blockStore), configFile, myClientId); +unique_ref CryDevice::CreateBlobStore(unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks) { + auto integrityEncryptedBlockStore = CreateIntegrityEncryptedBlockStore(std::move(blockStore), configFile, myClientId, noIntegrityChecks); // Create integrityEncryptedBlockStore 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( @@ -102,7 +102,7 @@ unique_ref CryDevice::CreateBlobStore(unique_refconfig()->BlocksizeBytes()); } -unique_ref CryDevice::CreateIntegrityEncryptedBlockStore(unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId) { +unique_ref CryDevice::CreateIntegrityEncryptedBlockStore(unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks) { auto encryptedBlockStore = CreateEncryptedBlockStore(*configFile->config(), std::move(blockStore)); auto statePath = LocalStateDir::forFilesystemId(configFile->config()->FilesystemId()); auto integrityFilePath = statePath / "integritydata"; @@ -115,8 +115,8 @@ unique_ref CryDevice::CreateIntegrityEncryptedBlockStore(unique_ref configFile->save(); } #endif - - return make_unique_ref(std::move(encryptedBlockStore), integrityFilePath, myClientId, false); + + return make_unique_ref(std::move(encryptedBlockStore), integrityFilePath, myClientId, noIntegrityChecks, false); } Key CryDevice::CreateRootBlobAndReturnKey() { diff --git a/src/cryfs/filesystem/CryDevice.h b/src/cryfs/filesystem/CryDevice.h index 5cc46664..f11d4069 100644 --- a/src/cryfs/filesystem/CryDevice.h +++ b/src/cryfs/filesystem/CryDevice.h @@ -18,7 +18,7 @@ namespace cryfs { class CryDevice final: public fspp::Device { public: - CryDevice(CryConfigFile config, cpputils::unique_ref blockStore, uint32_t myClientId); + CryDevice(CryConfigFile config, cpputils::unique_ref blockStore, uint32_t myClientId, bool noIntegrityChecks); void statfs(const boost::filesystem::path &path, struct ::statvfs *fsstat) override; @@ -53,12 +53,12 @@ private: blockstore::Key GetOrCreateRootKey(CryConfigFile *config); blockstore::Key CreateRootBlobAndReturnKey(); - static cpputils::unique_ref CreateFsBlobStore(cpputils::unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId); + static cpputils::unique_ref CreateFsBlobStore(cpputils::unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks); #ifndef CRYFS_NO_COMPATIBILITY static cpputils::unique_ref MigrateOrCreateFsBlobStore(cpputils::unique_ref blobStore, CryConfigFile *configFile); #endif - static cpputils::unique_ref CreateBlobStore(cpputils::unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId); - static cpputils::unique_ref CreateIntegrityEncryptedBlockStore(cpputils::unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId); + static cpputils::unique_ref CreateBlobStore(cpputils::unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks); + static cpputils::unique_ref CreateIntegrityEncryptedBlockStore(cpputils::unique_ref blockStore, CryConfigFile *configFile, uint32_t myClientId, bool noIntegrityChecks); static cpputils::unique_ref CreateEncryptedBlockStore(const CryConfig &config, cpputils::unique_ref baseBlockStore); struct BlobWithParent { diff --git a/test/blockstore/implementations/integrity/IntegrityBlockStoreTest_Specific.cpp b/test/blockstore/implementations/integrity/IntegrityBlockStoreTest_Specific.cpp index 7b6bae9e..3d0c6c57 100644 --- a/test/blockstore/implementations/integrity/IntegrityBlockStoreTest_Specific.cpp +++ b/test/blockstore/implementations/integrity/IntegrityBlockStoreTest_Specific.cpp @@ -249,6 +249,7 @@ TEST_F(IntegrityBlockStoreTest, LoadingWithDifferentBlockIdFails) { // - RollbackPrevention_DoesntAllowReintroducingDeletedBlocks with different client id (i.e. trying to re-introduce the newest block of a different client) // - RollbackPrevention_AllowsReintroducingDeletedBlocksWithNewVersionNumber with different client id // - Think about more... +// TODO Test that disabling integrity checks allows all these cases TEST_F(IntegrityBlockStoreTest, PhysicalBlockSize_zerophysical) { EXPECT_EQ(0u, blockStore->blockSizeFromPhysicalBlockSize(0)); diff --git a/test/cryfs-cli/program_options/ParserTest.cpp b/test/cryfs-cli/program_options/ParserTest.cpp index c345fc7c..04657915 100644 --- a/test/cryfs-cli/program_options/ParserTest.cpp +++ b/test/cryfs-cli/program_options/ParserTest.cpp @@ -156,6 +156,16 @@ TEST_F(ProgramOptionsParserTest, MissingBlockIsIntegrityViolationGiven_False) { EXPECT_FALSE(options.missingBlockIsIntegrityViolation().value()); } +TEST_F(ProgramOptionsParserTest, NoIntegrityChecks_True) { + ProgramOptions options = parse({"./myExecutable", "/home/user/baseDir", "--no-integrity-checks", "/home/user/mountDir"}); + EXPECT_TRUE(options.noIntegrityChecks()); +} + +TEST_F(ProgramOptionsParserTest, NoIntegrityChecks_False) { + ProgramOptions options = parse({"./myExecutable", "/home/user/baseDir", "/home/user/mountDir"}); + EXPECT_FALSE(options.noIntegrityChecks()); +} + TEST_F(ProgramOptionsParserTest, MissingBlockIsIntegrityViolationNotGiven) { ProgramOptions options = parse({"./myExecutable", "/home/user/baseDir", "/home/user/mountDir"}); EXPECT_EQ(none, options.missingBlockIsIntegrityViolation()); diff --git a/test/cryfs-cli/program_options/ProgramOptionsTest.cpp b/test/cryfs-cli/program_options/ProgramOptionsTest.cpp index db8580a7..abe148dd 100644 --- a/test/cryfs-cli/program_options/ProgramOptionsTest.cpp +++ b/test/cryfs-cli/program_options/ProgramOptionsTest.cpp @@ -23,98 +23,108 @@ namespace boost { class ProgramOptionsTest: public ProgramOptionsTestBase {}; TEST_F(ProgramOptionsTest, BaseDir) { - ProgramOptions testobj("/home/user/mydir", "", none, false, none, none, none, none, none, {"./myExecutable"}); + ProgramOptions testobj("/home/user/mydir", "", none, false, none, none, none, none, false, none, {"./myExecutable"}); EXPECT_EQ("/home/user/mydir", testobj.baseDir()); } TEST_F(ProgramOptionsTest, MountDir) { - ProgramOptions testobj("", "/home/user/mydir", none, false, none, none, none, none, none, {"./myExecutable"}); + ProgramOptions testobj("", "/home/user/mydir", none, false, none, none, none, none, false, none, {"./myExecutable"}); EXPECT_EQ("/home/user/mydir", testobj.mountDir()); } TEST_F(ProgramOptionsTest, ConfigfileNone) { - ProgramOptions testobj("", "", none, true, none, none, none, none, none, {"./myExecutable"}); + ProgramOptions testobj("", "", none, true, none, none, none, none, false, none, {"./myExecutable"}); EXPECT_EQ(none, testobj.configFile()); } TEST_F(ProgramOptionsTest, ConfigfileSome) { - ProgramOptions testobj("", "", bf::path("/home/user/configfile"), true, none, none, none, none, none, {"./myExecutable"}); + ProgramOptions testobj("", "", bf::path("/home/user/configfile"), true, none, none, none, none, false, none, {"./myExecutable"}); EXPECT_EQ("/home/user/configfile", testobj.configFile().get()); } TEST_F(ProgramOptionsTest, ForegroundFalse) { - ProgramOptions testobj("", "", none, false, none, none, none, none, none, {"./myExecutable"}); + ProgramOptions testobj("", "", none, false, none, none, none, none, false, none, {"./myExecutable"}); EXPECT_FALSE(testobj.foreground()); } TEST_F(ProgramOptionsTest, ForegroundTrue) { - ProgramOptions testobj("", "", none, true, none, none, none, none, none, {"./myExecutable"}); + ProgramOptions testobj("", "", none, true, none, none, none, none, false, none, {"./myExecutable"}); EXPECT_TRUE(testobj.foreground()); } TEST_F(ProgramOptionsTest, LogfileNone) { - ProgramOptions testobj("", "", none, true, none, none, none, none, none, {"./myExecutable"}); + ProgramOptions testobj("", "", none, true, none, none, none, none, false, none, {"./myExecutable"}); EXPECT_EQ(none, testobj.logFile()); } TEST_F(ProgramOptionsTest, LogfileSome) { - ProgramOptions testobj("", "", none, true, none, bf::path("logfile"), none, none, none, {"./myExecutable"}); + ProgramOptions testobj("", "", none, true, none, bf::path("logfile"), none, none, false, none, {"./myExecutable"}); EXPECT_EQ("logfile", testobj.logFile().get()); } TEST_F(ProgramOptionsTest, UnmountAfterIdleMinutesNone) { -ProgramOptions testobj("", "", none, true, none, none, none, none, none, {"./myExecutable"}); +ProgramOptions testobj("", "", none, true, none, none, none, none, false, none, {"./myExecutable"}); EXPECT_EQ(none, testobj.unmountAfterIdleMinutes()); } TEST_F(ProgramOptionsTest, UnmountAfterIdleMinutesSome) { - ProgramOptions testobj("", "", none, true, 10, none, none, none, none, {"./myExecutable"}); + ProgramOptions testobj("", "", none, true, 10, none, none, none, false, none, {"./myExecutable"}); EXPECT_EQ(10, testobj.unmountAfterIdleMinutes().get()); } TEST_F(ProgramOptionsTest, CipherNone) { - ProgramOptions testobj("", "", none, true, none, none, none, none, none, {"./myExecutable"}); + ProgramOptions testobj("", "", none, true, none, none, none, none, false, none, {"./myExecutable"}); EXPECT_EQ(none, testobj.cipher()); } TEST_F(ProgramOptionsTest, CipherSome) { - ProgramOptions testobj("", "", none, true, none, none, string("aes-256-gcm"), none, none, {"./myExecutable"}); + ProgramOptions testobj("", "", none, true, none, none, string("aes-256-gcm"), none, false, none, {"./myExecutable"}); EXPECT_EQ("aes-256-gcm", testobj.cipher().get()); } TEST_F(ProgramOptionsTest, BlocksizeBytesNone) { - ProgramOptions testobj("", "", none, true, none, none, none, none, none, {"./myExecutable"}); + ProgramOptions testobj("", "", none, true, none, none, none, none, false, none, {"./myExecutable"}); EXPECT_EQ(none, testobj.blocksizeBytes()); } TEST_F(ProgramOptionsTest, BlocksizeBytesSome) { - ProgramOptions testobj("", "", none, true, none, none, none, 10*1024, none, {"./myExecutable"}); + ProgramOptions testobj("", "", none, true, none, none, none, 10*1024, false, none, {"./myExecutable"}); EXPECT_EQ(10*1024u, testobj.blocksizeBytes().get()); } TEST_F(ProgramOptionsTest, MissingBlockIsIntegrityViolationTrue) { - ProgramOptions testobj("", "", none, true, none, none, none, none, true, {"./myExecutable"}); + ProgramOptions testobj("", "", none, true, none, none, none, none, false, true, {"./myExecutable"}); EXPECT_TRUE(testobj.missingBlockIsIntegrityViolation().value()); } TEST_F(ProgramOptionsTest, MissingBlockIsIntegrityViolationFalse) { - ProgramOptions testobj("", "", none, true, none, none, none, none, false, {"./myExecutable"}); + ProgramOptions testobj("", "", none, true, none, none, none, none, false, false, {"./myExecutable"}); EXPECT_FALSE(testobj.missingBlockIsIntegrityViolation().value()); } TEST_F(ProgramOptionsTest, MissingBlockIsIntegrityViolationNone) { - ProgramOptions testobj("", "", none, true, none, none, none, none, none, {"./myExecutable"}); + ProgramOptions testobj("", "", none, true, none, none, none, none, false, none, {"./myExecutable"}); EXPECT_EQ(none, testobj.missingBlockIsIntegrityViolation()); } +TEST_F(ProgramOptionsTest, NoIntegrityChecksFalse) { + ProgramOptions testobj("", "", none, true, none, none, none, none, false, none, {"./myExecutable"}); + EXPECT_FALSE(testobj.noIntegrityChecks()); +} + +TEST_F(ProgramOptionsTest, NoIntegrityChecksTrue) { + ProgramOptions testobj("", "", none, true, none, none, none, none, true, none, {"./myExecutable"}); + EXPECT_TRUE(testobj.noIntegrityChecks()); +} + TEST_F(ProgramOptionsTest, EmptyFuseOptions) { - ProgramOptions testobj("/rootDir", "/home/user/mydir", none, false, none, none, none, none, none, {}); + ProgramOptions testobj("/rootDir", "/home/user/mydir", none, false, none, none, none, none, false, none, {}); //Fuse should have the mount dir as first parameter EXPECT_VECTOR_EQ({}, testobj.fuseOptions()); } TEST_F(ProgramOptionsTest, SomeFuseOptions) { - ProgramOptions testobj("/rootDir", "/home/user/mydir", none, false, none, none, none, none, none, {"-f", "--longoption"}); + ProgramOptions testobj("/rootDir", "/home/user/mydir", none, false, none, none, none, none, false, none, {"-f", "--longoption"}); //Fuse should have the mount dir as first parameter EXPECT_VECTOR_EQ({"-f", "--longoption"}, testobj.fuseOptions()); }