/Users/eugenesiegel/btc/bitcoin/src/streams.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2009-present The Bitcoin Core developers |
2 | | // Distributed under the MIT software license, see the accompanying |
3 | | // file COPYING or https://opensource.org/license/mit/. |
4 | | |
5 | | #include <memusage.h> |
6 | | #include <span.h> |
7 | | #include <streams.h> |
8 | | #include <util/fs_helpers.h> |
9 | | |
10 | | #include <array> |
11 | | |
12 | | AutoFile::AutoFile(std::FILE* file, std::vector<std::byte> data_xor) |
13 | 20.1M | : m_file{file}, m_xor{std::move(data_xor)} |
14 | 20.1M | { |
15 | 20.1M | if (!IsNull()) { |
16 | 20.1M | auto pos{std::ftell(m_file)}; |
17 | 20.1M | if (pos >= 0) m_position = pos; |
18 | 20.1M | } |
19 | 20.1M | } |
20 | | |
21 | | std::size_t AutoFile::detail_fread(std::span<std::byte> dst) |
22 | 152k | { |
23 | 152k | if (!m_file) throw std::ios_base::failure("AutoFile::read: file handle is nullptr")0 ; |
24 | 152k | size_t ret = std::fread(dst.data(), 1, dst.size(), m_file); |
25 | 152k | if (!m_xor.empty()) { |
26 | 152k | if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::read: position unknown")0 ; |
27 | 152k | util::Xor(dst.subspan(0, ret), m_xor, *m_position); |
28 | 152k | } |
29 | 152k | if (m_position.has_value()) *m_position += ret; |
30 | 152k | return ret; |
31 | 152k | } |
32 | | |
33 | | void AutoFile::seek(int64_t offset, int origin) |
34 | 0 | { |
35 | 0 | if (IsNull()) { |
36 | 0 | throw std::ios_base::failure("AutoFile::seek: file handle is nullptr"); |
37 | 0 | } |
38 | 0 | if (std::fseek(m_file, offset, origin) != 0) { |
39 | 0 | throw std::ios_base::failure(feof() ? "AutoFile::seek: end of file" : "AutoFile::seek: fseek failed"); |
40 | 0 | } |
41 | 0 | if (origin == SEEK_SET) { |
42 | 0 | m_position = offset; |
43 | 0 | } else if (origin == SEEK_CUR && m_position.has_value()) { |
44 | 0 | *m_position += offset; |
45 | 0 | } else { |
46 | 0 | int64_t r{std::ftell(m_file)}; |
47 | 0 | if (r < 0) { |
48 | 0 | throw std::ios_base::failure("AutoFile::seek: ftell failed"); |
49 | 0 | } |
50 | 0 | m_position = r; |
51 | 0 | } |
52 | 0 | } |
53 | | |
54 | | int64_t AutoFile::tell() |
55 | 0 | { |
56 | 0 | if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::tell: position unknown"); |
57 | 0 | return *m_position; |
58 | 0 | } |
59 | | |
60 | | void AutoFile::read(std::span<std::byte> dst) |
61 | 152k | { |
62 | 152k | if (detail_fread(dst) != dst.size()) { |
63 | 0 | throw std::ios_base::failure(feof() ? "AutoFile::read: end of file" : "AutoFile::read: fread failed"); |
64 | 0 | } |
65 | 152k | } |
66 | | |
67 | | void AutoFile::ignore(size_t nSize) |
68 | 0 | { |
69 | 0 | if (!m_file) throw std::ios_base::failure("AutoFile::ignore: file handle is nullptr"); |
70 | 0 | unsigned char data[4096]; |
71 | 0 | while (nSize > 0) { |
72 | 0 | size_t nNow = std::min<size_t>(nSize, sizeof(data)); |
73 | 0 | if (std::fread(data, 1, nNow, m_file) != nNow) { |
74 | 0 | throw std::ios_base::failure(feof() ? "AutoFile::ignore: end of file" : "AutoFile::ignore: fread failed"); |
75 | 0 | } |
76 | 0 | nSize -= nNow; |
77 | 0 | if (m_position.has_value()) *m_position += nNow; |
78 | 0 | } |
79 | 0 | } |
80 | | |
81 | | void AutoFile::write(std::span<const std::byte> src) |
82 | 49.9k | { |
83 | 49.9k | if (!m_file) throw std::ios_base::failure("AutoFile::write: file handle is nullptr")0 ; |
84 | 49.9k | if (m_xor.empty()) { |
85 | 49.9k | if (std::fwrite(src.data(), 1, src.size(), m_file) != src.size()) { |
86 | 0 | throw std::ios_base::failure("AutoFile::write: write failed"); |
87 | 0 | } |
88 | 49.9k | if (m_position.has_value()) *m_position += src.size(); |
89 | 49.9k | } else { |
90 | 0 | std::array<std::byte, 4096> buf; |
91 | 0 | while (src.size()) { |
92 | 0 | auto buf_now{std::span{buf}.first(std::min<size_t>(src.size(), buf.size()))}; |
93 | 0 | std::copy_n(src.begin(), buf_now.size(), buf_now.begin()); |
94 | 0 | write_buffer(buf_now); |
95 | 0 | src = src.subspan(buf_now.size()); |
96 | 0 | } |
97 | 0 | } |
98 | 49.9k | } |
99 | | |
100 | | void AutoFile::write_buffer(std::span<std::byte> src) |
101 | 20.0M | { |
102 | 20.0M | if (!m_file) throw std::ios_base::failure("AutoFile::write_buffer: file handle is nullptr")0 ; |
103 | 20.0M | if (m_xor.size()) { |
104 | 20.0M | if (!m_position) throw std::ios_base::failure("AutoFile::write_buffer: obfuscation position unknown")0 ; |
105 | 20.0M | util::Xor(src, m_xor, *m_position); // obfuscate in-place |
106 | 20.0M | } |
107 | 20.0M | if (std::fwrite(src.data(), 1, src.size(), m_file) != src.size()) { |
108 | 0 | throw std::ios_base::failure("AutoFile::write_buffer: write failed"); |
109 | 0 | } |
110 | 20.0M | if (m_position) *m_position += src.size(); |
111 | 20.0M | } |
112 | | |
113 | | bool AutoFile::Commit() |
114 | 0 | { |
115 | 0 | return ::FileCommit(m_file); |
116 | 0 | } |
117 | | |
118 | | bool AutoFile::Truncate(unsigned size) |
119 | 0 | { |
120 | 0 | return ::TruncateFile(m_file, size); |
121 | 0 | } |
122 | | |
123 | | size_t DataStream::GetMemoryUsage() const noexcept |
124 | 1.19M | { |
125 | 1.19M | return sizeof(*this) + memusage::DynamicUsage(vch); |
126 | 1.19M | } |