diff --git a/libtransmission/inout.c b/libtransmission/inout.c index c79db6f2e..22b22e3b8 100644 --- a/libtransmission/inout.c +++ b/libtransmission/inout.c @@ -221,7 +221,7 @@ tr_ioWrite( tr_torrent * tor, ***** ****/ -static int +static tr_errno tr_ioRecalculateHash( const tr_torrent * tor, int pieceIndex, uint8_t * setme ) @@ -244,7 +244,7 @@ tr_ioRecalculateHash( const tr_torrent * tor, while( bytesLeft > 0 ) { const int bytesThisPass = MIN( bytesLeft, (int)sizeof(buf) ); - int err = tr_ioRead( tor, pieceIndex, offset, bytesThisPass, buf ); + tr_errno err = tr_ioRead( tor, pieceIndex, offset, bytesThisPass, buf ); if( err ) return err; SHA1_Update( &sha, buf, bytesThisPass ); @@ -256,38 +256,19 @@ tr_ioRecalculateHash( const tr_torrent * tor, return 0; } -int +tr_errno tr_ioTestPiece( const tr_torrent * tor, int pieceIndex ) { + int err; uint8_t hash[SHA_DIGEST_LENGTH]; - const int ret = tr_ioRecalculateHash( tor, pieceIndex, hash ) - || memcmp( hash, tor->info.pieces[pieceIndex].hash, SHA_DIGEST_LENGTH ); + + err = tr_ioRecalculateHash( tor, pieceIndex, hash ); + + if( !err && memcmp( hash, tor->info.pieces[pieceIndex].hash, SHA_DIGEST_LENGTH ) ) + err = TR_ERROR; + tr_dbg ("torrent [%s] piece %d hash check: %s", - tor->info.name, pieceIndex, ( ret ? "FAILED" : "OK" )); - return ret; -} - -int -tr_ioHash( tr_torrent * tor, int pieceIndex ) -{ - int ret; - const int success = !tr_ioTestPiece( tor, pieceIndex ); - - if( success ) - { - tr_dbg( "Piece %d hash OK", pieceIndex ); - tr_cpPieceAdd( tor->completion, pieceIndex ); - ret = TR_OK; - } - else - { - tr_err( "Piece %d hash FAILED", pieceIndex ); - tr_cpPieceRem( tor->completion, pieceIndex ); - ret = TR_ERROR; - } - - tr_peerMgrSetBlame( tor->handle->peerMgr, tor->info.hash, - pieceIndex, success ); - - return ret; + tor->info.name, pieceIndex, ( err ? "FAILED" : "OK" )); + + return err; } diff --git a/libtransmission/inout.h b/libtransmission/inout.h index b2b0944cb..61bc2bc57 100644 --- a/libtransmission/inout.h +++ b/libtransmission/inout.h @@ -50,17 +50,11 @@ tr_errno tr_ioWrite ( struct tr_torrent * tor, const uint8_t * writeme ); /** - * returns true if the piece matches its metainfo's SHA1 checksum, - * false otherwise. + * returns 0 if the piece matches its metainfo's SHA1 checksum, + * or TR_ERROR_IO_* if there was a problem reading the piece, + * or TR_ERROR if the checksum didn't match. */ -int tr_ioTestPiece( const tr_torrent*, int piece ); - - -/** - * tests the specified piece and uses the results to - * update the torrent's "completion" and "blame" fields. - */ -int tr_ioHash ( tr_torrent*, int piece ); +tr_errno tr_ioTestPiece( const tr_torrent*, int piece ); #endif diff --git a/libtransmission/peer-msgs.c b/libtransmission/peer-msgs.c index 6ac4d527c..0ac5650bd 100644 --- a/libtransmission/peer-msgs.c +++ b/libtransmission/peer-msgs.c @@ -1455,14 +1455,16 @@ clientGotBlock( tr_peermsgs * msgs, if( tr_cpPieceIsComplete( tor->completion, req->index ) ) { - if( tr_ioHash( tor, req->index ) ) - { - gotBadPiece( msgs, req->index ); - return 0; - } + const tr_errno err = tr_ioTestPiece( tor, req->index ); + tr_torrentSetHasPiece( tor, req->index, !err ); tr_torrentSetPieceChecked( tor, req->index, TRUE ); - fireClientHave( msgs, req->index ); + tr_peerMgrSetBlame( tor->handle->peerMgr, tor->info.hash, req->index, !err ); + + if( !err ) + fireClientHave( msgs, req->index ); + else + gotBadPiece( msgs, req->index ); } return 0; diff --git a/libtransmission/verify.c b/libtransmission/verify.c index a5ce6a1de..6ff1f5cc8 100644 --- a/libtransmission/verify.c +++ b/libtransmission/verify.c @@ -90,8 +90,23 @@ checkFile( tr_torrent * tor, } else if( !tr_torrentIsPieceChecked( tor, i ) ) { - const int check = tr_ioTestPiece( tor, i ); - tr_torrentSetHasPiece( tor, i, !check ); + const tr_errno err = tr_ioTestPiece( tor, i ); + + if( !err ) /* yay */ + { + tr_torrentSetHasPiece( tor, i, TRUE ); + } + else + { + /* if we were wrong about it being complete, + * reset and start again. if we were right about + * it being incomplete, do nothing -- we don't + * want to lose blocks in those incomplete pieces */ + + if( tr_cpPieceIsComplete( tor->completion, i ) ) + tr_torrentSetHasPiece( tor, i, FALSE ); + } + tr_torrentSetPieceChecked( tor, i, TRUE ); } }