Changeset 9335


Ignore:
Timestamp:
Oct 20, 2009, 3:14:44 AM (13 years ago)
Author:
charles
Message:

(trunk libT) make the ".part" suffix an optional feature as per BMW's request. Clean up the code a little.

Location:
trunk/libtransmission
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/inout.c

    r9328 r9335  
    7979    typedef size_t ( *iofunc )( int, void *, size_t );
    8080    iofunc          func = ioMode == TR_IO_READ ? (iofunc)read : (iofunc)write;
    81     struct stat     sb;
    8281    int             fd = -1;
    8382    int             err = 0;
     
    9897        /* the fd cache doesn't have this file...
    9998         * we'll need to open it and maybe create it */
    100         char * name;
     99        char * subpath;
     100        const char * base;
     101        tr_bool fileExists;
    101102        tr_preallocation_mode preallocationMode;
    102         tr_bool fileExists;
    103103   
    104         {
    105             char * path = tr_torrentFindFile( tor, fileIndex );
    106 
    107             fileExists = !stat( path, &sb );
    108 
    109             if( fileExists )
    110                 name = tr_strdup( strstr( path, file->name ) );
     104        fileExists = tr_torrentFindFile2( tor, fileIndex, &base, &subpath );
     105
     106        if( !fileExists )
     107        {
     108            base = tor->currentDir;
     109
     110            if( tr_sessionIsPartialFilenamesEnabled( tor->session ) )
     111                subpath = tr_torrentBuildPartial( tor, fileIndex );
    111112            else
    112                 name = tr_strdup_printf( "%s.part", file->name );
    113 
    114             tr_free( path );
     113                subpath = tr_strdup( file->name );
    115114        }
    116115
     
    124123            err = ENOENT;
    125124        }
    126         else if( ( fd = tr_fdFileCheckout( tor->uniqueId, fileIndex, tor->currentDir, name,
     125        else if( ( fd = tr_fdFileCheckout( tor->uniqueId, fileIndex, base, subpath,
    127126                                           doWrite, preallocationMode, file->length ) ) < 0 )
    128127        {
     128            char * filename;
    129129            err = errno;
    130             tr_torerr( tor, "tr_fdFileCheckout failed for \"%s\": %s", name, tr_strerror( err ) );
     130            filename = tr_buildPath( base, subpath, NULL );
     131            tr_torerr( tor, "tr_fdFileCheckout failed for \"%s\": %s", filename, tr_strerror( err ) );
     132            tr_free( filename );
    131133        }
    132134
    133135        if( doWrite && !err )
    134136            tr_statsFileCreated( tor->session );
     137
     138        tr_free( subpath );
    135139    }
    136140
  • trunk/libtransmission/rpcimpl.c

    r9330 r9335  
    12611261    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT, tr_sessionGetPeerLimitPerTorrent( s ) );
    12621262    tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR, tr_sessionGetIncompleteDir( s ) );
    1263     tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, tr_sessionGetIncompleteDirEnabled( s ) );
     1263    tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, tr_sessionIsIncompleteDirEnabled( s ) );
    12641264    tr_bencDictAddBool( d, TR_PREFS_KEY_PEX_ENABLED, tr_sessionIsPexEnabled( s ) );
    12651265    tr_bencDictAddBool( d, TR_PREFS_KEY_DHT_ENABLED, tr_sessionIsDHTEnabled( s ) );
  • trunk/libtransmission/session.c

    r9328 r9335  
    385385    tr_bencDictAddReal( d, TR_PREFS_KEY_RATIO,                    2.0 );
    386386    tr_bencDictAddBool( d, TR_PREFS_KEY_RATIO_ENABLED,            FALSE );
     387    tr_bencDictAddBool( d, TR_PREFS_KEY_RENAME_PARTIAL_FILES,     TRUE );
    387388    tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED,        FALSE );
    388389    tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_BIND_ADDRESS,         "0.0.0.0" );
     
    423424    tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION,               s->encryptionMode );
    424425    tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR,           tr_sessionGetIncompleteDir( s ) );
    425     tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED,   tr_sessionGetIncompleteDirEnabled( s ) );
     426    tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED,   tr_sessionIsIncompleteDirEnabled( s ) );
    426427    tr_bencDictAddBool( d, TR_PREFS_KEY_LAZY_BITFIELD,            s->useLazyBitfield );
    427428    tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL,                 tr_getMessageLevel( ) );
     
    446447    tr_bencDictAddReal( d, TR_PREFS_KEY_RATIO,                    s->desiredRatio );
    447448    tr_bencDictAddBool( d, TR_PREFS_KEY_RATIO_ENABLED,            s->isRatioLimited );
     449    tr_bencDictAddBool( d, TR_PREFS_KEY_RENAME_PARTIAL_FILES,     tr_sessionIsPartialFilenamesEnabled( s ) );
    448450    tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED,        tr_sessionIsRPCPasswordEnabled( s ) );
    449451    tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_BIND_ADDRESS,         tr_sessionGetRPCBindAddress( s ) );
     
    701703    tr_sessionSetIncompleteDirEnabled( session, boolVal );
    702704
     705    found = tr_bencDictFindBool( &settings, TR_PREFS_KEY_RENAME_PARTIAL_FILES, &boolVal );
     706    assert( found );
     707    tr_sessionSetPartialFilenamesEnabled( session, boolVal );
     708
    703709    found = tr_bencDictFindBool( &settings, TR_PREFS_KEY_PROXY_ENABLED, &boolVal );
    704710    assert( found );
     
    932938
    933939void
     940tr_sessionSetPartialFilenamesEnabled( tr_session * session, tr_bool b )
     941{
     942    assert( tr_isSession( session ) );
     943    assert( tr_isBool( b ) );
     944
     945    session->isPartialNamesEnabled = b;
     946}
     947
     948tr_bool
     949tr_sessionIsPartialFilenamesEnabled( const tr_session * session )
     950{
     951    assert( tr_isSession( session ) );
     952
     953    return session->isPartialNamesEnabled;
     954}
     955
     956/***
     957****
     958***/
     959
     960
     961void
    934962tr_sessionSetIncompleteDir( tr_session * session, const char * dir )
    935963{
     
    964992
    965993tr_bool
    966 tr_sessionGetIncompleteDirEnabled( const tr_session * session )
     994tr_sessionIsIncompleteDirEnabled( const tr_session * session )
    967995{
    968996    assert( tr_isSession( session ) );
  • trunk/libtransmission/session.h

    r9328 r9335  
    5252    tr_bool                      isWaiting;
    5353    tr_bool                      useLazyBitfield;
     54    tr_bool                      isPartialNamesEnabled;
    5455    tr_bool                      isRatioLimited;
    5556    tr_bool                      isIncompleteDirEnabled;
  • trunk/libtransmission/torrent.c

    r9333 r9335  
    582582            tor->downloadDir = tr_strdup( dir );
    583583
    584     if( tr_sessionGetIncompleteDirEnabled( session ) )
     584    if( tr_sessionIsIncompleteDirEnabled( session ) )
    585585        tor->incompleteDir = tr_strdup( tr_sessionGetIncompleteDir( session ) );
    586586
     
    22742274    for( f=0; f<tor->info.fileCount; ++f ) {
    22752275        tr_ptrArrayInsertSorted( &torrentFiles, tr_strdup( tor->info.files[f].name ), vstrcmp );
    2276         tr_ptrArrayInsertSorted( &torrentFiles, tr_strdup_printf( "%s.part", tor->info.files[f].name ), vstrcmp );
     2276        tr_ptrArrayInsertSorted( &torrentFiles, tr_torrentBuildPartial( tor, f ), vstrcmp );
    22772277    }
    22782278
     
    23412341***/
    23422342
    2343 static char*
    2344 rebaseFile( const tr_torrent * tor, tr_file_index_t fileNo,
    2345             const char * existingFile, const char * newRoot )
    2346 {
    2347     const char * base = strstr( existingFile, tor->info.files[fileNo].name );
    2348     assert( base != NULL );
    2349     return tr_buildPath( newRoot, base, NULL );
    2350 }
    2351 
    23522343struct LocationData
    23532344{
     
    23922383        for( i=0; !err && i<tor->info.fileCount; ++i )
    23932384        {
    2394             struct stat sb;
    23952385            const tr_file * f = &tor->info.files[i];
    2396             char * oldpath = tr_torrentFindFile( tor, i );
    2397             char * newpath = oldpath ? rebaseFile( tor, i, oldpath, location ) : NULL;
    2398 
    2399             if( do_move && ( oldpath != NULL ) )
     2386            const char * oldbase;
     2387            char * sub;
     2388            if( tr_torrentFindFile2( tor, i, &oldbase, &sub ) )
    24002389            {
    2401                 errno = 0;
    2402                 tr_torinf( tor, "moving \"%s\" to \"%s\"", oldpath, newpath );
    2403                 if( rename( oldpath, newpath ) )
     2390                char * oldpath = tr_buildPath( oldbase, sub, NULL );
     2391                char * newpath = tr_buildPath( location, sub, NULL );
     2392
     2393                if( do_move )
    24042394                {
    2405                     verify_needed = TRUE;
    2406                     if( tr_moveFile( oldpath, newpath ) )
     2395                    errno = 0;
     2396                    tr_torinf( tor, "moving \"%s\" to \"%s\"", oldpath, newpath );
     2397                    if( rename( oldpath, newpath ) )
    24072398                    {
    2408                         err = TRUE;
    2409                         tr_torerr( tor, "error moving \"%s\" to \"%s\": %s",
    2410                                         oldpath, newpath, tr_strerror( errno ) );
     2399                        verify_needed = TRUE;
     2400                        if( tr_moveFile( oldpath, newpath ) )
     2401                        {
     2402                            err = TRUE;
     2403                            tr_torerr( tor, "error moving \"%s\" to \"%s\": %s",
     2404                                            oldpath, newpath, tr_strerror( errno ) );
     2405                        }
    24112406                    }
    24122407                }
    2413             }
    2414             else if( !stat( newpath, &sb ) )
    2415             {
    2416                 tr_torinf( tor, "found \"%s\"", newpath );
     2408
     2409                tr_free( newpath );
     2410                tr_free( oldpath );
     2411                tr_free( sub );
    24172412            }
    24182413
     
    24222417                *data->setme_progress = bytesHandled / tor->info.totalSize;
    24232418            }
    2424 
    2425             tr_free( newpath );
    2426             tr_free( oldpath );
    24272419        }
    24282420
     
    25192511tr_torrentFileCompleted( tr_torrent * tor, tr_file_index_t fileNum )
    25202512{
    2521     char * oldpath;
     2513    char * sub;
     2514    const char * base;
    25222515
    25232516    /* close the file so that we can reopen in read-only mode as needed */
    25242517    tr_fdFileClose( tor, fileNum );
    25252518
    2526     /* if the torrent's file ends in ".part" to show that it was incomplete,
    2527      * strip that suffix */
    2528     oldpath = tr_torrentFindFile( tor, fileNum );
    2529     if( oldpath != NULL ) {
    2530         char * newpath = tr_strdup( oldpath );
    2531         char * pch = strrchr( newpath, '.' );
    2532         if(( pch != NULL ) && !strcmp( pch, ".part" )) {
    2533             *pch = '\0';
     2519    /* if the torrent's filename on disk isn't the same as the one in the metadata,
     2520     * then it's been modified to denote that it was a partial file.
     2521     * Now that it's complete, use the proper filename. */
     2522    if( tr_torrentFindFile2( tor, fileNum, &base, &sub ) )
     2523    {
     2524        const tr_file * file = &tor->info.files[fileNum];
     2525
     2526        if( strcmp( sub, file->name ) )
     2527        {
     2528            char * oldpath = tr_buildPath( base, sub, NULL );
     2529            char * newpath = tr_buildPath( base, file->name, NULL );
     2530
    25342531            if( rename( oldpath, newpath ) )
    25352532                tr_torerr( tor, "Error moving \"%s\" to \"%s\": %s", oldpath, newpath, tr_strerror( errno ) );
     2533
     2534            tr_free( newpath );
     2535            tr_free( oldpath );
    25362536        }
    2537         tr_free( newpath );
    2538     }
    2539     tr_free( oldpath );
     2537
     2538        tr_free( sub );
     2539    }
    25402540}
    25412541
     
    25442544***/
    25452545
    2546 enum
    2547 {
    2548     TR_FILE_PARTIAL         = (1<<0),
    2549     TR_FILE_INCOMPLETE_DIR  = (1<<1)
    2550 };
    2551 
    2552 static char*
    2553 tr_torrentBuildFilename( const tr_torrent * tor, tr_file_index_t fileNo, int flags )
    2554 {
    2555     const char * root;
    2556     char * base;
    2557     char * path;
    2558     const tr_bool partial = ( flags & TR_FILE_PARTIAL ) != 0;
    2559     const tr_bool incomplete = ( flags & TR_FILE_INCOMPLETE_DIR ) != 0;
    2560 
    2561     assert( tr_isTorrent( tor ) );
    2562     assert( fileNo < tor->info.fileCount );
    2563 
    2564     if( incomplete && ( tor->incompleteDir != NULL ) )
    2565         root = tor->incompleteDir;
    2566     else
    2567         root = tor->downloadDir;
    2568 
    2569     if( partial )
    2570         base = tr_strdup_printf( "%s.part", tor->info.files[fileNo].name );
    2571     else
    2572         base = tr_strdup( tor->info.files[fileNo].name );
    2573 
    2574     path = tr_buildPath( root, base, NULL );
    2575 
    2576     /* cleanup */
    2577     tr_free( base );
    2578     return path;
    2579 }
    2580 
    25812546static tr_bool
    25822547fileExists( const char * filename )
     
    25872552}
    25882553
     2554tr_bool
     2555tr_torrentFindFile2( const tr_torrent * tor, tr_file_index_t fileNum,
     2556                     const char ** base, char ** subpath )
     2557{
     2558    char * part;
     2559    const tr_file * file;
     2560    const char * b = NULL;
     2561    const char * s = NULL;
     2562
     2563    assert( tr_isTorrent( tor ) );
     2564    assert( fileNum < tor->info.fileCount );
     2565
     2566    file = &tor->info.files[fileNum];
     2567    part = tr_torrentBuildPartial( tor, fileNum );
     2568
     2569    if( b == NULL ) {
     2570        char * filename = tr_buildPath( tor->downloadDir, part, NULL );
     2571        if( fileExists( filename ) ) {
     2572            b = tor->downloadDir;
     2573            s = part;
     2574        }
     2575        tr_free( filename );
     2576    }
     2577
     2578    if( b == NULL ) {
     2579        char * filename = tr_buildPath( tor->downloadDir, file->name, NULL );
     2580        if( fileExists( filename ) ) {
     2581            b = tor->downloadDir;
     2582            s = file->name;
     2583        }
     2584        tr_free( filename );
     2585    }
     2586
     2587    if( tor->incompleteDir != NULL )
     2588    {
     2589        if( b == NULL ) {
     2590            char * filename = tr_buildPath( tor->incompleteDir, part, NULL );
     2591            if( fileExists( filename ) ) {
     2592                b = tor->incompleteDir;
     2593                s = part;
     2594            }
     2595            tr_free( filename );
     2596        }
     2597
     2598        if( b == NULL ) {
     2599            char * filename = tr_buildPath( tor->incompleteDir, file->name, NULL );
     2600            if( fileExists( filename ) ) {
     2601                b = tor->incompleteDir;
     2602                s = file->name;
     2603            }
     2604            tr_free( filename );
     2605        }
     2606    }
     2607
     2608    if( base != NULL )
     2609        *base = b;
     2610    if( subpath != NULL )
     2611        *subpath = tr_strdup( s );
     2612
     2613    tr_free( part );
     2614    return b != NULL;
     2615}
     2616
     2617
    25892618char*
    2590 tr_torrentFindFile( const tr_torrent * tor, tr_file_index_t fileNo )
    2591 {
    2592     int i;
    2593     char * filename;
    2594     int flags[4];
    2595     int n = 0;
    2596 
    2597     assert( tr_isTorrent( tor ) );
    2598     assert( fileNo < tor->info.fileCount );
    2599 
    2600     /* based on what we know about the torrent,
    2601      * put the most likely hits first... */
    2602     if( tr_cpFileIsComplete( &tor->completion, fileNo ) ) {
    2603         flags[n++] = 0;
    2604         flags[n++] = TR_FILE_INCOMPLETE_DIR;
    2605         flags[n++] = TR_FILE_PARTIAL;
    2606         flags[n++] = TR_FILE_INCOMPLETE_DIR|TR_FILE_PARTIAL;
    2607     } else {
    2608         flags[n++] = TR_FILE_INCOMPLETE_DIR|TR_FILE_PARTIAL;
    2609         flags[n++] = TR_FILE_PARTIAL;
    2610         flags[n++] = TR_FILE_INCOMPLETE_DIR;
    2611         flags[n++] = 0;
    2612     }
    2613        
    2614     for( i=0; i<n; ++i ) {
    2615         filename = tr_torrentBuildFilename( tor, fileNo, flags[i] );
    2616         if( fileExists( filename ))
    2617             break;
    2618         tr_free( filename );
    2619         filename = NULL;
    2620     }
    2621 
    2622     return filename;
     2619tr_torrentFindFile( const tr_torrent * tor, tr_file_index_t fileNum )
     2620{
     2621    char * subpath;
     2622    char * ret = NULL;
     2623    const char * base;
     2624
     2625    if( tr_torrentFindFile2( tor, fileNum, &base, &subpath ) )
     2626    {
     2627        ret = tr_buildPath( base, subpath, NULL );
     2628        tr_free( subpath );
     2629    }
     2630
     2631    return ret;
    26232632}
    26242633
     
    26272636refreshCurrentDir( tr_torrent * tor )
    26282637{
    2629     const char * dir = tor->downloadDir;
    2630 
    2631     if( tor->incompleteDir != NULL )
    2632     {
    2633         char * tmp1 = tr_torrentBuildFilename( tor, 0, 0 );
    2634         char * tmp2 = tr_torrentBuildFilename( tor, 0, TR_FILE_PARTIAL );
    2635 
    2636         if( !fileExists( tmp1 ) && !fileExists( tmp2 ) )
    2637             dir = tor->incompleteDir;
    2638 
    2639         tr_free( tmp2 );
    2640         tr_free( tmp1 );
    2641     }
     2638    const char * dir = NULL;
     2639    char * sub;
     2640
     2641    if( tor->incompleteDir == NULL )
     2642        dir = tor->downloadDir;
     2643    else if( !tr_torrentFindFile2( tor, 0, &dir, &sub ) )
     2644        dir = tor->incompleteDir;
    26422645
    26432646    assert( dir != NULL );
     
    26452648    tor->currentDir = dir;
    26462649}
     2650
     2651char*
     2652tr_torrentBuildPartial( const tr_torrent * tor, tr_file_index_t fileNum )
     2653{
     2654    return tr_strdup_printf( "%s.part", tor->info.files[fileNum].name );
     2655}
  • trunk/libtransmission/torrent.h

    r9334 r9335  
    361361
    362362
     363/* Like tr_torrentFindFile(), but splits the filename into base
     364 * (tr_torrent.incompleteDir or tr_torrent.downloadDir)  and subpath */
     365tr_bool tr_torrentFindFile2( const tr_torrent *, tr_file_index_t fileNo,
     366                             const char ** base, char ** subpath );
     367
     368
     369/* Returns a newly-allocated string that's been munged to the form
     370 * that denotes to humans that it's a partial file.
     371 * This is like the filenames in tr_torrent.info.files --
     372 * it's not a complete filename by itself, but a fragment that
     373 * can be passed to tr_buildPath() */
     374char* tr_torrentBuildPartial( const tr_torrent *, tr_file_index_t fileNo );
     375
     376
     377
     378
    363379#endif
  • trunk/libtransmission/transmission.h

    r9334 r9335  
    193193#define TR_PREFS_KEY_RATIO                      "ratio-limit"
    194194#define TR_PREFS_KEY_RATIO_ENABLED              "ratio-limit-enabled"
     195#define TR_PREFS_KEY_RENAME_PARTIAL_FILES       "rename-partial-files"
    195196#define TR_PREFS_KEY_RPC_AUTH_REQUIRED          "rpc-authentication-required"
    196197#define TR_PREFS_KEY_RPC_BIND_ADDRESS           "rpc-bind-address"
     
    333334
    334335/**
    335  * @brief Set the per-session incomplete download folder
     336 * @brief Set the per-session incomplete download folder.
     337 *
     338 * When you add a new torrent and the session's incomplete directory is enabled,
     339 * the new torrent will start downloading into that directory, and then be moved
     340 * to tr_torrent.downloadDir when the torrent is finished downloading.
     341 *
     342 * Torrents are not moved as a result of changing the session's incomplete dir --
     343 * it's applied to new torrents, not existing ones.
     344 *
     345 * tr_torrentSetLocation() overrules the incomplete dir: when a user specifies
     346 * a new location, that becomes the torrent's new downloadDir and the torrent
     347 * is moved there immediately regardless of whether or not it's complete.
     348 *
    336349 * @see tr_sessionInit()
    337350 * @see tr_sessionGetIncompleteDir()
     
    345358void tr_sessionSetIncompleteDirEnabled( tr_session * session, tr_bool );
    346359
    347 tr_bool tr_sessionGetIncompleteDirEnabled( const tr_session * session );
     360tr_bool tr_sessionIsIncompleteDirEnabled( const tr_session * session );
     361
     362
     363/**
     364 * @brief When enabled, unfinished torrent content files created after
     365 *        this call will have ".part" appended to their filename
     366 *
     367 * This is not retroactive -- toggling this will not rename existing files.
     368 * It only applies to new files created by Transmission after this API call.
     369 *
     370 * @param session
     371 * @param enable
     372 */
     373void tr_sessionSetPartialFilenamesEnabled( tr_session * session, tr_bool );
     374
     375tr_bool tr_sessionIsPartialFilenamesEnabled( const tr_session * session );
    348376
    349377/**
Note: See TracChangeset for help on using the changeset viewer.