Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2009-2010 Satoshi Nakamoto2// Copyright (c) 2009-present The Bitcoin Core developers3// Distributed under the MIT software license, see the accompanying4// file COPYING or http://www.opensource.org/licenses/mit-license.php.6#include <bitcoin-build-config.h> // IWYU pragma: keep8#include <util/fs_helpers.h>9#include <random.h>10#include <sync.h>11#include <tinyformat.h>12#include <util/byte_units.h>13#include <util/check.h>14#include <util/fs.h>15#include <util/log.h>16#include <util/syserror.h>18#include <cerrno>19#include <fstream>20#include <limits>21#include <map>22#include <memory>23#include <optional>24#include <stdexcept>25#include <string>26#include <system_error>27#include <utility>29#ifndef WIN3230#include <fcntl.h>31#include <sys/resource.h>32#include <sys/types.h>33#include <unistd.h>34#else35#include <io.h>36#include <shlobj.h>37#endif // WIN3239#ifdef __APPLE__40#include <sys/mount.h>41#include <sys/param.h>42#endif44/** Mutex to protect dir_locks. */45static GlobalMutex cs_dir_locks;46/** A map that contains all the currently held directory locks. After47* successful locking, these will be held here until the global destructor48* cleans them up and thus automatically unlocks them, or ReleaseDirectoryLocks49* is called.50*/51static std::map<std::string, std::unique_ptr<fsbridge::FileLock>> dir_locks GUARDED_BY(cs_dir_locks);52namespace util {53LockResult LockDirectory(const fs::path& directory, const fs::path& lockfile_name, bool probe_only)54{55LOCK(cs_dir_locks);56fs::path pathLockFile = directory / lockfile_name;58// If a lock for this directory already exists in the map, don't try to re-lock it59if (dir_locks.contains(fs::PathToString(pathLockFile))) {60return LockResult::Success;61}63// Create empty lock file if it doesn't exist.64if (auto created{fsbridge::fopen(pathLockFile, "a")}) {65std::fclose(created);66} else {67return LockResult::ErrorWrite;68}69auto lock = std::make_unique<fsbridge::FileLock>(pathLockFile);70if (!lock->TryLock()) {71LogError("Error while attempting to lock directory %s: %s\n", fs::PathToString(directory), lock->GetReason());72return LockResult::ErrorLock;73}74if (!probe_only) {75// Lock successful and we're not just probing, put it into the map76dir_locks.emplace(fs::PathToString(pathLockFile), std::move(lock));77}78return LockResult::Success;79}80} // namespace util81void UnlockDirectory(const fs::path& directory, const fs::path& lockfile_name)82{83LOCK(cs_dir_locks);84dir_locks.erase(fs::PathToString(directory / lockfile_name));85}87void ReleaseDirectoryLocks()88{89LOCK(cs_dir_locks);90dir_locks.clear();91}93bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes)94{95constexpr uint64_t min_disk_space{50_MiB};97uint64_t free_bytes_available = fs::space(dir).available;98return free_bytes_available >= min_disk_space + additional_bytes;99}101std::streampos GetFileSize(const char* path, std::streamsize max)102{103std::ifstream file{path, std::ios::binary};104file.ignore(max);105return file.gcount();106}108bool FileCommit(FILE* file)109{110if (fflush(file) != 0) { // harmless if redundantly called111LogError("fflush failed: %s", SysErrorString(errno));112return false;113}114#ifdef WIN32115HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));116if (FlushFileBuffers(hFile) == 0) {117LogError("FlushFileBuffers failed: %s", Win32ErrorString(GetLastError()));118return false;119}120#elif defined(__APPLE__) && defined(F_FULLFSYNC)121if (fcntl(fileno(file), F_FULLFSYNC, 0) == -1) { // Manpage says "value other than -1" is returned on success122LogError("fcntl F_FULLFSYNC failed: %s", SysErrorString(errno));123return false;124}125#elif HAVE_FDATASYNC126if (fdatasync(fileno(file)) != 0 && errno != EINVAL) { // Ignore EINVAL for filesystems that don't support sync127LogError("fdatasync failed: %s", SysErrorString(errno));128return false;129}130#else131if (fsync(fileno(file)) != 0 && errno != EINVAL) {132LogError("fsync failed: %s", SysErrorString(errno));133return false;134}135#endif136return true;137}139void DirectoryCommit(const fs::path& dirname)140{141#ifndef WIN32142FILE* file = fsbridge::fopen(dirname, "r");143if (file) {144fsync(fileno(file));145fclose(file);146}147#endif148}150bool TruncateFile(FILE* file, uint64_t length)151{152#if defined(WIN32)153return _chsize_s(_fileno(file), length) == 0;154#else155return ftruncate(fileno(file), length) == 0;156#endif157}159int RaiseFileDescriptorLimit(int min_fd)160{161Assert(min_fd >= 0);162#if defined(WIN32)163return 2048;164#else165struct rlimit limitFD;166if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {167// If the current soft limit is already higher, don't raise it168if (limitFD.rlim_cur != RLIM_INFINITY && std::cmp_less(limitFD.rlim_cur, min_fd)) {169const auto current_limit{limitFD.rlim_cur};170static_assert(std::in_range<rlim_t>(std::numeric_limits<int>::max()));171limitFD.rlim_cur = static_cast<rlim_t>(min_fd);172// Don't raise soft limit beyond hard limit173if ((limitFD.rlim_max != RLIM_INFINITY) && (limitFD.rlim_cur > limitFD.rlim_max)) {174limitFD.rlim_cur = limitFD.rlim_max;175}176if (current_limit != limitFD.rlim_cur) {177setrlimit(RLIMIT_NOFILE, &limitFD);178getrlimit(RLIMIT_NOFILE, &limitFD);179}180}181// Check the (possibly raised) current soft limit against the special182// value of RLIM_INFINITY. Some platforms implement this as the maximum183// uint64, others as int64 (-1). Avoid casting even if the return type184// is changed to uint64_t. We also cap unlikely but possible values185// that would overflow int.186if (limitFD.rlim_cur == RLIM_INFINITY ||187std::cmp_greater_equal(limitFD.rlim_cur, std::numeric_limits<int>::max())) {188return std::numeric_limits<int>::max();189}190return static_cast<int>(limitFD.rlim_cur);191}192return min_fd; // getrlimit failed, assume it's fine193#endif194}196/**197* this function tries to make a particular range of a file allocated (corresponding to disk space)198* it is advisory, and the range specified in the arguments will never contain live data199*/200void AllocateFileRange(FILE* file, uint64_t offset, unsigned int length)201{202#if defined(WIN32)203// Windows-specific version204HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));205LARGE_INTEGER nFileSize;206int64_t nEndPos = (int64_t)offset + length;207nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;208nFileSize.u.HighPart = nEndPos >> 32;209SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);210SetEndOfFile(hFile);211#elif defined(__APPLE__)212// OSX specific version213// NOTE: Contrary to other OS versions, the OSX version assumes that214// NOTE: offset is the size of the file.215fstore_t fst;216fst.fst_flags = F_ALLOCATECONTIG;217fst.fst_posmode = F_PEOFPOSMODE;218fst.fst_offset = 0;219fst.fst_length = length; // mac os fst_length takes the # of free bytes to allocate, not desired file size220fst.fst_bytesalloc = 0;221if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {222fst.fst_flags = F_ALLOCATEALL;223fcntl(fileno(file), F_PREALLOCATE, &fst);224}225ftruncate(fileno(file), static_cast<off_t>(offset) + length);226#else227#if defined(HAVE_POSIX_FALLOCATE)228// Version using posix_fallocate229off_t nEndPos = (off_t)offset + length;230if (0 == posix_fallocate(fileno(file), 0, nEndPos)) return;231#endif232// Fallback version233// TODO: just write one byte per block234static const char buf[65536] = {};235if (FileSeek64(file, offset, SEEK_SET)) {236return;237}238while (length > 0) {239unsigned int now = 65536;240if (length < now)241now = length;242fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway243length -= now;244}245#endif246}248#ifdef WIN32249fs::path GetSpecialFolderPath(int nFolder, bool fCreate)250{
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.