Skip to content

Commit f48a789

Browse files
committed
Merge bitcoin#28075: util: Remove DirIsWritable, GetUniquePath
fa3da62 Remove DirIsWritable, GetUniquePath (MarcoFalke) fad3a97 Return LockResult::ErrorWrite in LockDirectory (MarcoFalke) fa0afe7 refactor: Return enum in LockDirectory (MarcoFalke) Pull request description: `GetUniquePath` is only used in tests and in `DirIsWritable`. The check by `DirIsWritable` is redundant with the check done in `LockDirectory`. Fix the redundancy by removing everything, except `LockDirectory`. ACKs for top commit: TheCharlatan: Re-ACK fa3da62 hebasto: ACK fa3da62, I have reviewed the code and it looks OK. Tree-SHA512: e95f18cd586de7582e9c08ac7ddb860bfcfcbc8963804f45c5784c5e4c0598dc59ae7e45dd4daf30a5020dbf8433f5db2ad06e46a8676371982003790043c6c9
2 parents d646ca3 + fa3da62 commit f48a789

File tree

9 files changed

+67
-126
lines changed

9 files changed

+67
-126
lines changed

src/Makefile.am

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,6 @@ BITCOIN_CORE_H = \
304304
util/fees.h \
305305
util/fs.h \
306306
util/fs_helpers.h \
307-
util/getuniquepath.h \
308307
util/golombrice.h \
309308
util/hash_type.h \
310309
util/hasher.h \
@@ -741,7 +740,6 @@ libbitcoin_util_a_SOURCES = \
741740
util/fees.cpp \
742741
util/fs.cpp \
743742
util/fs_helpers.cpp \
744-
util/getuniquepath.cpp \
745743
util/hasher.cpp \
746744
util/sock.cpp \
747745
util/syserror.cpp \
@@ -984,7 +982,6 @@ libbitcoinkernel_la_SOURCES = \
984982
util/exception.cpp \
985983
util/fs.cpp \
986984
util/fs_helpers.cpp \
987-
util/getuniquepath.cpp \
988985
util/hasher.cpp \
989986
util/moneystr.cpp \
990987
util/rbf.cpp \

src/init.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,13 +1047,14 @@ static bool LockDataDirectory(bool probeOnly)
10471047
{
10481048
// Make sure only a single Bitcoin process is using the data directory.
10491049
const fs::path& datadir = gArgs.GetDataDirNet();
1050-
if (!DirIsWritable(datadir)) {
1050+
switch (util::LockDirectory(datadir, ".lock", probeOnly)) {
1051+
case util::LockResult::ErrorWrite:
10511052
return InitError(strprintf(_("Cannot write to data directory '%s'; check permissions."), fs::PathToString(datadir)));
1052-
}
1053-
if (!LockDirectory(datadir, ".lock", probeOnly)) {
1053+
case util::LockResult::ErrorLock:
10541054
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), fs::PathToString(datadir), PACKAGE_NAME));
1055-
}
1056-
return true;
1055+
case util::LockResult::Success: return true;
1056+
} // no default case, so the compiler can warn about missing cases
1057+
assert(false);
10571058
}
10581059

10591060
bool AppInitSanityChecks(const kernel::Context& kernel)

src/test/fs_tests.cpp

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include <test/util/setup_common.h>
66
#include <util/fs.h>
77
#include <util/fs_helpers.h>
8-
#include <util/getuniquepath.h>
98

109
#include <boost/test/unit_test.hpp>
1110

@@ -101,29 +100,14 @@ BOOST_AUTO_TEST_CASE(fsbridge_fstream)
101100
BOOST_CHECK_EQUAL(tmpfile1, fsbridge::AbsPathJoin(tmpfile1, ""));
102101
BOOST_CHECK_EQUAL(tmpfile1, fsbridge::AbsPathJoin(tmpfile1, {}));
103102
}
104-
{
105-
fs::path p1 = GetUniquePath(tmpfolder);
106-
fs::path p2 = GetUniquePath(tmpfolder);
107-
fs::path p3 = GetUniquePath(tmpfolder);
108-
109-
// Ensure that the parent path is always the same.
110-
BOOST_CHECK_EQUAL(tmpfolder, p1.parent_path());
111-
BOOST_CHECK_EQUAL(tmpfolder, p2.parent_path());
112-
BOOST_CHECK_EQUAL(tmpfolder, p3.parent_path());
113-
114-
// Ensure that generated paths are actually different.
115-
BOOST_CHECK(p1 != p2);
116-
BOOST_CHECK(p2 != p3);
117-
BOOST_CHECK(p1 != p3);
118-
}
119103
}
120104

121105
BOOST_AUTO_TEST_CASE(rename)
122106
{
123107
const fs::path tmpfolder{m_args.GetDataDirBase()};
124108

125-
const fs::path path1{GetUniquePath(tmpfolder)};
126-
const fs::path path2{GetUniquePath(tmpfolder)};
109+
const fs::path path1{tmpfolder / "a"};
110+
const fs::path path2{tmpfolder / "b"};
127111

128112
const std::string path1_contents{"1111"};
129113
const std::string path2_contents{"2222"};
@@ -158,13 +142,13 @@ BOOST_AUTO_TEST_CASE(create_directories)
158142
// Test fs::create_directories workaround.
159143
const fs::path tmpfolder{m_args.GetDataDirBase()};
160144

161-
const fs::path dir{GetUniquePath(tmpfolder)};
145+
const fs::path dir{tmpfolder / "a"};
162146
fs::create_directory(dir);
163147
BOOST_CHECK(fs::exists(dir));
164148
BOOST_CHECK(fs::is_directory(dir));
165149
BOOST_CHECK(!fs::create_directories(dir));
166150

167-
const fs::path symlink{GetUniquePath(tmpfolder)};
151+
const fs::path symlink{tmpfolder / "b"};
168152
fs::create_directory_symlink(dir, symlink);
169153
BOOST_CHECK(fs::exists(symlink));
170154
BOOST_CHECK(fs::is_symlink(symlink));

src/test/util_tests.cpp

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include <util/bitdeque.h>
1313
#include <util/fs.h>
1414
#include <util/fs_helpers.h>
15-
#include <util/getuniquepath.h>
1615
#include <util/message.h> // For MessageSign(), MessageVerify(), MESSAGE_MAGIC
1716
#include <util/moneystr.h>
1817
#include <util/overflow.h>
@@ -1106,31 +1105,39 @@ BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
11061105
BOOST_CHECK(!ParseFixedPoint("31.999999999999999999999", 3, &amount));
11071106
}
11081107

1109-
static void TestOtherThread(fs::path dirname, fs::path lockname, bool *result)
1110-
{
1111-
*result = LockDirectory(dirname, lockname);
1112-
}
1113-
11141108
#ifndef WIN32 // Cannot do this test on WIN32 due to lack of fork()
11151109
static constexpr char LockCommand = 'L';
11161110
static constexpr char UnlockCommand = 'U';
11171111
static constexpr char ExitCommand = 'X';
1112+
enum : char {
1113+
ResSuccess = 2, // Start with 2 to avoid accidental collision with common values 0 and 1
1114+
ResErrorWrite,
1115+
ResErrorLock,
1116+
ResUnlockSuccess,
1117+
};
11181118

11191119
[[noreturn]] static void TestOtherProcess(fs::path dirname, fs::path lockname, int fd)
11201120
{
11211121
char ch;
11221122
while (true) {
11231123
int rv = read(fd, &ch, 1); // Wait for command
11241124
assert(rv == 1);
1125-
switch(ch) {
1125+
switch (ch) {
11261126
case LockCommand:
1127-
ch = LockDirectory(dirname, lockname);
1127+
ch = [&] {
1128+
switch (util::LockDirectory(dirname, lockname)) {
1129+
case util::LockResult::Success: return ResSuccess;
1130+
case util::LockResult::ErrorWrite: return ResErrorWrite;
1131+
case util::LockResult::ErrorLock: return ResErrorLock;
1132+
} // no default case, so the compiler can warn about missing cases
1133+
assert(false);
1134+
}();
11281135
rv = write(fd, &ch, 1);
11291136
assert(rv == 1);
11301137
break;
11311138
case UnlockCommand:
11321139
ReleaseDirectoryLocks();
1133-
ch = true; // Always succeeds
1140+
ch = ResUnlockSuccess; // Always succeeds
11341141
rv = write(fd, &ch, 1);
11351142
assert(rv == 1);
11361143
break;
@@ -1165,53 +1172,58 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory)
11651172
TestOtherProcess(dirname, lockname, fd[0]);
11661173
}
11671174
BOOST_CHECK_EQUAL(close(fd[0]), 0); // Parent: close child end
1175+
1176+
char ch;
1177+
// Lock on non-existent directory should fail
1178+
BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
1179+
BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1180+
BOOST_CHECK_EQUAL(ch, ResErrorWrite);
11681181
#endif
11691182
// Lock on non-existent directory should fail
1170-
BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), false);
1183+
BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::ErrorWrite);
11711184

11721185
fs::create_directories(dirname);
11731186

11741187
// Probing lock on new directory should succeed
1175-
BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
1188+
BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);
11761189

11771190
// Persistent lock on new directory should succeed
1178-
BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
1191+
BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::Success);
11791192

11801193
// Another lock on the directory from the same thread should succeed
1181-
BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
1194+
BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::Success);
11821195

11831196
// Another lock on the directory from a different thread within the same process should succeed
1184-
bool threadresult;
1185-
std::thread thr(TestOtherThread, dirname, lockname, &threadresult);
1197+
util::LockResult threadresult;
1198+
std::thread thr([&] { threadresult = util::LockDirectory(dirname, lockname); });
11861199
thr.join();
1187-
BOOST_CHECK_EQUAL(threadresult, true);
1200+
BOOST_CHECK_EQUAL(threadresult, util::LockResult::Success);
11881201
#ifndef WIN32
11891202
// Try to acquire lock in child process while we're holding it, this should fail.
1190-
char ch;
11911203
BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
11921204
BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1193-
BOOST_CHECK_EQUAL((bool)ch, false);
1205+
BOOST_CHECK_EQUAL(ch, ResErrorLock);
11941206

11951207
// Give up our lock
11961208
ReleaseDirectoryLocks();
11971209
// Probing lock from our side now should succeed, but not hold on to the lock.
1198-
BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
1210+
BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);
11991211

12001212
// Try to acquire the lock in the child process, this should be successful.
12011213
BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
12021214
BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1203-
BOOST_CHECK_EQUAL((bool)ch, true);
1215+
BOOST_CHECK_EQUAL(ch, ResSuccess);
12041216

12051217
// When we try to probe the lock now, it should fail.
1206-
BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), false);
1218+
BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::ErrorLock);
12071219

12081220
// Unlock the lock in the child process
12091221
BOOST_CHECK_EQUAL(write(fd[1], &UnlockCommand, 1), 1);
12101222
BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
1211-
BOOST_CHECK_EQUAL((bool)ch, true);
1223+
BOOST_CHECK_EQUAL(ch, ResUnlockSuccess);
12121224

12131225
// When we try to probe the lock now, it should succeed.
1214-
BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
1226+
BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);
12151227

12161228
// Re-lock the lock in the child process, then wait for it to exit, check
12171229
// successful return. After that, we check that exiting the process
@@ -1224,7 +1236,7 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory)
12241236
BOOST_CHECK_EQUAL(write(fd[1], &ExitCommand, 1), 1);
12251237
BOOST_CHECK_EQUAL(waitpid(pid, &processstatus, 0), pid);
12261238
BOOST_CHECK_EQUAL(processstatus, 0);
1227-
BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
1239+
BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);
12281240

12291241
// Restore SIGCHLD
12301242
signal(SIGCHLD, old_handler);
@@ -1235,22 +1247,6 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory)
12351247
fs::remove_all(dirname);
12361248
}
12371249

1238-
BOOST_AUTO_TEST_CASE(test_DirIsWritable)
1239-
{
1240-
// Should be able to write to the data dir.
1241-
fs::path tmpdirname = m_args.GetDataDirBase();
1242-
BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
1243-
1244-
// Should not be able to write to a non-existent dir.
1245-
tmpdirname = GetUniquePath(tmpdirname);
1246-
BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), false);
1247-
1248-
fs::create_directory(tmpdirname);
1249-
// Should be able to write to it now.
1250-
BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
1251-
fs::remove(tmpdirname);
1252-
}
1253-
12541250
BOOST_AUTO_TEST_CASE(test_ToLower)
12551251
{
12561252
BOOST_CHECK_EQUAL(ToLower('@'), '@');

src/util/fs_helpers.cpp

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include <logging.h>
1313
#include <sync.h>
1414
#include <util/fs.h>
15-
#include <util/getuniquepath.h>
1615
#include <util/syserror.h>
1716

1817
#include <cerrno>
@@ -51,31 +50,35 @@ static GlobalMutex cs_dir_locks;
5150
* is called.
5251
*/
5352
static std::map<std::string, std::unique_ptr<fsbridge::FileLock>> dir_locks GUARDED_BY(cs_dir_locks);
54-
55-
bool LockDirectory(const fs::path& directory, const fs::path& lockfile_name, bool probe_only)
53+
namespace util {
54+
LockResult LockDirectory(const fs::path& directory, const fs::path& lockfile_name, bool probe_only)
5655
{
5756
LOCK(cs_dir_locks);
5857
fs::path pathLockFile = directory / lockfile_name;
5958

6059
// If a lock for this directory already exists in the map, don't try to re-lock it
6160
if (dir_locks.count(fs::PathToString(pathLockFile))) {
62-
return true;
61+
return LockResult::Success;
6362
}
6463

6564
// Create empty lock file if it doesn't exist.
66-
FILE* file = fsbridge::fopen(pathLockFile, "a");
67-
if (file) fclose(file);
65+
if (auto created{fsbridge::fopen(pathLockFile, "a")}) {
66+
std::fclose(created);
67+
} else {
68+
return LockResult::ErrorWrite;
69+
}
6870
auto lock = std::make_unique<fsbridge::FileLock>(pathLockFile);
6971
if (!lock->TryLock()) {
70-
return error("Error while attempting to lock directory %s: %s", fs::PathToString(directory), lock->GetReason());
72+
error("Error while attempting to lock directory %s: %s", fs::PathToString(directory), lock->GetReason());
73+
return LockResult::ErrorLock;
7174
}
7275
if (!probe_only) {
7376
// Lock successful and we're not just probing, put it into the map
7477
dir_locks.emplace(fs::PathToString(pathLockFile), std::move(lock));
7578
}
76-
return true;
79+
return LockResult::Success;
7780
}
78-
81+
} // namespace util
7982
void UnlockDirectory(const fs::path& directory, const fs::path& lockfile_name)
8083
{
8184
LOCK(cs_dir_locks);
@@ -88,19 +91,6 @@ void ReleaseDirectoryLocks()
8891
dir_locks.clear();
8992
}
9093

91-
bool DirIsWritable(const fs::path& directory)
92-
{
93-
fs::path tmpFile = GetUniquePath(directory);
94-
95-
FILE* file = fsbridge::fopen(tmpFile, "a");
96-
if (!file) return false;
97-
98-
fclose(file);
99-
remove(tmpFile);
100-
101-
return true;
102-
}
103-
10494
bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes)
10595
{
10696
constexpr uint64_t min_disk_space = 52428800; // 50 MiB

src/util/fs_helpers.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,15 @@ void AllocateFileRange(FILE* file, unsigned int offset, unsigned int length);
3535
*/
3636
[[nodiscard]] bool RenameOver(fs::path src, fs::path dest);
3737

38-
bool LockDirectory(const fs::path& directory, const fs::path& lockfile_name, bool probe_only = false);
38+
namespace util {
39+
enum class LockResult {
40+
Success,
41+
ErrorWrite,
42+
ErrorLock,
43+
};
44+
[[nodiscard]] LockResult LockDirectory(const fs::path& directory, const fs::path& lockfile_name, bool probe_only = false);
45+
} // namespace util
3946
void UnlockDirectory(const fs::path& directory, const fs::path& lockfile_name);
40-
bool DirIsWritable(const fs::path& directory);
4147
bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes = 0);
4248

4349
/** Get the size of a file by scanning it.

src/util/getuniquepath.cpp

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/util/getuniquepath.h

Lines changed: 0 additions & 19 deletions
This file was deleted.

src/wallet/bdb.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ bool BerkeleyEnvironment::Open(bilingual_str& err)
149149

150150
fs::path pathIn = fs::PathFromString(strPath);
151151
TryCreateDirectories(pathIn);
152-
if (!LockDirectory(pathIn, ".walletlock")) {
152+
if (util::LockDirectory(pathIn, ".walletlock") != util::LockResult::Success) {
153153
LogPrintf("Cannot obtain a lock on wallet directory %s. Another instance may be using it.\n", strPath);
154154
err = strprintf(_("Error initializing wallet database environment %s!"), fs::quoted(fs::PathToString(Directory())));
155155
return false;

0 commit comments

Comments
 (0)