/usr/include/eiskaltdcpp/dcpp/MerkleCheckOutputStream.h is in libeiskaltdcpp-dev 2.2.9-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | /*
* Copyright (C) 2001-2012 Jacek Sieka, arnetheduck on gmail point com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "Streams.h"
#include "MerkleTree.h"
namespace dcpp {
template<class TreeType, bool managed>
class MerkleCheckOutputStream : public OutputStream {
public:
MerkleCheckOutputStream(const TreeType& aTree, OutputStream* aStream, int64_t start) : s(aStream), real(aTree), cur(aTree.getBlockSize()), verified(0), bufPos(0) {
// Only start at block boundaries
dcassert(start % aTree.getBlockSize() == 0);
cur.setFileSize(start);
size_t nBlocks = static_cast<size_t>(start / aTree.getBlockSize());
if(nBlocks > aTree.getLeaves().size()) {
dcdebug("Invalid tree / parameters");
return;
}
cur.getLeaves().insert(cur.getLeaves().begin(), aTree.getLeaves().begin(), aTree.getLeaves().begin() + nBlocks);
}
virtual ~MerkleCheckOutputStream() noexcept { if(managed) delete s; }
virtual size_t flush() throw(FileException) {
if (bufPos != 0)
cur.update(buf, bufPos);
bufPos = 0;
cur.finalize();
if(cur.getLeaves().size() == real.getLeaves().size()) {
if (cur.getRoot() != real.getRoot())
throw FileException(_("TTH inconsistency"));
} else {
checkTrees();
}
return s->flush();
}
void commitBytes(const void* b, size_t len) throw(FileException) {
uint8_t* xb = (uint8_t*)b;
size_t pos = 0;
if(bufPos != 0) {
size_t bytes = min(TreeType::BASE_BLOCK_SIZE - bufPos, len);
memcpy(buf + bufPos, xb, bytes);
pos = bytes;
bufPos += bytes;
if(bufPos == TreeType::BASE_BLOCK_SIZE) {
cur.update(buf, TreeType::BASE_BLOCK_SIZE);
bufPos = 0;
}
}
if(pos < len) {
dcassert(bufPos == 0);
size_t left = len - pos;
size_t part = left - (left % TreeType::BASE_BLOCK_SIZE);
if(part > 0) {
cur.update(xb + pos, part);
pos += part;
}
left = len - pos;
memcpy(buf, xb + pos, left);
bufPos = left;
}
}
virtual size_t write(const void* b, size_t len) throw(FileException) {
commitBytes(b, len);
checkTrees();
return s->write(b, len);
}
int64_t verifiedBytes() {
return min(real.getFileSize(), (int64_t)(cur.getBlockSize() * cur.getLeaves().size()));
}
private:
OutputStream* s;
TreeType real;
TreeType cur;
size_t verified;
uint8_t buf[TreeType::BASE_BLOCK_SIZE];
size_t bufPos;
void checkTrees() throw(FileException) {
while(cur.getLeaves().size() > verified) {
if(cur.getLeaves().size() > real.getLeaves().size() ||
!(cur.getLeaves()[verified] == real.getLeaves()[verified]))
{
throw FileException(_("TTH inconsistency"));
}
verified++;
}
}
};
} // namespace dcpp
|