File indexing completed on 2025-01-05 04:37:09

0001 /*
0002     SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 #include "singledatachecker.h"
0007 #include <klocalizedstring.h>
0008 #include <torrent/globals.h>
0009 #include <torrent/torrent.h>
0010 #include <util/array.h>
0011 #include <util/error.h>
0012 #include <util/file.h>
0013 #include <util/functions.h>
0014 #include <util/log.h>
0015 
0016 namespace bt
0017 {
0018 SingleDataChecker::SingleDataChecker(bt::Uint32 from, bt::Uint32 to)
0019     : DataChecker(from, to)
0020 {
0021 }
0022 
0023 SingleDataChecker::~SingleDataChecker()
0024 {
0025 }
0026 
0027 void SingleDataChecker::check(const QString &path, const Torrent &tor, const QString &, const BitSet &current_status)
0028 {
0029     // open the file
0030     Uint32 num_chunks = tor.getNumChunks();
0031     Uint32 chunk_size = tor.getChunkSize();
0032     File fptr;
0033     if (!fptr.open(path, "rb")) {
0034         throw Error(i18n("Cannot open file %1: %2", path, fptr.errorString()));
0035     }
0036 
0037     if (from >= tor.getNumChunks())
0038         from = 0;
0039     if (to >= tor.getNumChunks())
0040         to = tor.getNumChunks() - 1;
0041 
0042     // initialize the bitset
0043     result = BitSet(num_chunks);
0044     // loop over all chunks
0045     Array<Uint8> buf(chunk_size);
0046     TimeStamp last_emitted = bt::Now();
0047     for (Uint32 i = from; i <= to && !need_to_stop; i++) {
0048         if (!fptr.eof()) {
0049             // read the chunk
0050             Uint32 size = i == num_chunks - 1 ? tor.getLastChunkSize() : tor.getChunkSize();
0051 
0052             fptr.seek(File::BEGIN, (Int64)i * tor.getChunkSize());
0053             fptr.read(buf, size);
0054             // generate and test hash
0055             SHA1Hash h = SHA1Hash::generate(buf, size);
0056             bool ok = (h == tor.getHash(i));
0057             result.set(i, ok);
0058             if (ok && current_status.get(i))
0059                 downloaded++;
0060             else if (!ok && current_status.get(i))
0061                 failed++;
0062             else if (!ok && !current_status.get(i))
0063                 not_downloaded++;
0064             else if (ok && !current_status.get(i))
0065                 found++;
0066         } else {
0067             // at end of file so set to default values for a failed chunk
0068             result.set(i, false);
0069             if (!current_status.get(i))
0070                 not_downloaded++;
0071             else
0072                 failed++;
0073         }
0074 
0075         TimeStamp now = Now();
0076         if (now - last_emitted > 1000 || i == num_chunks - 1) { // Emit signals once every second
0077             status(failed, found, downloaded, not_downloaded);
0078             progress(i - from, from - to + 1);
0079             last_emitted = now;
0080         }
0081     }
0082 
0083     status(failed, found, downloaded, not_downloaded);
0084 }
0085 
0086 }