diff options
author | murrayn <github@nesbitt.ca> | 2018-03-07 03:08:55 -0800 |
---|---|---|
committer | murrayn <github@nesbitt.ca> | 2018-03-14 19:07:30 -0700 |
commit | 8674e74b47c1f6e86a367cfbc738fcc9812b616b (patch) | |
tree | acf9d52938e2021e4dcb9ad1c89e02ae8362d82a | |
parent | b225010a808d475cbb53aeed484295f8dc8751c4 (diff) |
Provide relevant error message if datadir is not writable.
-rw-r--r-- | src/init.cpp | 3 | ||||
-rw-r--r-- | src/test/util_tests.cpp | 16 | ||||
-rw-r--r-- | src/util.cpp | 13 | ||||
-rw-r--r-- | src/util.h | 1 |
4 files changed, 33 insertions, 0 deletions
diff --git a/src/init.cpp b/src/init.cpp index f763c3a435..6493ae72bd 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1165,6 +1165,9 @@ static bool LockDataDirectory(bool probeOnly) { // Make sure only a single Bitcoin process is using the data directory. fs::path datadir = GetDataDir(); + if (!DirIsWritable(datadir)) { + return InitError(strprintf(_("Cannot write to data directory '%s'; check permissions."), datadir.string())); + } if (!LockDirectory(datadir, ".lock", probeOnly)) { return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), datadir.string(), _(PACKAGE_NAME))); } diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 58f033cd89..e750969b65 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -800,4 +800,20 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory) fs::remove_all(dirname); } +BOOST_AUTO_TEST_CASE(test_DirIsWritable) +{ + // Should be able to write to the system tmp dir. + fs::path tmpdirname = fs::temp_directory_path(); + BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true); + + // Should not be able to write to a non-existent dir. + tmpdirname = fs::temp_directory_path() / fs::unique_path(); + BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), false); + + fs::create_directory(tmpdirname); + // Should be able to write to it now. + BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true); + fs::remove(tmpdirname); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/util.cpp b/src/util.cpp index 82c99a3c2f..7ea7972564 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -418,6 +418,19 @@ void ReleaseDirectoryLocks() dir_locks.clear(); } +bool DirIsWritable(const fs::path& directory) +{ + fs::path tmpFile = directory / fs::unique_path(); + + FILE* file = fsbridge::fopen(tmpFile, "a"); + if (!file) return false; + + fclose(file); + remove(tmpFile); + + return true; +} + /** Interpret string as boolean, for argument parsing */ static bool InterpretBool(const std::string& strValue) { diff --git a/src/util.h b/src/util.h index e4170d8aa2..3e19375498 100644 --- a/src/util.h +++ b/src/util.h @@ -174,6 +174,7 @@ int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); bool RenameOver(fs::path src, fs::path dest); bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false); +bool DirIsWritable(const fs::path& directory); /** Release all directory locks. This is used for unit testing only, at runtime * the global destructor will take care of the locks. |