Changeset 11888


Ignore:
Timestamp:
Feb 13, 2011, 4:14:31 PM (11 years ago)
Author:
jordan
Message:

(trunk libT) #4016 "blocklists don't handle overlapping/unsorted rules" -- fixed.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/blocklist.c

    r11882 r11888  
    1212
    1313#include <stdio.h>
    14 #include <stdlib.h> /* free() */
     14#include <stdlib.h> /* qsort(), free() */
    1515#include <string.h>
    1616
     
    307307}
    308308
     309static int
     310compareAddressRangesByFirstAddress( const void * va, const void * vb )
     311{
     312    const struct tr_ipv4_range * a = va;
     313    const struct tr_ipv4_range * b = vb;
     314    if( a->begin != b->begin )
     315        return a->begin < b->begin ? -1 : 1;
     316    return 0;
     317}
     318
    309319int
    310 _tr_blocklistSetContent( tr_blocklist * b,
    311                          const char *   filename )
     320_tr_blocklistSetContent( tr_blocklist * b, const char * filename )
    312321{
    313322    FILE * in;
    314323    FILE * out;
    315324    int inCount = 0;
    316     int outCount = 0;
    317325    char line[2048];
    318326    const char * err_fmt = _( "Couldn't read \"%1$s\": %2$s" );
     327    struct tr_ipv4_range * ranges = NULL;
     328    size_t ranges_alloc = 0;
     329    size_t ranges_count = 0;
    319330
    320331    if( !filename )
     
    341352    }
    342353
     354    /* load the rules into memory */
    343355    while( fgets( line, sizeof( line ), in ) != NULL )
    344356    {
     
    359371        }
    360372
    361         if( fwrite( &range, sizeof( struct tr_ipv4_range ), 1, out ) != 1 )
     373        if( ranges_alloc == ranges_count )
    362374        {
    363             tr_err( _( "Couldn't save file \"%1$s\": %2$s" ), b->filename,
    364                    tr_strerror( errno ) );
    365             break;
     375            ranges_alloc += 4096; /* arbitrary */
     376            ranges = tr_renew( struct tr_ipv4_range, ranges, ranges_alloc );
    366377        }
    367378
    368         ++outCount;
    369     }
    370 
    371     {
     379        ranges[ranges_count++] = range;
     380    }
     381
     382    if( ranges_count > 0 ) /* sort and merge */
     383    {
     384        struct tr_ipv4_range * r;
     385        struct tr_ipv4_range * keep = ranges;
     386        const struct tr_ipv4_range * end;
     387
     388        /* sort */
     389        qsort( ranges, ranges_count, sizeof( struct tr_ipv4_range ),
     390               compareAddressRangesByFirstAddress );
     391
     392        /* merge */
     393        for( r=ranges+1, end=ranges+ranges_count; r!=end; ++r ) {
     394            if( keep->end < r->begin )
     395                *++keep = *r;
     396            else if( keep->end < r->end )
     397                keep->end = r->end;
     398        }
     399
     400        ranges_count = keep + 1 - ranges;
     401
     402#ifndef NDEBUG
     403        /* sanity checks: make sure the rules are sorted
     404         * in ascending order and don't overlap */
     405        {
     406            size_t i;
     407
     408            for( i=0; i<ranges_count; ++i )
     409                assert( ranges[i].begin <= ranges[i].end );
     410
     411            for( i=1; i<ranges_count; ++i )
     412                assert( ranges[i-1].end < ranges[i].begin );
     413        }
     414#endif
     415    }
     416
     417    if( fwrite( ranges, sizeof( struct tr_ipv4_range ), ranges_count, out ) != ranges_count )
     418        tr_err( _( "Couldn't save file \"%1$s\": %2$s" ), b->filename, tr_strerror( errno ) );
     419    else {
    372420        char * base = tr_basename( b->filename );
    373         tr_inf( _( "Blocklist \"%s\" updated with %d entries" ), base, outCount );
     421        tr_inf( _( "Blocklist \"%s\" updated with %zu entries" ), base, ranges_count );
    374422        tr_free( base );
    375423    }
    376424
     425    tr_free( ranges );
    377426    fclose( out );
    378427    fclose( in );
     
    380429    blocklistLoad( b );
    381430
    382     return outCount;
    383 }
    384 
     431    return ranges_count;
     432}
Note: See TracChangeset for help on using the changeset viewer.