mirror of
https://github.com/transmission/transmission
synced 2024-12-25 17:17:31 +00:00
'resume' cleanup
This commit is contained in:
parent
a08ef82039
commit
afde752dc0
8 changed files with 227 additions and 147 deletions
|
@ -313,7 +313,7 @@ tr_bencParse( const void * buf_in,
|
|||
int
|
||||
tr_bencLoad( const void * buf_in,
|
||||
int buflen,
|
||||
tr_benc * setme_benc,
|
||||
tr_benc * setme_benc,
|
||||
char ** setme_end )
|
||||
{
|
||||
const uint8_t * buf = buf_in;
|
||||
|
@ -570,6 +570,14 @@ tr_bencListAdd( tr_benc * list )
|
|||
return item;
|
||||
}
|
||||
|
||||
tr_benc *
|
||||
tr_bencListAddInt( tr_benc * list, int64_t i )
|
||||
{
|
||||
tr_benc * node = tr_bencListAdd( list );
|
||||
tr_bencInitInt( node, i );
|
||||
return node;
|
||||
}
|
||||
|
||||
tr_benc *
|
||||
tr_bencDictAdd( tr_benc * dict, const char * key )
|
||||
{
|
||||
|
@ -1051,3 +1059,48 @@ tr_bencSaveAsSerializedPHP( const tr_benc * top, int * len )
|
|||
evbuffer_free( data.out );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
int
|
||||
tr_bencSaveFile( const char * filename, const tr_benc * b )
|
||||
{
|
||||
int ret = TR_OK;
|
||||
int len;
|
||||
char * content = tr_bencSave( b, &len );
|
||||
FILE * out = NULL;
|
||||
|
||||
out = fopen( filename, "wb+" );
|
||||
if( !out )
|
||||
{
|
||||
tr_err( _( "Couldn't open \"%1$s\": %2$s" ),
|
||||
filename, tr_strerror( errno ) );
|
||||
ret = TR_EINVALID;
|
||||
}
|
||||
else if( fwrite( content, sizeof( char ), len, out ) != (size_t)len )
|
||||
{
|
||||
tr_err( _( "Couldn't save file \"%1$s\": %2$s" ),
|
||||
filename, tr_strerror( errno ) );
|
||||
ret = TR_EINVALID;
|
||||
}
|
||||
|
||||
tr_dbg( "tr_bencSaveFile returned %d when saving \"%s\"", ret, filename );
|
||||
tr_free( content );
|
||||
if( out )
|
||||
fclose( out );
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
tr_bencLoadFile( const char * filename, tr_benc * b )
|
||||
{
|
||||
int ret = TR_ERROR;
|
||||
size_t contentLen;
|
||||
uint8_t * content = tr_loadFile( filename, &contentLen );
|
||||
ret = content ? tr_bencLoad( content, contentLen, b, NULL )
|
||||
: TR_ERROR_IO_OTHER;
|
||||
tr_free( content );
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -99,6 +99,7 @@ int tr_bencListReserve( tr_benc * list, int count );
|
|||
/* note that for one key-value pair, count should be 1, not 2 */
|
||||
int tr_bencDictReserve( tr_benc * dict, int count );
|
||||
tr_benc * tr_bencListAdd( tr_benc * list );
|
||||
tr_benc * tr_bencListAddInt( tr_benc * list, int64_t val );
|
||||
/* note: key must not be freed or modified while val is in use */
|
||||
tr_benc * tr_bencDictAdd( tr_benc * dict, const char * key );
|
||||
tr_benc * tr_bencDictAddInt( tr_benc * dict, const char * key, int64_t val );
|
||||
|
@ -107,7 +108,9 @@ tr_benc * tr_bencDictAddList( tr_benc * dict, const char * key, int reserveCo
|
|||
tr_benc * tr_bencDictAddDict( tr_benc * dict, const char * key, int reserveCount );
|
||||
|
||||
char* tr_bencSave( const tr_benc * val, int * len );
|
||||
char* tr_bencSaveAsSerializedPHP( const tr_benc * top, int * len );
|
||||
char* tr_bencSaveAsSerializedPHP( const tr_benc * top, int * len );
|
||||
int tr_bencSaveFile( const char * filename, const tr_benc * );
|
||||
int tr_bencLoadFile( const char * filename, tr_benc * );
|
||||
|
||||
int tr_bencGetInt( const tr_benc * val, int64_t * setme );
|
||||
|
||||
|
|
|
@ -125,25 +125,64 @@ strlcat_utf8( void * dest, const void * src, size_t len, char skip )
|
|||
}
|
||||
|
||||
static void
|
||||
savedname( const tr_handle * handle,
|
||||
char * name,
|
||||
size_t len,
|
||||
const char * hash )
|
||||
getTorrentFilename( const tr_handle * handle,
|
||||
const tr_info * inf,
|
||||
char * buf,
|
||||
size_t buflen )
|
||||
{
|
||||
const char * dir = tr_getTorrentDir( handle );
|
||||
char base[MAX_PATH_LENGTH];
|
||||
snprintf( base, sizeof( base ), "%s.%16.16s.torrent", inf->name, inf->hashString );
|
||||
tr_buildPath( buf, buflen, dir, base, NULL );
|
||||
}
|
||||
|
||||
static void
|
||||
getTorrentOldFilename( const tr_handle * handle,
|
||||
const tr_info * info,
|
||||
char * name,
|
||||
size_t len )
|
||||
{
|
||||
const char * torDir = tr_getTorrentDir( handle );
|
||||
|
||||
if( !handle->tag )
|
||||
{
|
||||
tr_buildPath( name, len, torDir, hash, NULL );
|
||||
tr_buildPath( name, len, torDir, info->hashString, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
char base[1024];
|
||||
snprintf( base, sizeof(base), "%s-%s", hash, handle->tag );
|
||||
snprintf( base, sizeof(base), "%s-%s", info->hashString, handle->tag );
|
||||
tr_buildPath( name, len, torDir, base, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tr_metainfoMigrate( const tr_handle * handle,
|
||||
const tr_info * inf )
|
||||
{
|
||||
struct stat new_sb;
|
||||
char new_name[MAX_PATH_LENGTH];
|
||||
|
||||
getTorrentFilename( handle, inf, new_name, sizeof( new_name ) );
|
||||
|
||||
if( stat( new_name, &new_sb ) || ( ( new_sb.st_mode & S_IFMT ) != S_IFREG ) )
|
||||
{
|
||||
char old_name[MAX_PATH_LENGTH];
|
||||
size_t contentLen;
|
||||
uint8_t * content;
|
||||
|
||||
getTorrentOldFilename( handle, inf, old_name, sizeof( old_name ) );
|
||||
if(( content = tr_loadFile( old_name, &contentLen )))
|
||||
{
|
||||
FILE * out = fopen( new_name, "wb+" );
|
||||
if( fwrite( content, sizeof( uint8_t ), contentLen, out ) == contentLen )
|
||||
unlink( old_name );
|
||||
fclose( out );
|
||||
}
|
||||
|
||||
tr_free( content );
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
tr_metainfoParse( const tr_handle * handle,
|
||||
|
@ -172,9 +211,6 @@ tr_metainfoParse( const tr_handle * handle,
|
|||
}
|
||||
|
||||
tr_sha1_to_hex( inf->hashString, inf->hash );
|
||||
savedname( handle, buf, sizeof( buf ), inf->hashString );
|
||||
tr_free( inf->torrent );
|
||||
inf->torrent = tr_strdup( buf );
|
||||
|
||||
/* comment */
|
||||
memset( buf, '\0', sizeof( buf ) );
|
||||
|
@ -274,6 +310,12 @@ tr_metainfoParse( const tr_handle * handle,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
/* filename of Transmission's copy */
|
||||
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;
|
||||
|
||||
fail:
|
||||
|
@ -569,40 +611,15 @@ tr_trackerInfoClear( tr_tracker_info * info )
|
|||
|
||||
void
|
||||
tr_metainfoRemoveSaved( const tr_handle * handle,
|
||||
const char * hashString )
|
||||
const tr_info * inf )
|
||||
{
|
||||
char file[MAX_PATH_LENGTH];
|
||||
savedname( handle, file, sizeof file, hashString );
|
||||
unlink( file );
|
||||
}
|
||||
char filename[MAX_PATH_LENGTH];
|
||||
|
||||
/* Save a copy of the torrent file in the saved torrent directory */
|
||||
int
|
||||
tr_metainfoSave( const tr_handle * handle,
|
||||
const char * hash,
|
||||
const uint8_t * buf,
|
||||
size_t buflen )
|
||||
{
|
||||
char path[MAX_PATH_LENGTH];
|
||||
FILE * file;
|
||||
getTorrentFilename( handle, inf, filename, sizeof( filename ) );
|
||||
unlink( filename );
|
||||
|
||||
savedname( handle, path, sizeof path, hash );
|
||||
file = fopen( path, "wb+" );
|
||||
if( !file )
|
||||
{
|
||||
tr_err( _( "Couldn't open \"%1$s\": %2$s" ), path, tr_strerror( errno ) );
|
||||
return TR_EINVALID;
|
||||
}
|
||||
fseek( file, 0, SEEK_SET );
|
||||
if( fwrite( buf, 1, buflen, file ) != buflen )
|
||||
{
|
||||
tr_err( _( "Couldn't save file \"%1$s\": %2$s" ), path, tr_strerror( errno ) );
|
||||
fclose( file );
|
||||
return TR_EINVALID;
|
||||
}
|
||||
fclose( file );
|
||||
|
||||
return TR_OK;
|
||||
getTorrentOldFilename( handle, inf, filename, sizeof( filename ) );
|
||||
unlink( filename );
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -36,11 +36,9 @@ int tr_metainfoParse( const tr_handle * handle,
|
|||
void tr_metainfoFree( tr_info * inf );
|
||||
|
||||
void tr_metainfoRemoveSaved( const tr_handle * handle,
|
||||
const char * hashString );
|
||||
const tr_info * info );
|
||||
|
||||
int tr_metainfoSave( const tr_handle * handle,
|
||||
const char * hashString,
|
||||
const uint8_t * metainfo,
|
||||
size_t len );
|
||||
void tr_metainfoMigrate( const tr_handle * handle,
|
||||
const tr_info * inf );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,9 +10,7 @@
|
|||
* $Id:$
|
||||
*/
|
||||
|
||||
#include <sys/types.h> /* stat */
|
||||
#include <sys/stat.h> /* stat */
|
||||
#include <unistd.h> /* unlink, stat */
|
||||
#include <unistd.h> /* unlink */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -45,41 +43,14 @@
|
|||
#define KEY_PROGRESS_MTIMES "mtimes"
|
||||
#define KEY_PROGRESS_BITFIELD "bitfield"
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static time_t*
|
||||
getMTimes( const tr_torrent * tor, int * setme_n )
|
||||
{
|
||||
int i;
|
||||
const int n = tor->info.fileCount;
|
||||
time_t * m = tr_new( time_t, n );
|
||||
|
||||
for( i=0; i<n; ++i ) {
|
||||
char fname[MAX_PATH_LENGTH];
|
||||
struct stat sb;
|
||||
tr_buildPath( fname, sizeof(fname),
|
||||
tor->destination, tor->info.files[i].name, NULL );
|
||||
if ( !stat( fname, &sb ) && S_ISREG( sb.st_mode ) ) {
|
||||
#ifdef SYS_DARWIN
|
||||
m[i] = sb.st_mtimespec.tv_sec;
|
||||
#else
|
||||
m[i] = sb.st_mtime;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
*setme_n = n;
|
||||
return m;
|
||||
}
|
||||
|
||||
static void
|
||||
getResumeFilename( char * buf, size_t buflen, const tr_torrent * tor )
|
||||
{
|
||||
const char * dir = tr_getResumeDir( tor->handle );
|
||||
char base[4096];
|
||||
snprintf( base, sizeof( base ), "%s.%16.16s.resume", tor->info.name, tor->info.hashString );
|
||||
snprintf( base, sizeof( base ), "%s.%16.16s.resume",
|
||||
tor->info.name,
|
||||
tor->info.hashString );
|
||||
tr_buildPath( buf, buflen, dir, base, NULL );
|
||||
}
|
||||
|
||||
|
@ -91,7 +62,8 @@ static void
|
|||
savePeers( tr_benc * dict, const tr_torrent * tor )
|
||||
{
|
||||
tr_pex * pex;
|
||||
const int count = tr_peerMgrGetPeers( tor->handle->peerMgr, tor->info.hash, &pex );
|
||||
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 );
|
||||
|
@ -114,7 +86,8 @@ loadPeers( tr_benc * dict, tr_torrent * tor )
|
|||
for( i=0; i<count; ++i ) {
|
||||
tr_pex pex;
|
||||
memcpy( &pex, str + (i*sizeof(tr_pex)), sizeof(tr_pex) );
|
||||
tr_peerMgrAddPex( tor->handle->peerMgr, tor->info.hash, TR_PEER_FROM_CACHE, &pex );
|
||||
tr_peerMgrAddPex( tor->handle->peerMgr,
|
||||
tor->info.hash, TR_PEER_FROM_CACHE, &pex );
|
||||
}
|
||||
tr_tordbg( tor, "Loaded %d peers from resume file", count );
|
||||
ret = TR_FR_PEERS;
|
||||
|
@ -123,6 +96,10 @@ loadPeers( tr_benc * dict, tr_torrent * tor )
|
|||
return ret;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static void
|
||||
savePriorities( tr_benc * dict, const tr_torrent * tor )
|
||||
{
|
||||
|
@ -144,7 +121,8 @@ loadPriorities( tr_benc * dict, tr_torrent * tor )
|
|||
const tr_file_index_t n = inf->fileCount;
|
||||
tr_benc * list;
|
||||
|
||||
if( tr_bencDictFindList( dict, KEY_PRIORITY, &list ) && ( list->val.l.count == (int)n ) )
|
||||
if( tr_bencDictFindList( dict, KEY_PRIORITY, &list )
|
||||
&& ( list->val.l.count == (int)n ) )
|
||||
{
|
||||
int64_t tmp;
|
||||
tr_file_index_t i;
|
||||
|
@ -157,6 +135,10 @@ loadPriorities( tr_benc * dict, tr_torrent * tor )
|
|||
return ret;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static void
|
||||
saveSpeedLimits( tr_benc * dict, const tr_torrent * tor )
|
||||
{
|
||||
|
@ -194,6 +176,10 @@ loadSpeedLimits( tr_benc * dict, tr_torrent * tor )
|
|||
return ret;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static void
|
||||
saveProgress( tr_benc * dict, const tr_torrent * tor )
|
||||
{
|
||||
|
@ -209,13 +195,12 @@ saveProgress( tr_benc * dict, const tr_torrent * tor )
|
|||
tr_bencInitDict( p, 2 );
|
||||
|
||||
/* add the mtimes */
|
||||
m = tr_bencDictAdd( p, KEY_PROGRESS_MTIMES );
|
||||
mtimes = getMTimes( tor, &n );
|
||||
tr_bencInitList( m, n );
|
||||
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_bencInitInt( tr_bencListAdd( m ), mtimes[i] );
|
||||
tr_bencListAddInt( m, mtimes[i] );
|
||||
}
|
||||
|
||||
/* add the bitfield */
|
||||
|
@ -238,19 +223,19 @@ loadProgress( tr_benc * dict, tr_torrent * tor )
|
|||
tr_benc * m;
|
||||
tr_benc * b;
|
||||
int n;
|
||||
time_t * curMTimes = getMTimes( tor, &n );
|
||||
time_t * curMTimes = tr_torrentGetMTimes( tor, &n );
|
||||
|
||||
if( tr_bencDictFindList( p, KEY_PROGRESS_MTIMES, &m )
|
||||
&& ( m->val.l.count == (int64_t)tor->info.fileCount )
|
||||
&& ( 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 tmp;
|
||||
const time_t t = tr_bencGetInt( &m->val.l.vals[i], &tmp )
|
||||
? tmp : ~(time_t)0;
|
||||
if( curMTimes[i] == t )
|
||||
int64_t x;
|
||||
time_t t = tr_bencGetInt( &m->val.l.vals[i], &x ) ? x : recheck;
|
||||
if( ( t != recheck ) && ( curMTimes[i] == t ) )
|
||||
tr_torrentSetFileChecked( tor, i, TRUE );
|
||||
else {
|
||||
tr_torrentSetFileChecked( tor, i, FALSE );
|
||||
|
@ -287,19 +272,24 @@ loadProgress( tr_benc * dict, tr_torrent * tor )
|
|||
return ret;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
void
|
||||
tr_torrentSaveResume( const tr_torrent * tor )
|
||||
{
|
||||
tr_benc top;
|
||||
char * encoded;
|
||||
int len;
|
||||
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_DOWNLOADED, tor->downloadedPrev + tor->downloadedCur );
|
||||
tr_bencDictAddInt( &top, KEY_UPLOADED, tor->uploadedPrev + tor->uploadedCur );
|
||||
tr_bencDictAddInt( &top, KEY_DOWNLOADED,
|
||||
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 );
|
||||
savePeers( &top, tor );
|
||||
|
@ -307,19 +297,9 @@ tr_torrentSaveResume( const tr_torrent * tor )
|
|||
saveProgress( &top, tor );
|
||||
saveSpeedLimits( &top, tor );
|
||||
|
||||
/* save the bencoded data */
|
||||
if(( encoded = tr_bencSave( &top, &len )))
|
||||
{
|
||||
char filename[MAX_PATH_LENGTH];
|
||||
FILE * fp;
|
||||
getResumeFilename( filename, sizeof( filename ), tor );
|
||||
fp = fopen( filename, "wb+" );
|
||||
fwrite( encoded, len, 1, fp );
|
||||
fclose( fp );
|
||||
tr_free( encoded );
|
||||
}
|
||||
getResumeFilename( filename, sizeof( filename ), tor );
|
||||
tr_bencSaveFile( filename, &top );
|
||||
|
||||
/* cleanup */
|
||||
tr_bencFree( &top );
|
||||
}
|
||||
|
||||
|
@ -330,21 +310,15 @@ tr_torrentLoadResume( tr_torrent * tor,
|
|||
{
|
||||
int64_t i;
|
||||
const char * str;
|
||||
int benc_loaded = FALSE;
|
||||
uint64_t fieldsLoaded = 0;
|
||||
uint8_t * content = NULL;
|
||||
size_t contentLen;
|
||||
char filename[MAX_PATH_LENGTH];
|
||||
tr_benc top;
|
||||
|
||||
getResumeFilename( filename, sizeof( filename ), tor );
|
||||
|
||||
content = tr_loadFile( filename, &contentLen );
|
||||
benc_loaded = content && !tr_bencLoad( content, contentLen, &top, NULL );
|
||||
if( !benc_loaded )
|
||||
if( tr_bencLoadFile( filename, &top ) )
|
||||
{
|
||||
tr_free( content );
|
||||
tr_tordbg( tor, "Couldn't read \"%s\"; trying old resume file format.", filename );
|
||||
tr_tordbg( tor, "Couldn't read \"%s\"; trying old format.", filename );
|
||||
fieldsLoaded = tr_fastResumeLoad( tor, fieldsToLoad, ctor );
|
||||
|
||||
if( ( fieldsLoaded != 0 ) && ( fieldsToLoad == ~(uint64_t)0 ) )
|
||||
|
@ -359,41 +333,54 @@ tr_torrentLoadResume( tr_torrent * tor,
|
|||
|
||||
tr_tordbg( tor, "Read resume file \"%s\"", filename );
|
||||
|
||||
if( tr_bencDictFindInt( &top, KEY_CORRUPT, &i ) ) {
|
||||
if( ( fieldsToLoad & TR_FR_CORRUPT )
|
||||
&& tr_bencDictFindInt( &top, KEY_CORRUPT, &i ) ) {
|
||||
tor->corruptPrev = i;
|
||||
fieldsLoaded |= TR_FR_CORRUPT;
|
||||
}
|
||||
|
||||
if( tr_bencDictFindStr( &top, KEY_DESTINATION, &str ) ) {
|
||||
if( ( fieldsToLoad & TR_FR_DESTINATION )
|
||||
&& tr_bencDictFindStr( &top, KEY_DESTINATION, &str ) ) {
|
||||
tr_free( tor->destination );
|
||||
tor->destination = tr_strdup( str );
|
||||
fieldsLoaded |= TR_FR_DESTINATION;
|
||||
}
|
||||
|
||||
if( tr_bencDictFindInt( &top, KEY_DOWNLOADED, &i ) ) {
|
||||
if( ( fieldsToLoad & TR_FR_DOWNLOADED )
|
||||
&& tr_bencDictFindInt( &top, KEY_DOWNLOADED, &i ) ) {
|
||||
tor->downloadedPrev = i;
|
||||
fieldsLoaded |= TR_FR_DOWNLOADED;
|
||||
}
|
||||
|
||||
if( tr_bencDictFindInt( &top, KEY_UPLOADED, &i ) ) {
|
||||
if( ( fieldsToLoad & TR_FR_UPLOADED )
|
||||
&& tr_bencDictFindInt( &top, KEY_UPLOADED, &i ) ) {
|
||||
tor->uploadedPrev = i;
|
||||
fieldsLoaded |= TR_FR_UPLOADED;
|
||||
}
|
||||
|
||||
if( tr_bencDictFindInt( &top, KEY_MAX_PEERS, &i ) ) {
|
||||
if( ( fieldsToLoad & TR_FR_MAX_PEERS )
|
||||
&& tr_bencDictFindInt( &top, KEY_MAX_PEERS, &i ) ) {
|
||||
tor->maxConnectedPeers = i;
|
||||
fieldsLoaded |= TR_FR_MAX_PEERS;
|
||||
}
|
||||
|
||||
if( tr_bencDictFindInt( &top, KEY_PAUSED, &i ) ) {
|
||||
if( ( fieldsToLoad & TR_FR_RUN )
|
||||
&& tr_bencDictFindInt( &top, KEY_PAUSED, &i ) ) {
|
||||
tor->isRunning = i ? 0 : 1;
|
||||
fieldsLoaded |= TR_FR_RUN;
|
||||
}
|
||||
|
||||
fieldsLoaded |= loadPeers( &top, tor );
|
||||
fieldsLoaded |= loadPriorities( &top, tor );
|
||||
fieldsLoaded |= loadProgress( &top, tor );
|
||||
fieldsLoaded |= loadSpeedLimits( &top, tor );
|
||||
if( fieldsToLoad & TR_FR_PEERS )
|
||||
fieldsLoaded |= loadPeers( &top, tor );
|
||||
|
||||
if( fieldsToLoad & TR_FR_PRIORITY )
|
||||
fieldsLoaded |= loadPriorities( &top, tor );
|
||||
|
||||
if( fieldsToLoad & TR_FR_PROGRESS )
|
||||
fieldsLoaded |= loadProgress( &top, tor );
|
||||
|
||||
if( fieldsToLoad & TR_FR_SPEEDLIMIT )
|
||||
fieldsLoaded |= loadSpeedLimits( &top, tor );
|
||||
|
||||
tr_bencFree( &top );
|
||||
return fieldsLoaded;
|
||||
|
|
|
@ -81,27 +81,20 @@ loadCumulativeStats( const tr_handle * handle, tr_session_stats * setme )
|
|||
}
|
||||
|
||||
static void
|
||||
saveCumulativeStats( const tr_handle * handle, const tr_session_stats * stats )
|
||||
saveCumulativeStats( const tr_handle * handle, const tr_session_stats * s )
|
||||
{
|
||||
FILE * fp;
|
||||
char * str;
|
||||
char filename[MAX_PATH_LENGTH];
|
||||
int len;
|
||||
tr_benc top;
|
||||
|
||||
tr_bencInitDict( &top, 5 );
|
||||
tr_bencInitInt( tr_bencDictAdd( &top, "uploaded-bytes" ), stats->uploadedBytes );
|
||||
tr_bencInitInt( tr_bencDictAdd( &top, "downloaded-bytes" ), stats->downloadedBytes );
|
||||
tr_bencInitInt( tr_bencDictAdd( &top, "files-added" ), stats->filesAdded );
|
||||
tr_bencInitInt( tr_bencDictAdd( &top, "session-count" ), stats->sessionCount );
|
||||
tr_bencInitInt( tr_bencDictAdd( &top, "seconds-active" ), stats->secondsActive );
|
||||
tr_bencInitInt( tr_bencDictAdd( &top, "uploaded-bytes" ), s->uploadedBytes );
|
||||
tr_bencInitInt( tr_bencDictAdd( &top, "downloaded-bytes" ), s->downloadedBytes );
|
||||
tr_bencInitInt( tr_bencDictAdd( &top, "files-added" ), s->filesAdded );
|
||||
tr_bencInitInt( tr_bencDictAdd( &top, "session-count" ), s->sessionCount );
|
||||
tr_bencInitInt( tr_bencDictAdd( &top, "seconds-active" ), s->secondsActive );
|
||||
|
||||
str = tr_bencSave( &top, &len );
|
||||
getFilename( handle, filename, sizeof(filename) );
|
||||
fp = fopen( filename, "wb+" );
|
||||
fwrite( str, 1, len, fp );
|
||||
fclose( fp );
|
||||
tr_free( str );
|
||||
tr_bencSaveFile( filename, &top );
|
||||
|
||||
tr_bencFree( &top );
|
||||
}
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <sys/types.h> /* stat */
|
||||
#include <sys/stat.h> /* stat */
|
||||
#include <unistd.h> /* stat */
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h> /* memcmp */
|
||||
|
||||
|
@ -381,15 +385,13 @@ torrentRealInit( tr_handle * h,
|
|||
if( tr_ctorGetSave( ctor ) ) {
|
||||
const tr_benc * val;
|
||||
if( !tr_ctorGetMetainfo( ctor, &val ) ) {
|
||||
int len;
|
||||
uint8_t * text = (uint8_t*) tr_bencSave( val, &len );
|
||||
tr_metainfoSave( tor->handle,
|
||||
tor->info.hashString,
|
||||
text, len );
|
||||
tr_free( text );
|
||||
const char * filename = tor->info.torrent;
|
||||
tr_bencSaveFile( filename, val );
|
||||
}
|
||||
}
|
||||
|
||||
tr_metainfoMigrate( h, &tor->info );
|
||||
|
||||
if( doStart )
|
||||
tr_torrentStart( tor );
|
||||
}
|
||||
|
@ -812,7 +814,7 @@ tr_torrentSetHasPiece( tr_torrent * tor, tr_piece_index_t pieceIndex, int has )
|
|||
void
|
||||
tr_torrentRemoveSaved( tr_torrent * tor )
|
||||
{
|
||||
tr_metainfoRemoveSaved( tor->handle, tor->info.hashString );
|
||||
tr_metainfoRemoveSaved( tor->handle, &tor->info );
|
||||
|
||||
tr_torrentRemoveResume( tor );
|
||||
}
|
||||
|
@ -1419,3 +1421,28 @@ tr_torrentCountUncheckedPieces( const tr_torrent * tor )
|
|||
{
|
||||
return tor->info.pieceCount - tr_bitfieldCountTrueBits( tor->checkedPieces );
|
||||
}
|
||||
|
||||
time_t*
|
||||
tr_torrentGetMTimes( const tr_torrent * tor, int * setme_n )
|
||||
{
|
||||
int i;
|
||||
const int n = tor->info.fileCount;
|
||||
time_t * m = tr_new( time_t, n );
|
||||
|
||||
for( i=0; i<n; ++i ) {
|
||||
char fname[MAX_PATH_LENGTH];
|
||||
struct stat sb;
|
||||
tr_buildPath( fname, sizeof(fname),
|
||||
tor->destination, tor->info.files[i].name, NULL );
|
||||
if ( !stat( fname, &sb ) && S_ISREG( sb.st_mode ) ) {
|
||||
#ifdef SYS_DARWIN
|
||||
m[i] = sb.st_mtimespec.tv_sec;
|
||||
#else
|
||||
m[i] = sb.st_mtime;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
*setme_n = n;
|
||||
return m;
|
||||
}
|
||||
|
|
|
@ -101,6 +101,8 @@ void tr_torrentSetPieceChecked ( tr_torrent *, tr_piece_index_t piece, int i
|
|||
void tr_torrentSetFileChecked ( tr_torrent *, tr_file_index_t file, int isChecked );
|
||||
void tr_torrentUncheck ( tr_torrent * );
|
||||
|
||||
time_t* tr_torrentGetMTimes ( const tr_torrent *, int * setmeCount );
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TR_VERIFY_NONE,
|
||||
|
|
Loading…
Reference in a new issue