diff --git a/libtransmission/choking.c b/libtransmission/choking.c index a46256e51..e5a27b12b 100644 --- a/libtransmission/choking.c +++ b/libtransmission/choking.c @@ -29,11 +29,6 @@ # define lrintf(a) ((int)(0.5+(a))) #endif -/* We may try to allocate and free tables of size 0. - Quick and dirty way to handle it... */ -#define malloc tr_malloc -#define free tr_free - struct tr_choking_s { tr_lock_t lock; @@ -45,7 +40,7 @@ tr_choking_t * tr_chokingInit( tr_handle_t * h ) { tr_choking_t * c; - c = calloc( 1, sizeof( tr_choking_t ) ); + c = tr_new0( tr_choking_t, 1 ); c->h = h; c->slots = 4242; tr_lockInit( &c->lock ); @@ -92,14 +87,13 @@ static inline void sortPeers( tr_peer_t ** all, int allCount, /* Randomly shuffle non-uploaders, so they are treated equally */ if( *zeroCount && ( shuffle = tr_rand( *zeroCount ) ) ) { - tr_peer_t ** bak; - bak = malloc( shuffle * sizeof( tr_peer_t * ) ); + tr_peer_t ** bak = tr_new( tr_peer_t*, shuffle );; memcpy( bak, zero, shuffle * sizeof( tr_peer_t * ) ); memmove( zero, &zero[shuffle], ( *zeroCount - shuffle ) * sizeof( tr_peer_t * ) ); memcpy( &zero[*zeroCount - shuffle], bak, shuffle * sizeof( tr_peer_t * ) ); - free( bak ); + tr_free( bak ); } /* Sort uploaders by download rate */ @@ -149,8 +143,8 @@ void tr_chokingPulse( tr_choking_t * c ) peersTotalCount += tor->peerCount; } - canChoke = malloc( peersTotalCount * sizeof( tr_peer_t * ) ); - canUnchoke = malloc( peersTotalCount * sizeof( tr_peer_t * ) ); + canChoke = tr_new( tr_peer_t*, peersTotalCount ); + canUnchoke = tr_new( tr_peer_t*, peersTotalCount ); canChokeCount = 0; canUnchokeCount = 0; unchoked = 0; @@ -212,10 +206,10 @@ void tr_chokingPulse( tr_choking_t * c ) } } - canChokeZero = malloc( canChokeCount * sizeof( tr_peer_t * ) ); - canChokeNonZero = malloc( canChokeCount * sizeof( tr_peer_t * ) ); - canUnchokeZero = malloc( canUnchokeCount * sizeof( tr_peer_t * ) ); - canUnchokeNonZero = malloc( canUnchokeCount * sizeof( tr_peer_t * ) ); + canChokeZero = tr_new( tr_peer_t*, canChokeCount ); + canChokeNonZero = tr_new( tr_peer_t*, canChokeCount ); + canUnchokeZero = tr_new( tr_peer_t*, canUnchokeCount ); + canUnchokeNonZero = tr_new( tr_peer_t*, canUnchokeCount ); sortPeersDescending( canChoke, canChokeCount, canChokeZero, &canChokeZeroCount, @@ -224,8 +218,8 @@ void tr_chokingPulse( tr_choking_t * c ) canUnchokeZero, &canUnchokeZeroCount, canUnchokeNonZero, &canUnchokeNonZeroCount); - free( canChoke ); - free( canUnchoke ); + tr_free( canChoke ); + tr_free( canUnchoke ); if( mustOptimistic ) { @@ -303,10 +297,10 @@ void tr_chokingPulse( tr_choking_t * c ) tr_peerUnchoke( canUnchokeZero[--canUnchokeZeroCount] ); } - free( canChokeZero ); - free( canChokeNonZero ); - free( canUnchokeZero ); - free( canUnchokeNonZero ); + tr_free( canChokeZero ); + tr_free( canChokeNonZero ); + tr_free( canUnchokeZero ); + tr_free( canUnchokeNonZero ); /* Unlock all torrents */ for( tor = c->h->torrentList; tor; tor = tor->next ) @@ -318,5 +312,5 @@ void tr_chokingPulse( tr_choking_t * c ) void tr_chokingClose( tr_choking_t * c ) { tr_lockClose( &c->lock ); - free( c ); + tr_free( c ); } diff --git a/libtransmission/completion.c b/libtransmission/completion.c index 15253b9bb..61913e53e 100644 --- a/libtransmission/completion.c +++ b/libtransmission/completion.c @@ -51,13 +51,13 @@ tr_completion_t * tr_cpInit( tr_torrent_t * tor ) { tr_completion_t * cp; - cp = malloc( sizeof( tr_completion_t ) ); + cp = tr_new( tr_completion_t, 1 ); cp->tor = tor; cp->blockBitfield = tr_bitfieldNew( tor->blockCount ); - cp->blockDownloaders = malloc( tor->blockCount ); + cp->blockDownloaders = tr_new( uint8_t, tor->blockCount ); cp->pieceBitfield = tr_bitfieldNew( tor->info.pieceCount ); - cp->missingBlocks = malloc( tor->info.pieceCount * sizeof( int ) ); - cp->completeBlocks = malloc( tor->info.pieceCount * sizeof( int ) ); + cp->missingBlocks = tr_new( int, tor->info.pieceCount ); + cp->completeBlocks = tr_new( int, tor->info.pieceCount ); cp->nBlocksInLastPiece = tr_pieceCountBlocks ( tor->info.pieceCount - 1 ); cp->nBlocksInPiece = tor->info.pieceCount==1 ? cp->nBlocksInLastPiece @@ -70,12 +70,12 @@ tr_completion_t * tr_cpInit( tr_torrent_t * tor ) void tr_cpClose( tr_completion_t * cp ) { - tr_bitfieldFree( cp->blockBitfield ); - free( cp->blockDownloaders ); + tr_free( cp->completeBlocks ); + tr_free( cp->missingBlocks ); tr_bitfieldFree( cp->pieceBitfield ); - free( cp->missingBlocks ); - free( cp->completeBlocks ); - free( cp ); + tr_free( cp->blockDownloaders ); + tr_bitfieldFree( cp->blockBitfield ); + tr_free( cp ); } void tr_cpReset( tr_completion_t * cp ) @@ -263,7 +263,7 @@ int tr_cpMostMissingBlockInPiece( const tr_completion_t * cp, count = tr_cpCountBlocks( cp, piece ); end = start + count; - pool = malloc( count * sizeof( int ) ); + pool = tr_new( int, count ); poolSize = 0; min = 255; @@ -294,7 +294,7 @@ int tr_cpMostMissingBlockInPiece( const tr_completion_t * cp, ret = -1; } - free( pool ); + tr_free( pool ); return ret; } diff --git a/libtransmission/metainfo.c b/libtransmission/metainfo.c index 627bc21bb..aedba73fc 100644 --- a/libtransmission/metainfo.c +++ b/libtransmission/metainfo.c @@ -29,7 +29,7 @@ /*********************************************************************** * Local prototypes **********************************************************************/ -static int realparse( tr_info_t * inf, uint8_t * buf, size_t len ); +static int realparse( tr_info_t * inf, const uint8_t * buf, size_t len ); static void savedname( char * name, size_t len, const char * hash, const char * tag ); static uint8_t * readtorrent( const char * path, size_t * len ); @@ -59,13 +59,13 @@ tr_metainfoParseFile( tr_info_t * inf, const char * tag, buf = readtorrent( path, &size ); if( NULL == buf ) { - return 1; + return TR_EINVALID; } if( realparse( inf, buf, size ) ) { free( buf ); - return 1; + return TR_EINVALID; } if( save ) @@ -73,7 +73,7 @@ tr_metainfoParseFile( tr_info_t * inf, const char * tag, if( savetorrent( inf->hashString, tag, buf, size ) ) { free( buf ); - return 1; + return TR_EINVALID; } savedname( inf->torrent, sizeof inf->torrent, inf->hashString, tag ); } @@ -84,28 +84,28 @@ tr_metainfoParseFile( tr_info_t * inf, const char * tag, free( buf ); - return 0; + return TR_OK; } int tr_metainfoParseData( tr_info_t * inf, const char * tag, - uint8_t * data, size_t size, int save ) + const uint8_t * data, size_t size, int save ) { if( realparse( inf, data, size ) ) { - return 1; + return TR_EINVALID; } if( save ) { if( savetorrent( inf->hashString, tag, data, size ) ) { - return 1; + return TR_EINVALID; } savedname( inf->torrent, sizeof inf->torrent, inf->hashString, tag ); } - return 0; + return TR_OK; } int @@ -132,13 +132,13 @@ tr_metainfoParseHash( tr_info_t * inf, const char * tag, const char * hash ) buf = readtorrent( inf->torrent, &size ); if( NULL == buf ) { - return 1; + return TR_EINVALID; } if( realparse( inf, buf, size ) ) { free( buf ); - return 1; + return TR_EINVALID; } /* save a new tagged copy of the old untagged torrent */ @@ -147,18 +147,18 @@ tr_metainfoParseHash( tr_info_t * inf, const char * tag, const char * hash ) if( savetorrent( hash, tag, buf, size ) ) { free( buf ); - return 1; + return TR_EINVALID; } savedname( inf->torrent, sizeof inf->torrent, hash, tag ); } free( buf ); - return 0; + return TR_OK; } int -realparse( tr_info_t * inf, uint8_t * buf, size_t size ) +realparse( tr_info_t * inf, const uint8_t * buf, size_t size ) { benc_val_t meta, * beInfo, * val, * val2; int i; @@ -167,7 +167,7 @@ realparse( tr_info_t * inf, uint8_t * buf, size_t size ) if( tr_bencLoad( buf, size, &meta, NULL ) ) { tr_err( "Error while parsing bencoded data" ); - return 1; + return TR_EINVALID; } /* Get info hash */ @@ -176,7 +176,7 @@ realparse( tr_info_t * inf, uint8_t * buf, size_t size ) { tr_err( "%s \"info\" dictionary", ( beInfo ? "Invalid" : "Missing" ) ); tr_bencFree( &meta ); - return 1; + return TR_EINVALID; } SHA1( (uint8_t *) beInfo->begin, (long) beInfo->end - (long) beInfo->begin, inf->hash ); @@ -273,12 +273,12 @@ realparse( tr_info_t * inf, uint8_t * buf, size_t size ) } tr_bencFree( &meta ); - return 0; + return TR_OK; fail: tr_metainfoFree( inf ); tr_bencFree( &meta ); - return 1; + return TR_EINVALID; } void tr_metainfoFree( tr_info_t * inf ) @@ -310,13 +310,13 @@ static int getfile( char * buf, int size, if( TYPE_LIST != name->type ) { - return 1; + return TR_EINVALID; } list = calloc( name->val.l.count, sizeof( list[0] ) ); if( NULL == list ) { - return 1; + return TR_EINVALID; } for( ii = jj = 0; name->val.l.count > ii; ii++ ) @@ -342,7 +342,7 @@ static int getfile( char * buf, int size, if( 0 == jj ) { - return 1; + return TR_EINVALID; } strcatUTF8( buf, size, prefix, 0 ); @@ -353,7 +353,7 @@ static int getfile( char * buf, int size, } free( list ); - return 0; + return TR_OK; } static int getannounce( tr_info_t * inf, benc_val_t * meta ) @@ -457,14 +457,14 @@ static int getannounce( tr_info_t * inf, benc_val_t * meta ) if( NULL == val || TYPE_STR != val->type ) { tr_err( "No \"announce\" entry" ); - return 1; + return TR_EINVALID; } if( tr_httpParseUrl( val->val.s.s, val->val.s.i, &address, &port, &announce ) ) { tr_err( "Invalid announce URL (%s)", val->val.s.s ); - return 1; + return TR_EINVALID; } sublist = calloc( 1, sizeof( sublist[0] ) ); @@ -478,7 +478,7 @@ static int getannounce( tr_info_t * inf, benc_val_t * meta ) inf->trackerTiers = 1; } - return 0; + return TR_OK; } static char * announceToScrape( const char * announce ) @@ -614,18 +614,18 @@ int savetorrent( const char * hash, const char * tag, if( !file ) { tr_err( "Could not open file (%s) (%s)", path, strerror( errno ) ); - return 1; + return TR_EINVALID; } fseek( file, 0, SEEK_SET ); if( fwrite( buf, 1, buflen, file ) != buflen ) { tr_err( "Could not write file (%s) (%s)", path, strerror( errno ) ); fclose( file ); - return 1; + return TR_EINVALID; } fclose( file ); - return 0; + return TR_OK; } int @@ -638,14 +638,14 @@ parseFiles( tr_info_t * inf, benc_val_t * name, if( NULL == name || TYPE_STR != name->type ) { tr_err( "%s \"name\" string", ( name ? "Invalid" : "Missing" ) ); - return 1; + return TR_EINVALID; } strcatUTF8( inf->name, sizeof( inf->name ), name->val.s.s, 1 ); if( '\0' == inf->name[0] ) { tr_err( "Invalid \"name\" string" ); - return 1; + return TR_EINVALID; } inf->totalSize = 0; @@ -658,7 +658,7 @@ parseFiles( tr_info_t * inf, benc_val_t * name, if( NULL == inf->files ) { - return 1; + return TR_EINVALID; } for( ii = 0; files->val.l.count > ii; ii++ ) @@ -670,14 +670,14 @@ parseFiles( tr_info_t * inf, benc_val_t * name, { tr_err( "%s \"path\" entry", ( path ? "Invalid" : "Missing" ) ); - return 1; + return TR_EINVALID; } length = tr_bencDictFind( item, "length" ); if( NULL == length || TYPE_INT != length->type ) { tr_err( "%s \"length\" entry", ( length ? "Invalid" : "Missing" ) ); - return 1; + return TR_EINVALID; } inf->files[ii].length = length->val.i; inf->totalSize += length->val.i; @@ -692,7 +692,7 @@ parseFiles( tr_info_t * inf, benc_val_t * name, if( NULL == inf->files ) { - return 1; + return TR_EINVALID; } strcatUTF8( inf->files[0].name, sizeof( inf->files[0].name ), @@ -708,7 +708,7 @@ parseFiles( tr_info_t * inf, benc_val_t * name, ( length ? "invalid" : "missing" ) ); } - return 0; + return TR_OK; } /*********************************************************************** diff --git a/libtransmission/metainfo.h b/libtransmission/metainfo.h index b33dff63c..120d27e51 100644 --- a/libtransmission/metainfo.h +++ b/libtransmission/metainfo.h @@ -30,7 +30,7 @@ int tr_metainfoParseFile( tr_info_t *, const char * tag, const char * path, int save ); int tr_metainfoParseData( tr_info_t *, const char * tag, - uint8_t * data, size_t size, int save ); + const uint8_t * data, size_t size, int save ); int tr_metainfoParseHash( tr_info_t *, const char * tag, const char * hash ); void tr_metainfoFree( tr_info_t * inf ); void tr_metainfoRemoveSaved( const char * hashString, const char * tag ); diff --git a/libtransmission/torrent.c b/libtransmission/torrent.c index 58f1300eb..faa626219 100644 --- a/libtransmission/torrent.c +++ b/libtransmission/torrent.c @@ -276,16 +276,24 @@ infoCanAdd( const tr_handle_t * h, } int -tr_torrentCanAdd( const tr_handle_t * h, - const char * destination, - const char * path ) +tr_torrentParse( const tr_handle_t * h, + const char * path, + const char * destination, + tr_info_t * setme_info, + int * setme_canAdd ) { - tr_info_t info; + int ret; + tr_info_t tmp; - if( tr_metainfoParseFile( &info, h->tag, path, FALSE ) ) - return TR_EINVALID; + if( setme_info == NULL ) + setme_info = &tmp; - return infoCanAdd( h, destination, &info ); + ret = tr_metainfoParseFile( setme_info, h->tag, path, FALSE ); + + if( setme_canAdd ) + *setme_canAdd = ret ? ret : infoCanAdd( h, destination, setme_info ); + + return ret; } tr_torrent_t * @@ -296,10 +304,13 @@ tr_torrentInit( tr_handle_t * h, int * error ) { int val; + int err = 0; tr_torrent_t * tor = NULL; - if(( val = tr_torrentCanAdd( h, destination, path ) )) + if(( val = tr_torrentParse( h, destination, path, NULL, &err ))) *error = val; + else if( err ) + *error = err; else if(!(( tor = tr_new0( tr_torrent_t, 1 )))) *error = TR_EOTHER; else { @@ -311,30 +322,42 @@ tr_torrentInit( tr_handle_t * h, } static int -tr_torrentCanAddHash( tr_handle_t * h, - const char * destination, - const char * hashStr ) +tr_torrentParseHash( const tr_handle_t * h, + const char * hashStr, + const char * destination, + tr_info_t * setme_info, + int * setme_canAdd ) { - tr_info_t info; + int ret; + tr_info_t tmp; - if( tr_metainfoParseHash( &info, h->tag, hashStr ) ) - return TR_EINVALID; + if( setme_info == NULL ) + setme_info = &tmp; - return infoCanAdd( h, destination, &info ); + ret = tr_metainfoParseHash( setme_info, h->tag, hashStr ); + + if( setme_canAdd ) + *setme_canAdd = ret ? ret : infoCanAdd( h, destination, setme_info ); + + return ret; } + tr_torrent_t * -tr_torrentInitSaved( tr_handle_t * h, - const char * hashStr, - const char * destination, - int flags, - int * error ) +tr_torrentInitSaved( tr_handle_t * h, + const char * hashStr, + const char * destination, + int flags, + int * error ) { int val; + int err = 0; tr_torrent_t * tor = NULL; - if(( val = tr_torrentCanAddHash( h, destination, hashStr ) )) + if(( val = tr_torrentParseHash( h, hashStr, destination, NULL, &err ))) *error = val; + else if( err ) + *error = err; else if(!(( tor = tr_new0( tr_torrent_t, 1 )))) *error = TR_EOTHER; else { @@ -346,32 +369,43 @@ tr_torrentInitSaved( tr_handle_t * h, } static int -tr_torrentCanAddData( tr_handle_t * h, - const char * destination, - uint8_t * data, - size_t size ) +tr_torrentParseData( const tr_handle_t * h, + const uint8_t * data, + size_t size, + const char * destination, + tr_info_t * setme_info, + int * setme_canAdd ) { - tr_info_t info; + int ret; + tr_info_t tmp; - if( tr_metainfoParseData( &info, h->tag, data, size, FALSE ) ) - return TR_EINVALID; + if( setme_info == NULL ) + setme_info = &tmp; - return infoCanAdd( h, destination, &info ); + ret = tr_metainfoParseData( setme_info, h->tag, data, size, FALSE ); + + if( setme_canAdd ) + *setme_canAdd = ret ? ret : infoCanAdd( h, destination, setme_info ); + + return ret; } tr_torrent_t * -tr_torrentInitData( tr_handle_t * h, - uint8_t * data, - size_t size, - const char * destination, - int flags, - int * error ) +tr_torrentInitData( tr_handle_t * h, + const uint8_t * data, + size_t size, + const char * destination, + int flags, + int * error ) { int val; + int err = 0; tr_torrent_t * tor = NULL; - if(( val = tr_torrentCanAddData( h, destination, data, size ) )) + if(( val = tr_torrentParseData( h, data, size, destination, NULL, &err ) )) *error = val; + else if( err ) + *error = err; else if(!(( tor = tr_new0( tr_torrent_t, 1 )))) *error = TR_EOTHER; else { diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 5922160e4..95ef26eb8 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -263,19 +263,34 @@ void tr_close( tr_handle_t * ); #define TR_EUNSUPPORTED 2 #define TR_EDUPLICATE 3 #define TR_EOTHER 666 -tr_torrent_t * tr_torrentInit( tr_handle_t *, - const char * path, - const char * destination, - int flags, int * error ); +tr_torrent_t * tr_torrentInit( tr_handle_t * handle, + const char * metainfo_filename, + const char * destination, + int flags, + int * setme_error ); + +typedef struct tr_info_s tr_info_t; /** - * Checks to see if the specified torrent file could be - * successfully added to Transmission. - * returns TR_OK, TR_EDUPLICATE, TR_ERROR_IO_DUP_DOWNLOAD, or TR_EINVALID. + * Parses the specified metainfo file. + * + * Returns TR_OK or TR_INVALID based on whether or not the + * metainfo file is successfully parsed. + * + * If parsing succeeded and "setme_info" is non-NULL, + * it will be populated with the file's information. + * + * If "setme_canAdd" is non-NULL, it will be set to TR_OK, + * TR_EDUPLICATE, TR_ERROR_IO_DUP_DOWNLOAD, or TR_EINVALID. + * + * "destination" is used for the canAdd tests, so it can + * be NULL if "setme_canAdd" is too. */ -int tr_torrentCanAdd( const tr_handle_t * handle, - const char * destination, - const char * path ); +int tr_torrentParse( const tr_handle_t * handle, + const char * metainfo_filename, + const char * destination, + tr_info_t * setme_info, + int * setme_canAdd ); /*********************************************************************** * tr_torrentInitData @@ -284,7 +299,7 @@ int tr_torrentCanAdd( const tr_handle_t * handle, * instead of the filename. **********************************************************************/ tr_torrent_t * tr_torrentInitData( tr_handle_t *, - uint8_t * data, size_t size, + const uint8_t * data, size_t size, const char * destination, int flags, int * error ); @@ -314,7 +329,6 @@ void tr_torrentDisablePex( tr_torrent_t *, int disable ); *********************************************************************** * Return torrent metainfo. **********************************************************************/ -typedef struct tr_info_s tr_info_t; tr_info_t * tr_torrentInfo( tr_torrent_t * ); /***********************************************************************