static int checkFile( tr_torrent * tor, tr_file_index_t fileIndex, int * abortFlag ) { tr_piece_index_t i; int changed = FALSE; int nofile; struct stat sb; char * path; const tr_file * file = &tor->info.files[fileIndex]; path = tr_buildPath( tor->downloadDir, file->name, NULL ); nofile = stat( path, &sb ) || !S_ISREG( sb.st_mode ); for( i = file->firstPiece; i <= file->lastPiece && i < tor->info.pieceCount && ( !*abortFlag ); ++i ) { if( nofile ) { tr_torrentSetHasPiece( tor, i, 0 ); } else if( !tr_torrentIsPieceChecked( tor, i ) ) { const int wasComplete = tr_cpPieceIsComplete( tor->completion, i ); if( tr_ioTestPiece( tor, i ) ) /* yay */ { tr_torrentSetHasPiece( tor, i, TRUE ); if( !wasComplete ) changed = 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( wasComplete ) { tr_torrentSetHasPiece( tor, i, FALSE ); changed = TRUE; } } } tr_torrentSetPieceChecked( tor, i, TRUE ); } tr_free( path ); return changed; }
static uint64_t parseProgress( tr_torrent * tor, const uint8_t * buf, uint32_t len ) { uint64_t ret = 0; if( len == FR_PROGRESS_LEN( tor ) ) { int i; int n; tr_bitfield bitfield; /* compare file mtimes */ tr_time_t * curMTimes = getMTimes( tor, &n ); const uint8_t * walk = buf; tr_time_t mtime; for( i = 0; i < n; ++i ) { readBytes( &mtime, &walk, sizeof( tr_time_t ) ); if( curMTimes[i] == mtime ) tr_torrentSetFileChecked( tor, i, TRUE ); else { tr_torrentSetFileChecked( tor, i, FALSE ); tr_tordbg( tor, "Torrent needs to be verified" ); } } free( curMTimes ); /* get the completion bitfield */ memset( &bitfield, 0, sizeof bitfield ); bitfield.byteCount = FR_BLOCK_BITFIELD_LEN( tor ); bitfield.bitCount = bitfield.byteCount * 8; bitfield.bits = (uint8_t*) walk; if( tr_cpBlockBitfieldSet( tor->completion, &bitfield ) ) ret = TR_FR_PROGRESS; else { tr_torrentUncheck( tor ); tr_tordbg( tor, "Torrent needs to be verified" ); } } /* the files whose mtimes are wrong, remove from completion pending a recheck... */ { tr_piece_index_t i; for( i = 0; i < tor->info.pieceCount; ++i ) if( !tr_torrentIsPieceChecked( tor, i ) ) tr_cpPieceRem( tor->completion, i ); } return ret; }