Line | Count | Source |
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 | | #include <util/obfuscation.h> |
10 | | |
11 | | #include <array> |
12 | | |
13 | 1.22k | AutoFile::AutoFile(std::FILE* file, const Obfuscation& obfuscation) : m_file{file}, m_obfuscation{obfuscation} |
14 | 1.22k | { |
15 | 1.22k | if (!IsNull()) { Branch (15:9): [True: 1.22k, False: 0]
|
16 | 1.22k | auto pos{std::ftell(m_file)}; |
17 | 1.22k | if (pos >= 0) m_position = pos; Branch (17:13): [True: 1.22k, False: 0]
|
18 | 1.22k | } |
19 | 1.22k | } |
20 | | |
21 | | std::size_t AutoFile::detail_fread(std::span<std::byte> dst) |
22 | 0 | { |
23 | 0 | if (!m_file) throw std::ios_base::failure("AutoFile::read: file handle is nullptr"); Branch (23:9): [True: 0, False: 0]
|
24 | 0 | const size_t ret = std::fread(dst.data(), 1, dst.size(), m_file); |
25 | 0 | if (m_obfuscation) { Branch (25:9): [True: 0, False: 0]
|
26 | 0 | if (!m_position) throw std::ios_base::failure("AutoFile::read: position unknown"); Branch (26:13): [True: 0, False: 0]
|
27 | 0 | m_obfuscation(dst.subspan(0, ret), *m_position); |
28 | 0 | } |
29 | 0 | if (m_position) *m_position += ret; Branch (29:9): [True: 0, False: 0]
|
30 | 0 | return ret; |
31 | 0 | } |
32 | | |
33 | | void AutoFile::seek(int64_t offset, int origin) |
34 | 0 | { |
35 | 0 | if (IsNull()) { Branch (35:9): [True: 0, False: 0]
|
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) { Branch (38:9): [True: 0, False: 0]
|
39 | 0 | throw std::ios_base::failure(feof() ? "AutoFile::seek: end of file" : "AutoFile::seek: fseek failed"); Branch (39:38): [True: 0, False: 0]
|
40 | 0 | } |
41 | 0 | if (origin == SEEK_SET) { Branch (41:9): [True: 0, False: 0]
|
42 | 0 | m_position = offset; |
43 | 0 | } else if (origin == SEEK_CUR && m_position.has_value()) { Branch (43:16): [True: 0, False: 0]
Branch (43:38): [True: 0, False: 0]
|
44 | 0 | *m_position += offset; |
45 | 0 | } else { |
46 | 0 | int64_t r{std::ftell(m_file)}; |
47 | 0 | if (r < 0) { Branch (47:13): [True: 0, False: 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"); Branch (56:9): [True: 0, False: 0]
|
57 | 0 | return *m_position; |
58 | 0 | } |
59 | | |
60 | | int64_t AutoFile::size() |
61 | 0 | { |
62 | 0 | if (IsNull()) { Branch (62:9): [True: 0, False: 0]
|
63 | 0 | throw std::ios_base::failure("AutoFile::size: file handle is nullptr"); |
64 | 0 | } |
65 | | // Temporarily save the current position |
66 | 0 | int64_t current_pos = tell(); |
67 | 0 | seek(0, SEEK_END); |
68 | 0 | int64_t file_size = tell(); |
69 | | // Restore the original position |
70 | 0 | seek(current_pos, SEEK_SET); |
71 | 0 | return file_size; |
72 | 0 | } |
73 | | |
74 | | void AutoFile::read(std::span<std::byte> dst) |
75 | 0 | { |
76 | 0 | if (detail_fread(dst) != dst.size()) { Branch (76:9): [True: 0, False: 0]
|
77 | 0 | throw std::ios_base::failure(feof() ? "AutoFile::read: end of file" : "AutoFile::read: fread failed"); Branch (77:38): [True: 0, False: 0]
|
78 | 0 | } |
79 | 0 | } |
80 | | |
81 | | void AutoFile::ignore(size_t nSize) |
82 | 0 | { |
83 | 0 | if (!m_file) throw std::ios_base::failure("AutoFile::ignore: file handle is nullptr"); Branch (83:9): [True: 0, False: 0]
|
84 | 0 | unsigned char data[4096]; |
85 | 0 | while (nSize > 0) { Branch (85:12): [True: 0, False: 0]
|
86 | 0 | size_t nNow = std::min<size_t>(nSize, sizeof(data)); |
87 | 0 | if (std::fread(data, 1, nNow, m_file) != nNow) { Branch (87:13): [True: 0, False: 0]
|
88 | 0 | throw std::ios_base::failure(feof() ? "AutoFile::ignore: end of file" : "AutoFile::ignore: fread failed"); Branch (88:42): [True: 0, False: 0]
|
89 | 0 | } |
90 | 0 | nSize -= nNow; |
91 | 0 | if (m_position.has_value()) *m_position += nNow; Branch (91:13): [True: 0, False: 0]
|
92 | 0 | } |
93 | 0 | } |
94 | | |
95 | | void AutoFile::write(std::span<const std::byte> src) |
96 | 12.1M | { |
97 | 12.1M | if (!m_file) throw std::ios_base::failure("AutoFile::write: file handle is nullptr"); Branch (97:9): [True: 0, False: 12.1M]
|
98 | 12.1M | if (!m_obfuscation) { Branch (98:9): [True: 12.1M, False: 915]
|
99 | 12.1M | if (std::fwrite(src.data(), 1, src.size(), m_file) != src.size()) { Branch (99:13): [True: 0, False: 12.1M]
|
100 | 0 | throw std::ios_base::failure("AutoFile::write: write failed"); |
101 | 0 | } |
102 | 12.1M | m_was_written = true; |
103 | 12.1M | if (m_position.has_value()) *m_position += src.size(); Branch (103:13): [True: 12.1M, False: 0]
|
104 | 12.1M | } else { |
105 | 915 | std::array<std::byte, 4096> buf; |
106 | 1.83k | while (src.size()) { Branch (106:16): [True: 915, False: 915]
|
107 | 915 | auto buf_now{std::span{buf}.first(std::min<size_t>(src.size(), buf.size()))}; |
108 | 915 | std::copy_n(src.begin(), buf_now.size(), buf_now.begin()); |
109 | 915 | write_buffer(buf_now); |
110 | 915 | src = src.subspan(buf_now.size()); |
111 | 915 | } |
112 | 915 | } |
113 | 12.1M | } |
114 | | |
115 | | void AutoFile::write_buffer(std::span<std::byte> src) |
116 | 915 | { |
117 | 915 | if (!m_file) throw std::ios_base::failure("AutoFile::write_buffer: file handle is nullptr"); Branch (117:9): [True: 0, False: 915]
|
118 | 915 | if (m_obfuscation) { Branch (118:9): [True: 915, False: 0]
|
119 | 915 | if (!m_position) throw std::ios_base::failure("AutoFile::write_buffer: obfuscation position unknown"); Branch (119:13): [True: 0, False: 915]
|
120 | 915 | m_obfuscation(src, *m_position); // obfuscate in-place |
121 | 915 | } |
122 | 915 | if (std::fwrite(src.data(), 1, src.size(), m_file) != src.size()) { Branch (122:9): [True: 0, False: 915]
|
123 | 0 | throw std::ios_base::failure("AutoFile::write_buffer: write failed"); |
124 | 0 | } |
125 | 915 | m_was_written = true; |
126 | 915 | if (m_position) *m_position += src.size(); Branch (126:9): [True: 915, False: 0]
|
127 | 915 | } |
128 | | |
129 | | bool AutoFile::Commit() |
130 | 915 | { |
131 | 915 | return ::FileCommit(m_file); |
132 | 915 | } |
133 | | |
134 | | bool AutoFile::Truncate(unsigned size) |
135 | 0 | { |
136 | 0 | m_was_written = true; |
137 | 0 | return ::TruncateFile(m_file, size); |
138 | 0 | } |
139 | | |
140 | | size_t DataStream::GetMemoryUsage() const noexcept |
141 | 0 | { |
142 | 0 | return sizeof(*this) + memusage::DynamicUsage(vch); |
143 | 0 | } |