/root/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 | 143k | : m_file{file}, m_xor{std::move(data_xor)} |
14 | 143k | { |
15 | 143k | if (!IsNull()) { |
16 | 130k | auto pos{std::ftell(m_file)}; |
17 | 130k | if (pos >= 0) m_position = pos; |
18 | 130k | } |
19 | 143k | } |
20 | | |
21 | | std::size_t AutoFile::detail_fread(std::span<std::byte> dst) |
22 | 17.0M | { |
23 | 17.0M | if (!m_file) throw std::ios_base::failure("AutoFile::read: file handle is nullptr"); |
24 | 17.0M | size_t ret = std::fread(dst.data(), 1, dst.size(), m_file); |
25 | 17.0M | if (!m_xor.empty()) { |
26 | 524k | if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::read: position unknown"); |
27 | 524k | util::Xor(dst.subspan(0, ret), m_xor, *m_position); |
28 | 524k | } |
29 | 17.0M | if (m_position.has_value()) *m_position += ret; |
30 | 17.0M | return ret; |
31 | 17.0M | } |
32 | | |
33 | | void AutoFile::seek(int64_t offset, int origin) |
34 | 126 | { |
35 | 126 | if (IsNull()) { |
36 | 0 | throw std::ios_base::failure("AutoFile::seek: file handle is nullptr"); |
37 | 0 | } |
38 | 126 | 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 | 126 | if (origin == SEEK_SET) { |
42 | 55 | m_position = offset; |
43 | 71 | } else if (origin == SEEK_CUR && m_position.has_value()) { |
44 | 37 | *m_position += offset; |
45 | 37 | } else { |
46 | 34 | int64_t r{std::ftell(m_file)}; |
47 | 34 | if (r < 0) { |
48 | 0 | throw std::ios_base::failure("AutoFile::seek: ftell failed"); |
49 | 0 | } |
50 | 34 | m_position = r; |
51 | 34 | } |
52 | 126 | } |
53 | | |
54 | | int64_t AutoFile::tell() |
55 | 34 | { |
56 | 34 | if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::tell: position unknown"); |
57 | 34 | return *m_position; |
58 | 34 | } |
59 | | |
60 | | void AutoFile::read(std::span<std::byte> dst) |
61 | 16.7M | { |
62 | 16.7M | if (detail_fread(dst) != dst.size()) { |
63 | 1.97k | throw std::ios_base::failure(feof() ? "AutoFile::read: end of file" : "AutoFile::read: fread failed"); |
64 | 1.97k | } |
65 | 16.7M | } |
66 | | |
67 | | void AutoFile::ignore(size_t nSize) |
68 | 815 | { |
69 | 815 | if (!m_file) throw std::ios_base::failure("AutoFile::ignore: file handle is nullptr"); |
70 | 706 | unsigned char data[4096]; |
71 | 1.53k | while (nSize > 0) { |
72 | 1.13k | size_t nNow = std::min<size_t>(nSize, sizeof(data)); |
73 | 1.13k | if (std::fread(data, 1, nNow, m_file) != nNow) { |
74 | 298 | throw std::ios_base::failure(feof() ? "AutoFile::ignore: end of file" : "AutoFile::ignore: fread failed"); |
75 | 298 | } |
76 | 833 | nSize -= nNow; |
77 | 833 | if (m_position.has_value()) *m_position += nNow; |
78 | 833 | } |
79 | 706 | } |
80 | | |
81 | | void AutoFile::write(std::span<const std::byte> src) |
82 | 3.08M | { |
83 | 3.08M | if (!m_file) throw std::ios_base::failure("AutoFile::write: file handle is nullptr"); |
84 | 3.08M | if (m_xor.empty()) { |
85 | 899k | if (std::fwrite(src.data(), 1, src.size(), m_file) != src.size()) { |
86 | 1.54k | throw std::ios_base::failure("AutoFile::write: write failed"); |
87 | 1.54k | } |
88 | 898k | if (m_position.has_value()) *m_position += src.size(); |
89 | 2.18M | } else { |
90 | 2.18M | if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::write: position unknown"); |
91 | 2.18M | std::array<std::byte, 4096> buf; |
92 | 4.36M | while (src.size() > 0) { |
93 | 2.18M | auto buf_now{std::span{buf}.first(std::min<size_t>(src.size(), buf.size()))}; |
94 | 2.18M | std::copy(src.begin(), src.begin() + buf_now.size(), buf_now.begin()); |
95 | 2.18M | util::Xor(buf_now, m_xor, *m_position); |
96 | 2.18M | if (std::fwrite(buf_now.data(), 1, buf_now.size(), m_file) != buf_now.size()) { |
97 | 108 | throw std::ios_base::failure{"XorFile::write: failed"}; |
98 | 108 | } |
99 | 2.18M | src = src.subspan(buf_now.size()); |
100 | 2.18M | *m_position += buf_now.size(); |
101 | 2.18M | } |
102 | 2.18M | } |
103 | 3.08M | } |
104 | | |
105 | | bool AutoFile::Commit() |
106 | 0 | { |
107 | 0 | return ::FileCommit(m_file); |
108 | 0 | } |
109 | | |
110 | | bool AutoFile::Truncate(unsigned size) |
111 | 0 | { |
112 | 0 | return ::TruncateFile(m_file, size); |
113 | 0 | } |
114 | | |
115 | | size_t DataStream::GetMemoryUsage() const noexcept |
116 | 156k | { |
117 | 156k | return sizeof(*this) + memusage::DynamicUsage(vch); |
118 | 156k | } |