diff --git a/libtransmission/fdlimit.c b/libtransmission/fdlimit.c index 73edf6dbc..f819c1c7d 100644 --- a/libtransmission/fdlimit.c +++ b/libtransmission/fdlimit.c @@ -350,6 +350,7 @@ cached_file_close( struct tr_cached_file * o ) */ static int cached_file_open( struct tr_cached_file * o, + const char * existing_dir, const char * filename, tr_bool writable, tr_preallocation_mode allocation, @@ -359,6 +360,14 @@ cached_file_open( struct tr_cached_file * o, struct stat sb; tr_bool alreadyExisted; + /* confirm that existing_dir, if specified, exists on the disk */ + if( existing_dir && *existing_dir && stat( existing_dir, &sb ) ) + { + const int err = errno; + tr_err( _( "Couldn't open \"%1$s\": %2$s" ), existing_dir, tr_strerror( err ) ); + return err; + } + /* create subfolders, if any */ if( writable ) { @@ -565,6 +574,7 @@ int tr_fdFileCheckout( tr_session * session, int torrent_id, tr_file_index_t i, + const char * existing_dir, const char * filename, tr_bool writable, tr_preallocation_mode allocation, @@ -580,7 +590,7 @@ tr_fdFileCheckout( tr_session * session, if( !cached_file_is_open( o ) ) { - const int err = cached_file_open( o, filename, writable, allocation, file_size ); + const int err = cached_file_open( o, existing_dir, filename, writable, allocation, file_size ); if( err ) { errno = err; return -1; diff --git a/libtransmission/fdlimit.h b/libtransmission/fdlimit.h index 4ecf90127..78e564bb1 100644 --- a/libtransmission/fdlimit.h +++ b/libtransmission/fdlimit.h @@ -54,8 +54,13 @@ int tr_prefetch(int fd, off_t offset, size_t count); * continually opening and closing the same files when downloading * piece data. * - * - if doWrite is true, subfolders in torrentFile are created if necessary. - * - if doWrite is true, the target file is created if necessary. + * - if do_write is true, subfolders in torrentFile are created if necessary. + * - if do_write is true, the target file is created if necessary. + * + * @param existing_dir An ancestor of filename which must already exist and + * won't be created by tr_fdFileCheckout(). This prevents + * directories from being created in error, such as a mount + * point for an external drive when the drive is unplugged. * * on success, a file descriptor >= 0 is returned. * on failure, a -1 is returned and errno is set. @@ -63,16 +68,17 @@ int tr_prefetch(int fd, off_t offset, size_t count); * @see tr_fdFileClose */ int tr_fdFileCheckout( tr_session * session, - int torrentId, - tr_file_index_t fileNum, - const char * fileName, - tr_bool doWrite, - tr_preallocation_mode preallocationMode, - uint64_t desiredFileSize ); + int torrent_id, + tr_file_index_t file_num, + const char * existing_dir, + const char * filename, + tr_bool do_write, + tr_preallocation_mode preallocation_mode, + uint64_t preallocation_file_size ); int tr_fdFileGetCached( tr_session * session, - int torrentId, - tr_file_index_t fileNum, + int torrent_id, + tr_file_index_t file_num, tr_bool doWrite ); /** @@ -85,7 +91,7 @@ int tr_fdFileGetCached( tr_session * session, */ void tr_fdFileClose( tr_session * session, const tr_torrent * tor, - tr_file_index_t fileNo ); + tr_file_index_t file_num ); /** diff --git a/libtransmission/inout.c b/libtransmission/inout.c index c611dea4d..83c8e9485 100644 --- a/libtransmission/inout.c +++ b/libtransmission/inout.c @@ -120,7 +120,8 @@ readOrWriteBytes( tr_session * session, { char * filename = tr_buildPath( base, subpath, NULL ); - if( ( fd = tr_fdFileCheckout( session, tor->uniqueId, fileIndex, filename, + if( ( fd = tr_fdFileCheckout( session, tor->uniqueId, fileIndex, + base, filename, doWrite, preallocationMode, file->length ) ) < 0 ) { err = errno; diff --git a/libtransmission/inout.h b/libtransmission/inout.h index dc6b8c925..967def41b 100644 --- a/libtransmission/inout.h +++ b/libtransmission/inout.h @@ -60,11 +60,11 @@ tr_bool tr_ioTestPiece( tr_torrent * tor, /** * Converts a piece index + offset into a file index + offset. */ -void tr_ioFindFileLocation( const tr_torrent * tor, - tr_piece_index_t pieceIndex, - uint32_t pieceOffset, - tr_file_index_t * fileIndex, - uint64_t * fileOffset ); +void tr_ioFindFileLocation( const tr_torrent * tor, + tr_piece_index_t pieceIndex, + uint32_t pieceOffset, + tr_file_index_t * fileIndex, + uint64_t * fileOffset ); /* @} */