1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-26 01:27:28 +00:00
transmission/libtransmission/torrent-ctor.c
Jordan Lee 879a2afcbd Update the copyright year in the source code comments.
The Berne Convention says that the copyright year is moot, so instead of adding another year to each file as in previous years, I've removed the year altogether from the source code comments in libtransmission, gtk, qt, utils, daemon, and cli.

Juliusz's copyright notice in tr-dht and Johannes' copyright notice in tr-lpd have been left alone; it didn't seem appropriate to modify them.
2011-01-19 13:48:47 +00:00

478 lines
11 KiB
C

/*
* This file Copyright (C) Mnemosyne LLC
*
* This file is licensed by the GPL version 2. Works owned by the
* Transmission project are granted a special exemption to clause 2(b)
* so that the bulk of its code can remain under the MIT license.
* This exemption does not extend to derived works not owned by
* the Transmission project.
*
* $Id$
*/
#include <errno.h> /* EINVAL */
#include "transmission.h"
#include "bencode.h"
#include "magnet.h"
#include "platform.h"
#include "session.h" /* tr_sessionFindTorrentFile() */
#include "torrent.h" /* tr_ctorGetSave() */
#include "utils.h" /* tr_new0 */
struct optional_args
{
tr_bool isSet_paused;
tr_bool isSet_connected;
tr_bool isSet_downloadDir;
tr_bool isPaused;
uint16_t peerLimit;
char * downloadDir;
};
/** Opaque class used when instantiating torrents.
* @ingroup tr_ctor */
struct tr_ctor
{
const tr_session * session;
tr_bool saveInOurTorrentsDir;
tr_bool doDelete;
tr_priority_t bandwidthPriority;
tr_bool isSet_metainfo;
tr_bool isSet_delete;
tr_benc metainfo;
char * sourceFile;
struct optional_args optionalArgs[2];
char * incompleteDir;
tr_file_index_t * want;
tr_file_index_t wantSize;
tr_file_index_t * notWant;
tr_file_index_t notWantSize;
tr_file_index_t * low;
tr_file_index_t lowSize;
tr_file_index_t * normal;
tr_file_index_t normalSize;
tr_file_index_t * high;
tr_file_index_t highSize;
};
/***
****
***/
static void
setSourceFile( tr_ctor * ctor,
const char * sourceFile )
{
tr_free( ctor->sourceFile );
ctor->sourceFile = tr_strdup( sourceFile );
}
static void
clearMetainfo( tr_ctor * ctor )
{
if( ctor->isSet_metainfo )
{
ctor->isSet_metainfo = 0;
tr_bencFree( &ctor->metainfo );
}
setSourceFile( ctor, NULL );
}
int
tr_ctorSetMetainfo( tr_ctor * ctor,
const uint8_t * metainfo,
size_t len )
{
int err;
clearMetainfo( ctor );
err = tr_bencLoad( metainfo, len, &ctor->metainfo, NULL );
ctor->isSet_metainfo = !err;
return err;
}
const char*
tr_ctorGetSourceFile( const tr_ctor * ctor )
{
return ctor->sourceFile;
}
int
tr_ctorSetMetainfoFromMagnetLink( tr_ctor * ctor, const char * magnet_link )
{
int err;
tr_magnet_info * magnet_info = tr_magnetParse( magnet_link );
if( magnet_info == NULL )
err = -1;
else {
int len;
tr_benc tmp;
char * str;
tr_magnetCreateMetainfo( magnet_info, &tmp );
str = tr_bencToStr( &tmp, TR_FMT_BENC, &len );
err = tr_ctorSetMetainfo( ctor, (const uint8_t*)str, len );
tr_free( str );
tr_magnetFree( magnet_info );
}
return err;
}
int
tr_ctorSetMetainfoFromFile( tr_ctor * ctor,
const char * filename )
{
uint8_t * metainfo;
size_t len;
int err;
metainfo = tr_loadFile( filename, &len );
if( metainfo && len )
err = tr_ctorSetMetainfo( ctor, metainfo, len );
else
{
clearMetainfo( ctor );
err = 1;
}
setSourceFile( ctor, filename );
/* if no `name' field was set, then set it from the filename */
if( ctor->isSet_metainfo )
{
tr_benc * info;
if( tr_bencDictFindDict( &ctor->metainfo, "info", &info ) )
{
const char * name;
if( !tr_bencDictFindStr( info, "name.utf-8", &name ) )
if( !tr_bencDictFindStr( info, "name", &name ) )
name = NULL;
if( !name || !*name )
{
char * base = tr_basename( filename );
tr_bencDictAddStr( info, "name", base );
tr_free( base );
}
}
}
tr_free( metainfo );
return err;
}
int
tr_ctorSetMetainfoFromHash( tr_ctor * ctor,
const char * hashString )
{
int err;
const char * filename;
filename = tr_sessionFindTorrentFile( ctor->session, hashString );
if( !filename )
err = EINVAL;
else
err = tr_ctorSetMetainfoFromFile( ctor, filename );
return err;
}
/***
****
***/
void
tr_ctorSetFilePriorities( tr_ctor * ctor,
const tr_file_index_t * files,
tr_file_index_t fileCount,
tr_priority_t priority )
{
tr_file_index_t ** myfiles;
tr_file_index_t * mycount;
switch( priority ) {
case TR_PRI_LOW: myfiles = &ctor->low; mycount = &ctor->lowSize; break;
case TR_PRI_HIGH: myfiles = &ctor->high; mycount = &ctor->highSize; break;
default /*TR_PRI_NORMAL*/: myfiles = &ctor->normal; mycount = &ctor->normalSize; break;
}
tr_free( *myfiles );
*myfiles = tr_memdup( files, sizeof(tr_file_index_t)*fileCount );
*mycount = fileCount;
}
void
tr_ctorInitTorrentPriorities( const tr_ctor * ctor, tr_torrent * tor )
{
tr_file_index_t i;
for( i=0; i<ctor->lowSize; ++i )
tr_torrentInitFilePriority( tor, ctor->low[i], TR_PRI_LOW );
for( i=0; i<ctor->normalSize; ++i )
tr_torrentInitFilePriority( tor, ctor->normal[i], TR_PRI_NORMAL );
for( i=0; i<ctor->highSize; ++i )
tr_torrentInitFilePriority( tor, ctor->high[i], TR_PRI_HIGH );
}
void
tr_ctorSetFilesWanted( tr_ctor * ctor,
const tr_file_index_t * files,
tr_file_index_t fileCount,
tr_bool wanted )
{
tr_file_index_t ** myfiles = wanted ? &ctor->want : &ctor->notWant;
tr_file_index_t * mycount = wanted ? &ctor->wantSize : &ctor->notWantSize;
tr_free( *myfiles );
*myfiles = tr_memdup( files, sizeof(tr_file_index_t)*fileCount );
*mycount = fileCount;
}
void
tr_ctorInitTorrentWanted( const tr_ctor * ctor, tr_torrent * tor )
{
if( ctor->notWantSize )
tr_torrentInitFileDLs( tor, ctor->notWant, ctor->notWantSize, FALSE );
if( ctor->wantSize )
tr_torrentInitFileDLs( tor, ctor->want, ctor->wantSize, TRUE );
}
/***
****
***/
void
tr_ctorSetDeleteSource( tr_ctor * ctor,
tr_bool deleteSource )
{
ctor->doDelete = deleteSource != 0;
ctor->isSet_delete = 1;
}
int
tr_ctorGetDeleteSource( const tr_ctor * ctor,
uint8_t * setme )
{
int err = 0;
if( !ctor->isSet_delete )
err = 1;
else if( setme )
*setme = ctor->doDelete ? 1 : 0;
return err;
}
/***
****
***/
void
tr_ctorSetSave( tr_ctor * ctor,
tr_bool saveInOurTorrentsDir )
{
ctor->saveInOurTorrentsDir = saveInOurTorrentsDir != 0;
}
int
tr_ctorGetSave( const tr_ctor * ctor )
{
return ctor && ctor->saveInOurTorrentsDir;
}
void
tr_ctorSetPaused( tr_ctor * ctor,
tr_ctorMode mode,
tr_bool isPaused )
{
struct optional_args * args = &ctor->optionalArgs[mode];
args->isSet_paused = 1;
args->isPaused = isPaused ? 1 : 0;
}
void
tr_ctorSetPeerLimit( tr_ctor * ctor,
tr_ctorMode mode,
uint16_t peerLimit )
{
struct optional_args * args = &ctor->optionalArgs[mode];
args->isSet_connected = 1;
args->peerLimit = peerLimit;
}
void
tr_ctorSetDownloadDir( tr_ctor * ctor,
tr_ctorMode mode,
const char * directory )
{
struct optional_args * args = &ctor->optionalArgs[mode];
tr_free( args->downloadDir );
args->downloadDir = NULL;
args->isSet_downloadDir = 0;
if( directory && *directory )
{
args->isSet_downloadDir = 1;
args->downloadDir = tr_strdup( directory );
}
}
void
tr_ctorSetIncompleteDir( tr_ctor * ctor, const char * directory )
{
tr_free( ctor->incompleteDir );
ctor->incompleteDir = tr_strdup( directory );
}
int
tr_ctorGetPeerLimit( const tr_ctor * ctor,
tr_ctorMode mode,
uint16_t * setmeCount )
{
int err = 0;
const struct optional_args * args = &ctor->optionalArgs[mode];
if( !args->isSet_connected )
err = 1;
else if( setmeCount )
*setmeCount = args->peerLimit;
return err;
}
int
tr_ctorGetPaused( const tr_ctor * ctor,
tr_ctorMode mode,
uint8_t * setmeIsPaused )
{
int err = 0;
const struct optional_args * args = &ctor->optionalArgs[mode];
if( !args->isSet_paused )
err = 1;
else if( setmeIsPaused )
*setmeIsPaused = args->isPaused ? 1 : 0;
return err;
}
int
tr_ctorGetDownloadDir( const tr_ctor * ctor,
tr_ctorMode mode,
const char ** setmeDownloadDir )
{
int err = 0;
const struct optional_args * args = &ctor->optionalArgs[mode];
if( !args->isSet_downloadDir )
err = 1;
else if( setmeDownloadDir )
*setmeDownloadDir = args->downloadDir;
return err;
}
int
tr_ctorGetIncompleteDir( const tr_ctor * ctor,
const char ** setmeIncompleteDir )
{
int err = 0;
if( ctor->incompleteDir == NULL )
err = 1;
else
*setmeIncompleteDir = ctor->incompleteDir;
return err;
}
int
tr_ctorGetMetainfo( const tr_ctor * ctor,
const tr_benc ** setme )
{
int err = 0;
if( !ctor->isSet_metainfo )
err = 1;
else if( setme )
*setme = &ctor->metainfo;
return err;
}
tr_session*
tr_ctorGetSession( const tr_ctor * ctor )
{
return (tr_session*) ctor->session;
}
/***
****
***/
static tr_bool
isPriority( int i )
{
return (i==TR_PRI_LOW) || (i==TR_PRI_NORMAL) || (i==TR_PRI_HIGH);
}
void
tr_ctorSetBandwidthPriority( tr_ctor * ctor, tr_priority_t priority )
{
if( isPriority( priority ) )
ctor->bandwidthPriority = priority;
}
tr_priority_t
tr_ctorGetBandwidthPriority( const tr_ctor * ctor )
{
return ctor->bandwidthPriority;
}
/***
****
***/
tr_ctor*
tr_ctorNew( const tr_session * session )
{
tr_ctor * ctor = tr_new0( struct tr_ctor, 1 );
ctor->session = session;
ctor->bandwidthPriority = TR_PRI_NORMAL;
if( session != NULL )
{
tr_ctorSetDeleteSource( ctor, tr_sessionGetDeleteSource( session ) );
tr_ctorSetPaused( ctor, TR_FALLBACK, tr_sessionGetPaused( session ) );
tr_ctorSetPeerLimit( ctor, TR_FALLBACK, session->peerLimitPerTorrent );
tr_ctorSetDownloadDir( ctor, TR_FALLBACK, session->downloadDir );
}
tr_ctorSetSave( ctor, TRUE );
return ctor;
}
void
tr_ctorFree( tr_ctor * ctor )
{
clearMetainfo( ctor );
tr_free( ctor->optionalArgs[1].downloadDir );
tr_free( ctor->optionalArgs[0].downloadDir );
tr_free( ctor->incompleteDir );
tr_free( ctor->want );
tr_free( ctor->notWant );
tr_free( ctor->low );
tr_free( ctor->high );
tr_free( ctor->normal );
tr_free( ctor );
}