Changeset 12521


Ignore:
Timestamp:
Jun 26, 2011, 5:05:17 PM (10 years ago)
Author:
jordan
Message:

(trunk libT) #4101 "RPC method blocklist-update is broken" -- use lower-level zlib API calls so that we can skip writing a temporary gzipped file to disk

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/rpcimpl.c

    r12494 r12521  
    11371137    {
    11381138        int fd;
     1139        int err;
     1140        char * filename;
     1141        z_stream stream;
    11391142        const char * configDir = tr_sessionGetConfigDir( session );
    1140         char * filename = tr_buildPath( configDir, "blocklist.tmp", NULL );
    1141 
    1142         errno = 0;
    1143 
     1143        const size_t buflen = 1024 * 128; /* 128 KiB buffer */
     1144        uint8_t * buf = tr_valloc( buflen );
     1145
     1146        /* this is an odd Magic Number required by zlib to enable gz support.
     1147           See zlib's inflateInit2() documentation for a full description */
     1148        const int windowBits = 15 + 32;
     1149
     1150        stream.zalloc = (alloc_func) Z_NULL;
     1151        stream.zfree = (free_func) Z_NULL;
     1152        stream.opaque = (voidpf) Z_NULL;
     1153        stream.next_in = (void*) response;
     1154        stream.avail_in = response_byte_count;
     1155        inflateInit2( &stream, windowBits );
     1156
     1157        filename = tr_buildPath( configDir, "blocklist.tmp", NULL );
    11441158        fd = tr_open_file_for_writing( filename );
    11451159        if( fd < 0 )
    11461160            tr_snprintf( result, sizeof( result ), _( "Couldn't save file \"%1$s\": %2$s" ), filename, tr_strerror( errno ) );
    11471161
    1148         if( !errno ) {
    1149             const char * buf = response;
    1150             size_t buflen = response_byte_count;
    1151             while( buflen > 0 ) {
    1152                 int n = write( fd, buf, buflen );
    1153                 if( n < 0 ) {
     1162        for( ;; )
     1163        {
     1164            stream.next_out = (void*) buf;
     1165            stream.avail_out = buflen;
     1166            err = inflate( &stream, Z_NO_FLUSH );
     1167
     1168            if( stream.avail_out < buflen ) {
     1169                const int e = write( fd, buf, buflen - stream.avail_out );
     1170                if( e < 0 ) {
    11541171                    tr_snprintf( result, sizeof( result ), _( "Couldn't save file \"%1$s\": %2$s" ), filename, tr_strerror( errno ) );
    11551172                    break;
    11561173                }
    1157                 buf += n;
    1158                 buflen -= n;
    11591174            }
    1160             tr_close_file( fd );
    1161         }
    1162 
    1163 #ifdef HAVE_ZLIB
    1164         if( !errno )
    1165         {
    1166             char * filename2 = tr_buildPath( configDir, "blocklist.txt.tmp", NULL );
    1167             fd = tr_open_file_for_writing( filename2 );
    1168             if( fd < 0 )
    1169                 tr_snprintf( result, sizeof( result ), _( "Couldn't save file \"%1$s\": %2$s" ), filename2, tr_strerror( errno ) );
    1170             else {
    1171                 gzFile gzf = gzopen( filename, "r" );
    1172                 if( gzf ) {
    1173                     const size_t buflen = 1024 * 128; /* 128 KiB buffer */
    1174                     uint8_t * buf = tr_valloc( buflen );
    1175                     for( ;; ) {
    1176                         int n = gzread( gzf, buf, buflen );
    1177                         if( n < 0 ) /* error */
    1178                             tr_snprintf( result, sizeof( result ), _( "Error reading \"%1$s\": %2$s" ), filename, gzerror( gzf, NULL ) );
    1179                         if( n < 1 ) /* error or EOF */
    1180                             break;
    1181                         if( write( fd, buf, n ) < 0 )
    1182                             tr_snprintf( result, sizeof( result ), _( "Couldn't save file \"%1$s\": %2$s" ), filename2, tr_strerror( errno ) );
    1183                     }
    1184                     tr_free( buf );
    1185                     gzclose( gzf );
    1186                 } else {
    1187                     tr_snprintf( result, sizeof( result ), _( "Error opening \"%1$s\": %2$s" ), filename, tr_strerror( errno ) );
    1188                 }
    1189                 tr_close_file( fd );
     1175
     1176            if( err != Z_OK ) {
     1177                if( ( err != Z_STREAM_END ) && ( err != Z_DATA_ERROR ) )
     1178                    tr_snprintf( result, sizeof( result ), _( "Error uncompressing blocklist: %s (%d)" ), zError( err ), err );
     1179                break;
    11901180            }
    1191 
    1192             if( *result )
    1193                 tr_err( "%s", result );
    1194 
    1195             unlink( filename );
    1196             tr_free( filename );
    1197             filename = filename2;
    1198         }
    1199 #endif
    1200 
    1201         if( !errno ) {
     1181        }
     1182
     1183        inflateEnd( &stream );
     1184
     1185        if( err == Z_DATA_ERROR ) /* couldn't inflate it... it's probably already uncompressed */
     1186            if( write( fd, response, response_byte_count ) < 0 )
     1187                tr_snprintf( result, sizeof( result ), _( "Couldn't save file \"%1$s\": %2$s" ), filename, tr_strerror( errno ) );
     1188
     1189        if( *result )
     1190            tr_err( "%s", result );
     1191        else {
    12021192            /* feed it to the session and give the client a response */
    12031193            const int rule_count = tr_blocklistSetContent( session, filename );
     
    12081198        unlink( filename );
    12091199        tr_free( filename );
     1200        tr_free( buf );
    12101201    }
    12111202
Note: See TracChangeset for help on using the changeset viewer.