]> granicus.if.org Git - transmission/commitdiff
'resume' cleanup
authorCharles Kerr <charles@transmissionbt.com>
Mon, 14 Apr 2008 11:52:50 +0000 (11:52 +0000)
committerCharles Kerr <charles@transmissionbt.com>
Mon, 14 Apr 2008 11:52:50 +0000 (11:52 +0000)
libtransmission/bencode.c
libtransmission/bencode.h
libtransmission/metainfo.c
libtransmission/metainfo.h
libtransmission/resume.c
libtransmission/stats.c
libtransmission/torrent.c
libtransmission/torrent.h

index cdd0ac9dc46883a58d07657998ab206aa703b9a2..e09b3747d9fb8424303b37a098048d86af9eaa45 100644 (file)
@@ -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;
+}
index 4c7cfea96d57685b81092f8816b2f19442a41d81..f542c1c59bff3748dec736bd8469c7cfdaf826cc 100644 (file)
@@ -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 );
 
index 26dd5bc6d0cd4e1c2e3c78d252176ef0bb55b683..e36c3ac90585274c34fa265e19e34f8c65586ead 100644 (file)
@@ -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
index e056d7b57c2746dfc4dd3b9da9e5a0485ee582c8..b7dfd0227f92f74f9fbe9a617fd284d9b07e8b28 100644 (file)
@@ -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
index 37d04555bdb65ea34faf2a50edce94952a3b3f76..f3d95503f0a81c677b30fd90944c831d0da176f5 100644 (file)
@@ -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>
 
 #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;
index 849334e5fff7d81a9c9dd929a0c6deecc65a5125..44ba24ab2d55f87d9bfc5f267e3b5d37a6c58d7f 100644 (file)
@@ -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 );
 }
index 17f95a3ee422e36e80f01a391e0d3886dfeb8653..4a416f182c8c20abc89fac165ed556b7b66c6e75 100644 (file)
  * 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;
+}
index 5d06e3051200d8b139093782d4212765c6e8ef87..931ad83ba09c5acc5040feba3920503a3ac37bdb 100644 (file)
@@ -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,