コード例 #1
0
ファイル: platform.c プロジェクト: dreamcat4/transmission
void
tr_setConfigDir( tr_session * session, const char * configDir )
{
    char * path;

    session->configDir = tr_strdup( configDir );

    path = tr_buildPath( configDir, RESUME_SUBDIR, NULL );
    tr_mkdirp( path, 0777 );
    session->resumeDir = path;

    path = tr_buildPath( configDir, TORRENT_SUBDIR, NULL );
    tr_mkdirp( path, 0777 );
    session->torrentDir = path;

    migrateFiles( session );
}
コード例 #2
0
ファイル: fdlimit.c プロジェクト: dazwiafl/transmission
/**
 * returns 0 on success, or an errno value on failure.
 * errno values include ENOENT if the parent folder doesn't exist,
 * plus the errno values set by tr_mkdirp() and open().
 */
static int
TrOpenFile( int          i,
            const char * folder,
            const char * torrentFile,
            int          doWrite,
            int          doPreallocate,
            uint64_t     desiredFileSize )
{
    struct tr_openfile * file = &gFd->open[i];
    int                  flags;
    char               * filename;
    struct stat          sb;
    int                  alreadyExisted;

    /* confirm the parent folder exists */
    if( stat( folder, &sb ) || !S_ISDIR( sb.st_mode ) )
        return ENOENT;

    /* create subfolders, if any */
    filename = tr_buildPath( folder, torrentFile, NULL );
    if( doWrite )
    {
        char * tmp = tr_dirname( filename );
        const int err = tr_mkdirp( tmp, 0777 ) ? errno : 0;
        tr_free( tmp );
        if( err ) {
            tr_free( filename );
            return err;
        }
    }

    alreadyExisted = !stat( filename, &sb ) && S_ISREG( sb.st_mode );

    if( doWrite && !alreadyExisted && doPreallocate )
        if( preallocateFile( filename, desiredFileSize ) )
            tr_inf( _( "Preallocated file \"%s\"" ), filename );
    
    /* open the file */
    flags = doWrite ? ( O_RDWR | O_CREAT ) : O_RDONLY;
#ifdef O_LARGEFILE
    flags |= O_LARGEFILE;
#endif
#ifdef WIN32
    flags |= O_BINARY;
#endif
    file->fd = open( filename, flags, 0666 );
    if( file->fd == -1 )
    {
        const int err = errno;
        tr_err( _( "Couldn't open \"%1$s\": %2$s" ), filename,
               tr_strerror( err ) );
        tr_free( filename );
        return err;
    }

    tr_free( filename );
    return 0;
}
コード例 #3
0
ファイル: platform.c プロジェクト: fangang190/canary
void
tr_setConfigDir( tr_handle *  handle,
                 const char * configDir )
{
    char * path;

    handle->configDir = tr_strdup( configDir );

    path = tr_buildPath( configDir, RESUME_SUBDIR, NULL );
    tr_mkdirp( path, 0777 );
    handle->resumeDir = path;

    path = tr_buildPath( configDir, TORRENT_SUBDIR, NULL );
    tr_mkdirp( path, 0777 );
    handle->torrentDir = path;

    migrateFiles( handle );
}
コード例 #4
0
ファイル: util.c プロジェクト: ijuxda/transmission
int
gtr_mkdir_with_parents( const char * path, int mode )
{
#if GLIB_CHECK_VERSION( 2, 8, 0 )
    return !g_mkdir_with_parents( path, mode );
#else
    return !tr_mkdirp( path, mode );
#endif
}
コード例 #5
0
void
libttest_zero_torrent_populate (tr_torrent * tor, bool complete)
{
  tr_file_index_t i;

  for (i=0; i<tor->info.fileCount; ++i)
    {
      int err;
      uint64_t j;
      FILE * fp;
      char * path;
      char * dirname;
      const tr_file * file = &tor->info.files[i];
      struct stat sb;

      if (!complete && (i==0))
        path = tr_strdup_printf ("%s%c%s.part", tor->currentDir, TR_PATH_DELIMITER, file->name);
      else
        path = tr_strdup_printf ("%s%c%s", tor->currentDir, TR_PATH_DELIMITER, file->name);
      dirname = tr_dirname (path);
      tr_mkdirp (dirname, 0700);
      fp = fopen (path, "wb+");
      for (j=0; j<file->length; ++j)
        fputc (((!complete) && (i==0) && (j<tor->info.pieceSize)) ? '\1' : '\0', fp);
      fclose (fp);

      tr_free (dirname);
      tr_free (path);

      path = tr_torrentFindFile (tor, i);
      assert (path != NULL);
      err = errno;
      errno = 0;
      stat (path, &sb);
      assert (errno == 0);
      errno = err; 
      tr_free (path);
    }

  sync ();
  libttest_blockingTorrentVerify (tor);

  if (complete)
    assert (tr_torrentStat(tor)->leftUntilDone == 0);
  else
    assert (tr_torrentStat(tor)->leftUntilDone == tor->info.pieceSize);
}
コード例 #6
0
ファイル: blocklist-test.c プロジェクト: AllardJ/Tomato
static void
create_text_file (const char * path, const char * contents)
{
  FILE * fp;
  char * dir;

  dir = tr_dirname (path);
  tr_mkdirp (dir, 0700);
  tr_free (dir);

  tr_remove (path);
  fp = fopen (path, "w+");
  fprintf (fp, "%s", contents);
  fclose (fp);

  sync ();
}
コード例 #7
0
/* this is for really old versions of T and will probably be removed someday */
void
tr_metainfoMigrate( tr_session * session,
                    tr_info *   inf )
{
    struct stat new_sb;
    char *      name = getTorrentFilename( session, inf );

    if( stat( name, &new_sb ) || ( ( new_sb.st_mode & S_IFMT ) != S_IFREG ) )
    {
        char *    old_name = getOldTorrentFilename( session, inf );
        size_t    contentLen;
        uint8_t * content;

        tr_mkdirp( tr_getTorrentDir( session ), 0777 );
        if( ( content = tr_loadFile( old_name, &contentLen ) ) )
        {
            FILE * out;
            errno = 0;
            out = fopen( name, "wb+" );
            if( !out )
            {
                tr_nerr( inf->name, _( "Couldn't create \"%1$s\": %2$s" ),
                        name, tr_strerror( errno ) );
            }
            else
            {
                if( fwrite( content, sizeof( uint8_t ), contentLen, out )
                    == contentLen )
                {
                    tr_free( inf->torrent );
                    inf->torrent = tr_strdup( name );
                    tr_sessionSetTorrentFile( session, inf->hashString, name );
                    unlink( old_name );
                }
                fclose( out );
            }
        }

        tr_free( content );
        tr_free( old_name );
    }

    tr_free( name );
}
コード例 #8
0
/**
 * returns 0 on success, or an errno value on failure.
 * errno values include ENOENT if the parent folder doesn't exist,
 * plus the errno values set by tr_mkdirp () and open ().
 */
static int
cached_file_open (struct tr_cached_file  * o,
                  const char             * filename,
                  bool                     writable,
                  tr_preallocation_mode    allocation,
                  uint64_t                 file_size)
{
    int flags;
    struct stat sb;
    bool alreadyExisted;

    /* create subfolders, if any */
    if (writable)
    {
        char * dir = tr_dirname (filename);
        const int err = tr_mkdirp (dir, 0777) ? errno : 0;
        if (err) {
            tr_err (_("Couldn't create \"%1$s\": %2$s"), dir, tr_strerror (err));
            tr_free (dir);
            return err;
        }
        tr_free (dir);
    }

    alreadyExisted = !stat (filename, &sb) && S_ISREG (sb.st_mode);

    if (writable && !alreadyExisted && (allocation == TR_PREALLOCATE_FULL))
        if (preallocate_file_full (filename, file_size))
            tr_dbg ("Preallocated file \"%s\"", filename);

    /* open the file */
    flags = writable ? (O_RDWR | O_CREAT) : O_RDONLY;
    flags |= O_LARGEFILE | O_BINARY | O_SEQUENTIAL;
    o->fd = open (filename, flags, 0666);

    if (o->fd == -1)
    {
        const int err = errno;
        tr_err (_("Couldn't open \"%1$s\": %2$s"), filename, tr_strerror (err));
        return err;
    }

    /* If the file already exists and it's too large, truncate it.
     * This is a fringe case that happens if a torrent's been updated
     * and one of the updated torrent's files is smaller.
     * http://trac.transmissionbt.com/ticket/2228
     * https://bugs.launchpad.net/ubuntu/+source/transmission/+bug/318249
     */
    if (alreadyExisted && (file_size < (uint64_t)sb.st_size))
    {
        if (ftruncate (o->fd, file_size) == -1)
        {
            const int err = errno;
            tr_err (_("Couldn't truncate \"%1$s\": %2$s"), filename, tr_strerror (err));
            return err;
        }
    }

    if (writable && !alreadyExisted && (allocation == TR_PREALLOCATE_SPARSE))
        preallocate_file_sparse (o->fd, file_size);

    /* Many (most?) clients request blocks in ascending order,
     * so increase the readahead buffer.
     * Also, disable OS-level caching because "inactive memory" angers users. */
    tr_set_file_for_single_pass (o->fd);

    return 0;
}
コード例 #9
0
ファイル: session.c プロジェクト: liesen/transmission-horn
static void
tr_sessionInitImpl( void * vdata )
{
    int64_t i;
    int64_t j;
    double  d;
    tr_bool found;
    const char * str;
    tr_benc settings;
    char * filename;
    struct init_data * data = vdata;
    tr_benc * clientSettings = data->clientSettings;
    tr_session * session = data->session;

    assert( tr_amInEventThread( session ) );
    assert( tr_bencIsDict( clientSettings ) );

    dbgmsg( "tr_sessionInit: the session's top-level bandwidth object is %p", session->bandwidth );

    tr_bencInitDict( &settings, 0 );
    tr_sessionGetDefaultSettings( &settings );
    tr_bencMergeDicts( &settings, clientSettings );

#ifndef WIN32
    /* Don't exit when writing on a broken socket */
    signal( SIGPIPE, SIG_IGN );
#endif

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_LIMIT_TORRENT, &i );
    assert( found );
    session->peerLimitPerTorrent = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_MSGLEVEL, &i );
    assert( found );
    tr_setMessageLevel( i );
    tr_setMessageQueuing( data->messageQueuingEnabled );


    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEX_ENABLED, &i );
    assert( found );
    session->isPexEnabled = i != 0;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_ENCRYPTION, &i );
    assert( found );
    assert( tr_isEncryptionMode( i ) );
    session->encryptionMode = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PREALLOCATION, &i );
    assert( found );
    assert( tr_isPreallocationMode( i ) );
    session->preallocationMode = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_SOCKET_TOS, &i );
    assert( found );
    session->peerSocketTOS = i;

    found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_DOWNLOAD_DIR, &str );
    assert( found );
    session->downloadDir = tr_strdup( str );

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_ENABLED, &i );
    assert( found );
    session->isProxyEnabled = i != 0;

    found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_PROXY, &str );
    assert( found );
    session->proxy = tr_strdup( str );

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_PORT, &i );
    assert( found );
    session->proxyPort = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_TYPE, &i );
    assert( found );
    session->proxyType = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PROXY_AUTH_ENABLED, &i );
    assert( found );
    session->isProxyAuthEnabled = i != 0;

    found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_PROXY_USERNAME, &str );
    assert( found );
    session->proxyUsername = tr_strdup( str );

    found = tr_bencDictFindStr( &settings, TR_PREFS_KEY_PROXY_PASSWORD, &str );
    assert( found );
    session->proxyPassword = tr_strdup( str );

    session->so_sndbuf = 1500 * 3; /* 3x MTU for most ethernet/wireless */
    session->so_rcvbuf = 8192;

    tr_setConfigDir( session, data->configDir );

    tr_trackerSessionInit( session );
    assert( session->tracker != NULL );

    session->peerMgr = tr_peerMgrNew( session );

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_LAZY_BITFIELD, &i );
    assert( found );
    session->useLazyBitfield = i != 0;

    /* Initialize rate and file descripts controls */

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_OPEN_FILE_LIMIT, &i );
    assert( found );
    session->openFileLimit = i;
    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, &j );
    assert( found );
    tr_fdInit( session->openFileLimit, j );

    /**
    *** random port
    **/

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT_RANDOM_ENABLED, &i );
    assert( found );
    session->isPortRandom = i != 0;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, &i );
    assert( found );
    session->randomPortLow = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, &i );
    assert( found );
    session->randomPortHigh = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_PORT_FORWARDING, &i )
         && tr_bencDictFindInt( &settings, TR_PREFS_KEY_PEER_PORT, &j );
    assert( found );
    session->peerPort = session->isPortRandom ? getRandomPort( session ) : j;
    session->shared = tr_sharedInit( session, i, session->peerPort );
    session->isPortSet = session->isPortRandom || j>0;

    /**
    **/

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, &i );
    assert( found );
    session->uploadSlotsPerTorrent = i;

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_USPEED, &i )
         && tr_bencDictFindInt( &settings, TR_PREFS_KEY_USPEED_ENABLED, &j );
    assert( found );
    tr_sessionSetSpeedLimit( session, TR_UP, i );
    tr_sessionSetSpeedLimitEnabled( session, TR_UP, j );

    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_DSPEED, &i )
         && tr_bencDictFindInt( &settings, TR_PREFS_KEY_DSPEED_ENABLED, &j );
    assert( found );
    tr_sessionSetSpeedLimit( session, TR_DOWN, i );
    tr_sessionSetSpeedLimitEnabled( session, TR_DOWN, j );

    found = tr_bencDictFindDouble( &settings, TR_PREFS_KEY_RATIO, &d )
         && tr_bencDictFindInt( &settings, TR_PREFS_KEY_RATIO_ENABLED, &j );
    assert( found );
    tr_sessionSetRatioLimit( session, d );
    tr_sessionSetRatioLimited( session, j );

    /* initialize the blocklist */
    filename = tr_buildPath( session->configDir, "blocklists", NULL );
    tr_mkdirp( filename, 0777 );
    tr_free( filename );
    found = tr_bencDictFindInt( &settings, TR_PREFS_KEY_BLOCKLIST_ENABLED, &i );
    assert( found );
    session->isBlocklistEnabled = i;
    loadBlocklists( session );

    session->rpcServer = tr_rpcInit( session, &settings );

    tr_bencFree( &settings );

    assert( tr_isSession( session ) );

    /* first %s is the application name
       second %s is the version number */
    tr_inf( _( "%s %s started" ), TR_NAME, LONG_VERSION_STRING );

    tr_statsInit( session );
    session->web = tr_webInit( session );
    metainfoLookupRescan( session );
    session->isWaiting = FALSE;
    dbgmsg( "returning session %p; session->tracker is %p", session, session->tracker );
}
コード例 #10
0
ファイル: fdlimit.c プロジェクト: miracle2k/transmission
/**
 * returns 0 on success, or an errno value on failure.
 * errno values include ENOENT if the parent folder doesn't exist,
 * plus the errno values set by tr_mkdirp() and open().
 */
static int
TrOpenFile( tr_session             * session,
            int                      i,
            const char             * filename,
            tr_bool                  doWrite,
            tr_preallocation_mode    preallocationMode,
            uint64_t                 desiredFileSize )
{
    int flags;
    struct stat sb;
    tr_bool alreadyExisted;
    struct tr_openfile * file;

    assert( tr_isSession( session ) );
    assert( session->fdInfo != NULL );

    file = &session->fdInfo->openFiles[i];

    /* create subfolders, if any */
    if( doWrite )
    {
        char * dir = tr_dirname( filename );
        const int err = tr_mkdirp( dir, 0777 ) ? errno : 0;
        if( err ) {
            tr_err( _( "Couldn't create \"%1$s\": %2$s" ), dir, tr_strerror( err ) );
            tr_free( dir );
            return err;
        }
        tr_free( dir );
    }

    alreadyExisted = !stat( filename, &sb ) && S_ISREG( sb.st_mode );

    if( doWrite && !alreadyExisted && ( preallocationMode == TR_PREALLOCATE_FULL ) )
        if( preallocateFileFull( filename, desiredFileSize ) )
            tr_dbg( _( "Preallocated file \"%s\"" ), filename );

    /* open the file */
    flags = doWrite ? ( O_RDWR | O_CREAT ) : O_RDONLY;
#ifdef O_SEQUENTIAL
    flags |= O_SEQUENTIAL;
#endif
#ifdef O_LARGEFILE
    flags |= O_LARGEFILE;
#endif
#ifdef WIN32
    flags |= O_BINARY;
#endif
    file->fd = open( filename, flags, 0666 );
    if( file->fd == -1 )
    {
        const int err = errno;
        tr_err( _( "Couldn't open \"%1$s\": %2$s" ), filename, tr_strerror( err ) );
        return err;
    }

    /* If the file already exists and it's too large, truncate it.
     * This is a fringe case that happens if a torrent's been updated
     * and one of the updated torrent's files is smaller.
     * http://trac.transmissionbt.com/ticket/2228
     * https://bugs.launchpad.net/ubuntu/+source/transmission/+bug/318249
     */
    if( alreadyExisted && ( desiredFileSize < (uint64_t)sb.st_size ) )
        ftruncate( file->fd, desiredFileSize );

    if( doWrite && !alreadyExisted && ( preallocationMode == TR_PREALLOCATE_SPARSE ) )
        preallocateFileSparse( file->fd, desiredFileSize );

#ifdef HAVE_POSIX_FADVISE
    /* this doubles the OS level readahead buffer, which in practice
     * turns out to be a good thing, because many (most?) clients request
     * chunks of blocks in order.
     * It's okay for this to fail silently, so don't let it affect errno */
    {
        const int err = errno;
        posix_fadvise( file->fd, 0, 0, POSIX_FADV_SEQUENTIAL );
        errno = err;
    }
#endif

#if defined( SYS_DARWIN )
    /**
     * 1. Enable readahead for reasons described above w/POSIX_FADV_SEQUENTIAL.
     *
     * 2. Disable OS-level caching due to user reports of adverse effects of
     *    excessive inactive memory.  However this is experimental because
     *    previous attempts at this have *also* had adverse effects (see r8198)
     *
     * It's okay for this to fail silently, so don't let it affect errno
     */
    {
        const int err = errno;
        fcntl( file->fd, F_NOCACHE, 1 );
        fcntl( file->fd, F_RDAHEAD, 1 );
        errno = err;
    }
#endif

    return 0;
}
コード例 #11
0
tr_session *
libttest_session_init (tr_variant * settings)
{
  size_t len;
  const char * str;
  char * sandbox;
  char * path;
  tr_quark q;
  static bool formatters_inited = false;
  tr_session * session;
  tr_variant local_settings;

  tr_variantInitDict (&local_settings, 10);

  if (settings == NULL)
    settings = &local_settings;

  sandbox = libtest_sandbox_create ();

  if (!formatters_inited)
    {
      formatters_inited = true;
      tr_formatter_mem_init (MEM_K, MEM_K_STR, MEM_M_STR, MEM_G_STR, MEM_T_STR);
      tr_formatter_size_init (DISK_K,DISK_K_STR, DISK_M_STR, DISK_G_STR, DISK_T_STR);
      tr_formatter_speed_init (SPEED_K, SPEED_K_STR, SPEED_M_STR, SPEED_G_STR, SPEED_T_STR);
    }

  /* download dir */
  q = TR_KEY_download_dir;
  if (tr_variantDictFindStr (settings, q, &str, &len))
    path = tr_strdup_printf ("%s/%*.*s", sandbox, (int)len, (int)len, str);
  else
    path = tr_buildPath (sandbox, "Downloads", NULL);
  tr_mkdirp (path, 0700);
  tr_variantDictAddStr (settings, q, path);
  tr_free (path);

  /* incomplete dir */
  q = TR_KEY_incomplete_dir;
  if (tr_variantDictFindStr (settings, q, &str, &len))
    path = tr_strdup_printf ("%s/%*.*s", sandbox, (int)len, (int)len, str);
  else
    path = tr_buildPath (sandbox, "Incomplete", NULL);
  tr_variantDictAddStr (settings, q, path);
  tr_free (path);

  path = tr_buildPath (sandbox, "blocklists", NULL);
  tr_mkdirp (path, 0700);
  tr_free (path);

  q = TR_KEY_port_forwarding_enabled;
  if (!tr_variantDictFind (settings, q))
    tr_variantDictAddBool (settings, q, false);

  q = TR_KEY_dht_enabled;
  if (!tr_variantDictFind (settings, q))
    tr_variantDictAddBool (settings, q, false);

  q = TR_KEY_message_level;
  if (!tr_variantDictFind (settings, q))
    tr_variantDictAddInt (settings, q, verbose ? TR_LOG_DEBUG : TR_LOG_ERROR);

  session = tr_sessionInit ("libtransmission-test", sandbox, !verbose, settings);

  tr_free (sandbox);
  tr_variantFree (&local_settings);
  return session;
}