Transmission 2.33
[tomato.git] / release / src / router / transmission / libtransmission / torrent.c
blobadf4aacb451b629c5a1375cde66894ac6c0d3f72
1 /*
2 * This file Copyright (C) Mnemosyne LLC
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
10 * $Id: torrent.c 12540 2011-07-10 17:34:03Z jordan $
13 #include <signal.h> /* signal() */
14 #include <sys/types.h> /* stat */
15 #include <sys/stat.h> /* stat */
16 #ifndef WIN32
17 #include <sys/wait.h> /* wait() */
18 #else
19 #include <process.h>
20 #define waitpid(pid, status, options) _cwait(status, pid, WAIT_CHILD)
21 #endif
22 #include <unistd.h> /* stat */
23 #include <dirent.h>
25 #include <assert.h>
26 #include <math.h>
27 #include <stdarg.h>
28 #include <string.h> /* memcmp */
29 #include <stdlib.h> /* qsort */
30 #include <stdio.h> /* remove() */
32 #include <event2/util.h> /* evutil_vsnprintf() */
34 #include "transmission.h"
35 #include "announcer.h"
36 #include "bandwidth.h"
37 #include "bencode.h"
38 #include "cache.h"
39 #include "completion.h"
40 #include "crypto.h" /* for tr_sha1 */
41 #include "resume.h"
42 #include "fdlimit.h" /* tr_fdTorrentClose */
43 #include "inout.h" /* tr_ioTestPiece() */
44 #include "magnet.h"
45 #include "metainfo.h"
46 #include "peer-common.h" /* MAX_BLOCK_SIZE */
47 #include "peer-mgr.h"
48 #include "platform.h" /* TR_PATH_DELIMITER_STR */
49 #include "ptrarray.h"
50 #include "session.h"
51 #include "torrent.h"
52 #include "torrent-magnet.h"
53 #include "trevent.h" /* tr_runInEventThread() */
54 #include "utils.h"
55 #include "verify.h"
56 #include "version.h"
58 /***
59 ****
60 ***/
62 #define tr_deeplog_tor( tor, ... ) \
63 do { \
64 if( tr_deepLoggingIsActive( ) ) \
65 tr_deepLog( __FILE__, __LINE__, tr_torrentName( tor ), __VA_ARGS__ ); \
66 } while( 0 )
68 /***
69 ****
70 ***/
72 const char *
73 tr_torrentName( const tr_torrent * tor )
75 assert( tr_isTorrent( tor ) );
77 return tor->info.name;
80 int
81 tr_torrentId( const tr_torrent * tor )
83 return tor->uniqueId;
86 tr_torrent*
87 tr_torrentFindFromId( tr_session * session, int id )
89 tr_torrent * tor = NULL;
91 while(( tor = tr_torrentNext( session, tor )))
92 if( tor->uniqueId == id )
93 return tor;
95 return NULL;
98 tr_torrent*
99 tr_torrentFindFromHashString( tr_session * session, const char * str )
101 tr_torrent * tor = NULL;
103 while(( tor = tr_torrentNext( session, tor )))
104 if( !evutil_ascii_strcasecmp( str, tor->info.hashString ) )
105 return tor;
107 return NULL;
110 tr_torrent*
111 tr_torrentFindFromHash( tr_session * session, const uint8_t * torrentHash )
113 tr_torrent * tor = NULL;
115 while(( tor = tr_torrentNext( session, tor )))
116 if( *tor->info.hash == *torrentHash )
117 if( !memcmp( tor->info.hash, torrentHash, SHA_DIGEST_LENGTH ) )
118 return tor;
120 return NULL;
123 tr_torrent*
124 tr_torrentFindFromMagnetLink( tr_session * session, const char * magnet )
126 tr_magnet_info * info;
127 tr_torrent * tor = NULL;
129 if(( info = tr_magnetParse( magnet )))
131 tor = tr_torrentFindFromHash( session, info->hash );
132 tr_magnetFree( info );
135 return tor;
138 tr_torrent*
139 tr_torrentFindFromObfuscatedHash( tr_session * session,
140 const uint8_t * obfuscatedTorrentHash )
142 tr_torrent * tor = NULL;
144 while(( tor = tr_torrentNext( session, tor )))
145 if( !memcmp( tor->obfuscatedHash, obfuscatedTorrentHash,
146 SHA_DIGEST_LENGTH ) )
147 return tor;
149 return NULL;
152 bool
153 tr_torrentIsPieceTransferAllowed( const tr_torrent * tor,
154 tr_direction direction )
156 int limit;
157 bool allowed = true;
159 if( tr_torrentUsesSpeedLimit( tor, direction ) )
160 if( tr_torrentGetSpeedLimit_Bps( tor, direction ) <= 0 )
161 allowed = false;
163 if( tr_torrentUsesSessionLimits( tor ) )
164 if( tr_sessionGetActiveSpeedLimit_Bps( tor->session, direction, &limit ) )
165 if( limit <= 0 )
166 allowed = false;
168 return allowed;
171 /***
172 **** PER-TORRENT UL / DL SPEEDS
173 ***/
175 void
176 tr_torrentSetSpeedLimit_Bps( tr_torrent * tor, tr_direction dir, int Bps )
178 assert( tr_isTorrent( tor ) );
179 assert( tr_isDirection( dir ) );
180 assert( Bps >= 0 );
182 if( tr_bandwidthSetDesiredSpeed_Bps( &tor->bandwidth, dir, Bps ) )
183 tr_torrentSetDirty( tor );
185 void
186 tr_torrentSetSpeedLimit_KBps( tr_torrent * tor, tr_direction dir, int KBps )
188 tr_torrentSetSpeedLimit_Bps( tor, dir, toSpeedBytes( KBps ) );
192 tr_torrentGetSpeedLimit_Bps( const tr_torrent * tor, tr_direction dir )
194 assert( tr_isTorrent( tor ) );
195 assert( tr_isDirection( dir ) );
197 return tr_bandwidthGetDesiredSpeed_Bps( &tor->bandwidth, dir );
200 tr_torrentGetSpeedLimit_KBps( const tr_torrent * tor, tr_direction dir )
202 return toSpeedKBps( tr_torrentGetSpeedLimit_Bps( tor, dir ) );
205 void
206 tr_torrentUseSpeedLimit( tr_torrent * tor, tr_direction dir, bool do_use )
208 assert( tr_isTorrent( tor ) );
209 assert( tr_isDirection( dir ) );
211 if( tr_bandwidthSetLimited( &tor->bandwidth, dir, do_use ) )
212 tr_torrentSetDirty( tor );
215 bool
216 tr_torrentUsesSpeedLimit( const tr_torrent * tor, tr_direction dir )
218 assert( tr_isTorrent( tor ) );
219 assert( tr_isDirection( dir ) );
221 return tr_bandwidthIsLimited( &tor->bandwidth, dir );
224 void
225 tr_torrentUseSessionLimits( tr_torrent * tor, bool doUse )
227 bool changed;
229 assert( tr_isTorrent( tor ) );
231 changed = tr_bandwidthHonorParentLimits( &tor->bandwidth, TR_UP, doUse );
232 changed |= tr_bandwidthHonorParentLimits( &tor->bandwidth, TR_DOWN, doUse );
234 if( changed )
235 tr_torrentSetDirty( tor );
238 bool
239 tr_torrentUsesSessionLimits( const tr_torrent * tor )
241 assert( tr_isTorrent( tor ) );
243 return tr_bandwidthAreParentLimitsHonored( &tor->bandwidth, TR_UP );
246 /***
247 ****
248 ***/
250 void
251 tr_torrentSetRatioMode( tr_torrent * tor, tr_ratiolimit mode )
253 assert( tr_isTorrent( tor ) );
254 assert( mode==TR_RATIOLIMIT_GLOBAL || mode==TR_RATIOLIMIT_SINGLE || mode==TR_RATIOLIMIT_UNLIMITED );
256 if( mode != tor->ratioLimitMode )
258 tor->ratioLimitMode = mode;
260 tr_torrentSetDirty( tor );
264 tr_ratiolimit
265 tr_torrentGetRatioMode( const tr_torrent * tor )
267 assert( tr_isTorrent( tor ) );
269 return tor->ratioLimitMode;
272 void
273 tr_torrentSetRatioLimit( tr_torrent * tor, double desiredRatio )
275 assert( tr_isTorrent( tor ) );
277 if( (int)(desiredRatio*100.0) != (int)(tor->desiredRatio*100.0) )
279 tor->desiredRatio = desiredRatio;
281 tr_torrentSetDirty( tor );
285 double
286 tr_torrentGetRatioLimit( const tr_torrent * tor )
288 assert( tr_isTorrent( tor ) );
290 return tor->desiredRatio;
293 bool
294 tr_torrentGetSeedRatio( const tr_torrent * tor, double * ratio )
296 bool isLimited;
298 switch( tr_torrentGetRatioMode( tor ) )
300 case TR_RATIOLIMIT_SINGLE:
301 isLimited = true;
302 if( ratio )
303 *ratio = tr_torrentGetRatioLimit( tor );
304 break;
306 case TR_RATIOLIMIT_GLOBAL:
307 isLimited = tr_sessionIsRatioLimited( tor->session );
308 if( isLimited && ratio )
309 *ratio = tr_sessionGetRatioLimit( tor->session );
310 break;
312 default: /* TR_RATIOLIMIT_UNLIMITED */
313 isLimited = false;
314 break;
317 return isLimited;
320 /* returns true if the seed ratio applies --
321 * it applies if the torrent's a seed AND it has a seed ratio set */
322 static bool
323 tr_torrentGetSeedRatioBytes( tr_torrent * tor,
324 uint64_t * setmeLeft,
325 uint64_t * setmeGoal )
327 double seedRatio;
328 bool seedRatioApplies = false;
330 if( tr_torrentGetSeedRatio( tor, &seedRatio ) )
332 const uint64_t u = tor->uploadedCur + tor->uploadedPrev;
333 const uint64_t d = tor->downloadedCur + tor->downloadedPrev;
334 const uint64_t baseline = d ? d : tr_cpSizeWhenDone( &tor->completion );
335 const uint64_t goal = baseline * seedRatio;
336 if( setmeLeft ) *setmeLeft = goal > u ? goal - u : 0;
337 if( setmeGoal ) *setmeGoal = goal;
338 seedRatioApplies = tr_torrentIsSeed( tor );
341 return seedRatioApplies;
344 static bool
345 tr_torrentIsSeedRatioDone( tr_torrent * tor )
347 uint64_t bytesLeft;
348 return tr_torrentGetSeedRatioBytes( tor, &bytesLeft, NULL ) && !bytesLeft;
351 /***
352 ****
353 ***/
355 void
356 tr_torrentSetIdleMode( tr_torrent * tor, tr_idlelimit mode )
358 assert( tr_isTorrent( tor ) );
359 assert( mode==TR_IDLELIMIT_GLOBAL || mode==TR_IDLELIMIT_SINGLE || mode==TR_IDLELIMIT_UNLIMITED );
361 if( mode != tor->idleLimitMode )
363 tor->idleLimitMode = mode;
365 tr_torrentSetDirty( tor );
369 tr_idlelimit
370 tr_torrentGetIdleMode( const tr_torrent * tor )
372 assert( tr_isTorrent( tor ) );
374 return tor->idleLimitMode;
377 void
378 tr_torrentSetIdleLimit( tr_torrent * tor, uint16_t idleMinutes )
380 assert( tr_isTorrent( tor ) );
382 if( idleMinutes > 0 )
384 tor->idleLimitMinutes = idleMinutes;
386 tr_torrentSetDirty( tor );
390 uint16_t
391 tr_torrentGetIdleLimit( const tr_torrent * tor )
393 assert( tr_isTorrent( tor ) );
395 return tor->idleLimitMinutes;
398 bool
399 tr_torrentGetSeedIdle( const tr_torrent * tor, uint16_t * idleMinutes )
401 bool isLimited;
403 switch( tr_torrentGetIdleMode( tor ) )
405 case TR_IDLELIMIT_SINGLE:
406 isLimited = true;
407 if( idleMinutes )
408 *idleMinutes = tr_torrentGetIdleLimit( tor );
409 break;
411 case TR_IDLELIMIT_GLOBAL:
412 isLimited = tr_sessionIsIdleLimited( tor->session );
413 if( isLimited && idleMinutes )
414 *idleMinutes = tr_sessionGetIdleLimit( tor->session );
415 break;
417 default: /* TR_IDLELIMIT_UNLIMITED */
418 isLimited = false;
419 break;
422 return isLimited;
425 static bool
426 tr_torrentIsSeedIdleLimitDone( tr_torrent * tor )
428 uint16_t idleMinutes;
429 return tr_torrentGetSeedIdle( tor, &idleMinutes )
430 && difftime(tr_time(), MAX(tor->startDate, tor->activityDate)) >= idleMinutes * 60u;
433 /***
434 ****
435 ***/
437 void
438 tr_torrentCheckSeedLimit( tr_torrent * tor )
440 assert( tr_isTorrent( tor ) );
442 if( !tor->isRunning || !tr_torrentIsSeed( tor ) )
443 return;
445 /* if we're seeding and reach our seed ratio limit, stop the torrent */
446 if( tr_torrentIsSeedRatioDone( tor ) )
448 tr_torinf( tor, "Seed ratio reached; pausing torrent" );
450 tor->isStopping = true;
452 /* maybe notify the client */
453 if( tor->ratio_limit_hit_func != NULL )
454 tor->ratio_limit_hit_func( tor, tor->ratio_limit_hit_func_user_data );
456 /* if we're seeding and reach our inactiviy limit, stop the torrent */
457 else if( tr_torrentIsSeedIdleLimitDone( tor ) )
459 tr_torinf( tor, "Seeding idle limit reached; pausing torrent" );
461 tor->isStopping = true;
462 tor->finishedSeedingByIdle = true;
464 /* maybe notify the client */
465 if( tor->idle_limit_hit_func != NULL )
466 tor->idle_limit_hit_func( tor, tor->idle_limit_hit_func_user_data );
470 /***
471 ****
472 ***/
474 void
475 tr_torrentSetLocalError( tr_torrent * tor, const char * fmt, ... )
477 va_list ap;
479 assert( tr_isTorrent( tor ) );
481 va_start( ap, fmt );
482 tor->error = TR_STAT_LOCAL_ERROR;
483 tor->errorTracker[0] = '\0';
484 evutil_vsnprintf( tor->errorString, sizeof( tor->errorString ), fmt, ap );
485 va_end( ap );
487 tr_torerr( tor, "%s", tor->errorString );
489 if( tor->isRunning )
490 tor->isStopping = true;
493 static void
494 tr_torrentClearError( tr_torrent * tor )
496 tor->error = TR_STAT_OK;
497 tor->errorString[0] = '\0';
498 tor->errorTracker[0] = '\0';
501 static void
502 onTrackerResponse( tr_torrent * tor, const tr_tracker_event * event, void * unused UNUSED )
504 switch( event->messageType )
506 case TR_TRACKER_PEERS:
508 size_t i;
509 const int8_t seedProbability = event->seedProbability;
510 const bool allAreSeeds = seedProbability == 100;
512 if( allAreSeeds )
513 tr_tordbg( tor, "Got %zu seeds from tracker", event->pexCount );
514 else
515 tr_tordbg( tor, "Got %zu peers from tracker", event->pexCount );
517 for( i = 0; i < event->pexCount; ++i )
518 tr_peerMgrAddPex( tor, TR_PEER_FROM_TRACKER, &event->pex[i], seedProbability );
520 if( allAreSeeds && tr_torrentIsPrivate( tor ) )
521 tr_peerMgrMarkAllAsSeeds( tor );
523 break;
526 case TR_TRACKER_WARNING:
527 tr_torerr( tor, _( "Tracker warning: \"%s\"" ), event->text );
528 tor->error = TR_STAT_TRACKER_WARNING;
529 tr_strlcpy( tor->errorTracker, event->tracker, sizeof( tor->errorTracker ) );
530 tr_strlcpy( tor->errorString, event->text, sizeof( tor->errorString ) );
531 break;
533 case TR_TRACKER_ERROR:
534 tr_torerr( tor, _( "Tracker error: \"%s\"" ), event->text );
535 tor->error = TR_STAT_TRACKER_ERROR;
536 tr_strlcpy( tor->errorTracker, event->tracker, sizeof( tor->errorTracker ) );
537 tr_strlcpy( tor->errorString, event->text, sizeof( tor->errorString ) );
538 break;
540 case TR_TRACKER_ERROR_CLEAR:
541 if( tor->error != TR_STAT_LOCAL_ERROR )
542 tr_torrentClearError( tor );
543 break;
547 /***
548 ****
549 **** TORRENT INSTANTIATION
550 ****
551 ***/
553 static tr_piece_index_t
554 getBytePiece( const tr_info * info, uint64_t byteOffset )
556 assert( info );
557 assert( info->pieceSize != 0 );
559 return byteOffset / info->pieceSize;
562 static void
563 initFilePieces( tr_info * info,
564 tr_file_index_t fileIndex )
566 tr_file * file;
567 uint64_t firstByte, lastByte;
569 assert( info );
570 assert( fileIndex < info->fileCount );
572 file = &info->files[fileIndex];
573 firstByte = file->offset;
574 lastByte = firstByte + ( file->length ? file->length - 1 : 0 );
575 file->firstPiece = getBytePiece( info, firstByte );
576 file->lastPiece = getBytePiece( info, lastByte );
579 static int
580 pieceHasFile( tr_piece_index_t piece,
581 const tr_file * file )
583 return ( file->firstPiece <= piece ) && ( piece <= file->lastPiece );
586 static tr_priority_t
587 calculatePiecePriority( const tr_torrent * tor,
588 tr_piece_index_t piece,
589 int fileHint )
591 tr_file_index_t i;
592 tr_priority_t priority = TR_PRI_LOW;
594 /* find the first file that has data in this piece */
595 if( fileHint >= 0 ) {
596 i = fileHint;
597 while( i > 0 && pieceHasFile( piece, &tor->info.files[i - 1] ) )
598 --i;
599 } else {
600 for( i = 0; i < tor->info.fileCount; ++i )
601 if( pieceHasFile( piece, &tor->info.files[i] ) )
602 break;
605 /* the piece's priority is the max of the priorities
606 * of all the files in that piece */
607 for( ; i < tor->info.fileCount; ++i )
609 const tr_file * file = &tor->info.files[i];
611 if( !pieceHasFile( piece, file ) )
612 break;
614 priority = MAX( priority, file->priority );
616 /* when dealing with multimedia files, getting the first and
617 last pieces can sometimes allow you to preview it a bit
618 before it's fully downloaded... */
619 if( file->priority >= TR_PRI_NORMAL )
620 if( file->firstPiece == piece || file->lastPiece == piece )
621 priority = TR_PRI_HIGH;
624 return priority;
627 static void
628 tr_torrentInitFilePieces( tr_torrent * tor )
630 int * firstFiles;
631 tr_file_index_t f;
632 tr_piece_index_t p;
633 uint64_t offset = 0;
634 tr_info * inf = &tor->info;
636 /* assign the file offsets */
637 for( f=0; f<inf->fileCount; ++f ) {
638 inf->files[f].offset = offset;
639 offset += inf->files[f].length;
640 initFilePieces( inf, f );
643 /* build the array of first-file hints to give calculatePiecePriority */
644 firstFiles = tr_new( int, inf->pieceCount );
645 for( p=f=0; p<inf->pieceCount; ++p ) {
646 while( inf->files[f].lastPiece < p )
647 ++f;
648 firstFiles[p] = f;
651 #if 0
652 /* test to confirm the first-file hints are correct */
653 for( p=0; p<inf->pieceCount; ++p ) {
654 f = firstFiles[p];
655 assert( inf->files[f].firstPiece <= p );
656 assert( inf->files[f].lastPiece >= p );
657 if( f > 0 )
658 assert( inf->files[f-1].lastPiece < p );
659 for( f=0; f<inf->fileCount; ++f )
660 if( pieceHasFile( p, &inf->files[f] ) )
661 break;
662 assert( (int)f == firstFiles[p] );
664 #endif
666 for( p=0; p<inf->pieceCount; ++p )
667 inf->pieces[p].priority = calculatePiecePriority( tor, p, firstFiles[p] );
669 tr_free( firstFiles );
672 static void torrentStart( tr_torrent * tor );
675 * Decide on a block size. Constraints:
676 * (1) most clients decline requests over 16 KiB
677 * (2) pieceSize must be a multiple of block size
679 uint32_t
680 tr_getBlockSize( uint32_t pieceSize )
682 uint32_t b = pieceSize;
684 while( b > MAX_BLOCK_SIZE )
685 b /= 2u;
687 if( !b || ( pieceSize % b ) ) /* not cleanly divisible */
688 return 0;
689 return b;
692 static void refreshCurrentDir( tr_torrent * tor );
694 static void
695 torrentInitFromInfo( tr_torrent * tor )
697 uint64_t t;
698 tr_info * info = &tor->info;
700 tor->blockSize = tr_getBlockSize( info->pieceSize );
702 if( info->pieceSize )
703 tor->lastPieceSize = (uint32_t)(info->totalSize % info->pieceSize);
705 if( !tor->lastPieceSize )
706 tor->lastPieceSize = info->pieceSize;
708 if( tor->blockSize )
709 tor->lastBlockSize = info->totalSize % tor->blockSize;
711 if( !tor->lastBlockSize )
712 tor->lastBlockSize = tor->blockSize;
714 tor->blockCount = tor->blockSize
715 ? ( info->totalSize + tor->blockSize - 1 ) / tor->blockSize
716 : 0;
718 tor->blockCountInPiece = tor->blockSize
719 ? info->pieceSize / tor->blockSize
720 : 0;
722 tor->blockCountInLastPiece = tor->blockSize
723 ? ( tor->lastPieceSize + tor->blockSize - 1 ) / tor->blockSize
724 : 0;
726 /* check our work */
727 if( tor->blockSize != 0 )
728 assert( ( info->pieceSize % tor->blockSize ) == 0 );
729 t = info->pieceCount - 1;
730 t *= info->pieceSize;
731 t += tor->lastPieceSize;
732 assert( t == info->totalSize );
733 t = tor->blockCount - 1;
734 t *= tor->blockSize;
735 t += tor->lastBlockSize;
736 assert( t == info->totalSize );
737 t = info->pieceCount - 1;
738 t *= tor->blockCountInPiece;
739 t += tor->blockCountInLastPiece;
740 assert( t == (uint64_t)tor->blockCount );
742 tr_cpConstruct( &tor->completion, tor );
744 tr_torrentInitFilePieces( tor );
746 tor->completeness = tr_cpGetStatus( &tor->completion );
749 static void tr_torrentFireMetadataCompleted( tr_torrent * tor );
751 void
752 tr_torrentGotNewInfoDict( tr_torrent * tor )
754 torrentInitFromInfo( tor );
756 tr_peerMgrOnTorrentGotMetainfo( tor );
758 tr_torrentFireMetadataCompleted( tor );
761 static bool
762 hasAnyLocalData( const tr_torrent * tor )
764 tr_file_index_t i;
766 for( i=0; i<tor->info.fileCount; ++i )
767 if( tr_torrentFindFile2( tor, i, NULL, NULL, NULL ) )
768 return true;
770 return false;
773 static bool
774 setLocalErrorIfFilesDisappeared( tr_torrent * tor )
776 const bool disappeared = ( tr_cpHaveTotal( &tor->completion ) > 0 ) && !hasAnyLocalData( tor );
778 if( disappeared )
780 tr_deeplog_tor( tor, "%s", "[LAZY] uh oh, the files disappeared" );
781 tr_torrentSetLocalError( tor, "%s", _( "No data found! Ensure your drives are connected or use \"Set Location\". To re-download, remove the torrent and re-add it." ) );
784 return disappeared;
787 static void
788 torrentInit( tr_torrent * tor, const tr_ctor * ctor )
790 int doStart;
791 uint64_t loaded;
792 const char * dir;
793 bool isNewTorrent;
794 struct stat st;
795 static int nextUniqueId = 1;
796 tr_session * session = tr_ctorGetSession( ctor );
798 assert( session != NULL );
800 tr_sessionLock( session );
802 tor->session = session;
803 tor->uniqueId = nextUniqueId++;
804 tor->magicNumber = TORRENT_MAGIC_NUMBER;
806 tr_peerIdInit( tor->peer_id );
808 tr_sha1( tor->obfuscatedHash, "req2", 4,
809 tor->info.hash, SHA_DIGEST_LENGTH,
810 NULL );
812 if( !tr_ctorGetDownloadDir( ctor, TR_FORCE, &dir ) ||
813 !tr_ctorGetDownloadDir( ctor, TR_FALLBACK, &dir ) )
814 tor->downloadDir = tr_strdup( dir );
816 if( tr_ctorGetIncompleteDir( ctor, &dir ) )
817 dir = tr_sessionGetIncompleteDir( session );
818 if( tr_sessionIsIncompleteDirEnabled( session ) )
819 tor->incompleteDir = tr_strdup( dir );
821 tr_bandwidthConstruct( &tor->bandwidth, session, &session->bandwidth );
823 tor->bandwidth.priority = tr_ctorGetBandwidthPriority( ctor );
825 tor->error = TR_STAT_OK;
827 tor->finishedSeedingByIdle = false;
829 tr_peerMgrAddTorrent( session->peerMgr, tor );
831 assert( !tor->downloadedCur );
832 assert( !tor->uploadedCur );
834 tr_torrentSetAddedDate( tor, tr_time( ) ); /* this is a default value to be
835 overwritten by the resume file */
837 torrentInitFromInfo( tor );
838 loaded = tr_torrentLoadResume( tor, ~0, ctor );
839 tor->completeness = tr_cpGetStatus( &tor->completion );
840 setLocalErrorIfFilesDisappeared( tor );
842 tr_ctorInitTorrentPriorities( ctor, tor );
843 tr_ctorInitTorrentWanted( ctor, tor );
845 refreshCurrentDir( tor );
847 doStart = tor->isRunning;
848 tor->isRunning = 0;
850 if( !( loaded & TR_FR_SPEEDLIMIT ) )
852 tr_torrentUseSpeedLimit( tor, TR_UP, false );
853 tr_torrentSetSpeedLimit_Bps( tor, TR_UP, tr_sessionGetSpeedLimit_Bps( tor->session, TR_UP ) );
854 tr_torrentUseSpeedLimit( tor, TR_DOWN, false );
855 tr_torrentSetSpeedLimit_Bps( tor, TR_DOWN, tr_sessionGetSpeedLimit_Bps( tor->session, TR_DOWN ) );
856 tr_torrentUseSessionLimits( tor, true );
859 if( !( loaded & TR_FR_RATIOLIMIT ) )
861 tr_torrentSetRatioMode( tor, TR_RATIOLIMIT_GLOBAL );
862 tr_torrentSetRatioLimit( tor, tr_sessionGetRatioLimit( tor->session ) );
865 if( !( loaded & TR_FR_IDLELIMIT ) )
867 tr_torrentSetIdleMode( tor, TR_IDLELIMIT_GLOBAL );
868 tr_torrentSetIdleLimit( tor, tr_sessionGetIdleLimit( tor->session ) );
871 /* add the torrent to tr_session.torrentList */
872 ++session->torrentCount;
873 if( session->torrentList == NULL )
874 session->torrentList = tor;
875 else {
876 tr_torrent * it = session->torrentList;
877 while( it->next != NULL )
878 it = it->next;
879 it->next = tor;
882 /* if we don't have a local .torrent file already, assume the torrent is new */
883 isNewTorrent = stat( tor->info.torrent, &st );
885 /* maybe save our own copy of the metainfo */
886 if( tr_ctorGetSave( ctor ) )
888 const tr_benc * val;
889 if( !tr_ctorGetMetainfo( ctor, &val ) )
891 const char * path = tor->info.torrent;
892 const int err = tr_bencToFile( val, TR_FMT_BENC, path );
893 if( err )
894 tr_torrentSetLocalError( tor, "Unable to save torrent file: %s", tr_strerror( err ) );
895 tr_sessionSetTorrentFile( tor->session, tor->info.hashString, path );
899 tor->tiers = tr_announcerAddTorrent( tor, onTrackerResponse, NULL );
901 if( isNewTorrent )
903 tor->startAfterVerify = doStart;
904 tr_torrentVerify( tor );
906 else if( doStart )
908 torrentStart( tor );
911 tr_sessionUnlock( session );
914 static tr_parse_result
915 torrentParseImpl( const tr_ctor * ctor, tr_info * setmeInfo,
916 bool * setmeHasInfo, int * dictLength )
918 int doFree;
919 bool didParse;
920 bool hasInfo = false;
921 tr_info tmp;
922 const tr_benc * metainfo;
923 tr_session * session = tr_ctorGetSession( ctor );
924 tr_parse_result result = TR_PARSE_OK;
926 if( setmeInfo == NULL )
927 setmeInfo = &tmp;
928 memset( setmeInfo, 0, sizeof( tr_info ) );
930 if( tr_ctorGetMetainfo( ctor, &metainfo ) )
931 return TR_PARSE_ERR;
933 didParse = tr_metainfoParse( session, metainfo, setmeInfo,
934 &hasInfo, dictLength );
935 doFree = didParse && ( setmeInfo == &tmp );
937 if( !didParse )
938 result = TR_PARSE_ERR;
940 if( didParse && hasInfo && !tr_getBlockSize( setmeInfo->pieceSize ) )
941 result = TR_PARSE_ERR;
943 if( didParse && session && tr_torrentExists( session, setmeInfo->hash ) )
944 result = TR_PARSE_DUPLICATE;
946 if( doFree )
947 tr_metainfoFree( setmeInfo );
949 if( setmeHasInfo != NULL )
950 *setmeHasInfo = hasInfo;
952 return result;
955 tr_parse_result
956 tr_torrentParse( const tr_ctor * ctor, tr_info * setmeInfo )
958 return torrentParseImpl( ctor, setmeInfo, NULL, NULL );
961 tr_torrent *
962 tr_torrentNew( const tr_ctor * ctor, int * setmeError )
964 int len;
965 bool hasInfo;
966 tr_info tmpInfo;
967 tr_parse_result r;
968 tr_torrent * tor = NULL;
970 assert( ctor != NULL );
971 assert( tr_isSession( tr_ctorGetSession( ctor ) ) );
973 r = torrentParseImpl( ctor, &tmpInfo, &hasInfo, &len );
974 if( r == TR_PARSE_OK )
976 tor = tr_new0( tr_torrent, 1 );
977 tor->info = tmpInfo;
978 if( hasInfo )
979 tor->infoDictLength = len;
980 torrentInit( tor, ctor );
982 else
984 if( r == TR_PARSE_DUPLICATE )
985 tr_metainfoFree( &tmpInfo );
987 if( setmeError )
988 *setmeError = r;
991 return tor;
998 void
999 tr_torrentSetDownloadDir( tr_torrent * tor, const char * path )
1001 assert( tr_isTorrent( tor ) );
1003 if( !path || !tor->downloadDir || strcmp( path, tor->downloadDir ) )
1005 tr_free( tor->downloadDir );
1006 tor->downloadDir = tr_strdup( path );
1007 tr_torrentSetDirty( tor );
1010 refreshCurrentDir( tor );
1013 const char*
1014 tr_torrentGetDownloadDir( const tr_torrent * tor )
1016 assert( tr_isTorrent( tor ) );
1018 return tor->downloadDir;
1021 const char *
1022 tr_torrentGetCurrentDir( const tr_torrent * tor )
1024 assert( tr_isTorrent( tor ) );
1026 return tor->currentDir;
1030 void
1031 tr_torrentChangeMyPort( tr_torrent * tor )
1033 assert( tr_isTorrent( tor ) );
1035 if( tor->isRunning )
1036 tr_announcerChangeMyPort( tor );
1039 static inline void
1040 tr_torrentManualUpdateImpl( void * vtor )
1042 tr_torrent * tor = vtor;
1044 assert( tr_isTorrent( tor ) );
1046 if( tor->isRunning )
1047 tr_announcerManualAnnounce( tor );
1050 void
1051 tr_torrentManualUpdate( tr_torrent * tor )
1053 assert( tr_isTorrent( tor ) );
1055 tr_runInEventThread( tor->session, tr_torrentManualUpdateImpl, tor );
1058 bool
1059 tr_torrentCanManualUpdate( const tr_torrent * tor )
1061 return ( tr_isTorrent( tor ) )
1062 && ( tor->isRunning )
1063 && ( tr_announcerCanManualAnnounce( tor ) );
1066 const tr_info *
1067 tr_torrentInfo( const tr_torrent * tor )
1069 return tr_isTorrent( tor ) ? &tor->info : NULL;
1072 const tr_stat *
1073 tr_torrentStatCached( tr_torrent * tor )
1075 const time_t now = tr_time( );
1077 return tr_isTorrent( tor ) && ( now == tor->lastStatTime )
1078 ? &tor->stats
1079 : tr_torrentStat( tor );
1082 void
1083 tr_torrentSetVerifyState( tr_torrent * tor, tr_verify_state state )
1085 assert( tr_isTorrent( tor ) );
1086 assert( state==TR_VERIFY_NONE || state==TR_VERIFY_WAIT || state==TR_VERIFY_NOW );
1088 tor->verifyState = state;
1089 tor->anyDate = tr_time( );
1092 tr_torrent_activity
1093 tr_torrentGetActivity( tr_torrent * tor )
1095 assert( tr_isTorrent( tor ) );
1097 tr_torrentRecheckCompleteness( tor );
1099 if( tor->verifyState == TR_VERIFY_NOW )
1100 return TR_STATUS_CHECK;
1101 if( tor->verifyState == TR_VERIFY_WAIT )
1102 return TR_STATUS_CHECK_WAIT;
1103 if( !tor->isRunning )
1104 return TR_STATUS_STOPPED;
1105 if( tor->completeness == TR_LEECH )
1106 return TR_STATUS_DOWNLOAD;
1108 return TR_STATUS_SEED;
1111 static double
1112 getVerifyProgress( const tr_torrent * tor )
1114 tr_piece_index_t i, n;
1115 tr_piece_index_t checked = 0;
1117 assert( tr_isTorrent( tor ) );
1119 for( i=0, n=tor->info.pieceCount; i!=n; ++i )
1120 if( tor->info.pieces[i].timeChecked )
1121 ++checked;
1123 return checked / (double)tor->info.pieceCount;
1126 const tr_stat *
1127 tr_torrentStat( tr_torrent * tor )
1129 tr_stat * s;
1130 uint64_t now;
1131 uint64_t seedRatioBytesLeft;
1132 uint64_t seedRatioBytesGoal;
1133 bool seedRatioApplies;
1134 uint16_t seedIdleMinutes;
1136 if( !tor )
1137 return NULL;
1139 assert( tr_isTorrent( tor ) );
1140 tr_torrentLock( tor );
1142 tor->lastStatTime = tr_time( );
1144 s = &tor->stats;
1145 s->id = tor->uniqueId;
1146 s->activity = tr_torrentGetActivity( tor );
1147 s->error = tor->error;
1148 tr_strlcpy( s->errorString, tor->errorString, sizeof( s->errorString ) );
1150 s->manualAnnounceTime = tr_announcerNextManualAnnounce( tor );
1152 tr_peerMgrTorrentStats( tor,
1153 &s->peersConnected,
1154 &s->webseedsSendingToUs,
1155 &s->peersSendingToUs,
1156 &s->peersGettingFromUs,
1157 s->peersFrom );
1159 now = tr_time_msec( );
1160 s->rawUploadSpeed_KBps = toSpeedKBps( tr_bandwidthGetRawSpeed_Bps ( &tor->bandwidth, now, TR_UP ) );
1161 s->pieceUploadSpeed_KBps = toSpeedKBps( tr_bandwidthGetPieceSpeed_Bps( &tor->bandwidth, now, TR_UP ) );
1162 s->rawDownloadSpeed_KBps = toSpeedKBps( tr_bandwidthGetRawSpeed_Bps ( &tor->bandwidth, now, TR_DOWN ) );
1163 s->pieceDownloadSpeed_KBps = toSpeedKBps( tr_bandwidthGetPieceSpeed_Bps( &tor->bandwidth, now, TR_DOWN ) );
1165 s->percentComplete = tr_cpPercentComplete ( &tor->completion );
1166 s->metadataPercentComplete = tr_torrentGetMetadataPercent( tor );
1168 s->percentDone = tr_cpPercentDone ( &tor->completion );
1169 s->leftUntilDone = tr_cpLeftUntilDone( &tor->completion );
1170 s->sizeWhenDone = tr_cpSizeWhenDone ( &tor->completion );
1171 s->recheckProgress = s->activity == TR_STATUS_CHECK ? getVerifyProgress( tor ) : 0;
1172 s->activityDate = tor->activityDate;
1173 s->addedDate = tor->addedDate;
1174 s->doneDate = tor->doneDate;
1175 s->startDate = tor->startDate;
1176 s->secondsSeeding = tor->secondsSeeding;
1177 s->secondsDownloading = tor->secondsDownloading;
1179 if ((s->activity == TR_STATUS_DOWNLOAD || s->activity == TR_STATUS_SEED) && s->startDate != 0)
1180 s->idleSecs = difftime(tr_time(), MAX(s->startDate, s->activityDate));
1181 else
1182 s->idleSecs = -1;
1184 s->corruptEver = tor->corruptCur + tor->corruptPrev;
1185 s->downloadedEver = tor->downloadedCur + tor->downloadedPrev;
1186 s->uploadedEver = tor->uploadedCur + tor->uploadedPrev;
1187 s->haveValid = tr_cpHaveValid( &tor->completion );
1188 s->haveUnchecked = tr_cpHaveTotal( &tor->completion ) - s->haveValid;
1189 s->desiredAvailable = tr_peerMgrGetDesiredAvailable( tor );
1191 s->ratio = tr_getRatio( s->uploadedEver,
1192 s->downloadedEver ? s->downloadedEver : s->haveValid );
1194 seedRatioApplies = tr_torrentGetSeedRatioBytes( tor, &seedRatioBytesLeft,
1195 &seedRatioBytesGoal );
1197 switch( s->activity )
1199 /* etaXLSpeed exists because if we use the piece speed directly,
1200 * brief fluctuations cause the ETA to jump all over the place.
1201 * so, etaXLSpeed is a smoothed-out version of the piece speed
1202 * to dampen the effect of fluctuations */
1204 case TR_STATUS_DOWNLOAD:
1205 if( ( tor->etaDLSpeedCalculatedAt + 800 ) < now ) {
1206 tor->etaDLSpeed_KBps = ( ( tor->etaDLSpeedCalculatedAt + 4000 ) < now )
1207 ? s->pieceDownloadSpeed_KBps /* if no recent previous speed, no need to smooth */
1208 : ((tor->etaDLSpeed_KBps*4.0) + s->pieceDownloadSpeed_KBps)/5.0; /* smooth across 5 readings */
1209 tor->etaDLSpeedCalculatedAt = now;
1212 if( s->leftUntilDone > s->desiredAvailable )
1213 s->eta = TR_ETA_NOT_AVAIL;
1214 else if( tor->etaDLSpeed_KBps < 1 )
1215 s->eta = TR_ETA_UNKNOWN;
1216 else
1217 s->eta = s->leftUntilDone / toSpeedBytes(tor->etaDLSpeed_KBps);
1219 s->etaIdle = TR_ETA_NOT_AVAIL;
1220 break;
1222 case TR_STATUS_SEED: {
1223 if( !seedRatioApplies )
1224 s->eta = TR_ETA_NOT_AVAIL;
1225 else {
1226 if( ( tor->etaULSpeedCalculatedAt + 800 ) < now ) {
1227 tor->etaULSpeed_KBps = ( ( tor->etaULSpeedCalculatedAt + 4000 ) < now )
1228 ? s->pieceUploadSpeed_KBps /* if no recent previous speed, no need to smooth */
1229 : ((tor->etaULSpeed_KBps*4.0) + s->pieceUploadSpeed_KBps)/5.0; /* smooth across 5 readings */
1230 tor->etaULSpeedCalculatedAt = now;
1232 if( tor->etaULSpeed_KBps < 1 )
1233 s->eta = TR_ETA_UNKNOWN;
1234 else
1235 s->eta = seedRatioBytesLeft / toSpeedBytes(tor->etaULSpeed_KBps);
1238 if( tor->etaULSpeed_KBps < 1 && tr_torrentGetSeedIdle( tor, &seedIdleMinutes ) )
1239 s->etaIdle = seedIdleMinutes * 60 - s->idleSecs;
1240 else
1241 s->etaIdle = TR_ETA_NOT_AVAIL;
1242 break;
1245 default:
1246 s->eta = TR_ETA_NOT_AVAIL;
1247 s->etaIdle = TR_ETA_NOT_AVAIL;
1248 break;
1251 /* s->haveValid is here to make sure a torrent isn't marked 'finished'
1252 * when the user hits "uncheck all" prior to starting the torrent... */
1253 s->finished = tor->finishedSeedingByIdle || (seedRatioApplies && !seedRatioBytesLeft && s->haveValid);
1255 if( !seedRatioApplies || s->finished )
1256 s->seedRatioPercentDone = 1;
1257 else if( !seedRatioBytesGoal ) /* impossible? safeguard for div by zero */
1258 s->seedRatioPercentDone = 0;
1259 else
1260 s->seedRatioPercentDone = (double)(seedRatioBytesGoal - seedRatioBytesLeft) / seedRatioBytesGoal;
1262 tr_torrentUnlock( tor );
1264 /* test some of the constraints */
1265 assert( s->sizeWhenDone <= tor->info.totalSize );
1266 assert( s->leftUntilDone <= s->sizeWhenDone );
1267 assert( s->desiredAvailable <= s->leftUntilDone );
1268 return s;
1271 /***
1272 ****
1273 ***/
1275 static uint64_t
1276 fileBytesCompleted( const tr_torrent * tor, tr_file_index_t index )
1278 uint64_t total = 0;
1279 const tr_file * f = &tor->info.files[index];
1281 if( f->length )
1283 tr_block_index_t first;
1284 tr_block_index_t last;
1285 tr_torGetFileBlockRange( tor, index, &first, &last );
1287 if( first == last )
1289 if( tr_cpBlockIsComplete( &tor->completion, first ) )
1290 total = f->length;
1292 else
1294 /* the first block */
1295 if( tr_cpBlockIsComplete( &tor->completion, first ) )
1296 total += tor->blockSize - ( f->offset % tor->blockSize );
1298 /* the middle blocks */
1299 if( first + 1 < last ) {
1300 uint64_t u = tr_bitfieldCountRange( &tor->completion.blockBitfield, first+1, last );
1301 u *= tor->blockSize;
1302 total += u;
1305 /* the last block */
1306 if( tr_cpBlockIsComplete( &tor->completion, last ) )
1307 total += ( f->offset + f->length ) - ( (uint64_t)tor->blockSize * last );
1311 return total;
1314 tr_file_stat *
1315 tr_torrentFiles( const tr_torrent * tor,
1316 tr_file_index_t * fileCount )
1318 tr_file_index_t i;
1319 const tr_file_index_t n = tor->info.fileCount;
1320 tr_file_stat * files = tr_new0( tr_file_stat, n );
1321 tr_file_stat * walk = files;
1322 const bool isSeed = tor->completeness == TR_SEED;
1324 assert( tr_isTorrent( tor ) );
1326 for( i=0; i<n; ++i, ++walk ) {
1327 const uint64_t b = isSeed ? tor->info.files[i].length : fileBytesCompleted( tor, i );
1328 walk->bytesCompleted = b;
1329 walk->progress = tor->info.files[i].length > 0 ? ( (float)b / tor->info.files[i].length ) : 1.0f;
1332 if( fileCount )
1333 *fileCount = n;
1335 return files;
1338 void
1339 tr_torrentFilesFree( tr_file_stat * files,
1340 tr_file_index_t fileCount UNUSED )
1342 tr_free( files );
1345 /***
1346 ****
1347 ***/
1349 double*
1350 tr_torrentWebSpeeds_KBps( const tr_torrent * tor )
1352 double * ret = NULL;
1354 if( tr_isTorrent( tor ) )
1356 tr_torrentLock( tor );
1357 ret = tr_peerMgrWebSpeeds_KBps( tor );
1358 tr_torrentUnlock( tor );
1361 return ret;
1364 tr_peer_stat *
1365 tr_torrentPeers( const tr_torrent * tor, int * peerCount )
1367 tr_peer_stat * ret = NULL;
1369 if( tr_isTorrent( tor ) )
1371 tr_torrentLock( tor );
1372 ret = tr_peerMgrPeerStats( tor, peerCount );
1373 tr_torrentUnlock( tor );
1376 return ret;
1379 void
1380 tr_torrentPeersFree( tr_peer_stat * peers, int peerCount UNUSED )
1382 tr_free( peers );
1385 tr_tracker_stat *
1386 tr_torrentTrackers( const tr_torrent * torrent, int * setmeTrackerCount )
1388 tr_tracker_stat * ret = NULL;
1390 if( tr_isTorrent( torrent ) )
1392 tr_torrentLock( torrent );
1393 ret = tr_announcerStats( torrent, setmeTrackerCount );
1394 tr_torrentUnlock( torrent );
1397 return ret;
1400 void
1401 tr_torrentTrackersFree( tr_tracker_stat * trackers, int trackerCount )
1403 tr_announcerStatsFree( trackers, trackerCount );
1406 void
1407 tr_torrentAvailability( const tr_torrent * tor, int8_t * tab, int size )
1409 if( tr_isTorrent( tor ) && ( tab != NULL ) && ( size > 0 ) )
1411 tr_torrentLock( tor );
1412 tr_peerMgrTorrentAvailability( tor, tab, size );
1413 tr_torrentUnlock( tor );
1417 void
1418 tr_torrentAmountFinished( const tr_torrent * tor,
1419 float * tab,
1420 int size )
1422 assert( tr_isTorrent( tor ) );
1424 tr_torrentLock( tor );
1425 tr_cpGetAmountDone( &tor->completion, tab, size );
1426 tr_torrentUnlock( tor );
1429 static void
1430 tr_torrentResetTransferStats( tr_torrent * tor )
1432 tr_torrentLock( tor );
1434 tor->downloadedPrev += tor->downloadedCur;
1435 tor->downloadedCur = 0;
1436 tor->uploadedPrev += tor->uploadedCur;
1437 tor->uploadedCur = 0;
1438 tor->corruptPrev += tor->corruptCur;
1439 tor->corruptCur = 0;
1441 tr_torrentSetDirty( tor );
1443 tr_torrentUnlock( tor );
1446 void
1447 tr_torrentSetHasPiece( tr_torrent * tor,
1448 tr_piece_index_t pieceIndex,
1449 bool has )
1451 assert( tr_isTorrent( tor ) );
1452 assert( pieceIndex < tor->info.pieceCount );
1454 if( has )
1455 tr_cpPieceAdd( &tor->completion, pieceIndex );
1456 else
1457 tr_cpPieceRem( &tor->completion, pieceIndex );
1460 /***
1461 ****
1462 ***/
1464 static void
1465 freeTorrent( tr_torrent * tor )
1467 tr_torrent * t;
1468 tr_session * session = tor->session;
1469 tr_info * inf = &tor->info;
1471 assert( !tor->isRunning );
1473 tr_sessionLock( session );
1475 tr_peerMgrRemoveTorrent( tor );
1477 tr_cpDestruct( &tor->completion );
1479 tr_announcerRemoveTorrent( session->announcer, tor );
1481 tr_free( tor->downloadDir );
1482 tr_free( tor->incompleteDir );
1484 if( tor == session->torrentList )
1485 session->torrentList = tor->next;
1486 else for( t = session->torrentList; t != NULL; t = t->next ) {
1487 if( t->next == tor ) {
1488 t->next = tor->next;
1489 break;
1493 assert( session->torrentCount >= 1 );
1494 session->torrentCount--;
1496 tr_bandwidthDestruct( &tor->bandwidth );
1498 tr_metainfoFree( inf );
1499 tr_free( tor );
1501 tr_sessionUnlock( session );
1505 *** Start/Stop Callback
1508 static void
1509 torrentStartImpl( void * vtor )
1511 time_t now;
1512 tr_torrent * tor = vtor;
1514 assert( tr_isTorrent( tor ) );
1516 tr_sessionLock( tor->session );
1518 tr_torrentRecheckCompleteness( tor );
1520 now = tr_time( );
1521 tor->isRunning = true;
1522 tor->completeness = tr_cpGetStatus( &tor->completion );
1523 tor->startDate = tor->anyDate = now;
1524 tr_torrentClearError( tor );
1525 tor->finishedSeedingByIdle = false;
1527 tr_torrentResetTransferStats( tor );
1528 tr_announcerTorrentStarted( tor );
1529 tor->dhtAnnounceAt = now + tr_cryptoWeakRandInt( 20 );
1530 tor->dhtAnnounce6At = now + tr_cryptoWeakRandInt( 20 );
1531 tor->lpdAnnounceAt = now;
1532 tr_peerMgrStartTorrent( tor );
1534 tr_sessionUnlock( tor->session );
1537 uint64_t
1538 tr_torrentGetCurrentSizeOnDisk( const tr_torrent * tor )
1540 tr_file_index_t i;
1541 uint64_t byte_count = 0;
1542 const tr_file_index_t n = tor->info.fileCount;
1544 for( i=0; i<n; ++i )
1546 struct stat sb;
1547 char * filename = tr_torrentFindFile( tor, i );
1549 sb.st_size = 0;
1550 if( filename && !stat( filename, &sb ) )
1551 byte_count += sb.st_size;
1553 tr_free( filename );
1556 return byte_count;
1559 static void
1560 torrentStart( tr_torrent * tor )
1562 /* already running... */
1563 if( tor->isRunning )
1564 return;
1566 /* don't allow the torrent to be started if the files disappeared */
1567 if( setLocalErrorIfFilesDisappeared( tor ) )
1568 return;
1570 /* verifying right now... wait until that's done so
1571 * we'll know what completeness to use/announce */
1572 if( tor->verifyState != TR_VERIFY_NONE ) {
1573 tor->startAfterVerify = true;
1574 return;
1577 /* otherwise, start it now... */
1578 tr_sessionLock( tor->session );
1580 /* allow finished torrents to be resumed */
1581 if( tr_torrentIsSeedRatioDone( tor ) ) {
1582 tr_torinf( tor, _( "Restarted manually -- disabling its seed ratio" ) );
1583 tr_torrentSetRatioMode( tor, TR_RATIOLIMIT_UNLIMITED );
1586 /* corresponds to the peer_id sent as a tracker request parameter.
1587 * one tracker admin says: "When the same torrent is opened and
1588 * closed and opened again without quitting Transmission ...
1589 * change the peerid. It would help sometimes if a stopped event
1590 * was missed to ensure that we didn't think someone was cheating. */
1591 tr_peerIdInit( tor->peer_id );
1592 tor->isRunning = 1;
1593 tr_torrentSetDirty( tor );
1594 tr_runInEventThread( tor->session, torrentStartImpl, tor );
1596 tr_sessionUnlock( tor->session );
1599 void
1600 tr_torrentStart( tr_torrent * tor )
1602 if( tr_isTorrent( tor ) )
1603 torrentStart( tor );
1606 static void
1607 torrentRecheckDoneImpl( void * vtor )
1609 tr_torrent * tor = vtor;
1610 assert( tr_isTorrent( tor ) );
1612 tr_torrentRecheckCompleteness( tor );
1614 if( tor->startAfterVerify ) {
1615 tor->startAfterVerify = false;
1616 torrentStart( tor );
1620 static void
1621 torrentRecheckDoneCB( tr_torrent * tor )
1623 assert( tr_isTorrent( tor ) );
1625 tr_runInEventThread( tor->session, torrentRecheckDoneImpl, tor );
1628 static void
1629 verifyTorrent( void * vtor )
1631 tr_torrent * tor = vtor;
1633 tr_sessionLock( tor->session );
1635 /* if the torrent's already being verified, stop it */
1636 tr_verifyRemove( tor );
1638 /* if the torrent's running, stop it & set the restart-after-verify flag */
1639 if( tor->startAfterVerify || tor->isRunning ) {
1640 /* don't clobber isStopping */
1641 const bool startAfter = tor->isStopping ? false : true;
1642 tr_torrentStop( tor );
1643 tor->startAfterVerify = startAfter;
1646 if( setLocalErrorIfFilesDisappeared( tor ) )
1647 tor->startAfterVerify = false;
1648 else
1649 tr_verifyAdd( tor, torrentRecheckDoneCB );
1651 tr_sessionUnlock( tor->session );
1654 void
1655 tr_torrentVerify( tr_torrent * tor )
1657 if( tr_isTorrent( tor ) )
1658 tr_runInEventThread( tor->session, verifyTorrent, tor );
1661 void
1662 tr_torrentSave( tr_torrent * tor )
1664 assert( tr_isTorrent( tor ) );
1666 if( tor->isDirty )
1668 tor->isDirty = false;
1669 tr_torrentSaveResume( tor );
1673 static void
1674 stopTorrent( void * vtor )
1676 tr_torrent * tor = vtor;
1677 tr_torinf( tor, "Pausing" );
1679 assert( tr_isTorrent( tor ) );
1681 tr_torrentLock( tor );
1683 tr_verifyRemove( tor );
1684 tr_peerMgrStopTorrent( tor );
1685 tr_announcerTorrentStopped( tor );
1686 tr_cacheFlushTorrent( tor->session->cache, tor );
1688 tr_fdTorrentClose( tor->session, tor->uniqueId );
1690 if( !tor->isDeleting )
1691 tr_torrentSave( tor );
1693 tr_torrentUnlock( tor );
1696 void
1697 tr_torrentStop( tr_torrent * tor )
1699 assert( tr_isTorrent( tor ) );
1701 if( tr_isTorrent( tor ) )
1703 tr_sessionLock( tor->session );
1705 tor->isRunning = 0;
1706 tor->isStopping = 0;
1707 tr_torrentSetDirty( tor );
1708 tr_runInEventThread( tor->session, stopTorrent, tor );
1710 tr_sessionUnlock( tor->session );
1714 static void
1715 closeTorrent( void * vtor )
1717 tr_benc * d;
1718 tr_torrent * tor = vtor;
1720 assert( tr_isTorrent( tor ) );
1722 d = tr_bencListAddDict( &tor->session->removedTorrents, 2 );
1723 tr_bencDictAddInt( d, "id", tor->uniqueId );
1724 tr_bencDictAddInt( d, "date", tr_time( ) );
1726 tr_torinf( tor, "%s", _( "Removing torrent" ) );
1728 stopTorrent( tor );
1730 if( tor->isDeleting )
1732 tr_metainfoRemoveSaved( tor->session, &tor->info );
1733 tr_torrentRemoveResume( tor );
1736 tor->isRunning = 0;
1737 freeTorrent( tor );
1740 void
1741 tr_torrentFree( tr_torrent * tor )
1743 if( tr_isTorrent( tor ) )
1745 tr_session * session = tor->session;
1746 assert( tr_isSession( session ) );
1747 tr_sessionLock( session );
1749 tr_torrentClearCompletenessCallback( tor );
1750 tr_runInEventThread( session, closeTorrent, tor );
1752 tr_sessionUnlock( session );
1756 struct remove_data
1758 tr_torrent * tor;
1759 bool deleteFlag;
1760 tr_fileFunc * deleteFunc;
1763 static void tr_torrentDeleteLocalData( tr_torrent *, tr_fileFunc );
1765 static void
1766 removeTorrent( void * vdata )
1768 struct remove_data * data = vdata;
1770 if( data->deleteFlag )
1771 tr_torrentDeleteLocalData( data->tor, data->deleteFunc );
1773 tr_torrentClearCompletenessCallback( data->tor );
1774 closeTorrent( data->tor );
1775 tr_free( data );
1778 void
1779 tr_torrentRemove( tr_torrent * tor,
1780 bool deleteFlag,
1781 tr_fileFunc deleteFunc )
1783 struct remove_data * data;
1785 assert( tr_isTorrent( tor ) );
1786 tor->isDeleting = 1;
1788 data = tr_new0( struct remove_data, 1 );
1789 data->tor = tor;
1790 data->deleteFlag = deleteFlag;
1791 data->deleteFunc = deleteFunc;
1792 tr_runInEventThread( tor->session, removeTorrent, data );
1796 *** Completeness
1799 static const char *
1800 getCompletionString( int type )
1802 switch( type )
1804 /* Translators: this is a minor point that's safe to skip over, but FYI:
1805 "Complete" and "Done" are specific, different terms in Transmission:
1806 "Complete" means we've downloaded every file in the torrent.
1807 "Done" means we're done downloading the files we wanted, but NOT all
1808 that exist */
1809 case TR_PARTIAL_SEED:
1810 return _( "Done" );
1812 case TR_SEED:
1813 return _( "Complete" );
1815 default:
1816 return _( "Incomplete" );
1820 static void
1821 fireCompletenessChange( tr_torrent * tor,
1822 tr_completeness status,
1823 bool wasRunning )
1825 assert( ( status == TR_LEECH )
1826 || ( status == TR_SEED )
1827 || ( status == TR_PARTIAL_SEED ) );
1829 if( tor->completeness_func )
1830 tor->completeness_func( tor, status, wasRunning,
1831 tor->completeness_func_user_data );
1834 void
1835 tr_torrentSetCompletenessCallback( tr_torrent * tor,
1836 tr_torrent_completeness_func func,
1837 void * user_data )
1839 assert( tr_isTorrent( tor ) );
1841 tor->completeness_func = func;
1842 tor->completeness_func_user_data = user_data;
1845 void
1846 tr_torrentClearCompletenessCallback( tr_torrent * torrent )
1848 tr_torrentSetCompletenessCallback( torrent, NULL, NULL );
1851 void
1852 tr_torrentSetRatioLimitHitCallback( tr_torrent * tor,
1853 tr_torrent_ratio_limit_hit_func func,
1854 void * user_data )
1856 assert( tr_isTorrent( tor ) );
1858 tor->ratio_limit_hit_func = func;
1859 tor->ratio_limit_hit_func_user_data = user_data;
1862 void
1863 tr_torrentClearRatioLimitHitCallback( tr_torrent * torrent )
1865 tr_torrentSetRatioLimitHitCallback( torrent, NULL, NULL );
1868 void
1869 tr_torrentSetIdleLimitHitCallback( tr_torrent * tor,
1870 tr_torrent_idle_limit_hit_func func,
1871 void * user_data )
1873 assert( tr_isTorrent( tor ) );
1875 tor->idle_limit_hit_func = func;
1876 tor->idle_limit_hit_func_user_data = user_data;
1879 void
1880 tr_torrentClearIdleLimitHitCallback( tr_torrent * torrent )
1882 tr_torrentSetIdleLimitHitCallback( torrent, NULL, NULL );
1885 static void
1886 onSigCHLD( int i UNUSED )
1888 waitpid( -1, NULL, WNOHANG );
1891 static void
1892 torrentCallScript( const tr_torrent * tor, const char * script )
1894 char timeStr[128];
1895 const time_t now = tr_time( );
1897 tr_strlcpy( timeStr, ctime( &now ), sizeof( timeStr ) );
1898 *strchr( timeStr,'\n' ) = '\0';
1900 if( script && *script )
1902 int i;
1903 char * cmd[] = { tr_strdup( script ), NULL };
1904 char * env[] = {
1905 tr_strdup_printf( "TR_APP_VERSION=%s", SHORT_VERSION_STRING ),
1906 tr_strdup_printf( "TR_TIME_LOCALTIME=%s", timeStr ),
1907 tr_strdup_printf( "TR_TORRENT_DIR=%s", tor->currentDir ),
1908 tr_strdup_printf( "TR_TORRENT_ID=%d", tr_torrentId( tor ) ),
1909 tr_strdup_printf( "TR_TORRENT_HASH=%s", tor->info.hashString ),
1910 tr_strdup_printf( "TR_TORRENT_NAME=%s", tr_torrentName( tor ) ),
1911 NULL };
1913 tr_torinf( tor, "Calling script \"%s\"", script );
1915 #ifdef WIN32
1916 _spawnvpe( _P_NOWAIT, script, (const char*)cmd, env );
1917 #else
1918 signal( SIGCHLD, onSigCHLD );
1920 if( !fork( ) )
1922 for (i=0; env[i]; ++i)
1923 putenv(env[i]);
1924 execvp( script, cmd );
1925 _exit( 0 );
1927 #endif
1929 for( i=0; cmd[i]; ++i ) tr_free( cmd[i] );
1930 for( i=0; env[i]; ++i ) tr_free( env[i] );
1934 void
1935 tr_torrentRecheckCompleteness( tr_torrent * tor )
1937 tr_completeness completeness;
1939 assert( tr_isTorrent( tor ) );
1941 tr_torrentLock( tor );
1943 completeness = tr_cpGetStatus( &tor->completion );
1945 if( completeness != tor->completeness )
1947 const int recentChange = tor->downloadedCur != 0;
1948 const bool wasLeeching = !tr_torrentIsSeed( tor );
1949 const bool wasRunning = tor->isRunning;
1951 if( recentChange )
1953 tr_torinf( tor, _( "State changed from \"%1$s\" to \"%2$s\"" ),
1954 getCompletionString( tor->completeness ),
1955 getCompletionString( completeness ) );
1958 tor->completeness = completeness;
1959 tr_fdTorrentClose( tor->session, tor->uniqueId );
1961 if( tr_torrentIsSeed( tor ) )
1963 if( recentChange )
1965 tr_announcerTorrentCompleted( tor );
1966 tor->doneDate = tor->anyDate = tr_time( );
1969 if( wasLeeching && wasRunning )
1971 /* clear interested flag on all peers */
1972 tr_peerMgrClearInterest( tor );
1974 /* if completeness was TR_LEECH then the seed limit check will have been skipped in bandwidthPulse */
1975 tr_torrentCheckSeedLimit( tor );
1978 if( tor->currentDir == tor->incompleteDir )
1979 tr_torrentSetLocation( tor, tor->downloadDir, true, NULL, NULL );
1981 if( tr_sessionIsTorrentDoneScriptEnabled( tor->session ) )
1982 torrentCallScript( tor, tr_sessionGetTorrentDoneScript( tor->session ) );
1985 fireCompletenessChange( tor, completeness, wasRunning );
1987 tr_torrentSetDirty( tor );
1990 tr_torrentUnlock( tor );
1993 /***
1994 ****
1995 ***/
1997 static void
1998 tr_torrentFireMetadataCompleted( tr_torrent * tor )
2000 assert( tr_isTorrent( tor ) );
2002 if( tor->metadata_func )
2003 tor->metadata_func( tor, tor->metadata_func_user_data );
2006 void
2007 tr_torrentSetMetadataCallback( tr_torrent * tor,
2008 tr_torrent_metadata_func func,
2009 void * user_data )
2011 assert( tr_isTorrent( tor ) );
2013 tor->metadata_func = func;
2014 tor->metadata_func_user_data = user_data;
2019 *** File priorities
2022 void
2023 tr_torrentInitFilePriority( tr_torrent * tor,
2024 tr_file_index_t fileIndex,
2025 tr_priority_t priority )
2027 tr_piece_index_t i;
2028 tr_file * file;
2030 assert( tr_isTorrent( tor ) );
2031 assert( fileIndex < tor->info.fileCount );
2032 assert( tr_isPriority( priority ) );
2034 file = &tor->info.files[fileIndex];
2035 file->priority = priority;
2036 for( i = file->firstPiece; i <= file->lastPiece; ++i )
2037 tor->info.pieces[i].priority = calculatePiecePriority( tor, i, fileIndex );
2040 void
2041 tr_torrentSetFilePriorities( tr_torrent * tor,
2042 const tr_file_index_t * files,
2043 tr_file_index_t fileCount,
2044 tr_priority_t priority )
2046 tr_file_index_t i;
2047 assert( tr_isTorrent( tor ) );
2048 tr_torrentLock( tor );
2050 for( i = 0; i < fileCount; ++i )
2051 if( files[i] < tor->info.fileCount )
2052 tr_torrentInitFilePriority( tor, files[i], priority );
2053 tr_torrentSetDirty( tor );
2054 tr_peerMgrRebuildRequests( tor );
2056 tr_torrentUnlock( tor );
2059 tr_priority_t*
2060 tr_torrentGetFilePriorities( const tr_torrent * tor )
2062 tr_file_index_t i;
2063 tr_priority_t * p;
2065 assert( tr_isTorrent( tor ) );
2067 tr_torrentLock( tor );
2068 p = tr_new0( tr_priority_t, tor->info.fileCount );
2069 for( i = 0; i < tor->info.fileCount; ++i )
2070 p[i] = tor->info.files[i].priority;
2071 tr_torrentUnlock( tor );
2073 return p;
2077 *** File DND
2080 static void
2081 setFileDND( tr_torrent * tor, tr_file_index_t fileIndex, int doDownload )
2083 const int8_t dnd = !doDownload;
2084 tr_piece_index_t firstPiece;
2085 int8_t firstPieceDND;
2086 tr_piece_index_t lastPiece;
2087 int8_t lastPieceDND;
2088 tr_file_index_t i;
2089 tr_file * file = &tor->info.files[fileIndex];
2091 file->dnd = dnd;
2092 firstPiece = file->firstPiece;
2093 lastPiece = file->lastPiece;
2095 /* can't set the first piece to DND unless
2096 every file using that piece is DND */
2097 firstPieceDND = dnd;
2098 if( fileIndex > 0 )
2100 for( i = fileIndex - 1; firstPieceDND; --i )
2102 if( tor->info.files[i].lastPiece != firstPiece )
2103 break;
2104 firstPieceDND = tor->info.files[i].dnd;
2105 if( !i )
2106 break;
2110 /* can't set the last piece to DND unless
2111 every file using that piece is DND */
2112 lastPieceDND = dnd;
2113 for( i = fileIndex + 1; lastPieceDND && i < tor->info.fileCount; ++i )
2115 if( tor->info.files[i].firstPiece != lastPiece )
2116 break;
2117 lastPieceDND = tor->info.files[i].dnd;
2120 if( firstPiece == lastPiece )
2122 tor->info.pieces[firstPiece].dnd = firstPieceDND && lastPieceDND;
2124 else
2126 tr_piece_index_t pp;
2127 tor->info.pieces[firstPiece].dnd = firstPieceDND;
2128 tor->info.pieces[lastPiece].dnd = lastPieceDND;
2129 for( pp = firstPiece + 1; pp < lastPiece; ++pp )
2130 tor->info.pieces[pp].dnd = dnd;
2134 void
2135 tr_torrentInitFileDLs( tr_torrent * tor,
2136 const tr_file_index_t * files,
2137 tr_file_index_t fileCount,
2138 bool doDownload )
2140 tr_file_index_t i;
2142 assert( tr_isTorrent( tor ) );
2144 tr_torrentLock( tor );
2146 for( i=0; i<fileCount; ++i )
2147 if( files[i] < tor->info.fileCount )
2148 setFileDND( tor, files[i], doDownload );
2150 tr_cpInvalidateDND( &tor->completion );
2152 tr_torrentUnlock( tor );
2155 void
2156 tr_torrentSetFileDLs( tr_torrent * tor,
2157 const tr_file_index_t * files,
2158 tr_file_index_t fileCount,
2159 bool doDownload )
2161 assert( tr_isTorrent( tor ) );
2162 tr_torrentLock( tor );
2164 tr_torrentInitFileDLs( tor, files, fileCount, doDownload );
2165 tr_torrentSetDirty( tor );
2166 tr_peerMgrRebuildRequests( tor );
2168 tr_torrentUnlock( tor );
2171 /***
2172 ****
2173 ***/
2175 tr_priority_t
2176 tr_torrentGetPriority( const tr_torrent * tor )
2178 assert( tr_isTorrent( tor ) );
2180 return tor->bandwidth.priority;
2183 void
2184 tr_torrentSetPriority( tr_torrent * tor, tr_priority_t priority )
2186 assert( tr_isTorrent( tor ) );
2187 assert( tr_isPriority( priority ) );
2189 if( tor->bandwidth.priority != priority )
2191 tor->bandwidth.priority = priority;
2193 tr_torrentSetDirty( tor );
2197 /***
2198 ****
2199 ***/
2201 void
2202 tr_torrentSetPeerLimit( tr_torrent * tor,
2203 uint16_t maxConnectedPeers )
2205 assert( tr_isTorrent( tor ) );
2207 if ( tor->maxConnectedPeers != maxConnectedPeers )
2209 tor->maxConnectedPeers = maxConnectedPeers;
2211 tr_torrentSetDirty( tor );
2215 uint16_t
2216 tr_torrentGetPeerLimit( const tr_torrent * tor )
2218 assert( tr_isTorrent( tor ) );
2220 return tor->maxConnectedPeers;
2223 /***
2224 ****
2225 ***/
2227 void
2228 tr_torrentGetBlockLocation( const tr_torrent * tor,
2229 tr_block_index_t block,
2230 tr_piece_index_t * piece,
2231 uint32_t * offset,
2232 uint32_t * length )
2234 uint64_t pos = block;
2235 pos *= tor->blockSize;
2236 *piece = pos / tor->info.pieceSize;
2237 *offset = pos - ( *piece * tor->info.pieceSize );
2238 *length = tr_torBlockCountBytes( tor, block );
2242 tr_block_index_t
2243 _tr_block( const tr_torrent * tor,
2244 tr_piece_index_t index,
2245 uint32_t offset )
2247 tr_block_index_t ret;
2249 assert( tr_isTorrent( tor ) );
2251 ret = index;
2252 ret *= ( tor->info.pieceSize / tor->blockSize );
2253 ret += offset / tor->blockSize;
2254 return ret;
2257 bool
2258 tr_torrentReqIsValid( const tr_torrent * tor,
2259 tr_piece_index_t index,
2260 uint32_t offset,
2261 uint32_t length )
2263 int err = 0;
2265 assert( tr_isTorrent( tor ) );
2267 if( index >= tor->info.pieceCount )
2268 err = 1;
2269 else if( length < 1 )
2270 err = 2;
2271 else if( ( offset + length ) > tr_torPieceCountBytes( tor, index ) )
2272 err = 3;
2273 else if( length > MAX_BLOCK_SIZE )
2274 err = 4;
2275 else if( tr_pieceOffset( tor, index, offset, length ) > tor->info.totalSize )
2276 err = 5;
2278 if( err ) tr_tordbg( tor, "index %lu offset %lu length %lu err %d\n",
2279 (unsigned long)index,
2280 (unsigned long)offset,
2281 (unsigned long)length,
2282 err );
2284 return !err;
2287 uint64_t
2288 tr_pieceOffset( const tr_torrent * tor,
2289 tr_piece_index_t index,
2290 uint32_t offset,
2291 uint32_t length )
2293 uint64_t ret;
2295 assert( tr_isTorrent( tor ) );
2297 ret = tor->info.pieceSize;
2298 ret *= index;
2299 ret += offset;
2300 ret += length;
2301 return ret;
2304 void
2305 tr_torGetFileBlockRange( const tr_torrent * tor,
2306 const tr_file_index_t file,
2307 tr_block_index_t * first,
2308 tr_block_index_t * last )
2310 const tr_file * f = &tor->info.files[file];
2311 uint64_t offset = f->offset;
2312 *first = offset / tor->blockSize;
2313 if( !f->length )
2314 *last = *first;
2315 else {
2316 offset += f->length - 1;
2317 *last = offset / tor->blockSize;
2321 void
2322 tr_torGetPieceBlockRange( const tr_torrent * tor,
2323 const tr_piece_index_t piece,
2324 tr_block_index_t * first,
2325 tr_block_index_t * last )
2327 uint64_t offset = tor->info.pieceSize;
2328 offset *= piece;
2329 *first = offset / tor->blockSize;
2330 offset += ( tr_torPieceCountBytes( tor, piece ) - 1 );
2331 *last = offset / tor->blockSize;
2335 /***
2336 ****
2337 ***/
2339 void
2340 tr_torrentSetPieceChecked( tr_torrent * tor, tr_piece_index_t pieceIndex )
2342 assert( tr_isTorrent( tor ) );
2343 assert( pieceIndex < tor->info.pieceCount );
2345 tor->info.pieces[pieceIndex].timeChecked = tr_time( );
2348 void
2349 tr_torrentSetChecked( tr_torrent * tor, time_t when )
2351 tr_piece_index_t i, n;
2353 assert( tr_isTorrent( tor ) );
2355 for( i=0, n=tor->info.pieceCount; i!=n; ++i )
2356 tor->info.pieces[i].timeChecked = when;
2359 bool
2360 tr_torrentCheckPiece( tr_torrent * tor, tr_piece_index_t pieceIndex )
2362 const bool pass = tr_ioTestPiece( tor, pieceIndex );
2364 tr_deeplog_tor( tor, "[LAZY] tr_torrentCheckPiece tested piece %zu, pass==%d", (size_t)pieceIndex, (int)pass );
2365 tr_torrentSetHasPiece( tor, pieceIndex, pass );
2366 tr_torrentSetPieceChecked( tor, pieceIndex );
2367 tor->anyDate = tr_time( );
2368 tr_torrentSetDirty( tor );
2370 return pass;
2373 time_t
2374 tr_torrentGetFileMTime( const tr_torrent * tor, tr_file_index_t i )
2376 time_t mtime = 0;
2377 if( !tr_fdFileGetCachedMTime( tor->session, tor->uniqueId, i, &mtime ) )
2378 tr_torrentFindFile2( tor, i, NULL, NULL, &mtime );
2379 return mtime;
2382 bool
2383 tr_torrentPieceNeedsCheck( const tr_torrent * tor, tr_piece_index_t p )
2385 uint64_t unused;
2386 tr_file_index_t f;
2387 const tr_info * inf = tr_torrentInfo( tor );
2389 /* if we've never checked this piece, then it needs to be checked */
2390 if( !inf->pieces[p].timeChecked )
2391 return true;
2393 /* If we think we've completed one of the files in this piece,
2394 * but it's been modified since we last checked it,
2395 * then it needs to be rechecked */
2396 tr_ioFindFileLocation( tor, p, 0, &f, &unused );
2397 for( ; f < inf->fileCount && pieceHasFile( p, &inf->files[f] ); ++f )
2398 if( tr_cpFileIsComplete( &tor->completion, f ) )
2399 if( tr_torrentGetFileMTime( tor, f ) > inf->pieces[p].timeChecked )
2400 return true;
2402 return false;
2405 /***
2406 ****
2407 ***/
2409 static int
2410 compareTrackerByTier( const void * va, const void * vb )
2412 const tr_tracker_info * a = va;
2413 const tr_tracker_info * b = vb;
2415 /* sort by tier */
2416 if( a->tier != b->tier )
2417 return a->tier - b->tier;
2419 /* get the effects of a stable sort by comparing the two elements' addresses */
2420 return a - b;
2423 bool
2424 tr_torrentSetAnnounceList( tr_torrent * tor,
2425 const tr_tracker_info * trackers_in,
2426 int trackerCount )
2428 int i;
2429 tr_benc metainfo;
2430 bool ok = true;
2431 tr_tracker_info * trackers;
2433 tr_torrentLock( tor );
2435 assert( tr_isTorrent( tor ) );
2437 /* ensure the trackers' tiers are in ascending order */
2438 trackers = tr_memdup( trackers_in, sizeof( tr_tracker_info ) * trackerCount );
2439 qsort( trackers, trackerCount, sizeof( tr_tracker_info ), compareTrackerByTier );
2441 /* look for bad URLs */
2442 for( i=0; ok && i<trackerCount; ++i )
2443 if( !tr_urlIsValidTracker( trackers[i].announce ) )
2444 ok = false;
2446 /* save to the .torrent file */
2447 if( ok && !tr_bencLoadFile( &metainfo, TR_FMT_BENC, tor->info.torrent ) )
2449 bool hasInfo;
2450 tr_info tmpInfo;
2452 /* remove the old fields */
2453 tr_bencDictRemove( &metainfo, "announce" );
2454 tr_bencDictRemove( &metainfo, "announce-list" );
2456 /* add the new fields */
2457 if( trackerCount > 0 )
2459 tr_bencDictAddStr( &metainfo, "announce", trackers[0].announce );
2461 if( trackerCount > 1 )
2463 int i;
2464 int prevTier = -1;
2465 tr_benc * tier = NULL;
2466 tr_benc * announceList = tr_bencDictAddList( &metainfo, "announce-list", 0 );
2468 for( i=0; i<trackerCount; ++i ) {
2469 if( prevTier != trackers[i].tier ) {
2470 prevTier = trackers[i].tier;
2471 tier = tr_bencListAddList( announceList, 0 );
2473 tr_bencListAddStr( tier, trackers[i].announce );
2477 /* try to parse it back again, to make sure it's good */
2478 memset( &tmpInfo, 0, sizeof( tr_info ) );
2479 if( tr_metainfoParse( tor->session, &metainfo, &tmpInfo,
2480 &hasInfo, &tor->infoDictLength ) )
2482 /* it's good, so keep these new trackers and free the old ones */
2484 tr_info swap;
2485 swap.trackers = tor->info.trackers;
2486 swap.trackerCount = tor->info.trackerCount;
2487 tor->info.trackers = tmpInfo.trackers;
2488 tor->info.trackerCount = tmpInfo.trackerCount;
2489 tmpInfo.trackers = swap.trackers;
2490 tmpInfo.trackerCount = swap.trackerCount;
2492 tr_metainfoFree( &tmpInfo );
2493 tr_bencToFile( &metainfo, TR_FMT_BENC, tor->info.torrent );
2496 /* cleanup */
2497 tr_bencFree( &metainfo );
2499 /* if we had a tracker-related error on this torrent,
2500 * and that tracker's been removed,
2501 * then clear the error */
2502 if( ( tor->error == TR_STAT_TRACKER_WARNING )
2503 || ( tor->error == TR_STAT_TRACKER_ERROR ) )
2505 bool clear = true;
2507 for( i=0; clear && i<trackerCount; ++i )
2508 if( !strcmp( trackers[i].announce, tor->errorTracker ) )
2509 clear = false;
2511 if( clear )
2512 tr_torrentClearError( tor );
2515 /* tell the announcer to reload this torrent's tracker list */
2516 tr_announcerResetTorrent( tor->session->announcer, tor );
2519 tr_torrentUnlock( tor );
2521 tr_free( trackers );
2522 return ok;
2529 void
2530 tr_torrentSetAddedDate( tr_torrent * tor,
2531 time_t t )
2533 assert( tr_isTorrent( tor ) );
2535 tor->addedDate = t;
2536 tor->anyDate = MAX( tor->anyDate, tor->addedDate );
2539 void
2540 tr_torrentSetActivityDate( tr_torrent * tor, time_t t )
2542 assert( tr_isTorrent( tor ) );
2544 tor->activityDate = t;
2545 tor->anyDate = MAX( tor->anyDate, tor->activityDate );
2548 void
2549 tr_torrentSetDoneDate( tr_torrent * tor,
2550 time_t t )
2552 assert( tr_isTorrent( tor ) );
2554 tor->doneDate = t;
2555 tor->anyDate = MAX( tor->anyDate, tor->doneDate );
2562 uint64_t
2563 tr_torrentGetBytesLeftToAllocate( const tr_torrent * tor )
2565 tr_file_index_t i;
2566 uint64_t bytesLeft = 0;
2568 assert( tr_isTorrent( tor ) );
2570 for( i=0; i<tor->info.fileCount; ++i )
2572 if( !tor->info.files[i].dnd )
2574 struct stat sb;
2575 const uint64_t length = tor->info.files[i].length;
2576 char * path = tr_torrentFindFile( tor, i );
2578 bytesLeft += length;
2580 if( ( path != NULL ) && !stat( path, &sb )
2581 && S_ISREG( sb.st_mode )
2582 && ( (uint64_t)sb.st_size <= length ) )
2583 bytesLeft -= sb.st_size;
2585 tr_free( path );
2589 return bytesLeft;
2592 /****
2593 ***** Removing the torrent's local data
2594 ****/
2596 static int
2597 vstrcmp( const void * a, const void * b )
2599 return strcmp( a, b );
2602 static int
2603 compareLongestFirst( const void * a, const void * b )
2605 const size_t alen = strlen( a );
2606 const size_t blen = strlen( b );
2608 if( alen != blen )
2609 return alen > blen ? -1 : 1;
2611 return vstrcmp( a, b );
2614 static void
2615 addDirtyFile( const char * root,
2616 const char * filename,
2617 tr_ptrArray * dirtyFolders )
2619 char * dir = tr_dirname( filename );
2621 /* add the parent folders to dirtyFolders until we reach the root or a known-dirty */
2622 while ( ( dir != NULL )
2623 && ( strlen( root ) <= strlen( dir ) )
2624 && ( tr_ptrArrayFindSorted( dirtyFolders, dir, vstrcmp ) == NULL ) )
2626 char * tmp;
2627 tr_ptrArrayInsertSorted( dirtyFolders, tr_strdup( dir ), vstrcmp );
2629 tmp = tr_dirname( dir );
2630 tr_free( dir );
2631 dir = tmp;
2634 tr_free( dir );
2637 static bool
2638 isSystemFile( const char * base )
2640 int i;
2641 static const char * stockFiles[] = { ".DS_Store", "desktop.ini", "Thumbs.db" };
2642 static const int stockFileCount = sizeof(stockFiles) / sizeof(stockFiles[0]);
2644 for( i=0; i<stockFileCount; ++i )
2645 if( !strcmp( base, stockFiles[i] ) )
2646 return true;
2648 /* check for resource forks. <http://support.apple.com/kb/TA20578> */
2649 if( !memcmp( base, "._", 2 ) )
2650 return true;
2652 return false;
2655 static void
2656 deleteLocalFile( const tr_torrent * tor, const char * filename, tr_fileFunc fileFunc )
2658 struct stat sb;
2660 /* add safeguards for (1) making sure the file exists and
2661 (2) that we haven't somehow walked up past the torrent's top directory... */
2662 if( !stat( filename, &sb ) )
2663 if( !tr_is_same_file( tor->currentDir, filename ) )
2664 fileFunc( filename );
2667 static void
2668 walkLocalData( const tr_torrent * tor,
2669 const char * root,
2670 const char * dir,
2671 const char * base,
2672 tr_ptrArray * torrentFiles,
2673 tr_ptrArray * folders,
2674 tr_ptrArray * dirtyFolders,
2675 tr_fileFunc fileFunc )
2677 struct stat sb;
2678 char * buf = tr_buildPath( dir, base, NULL );
2679 int i = stat( buf, &sb );
2681 if( !i )
2683 DIR * odir = NULL;
2685 if( S_ISDIR( sb.st_mode ) && ( ( odir = opendir ( buf ) ) ) )
2687 struct dirent *d;
2688 tr_ptrArrayInsertSorted( folders, tr_strdup( buf ), vstrcmp );
2689 for( d = readdir( odir ); d != NULL; d = readdir( odir ) )
2690 if( d->d_name && strcmp( d->d_name, "." ) && strcmp( d->d_name, ".." ) )
2691 walkLocalData( tor, root, buf, d->d_name, torrentFiles, folders, dirtyFolders, fileFunc );
2692 closedir( odir );
2694 else if( S_ISREG( sb.st_mode ) && ( sb.st_size > 0 ) )
2696 if( isSystemFile( base ) )
2697 deleteLocalFile( tor, buf, fileFunc );
2698 else {
2699 const char * sub = buf + strlen( tor->currentDir ) + strlen( TR_PATH_DELIMITER_STR );
2700 const bool isTorrentFile = tr_ptrArrayFindSorted( torrentFiles, sub, vstrcmp ) != NULL;
2701 if( !isTorrentFile )
2702 addDirtyFile( root, buf, dirtyFolders );
2707 tr_free( buf );
2710 static void
2711 deleteLocalData( tr_torrent * tor, tr_fileFunc fileFunc )
2713 int i, n;
2714 char ** s;
2715 tr_file_index_t f;
2716 tr_ptrArray torrentFiles = TR_PTR_ARRAY_INIT;
2717 tr_ptrArray folders = TR_PTR_ARRAY_INIT;
2718 tr_ptrArray dirtyFolders = TR_PTR_ARRAY_INIT; /* dirty == contains non-torrent files */
2720 const char * firstFile = tor->info.files[0].name;
2721 const char * cpch = strchr( firstFile, TR_PATH_DELIMITER );
2722 char * tmp = cpch ? tr_strndup( firstFile, cpch - firstFile ) : NULL;
2723 char * root = tr_buildPath( tor->currentDir, tmp, NULL );
2725 for( f=0; f<tor->info.fileCount; ++f ) {
2726 tr_ptrArrayInsertSorted( &torrentFiles, tr_strdup( tor->info.files[f].name ), vstrcmp );
2727 tr_ptrArrayInsertSorted( &torrentFiles, tr_torrentBuildPartial( tor, f ), vstrcmp );
2730 /* build the set of folders and dirtyFolders */
2731 walkLocalData( tor, root, root, NULL, &torrentFiles, &folders, &dirtyFolders, fileFunc );
2733 /* try to remove entire folders first, so that the recycle bin will be tidy */
2734 s = (char**) tr_ptrArrayPeek( &folders, &n );
2735 for( i=0; i<n; ++i )
2736 if( tr_ptrArrayFindSorted( &dirtyFolders, s[i], vstrcmp ) == NULL )
2737 deleteLocalFile( tor, s[i], fileFunc );
2739 /* now blow away any remaining torrent files, such as torrent files in dirty folders */
2740 for( i=0, n=tr_ptrArraySize( &torrentFiles ); i<n; ++i ) {
2741 char * path = tr_buildPath( tor->currentDir, tr_ptrArrayNth( &torrentFiles, i ), NULL );
2742 deleteLocalFile( tor, path, fileFunc );
2743 tr_free( path );
2746 /* Now clean out the directories left empty from the previous step.
2747 * Work from deepest to shallowest s.t. lower folders
2748 * won't prevent the upper folders from being deleted */
2750 tr_ptrArray cleanFolders = TR_PTR_ARRAY_INIT;
2751 s = (char**) tr_ptrArrayPeek( &folders, &n );
2752 for( i=0; i<n; ++i )
2753 if( tr_ptrArrayFindSorted( &dirtyFolders, s[i], vstrcmp ) == NULL )
2754 tr_ptrArrayInsertSorted( &cleanFolders, s[i], compareLongestFirst );
2755 s = (char**) tr_ptrArrayPeek( &cleanFolders, &n );
2756 for( i=0; i<n; ++i )
2757 deleteLocalFile( tor, s[i], fileFunc );
2758 tr_ptrArrayDestruct( &cleanFolders, NULL );
2761 /* cleanup */
2762 tr_ptrArrayDestruct( &dirtyFolders, tr_free );
2763 tr_ptrArrayDestruct( &folders, tr_free );
2764 tr_ptrArrayDestruct( &torrentFiles, tr_free );
2765 tr_free( root );
2766 tr_free( tmp );
2769 static void
2770 tr_torrentDeleteLocalData( tr_torrent * tor, tr_fileFunc fileFunc )
2772 assert( tr_isTorrent( tor ) );
2774 if( fileFunc == NULL )
2775 fileFunc = remove;
2777 /* close all the files because we're about to delete them */
2778 tr_cacheFlushTorrent( tor->session->cache, tor );
2779 tr_fdTorrentClose( tor->session, tor->uniqueId );
2781 deleteLocalData( tor, fileFunc );
2784 /***
2785 ****
2786 ***/
2788 struct LocationData
2790 bool move_from_old_location;
2791 volatile int * setme_state;
2792 volatile double * setme_progress;
2793 char * location;
2794 tr_torrent * tor;
2797 static void
2798 setLocation( void * vdata )
2800 bool err = false;
2801 struct LocationData * data = vdata;
2802 tr_torrent * tor = data->tor;
2803 const bool do_move = data->move_from_old_location;
2804 const char * location = data->location;
2805 double bytesHandled = 0;
2807 assert( tr_isTorrent( tor ) );
2809 tr_dbg( "Moving \"%s\" location from currentDir \"%s\" to \"%s\"",
2810 tr_torrentName(tor), tor->currentDir, location );
2812 tr_mkdirp( location, 0777 );
2814 if( !tr_is_same_file( location, tor->currentDir ) )
2816 tr_file_index_t i;
2818 /* bad idea to move files while they're being verified... */
2819 tr_verifyRemove( tor );
2821 /* try to move the files.
2822 * FIXME: there are still all kinds of nasty cases, like what
2823 * if the target directory runs out of space halfway through... */
2824 for( i=0; !err && i<tor->info.fileCount; ++i )
2826 const tr_file * f = &tor->info.files[i];
2827 const char * oldbase;
2828 char * sub;
2829 if( tr_torrentFindFile2( tor, i, &oldbase, &sub, NULL ) )
2831 char * oldpath = tr_buildPath( oldbase, sub, NULL );
2832 char * newpath = tr_buildPath( location, sub, NULL );
2834 tr_dbg( "Found file #%d: %s", (int)i, oldpath );
2836 if( do_move && !tr_is_same_file( oldpath, newpath ) )
2838 bool renamed = false;
2839 errno = 0;
2840 tr_torinf( tor, "moving \"%s\" to \"%s\"", oldpath, newpath );
2841 if( tr_moveFile( oldpath, newpath, &renamed ) )
2843 err = true;
2844 tr_torerr( tor, "error moving \"%s\" to \"%s\": %s",
2845 oldpath, newpath, tr_strerror( errno ) );
2849 tr_free( newpath );
2850 tr_free( oldpath );
2851 tr_free( sub );
2854 if( data->setme_progress )
2856 bytesHandled += f->length;
2857 *data->setme_progress = bytesHandled / tor->info.totalSize;
2861 if( !err )
2863 /* blow away the leftover subdirectories in the old location */
2864 if( do_move )
2865 tr_torrentDeleteLocalData( tor, remove );
2867 /* set the new location and reverify */
2868 tr_torrentSetDownloadDir( tor, location );
2872 if( !err && do_move )
2874 tr_free( tor->incompleteDir );
2875 tor->incompleteDir = NULL;
2876 tor->currentDir = tor->downloadDir;
2879 if( data->setme_state )
2880 *data->setme_state = err ? TR_LOC_ERROR : TR_LOC_DONE;
2882 /* cleanup */
2883 tr_free( data->location );
2884 tr_free( data );
2887 void
2888 tr_torrentSetLocation( tr_torrent * tor,
2889 const char * location,
2890 bool move_from_old_location,
2891 volatile double * setme_progress,
2892 volatile int * setme_state )
2894 struct LocationData * data;
2896 assert( tr_isTorrent( tor ) );
2898 if( setme_state )
2899 *setme_state = TR_LOC_MOVING;
2900 if( setme_progress )
2901 *setme_progress = 0;
2903 /* run this in the libtransmission thread */
2904 data = tr_new( struct LocationData, 1 );
2905 data->tor = tor;
2906 data->location = tr_strdup( location );
2907 data->move_from_old_location = move_from_old_location;
2908 data->setme_state = setme_state;
2909 data->setme_progress = setme_progress;
2910 tr_runInEventThread( tor->session, setLocation, data );
2913 /***
2914 ****
2915 ***/
2917 void
2918 tr_torrentFileCompleted( tr_torrent * tor, tr_file_index_t fileNum )
2920 char * sub;
2921 const char * base;
2922 const tr_info * inf = &tor->info;
2923 const tr_file * f = &inf->files[fileNum];
2924 tr_piece * p;
2925 const tr_piece * pend;
2926 const time_t now = tr_time( );
2928 /* close the file so that we can reopen in read-only mode as needed */
2929 tr_fdFileClose( tor->session, tor, fileNum );
2931 /* now that the file is complete and closed, we can start watching its
2932 * mtime timestamp for changes to know if we need to reverify pieces */
2933 for( p=&inf->pieces[f->firstPiece], pend=&inf->pieces[f->lastPiece]; p!=pend; ++p )
2934 p->timeChecked = now;
2936 /* if the torrent's current filename isn't the same as the one in the
2937 * metadata -- for example, if it had the ".part" suffix appended to
2938 * it until now -- then rename it to match the one in the metadata */
2939 if( tr_torrentFindFile2( tor, fileNum, &base, &sub, NULL ) )
2941 if( strcmp( sub, f->name ) )
2943 char * oldpath = tr_buildPath( base, sub, NULL );
2944 char * newpath = tr_buildPath( base, f->name, NULL );
2946 if( rename( oldpath, newpath ) )
2947 tr_torerr( tor, "Error moving \"%s\" to \"%s\": %s", oldpath, newpath, tr_strerror( errno ) );
2949 tr_free( newpath );
2950 tr_free( oldpath );
2953 tr_free( sub );
2957 /***
2958 ****
2959 ***/
2961 #ifdef SYS_DARWIN
2962 #define TR_STAT_MTIME(sb) ((sb).st_mtimespec.tv_sec)
2963 #else
2964 #define TR_STAT_MTIME(sb) ((sb).st_mtime)
2965 #endif
2968 static bool
2969 fileExists( const char * filename, time_t * mtime )
2971 struct stat sb;
2972 const bool ok = !stat( filename, &sb );
2974 if( ok && ( mtime != NULL ) )
2975 *mtime = TR_STAT_MTIME( sb );
2977 return ok;
2980 bool
2981 tr_torrentFindFile2( const tr_torrent * tor, tr_file_index_t fileNum,
2982 const char ** base, char ** subpath, time_t * mtime )
2984 char * part = NULL;
2985 const tr_file * file;
2986 const char * b = NULL;
2987 const char * s = NULL;
2989 assert( tr_isTorrent( tor ) );
2990 assert( fileNum < tor->info.fileCount );
2992 file = &tor->info.files[fileNum];
2994 if( b == NULL ) {
2995 char * filename = tr_buildPath( tor->downloadDir, file->name, NULL );
2996 if( fileExists( filename, mtime ) ) {
2997 b = tor->downloadDir;
2998 s = file->name;
3000 tr_free( filename );
3003 if( ( b == NULL ) && ( tor->incompleteDir != NULL ) ) {
3004 char * filename = tr_buildPath( tor->incompleteDir, file->name, NULL );
3005 if( fileExists( filename, mtime ) ) {
3006 b = tor->incompleteDir;
3007 s = file->name;
3009 tr_free( filename );
3012 if( b == NULL )
3013 part = tr_torrentBuildPartial( tor, fileNum );
3015 if( ( b == NULL ) && ( tor->incompleteDir != NULL ) ) {
3016 char * filename = tr_buildPath( tor->incompleteDir, part, NULL );
3017 if( fileExists( filename, mtime ) ) {
3018 b = tor->incompleteDir;
3019 s = part;
3021 tr_free( filename );
3024 if( b == NULL) {
3025 char * filename = tr_buildPath( tor->downloadDir, part, NULL );
3026 if( fileExists( filename, mtime ) ) {
3027 b = tor->downloadDir;
3028 s = part;
3030 tr_free( filename );
3033 if( base != NULL )
3034 *base = b;
3035 if( subpath != NULL )
3036 *subpath = tr_strdup( s );
3038 tr_free( part );
3039 return b != NULL;
3042 char*
3043 tr_torrentFindFile( const tr_torrent * tor, tr_file_index_t fileNum )
3045 char * subpath;
3046 char * ret = NULL;
3047 const char * base;
3049 if( tr_torrentFindFile2( tor, fileNum, &base, &subpath, NULL ) )
3051 ret = tr_buildPath( base, subpath, NULL );
3052 tr_free( subpath );
3055 return ret;
3058 /* Decide whether we should be looking for files in downloadDir or incompleteDir. */
3059 static void
3060 refreshCurrentDir( tr_torrent * tor )
3062 const char * dir = NULL;
3064 if( tor->incompleteDir == NULL )
3065 dir = tor->downloadDir;
3066 else if( !tr_torrentHasMetadata( tor ) ) /* no files to find */
3067 dir = tor->incompleteDir;
3068 else if( !tr_torrentFindFile2( tor, 0, &dir, NULL, NULL ) )
3069 dir = tor->incompleteDir;
3071 assert( dir != NULL );
3072 assert( ( dir == tor->downloadDir ) || ( dir == tor->incompleteDir ) );
3073 tor->currentDir = dir;
3076 char*
3077 tr_torrentBuildPartial( const tr_torrent * tor, tr_file_index_t fileNum )
3079 return tr_strdup_printf( "%s.part", tor->info.files[fileNum].name );