File tree Expand file tree Collapse file tree 4 files changed +33
-0
lines changed Expand file tree Collapse file tree 4 files changed +33
-0
lines changed Original file line number Diff line number Diff line change @@ -1165,6 +1165,9 @@ static bool LockDataDirectory(bool probeOnly)
1165
1165
{
1166
1166
// Make sure only a single Bitcoin process is using the data directory.
1167
1167
fs::path datadir = GetDataDir ();
1168
+ if (!DirIsWritable (datadir)) {
1169
+ return InitError (strprintf (_ (" Cannot write to data directory '%s'; check permissions." ), datadir.string ()));
1170
+ }
1168
1171
if (!LockDirectory (datadir, " .lock" , probeOnly)) {
1169
1172
return InitError (strprintf (_ (" Cannot obtain a lock on data directory %s. %s is probably already running." ), datadir.string (), _ (PACKAGE_NAME)));
1170
1173
}
Original file line number Diff line number Diff line change @@ -800,4 +800,20 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory)
800
800
fs::remove_all (dirname);
801
801
}
802
802
803
+ BOOST_AUTO_TEST_CASE (test_DirIsWritable)
804
+ {
805
+ // Should be able to write to the system tmp dir.
806
+ fs::path tmpdirname = fs::temp_directory_path ();
807
+ BOOST_CHECK_EQUAL (DirIsWritable (tmpdirname), true );
808
+
809
+ // Should not be able to write to a non-existent dir.
810
+ tmpdirname = fs::temp_directory_path () / fs::unique_path ();
811
+ BOOST_CHECK_EQUAL (DirIsWritable (tmpdirname), false );
812
+
813
+ fs::create_directory (tmpdirname);
814
+ // Should be able to write to it now.
815
+ BOOST_CHECK_EQUAL (DirIsWritable (tmpdirname), true );
816
+ fs::remove (tmpdirname);
817
+ }
818
+
803
819
BOOST_AUTO_TEST_SUITE_END ()
Original file line number Diff line number Diff line change @@ -418,6 +418,19 @@ void ReleaseDirectoryLocks()
418
418
dir_locks.clear ();
419
419
}
420
420
421
+ bool DirIsWritable (const fs::path& directory)
422
+ {
423
+ fs::path tmpFile = directory / fs::unique_path ();
424
+
425
+ FILE* file = fsbridge::fopen (tmpFile, " a" );
426
+ if (!file) return false ;
427
+
428
+ fclose (file);
429
+ remove (tmpFile);
430
+
431
+ return true ;
432
+ }
433
+
421
434
/* * Interpret string as boolean, for argument parsing */
422
435
static bool InterpretBool (const std::string& strValue)
423
436
{
Original file line number Diff line number Diff line change @@ -174,6 +174,7 @@ int RaiseFileDescriptorLimit(int nMinFD);
174
174
void AllocateFileRange (FILE *file, unsigned int offset, unsigned int length);
175
175
bool RenameOver (fs::path src, fs::path dest);
176
176
bool LockDirectory (const fs::path& directory, const std::string lockfile_name, bool probe_only=false );
177
+ bool DirIsWritable (const fs::path& directory);
177
178
178
179
/* * Release all directory locks. This is used for unit testing only, at runtime
179
180
* the global destructor will take care of the locks.
You can’t perform that action at this time.
0 commit comments