Example #1
0
void tr_torrentSaveResume(tr_torrent* tor)
{
    int err;
    tr_variant top;
    char* filename;

    if (!tr_isTorrent(tor))
    {
        return;
    }

    tr_variantInitDict(&top, 50); /* arbitrary "big enough" number */
    tr_variantDictAddInt(&top, TR_KEY_seeding_time_seconds, tor->secondsSeeding);
    tr_variantDictAddInt(&top, TR_KEY_downloading_time_seconds, tor->secondsDownloading);
    tr_variantDictAddInt(&top, TR_KEY_activity_date, tor->activityDate);
    tr_variantDictAddInt(&top, TR_KEY_added_date, tor->addedDate);
    tr_variantDictAddInt(&top, TR_KEY_corrupt, tor->corruptPrev + tor->corruptCur);
    tr_variantDictAddInt(&top, TR_KEY_done_date, tor->doneDate);
    tr_variantDictAddStr(&top, TR_KEY_destination, tor->downloadDir);

    if (tor->incompleteDir != NULL)
    {
        tr_variantDictAddStr(&top, TR_KEY_incomplete_dir, tor->incompleteDir);
    }

    tr_variantDictAddInt(&top, TR_KEY_downloaded, tor->downloadedPrev + tor->downloadedCur);
    tr_variantDictAddInt(&top, TR_KEY_uploaded, tor->uploadedPrev + tor->uploadedCur);
    tr_variantDictAddInt(&top, TR_KEY_max_peers, tor->maxConnectedPeers);
    tr_variantDictAddInt(&top, TR_KEY_bandwidth_priority, tr_torrentGetPriority(tor));
    tr_variantDictAddBool(&top, TR_KEY_paused, !tor->isRunning && !tor->isQueued);
    savePeers(&top, tor);

    if (tr_torrentHasMetadata(tor))
    {
        saveFilePriorities(&top, tor);
        saveDND(&top, tor);
        saveProgress(&top, tor);
    }

    saveSpeedLimits(&top, tor);
    saveRatioLimits(&top, tor);
    saveIdleLimits(&top, tor);
    saveFilenames(&top, tor);
    saveName(&top, tor);

    filename = getResumeFilename(tor);

    if ((err = tr_variantToFile(&top, TR_VARIANT_FMT_BENC, filename)) != 0)
    {
        tr_torrentSetLocalError(tor, "Unable to save resume file: %s", tr_strerror(err));
    }

    tr_free(filename);

    tr_variantFree(&top);
}
Example #2
0
void
tr_torrentSaveResume( tr_torrent * tor )
{
    int err;
    tr_benc top;
    char * filename;

    if( !tr_isTorrent( tor ) )
        return;

    tr_bencInitDict( &top, 50 ); /* arbitrary "big enough" number */
    tr_bencDictAddInt( &top, KEY_TIME_SEEDING, tor->secondsSeeding );
    tr_bencDictAddInt( &top, KEY_TIME_DOWNLOADING, tor->secondsDownloading );
    tr_bencDictAddInt( &top, KEY_ACTIVITY_DATE, tor->activityDate );
    tr_bencDictAddInt( &top, KEY_ADDED_DATE, tor->addedDate );
    tr_bencDictAddInt( &top, KEY_CORRUPT, tor->corruptPrev + tor->corruptCur );
    tr_bencDictAddInt( &top, KEY_DONE_DATE, tor->doneDate );
    tr_bencDictAddStr( &top, KEY_DOWNLOAD_DIR, tor->downloadDir );
    if( tor->incompleteDir != NULL )
        tr_bencDictAddStr( &top, KEY_INCOMPLETE_DIR, tor->incompleteDir );
    tr_bencDictAddInt( &top, KEY_DOWNLOADED, tor->downloadedPrev + tor->downloadedCur );
    tr_bencDictAddInt( &top, KEY_UPLOADED, tor->uploadedPrev + tor->uploadedCur );
    tr_bencDictAddInt( &top, KEY_MAX_PEERS, tor->maxConnectedPeers );
    tr_bencDictAddInt( &top, KEY_BANDWIDTH_PRIORITY, tr_torrentGetPriority( tor ) );
    tr_bencDictAddBool( &top, KEY_PAUSED, !tor->isRunning );
    savePeers( &top, tor );
    if( tr_torrentHasMetadata( tor ) )
    {
        saveFilePriorities( &top, tor );
        saveDND( &top, tor );
        saveProgress( &top, tor );
    }
    saveSpeedLimits( &top, tor );
    saveRatioLimits( &top, tor );
    saveIdleLimits( &top, tor );

    filename = getResumeFilename( tor );
    if(( err = tr_bencToFile( &top, TR_FMT_BENC, filename )))
        tr_torrentSetLocalError( tor, "Unable to save resume file: %s", tr_strerror( err ) );
    tr_free( filename );

    tr_bencFree( &top );
}
Example #3
0
/* returns 0 on success, or an errno on failure */
static int
readOrWritePiece( tr_torrent       * tor,
                  int                ioMode,
                  tr_piece_index_t   pieceIndex,
                  uint32_t           pieceOffset,
                  uint8_t          * buf,
                  size_t             buflen )
{
    int             err = 0;
    tr_file_index_t fileIndex;
    uint64_t        fileOffset;
    const tr_info * info = &tor->info;

    if( pieceIndex >= tor->info.pieceCount )
        return EINVAL;
    //if( pieceOffset + buflen > tr_torPieceCountBytes( tor, pieceIndex ) )
    //    return EINVAL;

    tr_ioFindFileLocation( tor, pieceIndex, pieceOffset,
                           &fileIndex, &fileOffset );

    while( buflen && !err )
    {
        const tr_file * file = &info->files[fileIndex];
        const uint64_t bytesThisPass = MIN( buflen, file->length - fileOffset );

        err = readOrWriteBytes( tor->session, tor, ioMode, fileIndex, fileOffset, buf, bytesThisPass );
        buf += bytesThisPass;
        buflen -= bytesThisPass;
//fprintf( stderr, "++fileIndex to %d\n", (int)fileIndex );
        ++fileIndex;
        fileOffset = 0;

        if( ( err != 0 ) && (ioMode == TR_IO_WRITE ) && ( tor->error != TR_STAT_LOCAL_ERROR ) )
        {
            char * path = tr_buildPath( tor->downloadDir, file->name, NULL );
            tr_torrentSetLocalError( tor, "%s (%s)", tr_strerror( err ), path );
            tr_free( path );
        }
    }

    return err;
}
Example #4
0
/* returns 0 on success, or an errno on failure */
static int
readOrWriteBytes( tr_session       * session,
                  tr_torrent       * tor,
                  int                ioMode,
                  tr_file_index_t    fileIndex,
                  uint64_t           fileOffset,
                  void             * buf,
                  size_t             buflen )
{
    const tr_info * info = &tor->info;
    const tr_file * file = &info->files[fileIndex];

    int             fd = -1;
    int             err = 0;
    const tr_bool doWrite = ioMode >= TR_IO_WRITE;

//if( doWrite )
//    fprintf( stderr, "in file %s at offset %zu, writing %zu bytes; file length is %zu\n", file->name, (size_t)fileOffset, buflen, (size_t)file->length );

    assert( fileIndex < info->fileCount );
    assert( !file->length || ( fileOffset < file->length ) );
    assert( fileOffset + buflen <= file->length );

    if( !file->length )
        return 0;

    fd = tr_fdFileGetCached( session, tr_torrentId( tor ), fileIndex, doWrite );

    if( fd < 0 )
    {
        /* the fd cache doesn't have this file...
         * we'll need to open it and maybe create it */
        char * subpath;
        const char * base;
        tr_bool fileExists;
        tr_preallocation_mode preallocationMode;

        fileExists = tr_torrentFindFile2( tor, fileIndex, &base, &subpath );

        if( !fileExists )
        {
            base = tr_torrentGetCurrentDir( tor );

            if( tr_sessionIsIncompleteFileNamingEnabled( tor->session ) )
                subpath = tr_torrentBuildPartial( tor, fileIndex );
            else
                subpath = tr_strdup( file->name );
        }

        if( ( file->dnd ) || ( ioMode < TR_IO_WRITE ) )
            preallocationMode = TR_PREALLOCATE_NONE;
        else
            preallocationMode = tor->session->preallocationMode;

        if( ( ioMode < TR_IO_WRITE ) && !fileExists ) /* does file exist? */
        {
            err = ENOENT;
        }
        else
        {
            char * filename = tr_buildPath( base, subpath, NULL );

            if( ( fd = tr_fdFileCheckout( session, tor->uniqueId, fileIndex, filename,
                                          doWrite, preallocationMode, file->length ) ) < 0 )
            {
                err = errno;
                tr_torerr( tor, "tr_fdFileCheckout failed for \"%s\": %s", filename, tr_strerror( err ) );
            }

            tr_free( filename );
        }

        if( doWrite && !err )
            tr_statsFileCreated( tor->session );

        tr_free( subpath );
    }

    if( !err )
    {
        /* check & see if someone deleted the file while it was in our cache */
        struct stat sb;
        const tr_bool file_disappeared = fstat( fd, &sb ) || sb.st_nlink < 1;
        if( file_disappeared ) {
            tr_torrentSetLocalError( tor, "Please Verify Local Data! A file disappeared: \"%s\"", tor->info.files[fileIndex].name );
            err = ENOENT;
        }

        if( ioMode == TR_IO_READ ) {
            const int rc = tr_pread( fd, buf, buflen, fileOffset );
            if( rc < 0 ) {
                err = errno;
                tr_torerr( tor, "read failed for \"%s\": %s",
                           file->name, tr_strerror( err ) );
            }
        } else if( ioMode == TR_IO_PREFETCH ) {
            const int rc = tr_prefetch( fd, fileOffset, buflen );
            if( rc < 0 ) {
                /* (don't set "err" here... it's okay for prefetch to fail) */
                tr_tordbg( tor, "prefetch failed for \"%s\": %s",
                           file->name, tr_strerror( errno ) );
            }
        } else if( ioMode == TR_IO_WRITE ) {
            const int rc = tr_pwrite( fd, buf, buflen, fileOffset );
            if( rc < 0 ) {
                err = errno;
                tr_torerr( tor, "write failed for \"%s\": %s",
                           file->name, tr_strerror( err ) );
            }
        } else {
            abort();
        }
    }

    return err;
}