If the given base or mount directory doesn't exist, offer to create them

This commit is contained in:
Sebastian Messmer 2016-01-25 15:01:34 +01:00
parent af4ef5d425
commit 29065746c2
6 changed files with 42 additions and 9 deletions

View File

@ -2,6 +2,7 @@ Version 0.8.5
--------------- ---------------
* Fix package manager warning when installing the .deb package * Fix package manager warning when installing the .deb package
* Offer a default configuration when creating new filesystems * Offer a default configuration when creating new filesystems
* If the given base or mount directory doesn't exist, offer to create them
Version 0.8.4 Version 0.8.4
--------------- ---------------

View File

@ -47,6 +47,7 @@ using cpputils::TempFile;
using cpputils::RandomGenerator; using cpputils::RandomGenerator;
using cpputils::unique_ref; using cpputils::unique_ref;
using cpputils::SCryptSettings; using cpputils::SCryptSettings;
using cpputils::Console;
using std::cout; using std::cout;
using std::string; using std::string;
using std::endl; using std::endl;
@ -71,8 +72,8 @@ using boost::chrono::milliseconds;
namespace cryfs { namespace cryfs {
Cli::Cli(RandomGenerator &keyGenerator, const SCryptSettings &scryptSettings): Cli::Cli(RandomGenerator &keyGenerator, const SCryptSettings &scryptSettings, shared_ptr<Console> console):
_keyGenerator(keyGenerator), _scryptSettings(scryptSettings) {} _keyGenerator(keyGenerator), _scryptSettings(scryptSettings), _console(console) {}
void Cli::_showVersion() { void Cli::_showVersion() {
cout << "CryFS Version " << version::VERSION_STRING << endl; cout << "CryFS Version " << version::VERSION_STRING << endl;
@ -174,8 +175,7 @@ namespace cryfs {
CryConfigFile Cli::_loadOrCreateConfig(const ProgramOptions &options) { CryConfigFile Cli::_loadOrCreateConfig(const ProgramOptions &options) {
try { try {
auto configFile = _determineConfigFile(options); auto configFile = _determineConfigFile(options);
auto console = make_shared<IOStreamConsole>(); auto config = CryConfigLoader(_console, _keyGenerator, _scryptSettings,
auto config = CryConfigLoader(console, _keyGenerator, _scryptSettings,
std::bind(&Cli::_getPassword, this, std::cref(options), &Cli::_askPasswordForExistingFilesystem), std::bind(&Cli::_getPassword, this, std::cref(options), &Cli::_askPasswordForExistingFilesystem),
std::bind(&Cli::_getPassword, this, std::cref(options), &Cli::_askPasswordForNewFilesystem), std::bind(&Cli::_getPassword, this, std::cref(options), &Cli::_askPasswordForNewFilesystem),
options.cipher()).loadOrCreate(configFile); options.cipher()).loadOrCreate(configFile);
@ -247,7 +247,14 @@ namespace cryfs {
void Cli::_checkDirAccessible(const bf::path &dir, const std::string &name) { void Cli::_checkDirAccessible(const bf::path &dir, const std::string &name) {
if (!bf::exists(dir)) { if (!bf::exists(dir)) {
throw std::runtime_error(name+" not found."); bool create = _console->askYesNo("Could not find " + name + ". Do you want to create it?");
if (create) {
if (!bf::create_directory(dir)) {
throw std::runtime_error("Error creating "+name);
}
} else {
throw std::runtime_error(name + " not found.");
}
} }
if (!bf::is_directory(dir)) { if (!bf::is_directory(dir)) {
throw std::runtime_error(name+" is not a directory."); throw std::runtime_error(name+" is not a directory.");

View File

@ -6,13 +6,14 @@
#include "../config/CryConfigFile.h" #include "../config/CryConfigFile.h"
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <messmer/cpp-utils/tempfile/TempFile.h> #include <messmer/cpp-utils/tempfile/TempFile.h>
#include <messmer/cpp-utils/io/Console.h>
#include <messmer/cpp-utils/random/RandomGenerator.h> #include <messmer/cpp-utils/random/RandomGenerator.h>
#include "CallAfterTimeout.h" #include "CallAfterTimeout.h"
namespace cryfs { namespace cryfs {
class Cli final { class Cli final {
public: public:
Cli(cpputils::RandomGenerator &keyGenerator, const cpputils::SCryptSettings &scryptSettings); Cli(cpputils::RandomGenerator &keyGenerator, const cpputils::SCryptSettings &scryptSettings, std::shared_ptr<cpputils::Console> console);
int main(int argc, char *argv[]); int main(int argc, char *argv[]);
private: private:
@ -36,6 +37,7 @@ namespace cryfs {
cpputils::RandomGenerator &_keyGenerator; cpputils::RandomGenerator &_keyGenerator;
cpputils::SCryptSettings _scryptSettings; cpputils::SCryptSettings _scryptSettings;
std::shared_ptr<cpputils::Console> _console;
DISALLOW_COPY_AND_ASSIGN(Cli); DISALLOW_COPY_AND_ASSIGN(Cli);
}; };

View File

@ -5,8 +5,10 @@
using namespace cryfs; using namespace cryfs;
using cpputils::Random; using cpputils::Random;
using cpputils::SCrypt; using cpputils::SCrypt;
using std::make_shared;
using cpputils::IOStreamConsole;
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
auto &keyGenerator = Random::OSRandom(); auto &keyGenerator = Random::OSRandom();
return Cli(keyGenerator, SCrypt::DefaultSettings).main(argc, argv); return Cli(keyGenerator, SCrypt::DefaultSettings, make_shared<IOStreamConsole>()).main(argc, argv);
} }

View File

@ -3,6 +3,7 @@
namespace bf = boost::filesystem; namespace bf = boost::filesystem;
using ::testing::Values; using ::testing::Values;
using ::testing::WithParamInterface; using ::testing::WithParamInterface;
using ::testing::Return;
using std::vector; using std::vector;
using cpputils::TempFile; using cpputils::TempFile;
@ -117,9 +118,18 @@ TEST_P(CliTest_WrongEnvironment, MountDirIsBaseDir_BothRelative) {
TEST_P(CliTest_WrongEnvironment, BaseDir_DoesntExist) { TEST_P(CliTest_WrongEnvironment, BaseDir_DoesntExist) {
_basedir.remove(); _basedir.remove();
ON_CALL(*console, askYesNo("Could not find base directory. Do you want to create it?")).WillByDefault(Return(false)); // ON_CALL and not EXPECT_CALL, because this is a death test (i.e. it is forked) and gmock EXPECT_CALL in fork children don't report to parents.
Test_Run_Error("Error: base directory not found"); Test_Run_Error("Error: base directory not found");
} }
TEST_P(CliTest_WrongEnvironment, BaseDir_DoesntExist_Create) {
if (!GetParam().runningInForeground) {return;} // TODO Make this work also if run in background (see CliTest::EXPECT_RUN_SUCCESS)
_basedir.remove();
ON_CALL(*console, askYesNo("Could not find base directory. Do you want to create it?")).WillByDefault(Return(true));
Test_Run_Success();
EXPECT_TRUE(bf::exists(_basedir.path()) && bf::is_directory(_basedir.path()));
}
TEST_P(CliTest_WrongEnvironment, BaseDir_IsNotDirectory) { TEST_P(CliTest_WrongEnvironment, BaseDir_IsNotDirectory) {
TempFile basedirfile; TempFile basedirfile;
basedir = basedirfile.path(); basedir = basedirfile.path();
@ -155,9 +165,18 @@ TEST_P(CliTest_WrongEnvironment, BaseDir_NoPermission) {
TEST_P(CliTest_WrongEnvironment, MountDir_DoesntExist) { TEST_P(CliTest_WrongEnvironment, MountDir_DoesntExist) {
_mountdir.remove(); _mountdir.remove();
ON_CALL(*console, askYesNo("Could not find mount directory. Do you want to create it?")).WillByDefault(Return(false)); // ON_CALL and not EXPECT_CALL, because this is a death test (i.e. it is forked) and gmock EXPECT_CALL in fork children don't report to parents.
Test_Run_Error("Error: mount directory not found"); Test_Run_Error("Error: mount directory not found");
} }
TEST_P(CliTest_WrongEnvironment, MountDir_DoesntExist_Create) {
if (!GetParam().runningInForeground) {return;} // TODO Make this work also if run in background (see CliTest::EXPECT_RUN_SUCCESS)
_mountdir.remove();
ON_CALL(*console, askYesNo("Could not find mount directory. Do you want to create it?")).WillByDefault(Return(true));
Test_Run_Success();
EXPECT_TRUE(bf::exists(_mountdir.path()) && bf::is_directory(_mountdir.path()));
}
TEST_P(CliTest_WrongEnvironment, MountDir_IsNotDirectory) { TEST_P(CliTest_WrongEnvironment, MountDir_IsNotDirectory) {
TempFile mountdirfile; TempFile mountdirfile;
mountdir = mountdirfile.path(); mountdir = mountdirfile.path();

View File

@ -9,10 +9,11 @@
#include "../../../src/cli/Cli.h" #include "../../../src/cli/Cli.h"
#include <messmer/cpp-utils/logging/logging.h> #include <messmer/cpp-utils/logging/logging.h>
#include <messmer/cpp-utils/process/subprocess.h> #include <messmer/cpp-utils/process/subprocess.h>
#include "../../testutils/MockConsole.h"
class CliTest : public ::testing::Test { class CliTest : public ::testing::Test {
public: public:
CliTest(): _basedir(), _mountdir(), basedir(_basedir.path()), mountdir(_mountdir.path()), logfile(), configfile(false) {} CliTest(): _basedir(), _mountdir(), basedir(_basedir.path()), mountdir(_mountdir.path()), logfile(), configfile(false), console(std::make_shared<MockConsole>()) {}
cpputils::TempDir _basedir; cpputils::TempDir _basedir;
cpputils::TempDir _mountdir; cpputils::TempDir _mountdir;
@ -20,6 +21,7 @@ public:
boost::filesystem::path mountdir; boost::filesystem::path mountdir;
cpputils::TempFile logfile; cpputils::TempFile logfile;
cpputils::TempFile configfile; cpputils::TempFile configfile;
std::shared_ptr<MockConsole> console;
void run(std::vector<const char*> args) { void run(std::vector<const char*> args) {
std::vector<char*> _args; std::vector<char*> _args;
@ -29,7 +31,7 @@ public:
_args.push_back(const_cast<char*>(arg)); _args.push_back(const_cast<char*>(arg));
} }
auto &keyGenerator = cpputils::Random::PseudoRandom(); auto &keyGenerator = cpputils::Random::PseudoRandom();
cryfs::Cli(keyGenerator, cpputils::SCrypt::TestSettings).main(_args.size(), _args.data()); cryfs::Cli(keyGenerator, cpputils::SCrypt::TestSettings, console).main(_args.size(), _args.data());
} }
void EXPECT_EXIT_WITH_HELP_MESSAGE(std::vector<const char*> args, const std::string &message = "") { void EXPECT_EXIT_WITH_HELP_MESSAGE(std::vector<const char*> args, const std::string &message = "") {