Skip to content

Commit c290508

Browse files
committed
Merge #12630: Provide useful error message if datadir is not writable.
8674e74 Provide relevant error message if datadir is not writable. (murrayn) Pull request description: If the --datadir exists, but is not writable, the current error message on startup is 'Cannot obtain a lock on data directory foo. Bitcoin Core is probably already running.' This is misleading. I believe this PR addresses #11668, although the issue is not Windows-specific. Tree-SHA512: 10cbbaea433072aee4fb3e8938a72073c7a5c841f7a7685c9e12549c322b2925c7d34bac254ac33021b23132bfc352c058712bc9542298cf86f8fd9757f528b2
2 parents a6926b0 + 8674e74 commit c290508

File tree

4 files changed

+33
-0
lines changed

4 files changed

+33
-0
lines changed

src/init.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,9 @@ static bool LockDataDirectory(bool probeOnly)
11651165
{
11661166
// Make sure only a single Bitcoin process is using the data directory.
11671167
fs::path datadir = GetDataDir();
1168+
if (!DirIsWritable(datadir)) {
1169+
return InitError(strprintf(_("Cannot write to data directory '%s'; check permissions."), datadir.string()));
1170+
}
11681171
if (!LockDirectory(datadir, ".lock", probeOnly)) {
11691172
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), datadir.string(), _(PACKAGE_NAME)));
11701173
}

src/test/util_tests.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,4 +817,20 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory)
817817
fs::remove_all(dirname);
818818
}
819819

820+
BOOST_AUTO_TEST_CASE(test_DirIsWritable)
821+
{
822+
// Should be able to write to the system tmp dir.
823+
fs::path tmpdirname = fs::temp_directory_path();
824+
BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
825+
826+
// Should not be able to write to a non-existent dir.
827+
tmpdirname = fs::temp_directory_path() / fs::unique_path();
828+
BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), false);
829+
830+
fs::create_directory(tmpdirname);
831+
// Should be able to write to it now.
832+
BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
833+
fs::remove(tmpdirname);
834+
}
835+
820836
BOOST_AUTO_TEST_SUITE_END()

src/util.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,19 @@ void ReleaseDirectoryLocks()
419419
dir_locks.clear();
420420
}
421421

422+
bool DirIsWritable(const fs::path& directory)
423+
{
424+
fs::path tmpFile = directory / fs::unique_path();
425+
426+
FILE* file = fsbridge::fopen(tmpFile, "a");
427+
if (!file) return false;
428+
429+
fclose(file);
430+
remove(tmpFile);
431+
432+
return true;
433+
}
434+
422435
/** Interpret string as boolean, for argument parsing */
423436
static bool InterpretBool(const std::string& strValue)
424437
{

src/util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ int RaiseFileDescriptorLimit(int nMinFD);
174174
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length);
175175
bool RenameOver(fs::path src, fs::path dest);
176176
bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false);
177+
bool DirIsWritable(const fs::path& directory);
177178

178179
/** Release all directory locks. This is used for unit testing only, at runtime
179180
* the global destructor will take care of the locks.

0 commit comments

Comments
 (0)