Ignore:
Timestamp:
Nov 26, 2007, 3:54:20 AM (15 years ago)
Author:
charles
Message:

fix crash when loading fastresume files

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/fastresume.c

    r3815 r3969  
    5353#include <unistd.h>
    5454
     55#include <event.h>
     56
    5557#include "transmission.h"
    5658#include "completion.h"
     
    330332}
    331333
    332 static int
    333 loadDestination( tr_torrent * tor, FILE * fp, const char * destination, int argIsFallback )
    334 {
    335     int pathlen = 0;
    336     char path[MAX_PATH_LENGTH];
    337 
    338     for( ;; ) {
    339         const int ch = fgetc( fp );
    340         if( ch==EOF ) /* end of file */
    341             return TR_ERROR_IO_OTHER;
    342         if( ch=='\0' ) /* end of string */
    343             break;
    344         path[pathlen++] = (char) ch;
    345     }
    346 
    347     path[pathlen] = '\0';
    348 
    349     if( argIsFallback )
    350         tor->destination = tr_strdup( pathlen ? path : destination );
    351     else
    352         tor->destination = tr_strdup( destination && *destination ? destination : path );
    353 
    354     return TR_OK;
    355 }
    356 
    357 static int
    358 loadSpeeds( tr_torrent * tor, FILE * file )
    359 {
    360     const size_t len = FR_SPEED_LEN;
    361     char * buf = tr_new0( char, len );
    362     char * walk = buf;
    363     uint16_t i16;
    364     uint8_t i8;
    365 
    366     if( len != fread( buf, 1, len, file ) ) {
    367         tr_inf( "Couldn't read from resume file" );
    368         free( buf );
    369         return TR_ERROR_IO_OTHER;
    370     }
    371 
    372     memcpy( &i16, walk, 2 ); walk += 2;
    373     tr_torrentSetSpeedLimit( tor, TR_DOWN, i16 );
    374     memcpy( &i8, walk, 1 ); walk += 1;
    375     tr_torrentSetSpeedMode( tor, TR_DOWN, (tr_speedlimit)i8 );
    376     memcpy( &i16, walk, 2 ); walk += 2;
    377     tr_torrentSetSpeedLimit( tor, TR_UP, i16 );
    378     memcpy( &i8, walk, 1 ); walk += 1;
    379     tr_torrentSetSpeedMode( tor, TR_UP, (tr_speedlimit)i8 );
    380 
    381     tr_free( buf );
    382     return TR_OK;
    383 }
    384 
    385 
    386 static int
    387 loadPriorities( tr_torrent * tor,
    388                 FILE       * file )
    389 {
    390     const size_t n = tor->info.fileCount;
    391     const size_t len = 2 * n;
    392     int *dnd = NULL, dndCount = 0;
    393     int *dl = NULL, dlCount = 0;
    394     char * buf = tr_new0( char, len );
    395     char * walk = buf;
    396     size_t i;
    397 
    398     if( len != fread( buf, 1, len, file ) ) {
    399         tr_inf( "Couldn't read from resume file" );
    400         free( buf );
    401         return TR_ERROR_IO_OTHER;
    402     }
    403 
    404     /* set file priorities */
    405     for( i=0; i<n; ++i ) {
    406        tr_priority_t priority;
    407        const char ch = *walk++;
    408        switch( ch ) {
    409            case 'l': priority = TR_PRI_LOW; break;
    410            case 'h': priority = TR_PRI_HIGH; break;
    411            default:  priority = TR_PRI_NORMAL; break;
    412        }
    413        tor->info.files[i].priority = priority;
    414     }
    415 
    416     /* set the dnd flags */
    417     dl = tr_new( int, len );
    418     dnd = tr_new( int, len );
    419     for( i=0; i<n; ++i )
    420         if( *walk++ == 't' ) /* 't' means the DND flag is true */
    421             dnd[dndCount++] = i;
    422         else
    423             dl[dlCount++] = i;
    424 
    425     if( dndCount )
    426         tr_torrentSetFileDLs ( tor, dnd, dndCount, FALSE );
    427     if( dlCount )
    428         tr_torrentSetFileDLs ( tor, dl, dlCount, TRUE );
    429 
    430     tr_free( dnd );
    431     tr_free( dl );
    432     tr_free( buf );
    433     return TR_OK;
    434 }
    435 
    436 static int
    437 fastResumeLoadProgress( const tr_torrent  * tor,
    438                         tr_bitfield       * uncheckedPieces,
    439                         FILE              * file )
    440 {
    441     const size_t len = FR_PROGRESS_LEN( tor );
    442     uint8_t * buf = calloc( len, 1 );
    443     int ret = 0;
     334/***
     335****
     336***/
     337
     338static uint64_t
     339internalIdToPublicBitfield( uint8_t id )
     340{
     341    uint64_t ret = 0;
     342
     343    switch( id )
     344    {
     345        case FR_ID_PROGRESS_SLOTS: ret = 0;                 break;
     346        case FR_ID_DOWNLOADED:     ret = TR_FR_DOWNLOADED;  break;
     347        case FR_ID_UPLOADED:       ret = TR_FR_UPLOADED;    break;
     348        case FR_ID_PEERS_OLD:      ret = TR_FR_PEERS;       break;
     349        case FR_ID_PROGRESS:       ret = TR_FR_PROGRESS;    break;
     350        case FR_ID_PRIORITY:       ret = TR_FR_PRIORITY;    break;
     351        case FR_ID_SPEED:          ret = TR_FR_SPEEDLIMIT;  break;
     352        case FR_ID_RUN:            ret = TR_FR_RUN;         break;
     353        case FR_ID_CORRUPT:        ret = TR_FR_CORRUPT;     break;
     354        case FR_ID_PEERS:          ret = TR_FR_PEERS;       break;
     355        case FR_ID_DESTINATION:    ret = TR_FR_DESTINATION; break;
     356        case FR_ID_PEX:            ret = TR_FR_PEX;         break;
     357    }
     358
     359    return ret;
     360}
     361
     362static void
     363readBytes( void * target, const uint8_t ** source, size_t byteCount )
     364{
     365    memcpy( target, *source, byteCount );
     366    *source += byteCount;
     367}
     368
     369static uint64_t
     370parseDownloaded( tr_torrent * tor, const uint8_t * buf, uint32_t len )
     371{
     372    if( len != sizeof(uint64_t) )
     373        return 0;
     374    readBytes( &tor->downloadedPrev, &buf, sizeof(uint64_t) );
     375    return TR_FR_DOWNLOADED;
     376}
     377
     378static uint64_t
     379parseUploaded( tr_torrent * tor, const uint8_t * buf, uint32_t len )
     380{
     381    if( len != sizeof(uint64_t) )
     382        return 0;
     383    readBytes( &tor->uploadedPrev, &buf, sizeof(uint64_t) );
     384    return TR_FR_UPLOADED;
     385}
     386
     387static uint64_t
     388parseCorrupt( tr_torrent * tor, const uint8_t * buf, uint32_t len )
     389{
     390    if( len != sizeof(uint64_t) )
     391        return 0;
     392    readBytes( &tor->corruptPrev, &buf, sizeof(uint64_t) );
     393    return TR_FR_CORRUPT;
     394}
     395
     396static uint64_t
     397parseProgress( const tr_torrent  * tor,
     398               const uint8_t     * buf,
     399               uint32_t            len,
     400               tr_bitfield       * uncheckedPieces )
     401{
    444402    int i;
    445 
    446     if( len != fread( buf, 1, len, file ) )
    447     {
    448         tr_inf( "Couldn't read from resume file" );
    449         tr_bitfieldAddRange( uncheckedPieces, 0, tor->info.pieceCount );
    450         ret = TR_ERROR_IO_OTHER;
    451     }
    452     else
     403    uint64_t ret = 0;
     404   
     405    if( len == FR_PROGRESS_LEN( tor ) )
    453406    {
    454407        int n;
     
    457410        /* compare file mtimes */
    458411        tr_time_t * curMTimes = getMTimes( tor, &n );
    459         uint8_t * walk = buf;
     412        const uint8_t * walk = buf;
    460413        const tr_time_t * oldMTimes = (const tr_time_t *) walk;
    461414        for( i=0; i<n; ++i ) {
     
    474427        memset( &bitfield, 0, sizeof bitfield );
    475428        bitfield.len = FR_BLOCK_BITFIELD_LEN( tor );
    476         bitfield.bits = walk;
     429        bitfield.bits = (uint8_t*) walk;
    477430        tr_cpBlockBitfieldSet( tor->completion, &bitfield );
     431
     432        ret = TR_FR_PROGRESS;
    478433    }
    479434
     
    484439            tr_cpPieceRem( tor->completion, i );
    485440
    486 
    487     free( buf );
    488     return ret;
    489 }
    490 
    491 static uint64_t
    492 fastResumeLoadOld( tr_torrent   * tor,
    493                    tr_bitfield  * uncheckedPieces,
    494                    FILE         * file )
     441    return ret;
     442}
     443
     444static uint64_t
     445parsePriorities( tr_torrent * tor, const uint8_t * buf, uint32_t len )
    495446{
    496447    uint64_t ret = 0;
    497448
    498     /* Check the size */
    499     const int size = 4 + FR_PROGRESS_LEN( tor );
    500     fseek( file, 0, SEEK_END );
    501     if( ftell( file ) != size )
    502     {
    503         tr_inf( "Wrong size for resume file (%d bytes, %d expected)",
    504                 (int)ftell( file ), size );
    505         fclose( file );
    506         return 1;
    507     }
    508 
    509     /* load progress information */
    510     fseek( file, 4, SEEK_SET );
    511     if( fastResumeLoadProgress( tor, uncheckedPieces, file ) )
    512     {
    513         fclose( file );
    514         return 1;
    515     }
    516 
    517     fclose( file );
    518 
    519     ret |= TR_FR_PROGRESS;
    520     tr_inf( "Fast resuming successful (version 0)" );
    521 
    522     return ret;
    523 }
    524 
    525 static uint64_t
    526 internalIdToPublicBitfield( uint8_t id )
     449    if( len == (uint32_t)(2 * tor->info.fileCount) )
     450    {
     451        const size_t n = tor->info.fileCount;
     452        const size_t len = 2 * n;
     453        int *dnd = NULL, dndCount = 0;
     454        int *dl = NULL, dlCount = 0;
     455        size_t i;
     456        const uint8_t * walk = buf;
     457
     458        /* set file priorities */
     459        for( i=0; i<n; ++i ) {
     460           tr_priority_t priority;
     461           const char ch = *walk++;
     462           switch( ch ) {
     463               case 'l': priority = TR_PRI_LOW; break;
     464               case 'h': priority = TR_PRI_HIGH; break;
     465               default:  priority = TR_PRI_NORMAL; break;
     466           }
     467           tor->info.files[i].priority = priority;
     468        }
     469
     470        /* set the dnd flags */
     471        dl = tr_new( int, len );
     472        dnd = tr_new( int, len );
     473        for( i=0; i<n; ++i )
     474            if( *walk++ == 't' ) /* 't' means the DND flag is true */
     475                dnd[dndCount++] = i;
     476            else
     477                dl[dlCount++] = i;
     478
     479        if( dndCount )
     480            tr_torrentSetFileDLs ( tor, dnd, dndCount, FALSE );
     481        if( dlCount )
     482            tr_torrentSetFileDLs ( tor, dl, dlCount, TRUE );
     483
     484        tr_free( dnd );
     485        tr_free( dl );
     486
     487        ret = TR_FR_PRIORITY;
     488    }
     489
     490    return ret;
     491}
     492
     493static uint64_t
     494parseSpeedLimit( tr_torrent * tor, const uint8_t * buf, uint32_t len )
    527495{
    528496    uint64_t ret = 0;
    529497
    530     switch( id )
    531     {
    532         case FR_ID_PROGRESS_SLOTS: ret = 0;                 break;
    533         case FR_ID_DOWNLOADED:     ret = TR_FR_DOWNLOADED;  break;
    534         case FR_ID_UPLOADED:       ret = TR_FR_UPLOADED;    break;
    535         case FR_ID_PEERS_OLD:      ret = TR_FR_PEERS;       break;
    536         case FR_ID_PROGRESS:       ret = TR_FR_PROGRESS;    break;
    537         case FR_ID_PRIORITY:       ret = TR_FR_PRIORITY;    break;
    538         case FR_ID_SPEED:          ret = TR_FR_SPEEDLIMIT;  break;
    539         case FR_ID_RUN:            ret = TR_FR_RUN;         break;
    540         case FR_ID_CORRUPT:        ret = TR_FR_CORRUPT;     break;
    541         case FR_ID_PEERS:          ret = TR_FR_PEERS;       break;
    542         case FR_ID_DESTINATION:    ret = TR_FR_DESTINATION; break;
    543         case FR_ID_PEX:            ret = TR_FR_PEX;         break;
     498    if( len == FR_SPEED_LEN )
     499    {
     500        uint8_t i8;
     501        uint16_t i16;
     502
     503        readBytes( &i16, &buf, sizeof(i16) );
     504        tr_torrentSetSpeedLimit( tor, TR_DOWN, i16 );
     505        readBytes( &i8, &buf, sizeof(i8) );
     506        tr_torrentSetSpeedMode( tor, TR_DOWN, (tr_speedlimit)i8 );
     507        readBytes( &i16, &buf, sizeof(i16) );
     508        tr_torrentSetSpeedLimit( tor, TR_UP, i16 );
     509        readBytes( &i8, &buf, sizeof(i8) );
     510        tr_torrentSetSpeedMode( tor, TR_UP, (tr_speedlimit)i8 );
     511
     512        ret = TR_FR_SPEEDLIMIT;
     513    }
     514
     515    return ret;
     516}
     517
     518static uint64_t
     519parseRun( tr_torrent * tor, const uint8_t * buf, uint32_t len )
     520{
     521    if( len != 1 )
     522        return 0;
     523    tor->isRunning = *buf=='t';
     524    return TR_FR_RUN;
     525}
     526
     527static uint64_t
     528parsePex( tr_torrent * tor, const uint8_t * buf, uint32_t len )
     529{
     530    if( len != 1 )
     531        return 0;
     532    tor->pexDisabled = *buf!='t';
     533    return TR_FR_PEX;
     534}
     535
     536static uint64_t
     537parsePeers( tr_torrent * tor, const uint8_t * buf, uint32_t len )
     538{
     539    uint64_t ret = 0;
     540
     541    if( !tor->info.isPrivate )
     542    {
     543        const int count = len / sizeof(tr_pex);
     544        tr_peerMgrAddPex( tor->handle->peerMgr,
     545                          tor->info.hash,
     546                          TR_PEER_FROM_CACHE,
     547                          (tr_pex*)buf, count );
     548        tr_dbg( "found %i peers in resume file", count );
     549        ret = TR_FR_PEERS;
     550    }
     551
     552    return ret;
     553}
     554
     555static uint64_t
     556parseDestination( tr_torrent * tor, const uint8_t * buf, uint32_t len,
     557                  const char * destination, int argIsFallback )
     558{
     559    if( argIsFallback )
     560        tor->destination = tr_strdup( len ? (const char*)buf : destination );
     561    else
     562        tor->destination = tr_strdup( len ? destination : (const char*)buf );
     563
     564    return TR_FR_DESTINATION;
     565}
     566
     567static uint64_t
     568parseVersion1( tr_torrent * tor, const uint8_t * buf, const uint8_t * end,
     569               uint64_t fieldsToLoad,
     570               tr_bitfield  * uncheckedPieces,
     571               const char * destination, int argIsFallback )
     572{
     573    uint64_t ret = 0;
     574
     575    while( end-buf >= 5 )
     576    {
     577        uint8_t id;
     578        uint32_t len;
     579        readBytes( &id, &buf, sizeof(id) );
     580        readBytes( &len, &buf, sizeof(len) );
     581
     582        if( fieldsToLoad & internalIdToPublicBitfield( id ) ) switch( id )
     583        {
     584            case FR_ID_DOWNLOADED:  ret |= parseDownloaded( tor, buf, len ); break;
     585            case FR_ID_UPLOADED:    ret |= parseUploaded( tor, buf, len ); break;
     586            case FR_ID_PROGRESS:    ret |= parseProgress( tor, buf, len, uncheckedPieces ); break;
     587            case FR_ID_PRIORITY:    ret |= parsePriorities( tor, buf, len ); break;
     588            case FR_ID_SPEED:       ret |= parseSpeedLimit( tor, buf, len ); break;
     589            case FR_ID_RUN:         ret |= parseRun( tor, buf, len ); break;
     590            case FR_ID_CORRUPT:     ret |= parseCorrupt( tor, buf, len ); break;
     591            case FR_ID_PEERS:       ret |= parsePeers( tor, buf, len ); break;
     592            case FR_ID_PEX:         ret |= parsePex( tor, buf, len ); break;
     593            case FR_ID_DESTINATION: ret |= parseDestination( tor, buf, len, destination, argIsFallback ); break;
     594            default:                tr_dbg( "Skipping unknown resume code %d", (int)id ); break;
     595        }
     596
     597        buf += len;
     598    }
     599
     600    return ret;
     601}
     602
     603static uint8_t*
     604loadResumeFile( const tr_torrent * tor, size_t * len )
     605{
     606    uint8_t * ret = NULL;
     607    char path[MAX_PATH_LENGTH];
     608    const char * cacheDir = tr_getCacheDirectory ();
     609    const char * hash = tor->info.hashString;
     610
     611    if( !ret && tor->handle->tag )
     612    {
     613        char base[1024];
     614        snprintf( base, sizeof(base), "%s-%s", hash, tor->handle->tag );
     615        tr_buildPath( path, sizeof(path), cacheDir, base, NULL );
     616        ret = tr_loadFile( path, len );
     617    }
     618
     619    if( !ret )
     620    {
     621        tr_buildPath( path, sizeof(path), cacheDir, hash, NULL );
     622        ret = tr_loadFile( path, len );
    544623    }
    545624
     
    554633                     int            argIsFallback )
    555634{
    556     char      path[MAX_PATH_LENGTH];
    557     FILE    * file;
    558     int       version = 0;
    559     uint8_t   id;
    560     uint32_t  len;
    561     uint64_t  ret = 0;
    562 
    563     assert( tor != NULL );
    564     assert( uncheckedPieces != NULL );
    565 
    566     /* Open resume file */
    567     fastResumeFileName( path, sizeof path, tor, 1 );
    568     file = fopen( path, "rb" );
    569     if( !file )
    570     {
    571         if( ENOENT == errno )
    572         {
    573             fastResumeFileName( path, sizeof path, tor, 0 );
    574             file = fopen( path, "rb" );
    575             if( !file )
    576             {
    577                 fastResumeFileName( path, sizeof path, tor, 1 );
    578                 tr_inf( "Couldn't open '%s' for reading", path );
    579                 return ret;
    580             }
     635    uint64_t ret = 0;
     636    size_t size = 0;
     637    uint8_t * buf = loadResumeFile( tor, &size );
     638
     639    if( !buf )
     640        tr_inf( "Couldn't read resume file for '%s'", tor->info.name );
     641    else {
     642        const uint8_t * walk = buf;
     643        const uint8_t * end = walk + size;
     644        if( end - walk >= 4 ) {
     645            uint32_t version;
     646            readBytes( &version, &walk, sizeof(version) );
     647            if( version == 1 )
     648                ret |= parseVersion1 ( tor, walk, end, fieldsToLoad, uncheckedPieces, destination, argIsFallback );
     649            else
     650                tr_inf( "Unsupported resume file %d for '%s'", version, tor->info.name );
    581651        }
    582     }
    583 
    584     tr_dbg( "Resume file '%s' loaded", path );
    585 
    586     /* Check format version */
    587     fread( &version, 4, 1, file );
    588     if( 0 == version )
    589     {
    590         return fastResumeLoadOld( tor, uncheckedPieces, file );
    591     }
    592     if( 1 != version )
    593     {
    594         tr_inf( "Resume file has version %d, not supported", version );
    595         fclose( file );
    596         return ret;
    597     }
    598 
    599     /* read each block of data */
    600     while( 1 == fread( &id, 1, 1, file ) && 1 == fread( &len, 4, 1, file ) )
    601     {
    602         if( fieldsToLoad & internalIdToPublicBitfield( id ) ) switch( id )
    603         {
    604             case FR_ID_PROGRESS:
    605                 /* read progress data */
    606                 if( (uint32_t)FR_PROGRESS_LEN( tor ) == len )
    607                 {
    608                     const int rret = fastResumeLoadProgress( tor, uncheckedPieces, file );
    609 
    610                     if( rret && ( feof(file) || ferror(file) ) )
    611                     {
    612                         fclose( file );
    613                         return ret;
    614                     }
    615 
    616                     ret |= TR_FR_PROGRESS;
    617                     continue;
    618                 }
    619                 break;
    620 
    621             case FR_ID_PRIORITY:
    622 
    623                 /* read priority data */
    624                 if( len == (uint32_t)(2 * tor->info.fileCount) )
    625                 {
    626                     const int rret = loadPriorities( tor, file );
    627 
    628                     if( rret && ( feof(file) || ferror(file) ) )
    629                     {
    630                         fclose( file );
    631                         return ret;
    632                     }
    633 
    634                     ret |= TR_FR_PRIORITY;
    635                     continue;
    636                 }
    637                 break;
    638 
    639             case FR_ID_SPEED:
    640                 /*  read speed data */
    641                 if( len == FR_SPEED_LEN )
    642                 {
    643                     const int rret = loadSpeeds( tor, file );
    644 
    645                     if( rret && ( feof(file) || ferror(file) ) )
    646                     {
    647                         fclose( file );
    648                         return ret;
    649                     }
    650 
    651                     ret |= TR_FR_SPEEDLIMIT;
    652                     continue;
    653                 }
    654                 break;
    655 
    656             case FR_ID_DESTINATION:
    657                 {
    658                     const int rret = loadDestination( tor, file, destination, argIsFallback );
    659 
    660                     if( rret && ( feof(file) || ferror(file) ) )
    661                     {
    662                         fclose( file );
    663                         return ret;
    664                     }
    665 
    666                     ret |= TR_FR_DESTINATION;
    667                     continue;
    668                 }
    669                 break;
    670            
    671             case FR_ID_RUN:
    672                 {
    673                     char ch;
    674                     if( fread( &ch, 1, 1, file ) != 1 )
    675                     {
    676                         fclose( file );
    677                         return ret;
    678                     }
    679                     tor->isRunning = ch=='t';
    680                     ret |= TR_FR_RUN;
    681                     continue;
    682                 }
    683            
    684             case FR_ID_PEX:
    685                 {
    686                     char ch;
    687                     if( fread( &ch, 1, 1, file ) != 1 )
    688                     {
    689                         fclose( file );
    690                         return ret;
    691                     }
    692                     tor->pexDisabled = ch!='t';
    693                     ret |= TR_FR_PEX;
    694                     continue;
    695                 }
    696 
    697             case FR_ID_DOWNLOADED:
    698                 /* read download total */
    699                 if( 8 == len)
    700                 {
    701                     if( 1 != fread( &tor->downloadedPrev, 8, 1, file ) )
    702                     {
    703                         fclose( file );
    704                         return ret;
    705                     }
    706                     tor->downloadedCur = 0;
    707                     ret |= TR_FR_DOWNLOADED;
    708                     continue;
    709                 }
    710                 break;
    711 
    712             case FR_ID_UPLOADED:
    713                 /* read upload total */
    714                 if( 8 == len)
    715                 {
    716                     if( 1 != fread( &tor->uploadedPrev, 8, 1, file ) )
    717                     {
    718                         fclose( file );
    719                         return ret;
    720                     }
    721                     tor->uploadedCur = 0;
    722                     ret |= TR_FR_UPLOADED;
    723                     continue;
    724                 }
    725                 break;
    726 
    727             case FR_ID_CORRUPT:
    728                 /* read upload total */
    729                 if( 8 == len )
    730                 {
    731                     if( 1 != fread( &tor->corruptPrev, 8, 1, file ) )
    732                     {
    733                         fclose( file );
    734                         return ret;
    735                     }
    736                     tor->corruptCur = 0;
    737                     ret |= TR_FR_CORRUPT;
    738                     continue;
    739                 }
    740                 break;
    741 
    742             case FR_ID_PEERS_OLD:
    743                 if( !tor->info.isPrivate )
    744                 {
    745                     uint8_t * buf = malloc( len );
    746                     if( 1 != fread( buf, len, 1, file ) )
    747                     {
    748                         free( buf );
    749                         fclose( file );
    750                         return ret;
    751                     }
    752 
    753                     tr_peerMgrAddPeers( tor->handle->peerMgr,
    754                                         tor->info.hash,
    755                                         TR_PEER_FROM_CACHE,
    756                                         buf, len / 6 );
    757 
    758                     tr_dbg( "found %i peers in resume file", len/6 );
    759                     free( buf );
    760                     ret |= TR_FR_PEERS;
    761                 }
    762 
    763             case FR_ID_PEERS:
    764                 if( !tor->info.isPrivate )
    765                 {
    766                     const int count = len / sizeof(tr_pex);
    767                     tr_pex * pex = tr_new0( tr_pex, count );
    768                     if( 1 != fread( pex, sizeof(tr_pex), count, file ) )
    769                     {
    770                         free( pex );
    771                         fclose( file );
    772                         return ret;
    773                     }
    774 
    775                     tr_peerMgrAddPex( tor->handle->peerMgr,
    776                                       tor->info.hash,
    777                                       TR_PEER_FROM_CACHE,
    778                                       pex, count );
    779 
    780                     tr_dbg( "found %i peers in resume file", len/6 );
    781                     free( pex );
    782                     ret |= TR_FR_PEERS;
    783                 }
    784                 continue;
    785 
    786             default:
    787                 break;
    788         }
    789 
    790         /* if we didn't read the data, seek past it */
    791         tr_dbg( "Skipping resume data type %02x, %u bytes", id, len );
    792         fseek( file, len, SEEK_CUR );
    793     }
    794 
    795     fclose( file );
     652
     653        tr_free( buf );
     654    }
     655
    796656    return ret;
    797657}
Note: See TracChangeset for help on using the changeset viewer.