source: trunk/libtransmission/torrent-ctor.c @ 11709

Last change on this file since 11709 was 11709, checked in by jordan, 11 years ago

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.

  • Property svn:keywords set to Date Rev Author Id
File size: 11.1 KB
Line 
1/*
2 * This file Copyright (C) Mnemosyne LLC
3 *
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: torrent-ctor.c 11709 2011-01-19 13:48:47Z jordan $
11 */
12
13#include <errno.h> /* EINVAL */
14#include "transmission.h"
15#include "bencode.h"
16#include "magnet.h"
17#include "platform.h"
18#include "session.h" /* tr_sessionFindTorrentFile() */
19#include "torrent.h" /* tr_ctorGetSave() */
20#include "utils.h" /* tr_new0 */
21
22struct optional_args
23{
24    tr_bool         isSet_paused;
25    tr_bool         isSet_connected;
26    tr_bool         isSet_downloadDir;
27
28    tr_bool         isPaused;
29    uint16_t        peerLimit;
30    char          * downloadDir;
31};
32
33/** Opaque class used when instantiating torrents.
34 * @ingroup tr_ctor */
35struct tr_ctor
36{
37    const tr_session *      session;
38    tr_bool                 saveInOurTorrentsDir;
39    tr_bool                 doDelete;
40
41    tr_priority_t           bandwidthPriority;
42    tr_bool                 isSet_metainfo;
43    tr_bool                 isSet_delete;
44    tr_benc                 metainfo;
45    char *                  sourceFile;
46
47    struct optional_args    optionalArgs[2];
48
49    char                  * incompleteDir;
50
51    tr_file_index_t       * want;
52    tr_file_index_t         wantSize;
53    tr_file_index_t       * notWant;
54    tr_file_index_t         notWantSize;
55    tr_file_index_t       * low;
56    tr_file_index_t         lowSize;
57    tr_file_index_t       * normal;
58    tr_file_index_t         normalSize;
59    tr_file_index_t       * high;
60    tr_file_index_t         highSize;
61};
62
63/***
64****
65***/
66
67static void
68setSourceFile( tr_ctor *    ctor,
69               const char * sourceFile )
70{
71    tr_free( ctor->sourceFile );
72    ctor->sourceFile = tr_strdup( sourceFile );
73}
74
75static void
76clearMetainfo( tr_ctor * ctor )
77{
78    if( ctor->isSet_metainfo )
79    {
80        ctor->isSet_metainfo = 0;
81        tr_bencFree( &ctor->metainfo );
82    }
83
84    setSourceFile( ctor, NULL );
85}
86
87int
88tr_ctorSetMetainfo( tr_ctor *       ctor,
89                    const uint8_t * metainfo,
90                    size_t          len )
91{
92    int err;
93
94    clearMetainfo( ctor );
95    err = tr_bencLoad( metainfo, len, &ctor->metainfo, NULL );
96    ctor->isSet_metainfo = !err;
97    return err;
98}
99
100const char*
101tr_ctorGetSourceFile( const tr_ctor * ctor )
102{
103    return ctor->sourceFile;
104}
105
106int
107tr_ctorSetMetainfoFromMagnetLink( tr_ctor * ctor, const char * magnet_link )
108{
109    int err;
110    tr_magnet_info * magnet_info = tr_magnetParse( magnet_link );
111
112    if( magnet_info == NULL )
113        err = -1;
114    else {
115        int len;
116        tr_benc tmp;
117        char * str;
118
119        tr_magnetCreateMetainfo( magnet_info, &tmp );
120        str = tr_bencToStr( &tmp, TR_FMT_BENC, &len );
121        err = tr_ctorSetMetainfo( ctor, (const uint8_t*)str, len );
122
123        tr_free( str );
124        tr_magnetFree( magnet_info );
125    }
126
127    return err;
128}
129
130int
131tr_ctorSetMetainfoFromFile( tr_ctor *    ctor,
132                            const char * filename )
133{
134    uint8_t * metainfo;
135    size_t    len;
136    int       err;
137
138    metainfo = tr_loadFile( filename, &len );
139    if( metainfo && len )
140        err = tr_ctorSetMetainfo( ctor, metainfo, len );
141    else
142    {
143        clearMetainfo( ctor );
144        err = 1;
145    }
146
147    setSourceFile( ctor, filename );
148
149    /* if no `name' field was set, then set it from the filename */
150    if( ctor->isSet_metainfo )
151    {
152        tr_benc * info;
153        if( tr_bencDictFindDict( &ctor->metainfo, "info", &info ) )
154        {
155            const char * name;
156            if( !tr_bencDictFindStr( info, "name.utf-8", &name ) )
157                if( !tr_bencDictFindStr( info, "name", &name ) )
158                    name = NULL;
159            if( !name || !*name )
160            {
161                char * base = tr_basename( filename );
162                tr_bencDictAddStr( info, "name", base );
163                tr_free( base );
164            }
165        }
166    }
167
168    tr_free( metainfo );
169    return err;
170}
171
172int
173tr_ctorSetMetainfoFromHash( tr_ctor *    ctor,
174                            const char * hashString )
175{
176    int          err;
177    const char * filename;
178
179    filename = tr_sessionFindTorrentFile( ctor->session, hashString );
180    if( !filename )
181        err = EINVAL;
182    else
183        err = tr_ctorSetMetainfoFromFile( ctor, filename );
184
185    return err;
186}
187
188/***
189****
190***/
191
192void
193tr_ctorSetFilePriorities( tr_ctor                * ctor,
194                          const tr_file_index_t  * files,
195                          tr_file_index_t          fileCount,
196                          tr_priority_t            priority )
197{
198    tr_file_index_t ** myfiles;
199    tr_file_index_t * mycount;
200
201    switch( priority ) {
202        case TR_PRI_LOW: myfiles = &ctor->low; mycount = &ctor->lowSize; break;
203        case TR_PRI_HIGH: myfiles = &ctor->high; mycount = &ctor->highSize; break;
204        default /*TR_PRI_NORMAL*/: myfiles = &ctor->normal; mycount = &ctor->normalSize; break;
205    }
206
207    tr_free( *myfiles );
208    *myfiles = tr_memdup( files, sizeof(tr_file_index_t)*fileCount );
209    *mycount = fileCount;
210}
211
212void
213tr_ctorInitTorrentPriorities( const tr_ctor * ctor, tr_torrent * tor )
214{
215    tr_file_index_t i;
216
217    for( i=0; i<ctor->lowSize; ++i )
218        tr_torrentInitFilePriority( tor, ctor->low[i], TR_PRI_LOW );
219    for( i=0; i<ctor->normalSize; ++i )
220        tr_torrentInitFilePriority( tor, ctor->normal[i], TR_PRI_NORMAL );
221    for( i=0; i<ctor->highSize; ++i )
222        tr_torrentInitFilePriority( tor, ctor->high[i], TR_PRI_HIGH );
223}
224
225void
226tr_ctorSetFilesWanted( tr_ctor                * ctor,
227                       const tr_file_index_t  * files,
228                       tr_file_index_t          fileCount,
229                       tr_bool                  wanted )
230{
231    tr_file_index_t ** myfiles = wanted ? &ctor->want : &ctor->notWant;
232    tr_file_index_t * mycount = wanted ? &ctor->wantSize : &ctor->notWantSize;
233
234    tr_free( *myfiles );
235    *myfiles = tr_memdup( files, sizeof(tr_file_index_t)*fileCount );
236    *mycount = fileCount;
237}
238
239void
240tr_ctorInitTorrentWanted( const tr_ctor * ctor, tr_torrent * tor )
241{
242    if( ctor->notWantSize )
243        tr_torrentInitFileDLs( tor, ctor->notWant, ctor->notWantSize, FALSE );
244    if( ctor->wantSize )
245        tr_torrentInitFileDLs( tor, ctor->want, ctor->wantSize, TRUE );
246}
247
248/***
249****
250***/
251
252void
253tr_ctorSetDeleteSource( tr_ctor * ctor,
254                        tr_bool   deleteSource )
255{
256    ctor->doDelete = deleteSource != 0;
257    ctor->isSet_delete = 1;
258}
259
260int
261tr_ctorGetDeleteSource( const tr_ctor * ctor,
262                        uint8_t *       setme )
263{
264    int err = 0;
265
266    if( !ctor->isSet_delete )
267        err = 1;
268    else if( setme )
269        *setme = ctor->doDelete ? 1 : 0;
270
271    return err;
272}
273
274/***
275****
276***/
277
278void
279tr_ctorSetSave( tr_ctor * ctor,
280                tr_bool   saveInOurTorrentsDir )
281{
282    ctor->saveInOurTorrentsDir = saveInOurTorrentsDir != 0;
283}
284
285int
286tr_ctorGetSave( const tr_ctor * ctor )
287{
288    return ctor && ctor->saveInOurTorrentsDir;
289}
290
291void
292tr_ctorSetPaused( tr_ctor *   ctor,
293                  tr_ctorMode mode,
294                  tr_bool     isPaused )
295{
296    struct optional_args * args = &ctor->optionalArgs[mode];
297
298    args->isSet_paused = 1;
299    args->isPaused = isPaused ? 1 : 0;
300}
301
302void
303tr_ctorSetPeerLimit( tr_ctor *   ctor,
304                     tr_ctorMode mode,
305                     uint16_t    peerLimit )
306{
307    struct optional_args * args = &ctor->optionalArgs[mode];
308
309    args->isSet_connected = 1;
310    args->peerLimit = peerLimit;
311}
312
313void
314tr_ctorSetDownloadDir( tr_ctor *    ctor,
315                       tr_ctorMode  mode,
316                       const char * directory )
317{
318    struct optional_args * args = &ctor->optionalArgs[mode];
319
320    tr_free( args->downloadDir );
321    args->downloadDir = NULL;
322    args->isSet_downloadDir = 0;
323
324    if( directory && *directory )
325    {
326        args->isSet_downloadDir = 1;
327        args->downloadDir = tr_strdup( directory );
328    }
329}
330
331void
332tr_ctorSetIncompleteDir( tr_ctor * ctor, const char * directory )
333{
334    tr_free( ctor->incompleteDir );
335    ctor->incompleteDir = tr_strdup( directory );
336}
337
338int
339tr_ctorGetPeerLimit( const tr_ctor * ctor,
340                     tr_ctorMode     mode,
341                     uint16_t *      setmeCount )
342{
343    int err = 0;
344    const struct optional_args * args = &ctor->optionalArgs[mode];
345
346    if( !args->isSet_connected )
347        err = 1;
348    else if( setmeCount )
349        *setmeCount = args->peerLimit;
350
351    return err;
352}
353
354int
355tr_ctorGetPaused( const tr_ctor * ctor,
356                  tr_ctorMode     mode,
357                  uint8_t *       setmeIsPaused )
358{
359    int                          err = 0;
360    const struct optional_args * args = &ctor->optionalArgs[mode];
361
362    if( !args->isSet_paused )
363        err = 1;
364    else if( setmeIsPaused )
365        *setmeIsPaused = args->isPaused ? 1 : 0;
366
367    return err;
368}
369
370int
371tr_ctorGetDownloadDir( const tr_ctor * ctor,
372                       tr_ctorMode     mode,
373                       const char **   setmeDownloadDir )
374{
375    int                          err = 0;
376    const struct optional_args * args = &ctor->optionalArgs[mode];
377
378    if( !args->isSet_downloadDir )
379        err = 1;
380    else if( setmeDownloadDir )
381        *setmeDownloadDir = args->downloadDir;
382
383    return err;
384}
385
386int
387tr_ctorGetIncompleteDir( const tr_ctor  * ctor,
388                         const char    ** setmeIncompleteDir )
389{
390    int err = 0;
391
392    if( ctor->incompleteDir == NULL )
393        err = 1;
394    else
395        *setmeIncompleteDir = ctor->incompleteDir;
396
397    return err;
398}
399
400int
401tr_ctorGetMetainfo( const tr_ctor *  ctor,
402                    const tr_benc ** setme )
403{
404    int err = 0;
405
406    if( !ctor->isSet_metainfo )
407        err = 1;
408    else if( setme )
409        *setme = &ctor->metainfo;
410
411    return err;
412}
413
414tr_session*
415tr_ctorGetSession( const tr_ctor * ctor )
416{
417    return (tr_session*) ctor->session;
418}
419
420/***
421****
422***/
423
424static tr_bool
425isPriority( int i )
426{
427    return (i==TR_PRI_LOW) || (i==TR_PRI_NORMAL) || (i==TR_PRI_HIGH);
428}
429
430void
431tr_ctorSetBandwidthPriority( tr_ctor * ctor, tr_priority_t priority )
432{
433    if( isPriority( priority ) )
434        ctor->bandwidthPriority = priority;
435}
436
437tr_priority_t
438tr_ctorGetBandwidthPriority( const tr_ctor * ctor )
439{
440    return ctor->bandwidthPriority;
441}
442
443/***
444****
445***/
446
447tr_ctor*
448tr_ctorNew( const tr_session * session )
449{
450    tr_ctor * ctor = tr_new0( struct tr_ctor, 1 );
451
452    ctor->session = session;
453    ctor->bandwidthPriority = TR_PRI_NORMAL;
454    if( session != NULL )
455    {
456        tr_ctorSetDeleteSource( ctor, tr_sessionGetDeleteSource( session ) );
457        tr_ctorSetPaused( ctor, TR_FALLBACK, tr_sessionGetPaused( session ) );
458        tr_ctorSetPeerLimit( ctor, TR_FALLBACK, session->peerLimitPerTorrent );
459        tr_ctorSetDownloadDir( ctor, TR_FALLBACK, session->downloadDir );
460    }
461    tr_ctorSetSave( ctor, TRUE );
462    return ctor;
463}
464
465void
466tr_ctorFree( tr_ctor * ctor )
467{
468    clearMetainfo( ctor );
469    tr_free( ctor->optionalArgs[1].downloadDir );
470    tr_free( ctor->optionalArgs[0].downloadDir );
471    tr_free( ctor->incompleteDir );
472    tr_free( ctor->want );
473    tr_free( ctor->notWant );
474    tr_free( ctor->low );
475    tr_free( ctor->high );
476    tr_free( ctor->normal );
477    tr_free( ctor );
478}
Note: See TracBrowser for help on using the repository browser.