}
void
-tr_metainfoMigrate( const tr_handle * handle,
- const tr_info * inf )
+tr_metainfoMigrate( tr_handle * handle,
+ tr_info * inf )
{
struct stat new_sb;
char new_name[MAX_PATH_LENGTH];
{
FILE * out = fopen( new_name, "wb+" );
if( fwrite( content, sizeof( uint8_t ), contentLen, out ) == contentLen )
+ {
+ tr_free( inf->torrent );
+ inf->torrent = tr_strdup( new_name );
+ tr_sessionSetTorrentFile( handle, inf->hashString, new_name );
unlink( old_name );
+ }
fclose( out );
}
getTorrentFilename( handle, inf, buf, sizeof( buf ) );
tr_free( inf->torrent );
inf->torrent = tr_strdup( buf );
-fprintf( stderr, "inf->torrent is [%s]\n", inf->torrent );
return TR_OK;
void tr_metainfoRemoveSaved( const tr_handle * handle,
const tr_info * info );
-void tr_metainfoMigrate( const tr_handle * handle,
- const tr_info * inf );
+void tr_metainfoMigrate( tr_handle * handle,
+ tr_info * inf );
#endif
#define KEY_SPEEDLIMIT_UP_SPEED "up-speed"
#define KEY_SPEEDLIMIT_UP_MODE "up-mode"
-#define KEY_PROGRESS_MTIMES "mtimes"
+#define KEY_PROGRESS_MTIMES "mtimes"
#define KEY_PROGRESS_BITFIELD "bitfield"
static void
static void
savePeers( tr_benc * dict, const tr_torrent * tor )
{
- tr_pex * pex;
+ tr_pex * pex = NULL;
const int count = tr_peerMgrGetPeers( tor->handle->peerMgr,
tor->info.hash, &pex );
- if( count > 0 ) {
- tr_benc * child = tr_bencDictAdd( dict, KEY_PEERS );
- tr_bencInitStrDupLen( child, (const char*)pex, sizeof(tr_pex)*count );
- tr_free( pex );
- }
+ if( count > 0 )
+ tr_bencInitStrDupLen( tr_bencDictAdd( dict, KEY_PEERS ),
+ (const char*)pex, sizeof(tr_pex)*count );
+ tr_free( pex );
}
static uint64_t
****
***/
+static const time_t verifyNeeded = ~(time_t)0;
+
static void
saveProgress( tr_benc * dict, const tr_torrent * tor )
{
/* add the mtimes */
mtimes = tr_torrentGetMTimes( tor, &n );
m = tr_bencDictAddList( p, KEY_PROGRESS_MTIMES, n );
- for( i=0; i<n; ++i ) {
- if( !tr_torrentIsFileChecked( tor, i ) )
- mtimes[i] = ~(time_t)0; /* force a recheck next time */
- tr_bencListAddInt( m, mtimes[i] );
- }
+ for( i=0; i<n; ++i )
+ tr_bencListAddInt( m, tr_torrentIsFileChecked( tor, i )
+ ? mtimes[i] : verifyNeeded );
/* add the bitfield */
bitfield = tr_cpBlockBitfield( tor->completion );
&& ( m->val.l.count == n ) )
{
int i;
- const time_t recheck = ~(time_t)0;
for( i=0; i<m->val.l.count; ++i )
{
int64_t x;
- time_t t = tr_bencGetInt( &m->val.l.vals[i], &x ) ? x : recheck;
- if( ( t != recheck ) && ( curMTimes[i] == t ) )
+ const time_t t = tr_bencGetInt( &m->val.l.vals[i], &x )
+ ? x : verifyNeeded;
+ if( ( t != verifyNeeded ) && ( t == curMTimes[i] ) )
tr_torrentSetFileChecked( tor, i, TRUE );
else {
tr_torrentSetFileChecked( tor, i, FALSE );
tr_benc top;
char filename[MAX_PATH_LENGTH];
- /* populate the bencoded data */
tr_bencInitDict( &top, 10 );
- tr_bencDictAddInt( &top, KEY_CORRUPT, tor->corruptPrev + tor->corruptCur );
- tr_bencDictAddStr( &top, KEY_DESTINATION, tor->destination );
+ tr_bencDictAddInt( &top, KEY_CORRUPT,
+ tor->corruptPrev + tor->corruptCur );
+ tr_bencDictAddStr( &top, KEY_DESTINATION,
+ tor->destination );
tr_bencDictAddInt( &top, KEY_DOWNLOADED,
- tor->downloadedPrev + tor->downloadedCur );
+ tor->downloadedPrev + tor->downloadedCur );
tr_bencDictAddInt( &top, KEY_UPLOADED,
tor->uploadedPrev + tor->uploadedCur );
- tr_bencDictAddInt( &top, KEY_MAX_PEERS, tor->maxConnectedPeers );
- tr_bencDictAddInt( &top, KEY_PAUSED, tor->isRunning?0:1 );
+ tr_bencDictAddInt( &top, KEY_MAX_PEERS,
+ tor->maxConnectedPeers );
+ tr_bencDictAddInt( &top, KEY_PAUSED,
+ tor->isRunning ? 0 : 1 );
savePeers( &top, tor );
savePriorities( &top, tor );
saveProgress( &top, tor );
#include "blocklist.h"
#include "fdlimit.h"
#include "list.h"
+#include "metainfo.h" /* tr_metainfoFree */
#include "net.h"
#include "peer-mgr.h"
#include "platform.h" /* tr_lock */
****
***/
+static void metainfoLookupRescan( tr_handle * h );
+
tr_handle *
tr_initFull( const char * configDir,
const char * tag,
tr_statsInit( h );
+ metainfoLookupRescan( h );
+
return h;
}
tr_buildPath( filename, sizeof(filename), dirname, d->d_name, NULL );
tr_ctorSetMetainfoFromFile( ctor, filename );
tor = tr_torrentNew( h, ctor, NULL );
- if( tor != NULL ) {
+ if( tor ) {
tr_list_append( &list, tor );
n++;
}
{
return _tr_blocklistHasAddress( handle->blocklist, addr );
}
+
+/***
+****
+***/
+
+static int
+compareLookupEntries( const void * va, const void * vb )
+{
+ const struct tr_metainfo_lookup * a = va;
+ const struct tr_metainfo_lookup * b = vb;
+ return strcmp( a->hashString, b->hashString );
+}
+
+static void
+metainfoLookupResort( tr_handle * h )
+{
+ qsort( h->metainfoLookup,
+ h->metainfoLookupCount,
+ sizeof( struct tr_metainfo_lookup ),
+ compareLookupEntries );
+}
+
+static int
+compareHashStringToLookupEntry( const void * va, const void * vb )
+{
+ const char * a = va;
+ const struct tr_metainfo_lookup * b = vb;
+ return strcmp( a, b->hashString );
+}
+
+const char*
+tr_sessionFindTorrentFile( const tr_handle * h,
+ const char * hashStr )
+{
+ struct tr_metainfo_lookup * l = bsearch( hashStr,
+ h->metainfoLookup,
+ h->metainfoLookupCount,
+ sizeof( struct tr_metainfo_lookup ),
+ compareHashStringToLookupEntry );
+ return l ? l->filename : NULL;
+}
+
+static void
+metainfoLookupRescan( tr_handle * h )
+{
+ int i;
+ int n;
+ struct stat sb;
+ const char * dirname = tr_getTorrentDir( h );
+ DIR * odir = NULL;
+ tr_ctor * ctor = NULL;
+ tr_list * list = NULL;
+
+ /* walk through the directory and find the mappings */
+ ctor = tr_ctorNew( h );
+ tr_ctorSetSave( ctor, FALSE ); /* since we already have them */
+ if( !stat( dirname, &sb ) && S_ISDIR( sb.st_mode ) && (( odir = opendir( dirname ))))
+ {
+ struct dirent *d;
+ for (d = readdir( odir ); d!=NULL; d=readdir( odir ) )
+ {
+ if( d->d_name && d->d_name[0]!='.' ) /* skip dotfiles, ., and .. */
+ {
+ tr_info inf;
+ char filename[MAX_PATH_LENGTH];
+ tr_buildPath( filename, sizeof(filename), dirname, d->d_name, NULL );
+ tr_ctorSetMetainfoFromFile( ctor, filename );
+ if( !tr_torrentParse( h, ctor, &inf ) )
+ {
+ tr_list_append( &list, tr_strdup( inf.hashString ) );
+ tr_list_append( &list, tr_strdup( filename ) );
+ tr_metainfoFree( &inf );
+ }
+ }
+ }
+ closedir( odir );
+ }
+ tr_ctorFree( ctor );
+
+ n = tr_list_size( list ) / 2;
+ h->metainfoLookup = tr_new0( struct tr_metainfo_lookup, n );
+ h->metainfoLookupCount = n;
+ for( i=0; i<n; ++i )
+ {
+ char * hashString = tr_list_pop_front( &list );
+ char * filename = tr_list_pop_front( &list );
+
+ memcpy( h->metainfoLookup[i].hashString, hashString, 2*SHA_DIGEST_LENGTH+1 );
+ tr_free( hashString );
+ h->metainfoLookup[i].filename = filename;
+ }
+
+ metainfoLookupResort( h );
+ tr_dbg( "Found %d torrents in \"%s\"", n, dirname );
+}
+
+void
+tr_sessionSetTorrentFile( tr_handle * h,
+ const char * hashString,
+ const char * filename )
+{
+ struct tr_metainfo_lookup * l = bsearch( hashString,
+ h->metainfoLookup,
+ h->metainfoLookupCount,
+ sizeof( struct tr_metainfo_lookup ),
+ compareHashStringToLookupEntry );
+ if( l != NULL )
+ {
+ if( l->filename != filename )
+ {
+ tr_free( l->filename );
+ l->filename = tr_strdup( filename );
+ }
+ }
+ else
+ {
+ const int n = h->metainfoLookupCount++;
+ struct tr_metainfo_lookup * node;
+ h->metainfoLookup = tr_renew( struct tr_metainfo_lookup,
+ h->metainfoLookup,
+ h->metainfoLookupCount );
+ node = h->metainfoLookup + n;
+ memcpy( node->hashString, hashString, 2*SHA_DIGEST_LENGTH+1 );
+ node->filename = tr_strdup( filename );
+ metainfoLookupResort( h );
+ }
+}
const uint8_t* tr_getPeerId( void );
+struct tr_metainfo_lookup
+{
+ char hashString[2*SHA_DIGEST_LENGTH+1];
+ char * filename;
+};
+
+const char * tr_sessionFindTorrentFile( const tr_handle * h,
+ const char * hashString );
+
+void tr_sessionSetTorrentFile( tr_handle * h,
+ const char * hashString,
+ const char * filename );
+
struct tr_handle
{
- unsigned int isPortSet : 1;
- unsigned int isPexEnabled : 1;
- unsigned int isClosed : 1;
- unsigned int useUploadLimit : 1;
- unsigned int useDownloadLimit : 1;
+ unsigned int isPortSet : 1;
+ unsigned int isPexEnabled : 1;
+ unsigned int isClosed : 1;
+ unsigned int useUploadLimit : 1;
+ unsigned int useDownloadLimit : 1;
+
+ tr_encryption_mode encryptionMode;
- tr_encryption_mode encryptionMode;
+ struct tr_event_handle * events;
- struct tr_event_handle * events;
+ int peerSocketTOS;
- int peerSocketTOS;
+ int torrentCount;
+ tr_torrent * torrentList;
- int torrentCount;
- tr_torrent * torrentList;
+ char * tag;
- char * tag;
+ char * configDir;
+ char * torrentDir;
+ char * resumeDir;
- char * configDir;
- char * torrentDir;
- char * resumeDir;
+ struct tr_ratecontrol * upload;
+ struct tr_ratecontrol * download;
- struct tr_ratecontrol * upload;
- struct tr_ratecontrol * download;
+ struct tr_blocklist * blocklist;
+ struct tr_peerMgr * peerMgr;
+ struct tr_shared * shared;
- struct tr_blocklist * blocklist;
- struct tr_peerMgr * peerMgr;
- struct tr_shared * shared;
+ struct tr_lock * lock;
- struct tr_lock * lock;
+ tr_handle_status stats[2];
+ int statCur;
- tr_handle_status stats[2];
- int statCur;
+ struct tr_stats_handle * sessionStats;
+ struct tr_tracker_handle * tracker;
- struct tr_stats_handle * sessionStats;
- struct tr_tracker_handle * tracker;
+ struct tr_metainfo_lookup * metainfoLookup;
+ int metainfoLookupCount;
};
void tr_globalLock ( struct tr_handle * );
#include "transmission.h"
#include "bencode.h"
#include "platform.h"
+#include "session.h" /* tr_sessionFindTorrentFile */
#include "trcompat.h" /* strlcpy */
#include "utils.h"
tr_ctorSetMetainfoFromHash( tr_ctor * ctor,
const char * hashString )
{
- int err = -1;
- char basename[2048];
- char filename[MAX_PATH_LENGTH];
-
- if( err && ( ctor->handle->tag != NULL ) ) {
- snprintf( basename, sizeof(basename), "%s-%s", hashString, ctor->handle->tag );
- tr_buildPath( filename, sizeof(filename), tr_getTorrentDir( ctor->handle ), basename, NULL );
- err = tr_ctorSetMetainfoFromFile( ctor, filename );
- }
+ int err;
+ const char * filename;
- if( err ) {
- tr_buildPath( filename, sizeof(filename), tr_getTorrentDir( ctor->handle ), hashString, NULL );
- err = tr_ctorSetMetainfoFromFile( ctor, filename );
- }
+ if(( filename = tr_sessionFindTorrentFile( ctor->handle, hashString )))
+ err = tr_ctorSetMetainfoFromFile( ctor, filename );
+ else
+ err = TR_ERROR;
return err;
}
if( !tr_ctorGetMetainfo( ctor, &val ) ) {
const char * filename = tor->info.torrent;
tr_bencSaveFile( filename, val );
+ tr_sessionSetTorrentFile( tor->handle, tor->info.hashString, filename );
}
}