Inside Bitcoin
Opening the selected file…
Inside Bitcoin
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.
251throw OSError("invalid_mode", 0);252}254if (mode[0] == 'w') {255md = _O_WRONLY;256}257else if (mode[0] == 'r') {258md = _O_RDONLY;259}260else {261throw OSError("file_from_handle", 0);262}264int os_fhandle = _open_osfhandle((intptr_t)h, md);265if (os_fhandle == -1) {266CloseHandle(h);267throw OSError("_open_osfhandle", 0);268}270FILE *fp = _fdopen(os_fhandle, mode);271if (fp == 0) {272subprocess_close(os_fhandle);273throw OSError("_fdopen", 0);274}276return fp;277}279inline void configure_pipe(HANDLE* read_handle, HANDLE* write_handle, HANDLE* child_handle)280{281SECURITY_ATTRIBUTES saAttr;283// Set the bInheritHandle flag so pipe handles are inherited.284saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);285saAttr.bInheritHandle = TRUE;286saAttr.lpSecurityDescriptor = NULL;288// Create a pipe for the child process's STDIN.289if (!CreatePipe(read_handle, write_handle, &saAttr,0))290throw OSError("CreatePipe", 0);292// Ensure the write handle to the pipe for STDIN is not inherited.293if (!SetHandleInformation(*child_handle, HANDLE_FLAG_INHERIT, 0))294throw OSError("SetHandleInformation", 0);295}296#endif298/*!299* Function: split300* Parameters:301* [in] str : Input string which needs to be split based upon the302* delimiters provided.303* [in] deleims : Delimiter characters based upon which the string needs304* to be split. Default constructed to ' '(space) and '\t'(tab)305* [out] vector<string> : Vector of strings split at deleimiter.306*/307static inline std::vector<std::string>308split(const std::string& str, const std::string& delims=" \t")309{310std::vector<std::string> res;311size_t init = 0;313while (true) {314auto pos = str.find_first_of(delims, init);315if (pos == std::string::npos) {316res.emplace_back(str.substr(init, str.length()));317break;318}319res.emplace_back(str.substr(init, pos - init));320pos++;321init = pos;322}324return res;325}328#ifndef WIN32329/*!330* Function: set_clo_on_exec331* Sets/Resets the FD_CLOEXEC flag on the provided file descriptor332* based upon the `set` parameter.333* Parameters:334* [in] fd : The descriptor on which FD_CLOEXEC needs to be set/reset.335* [in] set : If 'true', set FD_CLOEXEC.336* If 'false' unset FD_CLOEXEC.337*/338static inline339void set_clo_on_exec(int fd, bool set = true)340{341int flags = fcntl(fd, F_GETFD, 0);342if (flags == -1) {343throw OSError("fcntl F_GETFD failed", errno);344}345if (set) flags |= FD_CLOEXEC;346else flags &= ~FD_CLOEXEC;347if (fcntl(fd, F_SETFD, flags) == -1) {348throw OSError("fcntl F_SETFD failed", errno);349}350}353/*!354* Function: pipe_cloexec355* Creates a pipe and sets FD_CLOEXEC flag on both356* read and write descriptors of the pipe.357* Parameters:358* [out] : A pair of file descriptors.359* First element of pair is the read descriptor of pipe.360* Second element is the write descriptor of pipe.361*/362static inline363std::pair<int, int> pipe_cloexec() noexcept(false)364{365int pipe_fds[2];366int res = pipe(pipe_fds);367if (res) {368throw OSError("pipe failure", errno);369}371set_clo_on_exec(pipe_fds[0]);372set_clo_on_exec(pipe_fds[1]);374return std::make_pair(pipe_fds[0], pipe_fds[1]);375}376#endif379/*!380* Function: write_n381* Writes `length` bytes to the file descriptor `fd`382* from the buffer `buf`.383* Parameters:384* [in] fd : The file descriptotr to write to.385* [in] buf: Buffer from which data needs to be written to fd.386* [in] length: The number of bytes that needs to be written from387* `buf` to `fd`.388* [out] int : Number of bytes written or -1 in case of failure.389*/390static inline391int write_n(int fd, const char* buf, size_t length)392{393size_t nwritten = 0;394while (nwritten < length) {395int written = subprocess_write(fd, buf + nwritten, length - nwritten);396if (written == -1) return -1;397nwritten += written;398}399return nwritten;400}403/*!404* Function: read_atmost_n405* Reads at the most `read_upto` bytes from the406* file object `fp` before returning.407* Parameters:408* [in] fp : The file object from which it needs to read.409* [in] buf : The buffer into which it needs to write the data.410* [in] read_upto: Max number of bytes which must be read from `fd`.411* [out] int : Number of bytes written to `buf` or read from `fd`412* OR -1 in case of error.413* NOTE: In case of EINTR while reading from socket, this API414* will retry to read from `fd`, but only till the EINTR counter415* reaches 50 after which it will return with whatever data it read.416*/417static inline418int read_atmost_n(FILE* fp, char* buf, size_t read_upto)419{420#ifdef WIN32421return (int)fread(buf, 1, read_upto, fp);422#else423int fd = subprocess_fileno(fp);424int rbytes = 0;425int eintr_cnter = 0;427while (1) {428int read_bytes = read(fd, buf + rbytes, read_upto - rbytes);429if (read_bytes == -1) {430if (errno == EINTR) {431if (eintr_cnter >= 50) return -1;432eintr_cnter++;433continue;434}435return -1;436}437if (read_bytes == 0) return rbytes;439rbytes += read_bytes;440}441return rbytes;442#endif443}446/*!447* Function: read_all448* Reads all the available data from `fp` into449* `buf`. Internally calls read_atmost_n.450* Parameters:451* [in] fp : The file object from which to read from.452* [in] buf : The buffer of type `class Buffer` into which453* the read data is written to.454* [out] int: Number of bytes read OR -1 in case of failure.455*456* NOTE: `class Buffer` is a exposed public class. See below.457*/459static inline int read_all(FILE* fp, std::vector<char>& buf)460{461auto buffer = buf.data();462int total_bytes_read = 0;463int fill_sz = buf.size();465while (1) {466const int rd_bytes = read_atmost_n(fp, buffer, fill_sz);468if (rd_bytes == -1) { // Read finished469if (total_bytes_read == 0) return -1;470break;472} else if (rd_bytes == fill_sz) { // Buffer full473const auto orig_sz = buf.size();474const auto new_sz = orig_sz * 2;475buf.resize(new_sz);476fill_sz = new_sz - orig_sz;478//update the buffer pointer479buffer = buf.data();480total_bytes_read += rd_bytes;481buffer += total_bytes_read;483} else { // Partial data ? Continue reading484total_bytes_read += rd_bytes;485fill_sz -= rd_bytes;486break;487}488}489buf.erase(buf.begin()+total_bytes_read, buf.end()); // remove extra nulls490return total_bytes_read;491}493#ifndef WIN32494/*!495* Function: wait_for_child_exit496* Waits for the process with pid `pid` to exit497* and returns its status.498* Parameters:499* [in] pid : The pid of the process.500* [out] pair<int, int>:
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.