Changeset 7473


Ignore:
Timestamp:
Dec 23, 2008, 4:04:11 PM (12 years ago)
Author:
charles
Message:

(trunk) #1029: When removing local data only remove data from the torrent

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/tr-torrent.c

    r7199 r7473  
    319319tr_torrent_delete_files( TrTorrent * gtor )
    320320{
    321     tr_file_index_t i;
    322     const tr_info * info = tr_torrent_info( gtor );
    323     const char *    stop =
    324         tr_torrentGetDownloadDir( tr_torrent_handle( gtor ) );
    325 
    326     for( i = 0; info && i < info->fileCount; ++i )
    327     {
    328         char * file = g_build_filename( stop, info->files[i].name, NULL );
    329         while( strcmp( stop, file ) && strlen( stop ) < strlen( file ) )
    330         {
    331             char * swap = g_path_get_dirname( file );
    332             tr_file_trash_or_unlink( file );
    333             g_free( file );
    334             file = swap;
    335         }
    336 
    337         g_free( file );
    338     }
     321    tr_torrentDeleteLocalData( tr_torrent_handle( gtor ), tr_file_trash_or_unlink );
    339322}
    340323
  • trunk/gtk/util.c

    r7464 r7473  
    515515}
    516516
    517 void
     517int
    518518tr_file_trash_or_unlink( const char * filename )
    519519{
     
    522522        gboolean trashed = FALSE;
    523523#ifdef HAVE_GIO
    524         GError * err = NULL;
    525524        GFile *  file = g_file_new_for_path( filename );
    526         trashed = g_file_trash( file, NULL, &err );
     525        trashed = g_file_trash( file, NULL, NULL );
    527526        g_object_unref( G_OBJECT( file ) );
    528527#endif
     
    530529            g_unlink( filename );
    531530    }
     531
     532    return 0;
    532533}
    533534
  • trunk/gtk/util.h

    r7464 r7473  
    133133gpointer    tr_object_ref_sink( gpointer object );
    134134
    135 void        tr_file_trash_or_unlink( const char * filename );
     135int         tr_file_trash_or_unlink( const char * filename );
    136136
    137137#endif /* GTK_MAJOR_VERSION */
  • trunk/libtransmission/rpcimpl.c

    r7404 r7473  
    151151        int64_t deleteFlag;
    152152        if( tr_bencDictFindInt( args_in, "delete-local-data", &deleteFlag ) && deleteFlag )
    153             tr_torrentDeleteLocalData( tor );
     153            tr_torrentDeleteLocalData( tor, NULL );
    154154        if( !( status & TR_RPC_NOREMOVE ) )
    155155            tr_torrentRemove( tor );
  • trunk/libtransmission/torrent.c

    r7446 r7473  
    2626#include <sys/stat.h> /* stat */
    2727#include <unistd.h> /* stat */
     28#include <dirent.h>
    2829
    2930#include <assert.h>
     
    4142#include "metainfo.h"
    4243#include "peer-mgr.h"
     44#include "platform.h" /* TR_PATH_DELIMITER_STR */
     45#include "ptrarray.h"
    4346#include "ratecontrol.h"
    4447#include "torrent.h"
     
    11891192
    11901193void
    1191 tr_torrentDeleteLocalData( tr_torrent * tor )
    1192 {
    1193     tr_file_index_t i;
    1194 
    1195     for( i=0; i<tor->info.fileCount; ++i )
    1196     {
    1197         const tr_file * file = &tor->info.files[i];
    1198         char * path = tr_buildPath( tor->downloadDir, file->name, NULL );
    1199         tr_fdFileClose( path );
    1200         unlink( path );
    1201         tr_free( path );
    1202     }
    1203 }
    1204 
    1205 void
    12061194tr_torrentStop( tr_torrent * tor )
    12071195{
     
    18161804    return bytesLeft;
    18171805}
     1806
     1807/****
     1808*****  Removing the torrent's local data
     1809****/
     1810
     1811static int
     1812vstrcmp( const void * a, const void * b )
     1813{
     1814    return strcmp( a, b );
     1815}
     1816
     1817static int
     1818compareLongestFirst( const void * a, const void * b )
     1819{
     1820    const size_t alen = strlen( a );
     1821    const size_t blen = strlen( b );
     1822
     1823    if( alen != blen )
     1824        return alen > blen ? -1 : 1;
     1825
     1826    return vstrcmp( a, b );
     1827}
     1828
     1829static void
     1830addDirtyFile( const char  * root,
     1831              const char  * filename,
     1832              tr_ptrArray * dirtyFolders )
     1833{
     1834    char * dir = tr_dirname( filename );
     1835
     1836    /* add the parent folders to dirtyFolders until we reach the root or a known-dirty */
     1837    while (     ( dir != NULL )
     1838             && ( strlen( root ) <= strlen( dir ) )
     1839             && ( tr_ptrArrayFindSorted( dirtyFolders, dir, vstrcmp ) == NULL ) )
     1840    {
     1841        char * tmp;
     1842        tr_ptrArrayInsertSorted( dirtyFolders, tr_strdup( dir ), vstrcmp );
     1843        tmp = tr_dirname( dir );
     1844        tr_free( dir );
     1845        dir = tmp;
     1846    }
     1847
     1848    tr_free( dir );
     1849}
     1850
     1851static void
     1852walkLocalData( const tr_torrent * tor,
     1853               const char       * root,
     1854               const char       * dir,
     1855               const char       * base,
     1856               tr_ptrArray      * torrentFiles,
     1857               tr_ptrArray      * folders,
     1858               tr_ptrArray      * dirtyFolders )
     1859{
     1860    int i;
     1861    struct stat sb;
     1862    char * buf;
     1863
     1864    buf = tr_buildPath( dir, base, NULL );
     1865    i = stat( buf, &sb );
     1866    if( !i )
     1867    {
     1868        DIR * odir = NULL;
     1869
     1870        if( S_ISDIR( sb.st_mode ) && ( ( odir = opendir ( buf ) ) ) )
     1871        {
     1872            struct dirent *d;
     1873            tr_ptrArrayInsertSorted( folders, tr_strdup( buf ), vstrcmp );
     1874            for( d = readdir( odir ); d != NULL; d = readdir( odir ) )
     1875                if( d->d_name && d->d_name[0] != '.' ) /* skip dotfiles */
     1876                    walkLocalData( tor, root, buf, d->d_name, torrentFiles, folders, dirtyFolders );
     1877            closedir( odir );
     1878        }
     1879        else if( S_ISREG( sb.st_mode ) && ( sb.st_size > 0 ) )
     1880        {
     1881            const char * sub = buf + strlen( tor->downloadDir ) + strlen( TR_PATH_DELIMITER_STR );
     1882            const tr_bool isTorrentFile = tr_ptrArrayFindSorted( torrentFiles, sub, vstrcmp ) != NULL;
     1883            if( !isTorrentFile )
     1884                addDirtyFile( root, buf, dirtyFolders );
     1885        }
     1886    }
     1887
     1888    tr_free( buf );
     1889}
     1890
     1891static void
     1892deleteLocalData( tr_torrent * tor, tr_fileFunc fileFunc )
     1893{
     1894    int i, n;
     1895    char ** s;
     1896    tr_file_index_t f;
     1897    tr_ptrArray * torrentFiles = tr_ptrArrayNew( );
     1898    tr_ptrArray * folders = tr_ptrArrayNew( );
     1899    tr_ptrArray * dirtyFolders = tr_ptrArrayNew( ); /* dirty == contains non-torrent files */
     1900
     1901    const char * firstFile = tor->info.files[0].name;
     1902    const char * cpch = strchr( firstFile, TR_PATH_DELIMITER );
     1903    char * tmp = cpch ? tr_strndup( firstFile, cpch - firstFile ) : NULL;
     1904    char * root = tr_buildPath( tor->downloadDir, tmp, NULL );
     1905
     1906    for( f=0; f<tor->info.fileCount; ++f )
     1907        tr_ptrArrayInsertSorted( torrentFiles, tor->info.files[f].name, vstrcmp );
     1908
     1909    /* build the set of folders and dirtyFolders */
     1910    walkLocalData( tor, root, root, NULL, torrentFiles, folders, dirtyFolders );
     1911
     1912    /* close all the files because we're about to delete them */
     1913    for( f=0; f<tor->info.fileCount; ++f ) {
     1914        char * path = tr_buildPath( tor->downloadDir, tor->info.files[f].name, NULL );
     1915        tr_fdFileClose( path );
     1916        tr_free( path );
     1917    }
     1918
     1919    /* try to remove entire folders first, so that the recycle bin will be tidy */
     1920    s = (char**) tr_ptrArrayPeek( folders, &n );
     1921    for( i=0; i<n; ++i )
     1922        if( tr_ptrArrayFindSorted( dirtyFolders, s[i], vstrcmp ) == NULL )
     1923            fileFunc( s[i] );
     1924
     1925    /* now blow away any remaining torrent files, such torrent files in dirty folders */
     1926    for( f=0; f<tor->info.fileCount; ++f ) {
     1927        char * path = tr_buildPath( tor->downloadDir, tor->info.files[f].name, NULL );
     1928        fileFunc( path );
     1929        tr_free( path );
     1930    }
     1931
     1932    /* Now clean out the directories left empty from the previous step.
     1933     * Work from deepest to shallowest s.t. lower folders
     1934     * won't prevent the upper folders from being deleted */
     1935    {
     1936        tr_ptrArray * cleanFolders = tr_ptrArrayNew( );
     1937        s = (char**) tr_ptrArrayPeek( folders, &n );
     1938        for( i=0; i<n; ++i )
     1939            if( tr_ptrArrayFindSorted( dirtyFolders, s[i], vstrcmp ) == NULL )
     1940                tr_ptrArrayInsertSorted( cleanFolders, s[i], compareLongestFirst );
     1941        s = (char**) tr_ptrArrayPeek( cleanFolders, &n );
     1942        for( i=0; i<n; ++i )
     1943            fileFunc( s[i] );
     1944        tr_ptrArrayFree( cleanFolders, NULL );
     1945    }
     1946
     1947    /* cleanup */
     1948    tr_ptrArrayFree( dirtyFolders, tr_free );
     1949    tr_ptrArrayFree( folders, tr_free );
     1950    tr_ptrArrayFree( torrentFiles, NULL );
     1951    tr_free( root );
     1952    tr_free( tmp );
     1953}
     1954
     1955void
     1956tr_torrentDeleteLocalData( tr_torrent * tor, tr_fileFunc fileFunc )
     1957{
     1958    if( fileFunc == NULL )
     1959        fileFunc = unlink;
     1960
     1961    if( tor->info.fileCount > 1 )
     1962        deleteLocalData( tor, fileFunc );
     1963    else {
     1964        char * path = tr_buildPath( tor->downloadDir, tor->info.files[0].name, NULL );
     1965        fileFunc( path );
     1966        tr_free( path );
     1967    }
     1968}
  • trunk/libtransmission/transmission.h

    r7468 r7473  
    796796void tr_torrentStop( tr_torrent * torrent );
    797797
    798 /** @brief Deletes the torrent data stored on disk. */
    799 void tr_torrentDeleteLocalData( tr_torrent * torrent );
     798typedef int tr_fileFunc( const char * filename );
     799
     800/**
     801 * @brief Deletes the torrent's local data.
     802 * @param torrent
     803 * @param fileFunc Pass in "unlink" to destroy the files or, on platforms with
     804 *                 recycle bins, pass in a function that uses it instead.
     805 *                 tr_torrentDeleteLocalData() ignores fileFunc's return value.
     806 */
     807void tr_torrentDeleteLocalData( tr_torrent * torrent,  tr_fileFunc fileFunc );
    800808
    801809/**
Note: See TracChangeset for help on using the changeset viewer.