Changeset 9328
- Timestamp:
- Oct 19, 2009, 5:05:00 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 2 deleted
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gtk/main.c
r9308 r9328 1127 1127 tr_sessionSetPeerPortRandomOnStart( tr, pref_flag_get( key ) ); 1128 1128 } 1129 else if( !strcmp( key, TR_PREFS_KEY_INCOMPLETE_DIR ) ) 1130 { 1131 tr_sessionSetIncompleteDir( tr, pref_string_get( key ) ); 1132 } 1133 else if( !strcmp( key, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED ) ) 1134 { 1135 tr_sessionSetIncompleteDirEnabled( tr, pref_flag_get( key ) ); 1136 } 1129 1137 } 1130 1138 -
trunk/gtk/tr-prefs.c
r9284 r9328 290 290 hig_workarea_add_row_w( t, &row, l, w, NULL ); 291 291 #endif 292 293 s = _( "Keep incomplete files in:" ); 294 l = new_check_button( s, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, core ); 295 w = new_path_chooser_button( TR_PREFS_KEY_INCOMPLETE_DIR, core ); 296 gtk_widget_set_sensitive( GTK_WIDGET( w ), pref_flag_get( TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED ) ); 297 g_signal_connect( l, "toggled", G_CALLBACK( target_cb ), w ); 298 hig_workarea_add_row_w( t, &row, l, w, NULL ); 292 299 293 300 s = _( "Display _options dialog" ); -
trunk/libtransmission/Makefile.am
r9259 r9328 21 21 ConvertUTF.c \ 22 22 crypto.c \ 23 fastresume.c \24 23 fdlimit.c \ 25 24 ggets.c \ … … 69 68 crypto.h \ 70 69 completion.h \ 71 fastresume.h \72 70 fdlimit.h \ 73 71 ggets.h \ -
trunk/libtransmission/fdlimit.c
r9066 r9328 84 84 struct tr_openfile 85 85 { 86 tr_bool isWritable; 87 int torrentId; 88 char filename[MAX_PATH_LENGTH]; 89 int fd; 90 uint64_t date; 86 tr_bool isWritable; 87 int torrentId; 88 tr_file_index_t fileNum; 89 char filename[MAX_PATH_LENGTH]; 90 int fd; 91 uint64_t date; 91 92 }; 92 93 … … 382 383 } 383 384 385 int 386 tr_fdFileGetCached( int torrentId, 387 tr_file_index_t fileNum, 388 tr_bool doWrite ) 389 { 390 int i; 391 struct tr_openfile * o; 392 393 assert( torrentId > 0 ); 394 assert( tr_isBool( doWrite ) ); 395 396 /* is it already open? */ 397 for( i=0; i<gFd->openFileLimit; ++i ) 398 { 399 o = &gFd->openFiles[i]; 400 401 if( !fileIsOpen( o ) ) 402 continue; 403 if( torrentId != o->torrentId ) 404 continue; 405 if( fileNum != o->fileNum ) 406 continue; 407 408 break; 409 } 410 411 if( ( o != NULL ) && ( !doWrite || o->isWritable ) ) 412 { 413 o->date = tr_date( ); 414 return o->fd; 415 } 416 417 return -1; 418 } 419 384 420 /* returns an fd on success, or a -1 on failure and sets errno */ 385 421 int 386 422 tr_fdFileCheckout( int torrentId, 423 tr_file_index_t fileNum, 387 424 const char * folder, 388 425 const char * torrentFile, … … 412 449 if( torrentId != o->torrentId ) 413 450 continue; 414 if( strcmp( filename, o->filename ))451 if( fileNum != o->fileNum ) 415 452 continue; 416 453 … … 479 516 dbgmsg( "checking out '%s' in slot %d", filename, winner ); 480 517 o->torrentId = torrentId; 518 o->fileNum = fileNum; 481 519 o->date = tr_date( ); 482 520 return o->fd; … … 484 522 485 523 void 486 tr_fdFileClose( const char * filename)524 tr_fdFileClose( const tr_torrent * tor, tr_file_index_t fileNum ) 487 525 { 488 526 struct tr_openfile * o; 489 527 const struct tr_openfile * end; 490 528 const int torrentId = tr_torrentId( tor ); 491 529 for( o=gFd->openFiles, end=o+gFd->openFileLimit; o!=end; ++o ) 492 530 { 493 if( !fileIsOpen( o ) || strcmp( filename, o->filename ) ) 494 continue; 495 dbgmsg( "tr_fdFileClose closing \"%s\"", filename ); 531 if( !fileIsOpen( o ) ) 532 continue; 533 if( torrentId != o->torrentId ) 534 continue; 535 if( fileNum != o->fileNum ) 536 continue; 537 538 dbgmsg( "tr_fdFileClose closing \"%s\"", o->filename ); 496 539 TrCloseFile( o ); 497 540 } -
trunk/libtransmission/fdlimit.h
r8935 r9328 66 66 */ 67 67 int tr_fdFileCheckout( int torrentId, 68 tr_file_index_t fileNum, 68 69 const char * folder, 69 70 const char * torrentFile, … … 71 72 tr_preallocation_mode preallocationMode, 72 73 uint64_t desiredFileSize ); 74 75 int tr_fdFileGetCached( int torrentId, 76 tr_file_index_t fileNum, 77 tr_bool doWrite ); 73 78 74 79 /** … … 80 85 * @see tr_fdFileCheckout 81 86 */ 82 void tr_fdFileClose( const char * filename);87 void tr_fdFileClose( const tr_torrent * tor, tr_file_index_t fileNo ); 83 88 84 89 -
trunk/libtransmission/inout.c
r9080 r9328 76 76 const tr_info * info = &tor->info; 77 77 const tr_file * file = &info->files[fileIndex]; 78 tr_preallocation_mode preallocationMode;79 78 80 79 typedef size_t ( *iofunc )( int, void *, size_t ); … … 82 81 struct stat sb; 83 82 int fd = -1; 84 int err ;85 int fileExists;86 87 assert( tor-> downloadDir && *tor->downloadDir );83 int err = 0; 84 const tr_bool doWrite = ioMode == TR_IO_WRITE; 85 86 assert( tor->currentDir && *tor->currentDir ); 88 87 assert( fileIndex < info->fileCount ); 89 88 assert( !file->length || ( fileOffset < file->length ) ); 90 89 assert( fileOffset + buflen <= file->length ); 91 90 92 {93 char path[MAX_PATH_LENGTH];94 tr_snprintf( path, sizeof( path ), "%s%c%s", tor->downloadDir, TR_PATH_DELIMITER, file->name );95 fileExists = !stat( path, &sb );96 }97 98 91 if( !file->length ) 99 92 return 0; 100 93 101 if( ( file->dnd ) || ( ioMode != TR_IO_WRITE ) ) 102 preallocationMode = TR_PREALLOCATE_NONE; 103 else 104 preallocationMode = tor->session->preallocationMode; 105 106 if( ( ioMode == TR_IO_READ ) && !fileExists ) /* does file exist? */ 107 err = ENOENT; 108 else if( ( fd = tr_fdFileCheckout( tor->uniqueId, tor->downloadDir, file->name, ioMode == TR_IO_WRITE, preallocationMode, file->length ) ) < 0 ) { 109 err = errno; 110 tr_torerr( tor, "tr_fdFileCheckout failed for \"%s\": %s", file->name, tr_strerror( err ) ); 111 } 112 else if( tr_lseek( fd, (int64_t)fileOffset, SEEK_SET ) == -1 ) { 113 err = errno; 114 tr_torerr( tor, "tr_lseek failed for \"%s\": %s", file->name, tr_strerror( err ) ); 115 } 116 else if( func( fd, buf, buflen ) != buflen ) { 117 err = errno; 118 tr_torerr( tor, "read/write failed for \"%s\": %s", file->name, tr_strerror( err ) ); 119 } 120 else 121 err = 0; 122 123 if( ( !err ) && ( !fileExists ) && ( ioMode == TR_IO_WRITE ) ) 124 tr_statsFileCreated( tor->session ); 94 fd = tr_fdFileGetCached( tr_torrentId( tor ), fileIndex, doWrite ); 95 96 if( fd < 0 ) 97 { 98 /* the fd cache doesn't have this file... 99 * we'll need to open it and maybe create it */ 100 char * name; 101 tr_preallocation_mode preallocationMode; 102 tr_bool fileExists; 103 104 { 105 char * path = tr_torrentFindFile( tor, fileIndex ); 106 107 fileExists = !stat( path, &sb ); 108 109 if( fileExists ) 110 name = tr_strdup( strstr( path, file->name ) ); 111 else 112 name = tr_strdup_printf( "%s.part", file->name ); 113 114 tr_free( path ); 115 } 116 117 if( ( file->dnd ) || ( ioMode != TR_IO_WRITE ) ) 118 preallocationMode = TR_PREALLOCATE_NONE; 119 else 120 preallocationMode = tor->session->preallocationMode; 121 122 if( ( ioMode == TR_IO_READ ) && !fileExists ) /* does file exist? */ 123 { 124 err = ENOENT; 125 } 126 else if( ( fd = tr_fdFileCheckout( tor->uniqueId, fileIndex, tor->currentDir, name, 127 doWrite, preallocationMode, file->length ) ) < 0 ) 128 { 129 err = errno; 130 tr_torerr( tor, "tr_fdFileCheckout failed for \"%s\": %s", name, tr_strerror( err ) ); 131 } 132 133 if( doWrite && !err ) 134 tr_statsFileCreated( tor->session ); 135 } 136 137 if( !err ) 138 { 139 if( tr_lseek( fd, (int64_t)fileOffset, SEEK_SET ) == -1 ) 140 { 141 err = errno; 142 tr_torerr( tor, "tr_lseek failed for \"%s\": %s", file->name, tr_strerror( err ) ); 143 } 144 else if( func( fd, buf, buflen ) != buflen ) 145 { 146 err = errno; 147 tr_torerr( tor, "read/write failed for \"%s\": %s", file->name, tr_strerror( err ) ); 148 } 149 } 125 150 126 151 return err; -
trunk/libtransmission/peer-mgr.c
r9239 r9328 26 26 #include "completion.h" 27 27 #include "crypto.h" 28 #include "fdlimit.h"29 28 #include "handshake.h" 30 29 #include "inout.h" /* tr_ioTestPiece */ … … 1156 1155 tr_peerMsgsHave( peers[i]->msgs, p ); 1157 1156 1158 for( fileIndex=0; fileIndex<tor->info.fileCount; ++fileIndex ) 1159 { 1157 for( fileIndex=0; fileIndex<tor->info.fileCount; ++fileIndex ) { 1160 1158 const tr_file * file = &tor->info.files[fileIndex]; 1161 if( ( file->firstPiece <= p ) && ( p <= file->lastPiece ) && tr_cpFileIsComplete( &tor->completion, fileIndex ) ) 1162 { 1163 char * path = tr_buildPath( tor->downloadDir, file->name, NULL ); 1164 tordbg( t, "closing recently-completed file \"%s\"", path ); 1165 tr_fdFileClose( path ); 1166 tr_free( path ); 1167 } 1159 if( ( file->firstPiece <= p ) && ( p <= file->lastPiece ) ) 1160 if( tr_cpFileIsComplete( &tor->completion, fileIndex ) ) 1161 tr_torrentFileCompleted( tor, fileIndex ); 1168 1162 } 1169 1163 } 1170 1171 tr_torrentRecheckCompleteness( tor );1172 1164 } 1173 1165 break; -
trunk/libtransmission/resume.c
r9218 r9328 18 18 #include "bencode.h" 19 19 #include "completion.h" 20 #include "fastresume.h"21 20 #include "peer-mgr.h" /* pex */ 22 21 #include "platform.h" /* tr_getResumeDir */ … … 33 32 #define KEY_DND "dnd" 34 33 #define KEY_DOWNLOADED "downloaded" 34 #define KEY_INCOMPLETE_DIR "incomplete-dir" 35 35 #define KEY_MAX_PEERS "max-peers" 36 36 #define KEY_PAUSED "paused" … … 504 504 tr_tordbg( tor, "Saving .resume file for \"%s\"", tr_torrentName( tor ) ); 505 505 506 tr_bencInitDict( &top, 32 ); /* arbitrary "big enough" number */ 507 tr_bencDictAddInt( &top, KEY_ACTIVITY_DATE, 508 tor->activityDate ); 509 tr_bencDictAddInt( &top, KEY_ADDED_DATE, 510 tor->addedDate ); 511 tr_bencDictAddInt( &top, KEY_CORRUPT, 512 tor->corruptPrev + tor->corruptCur ); 513 tr_bencDictAddInt( &top, KEY_DONE_DATE, 514 tor->doneDate ); 515 tr_bencDictAddStr( &top, KEY_DOWNLOAD_DIR, 516 tor->downloadDir ); 517 tr_bencDictAddInt( &top, KEY_DOWNLOADED, 518 tor->downloadedPrev + tor->downloadedCur ); 519 tr_bencDictAddInt( &top, KEY_UPLOADED, 520 tor->uploadedPrev + tor->uploadedCur ); 521 tr_bencDictAddInt( &top, KEY_MAX_PEERS, 522 tor->maxConnectedPeers ); 523 tr_bencDictAddInt( &top, KEY_BANDWIDTH_PRIORITY, 524 tr_torrentGetPriority( tor ) ); 506 tr_bencInitDict( &top, 33 ); /* arbitrary "big enough" number */ 507 tr_bencDictAddInt( &top, KEY_ACTIVITY_DATE, tor->activityDate ); 508 tr_bencDictAddInt( &top, KEY_ADDED_DATE, tor->addedDate ); 509 tr_bencDictAddInt( &top, KEY_CORRUPT, tor->corruptPrev + tor->corruptCur ); 510 tr_bencDictAddInt( &top, KEY_DONE_DATE, tor->doneDate ); 511 tr_bencDictAddStr( &top, KEY_DOWNLOAD_DIR, tor->downloadDir ); 512 if( tor->incompleteDir != NULL ) 513 tr_bencDictAddStr( &top, KEY_INCOMPLETE_DIR, tor->incompleteDir ); 514 tr_bencDictAddInt( &top, KEY_DOWNLOADED, tor->downloadedPrev + tor->downloadedCur ); 515 tr_bencDictAddInt( &top, KEY_UPLOADED, tor->uploadedPrev + tor->uploadedCur ); 516 tr_bencDictAddInt( &top, KEY_MAX_PEERS, tor->maxConnectedPeers ); 517 tr_bencDictAddInt( &top, KEY_BANDWIDTH_PRIORITY, tr_torrentGetPriority( tor ) ); 525 518 tr_bencDictAddBool( &top, KEY_PAUSED, !tor->isRunning ); 526 519 savePeers( &top, tor ); … … 556 549 if( tr_bencLoadFile( &top, TR_FMT_BENC, filename ) ) 557 550 { 558 tr_tordbg( tor, "Couldn't read \"%s\"; trying old format.", 559 filename ); 560 fieldsLoaded = tr_fastResumeLoad( tor, fieldsToLoad ); 561 562 if( ( fieldsLoaded != 0 ) && ( fieldsToLoad == ~(uint64_t)0 ) ) 563 { 564 tr_torrentSaveResume( tor ); 565 tr_fastResumeRemove( tor ); 566 tr_tordbg( tor, "Migrated resume file to \"%s\"", filename ); 567 } 551 tr_tordbg( tor, "Couldn't read \"%s\"", filename ); 568 552 569 553 tr_free( filename ); … … 587 571 tor->downloadDir = tr_strdup( str ); 588 572 fieldsLoaded |= TR_FR_DOWNLOAD_DIR; 573 } 574 575 if( ( fieldsToLoad & ( TR_FR_PROGRESS | TR_FR_INCOMPLETE_DIR ) ) 576 && ( tr_bencDictFindStr( &top, KEY_INCOMPLETE_DIR, &str ) ) 577 && ( str && *str ) ) 578 { 579 tr_free( tor->incompleteDir ); 580 tor->incompleteDir = tr_strdup( str ); 581 fieldsLoaded |= TR_FR_INCOMPLETE_DIR; 589 582 } 590 583 … … 748 741 { 749 742 char * filename = getResumeFilename( tor ); 750 751 743 unlink( filename ); 752 tr_fastResumeRemove( tor );753 744 tr_free( filename ); 754 745 } -
trunk/libtransmission/resume.h
r8254 r9328 31 31 TR_FR_RUN = ( 1 << 9 ), 32 32 TR_FR_DOWNLOAD_DIR = ( 1 << 10 ), 33 TR_FR_MAX_PEERS = ( 1 << 11 ), 34 TR_FR_ADDED_DATE = ( 1 << 12 ), 35 TR_FR_DONE_DATE = ( 1 << 13 ), 36 TR_FR_ACTIVITY_DATE = ( 1 << 14 ), 37 TR_FR_RATIOLIMIT = ( 1 << 15 ) 33 TR_FR_INCOMPLETE_DIR = ( 1 << 11 ), 34 TR_FR_MAX_PEERS = ( 1 << 12 ), 35 TR_FR_ADDED_DATE = ( 1 << 13 ), 36 TR_FR_DONE_DATE = ( 1 << 14 ), 37 TR_FR_ACTIVITY_DATE = ( 1 << 15 ), 38 TR_FR_RATIOLIMIT = ( 1 << 16 ) 38 39 }; 39 40 -
trunk/libtransmission/session.c
r9189 r9328 348 348 349 349 void 350 tr_sessionGetDefaultSettings( tr_benc * d ) 351 { 350 tr_sessionGetDefaultSettings( const char * configDir, tr_benc * d ) 351 { 352 char * incompleteDir = tr_buildPath( configDir, "Incomplete", NULL ); 353 352 354 assert( tr_bencIsDict( d ) ); 353 355 … … 359 361 tr_bencDictAddBool( d, TR_PREFS_KEY_DSPEED_ENABLED, FALSE ); 360 362 tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION, TR_DEFAULT_ENCRYPTION ); 363 tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR, incompleteDir ); 364 tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, FALSE ); 361 365 tr_bencDictAddBool( d, TR_PREFS_KEY_LAZY_BITFIELD, TRUE ); 362 366 tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL, TR_MSG_INF ); … … 402 406 tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4, TR_DEFAULT_BIND_ADDRESS_IPV4 ); 403 407 tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6, TR_DEFAULT_BIND_ADDRESS_IPV6 ); 408 409 tr_free( incompleteDir ); 404 410 } 405 411 … … 416 422 tr_bencDictAddBool( d, TR_PREFS_KEY_DSPEED_ENABLED, tr_sessionIsSpeedLimited( s, TR_DOWN ) ); 417 423 tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION, s->encryptionMode ); 424 tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR, tr_sessionGetIncompleteDir( s ) ); 425 tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, tr_sessionGetIncompleteDirEnabled( s ) ); 418 426 tr_bencDictAddBool( d, TR_PREFS_KEY_LAZY_BITFIELD, s->useLazyBitfield ); 419 427 tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL, tr_getMessageLevel( ) ); … … 474 482 * preserve those and use the session defaults to fill in any missing gaps. */ 475 483 tr_bencInitDict( &sessionDefaults, 0 ); 476 tr_sessionGetDefaultSettings( &sessionDefaults );484 tr_sessionGetDefaultSettings( configDir, &sessionDefaults ); 477 485 tr_bencMergeDicts( &sessionDefaults, d ); 478 486 tmp = *d; *d = sessionDefaults; sessionDefaults = tmp; … … 635 643 636 644 tr_bencInitDict( &settings, 0 ); 637 tr_sessionGetDefaultSettings( &settings );645 tr_sessionGetDefaultSettings( data->configDir, &settings ); 638 646 tr_bencMergeDicts( &settings, clientSettings ); 639 647 … … 684 692 assert( found ); 685 693 session->downloadDir = tr_strdup( str ); 694 695 found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_INCOMPLETE_DIR, &str ); 696 assert( found ); 697 tr_sessionSetIncompleteDir( session, str ); 698 699 found = tr_bencDictFindBool( &settings, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, &boolVal ); 700 assert( found ); 701 tr_sessionSetIncompleteDirEnabled( session, boolVal ); 686 702 687 703 found = tr_bencDictFindBool( &settings, TR_PREFS_KEY_PROXY_ENABLED, &boolVal ); … … 909 925 910 926 return session->downloadDir; 927 } 928 929 /*** 930 **** 931 ***/ 932 933 void 934 tr_sessionSetIncompleteDir( tr_session * session, const char * dir ) 935 { 936 assert( tr_isSession( session ) ); 937 938 if( session->incompleteDir != dir ) 939 { 940 tr_free( session->incompleteDir ); 941 942 session->incompleteDir = tr_strdup( dir ); 943 944 tr_mkdirp( session->incompleteDir, 0777 ); 945 } 946 } 947 948 const char* 949 tr_sessionGetIncompleteDir( const tr_session * session ) 950 { 951 assert( tr_isSession( session ) ); 952 953 return session->incompleteDir; 954 } 955 956 void 957 tr_sessionSetIncompleteDirEnabled( tr_session * session, tr_bool b ) 958 { 959 assert( tr_isSession( session ) ); 960 assert( tr_isBool( b ) ); 961 962 session->isIncompleteDirEnabled = b; 963 } 964 965 tr_bool 966 tr_sessionGetIncompleteDirEnabled( const tr_session * session ) 967 { 968 assert( tr_isSession( session ) ); 969 970 return session->isIncompleteDirEnabled; 911 971 } 912 972 -
trunk/libtransmission/session.h
r9170 r9328 53 53 tr_bool useLazyBitfield; 54 54 tr_bool isRatioLimited; 55 tr_bool isIncompleteDirEnabled; 55 56 56 57 tr_benc removedTorrents; … … 102 103 char * resumeDir; 103 104 char * torrentDir; 105 char * incompleteDir; 104 106 105 107 tr_proxy_type proxyType; -
trunk/libtransmission/torrent.c
r9276 r9328 551 551 } 552 552 553 static void refreshCurrentDir( tr_torrent * tor );; 554 553 555 static void 554 556 torrentRealInit( tr_torrent * tor, const tr_ctor * ctor ) … … 579 581 !tr_ctorGetDownloadDir( ctor, TR_FALLBACK, &dir ) ) 580 582 tor->downloadDir = tr_strdup( dir ); 583 584 if( tr_sessionGetIncompleteDirEnabled( session ) ) 585 tor->incompleteDir = tr_strdup( tr_sessionGetIncompleteDir( session ) ); 581 586 582 587 tor->lastPieceSize = info->totalSize % info->pieceSize; … … 643 648 loaded = tr_torrentLoadResume( tor, ~0, ctor ); 644 649 650 refreshCurrentDir( tor ); 651 645 652 doStart = tor->isRunning; 646 653 tor->isRunning = 0; … … 775 782 tr_torrentSetDirty( tor ); 776 783 } 784 785 refreshCurrentDir( tor ); 777 786 } 778 787 … … 1242 1251 1243 1252 tr_free( tor->downloadDir ); 1253 tr_free( tor->incompleteDir ); 1244 1254 tr_free( tor->peer_id ); 1245 1255 … … 1597 1607 tor->needsSeedRatioCheck = TRUE; 1598 1608 tr_fdTorrentClose( tor->uniqueId ); 1609 1610 /* if the torrent is a seed now, 1611 * and the files used to be in the incompleteDir, 1612 * then move them to the destination directory */ 1613 if( tr_torrentIsSeed( tor ) && ( tor->currentDir == tor->incompleteDir ) ) 1614 tr_torrentSetLocation( tor, tor->downloadDir, TRUE, NULL, NULL ); 1615 1599 1616 fireCompletenessChange( tor, completeness ); 1600 1617 … … 1980 1997 1981 1998 time_t* 1982 tr_torrentGetMTimes( const tr_torrent * tor, 1983 size_t * setme_n ) 1999 tr_torrentGetMTimes( const tr_torrent * tor, size_t * setme_n ) 1984 2000 { 1985 2001 size_t i; … … 1992 2008 { 1993 2009 struct stat sb; 1994 char * path = tr_ buildPath( tor->downloadDir, tor->info.files[i].name, NULL);1995 if( !stat( path, &sb) )2010 char * path = tr_torrentFindFile( tor, i ); 2011 if( ( path != NULL ) && !stat( path, &sb ) && S_ISREG( sb.st_mode ) ) 1996 2012 { 1997 2013 #ifdef SYS_DARWIN … … 2125 2141 tr_torrentGetBytesLeftToAllocate( const tr_torrent * tor ) 2126 2142 { 2127 const tr_file * it; 2128 const tr_file * end; 2129 struct stat sb; 2143 tr_file_index_t i; 2130 2144 uint64_t bytesLeft = 0; 2131 2145 2132 2146 assert( tr_isTorrent( tor ) ); 2133 2147 2134 for( i t=tor->info.files, end=it+tor->info.fileCount; it!=end; ++it)2135 { 2136 if( ! it->dnd )2148 for( i=0; i<tor->info.fileCount; ++i ) 2149 { 2150 if( !tor->info.files[i].dnd ) 2137 2151 { 2138 char * path = tr_buildPath( tor->downloadDir, it->name, NULL ); 2139 2140 bytesLeft += it->length; 2141 2142 if( !stat( path, &sb ) 2143 && S_ISREG( sb.st_mode ) 2144 && ( (uint64_t)sb.st_size <= it->length ) ) 2152 struct stat sb; 2153 const uint64_t length = tor->info.files[i].length; 2154 char * path = tr_torrentFindFile( tor, i ); 2155 2156 bytesLeft += length; 2157 2158 if( ( path != NULL ) && !stat( path, &sb ) 2159 && S_ISREG( sb.st_mode ) 2160 && ( (uint64_t)sb.st_size <= length ) ) 2145 2161 bytesLeft -= sb.st_size; 2146 2162 … … 2229 2245 else if( S_ISREG( sb.st_mode ) && ( sb.st_size > 0 ) ) 2230 2246 { 2231 const char * sub = buf + strlen( tor-> downloadDir ) + strlen( TR_PATH_DELIMITER_STR );2247 const char * sub = buf + strlen( tor->currentDir ) + strlen( TR_PATH_DELIMITER_STR ); 2232 2248 const tr_bool isTorrentFile = tr_ptrArrayFindSorted( torrentFiles, sub, vstrcmp ) != NULL; 2233 2249 if( !isTorrentFile ) … … 2252 2268 const char * cpch = strchr( firstFile, TR_PATH_DELIMITER ); 2253 2269 char * tmp = cpch ? tr_strndup( firstFile, cpch - firstFile ) : NULL; 2254 char * root = tr_buildPath( tor->downloadDir, tmp, NULL ); 2255 2256 assert( tr_isTorrent( tor ) ); 2257 2258 for( f=0; f<tor->info.fileCount; ++f ) 2259 tr_ptrArrayInsertSorted( &torrentFiles, tor->info.files[f].name, vstrcmp ); 2270 char * root = tr_buildPath( tor->currentDir, tmp, NULL ); 2271 2272 assert( tr_isTorrent( tor ) ); 2273 2274 for( f=0; f<tor->info.fileCount; ++f ) { 2275 tr_ptrArrayInsertSorted( &torrentFiles, tr_strdup( tor->info.files[f].name ), vstrcmp ); 2276 tr_ptrArrayInsertSorted( &torrentFiles, tr_strdup_printf( "%s.part", tor->info.files[f].name ), vstrcmp ); 2277 } 2260 2278 2261 2279 /* build the set of folders and dirtyFolders */ … … 2270 2288 /* now blow away any remaining torrent files, such as torrent files in dirty folders */ 2271 2289 for( f=0; f<tor->info.fileCount; ++f ) { 2272 char * path = tr_buildPath( tor-> downloadDir, tor->info.files[f].name, NULL );2290 char * path = tr_buildPath( tor->currentDir, tor->info.files[f].name, NULL ); 2273 2291 fileFunc( path ); 2274 2292 tr_free( path ); … … 2293 2311 tr_ptrArrayDestruct( &dirtyFolders, tr_free ); 2294 2312 tr_ptrArrayDestruct( &folders, tr_free ); 2295 tr_ptrArrayDestruct( &torrentFiles, NULL);2313 tr_ptrArrayDestruct( &torrentFiles, tr_free ); 2296 2314 tr_free( root ); 2297 2315 tr_free( tmp ); … … 2313 2331 else { 2314 2332 /* torrent only has one file */ 2315 char * path = tr_ buildPath( tor->downloadDir, tor->info.files[0].name, NULL);2333 char * path = tr_torrentFindFile( tor, 0 ); 2316 2334 fileFunc( path ); 2317 2335 tr_free( path ); … … 2322 2340 **** 2323 2341 ***/ 2342 2343 static char* 2344 rebaseFile( const tr_torrent * tor, tr_file_index_t fileNo, 2345 const char * existingFile, const char * newRoot ) 2346 { 2347 const char * base = strstr( existingFile, tor->info.files[fileNo].name ); 2348 assert( base != NULL ); 2349 return tr_buildPath( newRoot, base, NULL ); 2350 } 2324 2351 2325 2352 struct LocationData … … 2345 2372 assert( tr_isTorrent( tor ) ); 2346 2373 2347 if( strcmp( location, tor-> downloadDir ) )2374 if( strcmp( location, tor->currentDir ) ) 2348 2375 { 2349 2376 tr_file_index_t i; … … 2367 2394 struct stat sb; 2368 2395 const tr_file * f = &tor->info.files[i]; 2369 char * oldpath = tr_ buildPath( tor->downloadDir, f->name, NULL);2370 char * newpath = tr_buildPath( location, f->name, NULL );2371 2372 if( do_move )2396 char * oldpath = tr_torrentFindFile( tor, i ); 2397 char * newpath = oldpath ? rebaseFile( tor, i, oldpath, location ) : NULL; 2398 2399 if( do_move && ( oldpath != NULL ) ) 2373 2400 { 2374 2401 errno = 0; … … 2484 2511 } 2485 2512 } 2513 2514 /*** 2515 **** 2516 ***/ 2517 2518 void 2519 tr_torrentFileCompleted( tr_torrent * tor, tr_file_index_t fileNum ) 2520 { 2521 char * oldpath = tr_torrentFindFile( tor, fileNum ); 2522 char * newpath = tr_strdup( oldpath ); 2523 char * pch = strrchr( newpath, '.' ); 2524 assert( !strcmp( pch, ".part" ) ); 2525 *pch = '\0'; 2526 2527 /* close the file so that we can reopen in read-only mode as needed */ 2528 tr_fdFileClose( tor, fileNum ); 2529 2530 /* strip the trailing ".part" from the filename */ 2531 if( rename( oldpath, newpath ) ) 2532 tr_torerr( tor, "Error moving \"%s\" to \"%s\": %s", oldpath, newpath, tr_strerror( errno ) ); 2533 2534 tr_free( newpath ); 2535 tr_free( oldpath ); 2536 } 2537 2538 /*** 2539 **** 2540 ***/ 2541 2542 enum 2543 { 2544 TR_FILE_PARTIAL = (1<<0), 2545 TR_FILE_INCOMPLETE_DIR = (1<<1) 2546 }; 2547 2548 static char* 2549 tr_torrentBuildFilename( const tr_torrent * tor, tr_file_index_t fileNo, int flags ) 2550 { 2551 const char * root; 2552 char * base; 2553 char * path; 2554 const tr_bool partial = ( flags & TR_FILE_PARTIAL ) != 0; 2555 const tr_bool incomplete = ( flags & TR_FILE_INCOMPLETE_DIR ) != 0; 2556 2557 assert( tr_isTorrent( tor ) ); 2558 assert( fileNo < tor->info.fileCount ); 2559 2560 if( incomplete && ( tor->incompleteDir != NULL ) ) 2561 root = tor->incompleteDir; 2562 else 2563 root = tor->downloadDir; 2564 2565 if( partial ) 2566 base = tr_strdup_printf( "%s.part", tor->info.files[fileNo].name ); 2567 else 2568 base = tr_strdup( tor->info.files[fileNo].name ); 2569 2570 path = tr_buildPath( root, base, NULL ); 2571 2572 /* cleanup */ 2573 tr_free( base ); 2574 return path; 2575 } 2576 2577 static tr_bool 2578 fileExists( const char * filename ) 2579 { 2580 struct stat sb; 2581 const tr_bool ok = !stat( filename, &sb ); 2582 return ok; 2583 } 2584 2585 char* 2586 tr_torrentFindFile( const tr_torrent * tor, tr_file_index_t fileNo ) 2587 { 2588 int i; 2589 char * filename; 2590 int flags[4]; 2591 int n = 0; 2592 2593 assert( tr_isTorrent( tor ) ); 2594 assert( fileNo < tor->info.fileCount ); 2595 2596 /* based on what we know about the torrent, 2597 * put the most likely hits first... */ 2598 if( tr_cpFileIsComplete( &tor->completion, fileNo ) ) { 2599 flags[n++] = 0; 2600 flags[n++] = TR_FILE_INCOMPLETE_DIR; 2601 flags[n++] = TR_FILE_PARTIAL; 2602 flags[n++] = TR_FILE_INCOMPLETE_DIR|TR_FILE_PARTIAL; 2603 } else { 2604 flags[n++] = TR_FILE_INCOMPLETE_DIR|TR_FILE_PARTIAL; 2605 flags[n++] = TR_FILE_PARTIAL; 2606 flags[n++] = TR_FILE_INCOMPLETE_DIR; 2607 flags[n++] = 0; 2608 } 2609 2610 for( i=0; i<n; ++i ) { 2611 filename = tr_torrentBuildFilename( tor, fileNo, flags[i] ); 2612 if( fileExists( filename )) 2613 break; 2614 tr_free( filename ); 2615 filename = NULL; 2616 } 2617 2618 return filename; 2619 } 2620 2621 /* Decide whether we should be looking for files in downloadDir or incompleteDir. */ 2622 static void 2623 refreshCurrentDir( tr_torrent * tor ) 2624 { 2625 const char * dir = tor->downloadDir; 2626 2627 if( tor->incompleteDir != NULL ) 2628 { 2629 char * tmp1 = tr_torrentBuildFilename( tor, 0, 0 ); 2630 char * tmp2 = tr_torrentBuildFilename( tor, 0, TR_FILE_PARTIAL ); 2631 2632 if( !fileExists( tmp1 ) && !fileExists( tmp2 ) ) 2633 dir = tor->incompleteDir; 2634 2635 tr_free( tmp2 ); 2636 tr_free( tmp1 ); 2637 } 2638 2639 assert( dir != NULL ); 2640 assert( ( dir == tor->downloadDir ) || ( dir == tor->incompleteDir ) ); 2641 tor->currentDir = dir; 2642 } -
trunk/libtransmission/torrent.h
r9170 r9328 158 158 uint8_t * peer_id; 159 159 160 /* Where t o download*/160 /* Where the files will be when it's complete */ 161 161 char * downloadDir; 162 163 /* Where the files are when the torrent is incomplete */ 164 char * incompleteDir; 165 166 /* Where the files are now. 167 * This pointer will be equal to downloadDir or incompleteDir */ 168 const char * currentDir; 162 169 163 170 /* How many bytes we ask for per request */ … … 348 355 } 349 356 357 /** 358 * Get the file that exists on the disk, or NULL if no file exists yet. 359 * @return the file that exists on the disk, or NULL if no file exists yet. 360 * @param tor the torrent whose file we're using 361 * @param fileNum the fileIndex, in [0..tor->info.fileCount) 362 */ 363 char* tr_torrentFindFile( const tr_torrent * tor, tr_file_index_t fileNo ); 364 365 /** 366 * Tell the tr_torrent that one of its files has become complete 367 */ 368 void tr_torrentFileCompleted( tr_torrent * tor, tr_file_index_t fileNo ); 369 370 350 371 #endif -
trunk/libtransmission/transmission.h
r9292 r9328 169 169 #define TR_PREFS_KEY_DOWNLOAD_DIR "download-dir" 170 170 #define TR_PREFS_KEY_ENCRYPTION "encryption" 171 #define TR_PREFS_KEY_INCOMPLETE_DIR "incomplete-dir" 172 #define TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED "incomplete-dir-enabled" 171 173 #define TR_PREFS_KEY_LAZY_BITFIELD "lazy-bitfield-enabled" 172 174 #define TR_PREFS_KEY_MSGLEVEL "message-level" … … 227 229 * @see tr_getDefaultConfigDir() 228 230 */ 229 void tr_sessionGetDefaultSettings( struct tr_benc * dictionary );231 void tr_sessionGetDefaultSettings( const char * configDir, struct tr_benc * dictionary ); 230 232 231 233 /** … … 329 331 */ 330 332 const char * tr_sessionGetDownloadDir( const tr_session * session ); 333 334 /** 335 * @brief Set the per-session incomplete download folder 336 * @see tr_sessionInit() 337 * @see tr_sessionGetIncompleteDir() 338 * @see tr_sessionSetIncompleteDirEnabled() 339 * @see tr_sessionGetIncompleteDirEnabled() 340 */ 341 void tr_sessionSetIncompleteDir( tr_session * session, const char * dir ); 342 343 const char* tr_sessionGetIncompleteDir( const tr_session * session ); 344 345 void tr_sessionSetIncompleteDirEnabled( tr_session * session, tr_bool ); 346 347 tr_bool tr_sessionGetIncompleteDirEnabled( const tr_session * session ); 331 348 332 349 /** -
trunk/libtransmission/verify.c
r9287 r9328 80 80 if( !filePos && (fd<0) ) 81 81 { 82 char * filename = tr_ buildPath( tor->downloadDir, file->name, NULL);83 fd = tr_open_file_for_scanning( filename );82 char * filename = tr_torrentFindFile( tor, fileIndex ); 83 fd = filename == NULL ? -1 : tr_open_file_for_scanning( filename ); 84 84 /* fprintf( stderr, "opening file #%d (%s) -- %d\n", fileIndex, filename, fd ); */ 85 85 tr_free( filename ); … … 255 255 { 256 256 struct stat sb; 257 char * path = tr_ buildPath( tor->downloadDir, tor->info.files[i].name, NULL);258 if( !stat( path, &sb ) && ( sb.st_size > 0 ) )257 char * path = tr_torrentFindFile( tor, i ); 258 if( ( path != NULL ) && !stat( path, &sb ) && ( sb.st_size > 0 ) ) 259 259 hasAny = TRUE; 260 260 tr_free( path ); -
trunk/macosx/Controller.m
r9316 r9328 265 265 tr_benc settings; 266 266 tr_bencInitDict(&settings, 34); 267 tr_sessionGetDefaultSettings(&settings); 267 const char * configDir = tr_getDefaultConfigDir("Transmission"); 268 tr_sessionGetDefaultSettings(configDir, &settings); 268 269 269 270 const BOOL usesSpeedLimitSched = [fDefaults boolForKey: @"SpeedLimitAuto"]; … … 319 320 tr_bencDictAddBool(&settings, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, [fDefaults boolForKey: @"RPCUseWhitelist"]); 320 321 321 fLib = tr_sessionInit("macosx", tr_getDefaultConfigDir("Transmission"), YES, &settings);322 fLib = tr_sessionInit("macosx", configDir, YES, &settings); 322 323 tr_bencFree(&settings); 323 324 -
trunk/qt/session.cc
r9244 r9328 263 263 tr_benc settings; 264 264 tr_bencInitDict( &settings, 0 ); 265 tr_sessionGetDefaultSettings( &settings );266 265 tr_sessionLoadSettings( &settings, myConfigDir.toUtf8().constData(), "qt" ); 267 266 mySession = tr_sessionInit( "qt", myConfigDir.toUtf8().constData(), true, &settings );
Note: See TracChangeset
for help on using the changeset viewer.