diff --git a/docs/manual.html b/docs/manual.html index 3d94ed206..7054120d2 100644 --- a/docs/manual.html +++ b/docs/manual.html @@ -4393,7 +4393,8 @@ struct session_settings bool always_send_user_agent; bool apply_ip_filter_to_trackers; int read_job_every; - use_disk_read_ahead; + bool use_disk_read_ahead; + bool lock_files; };

version is automatically set to the libtorrent version you're using @@ -5115,6 +5116,10 @@ instead pick one read job off of the sorted queue, where x is use_disk_read_ahead defaults to true and will attempt to optimize disk reads by giving the operating system heads up of disk read requests as they are queued in the disk job queue. This gives a significant performance boost for seeding.

+

lock_files determines whether or not to lock files which libtorrent is downloading +to or seeding from. This is implemented using fcntl(F_SETLK) on unix systems and +by not passing in SHARE_READ and SHARE_WRITE on windows. This might prevent +3rd party processes from corrupting the files under libtorrent's feet.

diff --git a/docs/manual.rst b/docs/manual.rst index 4c587fcea..4a404ef9f 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -4405,7 +4405,8 @@ session_settings bool always_send_user_agent; bool apply_ip_filter_to_trackers; int read_job_every; - use_disk_read_ahead; + bool use_disk_read_ahead; + bool lock_files; }; ``version`` is automatically set to the libtorrent version you're using @@ -5274,6 +5275,11 @@ instead pick one read job off of the sorted queue, where *x* is ``read_job_every by giving the operating system heads up of disk read requests as they are queued in the disk job queue. This gives a significant performance boost for seeding. +``lock_files`` determines whether or not to lock files which libtorrent is downloading +to or seeding from. This is implemented using ``fcntl(F_SETLK)`` on unix systems and +by not passing in ``SHARE_READ`` and ``SHARE_WRITE`` on windows. This might prevent +3rd party processes from corrupting the files under libtorrent's feet. + pe_settings =========== diff --git a/include/libtorrent/file.hpp b/include/libtorrent/file.hpp index dd5fd1f12..4fb9c6489 100644 --- a/include/libtorrent/file.hpp +++ b/include/libtorrent/file.hpp @@ -182,10 +182,10 @@ namespace libtorrent read_write = 2, rw_mask = read_only | write_only | read_write, no_buffer = 4, - mode_mask = rw_mask | no_buffer, sparse = 8, no_atime = 16, random_access = 32, + lock_file = 64, attribute_hidden = 0x1000, attribute_executable = 0x2000, diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index a4b1e02a6..1cfd0fa9a 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -269,6 +269,7 @@ namespace libtorrent , apply_ip_filter_to_trackers(true) , read_job_every(10) , use_disk_read_ahead(true) + , lock_files(false) {} // libtorrent version. Used for forward binary compatibility @@ -1075,6 +1076,10 @@ namespace libtorrent // issue posix_fadvise() or fcntl(F_RDADVISE) for disk reads // ahead of time bool use_disk_read_ahead; + + // if set to true, files will be locked when opened. + // preventing any other process from modifying them + bool lock_files; }; #ifndef TORRENT_DISABLE_DHT diff --git a/src/file.cpp b/src/file.cpp index be033ff69..d479a47a4 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -755,29 +755,17 @@ namespace libtorrent struct open_mode_t { DWORD rw_mode; - DWORD share_mode; DWORD create_mode; - DWORD flags; }; const static open_mode_t mode_array[] = { // read_only - {GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0}, + {GENERIC_READ, OPEN_EXISTING}, // write_only - {GENERIC_WRITE, FILE_SHARE_READ, OPEN_ALWAYS, 0}, + {GENERIC_WRITE, OPEN_ALWAYS}, // read_write - {GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, OPEN_ALWAYS, 0}, - // invalid option - {0,0,0,0}, - // read_only no_buffer - {GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING }, - // write_only no_buffer - {GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING }, - // read_write no_buffer - {GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING }, - // invalid option - {0,0,0,0} + {GENERIC_WRITE | GENERIC_READ, OPEN_ALWAYS}, }; const static DWORD attrib_array[] = @@ -788,6 +776,16 @@ namespace libtorrent FILE_ATTRIBUTE_HIDDEN, // hidden + executable }; + const static DWORD share_array[] = + { + // read only (no locking) + FILE_SHARE_READ | FILE_SHARE_WRITE, + // write only (no locking) + FILE_SHARE_READ, + // read/write (no locking) + FILE_SHARE_READ, + }; + #if TORRENT_USE_WSTRING #define CreateFile_ CreateFileW m_path = convert_to_wstring(path); @@ -797,14 +795,17 @@ namespace libtorrent #endif TORRENT_ASSERT((mode & mode_mask) < sizeof(mode_array)/sizeof(mode_array[0])); - open_mode_t const& m = mode_array[mode & mode_mask]; + open_mode_t const& m = mode_array[mode & rw_mask]; DWORD a = attrib_array[(mode & attribute_mask) >> 12]; - DWORD extra_flags = ((mode & random_access) ? FILE_FLAG_RANDOM_ACCESS : 0) - | (a ? a : FILE_ATTRIBUTE_NORMAL); + DWORD flags + = ((mode & random_access) ? FILE_FLAG_RANDOM_ACCESS : 0) + | (a ? a : FILE_ATTRIBUTE_NORMAL) + | ((mode & no_buffer) ? FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING : 0); - m_file_handle = CreateFile_(m_path.c_str(), m.rw_mode, m.share_mode, 0 - , m.create_mode, m.flags | extra_flags, 0); + m_file_handle = CreateFile_(m_path.c_str(), m.rw_mode + , (mode & lock_file) ? 0 : share_array[mode & rw_mask] + , 0, m.create_mode, flags, 0); if (m_file_handle == INVALID_HANDLE_VALUE) { @@ -869,6 +870,25 @@ namespace libtorrent return false; } +#ifdef F_SETLK + if (mode & lock_file) + { + struct flock l = + { + 0, // start offset + 0, // length (0 = until EOF) + getpid(), // owner + (mode & write_only) ? F_WRLCK : F_RDLCK, // lock type + SEEK_SET // whence + }; + if (fcntl(m_fd, F_SETLK, &l) != 0) + { + ec.assign(errno, get_posix_category()); + return false; + } + } +#endif + #ifdef DIRECTIO_ON // for solaris if (mode & no_buffer) diff --git a/src/storage.cpp b/src/storage.cpp index 039205a60..75291eddd 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -1382,6 +1382,8 @@ ret: || (cache_setting == session_settings::disable_os_cache_for_aligned_files && ((fe->offset + files().file_base(*fe)) & (m_page_size-1)) == 0)) mode |= file::no_buffer; + bool lock_files = m_settings ? settings().lock_files : false; + if (lock_files) mode |= file::lock_file; if (!m_allocate_files) mode |= file::sparse; if (m_settings && settings().no_atime_storage) mode |= file::no_atime;