Ignore:
Timestamp:
Oct 19, 2009, 5:05:00 AM (13 years ago)
Author:
charles
Message:

(trunk) #1483: move completed torrents to a user-specified directory + #629: different file extension for incomplete files

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/torrent.c

    r9276 r9328  
    551551}
    552552
     553static void refreshCurrentDir( tr_torrent * tor );;
     554
    553555static void
    554556torrentRealInit( tr_torrent * tor, const tr_ctor * ctor )
     
    579581        !tr_ctorGetDownloadDir( ctor, TR_FALLBACK, &dir ) )
    580582            tor->downloadDir = tr_strdup( dir );
     583
     584    if( tr_sessionGetIncompleteDirEnabled( session ) )
     585        tor->incompleteDir = tr_strdup( tr_sessionGetIncompleteDir( session ) );
    581586
    582587    tor->lastPieceSize = info->totalSize % info->pieceSize;
     
    643648    loaded = tr_torrentLoadResume( tor, ~0, ctor );
    644649
     650    refreshCurrentDir( tor );
     651
    645652    doStart = tor->isRunning;
    646653    tor->isRunning = 0;
     
    775782        tr_torrentSetDirty( tor );
    776783    }
     784
     785    refreshCurrentDir( tor );
    777786}
    778787
     
    12421251
    12431252    tr_free( tor->downloadDir );
     1253    tr_free( tor->incompleteDir );
    12441254    tr_free( tor->peer_id );
    12451255
     
    15971607        tor->needsSeedRatioCheck = TRUE;
    15981608        tr_fdTorrentClose( tor->uniqueId );
     1609
     1610        /* if the torrent is a seed now,
     1611         * and the files used to be in the incompleteDir,
     1612         * then move them to the destination directory */
     1613        if( tr_torrentIsSeed( tor ) && ( tor->currentDir == tor->incompleteDir ) )
     1614            tr_torrentSetLocation( tor, tor->downloadDir, TRUE, NULL, NULL );
     1615
    15991616        fireCompletenessChange( tor, completeness );
    16001617
     
    19801997
    19811998time_t*
    1982 tr_torrentGetMTimes( const tr_torrent * tor,
    1983                      size_t *           setme_n )
     1999tr_torrentGetMTimes( const tr_torrent * tor, size_t * setme_n )
    19842000{
    19852001    size_t       i;
     
    19922008    {
    19932009        struct stat sb;
    1994         char * path = tr_buildPath( tor->downloadDir, tor->info.files[i].name, NULL );
    1995         if( !stat( path, &sb ) )
     2010        char * path = tr_torrentFindFile( tor, i );
     2011        if( ( path != NULL ) && !stat( path, &sb ) && S_ISREG( sb.st_mode ) )
    19962012        {
    19972013#ifdef SYS_DARWIN
     
    21252141tr_torrentGetBytesLeftToAllocate( const tr_torrent * tor )
    21262142{
    2127     const tr_file * it;
    2128     const tr_file * end;
    2129     struct stat sb;
     2143    tr_file_index_t i;
    21302144    uint64_t bytesLeft = 0;
    21312145
    21322146    assert( tr_isTorrent( tor ) );
    21332147
    2134     for( it=tor->info.files, end=it+tor->info.fileCount; it!=end; ++it )
    2135     {
    2136         if( !it->dnd )
     2148    for( i=0; i<tor->info.fileCount; ++i )
     2149    {
     2150        if( !tor->info.files[i].dnd )
    21372151        {
    2138             char * path = tr_buildPath( tor->downloadDir, it->name, NULL );
    2139 
    2140             bytesLeft += it->length;
    2141 
    2142             if( !stat( path, &sb )
    2143                     && S_ISREG( sb.st_mode )
    2144                     && ( (uint64_t)sb.st_size <= it->length ) )
     2152            struct stat sb;
     2153            const uint64_t length = tor->info.files[i].length;
     2154            char * path = tr_torrentFindFile( tor, i );
     2155
     2156            bytesLeft += length;
     2157
     2158            if( ( path != NULL ) && !stat( path, &sb )
     2159                                 && S_ISREG( sb.st_mode )
     2160                                 && ( (uint64_t)sb.st_size <= length ) )
    21452161                bytesLeft -= sb.st_size;
    21462162
     
    22292245        else if( S_ISREG( sb.st_mode ) && ( sb.st_size > 0 ) )
    22302246        {
    2231             const char * sub = buf + strlen( tor->downloadDir ) + strlen( TR_PATH_DELIMITER_STR );
     2247            const char * sub = buf + strlen( tor->currentDir ) + strlen( TR_PATH_DELIMITER_STR );
    22322248            const tr_bool isTorrentFile = tr_ptrArrayFindSorted( torrentFiles, sub, vstrcmp ) != NULL;
    22332249            if( !isTorrentFile )
     
    22522268    const char * cpch = strchr( firstFile, TR_PATH_DELIMITER );
    22532269    char * tmp = cpch ? tr_strndup( firstFile, cpch - firstFile ) : NULL;
    2254     char * root = tr_buildPath( tor->downloadDir, tmp, NULL );
    2255 
    2256     assert( tr_isTorrent( tor ) );
    2257 
    2258     for( f=0; f<tor->info.fileCount; ++f )
    2259         tr_ptrArrayInsertSorted( &torrentFiles, tor->info.files[f].name, vstrcmp );
     2270    char * root = tr_buildPath( tor->currentDir, tmp, NULL );
     2271
     2272    assert( tr_isTorrent( tor ) );
     2273
     2274    for( f=0; f<tor->info.fileCount; ++f ) {
     2275        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 );
     2277    }
    22602278
    22612279    /* build the set of folders and dirtyFolders */
     
    22702288    /* now blow away any remaining torrent files, such as torrent files in dirty folders */
    22712289    for( f=0; f<tor->info.fileCount; ++f ) {
    2272         char * path = tr_buildPath( tor->downloadDir, tor->info.files[f].name, NULL );
     2290        char * path = tr_buildPath( tor->currentDir, tor->info.files[f].name, NULL );
    22732291        fileFunc( path );
    22742292        tr_free( path );
     
    22932311    tr_ptrArrayDestruct( &dirtyFolders, tr_free );
    22942312    tr_ptrArrayDestruct( &folders, tr_free );
    2295     tr_ptrArrayDestruct( &torrentFiles, NULL );
     2313    tr_ptrArrayDestruct( &torrentFiles, tr_free );
    22962314    tr_free( root );
    22972315    tr_free( tmp );
     
    23132331    else {
    23142332        /* torrent only has one file */
    2315         char * path = tr_buildPath( tor->downloadDir, tor->info.files[0].name, NULL );
     2333        char * path = tr_torrentFindFile( tor, 0 );
    23162334        fileFunc( path );
    23172335        tr_free( path );
     
    23222340****
    23232341***/
     2342
     2343static char*
     2344rebaseFile( 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}
    23242351
    23252352struct LocationData
     
    23452372    assert( tr_isTorrent( tor ) );
    23462373
    2347     if( strcmp( location, tor->downloadDir ) )
     2374    if( strcmp( location, tor->currentDir ) )
    23482375    {
    23492376        tr_file_index_t i;
     
    23672394            struct stat sb;
    23682395            const tr_file * f = &tor->info.files[i];
    2369             char * oldpath = tr_buildPath( tor->downloadDir, f->name, NULL );
    2370             char * newpath = tr_buildPath( location, f->name, NULL );
    2371 
    2372             if( do_move )
     2396            char * oldpath = tr_torrentFindFile( tor, i );
     2397            char * newpath = oldpath ? rebaseFile( tor, i, oldpath, location ) : NULL;
     2398
     2399            if( do_move && ( oldpath != NULL ) )
    23732400            {
    23742401                errno = 0;
     
    24842511    }
    24852512}
     2513
     2514/***
     2515****
     2516***/
     2517
     2518void
     2519tr_torrentFileCompleted( tr_torrent * tor, tr_file_index_t fileNum )
     2520{
     2521    char * oldpath = tr_torrentFindFile( tor, fileNum );
     2522    char * newpath = tr_strdup( oldpath );
     2523    char * pch = strrchr( newpath, '.' );
     2524    assert( !strcmp( pch, ".part" ) );
     2525    *pch = '\0';
     2526
     2527    /* close the file so that we can reopen in read-only mode as needed */
     2528    tr_fdFileClose( tor, fileNum );
     2529
     2530    /* strip the trailing ".part" from the filename */
     2531    if( rename( oldpath, newpath ) )
     2532        tr_torerr( tor, "Error moving \"%s\" to \"%s\": %s", oldpath, newpath, tr_strerror( errno ) );
     2533
     2534    tr_free( newpath );
     2535    tr_free( oldpath );
     2536}
     2537
     2538/***
     2539****
     2540***/
     2541
     2542enum
     2543{
     2544    TR_FILE_PARTIAL         = (1<<0),
     2545    TR_FILE_INCOMPLETE_DIR  = (1<<1)
     2546};
     2547
     2548static char*
     2549tr_torrentBuildFilename( const tr_torrent * tor, tr_file_index_t fileNo, int flags )
     2550{
     2551    const char * root;
     2552    char * base;
     2553    char * path;
     2554    const tr_bool partial = ( flags & TR_FILE_PARTIAL ) != 0;
     2555    const tr_bool incomplete = ( flags & TR_FILE_INCOMPLETE_DIR ) != 0;
     2556
     2557    assert( tr_isTorrent( tor ) );
     2558    assert( fileNo < tor->info.fileCount );
     2559
     2560    if( incomplete && ( tor->incompleteDir != NULL ) )
     2561        root = tor->incompleteDir;
     2562    else
     2563        root = tor->downloadDir;
     2564
     2565    if( partial )
     2566        base = tr_strdup_printf( "%s.part", tor->info.files[fileNo].name );
     2567    else
     2568        base = tr_strdup( tor->info.files[fileNo].name );
     2569
     2570    path = tr_buildPath( root, base, NULL );
     2571
     2572    /* cleanup */
     2573    tr_free( base );
     2574    return path;
     2575}
     2576
     2577static tr_bool
     2578fileExists( const char * filename )
     2579{
     2580    struct stat sb;
     2581    const tr_bool ok = !stat( filename, &sb );
     2582    return ok;
     2583}
     2584
     2585char*
     2586tr_torrentFindFile( const tr_torrent * tor, tr_file_index_t fileNo )
     2587{
     2588    int i;
     2589    char * filename;
     2590    int flags[4];
     2591    int n = 0;
     2592
     2593    assert( tr_isTorrent( tor ) );
     2594    assert( fileNo < tor->info.fileCount );
     2595
     2596    /* based on what we know about the torrent,
     2597     * put the most likely hits first... */
     2598    if( tr_cpFileIsComplete( &tor->completion, fileNo ) ) {
     2599        flags[n++] = 0;
     2600        flags[n++] = TR_FILE_INCOMPLETE_DIR;
     2601        flags[n++] = TR_FILE_PARTIAL;
     2602        flags[n++] = TR_FILE_INCOMPLETE_DIR|TR_FILE_PARTIAL;
     2603    } else {
     2604        flags[n++] = TR_FILE_INCOMPLETE_DIR|TR_FILE_PARTIAL;
     2605        flags[n++] = TR_FILE_PARTIAL;
     2606        flags[n++] = TR_FILE_INCOMPLETE_DIR;
     2607        flags[n++] = 0;
     2608    }
     2609       
     2610    for( i=0; i<n; ++i ) {
     2611        filename = tr_torrentBuildFilename( tor, fileNo, flags[i] );
     2612        if( fileExists( filename ))
     2613            break;
     2614        tr_free( filename );
     2615        filename = NULL;
     2616    }
     2617
     2618    return filename;
     2619}
     2620
     2621/* Decide whether we should be looking for files in downloadDir or incompleteDir. */
     2622static void
     2623refreshCurrentDir( tr_torrent * tor )
     2624{
     2625    const char * dir = tor->downloadDir;
     2626
     2627    if( tor->incompleteDir != NULL )
     2628    {
     2629        char * tmp1 = tr_torrentBuildFilename( tor, 0, 0 );
     2630        char * tmp2 = tr_torrentBuildFilename( tor, 0, TR_FILE_PARTIAL );
     2631
     2632        if( !fileExists( tmp1 ) && !fileExists( tmp2 ) )
     2633            dir = tor->incompleteDir;
     2634
     2635        tr_free( tmp2 );
     2636        tr_free( tmp1 );
     2637    }
     2638
     2639    assert( dir != NULL );
     2640    assert( ( dir == tor->downloadDir ) || ( dir == tor->incompleteDir ) );
     2641    tor->currentDir = dir;
     2642}
Note: See TracChangeset for help on using the changeset viewer.